Interactive Bar

Aus toolbox_interaktion
Wechseln zu: Navigation, Suche
Drink.png

Die Idee war es einen Bartresen zu bauen, der eine Interaktion mit dem Gast ermöglicht jedoch nicht wie ein herkömmlicher Multitouch-Tisch sehr teuer ist. Vor allem wenn man ihn in einer so aufwendigen Form wie einer Bar baut. Hierzu werden unter den Gläsern der Gäste, sowie unter Flaschen oder Bierdeckeln Marker installiert. Diese werden über eine Kamera erkannt, die unter einer matten Plexiglasscheibe angebracht ist und entweder nur auf einem kleinen Bildschirm für den Barkeeper (Tablet) oder einem im Hintergrund angebrachten TV über eine Animation ausgewertet.


Anwendung

Konzept war es, einen Gast der an die Bar kommt zu unterhalten und beim Bezahlvorgang zu unterstützen, bzw diesem zu Regeln. Dazu wird eine Bestellung vom Barkeeper bearbeitet, er mischt also den Drink und stellt diesen auf den Tisch. Zu diesem Zeitpunkt erkennt das System nur ein leeres Glas. Jetzt hat der Barkeeper mehrere Gegenstände, unter denen sich Marker befinden, die jeweils ein Getränk repräsentieren.
Stellt er den Marker in die nähe des noch nicht identifizierten Glases, wird diesem ein Inhalt zugewiesen und der Preis festgelegt. Der Kunde bezahlt dann das Getränk indem er einen eigenen Marker, den er zuvor bekommen hat, neben das Glas legt und so dessen Preis auf seinen „Deckel“ anrechnet. Am ende des Abends geht der Kunde zur Kasse, gibt seinen Marker ab und bezahlt dann die gesamte Rechnung. Das erspar es dem Barkeeper jede einzelne Bestellung gleich abzurechnen, gibt für den Gast einen bessern überblick was er bereits getrunken hat und ist nebenbei eine nette Attraktion.

Zukünftig könnten viele Arten von Gegenständen (mittels Markern) erkannt werden die Irgendwie eingebunden werden könnten, z.B. Getränkekarten, Informationszettel zu Cocktails oder ähnliches.


Aufbau

Da es zu aufwendig gewesen wäre eine ganze Bar aufzubauen wurde eine Box angefertigt, die zu Testzwecken und zur Demonstration verwendet werden kann. Die Box ist ca. 50 cm hoch und mit einer Kantenlänge von 35 cm groß genug um darauf ein paar Gläser abzustellen, die dann von einer Kamera erkannt werden die mittig unter einer matten Plexiglasscheibe steht. Die Marker wurden ausgedruckt und einfach unter die Gläser geklebt.


Prototyp

Reactivision

Die Schwierigkeit bestand darin die Marker gut und vor allem schnell zu erkennen, damit auf dem Bildschirm eine schnelle und flüssige anzeige möglich ist, bzw. die Gläser überhaupt erkannt werden. Dazu ist neben der Größe der Marker und der Beleuchtung in und außerhalb der Box auch die Art der Kamera wichtig.

Marker und Platte:

Marker.png

Um eine flüssige Bewegung darstellen zu können ist es wichtig das bei jedem Frame alle Marker auf der Platte erkannt werden. Das System erkennt sie zwar wenn auch wenn sie nicht sehr deutlich sind, braucht dafür aber länger, wodurch Ungenauigkeiten und ein flackern in der Ausgabe entstehen. Dazu müssten die Marker zum einen groß genug erscheinen, zum anderen sollte die Platte nicht zu undurchsichtig sein. Zunächst hatten wir mit einer komplett durchsichtigen Glasscheibe experimentiert, wodurch man aber den kompletten Inhalt der Box sehen konnte. Die blinde Pexiglasscheibe hat bei der richtigen Beleuchtung allerdings auch funktioniert, lediglich die Konturen der Marker sind etwas verschwommen. Damit dieser Effekt nicht zu stark wird muss die matte Seite nach oben angebracht werden, damit ein möglichst kleiner abstand zwischen der Kontur und der streuenden Glasschicht ist.

Beleuchtung:

Um den Kontrast zwischen dem dunklen Druck und dem hellen Papier bei den Marker möglichst groß zu gestallten wurde die Bar von innen beleuchtet. Natürlich hat tat das der Optik der Bar auch ganz gut. Bei der Beleuchtung ist weniger wichtig wie hell diese insgesamt ist, sondern eher das Verhältnis von innen zu außen, da die Kammer die Belichtung automatisch einstellt. Es sollte also kein zu großer Unterschied zwischen innen und außen herrschen, jedoch genug Licht in der Bar vorhanden sein um die Marker erkennen zu können. Vor allem direkte Einstrahlung von Oben in die Box ist sehr schlecht, z.B. unter einer Lampe.

Spiegelungen:

Diese sind sehr problematisch, da sie Teile des Bildes verdecken und so Marker dort nicht mehr erkannt werden. Die meisten Spiegelungen hatten wir durch die Innenbeleuchtung die wir durch eine rote Lichterkette realisiert hatten. Die einzelnen Lampen mussten nach oben hin lichtdicht verdeckt werden, aber ohne das zu viel Licht verloren ging.

Kamera:

Zunächst wurde eine einfache HD USB Kamera verwendet. Mit dieser wahr aber leider keine schnelle Anzeige möglich, da die Framerate einfach zu gering war. Erst die Sony EyeToy Cam von der PS3 hat mit 60 Hz und einer kleinen, schnell zu verarbeitenden, Auflösung die gewünschten Ergebnisse geliefert.


Die eigene Software

Software

Reactivision und das dazugehörige Processing Plugin Tuio, haben sich hier bewehrt. Alle Bestandteile sind kostenlos und wurden auch schon in anderen Projekten verwendet, wodurch genug Dokumentation zur Verfügung steht. Während die ersten Versionen der Software nur auf dem Beispielcode basierten und nur rudimentäre Funktion lieferten, gibt es inzwischen eine halbwegs benutzbare Version die in allen Einzelheiten Dockumentiert auch im OCS zu finden ist.

Kurz gesagt liefert Tuio eine Reihe von Objekten, die die gerade erkannten Marker repräsentieren. Über die Eigenschaften dieser kann dann eine Ausgabe erzeugt werden. Wir haben in unserer Software eigene Objekte für die Gläser, Personen und Getränkemarker erstellt, die dann mit den erkannten Markern verknüpft werden. Um die Interaktion erkennen zu können, also das annähern eines Drinks an einen Benutzer um diesen zu bezahlen, werden stetig die Positionen der einzelnen Marker verglichen.

Implementierung von Tuio in Processing

import TUIO.*;
TuioProcessing tuioClient;
MarkerInterface marker[];
ArrayList<MarkerInterface> markerListe = new ArrayList<MarkerInterface>();
User users[]; //ein Nutzer
Drink drinks[];  //der Getränke Idenfizierer
Glass glasses[]; //ein Glas mit oder ohne drink
TuioObject tobj;

Aufrufen der Tuio Parameter

void draw() {  //eine Typische draw Funktion, die die Anzeige aller Objekte regelt. 

  background(0);
  image(bg, 0, 0);

  Vector tuioObjectList = tuioClient.getTuioObjects();

  //in diesen Schleifen werden die alle gerade Erkannten Marker durchlaufen, bei jedem Marker wird das zugerhörige Objekt herausgesucht und 
  //dieses Angezeigt, in dem dessen drawItem Funktion aufgerufen wird. Mit den Werten die (x,y,Winkel) die der Marker gerade hat. 
  for (int i=0;i<tuioObjectList.size();i++) {
    tobj = (TuioObject)tuioObjectList.elementAt(i);
  
    for(MarkerInterface m : markerListe) {
     if(m.getID() ==  tobj.getSymbolID()) {
       markerListe.get(tobj.getSymbolID()).drawItem(tobj.getScreenX(width), tobj.getScreenY(height), tobj.getAngle());
     }
    }
  }
  
  payOperations(); //bezahlt Drinks und Aktualliesiert die Werte der Nutzer.
  fillOperations(); //befüllt Gläser und setzt die Preise.

//Es folgen nur noch einige Standartfunktionen von TUIO

// called when an object is moved
void updateTuioObject (TuioObject tobj) {
  //println("update object "+tobj.getSymbolID()+" ("+tobj.getSessionID()+") "+tobj.getX()+" "+tobj.getY()+" "+tobj.getAngle()
  //       +" "+tobj.getMotionSpeed()+" "+tobj.getRotationSpeed()+" "+tobj.getMotionAccel()+" "+tobj.getRotationAccel());
}

// called when a cursor is added to the scene
void addTuioCursor(TuioCursor tcur) {
  //println("add cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+ ") " +tcur.getX()+" "+tcur.getY());
}

// called when a cursor is moved
void updateTuioCursor (TuioCursor tcur) {
  //println("update cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+ ") " +tcur.getX()+" "+tcur.getY()
  //       +" "+tcur.getMotionSpeed()+" "+tcur.getMotionAccel());
}

// called when a cursor is removed from the scene
void removeTuioCursor(TuioCursor tcur) {
  //println("remove cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+")");
}

// called after each message bundle
// representing the end of an image frame
void refresh(TuioTime bundleTime) { 
  redraw();
}

Fazit

Uns ist es gelungen einen Prototyp mit günstigen Mitteln zu bauen. Die Software ist beliebig erweiterbar und je nach Budget kann auch ein Tresen mit beliebiger größe, projektion auf die Plexiglaßplatte etc. gebaut werden.

Das Ergebnis

Gesammtes Layout

alle marker

Anwendung

Bestellvorgang
Kellner stellt ein leeres Glaß auf den Tresen
Er berührt das leere Glaß mit dem bestelltem Drink Marker
Nun zeigt das Glaß den bestellten Drink an
Bestellvorgang
User legt seinen Marker auf den Tresen
Bewegt der User seinen Marker an das Glaß wird der Drink mit seinem Konto verrechnet