Technische Dokumentation Roboter
Inhaltsverzeichnis 1 EINLEITUNG... 3 2 DIE ROBOTER LOGIK... 3 3 SCHNITTSTELLE AUF DER SIMULATION...3 3.1 ROBOTFACTORY...3 3.2 MAP::ROBOT... 3 4 SCHNITTSTELLE ZUM RCX... 4 4.1 ÜBER LEJOS...4 4.2 LEJOSRUNTIME... 4 4.3 LIGHTSENSORLISTENER... 4 5 DIE EINZELNEN WESEN... 5 5.1 WESEN 1: STREUNEN...5 5.2 WESEN 2A: FURCHT... 5 5.3 WESEN 2B: AGRESSION...5 5.4 WESEN 3A/B: LIEBE... 6 5.5 WESEN 4A: GESCHMACK...7 5.6 WESEN 4B: WERTUNG...8 5.7 WEITERE WESEN AUS BRAITENBERG...8 6 VERHALTEN DER WESEN IN DER REALITÄT... 9 6.1 LICHTSENSOREN...9 6.2 MOTOREN... 9 7.1 VORAUSSETZUNGEN... 10 7.2 SOURCE CODE ANPASSEN... 10 7.3 SOURCE CODE MIT LEJOS KOMPILIEREN, LINKEN UND ÜBERTRAGEN...10 31.08.2005 Seite 2/11
1 Einleitung Zentrale Anforderung an das Projekt war die Implementation unterschiedlichsten Roboter Logiken. Der Source Code für diese Programme müsse sowohl in der Simulation wie auch auf dem RCX Roboter lauffähig sein. 2 Die Roboter Logik Die Logik, welche den Roboter auf die Sensor Werte reagieren lässt und die Motoren steuert, musste unabhängig von der Simulation oder vom RCX programmiert werden. So kann sichergestellt werden, das die Logik universell einsetzbar ist. «interface» Robot::IRobot ~ GetMotorSensor(int) : int[] Eine Roboterlogik muss das Interface IRobot implementieren, welches folgende Methode vorschreibt: int[] GetMotorSensor( int[] sensorvalues ) Als Parameter wird ein Array mit den von den Sensoren erhaltenen Werten übergeben. Auf Basis dieser Angaben kann die Logik beschliessen, mit welcher Geschwindigkeit die Motoren angesteuert werden sollen. Die neuen Werte für die Motoren werden wiederum als int Array zurückgegeben. Da dieser Programmteil auch auf dem RCX laufen soll, muss der Speicherverbrauch minimal gehalten werden. Primär muss vermieden werden, unnötige Objekte zu instanzieren oder ein Array immer neu zu definieren. 3 Schnittstelle auf der Simulation In die Simulation können mehrere Roboter geladen werden, welche von der oben erwähnten Logik gesteuert werden. Object3D Map::Robot Robot:: RobotFactory 3.1 RobotFactory Die einzelnen Dateien mit der kompilierten Roboterlogik liegen als.class Datei in einem bestimmten Verzeichniss. Dieses kann über die Datei Setting.ini festgelegt werden. Mit der Methode GetRobots werden alle verfügbaren Roboter zurückgegeben und mit GetRobot eine Instanz einer konkreter Logik erzeugt. #robot «interface» Robot::IRobot 3.2 Map::Robot Stellt ein Roboter auf der Karte dar. In dieses Objekt kann eine beliebige Logik geladen werden, welche danach das Verhalten in der Simulation bestimmt. Die Simulation berechnet bei jedem Zeitabschnitt die Werte der Sensoren. Diese werden über das Map Objekt an die Logik übergeben. Die dort errechneten Motorgeschwindigkeiten auswertet und entsprechend die Position des Roboters auf der Karte verändert. 31.08.2005 Seite 3/11
4 Schnittstelle zum RCX 4.1 Über Lejos Lejos ist ein Betriebssystem für den Lego Mindstorms RCX Baustein. Damit ist es möglich, Java Programme auf dem Lego Controller auszuführen. Mit Lejos wird ein Framework mitgeliefert, welches die Interaktion mit der Lego Hardware ermöglicht. Damit können die Werte der Sensoren gelesen und die Motoren angesteuert werden. LejosRuntime SensorListener LightSensorListener robot «interface» Robot::IRobot Mit einem speziellen Lejos Compiler und zugehörigem Linker werden Binary erstellt, die auf dem RCX lauffähig sind. Obwohl fast alle Java Funktionen zur Verfügung stehen, gibt es auf dem Lego Roboter eine gewichtige Einschränkung: Der geringe Speicher. Um entsprechende Probleme zu vermeiden, sollte man in den Methoden möglichst wenige Variablen definieren und statt dessen auf Objekt Variablen zugreifen. Ansonsten wird der Lego Roboter recht schnell mit einer MemoryException abstürzten. 4.2 LejosRuntime Diese Klasse enthält die Main() Methode, welche beim Starten des RCX aufgerufen wird. Dort werden die Sensoren initialisiert und die LightSensorListener für die beiden Lichtsensoren erstellt. 4.3 LightSensorListener Bei jeder Veränderung der Sensor Werte wird in der Klasse LightSensorListener die Methode statechanged aufgerufen. Wenn dies geschieht, werden die Werte an die Roboterlogik übergeben und die berechneten Motorgeschwindigkeiten an die entsprechenden Lego Antriebe übergeben. 31.08.2005 Seite 4/11
5 Die einzelnen Wesen Teil der Aufgabe war die Implementieren der im Buch Künstliche Wesen 1 von Valentin Braitenberg beschriebenen Wesen. Soweit dies möglich war wurden diese Wesen in der von uns definierten Logik umgesetzt. Damit kann deren Verhalten sowohl in der Simulation wie auch direkt auf dem Lego Roboter beobachtet werden. 5.1 Wesen 1: Streunen Hier wird der Wert eines Sensors auf alle Motoren übertragen. Das bedeutet, der Roboter fährt immer gerade aus; je näher am Licht desto schneller. Robots:: Wesen1Streunen motorvalues[0] = sensorvalues[0]; motorvalues[1] = sensorvalues[0]; motorvalues[2] = sensorvalues[0]; 5.2 Wesen 2a: Furcht Robots:: Wesen2aFurcht Bei diesem Wesen werden die Werte des linken Sensors direkt an den linken Motor weitergegeben. Das gleiche passiert mit dem rechten Sensor, welcher die Werte an den rechten Motor weiter gibt. Wenn nun der rechte Sensor mehr Licht wahrnimmt, dann dreht der rechte Motor entsprechend schneller. Die folge ist, das der Roboter nach links abdreht und sich vom Licht entfernt. Dieses Verhalten kann als Furcht interpretiert werden. motorvalues[0] = sensorvalues[0]; motorvalues[1] = sensorvalues[1]; 5.3 Wesen 2b: Agression Dieses Wesen funktioniert im Prinzip identisch wie das letzte Wesen Furcht, nur das die Werte der Sensoren an den jeweils gegenüber liegenden Motor gesendet werden. Wenn nun der Sensor auf der linken Seite mehr Licht wahrnimmt, läuft der rechte Motor schneller. Hier dreht der Roboter also zum Licht, bis er es überfährt. Hier legt der Motor also ein aggressives Verhalten an den Tag Robots:: Wesen2bAgression motorvalues[0] = sensorvalues[1]; motorvalues[1] = sensorvalues[0]; 1 http://j airs.sourceforge.net/download/braitenberg.pdf 31.08.2005 Seite 5/11
5.4 Wesen 3a/b: Liebe In den beiden Wesen Liebe sind die Sensoren identisch mit dem Motoren verbunden wie beim Wesen 2. Der Unterschied ist der, das sich hier die Motoren verlangsamen, je höher der Lichtwert ist. Umgekehrt werden sie schneller, je dunkler die Umgebung wird. Beim Wesen 3a werden die Sensoren wieder direkt zum Motor auf der jeweiligen Seite gekoppelt. Die Folge ist, dass der Roboter direkt auf die Lichtquelle zusteuert. Je näher er ihr kommt, desto langsamer wird er bis er schliesslich unmittelbar davor stehen bleibt. Bei der Variante 3b sind die Sensoren wieder gekreuzt mit den Motoren verbunden. Das Wesen wird damit zwar nahe an das Licht heran fahren, sich dann aber wieder abwenden und auf die Suche nach einer anderen, evtl. stärkeren Quelle gehen. Das heisst, beide Wesen haben zwar gerne Licht, während das erste aber in endloser Liebe davor stehen bleibt, macht sich das Zweite auf die Suche nach etwas anderem. motorvalues[0] = sensorvalues[1]; motorvalues[1] = sensorvalues[0]; // Wie Wert umkehren motorvalues[0] = maxsensorvalue - motorvalues[0]; motorvalues[1] = maxsensorvalue - motorvalues[1]; Robots:: Wesen3aLiebe Robots:: Wesen3bLiebe 31.08.2005 Seite 6/11
5.5 Wesen 4a: Geschmack Die Wesen, die wir bis jetzt gesehen haben, wurden stets durch eine lineare Abhängigkeit zwischen den Sensor Werten und dem Motor beschrieben. In diesem Wesen lassen wir die Motoren wie bei Wesen 2a mit zunehmender Lichtintensität schneller laufen. Allerdings nur bis zu einem bestimmten Grenzwert, ab da werden sie wieder langsamer. Je nach Grenzwert und Anfahrtsweg auf die Lichtquelle können sich verschiedene Kurven ergeben: // Wir brauchen in diesem Beispiel nur einen Sensor. if (sensorvalues == null sensorvalues.length < 2) // Der Wert des Sensors wird linear umgerechnet motorvalues[0] = sensorvalues[1]; motorvalues[1] = sensorvalues[0]; // Wie Wert umkehren if (motorvalues[0] > grenzwert) motorvalues[0] = grenzwert - (motorvalues[0] - grenzwert); if (motorvalues[1] > grenzwert) motorvalues[1] = grenzwert - (motorvalues[1] - grenzwert); // Die Motorwerte sollte aber nicht negativ werden... if (motorvalues[0] < 0) motorvalues[0] = 0; if (motorvalues[1] < 0) motorvalues[1] = 0; // Alle Motoren sollen mit der gleichen Geschwindigkeit fahren 31.08.2005 Seite 7/11
5.6 Wesen 4b: Wertung Wesen 4b ändert sein Verhalten im Gegensatz zu 4a Sprunghaft. Zum Beispiel bewegen sich die Motoren erst, wenn ein gewisser Start Wert erreicht wurde und hören bereits bei einem bestimmten Grenzwert wieder auf. In unserem Wesen haben wir die Variante implementiert, welche erst ab einer gewissen Sensor Stärke reagiert: // Wir brauchen in diesem Beispiel nur einen Sensor. if (sensorvalues == null sensorvalues.length < 2) // Der Wert des Sensors wird linear umgerechnet, mit // einem bestimmten Grenzwert motorvalues[0] = sensorvalues[1] - grenzwert; motorvalues[1] = sensorvalues[0] - grenzwert; // Die Motorwerte sollte aber nicht negativ werden... if (motorvalues[0] < 0) motorvalues[0] = 0; if (motorvalues[1] < 0) motorvalues[1] = 0; // Alle Motoren sollen mit der gleichen Geschwindigkeit fahren 5.7 Weitere Wesen aus Braitenberg Valentin Braitenberg erwähnt in seinem Buch noch mehrere weitere Wesen, welche gegenüber den bereits erwähnten nicht minder interessant sind. Leider benötigen diese mehr Lichtsensoren als die zwei von uns zur Verfügung gestellten. Zudem kommen sofort weitere Wahrnehmungen dazu, wie zum Beispiel Farbe oder auch Gerüche, welche weder der Lego Roboter noch die Simulation ohne weiteres interpretieren kann. Aus diesen Gründen haben wir nur die in diesem Dokument erwähnten Wesen implementiert. 31.08.2005 Seite 8/11
6 Verhalten der Wesen in der Realität Das Ziel der Projektes war, die erstellten Wesen sowohl in der Simulation wie auch in der Realität auf einem Lego Roboter laufen zu lassen. Während letzteres technisch zwar kein Problem war, stellten sich die Resultate aber als im höchsten Grade ernüchternd heraus. Der Hemmfuss war die unzulängliche Hardware auf dem Lego Roboter, welche in diverser Hinsicht zu ungenau war. 6.1 Lichtsensoren Die Lichtsensoren lieferten zu ungenaue Resultate, um diese im Sinne der Aufgabe verwerten zu können. Primär wurden diese Lego Sensoren entworfen, um eine Weisse Linie auf schwarzem Grund zu erkennen. Bei der Lokalisierung eines mit der Taschenlampe geworfenen Lichtkegels scheiterte sie jedoch kläglich. Eine Reaktion war erst erkennbar, wenn die Taschenlampe direkt in die Sensoren gehalten wurde. 6.2 Motoren Die Lejos API kann einen Lego Motor zwar mit sieben verschiedenen Geschwindigkeiten ansprechen, was aber in der Realität keinen Unterschied zeigte. Tatsächlich lässt sich der Motor nur binär ansprechen; entweder läuft er oder dann eben nicht. Da aber sämtliche Wesen auf eine feine Abstufung der Geschwindigkeit angewiesen sind, war eine Adaption auf den Lego Roboter von Anfang an zum Scheitern verurteilt. Weiter mussten wir feststellten, das zwei Motoren mit Identischer Listung nicht mit der gleichen Gewindigkeit laufen. So fuhr der Roboter mit der Logik des Wesens 1 nach kurzer Zeit eine deutliche Kurve, obwohl dieses Wesen beide Motore gleich ansteuert und somit nur geradeaus fahren kann. 31.08.2005 Seite 9/11
7 Anleitungen: Wesen auf dem RCX In diesem Kapitel wird beschrieben, wie ein bestimmtes Wesen auf dem RCX ausgeführt werden kann. 7.1 Voraussetzungen Folgende Anforderungen müssen erfüllte sein, damit die nachfolgende Anleitung reibungslos funktioniert: Der Source Code vom J Airs Projekt muss vorhanden sein Die Lejos Umgebung muss installiert und konfiguriert sein. Der Lego Tower für die Übermittlung des Programmes an den RCX muss angeschlossen und konfiguriert sein Auf dem Lego Roboter müssen zwei Lichtsensoren und zwei Motoren an den jeweils zwei ersten Steckplätzen angeschlossen sein. 7.2 Source Code anpassen In der Java Datei LejosRuntime im Package ch.jairs.lejosruntime muss die Logik definiert werden, welche auf den RCX übertragen werden soll. Die erste Zeile der Methode Main() muss wie folgt angepasst werden: // Roboter-Logik erstellen <RoboterName> robot = new <RoboterName>(); wobei <RoboterName> durch den Name der zu ladenden Logik ersetzt werden muss, also zum Beispiel: // Roboter-Logik erstellen Wesen2bAgression robot = new Wesen2bAgression(); 7.3 Source Code mit Lejos kompilieren, linken und übertragen Im Verzeichniss, welches die Datei LejosRuntime.java enthält, muss folgender Befehl ausgeführt werden um den Source zu kompilieren: lejosc../robot/irobot.java../robots/wesen2bagression.java LightSensorListener.java LejosRuntime.java Wir wechseln nun in Root Verzeichniss des J Airs Projektes und geben dort folgenden Befehl ein lejoslink.bat -o ch\jairs\lejosruntime\lejosruntime.bin ch.jairs.lejosruntime.lejosruntime Damit werden die benötigten Dateien gelinkt und es wird ein entsprechendes Binary erstellt, welches den auf dem RCX lauffähigen Code enthält. Abschliessend können wir mit folgendem Befehl die erstellt Datei auf den Lego Roboter übertragen: 31.08.2005 Seite 10/11
lejosdl.bat LejosRuntime.bin 31.08.2005 Seite 11/11