Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektesose2015:dasdritteauge_clean:start

Das Dritte Auge

Entwickelt von Leo Harlos, Erik Jarke, Markus Okur im SS 2015 im MINTgrün Robotik-Labor der TU Berlin

Einleitung

DasDritteAuge ist ein Roboter, der es einer Person, die nicht sehen kann, ermöglicht, sich in einem 3-dimensionalen Raum mit Hindernissen ohne Kollision zu bewegen.

Wir kamen schnell zu dem Entschluss, als Grundlage den Sensor einer Microsoft Kinect zu verwenden, welcher Tiefen- und Bildmesswerte erfassen kann und diese an einen Rechner weiterleitet, der diese Werte interpretiert und dann die entsprechenden Informationen über einen Arduino mittels Vibrationsmotoren an den Nutzer weitergibt.

Die Vibrationsmotoren sollen in ein geeignetes Kleidungsstück z.B. einen Gürtel oder Handschuh eingearbeitet sein und durch ihre Vibrationen dem Nutzer anzeigen, dass sich ein Hindernis 1. in unmittelbarer Nähe befindet und 2. wo genau sich das Hindernis befindet (rechts? links? Mitte?). Die Intensität des Vibrationsmotors soll anzeigen, in welchem Abstand zum Nutzer sich der Gegenstand befindet (ist die Vibration stark, befindet sich der Gegenstand in unmittelbarer Nähe, sodass eine Kollision bald bevorsteht). Dem Nutzer soll somit ermöglicht werden, das Hindernis zu umgehen, sodass es zu keiner Kollision kommt.

Ähnliche Projekte: Kinecthesia

Was war zu tun, damit diese Lösung funktionieren kann?

  • Funktionierende Bilderkennung, welche aus Vielzahl der Messpunkte die relevanten Strukturen erkennen und interpretieren kann
  • Eine stabile Konstruktion, auf welcher die Kinect angebracht werden kann
  • Entwurf geeigner Ausgabemöglichkeiten, die dem Nutzer Feedback gibt
  • Grundprinzipien der Theorie der Mensch-Computer-Interaktion verstehen und anwenden

Hardware

(Bitte Bild anklicken für größere Ansicht)

  • XBOX Kinect
  • Laptop
  • 3 Vibrationsmotoren (9mm)
  • Arduino
  • Zubehör zur Stromversorgung (Akku/Batterien)
  • Eine geeignete mobile Konstruktion (Gürtel/Handschuhe, Rucksack für PC)

Schematischer Aufbau

(Bitte Bild anklicken für größere Ansicht)

Software

Processing SimpleOpenNI Arduino IDE Kinect SDK

Processing ist eine Programmiersprache, die vom Prinzip her Java gleicht, aber einige spezifische Extrafunktionen bietet, die zu einem großen Teil auf die ursprüngliche Zielgruppe von Processing zielen (GrafikdesignerInnen, denen ein Einstieg in das Programmieren erleichtert werden soll). Zu diesen Funktionen gehören die Klassenbibliotheken, die 3d Darstellungen, Sound, Grafik und Datenzugriff ermöglichen. Processing beinhaltet außerdem eine zugehörige Entwicklungsumgebung mit einer Konsolenausgabe und einem Fenster, was die Grafikausgabe der kompilierten Programme zeigt. Zusammen mit der SimpleOpenNI Bibliothek kann Processing mit dem Kinectsensor interagieren. Rückblickend war diese Kombination eine, wenn auch mit einigen Anlaufschwierigkeiten verbundene, gute Wahl für unser Projekt.

Grobe Aufgabenbereiche

1.1 Bilderfassung-Tiefensensor Der Tiefensensor nimmt 640*480 Pixel auf und speichert jeden dieser Pixel mit einer x-,y-und z-Komponente, mit diesen lässt sich jeder Pixel in einem dreidimensionalen Raum darstellen, indem man z.B. mit void setup() { size(200,200,P3D); } das Processing Fenster mit der „size“ Funktion in den P3D render-mode umstellt (der eine Darstellung von dreidimensionalen Objekten ermöglicht)und für jeden Pixel einen Punkt in den Raum zeichnet. Macht man das mit jedem Pixel, dann erhält man ein Abbild des aufgenommenen Raumes, welches eine 3d Aufnahme (ohne Farben) zeigt. Hier eine Beispielaufnahme von einem Teammitglied (Erik) mit der eben beschriebenen Methode (Bitte Bild anklicken für größere Ansicht) Hier ist eine schematische Darstellung einer 4 Pixel großen Fläche im R³, diese soll nocheinmal anschaulich darstellen, welche Bedeutung die x,y,z Komponenten einer Messung des Tiefensensors haben. (Bitte Bild anklicken für größere Ansicht) Betrachtet man den Sensor als Koordinatenursprung, dann kann man die einzelnen Pixel als Vektoren mit drei Komponenten(x,y,z) im R³ betrachten und so mit ihnen rechnen. So wird auch Processing-intern mit ihnen verfahren, denn die SimpleOpenNI Bibliothek gibt Das Bild des Tiefensensors in einem ein-dimensionalem PVector Array aus. Die PVector Klasse ist eine Processing-interne Klasse, welche es dem Programmierer erlaubt mit Vektoren zu rechnen. testarraykinect_readfile_writefile_beiknopfdruck.zip

1.2 Ausgabe in Form von Vibrations-Feedback

Für die Ausgabe zeichnet sich ein an das Laptop angeschlossener Arduino samt flacher Coin-Vibrationsmotoren (9mm) verantwortlich. Um die Vibrationsmotoren überhaupt zum Laufen zu bekommen, sind einige Vorüberlegungen notwendig. Laut Datenblatt der Vibrationsmotoren läuft ein Vibrationsmotor mit 3V und bezieht ca. 120 mA. Die I/O-Pins des Arduino können nur maximal 40mA aufbringen, bei großen Lasten, wie bei mehreren Vibrationsmotoren benötigt man eine Zusatzschaltung, um den I/O-Pin zu verstärken. Diese nennt sich MOSFET.

Sehr grob zusammengefasst ist ein MOSFET ein spezieller Transistor und besteht aus den drei Anschlüssen G (gate = Steuerelektrode) zur Kontrolle, D (drain = Abfluss) als Out und S (source =Quelle) als In. Der MOSFET befindet sich immer im Sperr-Zustand, wenn keine positive Spannung zwischen G- und S-Anschluss anliegt. Wenn man nun ein HIGH signal an G schickt, schaltet der Transistor um und erlaubt es dem Strom von S zu D zu fließen.

Der MOSFET kann auf zwei verschiedene Arten schalten:

Ein-/Ausschalten mit Digital Pin

pinMode(5, OUTPUT;   // in der Setup-Routine
digitalWrite(5, HIGH); // Einschalten des MOSFET
digitalWrite(5, LOW);  // Ausschalten des MOSFET

Pin 5 ist hier ein beliebiger Digital-Pin

Leistungsregelung durch Pulsweitenmodulation (PWM)

In Kürze erklärt, beschreibt Pulse Width Modulation ein Verfahren, bei dem der Strom in schneller Abfolge ein- und abgeschalten wird. Ein Zeitintervall ist dabei ca. 20 Millisekunden lang. Träge Bauelemente kann man durch ein PWM Signal dimmen. Ist der Strom z.B. 10 Millisekunden ein- und danach 10 Millisekunden abgeschalten, ist der resultierende Strom und dessen Verbrauch nur halb so groß. Eine Vibrationsmotor würde also nur halb so kräftig vibrieren.

Für Pulsweitenmodulation (PWM) muss ein PWM-fähiger Pin des Arduino verwendet werden z.B. 3, 5, 6, 9, 10, 11. Bei PWM wird ein Signal mit etwa 490Hz am Pin erzeugt, dessen Impuls-/Pauseverhältnis mit einem 8Bit-Wert (0…255) gesteuert wird:

analogWrite(5, 128)  // 50%

erzeugt ein Puls-/Pauseverhältnis von 50%. Die beiden Grenzwerte lauten:

analogWrite(5, 0)     // 0% ausgeschaltet
analogWrite(5, 255) // 100% voll eingeschaltet

Anhand dieser Vorüberlegungen lassen sich die Vibrationsmotoren an dem Arduino betreiben.

1.3 Bau einer mobilen Konstruktion

Der Bau einer mobilen Konstruktion ist sicherlich der Teil, der uns vor Anfang unseres Projektes am allermeisten gereizt hat. Wir malten uns aus, wie wir uns in den verworrenen Gängen des Mathebaus mit verbundenen Augen mithilfe unserer mobilen DasDritteAuge-Konstruktion orientieren können würden und Labyrinthe zum Testen bauen würden. Doch leider hat uns die Realität schon sehr bald eingeholt und die Implementierung des RANSAC-Algorithmus erforderte all unsere Aufmerksamkeit.

1.4 Ransac-Algorithmus anwenden zur Objekterkennung eines spezifischen Gegenstandes (z.B. Wand, Ball):

Grundlegende Erklärung

Der Ransac-Algorithmus dient eigentlich dazu, Ausreißer aus einem Messversuch herauszufiltern. Man kann ihn jedoch auch abändern, um bestimmte Modelle in einem Bild erkennen zu können. Hierzu wird eine Ebenengleichung aufgestellt, die eine Ebene im Raum beschreibt. Dazu sucht man als erstes genügend Messpunkte, um das Modell zu erzeugen, zufällig aus dem Bild (1.) und erzeugt aus ihnen ein Modell (2. und 3.). Dieses Modell wird nun getestet (4), indem man das Bild durchgeht und für jeden Punkt überprüft, ob dieser auf der Ebene liegt. Hat ein Modell sehr viele Elemente, kann man davon ausgehen, dass es ein sehr gutes Modell ist. Dieses Vorgehen wird wiederholt, um möglichst viele Modelle zu erzeugen und somit eine höhere Genauigkeit zu erreichen.

Detaillierte Erklärung der einzelnen Schritte mit mathematischen Details

1. Als erstes werden drei Punkte zufällig aus dem Bild gewählt. Dabei sollte darauf geachtet werden, dass die Punkte überhaupt eine Ebene erzeugen können. So ist z.B. ein Punkt mit z == 0 nicht sinnvoll, da dieser Punkt weiter weg ist, als die Kinect messen kann und daher keine sinnvolle Ebene bildet.

2. Aus diesen drei Punkten erstellt man nun eine Ebenengleichung in Parameterform mit Hilfe der Drei-Punkte-Form:

$ \vec{x} = \vec{OA} + r * \vec{AB} + s * \vec{AC} $

3. Nun wird die Ebenengleichung in die Normalenform umgewandelt, um mit der Gleichung besser arbeiten zu können. Für den Stützvektor kann man $ \vec{OA} $ verwenden, wärend man den Normalenvektor per Kreuzprodukt aus $ \vec{AB} $ und $ \vec{AC} $ bestimmt.

$ ( \vec{x} - \vec{OA} )* \vec{n} = 0 $

4. Als letztes wird das Modell getestet. Dazu geht der Algorithmus durch den Bildarray und überprüft, ob die jeweiligen Bildpunkte auf der Ebene liegen. Dabei werden die Elemente gezählt, sodass man danach die Modelle anhand der Anzahl bewerten kann. Dabei sind Modelle mit vielen Elementen logischerweise realistischer, als welche mit wenig Elementen.

5. Dieses Vorgehen wird für jedes Bild beliebig oft wiederholt, bis man ausreichend Modelle hat, um die Umgebung optimal zu beschreiben.

ransac_schlank.zip

Herausforderungen

Die Implementierung des RANSAC-Algorithmus war sehr zeitaufwändig, wesentliche Probleme waren die Laufzeit sowie die Filterung der Modellgruppen. Trotz allem ist der RANSAC-Algorithmus eine sehr gute Wahl gewesen, da er auch Flächen erkennt, die teilweise verdeckt sind (z.B. ein vollgestellter Tisch) und zudem mit weiteren Modellen (z.B. eine Kugel) ergänzt und an die Situation angepasst werden kann. Für ein marktreifes Produkt müsste diese Technik allerings mit anderen Algorithmen kombiniert werden, da nicht jeder Gegenstand als Modell erfasst werden kann und somit der Raum nicht vollständig an dem Benutzer weitergegeben werden kann.

Anfänglich war die Laufzeit der RANSAC-Implementierung sehr langsam. Dies liegt hauptsächlich an dem großen Bildarray(307 200 Elemente), dem man zum einen einlesen und zum anderen innerhalb des Algorithmus durchlaufen muss. Das Einlesen hat am Anfang ca. 50 Sekunden pro Bild gedauert, doch dieses Problem konnten wir beheben, indem wir Binärdateien statt Textdateien verwenden. Dadurch dauert das Einlesen ca. eine Sekunde. Eine Echtzeitanalyse ist allerdings immer noch nicht möglich, da das Programm lediglich 15 Gruppen pro Minute findet(Win 8.1 64-Bit: Intel Core i5, 8 GB RAM). Die Ursache dieser langsammen Laufzeit ist der große Bildarray, dessen Elemente bei jeder neuen Gruppe mit dieser verglichen werden müssen. Ein weiterer Grund ist die Programmiersprache, die wir verwendeten: Programme in Java/Processing werden in einer virtuellen Maschiene ausgeführt, weshalb die Programme systemunabhänig laufen, allerdings auch deutlich langsammer. Die Laufzeit wird hauptsächlich durch Anzahl der Wiederholungen des Algorithmus bestimmt, also der Anzahl an erzeugten Modellen je Bild. Je weniger Modelle erzeugt werden, desto unwahrscheinlicher ist es, dass alle relevanten Ebenen gefunden wurden.

Desweiteren hatten wir Probleme, die gefundenen Gruppen sinnvoll zu filtern. Hierbei ist besonders die Streuung entscheident, die festlegt, wie stark die Werte abweichen können, um trotzdem einer Gruppe zugeordnet zu werden. Bei einer kleinen bis normalen Streuung wurden immer viele Ebenen gefunden, die sich überlagern, sodass eine Fläche nicht als einzelne Fläche erkannt wurde, sondern eine Kombination verschiedener Ebenen. Bei einer zu großen Streuung wurden alle Punkte, die ungleich 0 waren, zu einer Ebene zusammengefasst. Des weiteren wird auch nach der Anzahl der Gruppenelmente sortiert. So wird eine Gruppe mit mehr Elementen immer bevorzugt behandelt, da sie mit höherer Wahrscheinlichkeit eine Ebene beschreibt.

zu kleine Streuung:

Man sieht nicht viel auf dem Bild, da nur sehr kleine Gruppen gebildet werden, da bereits eine kleine Abweichung dazu führt, dass die Punkte der Gruppe nicht zugeordnet werden. Mit solch kleinen Gruppen kann die Umgebung nicht beschrieben werden, zumal man viel mehr Gruppen finden muss, um ein aussagekräftiges Ergebnis zu bekommen, was wiederum zu einer erhöhten Laufzeit führt.

zu große Streuung:

Bei einer zu großen Streuung wird die Umgebung recht gut sichtbar, so kann man gut die zwei Stühle sowie den Pfeiler im Hintergrund erkennen. Allerdings wurden alle Punkte, deren z-Werte ungleich Null sind, in eine Gruppe zusammengefasst, die natürlich nicht besonders aussagekräftig ist. Dementsprechend ist eine zu große Streuung ähnlich hilfreich, wie eine zu kleine.

gute Streuung:

Bei diesem Bild ist die Streuung recht gut gewählt, da Ebenen, die dicht hintereinander liegen, als einzelne Ebenen erkannt werden(siehe Stuhl links unten). Allerdings ist noch ein Fehler in der Filterung zu erkennen: Die vielen Linien, die schräg durchs Bild laufen, sind schräg im Raum stehende Ebenen, die fälschlicherweise erkannt werden. Um dieses Problem zu lösen, muss man die erstellten Gruppen noch stärker filtern.

Ein weitere Herausforderung ist das bislang noch nicht so weit vorgeschrittene softwareseitige Entwicklung des haptischen Feedbacks an den Nutzer. Da wir aufgrund der oben genannten Schwierigkeiten in unserem Zeitplan hinterherhinkten, haben wir uns bisher noch nicht umfassend damit beschäftigen können, streben dies aber auf jeden Fall an.

Wissen

Was muss noch recherchiert werden?

  • genaue Distanz- und Größenberechnung der gefundenen Ebenen
  • beste Art und Weise haptisches Feedback durch Vibrationsmotoren zu vermitteln um einen möglichst genauen Eindruck der Umgebung zu bekommen
  • wie kann man aus den Gefundenen Ebenen mittels Referenzmodellen Informationen gewinnen z.B. was ist der Boden?, Treppenerkennung, plötzliche Höhenabfälle, oder um was für ein Objekt es sich handelt z.B. ein Ball oder ein Stuhl usw.

Fazit mit Bezug auf Gantt-Diagramm

Gantt-Diagramm

Das Gantt-Diagramm war wahrscheinlich das Erste, was wir gemeinsam als Gruppe erstellt haben und das letze, worüber wir gemeinsam reflektiert haben (für alle die es nicht wissen: Ganttproject ist eine Art Zeitplaner, mit dem man sich die Arbeit aufteilen kann und Zeitmarken setzten kann, wie z.B.„wir wollen am 8.06. eine Materialliste erstellt haben!“).

Materialliste

Als erster Punkt steht die Materialliste auf dem Plan, auch deswegen, weil wir sie ziemlich früh, mit einer Deadline, in das Kurswiki eintragen mussten. Sie hat sich recht grundlegend geändert, z.B sind viele Entscheidungen zu diesem Zeitpunkt noch nicht getroffen worden und viele Erkentnisse noch nicht gewonnen worden, wie z.B. »welche Kinect, der vielen, die es auf dem Markt gibt, verwenden wir?«, die Antwort:»die, die im Schrank eingeschlossen ist!« (Kinect v1 für XBOX). Als Rechner wollten wir anfänglich noch einen kleinen Einplatinencomputer verwenden, wie z.B. einen Raspberry Pi, doch uns ist später aufgefallen, dass die Leistung dieser nicht ausreichte und wir sind dazu übergegegangen einfach den einzigen unserer drei Laptops zu verwenden, der die Kinect erkannt hat. Am Anfang gab es noch die Debatte, ob wir Audio- oder Vibrationsfeedback ausgeben lassen sollten, die Entscheidung fiel auf Vibrationsfeedback, daher sind z.B. die Kopfhörer auf der ersten Materialliste gestrichen worden. Außerdem sind mit fortschreitendem Wissensstand auch kleine elektronische Bauteile wie z.B. Dioden, Kondensatoren, Transistoren, Widerstände usw., für die Ansteuerung der Vibrationsmotoren mit dem Arduino, in die Liste eingetragen worden.

Funktionsfähigkeit

Der nächste Punkt, in unserem blauäugigen Diagramm, ist die Funktionsfähigkeit, womit soviel gemeint ist wie: »Ein funktionsfähiger Prototyp, der nur noch einen Feinschliff braucht«. Diese Prognose war etwas zu optimistisch, wie sich alsbald herausgestellt hat. Denn selbst für den nächsten Punkt „Kinect anschließen“ haben wir erstaunliche eineinhalb Wochen gebraucht, der Rest streckt sich dementsprechend. Für eine einfache Bilderkennung haben wir uns zwar viereinhalb Wochen gegeben, allerdings wollten wir schon nach einer Woche die ersten Ergebnisse sehen, um Material zu haben, mit dem man an einem Vibrationsfeedback arbeiten kann. Im Nachhinein scheint die Schachtelung der Aufgaben seltsam eng, das liegt vielleicht auch daran, dass das Gant-Diagramm am 15.07. endet (Dieser Eintrag ist am 13.08. erstellt).

projektesose2015/dasdritteauge_clean/start.txt · Zuletzt geändert: 2016/01/21 12:45 (Externe Bearbeitung)