Diese Woche gibt es Updates…

 So, lange gab es keinen neuen Artikel… Hintergrund ist, das zurzeit an einer sehr umfänglichen Umstrukturierung an der direcs-Software gearbeitet wird. Hierzu wurde extra im Sourcecode-Repository ein separater Branch eröffnet, da die grundsätzliche Arbeitsweise rund um den seriellen Port geändert wird. Ursache waren diverse Probleme in der Vergangenheit mit der Kommunikation zwischen PC / Mac und dem Roboter. Aber dazu in den nächsten Tagen mehr…

Kinect sychron mit OpenCV als Qt Thread – endlich

 Nach vielen Versuchen in der noch frischen Kinect-Welt ist nun endlich ein lauffähiger erster Wurf heraus gekommen. Aber erst noch ein paar Worte zur Vorgeschichte und als Erfahrungsbericht, falls noch jemand in diese Probleme Herausforderungen läuft.

Begonnen wurde mit der Nutzung von openFrameworks, da es hierzu ein komplexes Beispiel gab, welches auf Anhieb das Bild der Kinect (RGB und Tiefenbild) anzeigt und zusätzlich sogar eine 3D-Punktwolke und auch schon per OpenCV Hindernisse als Blobs darstellt. Vorteil dieser Lösung ist, dass sie unter Mac OS X und unter Linux einwandfrei lief. Nachteil lag (für mich) darin, dass es ein recht komplexes oder besser gesagt sehr vielfältiges Framework ist, welches zusätzlich auf diverse eigene Bibliotheken und zig eigene Datentypen zurückgreift – Nicht gerade der einfachste Einstieg, wenn man ansonsten nicht auf diesem Framework aaufbaut.

Eine weitere Herausforderung war, dass das Ganze in die "Qt-Welt" von direcs eingebettet werden muss, also z.B. mit den genialen Qt-eigenen Mitteln für Events und Eventhandler (sogenannte Signals und Slots). Hierzu gab es dann weitere Experimente, die dann auch mit dem Qt Framework ganz gut zusammen liefen. Hier gab es dann die Schwierigkeit (für mich), dass das Bild mittels OpenGL angezeigt wurde. Da aber ja der Bildinhalt später mit OpenCV weiter verarbeitet werden sollte, gestaltete sich dieses als schwierig.

Um OpenCV erst einmal weitere Erfahrungen zu sammeln, wurde das Buch Learning OpenCV (ISBN 978-0-596-51613-0) von Gary Bradski & Adrain Kaehler aus dem berühmten O’REILLY-Verlag beschafft. Für 50 EUR nicht gerade ein Schnäppchen; ein Fachbuch eben. Das Buch gefällt; leider basiert es auf der alten OpenCV Version 2.0. Seit Dezember 2010 ist Version 2.2 aktuell, bei der es so einige Änderungen gab – insbesondere haben sich die Bibliotheksnamen geändert und es wird offenbar nun viel der Datentyp Mat statt IplImage verwendet, was beim Verständnis bzw. beim Umsetzen von Code-Beispielen, die man im Netz aktuell hat (mir) oft noch schwer fällt. Erste Erfolge wurden daraufhin wie hier beschrieben dann auch zusammen mit Qt und OpenCV erzielt – hier aber noch mit der im iMac verbauten Kamera, nicht mit der Kinect. 

Nun galt es per libfreenect / OpenKinect an das Kamerabild der Kinect zu kommen, das ganze als Qt Thread laufen zu lassen und per OpenCV weiter zu verarbeiten. Und – tadaa – hier es das Ergebnis:

 

 

Und nach vielen Stunden Anpassen, Programmieren und Verstehen kam dann auch das Tiefenbild hinzu: 

 

Hier noch einmal mit Roboter und Laserscanner im vollen Betrieb:

  

Im Gegensatz zu den meisten Beispielen im Netz wird hier übrigens das synchronous Interface / Wrapper genutzt! Verwendet wurde Qt 4.7.1 und OpenCV 2.2.0 – beides installiert unter Mac OS X via MacPorts. Der Sourcecode ist wie immer bei im online Repository bei github als Open Source verfügbar (camThread.h und camThread.cpp). Viel Spaß. Fragen? Kommentare? Gerne.

Kinect Live-Bild in vorhandene Roboter GUI integriert

 Die Integration des Kinect-Bildes geht voran. Sowohl das Live-Bild, als auch das "Tiefenbild" wird nun in der GUI angezeigt. Und hier die ersten Tests:

  

Wie man sieht, ist auf dem ersten Bild eine leicht geöffnete Tür (zum Flur) erkennbar – sowohl auf dem "original" Livebild der Kamera, als auch an den grünen Laserlinien und im Tiefenbild der Kinect; erkennbar am blauen Bereich. Im zweiten Bild sieht man die geöffnete Tür. Auf dem dritten ist sowohl auf dem Kamerabild also auch bei den Laserlinien eine Person gut erkennbar.

Weitere Fortschritte mit der Microsoft Kinect – Erste erfolgreiche Nutzung mit Qt!

 Ein erster eigener Erfolg wurde beim Ansteuern der Kinect erzielt: Vollständige Integration in ein eigenes eigenständiges Qt-Programm. Zugrunde liegend der Open Source Treiber / die Library OpenKinect. Des weiteren sollte der Wrapper für das Qt Framework, welches von mir genutzt wird, verwendet werden, dieser aber brach aber mit Compiler-Fehlermeldungen ab. Statt dessen wurde auf OpenKinect and Qt reference von Jon Macey zurück gegriffen, welches genau so einen Wrapper zur Verfügung stellt. Und so sieht das ganze dann in der per Qt-Designer erstellten GUI aus:

Der Sourcecode ist wie immer hier verfügbar. Der direkte Link zum eigenständigen Kinect-Testprogramm ist dann dieser. Das Original von Jon Macey wurde des weiteren dahingehend erweitert, dass es z.B. bei nicht angeschlossener Kinect das Programm nicht per EXIT beendet, sondern eine von außen abfragbare Variable abgefragt werden kann, ob die Kamera erkannt wurde oder eben nicht.

coding, coding, coding…

Nachdem es in der Vergangenheit öfter Probleme mit der seriellen Übertragung gab, fiel der Entschluss, alle Übertragungen zwischen dem Atmelboard und dem Computer nicht mehr in Binärform sondern in reinem ASCII zu senden. Dazu wurde im git Repository ein neuer Branch namens AtmelSerialClearText angelegt und seit Mitte August immer mal wieder daran gearbeitet. Nun ist es endlich soweit, nahezu alle Funktionen sind komplett auf die neue Übertragungsmethode umgestellt – sowohl auf Computer, als auch auf Atmel-Seite. Wie man sieht, waren dazu doch einige Änderungen nötig:

Merge made by recursive.

 direcs-avr/adconv.c         |   33 ++

 direcs-avr/adconv.h         |    6 +

 direcs-avr/main.c           | 1040 +++++++++++++++++++++++++++++————–

 direcs-avr/main.h           |   13 +-

 direcs-avr/micromag.c       |    4 +

 direcs-avr/usart.c          |  174 ++++++–

 direcs-avr/usart.h          |   38 ++-

 direcs/direcs.tag           |  193 ++++++–

 direcs/src/circuit.cpp      |  112 ++++-

 direcs/src/circuit.h        |   39 ++-

 direcs/src/direcs.cpp       |  127 +++++-

 direcs/src/direcs.h         |   19 +-

 direcs/src/direcsSerial.cpp |   65 ++–

 direcs/src/direcsSerial.h   |    2 +-

 direcs/src/gui.cpp          |   79 ++++-

 direcs/src/gui.h            |   37 ++-

 direcs/src/interfaceAvr.cpp |   98 ++++

 direcs/src/interfaceAvr.h   |   58 ++-

 direcs/src/mainWindow.ui    |   86 +++-

 direcs/src/motor.cpp        |  792 +++++++++++++++++++++———–

 direcs/src/motor.h          |   46 +-

 direcs/src/plotThread.cpp   |   47 ++-

 direcs/src/plotThread.h     |   14 +-

 direcs/src/sensorThread.cpp |  495 +++++++++++———-

 direcs/src/sensorThread.h   |   27 +-

 25 files changed, 2540 insertions(+), 1104 deletions(-)

Zusätzlich wurde das serielle Verfahren auf dem Atmel ebenfalls vollständig neu geschrieben und arbeitet nun – anstatt in einer Endlosschleife auf den Empfang eines Zeichens zu warten – vollständig interruptbasiert.

Wie aber weiß nun der Atmel, wann eine Übertragung für ihn anfängt oder abgeschlossen ist? ganz einfach: Jede Übertragung muss mit einem ‚*‘ starten und mit einem ‚#‘ enden. Alle anderen Zeichenketten werden ignoriert. Eine Signalisierung über LEDs auf der Platine findet ebenfalls statt: Bei jedem empfangenen Zeichen blinkt die rote LED abwechselnd und sobald das Ende eines Befehls mit # erkannt wurde (und zuvor auch mit * startete!) wird dieses über eine grüne LED angezeigt.

Diese Art der Übertragung hat den Vorteil, dass man sie per Terminalprogramm gut debuggen kann, denn es werden nur ASCII-Zeichen verwendet. Zusätzlich antwortet der Atmel auch immer mit der empfangenen Zeichenkette, die wiederum vom Computer als Antwort überprüft wird. Eine neue Sicherheitsfunktion, die zuvor fehlte. Auch kann man dem Atmel so selbst mit einem Terminalprogramm Befehle senden und „sieht“ was er antwortet. Fragt man einen Wert vom Atmel ab, so antwortet er nur mit diesem Wert und dem Starter und Terminator, also z.B. mit *42#.

Und das sind die derzeitigen Befehle:

re = reset

s1 = get value from sensor 1

s8 = get value from sensor 8

s16 = get value from sensor 16

cc = check if compass module is connected. ‚ok‘ or ‚er‘

cx = get value from compass axis x

cy = get value from compass axis y

cz = get value from compass axis z

ms1 = get value from motor sensor 1

ms4 = get value from motor sensor 4

dd1 = get driven distance 1

..

dd4 = get driven distance 4

id1 = init distance 1

id4 = init distance 4

mp1of = motor power 1 off

mp4of = motor power 4 off

md1cw = motor direction 1 clockwise

md4cw = motor direction 4 clockwise

md1cc = motor direction 1 counterclockwise

md4cc = motor direction 4 counterclockwise

mv1nnn = set motor velocity 1 to nnn (0-255)

mv4nnn = set motor velocity 4 to nnn (0-255)

mv0nnn = set motor velocity for all motors to nnn (0-255)

bdf = bot drive forward

bdb = bot drive backward

bdl = bot drive left

bdr = bot drive right

btl = bot turn left

btr = bot turn right

bgo = bot go

bst = bot stop

bwa = bot wait

Portierung zu Mac OS

 Nachdem ich mich entscheiden habe, statt meines good-old Linux-PCs zu einem Apple iMac zu wechseln, stand auch die Portierung zu Mac OS an. Stand deshalb, weil die ersten Schritte mitterweile erledigt sind. Und so sieht das Ganze dann aus:

Noch nicht portiert sind sämtliche Funktionen für den seriellen Port, Sprachausgabe (espeak liegt nicht als Library vor) und OpenCV (Compiler läuft auf Fehler). Aber starten lässt sich die Applikation schon. Kommt Zeit, kommt volle Unterstützung… :-)

Wer einen Eindruck des Aufwandes haben möchte, bitte sehr; hält sich danke Qt sehr in Grenzen:

 direcs/direcs.pro.user       |  264 +++++++——-

 direcs/src/camThread.cpp     |   12 +-

 direcs/src/camThread.h       |   26 +-

 direcs/src/direcs.cpp        |  826 +++++++++++++++++++++———————

 direcs/src/direcs.h          |    4 +-

 direcs/src/direcsSerial.cpp  |    5 +

 direcs/src/direcsSerial.h    |    4 +

 direcs/src/gui.cpp           |    2 +

 direcs/src/gui.h             |    6 +-

 direcs/src/joystick.cpp      |    6 +-

 direcs/src/joystick.h        |    6 +-

 direcs/src/laserSickS300.cpp |   25 ++-

 direcs/src/laserSickS300.h   |    8 +-

 direcs/src/speakThread.cpp   |   25 +-

 direcs/src/speakThread.h     |    2 +

 direcs/src/src.pro           |   41 ++-

 16 files changed, 685 insertions(+), 577 deletions(-)

Screenshots direcs

 

Zwei aktuelle Screenshots – einmal der erste Test mit dem neuen ARM-Board unter Linux in der Debian-VM (Parallels unter Mac OS X), der zweite nativ auf dem Mac.
15.04.2012

Erste Experimente mit der Microsoft Kinect Kamera und dem OpenKinect / libfreenect Sourcecode.
30.12.2010

Größeres Redesing: Grafischen Heartbeat korrigiert, Roboter-Motor-Status wird nun grafisch rechts oben angezeigt (mit GUI LEDs), Änderung der Hauptfenstergröße zur Anzeigen auf dem MacBook Pro.
30.11.2010

Kleine Verbesserungen in der GUI: Grafische LEDs über den Zustand diverser Module im „state“ Bereich rechts oben, Gitternetzlinien innerhalb der Plot-Fenster (Batteriespannungen) und ein grafischer Heartbeat (rot).
14.11.2010