Concept - AR InShop Navigation

Animation der App

Was und Warum?

Okay, Leute, ihr kennt das sicherlich: Man geht in einen riesigen Baumarkt oder Lebensmittelgeschäft und hat keine Ahnung, wo sich die gesuchten Produkte befinden. Da läuft man gefühlt stundenlang durch die Regale und fragt sich irgendwann, ob man den Ausgang jemals wiederfinden wird. Genau hier kommt unser Konzept der "AR InShop Navigation" ins Spiel.

Als Teil des Pitch-Projekts an der DHBW Mosbach haben wir uns in unserer Gruppe mit der Aufgabe auseinandergesetzt, ein Startup zu konzipieren und es wie in der Fernsehserie "Die Höhle der Löwen" zu präsentieren. Unsere Idee war es, eine Web-Applikation zu entwickeln, die es Kunden ermöglicht, sich in Baumärkten und Lebensmittelgeschäften besser zurechtzufinden. Und das alles ohne große Mühe oder aufdringliche Verkäufer, die einem im Nacken sitzen.

Unser Konzept war so einfach wie genial: Kunden scannen einfach den QR-Code des Geschäfts mit der App und fügen das gewünschte Produkt ihrer Einkaufsliste hinzu. Anschließend navigiert die App den Kunden durch das Geschäft, indem sie auf dem Boden verteilte Vinyl-Sticker erkennt und ihm mit einem Pfeil den Weg zum nächsten Marker weist. Keine Verwirrung mehr, kein nerviges Herumirren, keine verloren gegangenen Nerven - einfach nur effiziente Orientierung und schnelles Finden der gewünschten Produkte.

Aber das war noch nicht alles. Wir hatten auch geplant, dass Kunden den Barcode eines Produkts scannen können, um weitere Informationen wie den Preis, die Eigenschaften, verwandte Produkte und zusätzliche Empfehlungen zu erhalten. Und wenn ein Kunde wirklich mal nicht weiter weiß, kann er einfach einen Mitarbeiter zu seiner Position rufen lassen, indem er einen Button in der App drückt. Keine lästigen Suchaktionen mehr, keine Frustration - nur noch ein entspanntes Einkaufen.

Die Technik

Okay, jetzt wollen wir mal ein bisschen ins Detail gehen und euch zeigen, wie wir das technisch umgesetzt haben. Aber keine Sorge, wir werden es euch so einfach wie möglich erklären.

Da unser Projekt nicht allzu komplexe Szenen darstellen musste, haben wir uns für eine webbasierte Lösung entschieden. Das hat den Vorteil, dass die Erfahrung direkt über den Browser ausgeliefert werden kann, ohne dass eine eigene App heruntergeladen werden muss. Und da die Performance von Browsern und Webtechnologien in den letzten Jahren immer besser geworden ist, gab es hier keine größeren Probleme.

Zunächst einmal mussten wir uns entscheiden, welche Technologie wir für unser Projekt verwenden wollen. Wir haben uns für AR.js entschieden, eine Open-Source-Lösung für Augmented Reality im Web. AR.js wurde von den Entwicklern Nicolò Carpignoli und Jerome Etienne ins Leben gerufen und hat mittlerweile den Status einer GitHub-Organisation erreicht. Das Ziel hinter AR.js ist es, jedem einfach AR im Web zur Verfügung zu stellen und AR im Web zu etablieren. Klingt super, oder?

Die Entwicklung mit AR.js ist auch vergleichsweise simpel. Um eine Erfahrung mit AR.js zu erstellen, benötigt man in der Regel nur HTML, JavaScript und CSS. Und das Beste daran ist, dass AR.js nur wenige Voraussetzungen an das Zielsystem stellt. Für einfache Projekte reicht schon die Rechenleistung sowie die Kameraqualität eines aktuellen Mittelklasse-Smartphones aus. Auch die benötigten Browserfeatures halten sich in Grenzen, hier werden nur WebGL und WebRTC benötigt. WebGL kommt zum Einsatz, um über JavaScript eingefügte 3D-Objekte mittels der Hardware des Endgeräts zu rendern. WebRTC oder auch die getUserMedia/Stream-API wird benötigt, um auf die Kamera des Endgeräts zuzugreifen.

function getArrowRotation(markerId) {
  // hier wird die Rotation des Pfeils zum nächsten anhand der Marker-ID berechnet
  // Rückgabe der Rotation als Array [x, y, z]
  return [0, 0, 45]; // Beispiel-Wert, Rotation um 45 Grad
}

// Laden des AR-Trackers und des Pfeils
var markerUrl = "path/to/marker.patt"; // Pfad zum Marker-File
var arrowUrl = "path/to/arrow.gltf"; // Pfad zum Pfeil-Modell

var marker = new THREE.Group();
var arrow;

new THREEx.ArMarkerControls({
  // Hier wird der Marker geladen und auf eine Gruppe gelegt
  // (die Gruppe dient später dazu, den Pfeil relativ zum Marker zu positionieren)
  type: "pattern",
  patternUrl: markerUrl,
  changeMatrixMode: "cameraTransformMatrix",
  matrixAutoUpdate: true,
  minConfidence: 0.5,
  width: 1,
  height: 1,
  onLoaded: function() {
    marker.add(this.object3d);
  }
});

// Laden des Pfeils
var loader = new THREE.GLTFLoader();
loader.load(arrowUrl, function(gltf) {
  arrow = gltf.scene;
  arrow.scale.set(0.1, 0.1, 0.1);
  marker.add(arrow);
});

// Render-Schleife
function animate() {
  requestAnimationFrame(animate);

  if (marker.visible && arrow) {
    // Hier wird die Rotation des Pfeils angepasst
    var rotation = getArrowRotation(marker.id);
    arrow.rotation.z = rotation[2];
  }

  renderer.render(scene, camera);
}

animate();

Um die Navigation zu realisieren, haben wir einen modifizierten Dijkstra-Algorithmus verwendet. Dieser findet den kürzesten Weg zwischen den Markern, indem er jedem Marker seine Nachbarmarker hinterlegt. Zusätzlich haben wir den Winkel in dem sich die Nachbar-Marker befinden, angegeben, um den projizierten Pfeil in die richtige Richtung zeigen zu lassen.

Visualisierung der Navigation
function shortestPath(graph, startNode, endNode) {
  // Initialisiere Distanzen und besuchte Knoten-Liste
  const distances = {};
  const visited = {};
  Object.keys(graph).forEach((node) => {
    distances[node] = Infinity; // Setze alle Knoten auf unendliche Distanz
    visited[node] = false; // Setze alle Knoten auf unbesucht
  });

  // Setze Startknoten auf Distanz 0
  distances[startNode] = 0;

  // Gehe alle Knoten durch und finde den kürzesten Pfad
  let currentNode = startNode;
  while (currentNode !== endNode) {
    // Finde Nachbarn des aktuellen Knotens und berechne ihre Distanz
    const neighbors = graph[currentNode];
    Object.keys(neighbors).forEach((neighbor) => {
      const distance = distances[currentNode] + neighbors[neighbor]; // Berechne Distanz zum Nachbarn
      if (distance < distances[neighbor]) {
        distances[neighbor] = distance; // Aktualisiere Distanz zum Nachbarn, falls kleiner
      }
    });

    // Markiere aktuellen Knoten als besucht
    visited[currentNode] = true;

    // Finde den nächsten Knoten mit der kürzesten Distanz
    let shortestDistance = Infinity;
    let nextNode;
    Object.keys(distances).forEach((node) => {
      if (!visited[node] && distances[node] < shortestDistance) {
        shortestDistance = distances[node]; // Aktualisiere kürzeste Distanz, falls kleiner
        nextNode = node; // Setze nächsten Knoten als den mit der kürzesten Distanz
      }
    });

    // Wenn kein nächster Knoten gefunden wurde, gib null zurück
    if (!nextNode) {
      return null;
    }

    // Setze nächsten Knoten als neuen aktuellen Knoten
    currentNode = nextNode;
  }

  // Gib die kürzeste Distanz zurück
  return distances[endNode];
}

// Beispielverwendung
const graph = {
  A: { B: 1, C: 4 },
  B: { D: 2 },
  C: { D: 1 },
  D: {},
};
console.log(shortestPath(graph, 'A', 'D')); // Ausgabe: 3

Durch ein System, das auf verschiedene Marker als Nodes setzt, könnten später auch Marker gewichtet werden. Dies würde bei gleicher Entfernung zum Ziel die Möglichkeit geben, Routen vorzugeben, um den Kunden beispielsweise direkt zu Sonderangeboten zu führen.

Obwohl wir derzeit keine Pläne haben, das Projekt weiterzuentwickeln, sehen wir das Potenzial unserer Lösung für andere Anwendungsfälle und sind offen für zukünftige Projekte, die auf dieser Technologie basieren.

Dank der webbasierten Lösung und der Verwendung von AR.js konnte die AR-Erfahrung direkt über den Browser ausgeliefert werden, ohne dass eine eigene App benötigt wurde. Wir sind stolz darauf, eine Lösung entwickelt zu haben, die den Kunden in Baumärkten und Lebensmittelgeschäften dabei helfen kann, sich schnell und einfach zurechtzufinden und gesuchte Produkte zu finden.

Wir sind gespannt, welche neuen Anwendungsfälle sich in Zukunft für unser Konzept ergeben werden und freuen uns darauf, unsere Erfahrungen und Kenntnisse in anderen Projekten und Technologien einzubringen.