Johnny 5


  Johnny-5-Projekt von Jörg Roth
  

     
   

  Einleitung 

  Die Idee 

  Resultate 

  Drei-Motoren-Problem 

  LabView Programmierung 

  Mechanik 


Alle Mindstorms-Projekte

Jörg Roths Homepage

Email email 

Impressum 


English This page
in English

















   

Einleitung

Ob R2D2, Marvin, Data, T101, Twiki oder RX2714 – irgendwann kommt bestimmt bei jedem Mindstorms NXT-Fan der Wunsch auf, einen Film-Roboter nachzubauen. Für mich war klar, dass nur ein Roboter für solch ein Vorhaben in Frage kommt: Johnny (Nummer) 5 aus dem Film "Nummer 5 lebt!".
Auf der Basis vergangener NXT-Erfahrungen habe ich mir Folgendes vorgenommen:
  • Das Modell sollte eine Kombination aus Standmodell und funktionsfähigem Modell sein: es sollte im Rahmen der Möglichkeiten dem Spielfilm-Vorbild möglichst ähnlich sehen. Andererseits sollte es verschiedene einfache Aufgaben ausführen können.
  • Es sollte Lego-Technics-Elemente mit klassischen Lego-Bausteinen kombinieren.
  • Schließlich sollte mit diesem Modell die Grenzen der LabView-Programmierung, die Grenzen des NXT-Ansatzes und die mechanischen Grenzen der Lego-Bauweise erkundet werden.
Im Folgenden möchte ich einige Erfahrungen mit dem Aufbau darstellen.
Johnny 5 sketch

"Original" Johnny 5

Die Idee

Johnny 5 war im Film ein ehemaliger Militärroboter – gut zu erkennen an dem Kettenlaufwerk, das gut für raues Terrain geeignet ist. Um das nachzubauen, benötigt man weitere Bausteine, denn Ketten-artige Elemente findet man im NXT-Bausatz vergeblich. Glücklicherweise konnte ich auf 30 Jahre alte Lego-Bausteine meiner Kindheit zurückgreifen, unter denen sich auch ein Satz Ketten-Elemente befand. Die ersten Module des Modells waren dann auch die beiden Laufwerke. Mit ihnen sollte Johnny 5 vorwärts und rückwärts fahren, auf der Stelle drehen sowie Kurven fahren können. Darüber hinaus sollten auch kleine Hindernisse überfahren werden können.
Neben dem Ausführen von Fahrbefehlen sollte Johnny 5 die Umgebung mit seinen Sensoren erfassen können. Dazu sollte der Kopf mit dem Ultraschallentfernungssensor ausgestattet werden (was rein optisch auch sehr nahe liegt). Daneben sollte der eine Arm mit dem taktilen Sensor, der andere mit dem Lichtsensor ausgestattet werden. Der Tonsensor sollte nicht verwendet werden (ich persönlich finde ihn auch mehr als überflüssig). Zur Sensorerfassung mit den Armen sollten die Arme wechselweise nach vorne gebracht werden, je nachdem welche Sensorerfassung man durchführen möchte. Darüber hinaus sollte der Kopf in alle Richtungen gedreht werden, um Entfernungen in verschiedenen Winkeln messen zu können.
Die verschiedenen Funktionen sollten durch eine Bausteinbibliothek repräsentiert werden. Es sollte folgende Bausteine geben:
  • Geradeausfahren bis zu einem Hindernis; protokollieren des zurückgelegten Weges
  • Geradeausfahren um x cm oder Hindernis; protokollieren des zurückgelegten Weges
  • Drehen um +/-x Grad auf der Stelle
  • Drehen des Kopfes nach vorne/rechts/links; protokollieren der gemessenen Entfernung
  • Vorbringen eines der Sensorarme; durchführen und protokollieren der jeweiligen Messung
Weitere Bausteine zum Initialisieren und Abschließen der Umgebung sollten hinzukommen. Mit Hilfe aller Bausteinen sollten komplexe Programme z.B. die Umgebungsexploration einfach entwickelt werden können.
     
Johnny 5

Johnny 5

Resultate

Das Modell von Johnny 5 sah, nach diversen Verbesserungen wie folgt aus:

Johnny 5

Johnny 5 von vorne

Johnny 5

Johnny 5 von der Seite

Beim Aufbau und bei der Programmierung mussten einige Probleme gelöst werden:
  • Die Programmierung mit LabView stieß an diverse konzeptionelle Grenzen sowie an Grenzen der Stabilität. Während neue Versionen der Programmierumgebung sicher auch stabiler werden, lassen sich die konzeptionellen Grenzen nicht so leicht beheben (siehe später mehr dazu).
  • Ursprünglich sollte anhand der Sensordaten eine Umgebungskarte im NXT-Baustein aufgebaut werden. Das war, wie sich schnell herausstellte, zu ambitioniert für die vorliegende Laufzeitumgebung. Dann sollten die Sensorinformationen wenigstens direkt per Bluetooth an einen PC gesendet werden, der dann eine Karte erstellt. Wegen einer Bluetooth-Unverträglichkeit des NXT-Bausteins mit meinen PC (was erwiesenermaßen aber die Schuld des NXT-Bausteins war), musste ich von diesem Plan Abstand nehmen. Stattdessen wurden die Sensor-Logs in eine Datei protokolliert, die später zur Auswertung per USB ausgelesen werden kann.
  • Die Beschränkung von drei Motoren pro NXT-Baustein erwies sich für mein Vorhaben als sehr störend (auch dazu später mehr).
  • Der mechanische Aufbau war nicht ganz einfach. Vor allem der Kettenantrieb erwies sich als Problem: Während der "echte" Johnny 5 Ketten hatte, die in Querrichtung leicht über den Untergrund bewegt werden konnten, hafteten meine Kettenelemente in jeder Richtung gleich gut am Untergrund. Beim Drehen auf der Stelle entstanden so mechanische Spannungen in Querrichtung. Das konnte ich zwar durch ein zusätzliches Zahnrad beheben, allerdings ging dadurch auch die Eigenschaft verloren, mit den Ketten über Hindernisse zu fahren.
Für die meisten der genannten Probleme gab es Lösungen oder zumindest Work-arounds. Zu den größten Problemen komme ich später noch einmal. An dieser Stelle möchte ich erst einmal einige Beispielprogramme darstellen:

Fahren und Sensorwerte erfassen

Dieses einfache Programm lässt Johnny 5 bis zu einem Hindernis vorwärts fahren. Dann werden die Sensoren der Arme eingesetzt, um die Lichtintensität zu messen, sowie zu testen, ob ein massives Hindernis vorliegt.

Johnny 5 programm

Programm: Run_and_probe


      Die resultierende Log-Datei:
Light density/lamp on: 27
Light density/lamp off: 26
Tactile/currentPos: free
Tactile/7cm ahead: pressed

Drehen – Fahren – Drehen

Dieses Programm illustriert Fahrbewegungen. Die Aufgabe ist, auf der Stelle zu drehen, eine bestimmte Distanz geradeaus zu fahren und nochmals auf der Stelle zu drehen.

Johnny 5 programm

Programm: Turn_and_run


      Die resultierende Log-Datei:
Turned Right [deg]: 90
Moved forward [cm]:20
Turned Left [deg]: 90

Exploration der Umgebung

Dieses Programm ist das endgültige Betriebsprogramm von Johnny 5. Die Aufgabe ist, für eine bestimmte Zeit in einem vorher abgesteckten Gebiet zu fahren und dabei die Abstände zu den Hindernissen zu messen. Die Sensor-Log-Datei kann danach im PC eingelesen und in eine Karte umgewandelt werden.

Johnny 5 programm

Programm: Exploration



Die resultierende Log-Datei:
Moved forward [cm]:53
Ultrasonic distance/looking front [cm]:  71
Ultrasonic distance/looking left [cm]:  255
Ultrasonic distance/looking right [cm]:  62
Turned Right [deg]: 45
Moved forward [cm]:30
Ultrasonic distance/looking front [cm]:  37
Ultrasonic distance/looking left [cm]:  49
Ultrasonic distance/looking right [cm]:  37
Turned Right [deg]: 45
Moved forward [cm]:1
Ultrasonic distance/looking front [cm]:  36
Ultrasonic distance/looking left [cm]:  36
Ultrasonic distance/looking right [cm]:  118
Turned Right [deg]: 45
Moved forward [cm]:53
Ultrasonic distance/looking front [cm]:  57
Ultrasonic distance/looking left [cm]:  25
Ultrasonic distance/looking right [cm]:  255
Turned Right [deg]: 45
Moved forward [cm]:52
Ultrasonic distance/looking front [cm]:  255
Ultrasonic distance/looking left [cm]:  21
Ultrasonic distance/looking right [cm]:  255
Turned Right [deg]: 45
Moved forward [cm]:16
Ultrasonic distance/looking front [cm]:  255
Ultrasonic distance/looking left [cm]:  255
Ultrasonic distance/looking right [cm]:  145
Turned Right [deg]: 45
Moved forward [cm]:52
Ultrasonic distance/looking front [cm]:  89
Ultrasonic distance/looking left [cm]:  40
Ultrasonic distance/looking right [cm]:  255
Turned Right [deg]: 45
          
Explored environment

Mit Sensoren erkundete Umgebung

Das Drei-Motoren-Problem

Eine große Herausforderung entstand durch die eine Restriktion im NXT-Konzept, die ich nicht wirklich verstanden habe: es gibt lediglich drei Motoren. Die Motoren können zwar einzeln hinzugekauft werden, allerdings hat der NXT-Baustein nur drei Motorenausgänge. Ein Grund für diese Restriktion könnte gewesen sein, dass die Anschlussfläche am Baustein beschränkt ist, man sich daher nur insgesamt sieben Anschlüsse leisten konnte. Wenn dem so ist, hätte man meiner Meinung den Geräuschsensor einsparen können und stattdessen einen vierten Motor spendieren können. Man hätte die Motoren und Sensoren auch über eine Art Bussystem verbinden können. Damit wäre auch die zentralistische Verkabelung, die manchmal ein Problem darstellt vermieden worden.
Wie dem auch sei – ich hatte mehr Funktionen im Sinn, als durch drei Motoren bewältigt werden kann. Für das Fahren in alle Richtungen inklusive Kurven benötigt man alleine schon zwei Motoren. Für die Sensorerfassung mit den Armen und das Drehen des Kopfes stand damit nur noch ein Motor zur Verfügung.

Johnny 5

Der Oberkörper

Johnny 5

Der Kopf

Johnny 5

Der Kopf von hinten

Johnny 5

Der taktile Sensor

Die nicht sehr zufriedenstellende Lösung des Problems war, die Arme und den Kopf zu koppeln. Damit ist keine unabhängige Bewegung mehr möglich. Die Lösung im Detail:
  • Eine Drehung des Armmotors um 180 Grad wechselt die Stellung der Arme. Der Kopf bewegt sich vernachlässigbar minimal.
  • Eine Drehung des Armmotors um n*360 Grad bewegt zwar die Arme, nach der Ausführung ist die Armstellung aber wie vor der Ausführung. Der Kopf hat sich aber nach rechts oder links gedreht.
Durch Drehen eines Winkels von n*360+m*180 (n aus {0...7}, m aus {0,1}) kann man damit jede gewünschte Kopf- und Armstellung einstellen. Der Nachteil ist jedoch, dass sich bei der Kopfbewegung die Arme erst einmal mitbewegen, auch wenn sie später wieder die Ausgangsstellung erreichen. Für umfangreiche Bewegungen ist das störend, so dass ich für das Explorationsprogramm die Arme mechanisch fixiert habe.

Programmieren mit LabView

Die zweite große Herausforderung war die Programmierung mit LabView. Mit einem Hintergrund von mehreren mio. Zeilen Code imperativer und objektorientierter Programmierung sollte die Programmierung mit LabView eigentlich kein großes Problem darstellen...
Leider stellte sich die Programmierung aus meiner Sicht dennoch als Problem heraus. Die Gründe:
  • Die Programmierung mit dem Datenflussmodell hat diverse konzeptionelle Limitationen.
  • Die LabView-Umgebung für NXT stellt sich als äußerst instabil heraus.
  • Aus der Original-LabView-Umgebung wurden einige wichtige Funktionen für NXT weggelassen.
Die LabView-Umgebung von NXT folgt folgendem Prinzip: Einfaches ist einfach, Komplexes ist unmöglich. Die Intension war wohl, dass einfache Programme von Laien schnell entwickelt werden können. Die Erfahrung mit Johnny 5 hat gezeigt, dass man zwar auch kompliziertere Anwendungen programmieren kann, Vorhaben wie die Kartographierung der Umgebung im NXT-Baustein sind aber mangels einer vernünftigen Zustandsverwaltung im Datenflussmodell unmöglich. Im Datenflussmodell wird ein Ausgangswert eines Blocks (z.B. ein Sensorwert) direkt in den Eingang eines weiteren Blocks gegeben (z.B. als ein Wert, der die Motordrehzahl steuert). Da es auch Bausteine gibt, die kleine Rechnungen ausführen, kann man so auch komplizierte Sachverhalte zwischen Ein- und Ausgängen ausdrücken.
Alles ist also irgendwie im Fluss. Man kann zwar auch Statusinformationen in Variablen speichern; während das in der imperativen und objektorientierten Programmierung der Normalfall ist, stellt das aber bei LabView die Ausnahme dar. Das zeigt sich auch in einer Reihe von Problemen mit Variablen, angefangen von der Sichtbarkeit bis dahin, dass unklar, ist, wann genau ein Wert geschrieben wird.
Darüber hinaus fehlen einige wichtige Objekte, die im Original-LabView existieren, z.B. Felder oder dynamisch allozierbare Speicherbereiche. Das macht die Entwicklung komplexer Anwendungen schwierig bis unmöglich. Einiges von dem, was ich vor hatte, konnte definitiv nicht mit diesen Mitteln entwickelt werden. So hatte ich ursprünglich vor, dass der Roboter seine Umgebung mit den Sensoren erkundet und eine eigene Karte aufbaut. Das lässt sich mit dem Datenflussparadigma und der vorhanden Laufzeitumgebung nicht realisieren. Als "Krücke" schreibt der Roboter alle Sensordaten in eine Log-Datei, die dann Offline ausgewertet werden kann.
Damit sich die Komplexität eines Programms mit vielen Funktionen auch im Datenflussmodell kontrollieren lässt, bietet sich die Modularisierung mit eigenen Blöcken an. Diese lassen sich mit Unterprogrammen aus der imperativen Programmierung vergleichen. Hier die resultierende Blöcke:

Johnny 5 Software Blocks

Damit handelte ich mir allerdings ein Problem ein: Wie verwaltet man übergeordnete Statusinformationen? Als Beispiel: die Funktion Look_right sollte den Kopf auf 45 Grad nach rechts drehen, egal, wo sich der Kopf gerade befindet. Wenn also der Kopf schon rechts ist, sollte nichts passieren. Dazu sollte die aktuelle Kopfposition in einer Statusvariablen gespeichert werden. Nach einigem Probieren ergab sich folgende Vorgehensweise zur Verwaltung globaler Zustände:
  • Man legt im Hauptprogramm eine Variable mit einem Namen an.
  • Man definiert im eigenen Block die Variable mit demselben Namen.
  • Ist der Name exakt gleich, so verwendet die Laufzeitumgebung dieselbe Speicherzelle. Man erhält damit eine Möglichkeit, zwischen Blöcken Informationen auszutauschen, ohne dass eine Datenleitung existieren muss.
Diese Vorgehensweise enthält aber einen Fallstrick: per Cut-and-Copy kann man beispielsweise ein Variablenobjekt in einen Block kopieren. Wird die Variable aber nicht explizit angelegt, so verwendet LabView innerhalb des Blocks eine andere Variable, auch wenn der Name gleich ist. Es gibt keine Warnung, keinen Fehler – das Programm läuft ganz normal, verwendet eben nur zwei verschiedene Speicherzellen. Also:
  • im Hauptprogramm eine Variable anlegen
  • dann im Block dieselbe Variable anlegen
  • dann im Block diese Variable verwenden.
Diese Reihenfolge ist also wichtig.
Es bietet sich übrigens unbedingt an, die so genannten Mini Blocks zu verwenden. Auf der NXT-Seite werden kleine Varianten verschiedener Blöcke angeboten, die offensichtlich wesentlich besser programmiert wurden, daher wesentlich weniger von dem kostbaren Speicher im NXT-Baustein belegen. (Nebenbei: auch das ist mir nicht klar: wieso hat der Baustein so erschreckend wenig Speicher.) Durch den Austausch von Standardblocks durch Mini-Blocks konnte ein Beispielprogramm 11.2 kB auf sagenhafte 6.8 kB verkleinert werden. Außerdem sind die neuen Motor-Miniblocks wesentlich präziser. Insbesondere die Einstellung "Control->Motor Power" (d.h. Erhöhung der Stärke bei Widerstand) ist sehr angenehm.

An dieser Stelle möchte ich noch einige weitere Probleme darstellen, die ich mit der LabView-Umgebung (Version 1.0 mit Mini-Block-Erweiterung) hatte:
  • Ich konnte Bluetooth nicht zum Laufen bringen. Der Baustein ließ sich nicht mit meiner PC-Umgebung paaren, die ansonsten aber mit allen anderen Geräten außer dem NXT zusammenarbeitet.
  • Instabilität des LabView-Editors: Dieser stürze hin und wieder ohne Grund ab (Windows Fehler). Der Fehler ließ sich nicht ausmachen hing aber mit bestimmen Blöcken zusammen. Daher habe ich teilweise komplette Blöcke in derselben Weise neu erstellen müssen.
  • Es gab einen selbsterstellten Block, der immer einen Absturz verursachte, wollte ich ihn in mein Programm einfügen. Selbst durch Neuerstellung des Blocks konnte das Problem nicht behoben werden. Als Resultat habe ich die Funktionalität hinter dem Block von Hand an jede entsprechende Stelle des Programms kopiert, was nicht gerade der Sinn von Blöcken ist.
  • Wenn man einen Programmier-Fehler gemacht hat, kommt als Fehlermeldung nur ein allgemeiner Text, aus dem man nicht auf den verursachenden Block schließen kann. Die Suche nach dem Fehler gestaltet sich damit enorm schwierig. Die häufigsten Fehler entstehen übrigens dadurch, dass man Verdrahtungsendpunkte nicht exakt trifft und somit ein "loses Ende" produziert. Zusätzlich kann es passieren, dass man einen Block nicht auf den gewünschten Thread fallenlässt. Er wird dann nicht ausgeführt.
  • Der Editor macht bei Schleifen oder Verzweigungen oft sinnlose Layouts, Es entstehen manchmal leere Fläche oder, was viel schlimmer ist, die Blöcke werden soweit verkleinert dargestellt, dass man sie nicht mehr editieren kann. Leider hat der Entwickler keine explizite Kontrolle über das Layout von Schleifen oder Verzweigungen.

Die Mechanik

Eine große Änderung mit dem NXT-Bausatz gegenüber dem Vorgänger war, dass die alten Legosteine (die mit den Noppen) im Wesentlichen verbannt wurden. Alles basiert auf den Lego technics Teilen. Damit werden NXT-Robots vor allem durch die Lochstangen aufgebaut – geschlossene Bauteile sind damit nicht mehr möglich. Erstaunlicherweise bekommt man sehr viel mit diesen Lochstangen hin. Manchmal sehnt man sich jedoch nach den alten Steinen zurück...
Verwendet man beide Arten von Teilen, muss man zwischen zwei Welten vermitteln. Glücklicherweise gibt es eine Reihe von Bausteinen, die in beiden Welten zuhause sind. So passen die Noppen exakt in die Löcher der Lochstangen; die Achsen können durch die Achsenbausteine und die Lochstangen gezogen werden; usw. So war dann der kombinierte Aufbau kein großes Problem. Der massive Unterbau von Johnny 5 (der zwischen den Laufwerken unter dem NXT-Stein) wäre ohne die Noppensteine in dieser Stabilität nicht möglich gewesen.
Wie schon erwähnt, wurden die alten Steine auch wegen der Kettenelemente benötigt. Auch eine Reihe von alten Zahnrädern musste daher aus der Krabbelkiste hervorgeholt werden, da die neuen Zahnräder sehr viel feinere Zahnabstände haben und nicht mehr zu den groben Kettenelementen passten.
Die beiden Laufwerke waren aus rein mechanischer Sicht die Achillesfersen des Modells. Wie oben schon erwähnt war ihr Aufbau nicht einfach, so dass zwei Varianten ausprobiert wurden:

Johnny 5

Die erste Version des Kettenantriebs
(ohne zusätzliches bodenführendes Zahnrad)

Johnny 5

Der Kettenantrieb
(endgültige Version)

Johnny 5

Der Kettenantrieb von vorne

Johnny 5

Das Hinterrad

Die erste Variante hatte eine flach aufliegende Kette. Wie schon oben erwähnt, macht das Probleme beim Drehen auf der Stelle, da sich dann das ganze Bauteil der Drehung widersetzt. Als Lösung wurde der Anteil der Kette, der auf dem Boden flach aufliegt durch ein weiteres Zahnrad verkürzt. Als ein weiterer Mechanismus fährt Johnny 5 nach jeweils 45 Grad Drehung auf der Stelle kurz vor und zurück, damit sich die Laufwerke "entspannen", d.h. wieder in eine gerade Position zurück gehen. Das führte zur gewünschten Wendigkeit. Für ein Modell, das präzise Fahrmanöver ausführen soll, hat sich der Kettenantrieb allerdings als ungeeignet herausgestellt. Hier bieten sich Laufwerke mit den einfachen Reifen eher an.