universit - institut für informatikfsjaetzo/archive/art.pdf · hester institute of t ec hnology,...

151

Upload: vuthuy

Post on 25-Mar-2018

214 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

UNIVERSIT�AT OSNABR�UCK

Fachbereich Mathematik/Informatik

Diplomstudiengang Mathematik, Vertiefungsfach Informatik

Diplomarbeit

Objekte, Threads und Events

f�ur Roboter{ Ein Toolkit zur hardware-unabh�angigen Robotersteuerung in Java {

Betreuer: Verfasser:

Prof. Dr. AXEL T. SCHREINER STEPHAN J�ATZOLD

Vorgelegt im Februar 2002

Page 2: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en
Page 3: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

iii

Danksagungen

Ich danke Herrn Prof. Dr. Axel-Tobias Schreiner f�ur seine Unterst�utzung und

die Betreung dieser Diplomarbeit. Seine Bereitschaft neue Inhalte und Ideen in

die Lehre an der Universit�at zu bringen ist bemerkenswert.

F�ur die �nanzielle Unterst�utzung bei zwei Forschungsaufenthalten in den

USA, am Rochester Institute of Technology, im Zusammenhang mit dieser Ar-

beit, bin ich der Universit�atsgesellschaft Osnabr�uck und dem Fachbereich Ma-

thematik/Informatik der Universit�at Osnabr�uck zu Dank verp ichtet.

Ganz besonderer Dank gilt meinen Eltern, die mir f�ur meine Ausbildung

jede m�ogliche Freiheit lassen und dabei gro�e Geduld beweisen. Ich ho�e ich

kann ihnen vermitteln, da� es sich lohnt.

F�ur die Durchsicht des Textes und inhaltliche Diskussionen danke ich Bernd

K�uhl, Eva Ebenh�oh und Helga J�atzold.

Eva Ebenh�oh danke ich f�ur ihre Geduld und ihre Unterst�utzung, sie versteht

mich wie sonst niemand.

Hilfsmittel

F�ur die Erstellung dieser Arbeit wurden die folgenden Programme verwendet:

nedit zum editieren der Texte

LATEX in Verbindung mit einer Menge Erweiterungen zum Setzen dieser Arbeit

x�g zur Erstellung der Gra�ken

linux und viele der dort �ublicherweise installierten Tools wie make, convert

usw.

jikes als haupts�achlich verwendeter Java-Compiler

� verschiedene Java Development Kits zur Java-Entwicklung

� verschiedene Programme und Ger�ate zur Erstellung und Bearbeitung der

Fotos

Erkl�arung

Hiermit erkl�are ich, diese Diplomarbeit selbst�andig verfasst und keine anderen

als die angegebenen Quellen und Hilfsmittel verwendet zu haben.

Stephan J�atzold

Page 4: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

iv

Page 5: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

Inhaltsverzeichnis

1 Einleitung 1

1.1 Vorgeschichte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Begri�skl�arungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.3 Zielgruppe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.4 Inhalts�ubersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Ariadne { a Li(ght)Se(arching) Trusty 7

2.1 Trusty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.2 LiSe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.3 Ariadne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.4 Hervorzuhebende Eigenschaften . . . . . . . . . . . . . . . . . . . 9

3 Programmiersysteme f�ur Roboter 13

3.1 Gra�sche Programmiersysteme . . . . . . . . . . . . . . . . . . . 13

3.1.1 LLWin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3.1.2 RCX-Code . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.1.3 Robolab . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.2 Textbasierte Programmiersysteme . . . . . . . . . . . . . . . . . 22

3.2.1 Fernsteuerungen . . . . . . . . . . . . . . . . . . . . . . . 22

3.2.2 Sprachen f�ur die Lego-Firmware . . . . . . . . . . . . . . 24

3.2.3 Systeme mit eigener Firmware . . . . . . . . . . . . . . . 25

3.2.4 leJOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3.3 Vorl�au�ges Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4 Die Idee des Abstract Robot Toolkit 35

4.1 Tutebot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.2 Fischertechnik und Lego Mindstorms . . . . . . . . . . . . . . . . 39

4.3 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4.4 Design-Pattern und das AWT . . . . . . . . . . . . . . . . . . . . 41

4.5 Das Abstract Robot Toolkit . . . . . . . . . . . . . . . . . . . . . 43

4.6 Die Sensor-Implementierungen in ART . . . . . . . . . . . . . . 50

4.7 Model, View, Controller . . . . . . . . . . . . . . . . . . . . . . . 56

4.8 Subsumption-Architektur . . . . . . . . . . . . . . . . . . . . . . 57

v

Page 6: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

vi INHALTSVERZEICHNIS

5 Ariadne & ART - Ein Tutorial 59

5.1 "Hello, Robot!" . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

5.2 DriveTrain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

5.3 Und wie benutzt man das nun? . . . . . . . . . . . . . . . . . . . 73

5.4 Trusty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

5.5 Kon�gurierte Sensoren . . . . . . . . . . . . . . . . . . . . . . . . 86

5.5.1 SubsumptionTrustyMSDemoRobot . . . . . . . . . . . . . . 86

5.5.2 Der Lego-Rotationssensor . . . . . . . . . . . . . . . . . . 89

5.5.3 Rotationsmessung mit den Fischertechnik-Impulsr�adern . 91

5.6 LiSe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

5.7 Ariadne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

6 Implementierung eines RobotInterface 107

6.1 Ein virtuelles RobotInterface . . . . . . . . . . . . . . . . . . . 107

6.2 Die Peers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

6.3 Die Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

6.4 Die Methoden von RobotInterface . . . . . . . . . . . . . . . . 117

6.5 Die Einbindung in ART: RobotInterfaceFactory . . . . . . . . 120

7 Zusammenfassung 125

7.1 Ergebnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7.2 Geschwindigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7.3 Flexibilit�at . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

7.4 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

7.5 Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

7.6 Andere Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7.7 Subsumption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7.8 JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

7.9 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

7.10 Persistenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

A Installation des Abstract Robot Toolkit 135

A.1 Installation der Beispiele . . . . . . . . . . . . . . . . . . . . . . . 136

A.2 Klassendokumentation . . . . . . . . . . . . . . . . . . . . . . . . 137

B Troubleshooting 139

B.1 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

B.2 Geschwindigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

B.3 Automatische Erkennung . . . . . . . . . . . . . . . . . . . . . . 140

Abbildungsverzeichnis 141

Literaturverzeichnis 143

Page 7: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

1

Einleitung

Moderne Programmiersprachen, wie z.B. Java, stellen inzwischen f�ur viele Be-

reiche ein recht weit entwickeltes API (Application Program Interface) zur

Verf�ugung. F�ur die Programmierung von Robotern scheint es aber bisher zu-

mindest kein frei verf�ugbares API zu geben, das einen objektorientierten, von

der konkreten Hardware abstrahierenden Zugang zu Robotern bereitstellt. F�ur

die Ansteuerung von Robotern aus Java heraus ist man in vielen F�allen auf die

Besch�aftigung mit wenig intuitiven Byte-Str�omen angewiesen.

Die vorliegende Arbeit will diese L�ucke f�ullen. Es wird eine Schnittstelle ent-

wickelt, die eine objektorientierte und event-basierte Sicht auf die Komponenten

eines Roboters erm�oglicht. Unter Verwendung dieser Schnittstelle kann man Al-

gorithmen zur Robotersteuerung entwickeln, die weitgehend wiederverwendbar

sind { nicht nur f�ur den gleichen Roboter, sondern f�ur verschiedene Roboter,

von m�oglicherweise sogar unterschiedlicher Hardware-Architektur. Wo immer es

m�oglich ist, werden die gleichen Klassen f�ur unterschiedliche Roboter-Hardware

verwendet, womit eine weitgehende Unabh�angigkeit von der verwendeten Platt-

form erreicht wird.

Implementiert wurde diese Schnittstelle exemplarisch f�ur Roboter-Hardware

von Lego und Fischertechnik; ein Beispiel f�ur eine Implementierung f�ur weitere

Plattformen wird gegeben.

1.1 Vorgeschichte

Lego Mindstorms kam Ende 1998 in den USA auf den Markt und ein Jahr sp�ater

auch in Deutschland. Seitdem hat sich eine gro�e Fan-Gemeinde entwickelt und

im Internet organisiert. Die von Lego zur Verf�ugung gestellten M�oglichkeiten

zur Programmierung des Brick, wie der gro�e gelbe Legostein mit Batterien

und einem Computer darin h�au�g genannt wird1, waren damals die gra�sche

Programmierumgebung RCX-Code und das ActiveX-Control Spirit.ocx.

1In diesem Dokument soll mit Brick die Hardware des Computer-Bausteins im Lego Mind-

storms Robotics-Invention-System (RIS) bezeichnet werden. Der Begri� RCX (so wird der

Brick auch manchmal genannt) soll hier hingegen die Original-Firmware, das von Lego aus-

gelieferte Betriebssystem des Brick bezeichnen. Es existieren verschiedene RCX-Versionen f�ur

den Brick und weitere Lego-Produkte wie den Cybermaster und den Scout.

1

Page 8: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

2 1. EINLEITUNG

Beide Systeme laufen auch heute nur unter Windows und vor allem RCX-

Code ist au�erdem f�ur Menschen ohne Programmiererfahrung konzipiert wor-

den, aber: Der Brick kann sein Betriebssystem �uber Infrarot laden, es ist nicht

auf dem Chip eingebrannt. Vielleicht war es aber auch schlicht der Drang, wis-

sen zu wollen, wie "Es" funktioniert, auf jeden Fall knackte Kekoa Proudfoot

(Proudfoot, 1998) noch im selben Jahr den Brick (im wahrsten Sinne des Wor-

tes) und Dave Baum entwickelte NQC (Baum, 2001), eine alternative Program-

miersprache zur Programmierung von RCX, dem Betriebssystem des Brick.�Uber das Internet wurden und werden die Erkenntnisse und die Arbeiten

einer immer gr�o�er werdenden Gruppe von Enthusiasten zug�anglich gemacht,

so da� gute eineinhalb Jahre sp�ater, im Fr�uhjahr 2000, der Brick in vielen

Sprachen, darunter C, C++, Forth und Java, programmiert werden kann. Ei-

nige dieser Systeme setzen daf�ur nicht auf der Standard-Firmware auf, sondern

beinhalten gleich ein eigenes Betriebssystem f�ur den Brick, welches die M�oglich-

keiten, z.B. zur Ansteuerung des integrierten LCD betr�achtlich erweitert.

Inzwischen hat auch Lego das Betriebssystem erweitert und die textbasierte

Programmiersprache Mindscript entwickelt, sowie die Bytecodes des RCX unter

dem Namen Lego-Assembler ver�o�entlicht.

Doch Konstruktionsbauk�asten mit Computern zu verbinden ist eine Idee, die

f�ur Fischertechnik bereits 1984 in ein Produkt umgesetzt wurde. Das Universal-

Interface kann an die parallele Schnittstelle eines IBM-PC, Commodore C64

oder Atari ST angeschlossen werden. Das Interface hat keinen eigenen Mikro-

controller, sondern vermittelt im Wesentlichen nur zwischen den elektrischen

Signalen des angeschlossenen Computers und den an das Interface angeschlosse-

nen Motoren und Sensoren. Erst das 1997 herausgebrachte Intelligent-Interface

kann auf der Basis der Windows-Software LLWin entwickelte Programme auch

autonom ausf�uhren. LLWin ist ein gra�sches Programmiersystem, das an das

industriell verwendete iCon-L der Firma Pro-Sign Process Design GmbH ange-

lehnt ist.

Bereits von Anfang an lag dem Universal-Interface eine gedruckte Doku-

mentation bei, welche die Signale an der parallelen Schnittstelle beschreibt, die

zur Ansteuerung des Interface n�otig sind. Au�erdem verf�ugt das Interface �uber

mehr Ein- und Ausg�ange als der Brick. Trotzdem ist die Fan-Gemeinde und die

frei verf�ugbare Software f�ur die Fischertechnik-Interfaces wesentlich weniger

weit entwickelt, als das bei Lego Mindstorms der Fall ist. F�ur das Intelligent-

Interface, welches eine serielle Schnittstelle hat, ist von Fischertechnik ein Kom-

munikationsprotokoll ver�o�entlicht worden, mit welchem die gleichen M�oglich-

keiten wie mit dem Universal-Interface er�o�net werden. Die F�ahigkeit, Pro-

gramme auf das Interface zu laden und dort dann lokal, vom PC getrennt

ausf�uhren zu lassen, bleibt leider der Fischertechnik-Software LLWin vorbe-

halten. Es scheint keine Quelle zu geben, die diesen Vorgang dokumentiert und

eine Analyse der Daten die von LLWin an das Interface gesendet werden ist

nicht so einfach, da die Datenmenge bereits bei den einfachsten Programmen

recht gro� ist.

Page 9: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

1.2. BEGRIFFSKL�ARUNGEN 3

1.2 Begri�skl�arungen

Die meisten der betrachteten Programmiersysteme f�ur Roboter bieten Program-

mierern nur sehr eingeschr�ankte M�oglichkeiten zur Anwendung �ublicher Tech-

niken und Paradigmen in der Softwareentwicklung. Im Folgenden wird auf ein

paar Aspekte eingegangen, die in dieser Arbeit immer wieder zur Bewertung

der einzelnen Programmiersysteme herangezogen werden.

Wiederverwendung von Code: Damit ist der Umstand gemeint, da�

ein Programm, oder Teile davon, in einem neuen Programm erneut verwendet

werden. Eine Form von Wiederverwendung ist das Kopieren (von Teilen) eines

Quelltextes, entweder durch "Cut&Paste" oder durch blo�es Abschreiben aus

Beispielprogrammen. Diese Vorgehensweise kann zum Lernen von neuen Tech-

niken durchaus als geeignet angesehen werden. Zum Aufbau einer Bibliothek

von h�au�g benutzten Bausteinen gibt es aber besseres. Solche Sofwarebausteine

k�onnen heute �ublicherweise Funktionen oder Objekte sein. Sind diese Bausteine

fertig, getestet und gen�ugend abstrakt, bzw. modular gehalten (sowie nat�urlich

deren Funktionsweise hinreichend bekannt), mu� nur noch der Code geschrieben

werden, der diese miteinander verbindet, und sie k�onnen somit eine erhebliche

Arbeitserleichterung darstellen.

Threads: Unter Threads versteht man den aus logischer Sicht gleichzeiti-

gen Ablauf verschiedener Programmteile nebeneinander. Ein Scheduler verteilt

diese Abl�aufe auf die verf�ugbaren Prozessoren. Preemptive Scheduling liegt vor,

wenn der Scheduler zu beliebiger Zeit einen Thread zugunsten eines anderen

vor�ubergehend stilllegen kann.

Interrupts vs. Polling: Wenn Software auf Zustands�anderungen in der

Hardware reagieren soll, stehen im Wesentlichen zwei Techniken zur Verf�ugung:

Interrupts und Polling. Polling bedeutet, da� der Zustand von der Seite der

Software aus st�andig aktiv �uberpr�uft wird. Umgekehrt wird bei Interrupts die

Software erst dann aktiv, wenn eine �Anderung eingetreten ist. Die �Anderung

wird in diesem Fall von der Hardware �uber den Interrupt signalisiert. Wenn

man Polling verwenden mu�, weil die Hardware keine (geeigneten) Interrupts

zur Verf�ugung stellt, ist es mit Threads m�oglich, die ben�otigten Interrupts in

der Software zu simulieren. So programmiert man oberhalb dieser Simulation,

als w�aren Interrupts in der Hardware vorhanden. Zudem ist es mit mehreren

Threads m�oglich, die Notwendigkeit des Polling vollends zu kapseln, also in

einem Modul zu verstecken. Ein Modul besitzt mit Threads die M�oglichkeit,

v�ollig unabh�angig von anderen Modulen aktiv zu werden. Ohne Threads w�are

es notwendig, da� der einzige vorhandene Programmz�ahler h�au�g genug in dem,

dann als passiv zu bezeichnenden, Polling-Modul "vorbeikommt".

Events: Events sind im Zusammenhang mit Threads und Modularisierung

wichtig. Ein Thread gibt anderen Threads (in anderen Modulen) �uber Events

Nachrichten. Ein Thread kann auf einen Event warten, bzw. ein Modul wird

von einem Thread ausgef�uhrt, wenn ein bestimmter Event eingetreten ist. Da-

bei sollte ein auf einen Event wartender Thread keine, bzw. wenig Rechenzeit

in Anspruch nehmen m�ussen., also kein sogenanntes busy-wait durchf�uhren.

Im Optimalfall wird ein Event z.B. f�ur die �Anderung eines Sensorwertes von

der Hardware durch einen Interrupt ausgel�ost, der dann die Ausf�uhrung eines

Page 10: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4 1. EINLEITUNG

Threads veranla�t.

Subsumption: Subsumption ist ein von Rodney A. Brooks (Brooks, 1985)

erdachtes Konzept zur Steuerung von Robotern. Es basiert auf der Idee, bzw.

der Beobachtung aus der Biologie, da� komplexe Verhaltensweisen h�au�g das

Ergebnis von dem Zusammenspiel vieler einzelner, einfacher Verhaltensweisen

(Re exe) sind. Es eignet sich besonders gut f�ur die Wiederverwendung, da

die einzelenen Verhaltensweisen unterschiedlich kombiniert werden k�onnen. Der

"Original-Trusty" von Knudsen ist z.B. mit Subsumption programmiert worden

(Knudsen, 1999, S. 179�).

Objektorientierung: Diese Technik zur Modularisierung mittels Klassen

und zur Abstraktion mittels Interfaces2 ist sehr n�utzlich, da sie in weiten Teilen

an die menschliche Vorstellung von Dingen angelehnt ist. Das Entwickeln einer

vern�unftigen Modularisierung, deren Funktionsweise auch verst�andlich ist, wird

damit erleichtert.

Java: Java (Gosling et al., 2000) ist eine Sprache in der diese Techniken

relativ leicht und elegant einsetzbar sind. Au�erdem bietet Java die M�oglich-

keit der plattform�ubergreifenden Programmierung (Lindholm und Yellin, 1999),

mit dem (leider nicht ganz perfekt eingel�osten) Versprechen "Write Once, Run

Anywhere". So soll der Programmierer eigentlich nicht einmal darauf achten

m�ussen, auf welcher Plattform die Software am Ende laufen soll. Salopp gesagt,

k�onnte man die Motivation f�ur diese Arbeit auch folgenderma�en zusammen-

fassen: "Das, was Java f�ur normale Computer ist, will ich f�ur Roboter auch!"

1.3 Zielgruppe

Diese Arbeit ist weitgehend unter Verwendung zweier Produktreihen entstan-

den, die als Spielzeug vermarktet werden: Lego Mindstorms und Fischertechnik

Computing. Sowohl Lego als auch Fischertechnik wird au�erdem im Forschungs-

und Bildungsbereich eingesetzt und auf der Basis von Fischertechnik werden

Modelle zur Simulation von industriellen Fertigungsanlagen entwickelt. In die-

sem, eigentlich sehr breiten, Anwendungsbereich bewegt sich auch diese Arbeit.

Die Ideen, die hinter dem in dieser Arbeit entwickelten Programmiersystem

stecken, sind von der konkret verwendeten Hardware zwar unabh�angig, wurden

aber bislang nur f�ur Hardware aus den Lego Mindstorms und Fischertechnik

Computing Produktreihen realisiert. Daraus ergibt sich aber bereits ein Impuls

f�ur den Forschungsbereich, denn eine Portierung, bzw. Erweiterung auf ande-

re, neue Roboter-Hardware w�are sozusagen eine �Uberpr�ufung des entwickelten

Modells an der Realit�at.

Wer sich mit Robotern als Hobby besch�aftigt, will dabei (auch) Spa� haben.

Nun kann auch Java-Programmieren Spa� machen, warum also nicht beides

miteinander verbinden?Macht Java programmieren keinen Spa�, bzw. mu� man

es erst lernen, so kann man sich vielleicht mit einem Roboter als Anwendung

motivieren.

2Der Begri� Interface wird hier im gleichen Sinne wie in Java verwendet. Ein Interface be-

schreibt die Schnittstelle und bis zu einem gewissen Grad auch das Ergebnis der Funktionalit�at

von Objekten.

Page 11: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

1.4. INHALTS�UBERSICHT 5

F�ur Lehrende und Lernende ist Motivation sehr hilfreich. Durch die Ver-

bindung von Mechanik und Informatik im Roboterbau kann man das eine als

Vehikel benutzen, um die damit verbundene Motivation auf das andere zu �uber-

tragen. In diesem Fall, wie auch beim Hobby, kommt es weniger auf perfekte

Pr�azision und hohe Geschwindigkeit des Roboters an, als darauf, da� man re-

lativ leicht und schnell zu greifbaren Ergebnissen kommt. Spielzeug ist daf�ur

eigentlich die ideale Plattform (Nievergelt, 1999), zumal die notwendige Hard-

ware im Vergleich mit professionelleren Systemen deutlich billiger zu bekommen

ist.

Bei der Entwicklung von Simulationsmodellen in der Industrie ist zwar der

Spielraum f�ur den Hardware-Aufwand gr�o�er, aber daf�ur die Entwicklungszeit

oft von entscheidender Bedeutung. Je mehr dabei auf bereits vorhandene Mo-

dule zur�uckgegri�en werden kann desto besser. Kann die gleiche Software so-

wohl die Modelle als auch die "gro�en" Anlagen steuern, hat man nicht nur

Zeit gespart, sondern bekommt auch die unsch�atzbare M�oglichkeit, die Softwa-

re vorher, am Modell, ohne gr�o�ere Gefahr, zu testen. Eine Implementierung

f�ur diesen speziellen Verwendungszweck ist zwar im Rahmen dieser Arbeit nicht

geschehen, wurde aber weitgehend o�engehalten. F�ur die Programmierung der

reinen Simulationsmodelle, z.B. aus Fischertechnik, n�utzen die gleichen Din-

ge wie auch schon bei Hobby & Lehre: Es macht Spa� und produziert schnell

Ergebnisse.

1.4 Inhalts�ubersicht

Das folgende Kapitel beschreibt den "Beispielroboter" Ariadne. Ariadne kann

auf ein Licht zufahren und dabei Hindernissen ausweichen. Der Roboter ist

daf�ur aus zwei unabh�angigen Modulen aufgebaut, von denen eines ein Licht

�nden (LiSe) und das andere fahren und Hindernissen ausweichen kann (Trus-

ty).

In Kapitel 3 werden bereits bestehende Programmiersysteme untersucht.

Durch die Programmierung des in Kapitel 2 beschriebenen Robotermodells mit

unterschiedlichen Systemen werden deren Besonderheiten und Unterschiede ver-

deutlicht. Am Ende dieses �Uberblicks werden die dadurch erlangten Erkennt-

nisse zusammengefasst und erste Schlussfolgerungen daraus gezogen, welche vor

allem einen Ausgangspunkt f�ur das darauf folgende Kapitel bilden sollen.

Kapitel 4 ist die Beschreibung des im Rahmen dieser Arbeit entwickelten

Programmiersystems, das Abstract Robot Toolkit (ART). Es wird zuerst der

Grundgedanke erl�autert, welcher hinter dem System steckt, und welche Ziele

mit dem System erreicht werden sollen. Zudem werden einige wichtige Konzepte

wie MVC und Subsumption in diesem Zusammenhang n�aher betrachtet.

In Kapitel 5 wird eine praktische Einf�uhrung in das System gegeben, bei der

gezeigt wird, wie man damit Roboter programmieren kann. Hier wird, neben

einigen zus�atzlichen Erl�auterungen der F�ahigkeiten von ART, der rote Faden

aus Kapitel 3 wieder aufgenommen und das von dort bereits bekannte Robo-

termodell programmiert.

In Kapitel 6 wird erkl�art, wie das System f�ur andere Roboter-Hardware er-

Page 12: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6 1. EINLEITUNG

weitert werden kann. Daf�ur wird als Beispiel ein "Treiber" erl�autert, welcher

Textfelder des AWT als Ein- und Ausg�ange f�ur Sensoren und Aktuatoren ver-

wendet.

Das letzte Kapitel baut auf die Schlussfolgerungen aus Abschnitt 3.3 auf.

Es wird ein Vergleich zwischen den Systemen aus Kapitel 3 und dem eige-

nen System, das in den Kapiteln 4 bis 6 beschrieben wurde, durchgef�uhrt. Die

wesentlichen Vor- und Nachteile, sowie die Unterschiede, die in Kapitel 5 zu-

tage getreten sind, werden noch einmal zusammengefasst. Es wird bewertet,

wie vollst�andig die gesetzten Ziele erreicht wurden und wo o�enbar prinzipiel-

le Schwierigkeiten stecken. Au�erdem werden Ideen f�ur eine Weiterentwicklung

aufgezeigt.

Page 13: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

2

Ariadne {

a Li(ght)Se(arching) Trusty

Als Anwendungsbeispiel f�ur die verschiedenen Programmiersysteme soll ein Ro-

botermodell dienen, welches auf ein Licht zufahren und dabei Hindernissen aus-

weichen kann. Dieses Modell soll (auf der Harware-Seite), mit m�oglichst ver-

gleichbarer Funktionalit�at, einerseits aus Fischertechnik- und andererseits aus

Lego-Bauteilen realisiert werden. Zudem soll es aus zwei weitgehend unabh�angi-

gen Modulen bestehen: Eines ist f�ur das Chassis, das fahren und Hindernissen

ausweichen kann (Trusty). Das andere Modul ermittelt die relative Richtung,

in der sich eine Lichtquelle be�ndet (LiSe). Die Verbindung der beiden Module

kann dann einen Roboter ergeben, der auf ein Licht zufahren und dabei Hinder-

nissen ausweichen kann (Ariadne). Jeder lichtsuchende Trusty-Roboter besteht

also aus zwei Robotern mit geringerem Funktionsumfang, die von Ariadne mit-

einander verbunden werden.1

2.1 Trusty

Robotermodelle, die herumfahren und dabei im Weg stehenden Dingen wie

Cola aschen, St�uhlen oder auch Menschen ausweichen, sind beliebt. Der Name

Trusty stammt aus Knudsen (1999) und hat sich im Rahmen der Vorlesung zur

Roboterprogrammierung an der Universit�at Osnabr�uck (Schreiner, 2000b) als

Name f�ur solche ausweichenden Roboter eingeb�urgert.

Die hier verwendete Variante besitzt einen Antrieb, der aus zwei Motoren

besteht, die jeweils ein Rad antreiben. Ein drittes Rad ist leicht drehbar um die

senkrechte Achse gelagert, um einerseits einen sicheren Stand des Roboters zu

erm�oglichen, aber andererseits der durch die R�ader mit den Motoren vorgege-

benen Bewegung weitgehend zu folgen. Dieser Antrieb ist typisch f�ur einfache

1www.webster.com wei� �uber Ariadne folgendes zu berichten:

Etymology: Latin, from Greek Ariadne

: a daughter of Minos who helps Theseus escape from the labyrinth

Nun gut, hier ist es Trusty, der die Hilfe bekommt und da unsere Ariadne von LiSe unterst�utzt

wird, braucht sie auch keinen Faden . . .

7

Page 14: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

8 2. ARIADNE { A LI(GHT)SE(ARCHING) TRUSTY

Abbildung 2.1: Das Trusty-Chassis als Schema. Zwei voneinader unabh�angige An-triebsr�ader, sowie vorne zwei Bumper-Sensoren.

mobile Roboter.2

Vorne sind zwei bewegliche Querstangen angebracht, die jeweils einen Touch-

sensor bet�atigen, wenn der Roboter gegen ein Hindernis f�ahrt. Der Roboter ist

also nur in der Lage, gen�ugend fest stehende Hindernisse, die sich zudem auch

noch in der richtigen H�ohe be�nden, zu erkennen. Von Tischkanten zum Beispiel

w�urde er einfach herunterfallen.

2.2 LiSe

Oben auf dem Roboter be�nden sich zwei um eine senkrechte Achse drehbar

montierte Lichtsensoren. Mit zwei Sensoren, die V-f�ormig montiert sind, ist es

relativ einfach herauszu�nden, ob links oder rechts mehr Licht ist. Die Dreh-

achse wird von einem Motor, stark untersetzt (1:243 bei Lego und 1:6 { bzw.

1:1448,7 wenn man das am Motor montierte Getriebe mit einbezieht { bei Fi-

schertechnik), angetrieben. Au�erdem kann die Position der Drehachse �uber

einen Rotationssensor gemessen werden (Lego 48, Fischertechnik 48 Abstufun-

gen pro Umdrehung der Achse mit dem Lichtsensor; da� diese Werte gleich

sind, ist nur ein Zufall).

Da die Lichtsensoren an einem Kabel h�angen, k�onnen sie au�erdem nicht

um ganze 360Æ gedreht werden. Es gibt also eine Art Endabschalter, d.h. einen

Touchsensor, der bei Erreichen des einen Randes des Bewegungsbereiches be-

t�atigt wird. Das Erreichen des anderen Randes kann dann �uber den Rotations-

sensor festgestellt werden. Damit ist es au�erdem m�oglich, die zum Unterbau

relative Ausrichtung der Drehachse festzustellen, ohne da� sich die Achse beim

Start in einer de�nierten Position be�nden mu�.

Mit diesem Aufbau ist es m�oglich, die Lichtsensoren auf eine Lichtquelle aus-

zurichten und diese Ausrichtung bei einer relativen Bewegung der Lichtquelle

daran anzupassen. Die Lichtquelle kann innerhalb des Bewegungsbereiches ver-

folgt werden und die Position der Ausrichtung ist �uber den Rotationssensor

feststellbar. Der Name LiSe steht f�ur "Light-Search".

2Das beschriebene Rad wird im englischen auch als idler wheel bezeichnet.

Page 15: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

2.3. ARIADNE 9

S

Abbildung 2.2: LiSe als Schema. Zwei Lichtsensoren, V-f�ormig zueinander positioniert,ein Antrieb mit Rotationssensor (S) und Endabschalter.

2.3 Ariadne

Beide Teile, das Trusty-Chassis und der drehbare Turm mit den Lichtsensoren

von LiSe, sind f�ur sich genommen schon als eigenst�andige Roboter anzusehen.

Trusty kann herumfahren und Hindernissen ausweichen und LiSe kann eine sich

bewegende Lichtquelle verfolgen. F�ugt man diese beiden Module zusammen hat

man einen Roboter der eine Lichtquelle verfolgen, darauf zufahren, und dabei

Hindernissen ausweichen kann: Ariadne. Dieses Zusammenf�ugen geschieht auf

der Ebene der Lego- bzw. Fischertechnik-Bausteine, indem der Turm auf dem

Chassis in nat�urlicher Weise montiert wird.

Dieses Zusammenf�ugen der voneinander unabh�angigen Module zu einem

komplexeren Ganzen soll so weit wie m�oglich auch auf der Steuerungsebene in

der Software nachvollzogen werden. Die Steuerung f�ur die jeweiligen Module

soll daher unabh�angig voneinander programmiert werden. Trotzdem wird ver-

sucht, die dabei entstandene Software mit m�oglichst wenig Aufwand f�ur Ariadne

wiederverzuverwenden.

W�urde man die Lichtsensoren z.B. durch eine Kamera ersetzen, so k�onnten

nat�urlich auch Objekte wie beispielsweise ein Fu�ball verfolgt werden { schon

k�onnte der Roboter beim Robocup mitspielen!

2.4 Hervorzuhebende Eigenschaften

Das Robotermodell Ariadne ist aus verschiedenen Bed�urfnissen heraus entstan-

den.

typische Sensorik: Obwohl man an die Eing�ange des Brick und des Intelli-

gent Interface im Grunde beliebige Strom- bzw. Widerstandsquellen an-

schlie�en kann, so sind doch die Schalter (Tastsensoren) am h�au�gsten

anzutre�en. F�ur analoge Sensoren ist ein Lichtsensor das beste Beispiel,

da er in den Grundbauk�asten "Robotics Invention System" (1.0 - 2.0)

und "Mobile Robots" bereits vorhanden ist. Ein Rotationssensor geh�ort

bei Lego zwar nicht zum "Standard", ist aber auch ein sehr wichtiger

Page 16: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

10 2. ARIADNE { A LI(GHT)SE(ARCHING) TRUSTY

Abbildung 2.3: Die Lichtsensoren bei Lego sind die beiden blauen Steine mit dem rotleuchtenden Punkt.Bei Fischertechnik sind die Lichtsensoren die kleinen gelben Steine, die wie Lampenaussehen. Das selbstgebaute Getriebe f�ur die �Ubersetzung nimmt viel Platz ein.

Sensor, da nur mit ihm eine pr�azise Steuerung der Motoren m�oglich ist.

Die Rotationssensoren von Lego und Fischertechnik unterscheiden sich

von den anderen Sensoren zudem dadurch, da� sie eine kontinuierliche

Abfrage ihres Zustands ben�otigen, um einen sinnvollen Wert liefern zu

k�onnen.

modularer Aufbau: Da ein wesentlicher der betrachteten Aspekte die Modu-

larisierung und Wiederverwendung von Software ist, mu� der Beispielro-

boter selbst aus Modulen bestehen, die unabh�angig voneinander betrach-

tet werden k�onnen.

Standardmodell: Wenigstens eines der Modelle sollte eine Art "Standardmo-

dell" sein. Ein Beispiel, das in vielen B�uchern zu dem Thema verwendet

wird, ist ein Roboter wie Trusty. Damit ist es auch einem Leser ohne Er-

fahrung in der Konstruktion mit Lego und/oder Fischertechnik m�oglich,

zumindest Trusty nachzubauen und eigene Programmierversuche durch-

zuf�uhren. Selbst die Anleitungen zu den Grundbauk�asten enthalten Bei-

spiele f�ur einen solchen Roboter (er hei�t dort nur nicht Trusty).

viele Sensoren und Motoren: Die Anschlussm�oglichkeiten der verwendeten

Hardware sollten weitgehend ausgereizt werden, um zu sehen, wie sich die

Systeme bei aufw�andigeren Konstruktionen verhalten. Der Brick bietet

im Grunde nur drei Anschl�usse f�ur Sensoren, f�ur das komplette Ariadne-

Beispiel werden aber sechs Sensoren verwendet. Da aber vor allem die

Tastsensoren des Brick nicht unbedingt eine spezielle Konstruktion be-

n�otigen, kann man diese durchaus parallel zu einem anderen Sensor ver-

Page 17: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

2.4. HERVORZUHEBENDE EIGENSCHAFTEN 11

wenden (Ferrari und Ferrari, 2002). Es ist dann aber notwendig, da� die

verwendete Software einem weitgehende Freiheit darin l�asst, wie man den

Eingang kon�guriert und seinen Wert ausliest.

Lego und Fischertechnik Die Interface-Hardware von Lego und Fischertech-

nik ist sehr verschieden. So wird ein g�anzlich anderes serielles Protokoll

verwendet, die elektrischen Eigenschaften der Sensoren unterscheiden sich

weitgehend und die Ansteuerung der Motoren ist auch nicht auf die gleiche

Weise umgesetzt. Zudem sind am Intelligent Interface sogar noch ein paar

Anschl�usse frei. Trotzdem k�onnen mit beiden Systemen Roboter gebaut

werden, die sich im Wesentlichen gleichen. Damit k�onnen, anhand eines

gemeinsamen Steuerungsalgorithmus f�ur beide Varianten, die Abstrakti-

onsf�ahigkeiten des Abstract Robot Toolkit (ART) auf die Probe gestellt

werden.

Das Abstract Robot Toolkit ist aber keineswegs nur f�ur dieses Roboter-

modell entwickelt worden. Es soll vielmehr jeder Roboter mit ART gesteuert

werden k�onnen, zumindest vom Prinzip her. Die Verwendung von Lego und

Fischertechnik hat rein praktische Gr�unde. Die Hardware ist billig und der Zu-

sammenbau eines Roboters erfordert keine tiefgehenden ingenieurwisenschaft-

lichen Kenntnisse. Der Beispielroboter Ariadne ist nur das Testobjekt mit dem

das Prinzip erkl�art und �uberpr�uft wird.

Page 18: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

12 2. ARIADNE { A LI(GHT)SE(ARCHING) TRUSTY

Page 19: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3

Programmiersysteme f�ur

Roboter

In diesem Kapitel werden verschiedene Programmiersysteme f�ur LEGO Mind-

storms und Fischertechnik Computing vorgestellt. Besonderer Wert wird dabei

auf die M�oglichkeiten zur Modularisierung undWiederverwendung gelegt, sowie

auf die Verwendung von Threads und Events.

Im Abschnitt 3.1 werden gra�sche Programmierumgebungen vorgestellt.

Der Abschnitt 3.2 auf Seite 22 besch�aftigt sich mit den verschiedenen Program-

miersystemen auf Textbasis, von denen einige gleich ein eigenes Betriebssystem

mitbringen.

Es gibt noch wesentlich mehr, frei verf�ugbare Systeme, als hier beschrieben

werden. Als Einstieg im Zusammenhang mit dem Brick bietet sich das Lugnet-

Forum im Internet an (http://news.lugnet.com/robotics/rcx/). Von Fi-

schertechnik gibt es auch eine Web-Seite von welcher aus weitere Program-

miersysteme erreichbar sind, die sich aber meistens auf eine Art Treiber, f�ur

die Ansteuerung aus bestimmten Programmiersprachen heraus, beschr�anken

(http://www.fischertechnik.de/ft-Computing.html).

Alle bekannten verf�ugbaren Systeme zu betrachten w�urde im Rahmen dieser

Arbeit zu weit gehen. Aus den Bereichen der gra�schen Programmiersysteme

wird LLWin besonders ausf�uhrlich behandelt, bei den textbasierten wurde le-

JOS der meiste Raum einger�aumt. Ansonsten werden einige der wichtigsten Sy-

steme kurz vorgestellt und die im Zusammenhang mit dieser Arbeit wichtigen

Eigenschaften erl�autert. F�ur einige der vorgestellten Systeme existieren Bei-

spielprogramme f�ur LiSe, Trusty und Ariadne, deren Quellcode auf der CD zu

dieser Arbeit enthalten ist, sowie aus dem Internet geladen werden kann (siehe

Anhang, Abschnitt A.1 auf Seite 136). Hin und wieder werden, um Besonder-

heiten am realen Beispiel zu verdeutlichen, Ausschnitte aus den Programmen

in der Beschreibung der jeweiligen Systeme gezeigt.

3.1 Gra�sche Programmiersysteme

F�ur die Computerinterfaces von Lego und Fischertechnik sind vor allem drei

gra�sche Programmierumgebungen von Bedeutung, die vom Hersteller der je-

13

Page 20: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

14 3. PROGRAMMIERSYSTEME F�UR ROBOTER

weiligen Hardware angeboten werden:

� LLWin (Lucky Logic f�ur Windows) f�ur Fischertechnik

� RCX-Code f�ur Lego

� Robolab f�ur Lego

RCX-Code ist speziell f�ur das Robotics Invention System entwickelt wor-

den. Robolab und LLWin sind an die jeweilige Hardware angepasste Versionen

einer Software, die auch in der Industrie eingesetzt wird. Robolab stammt von

LabVIEW ab und der gro�e Bruder von LLWin ist iCon-L. LabVIEW wird

von National Instruments verkauft und ist vor allem f�ur den Einsatz im La-

bor konzipiert. iCon-L wird von der Firma Pro-Sign Process Design GmbH als

Programmiersystem f�ur Prozessautomation verkauft.

Bei den gra�schen Systemen wird ein Schwerpunkt auf LLWin gelegt. LL-

Win ist einerseits m�achtiger als RCX-Code, allein schon deswegen, weil man

Variablen verwenden kann, andererseits ist es �uberschaubarer als Robolab, da

weniger Programmierbausteine zur Verf�ugung stehen.

3.1.1 LLWin

LLWin wird von Fischertechnik verkauft und l�auft nur unter Windows. �Ahn-

lich wie bei den anderen gra�schen Programmiersystemen werden Bausteine auf

einem Arbeitsblatt plaziert und durch "Dr�ahte", die den Kontroll uss symbo-

lisieren, miteinander verbunden. Programme k�onnen in das Interface geladen

werden. Das Interface f�uhrt sie dann unabh�angig von einem angeschlossenen

PC aus. Werden die Programme hingegen auf dem PC betrieben, ist sogar eine

Ablaufverfolgung in der gra�schen Programmansicht m�oglich.

Es gibt 115 Speicherpl�atze f�ur Variablen1 und innerhalb von Zuweisungen

und Vergleichen k�onnen, zumindest ab Version 3.0, einfache arithmetische Ope-

rationen wie +��= und Klammern eingesetzt werden. Ohne diese Operationen

war bisher etwa eine sinnvolle Kalibrierung von Sensoren kaum zu bewerkstelli-

gen, da man beispielsweise ein arithmetisches Mittel nur auf dem Umweg �uber

die Operationen INC, DEC, einen Vergleich und eine Schleife (also mit entspre-

chend gro�em Aufwand) berechnen konnte.

Die LLWin-Version von Trusty wurde mit Subsumption (siehe 1.2 auf Sei-

te 4) programmiert, LiSe hingegen nicht. Bei Trusty ist Subsumption besonders

hilfreich im Hinblick auf die sp�atere Erweiterung zu Ariadne, da dadurch in

Trusty's Verhalten leichter eingegri�en werden kann.

LiSe k�onnte, von der Aufgabenstellung her, zwar auch sehr gut mit Sub-

sumption programmiert werden (siehe z.B. Abschnitt 3.2.4 auf Seite 27 oder

auch Abschnitt 5.6 auf Seite 99), eine solche Implementierung in LLWin w�urde

jedoch 3-4 Threads mehr ben�otigen. Die Steuerung von Ariadne ist aber bereits

in ihrer jetzigen Form { ohne Subsumption bei LiSe { schon zu komplex, um

199 normale sowie 16 Z�ahlvariablen, die auch von dem Baustein POSITION benutzt werden.

Alle sind 16 Bit signed.

Page 21: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.1. GRAFISCHE PROGRAMMIERSYSTEME 15

auf das Interface heruntergeladen zu werden. Die Ausf�uhrung ist dort schlicht

zu langsam. Bei Ausf�uhrung in LLWin auf einem angeschlossenen PC (Penti-

um III, 650Mhz) ist die Geschwindigkeit zwar noch ausreichend, die Reaktions-

zeiten "f�uhlen" sich aber bereits etwas langsam an. Aus diesem Grund wurde

die Steuerung von LiSe in LLWin auf konventionellem Weg, mit einer gro�en

Schleife, realisiert.

Bei der Programmierung mu�ten Kompromisse eingegangen werden, da die

komplette Fassung von Ariadne anfangs zu langsam und zu ungenau lief. Zum

Beispiel war die Positionsmessung mit so gro�en Fehlern behaftet, da� sie un-

brauchbar war. Zur L�osung wird nun immer die letzte gewollte Drehrichtung

gespeichert und zwischen einer Umkehrung der Drehrichtung eine kurze Pause

eingelegt, in der der Motor steht. Damit wird die Positionsmessung zwar noch

langsamer, aber wieder ausreichend genau.

Ein Grund f�ur die geringe Ausf�uhrungsgeschwindigkeit sind wahrscheinlich

die vielen Threads. Sie sind jedoch f�ur eine elegante und �ubersichtliche Program-

mierung unabdingbar. Zudem sollten ja auch die M�oglichkeiten von LLWin aus-

gelotet werden. Es ist bestimmt m�oglich, mit LLWin eine Steuerung f�ur Ariadne

zu entwickeln, die schneller l�auft und den Roboter mindestens genausogut steu-

ert, das w�are dann wahrscheinlich aber kein geeignetes Beispiel mehr, weil man

wohl auf den Versuch der Modularisierung und Wiederverwendbarkeit, elegante

Beispiele f�ur Thread-Synchronisation sowie Subsumption verzichten m�u�te.

Threads

In LLWin ist das eigentliche Erzeugen von verschiedenen Threas sehr einfach.

Dazu braucht man nur mehrere Startsymbole auf das Arbeitsblatt zu setzen. Ei-

ne M�oglichkeit zu deren Synchronisierung ist jedoch nicht vorgesehen. Es bleibt

nur der Ausweg dieses �uber Variablen selbst umzusetzen. Threads k�onnen sich

nicht gegenseitig aufwecken oder unterbrechen, eine Synchronisierung verlangt

daher die wiederholte Abfrage eines Zustands.

VAR81 1

VAR97 1025

VAR96 1025

VAR98 EX

Obergrenzen für den Analogwert

Signal an Main-Thread, daß dieInitialisierung abgeschlossen ist.

Kopierthread für Analogwerte.

VAR81=1

1

0

VAR5 VAR96

VAR6 VAR97

Kopierthread für die Analogwerteerst einmal durchlaufen lassen.

Eigene Variablen initialisieren

Obere Schranke der Lichtsensoren.

Main

...

...

Abbildung 3.1: Der linke Thread braucht f�ur die Initialisierung seiner Variablen diebereits initialisierten Variablen VAR96/97 aus dem rechten Thread. Der Linke wartetzu Beginn daher bis der Rechte einen bestimmten Punkt in seiner Ausf�uhrung erreichthat (in diesem Fall bis die Schleife einmal durchgelaufen ist).

Im Beispielprogramm werden Threads auf zwei Arten synchronisiert. Im

Page 22: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

16 3. PROGRAMMIERSYSTEME F�UR ROBOTER

einen Fall soll ein Thread warten, bzw. einen bestimmten Ausf�uhrungsweg erst

dann nehmen, wenn ihm ein anderer explizit dazu die Erlaubnis gibt. Das wird

schlicht �uber das Setzen und Abfragen von jeweils einer Variable pro solch einer

Kommunikation geregelt. Im einfachsten Fall wird dies { im Algorithmus von

LiSe { dazu verwendet, zwei Threads ihre Initialisierung in einer bestimmten

Reihenfolge ausf�uhren zu lassen (siehe Abbildung 3.1 auf der vorherigen Seite).

Im Algorithmus von Trusty sollen die Threads, die f�ur die Implementie-

rung der jeweiligen Verhaltensweisen zust�andig sind, nur dann ihr Verhalten

ausf�uhren, wenn der Thread, der die Priorit�aten der Verhaltensweisen regelt,

ihnen das Signal dazu gibt. Der Thread f�ur die Priorit�atenvergabe hingegen

mu� dann warten, bis die jeweils angesto�ene Verhaltensweise "fertig" ist, damit

nicht die n�achste beginnt, solange die vorherige noch l�auft. An dieser Stelle wird

der Baustein POSITION verwendet, um Threads m�oglichst ressourcenschonend

zu synchronisieren (siehe Abschnitt 3.1.1 und Abbildung 3.3 auf der n�achsten

Seite).

Etwas schwieriger wird es, wenn es nicht darum geht, zwei Threads immer an

der gleichen Stelle aufeinander warten zu lassen, sondern wenn erreicht werden

soll, da� bestimmte, kritische Bereiche nicht von mehreren Threads gleichzeitig

ausgef�uhrt werden k�onnen. In Java gibt es daf�ur eine eigene Kontrollstruktur {

synchronized. Ohne Java l�ost man solch ein Problem z.B. mit einer Semaphore.

Aus

0.5 s

VAR82

VAR82

VAR82<0

0

1

Ein

Aus

VAR82

Ein

Abbildung 3.2: Implementierung einer Semaphore in LLWin. Das UnterprogrammAQUIRE z�ahlt VAR82 um eins herunter, wird aber nur verlassen, wenn VAR82 dabei nichtkleiner 0 wird. RELEASE z�ahlt VAR82 wieder um eins hoch.

Abbildung 3.2 zeigt die Implementierung einer Art Semaphore (Tanenbaum,

1990; Dijkstra, 1965) als Unterprogramm in LLWin. Die korrekte Funktions-

weise dieser Implementierung ist davon abh�angig, da� die einzelnen Bausteine

unteilbar abgewickelt werden. Davon kann man aber ausgehen, da es sich bei

LLWin um einen Interpreter handelt.

Mit dieser Implementierung ist ein gesch�utzter Bereich m�oglich. F�ur mehre-

re m�u�ten auch mehrere solcher Unterprogramm-Paare implementiert werden.

Mit dem Unterprogramm AQUIREwird Zugri� auf einen gesch�utzten Bereich ver-

langt, mit RELEASE wird er wieder freigegeben. Dabei mu� man sich nat�urlich

an die Spielregeln halten und darf z.B. nicht RELEASE aufrufen, wenn man noch

gar kein AQUIRE aufgerufen hat. Direkte Ver�anderungen an der von den Unter-

programmen benutzten Variable sind in diesem Sinne (nat�urlich) genausowenig

gestattet.

Eine Ausnahme ist die Initialisierung der Z�ahlvariable von AQUIRE/RELEASE.

Das Programm beginnt mit einem Zustand, in dem kein Aufruf von AQUIRE zu

Page 23: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.1. GRAFISCHE PROGRAMMIERSYSTEME 17

Ende gehen w�urde, d.h. ein Thread sollte mindestens einmal RELEASE ohne

ein vorausgegangenes AQUIRE aufrufen. Es gibt also zu jedem Zeitpunkt nur

h�ochstens genausoviele bereits durchlaufene AQUIRE-Aufrufe wie bereits durch-

laufene RELEASE-Aufrufe.

Events

In LLWin gibt es etwas, das man mit Events vergleichen kann, in zwei Bau-

steinen: POSITION und FLANKE. Kommt ein Thread zu solch einem Baustein,

verharrt er dort solange, bis die angegebene Anzahl von Flanken (POSITION),

bzw. der angegebene Typ Flanke (fallend oder steigend bei FLANKE) an dem

angegebenen Eingang registriert wurde. In Bezug auf die analogen Eing�ange

mu� man auf Events verzichten.

VAR22 0

VAR32=1

1

0

VAR22 0

VAR22 1

E 1

1

0

VAR32 0

E6 VAR34 0

E6 VAR35 0

E6 VAR31 0

VAR25=1

0

1

VAR35 1

VAR31 1

VAR34 1

VAR21=1

0

1

VAR24=1

0

1

Scheduler für Subsumption

AusweichenMitte

Ins LichtDrehen

ImmerGeradeaus

.....

.

...

VerhaltensweiseAusweichen Links

Linker Bumper Sensor

Darf nicht

Soll

Ausweichen ...

Nachricht an Scheduler,daß fertig

Will

Will nicht

Abbildung 3.3: Die Variablen VAR3x werden von dem Scheduler (links) auf den Wert 1

gesetzt, als Signal an den jeweiligen Verhaltensweisen-Thread (rechts). Umgekehrt setztein Verhaltensweisen-Thread, nachdem er sein Verhalten ausgef�uhrt hat, diese Variablewieder auf 0. Die gleiche Variable kann hier f�ur zwei verschiedene Kommunikationengenutzt werden, da die Kommunikationen sich immer genau abwechseln.

Da der Baustein POSITION zum Z�ahlen eine globale Variable benutzt, ist es

m�oglich (aus einem anderen Thread heraus) den Wert auf die im Baustein an-

gegebene Zahl zu setzen und damit die Ausf�uhrung des Bausteins zu beenden.

Es ist zwar nicht dokumentiert, aber der Baustein sollte in diesem Fall auch

wirklich immer zu Ende gehen, da ein Test zeigt, da� auch eine �Uber-, bzw.

Unterschreitung der angegebenen Zahl zum Abbruch f�uhrt. Es ist also durch

"Missbrauch" des Bausteines POSITION realisierbar, einen Thread { m�oglicher-

weise2 ohne Ressourcenverbrauch { auf ein durch einen anderen Thread aus-

2Die konkrete Implementation von POSITION ist nicht dokumentiert.

Page 24: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

18 3. PROGRAMMIERSYSTEME F�UR ROBOTER

gel�ostes Ereignis warten zu lassen (siehe Abbildung 3.3 auf der vorherigen Seite).

Will man durch ein Ereignis, wie z.B. eine steigende Flanke, einen bestimm-

ten Vorgang ansto�en und w�ahrenddessen aber weiterhin den Eingang auf ein

erneutes Eintreten des Ereignisses �uberwachen, mu� man sich darum selber

k�ummern. Aus diesem Grund gibt es zur kontinuierlichen Bestimmung der Po-

sition des Towers im Algorithmus von LiSe zwei Threads, denn um die Position

einer Achse mit einem der vorgesehenen Impulsr�ader zu �uberwachen, reicht der

Baustein POSITION alleine nicht aus.

VAR8=1

0

1

VAR71 VAR71-(VA...VAR71 VAR71+(VA...

VAR73 VAR72

VAR74 VAR73

VAR72 > VAR73

1

0

AQUIRE

RELEASE

E 34

1

0

E 44

0

1

E34=1 bedeutet M4 dreht linksherum.

Seit dem letzten Durchgang beobachtete Flanken je nachMotorzustand von der Positionsvariable (VAR71)subtrahieren (Rechtsdrehung) oder zu ihr addieren (Linksdrehung).

Beginn eines exklusiven Zugriffs-bereichs. VAR82 wird dafür ähnlichwie Semaphore verwendet.

Ende desExklusiven Bereiches

Positionsthread.Speichert Position vonM4 ständig in VAR71.

Die Berechnung ist von einem Aquire-Release Paarumgeben, um einen sicheren Reset der Variablenzur Laufzeit zu ermöglichen. (RST_ROT)

E44=1 heißt M4 rechtsdrehend.

In VAR8 steht die letzte Suchrichtung.

E8 VAR72 32000

Flanken beobachten und mit minimalemAufwand speichern um möglichst keineFlanke zu verpassen.

Abbildung 3.4: Ein Thread z�ahlt die Flanken, der andere bestimmt die Richtung. W�urdedas der gleiche Thread machen, gingen Flanken leichter verloren. Leider ist es nichtganz einfach die Drehrichtung eines Motors zu bestimmen, der vielleicht inzwischenschon wieder aus ist ...

Einer der Threads be�ndet sich st�andig im Baustein POSITION, damit m�og-

lichst keine Flanke verloren geht. Ein weiterer beobachtet die Z�ahlvariable die-

ses POSITION-Bausteins und addiert oder subtrahiert die Ver�anderungen seit

seinem letzten Schleifendurchlauf in einer weiteren Variablen, je nachdem in

welche Richtung sich der Tower gerade dreht, bzw. wahrscheinlich das letzte

Mal gedreht hat. Diese Variable enth�alt dann die Position des Towers (siehe

Abbildung 3.4).

Modularisierung und Wiederverwendung

Zur Strukturierung eines Programms hat man die M�oglichkeit, Unterprogram-

me zu erstellen. Parameter oder lokale Variablen gibt es nicht, ein Unterpro-

Page 25: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.1. GRAFISCHE PROGRAMMIERSYSTEME 19

gramm greift auf dieselben globalen Variablen zu wie der Rest des Programms.

Wiederverwendung von (Teilen von) Programmen in anderen Programmen

ist nur durch Cut&Paste einer Selektion von Symbolen auf dem Arbeitsblatt

m�oglich. Dabei mu� au�erdem darauf geachtet werden, da� eventuell mitselek-

tierte Unterprogramme bereits vorher kopiert wurden und den gleichen Namen

bekommen haben.

Eine gro�e Schwierigkeit stellen in diesem Zusammenhang die Variablen dar.

Da alle Variablen global und deren Anzahl beschr�ankt ist, mu� man zwangsl�au-

�g irgendwann mit �Uberschneidungen bei den verwendeten Variablen rechnen.

Dann m�ussen Variablen umbenannt werden, wodurch sehr leicht neue Fehler

entstehen. Welche Variable im jeweiligen Projekt noch nicht benutzt wurde, ist

nur durch eigene Kontrolle herauszu�nden, eine Suchfunktion oder �Ahnliches

gibt es nicht. In einem Projekt wie Ariadne werden die Variablen bereits knapp,

vor allem, wenn man wenigstens etwas Struktur hineinbringen und Variablen

innerhalb eines gemeinsamen Kontextes systematisch ausw�ahlen m�ochte.

Im Beispiel kann der Algorithmus von LiSe ohne Anpassungen (wenn man

einmal von Variablennamen absieht) per Cut&Paste �ubernommen werden. Bei

Trusty ist das schon etwas schwieriger, da die Steuerung von Ariadne nicht

gleichzeitig mit der Trusty-Steuerung auf die gleichen Ausg�ange zugreifen darf.

Diese beiden Steuerungen m�ussen miteinander kooperieren. Durch Subsumption

(siehe Abschnitt 1.2 auf Seite 4) ist die Integration von Trusty und Ariadne

zwar einfach, aber nicht ohne Ver�anderung des bereits f�ur Trusty existierenden

Schedulers (vgl. Abbildung 3.3 auf Seite 17) zu bewerkstelligen, da Ariadne in

dessen Vorrangregelung integriert werden mu�.

3.1.2 RCX-Code

Die mit dem Robotics Invention System mitgelieferte Programmierumgebung,

RCX-Code, basiert im Wesentlichen auf stark spezialisierten und eingeschr�ank-

ten Struktogrammen nach Nassi-Shneiderman (Schreiner, 2000b). Das bedeutet

unter anderem, da� die einzelnen Bausteine des Programms direkt aneinander-

gesetzt und daher im Gegensatz zu LLWin und Robolab daf�ur keine Dr�ahte

gezogen werden m�ussen.

Auch in RCX-Code gibt es einen Start-Baustein und �uber die sogenannten

"Sensor-Watcher" k�onnen Threads beim Auftreten eines, durch den Sensor-

Watcher de�nierten, Events gestartet werden. Der gesamte Sprachumfang des

RCX-Code aus dem RIS 1.0 ist recht ausf�uhrlich in Schreiner (2000b) doku-

mentiert. In den Versionen f�ur das RIS 1.5 und 2.0 ist RCX-Code nochmals

deutlich erweitert worden.

Die gesamte Ober �ache des RIS, in welche die Programmierumgebung RCX-

Code eingebettet ist, wird vor allem der erkl�arten Zielgruppe des Produkts

gerecht. Sie ist ansprechend, fast wie ein Computerspiel, gestaltet und um sich

in RCX-Code hineinzu�nden sind kaum Erfahrungen in der Programmierung

notwendig. Die Bausteine sind weitgehend selbsterkl�arend und nicht schwer

zu �nden, da der Zugri� auf den gesamten Vorrat praktisch direkt auf der

Ober �ache, ohne irgendwelche Men�uzugri�e m�oglich ist.

Wer bereits mit "richtigen" Programmierersprachen Erfahrungen gemacht

Page 26: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

20 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Abbildung 3.5: Ein Programm in RCX-Code, der Programmierumgebung des RIS. Es

steuert einen Trusty-�ahnlichen Roboter und demonstriert die M�oglichkeit, da� Threads

�uber die einzige Variable in RCX-Code, den "Counter", kommunizieren.

hat, wird jedoch sehr bald feststellen, da� er f�ur die gewohnte L�osung von

erstaunlich vielen Programmieraufgaben Variablen braucht. Leider sind diese

in RCX-Code praktisch gar nicht vorhanden. Auf diese Weise sind auch die

M�oglichkeiten zum Datenaustausch zwischen den einzelnen Threads nur sehr

eingeschr�ankt m�oglich.

Andererseits ist es auch erstaunlich, was trotzdem alles mit dieser Umge-

bung programmierbar ist. Zudem liegt der Ursprung des RIS amMassachusettes

Institute of Technology { dem gleichen Umfeld aus dem auch die LOGO-Turtle

kommt (Papert, 1999). Die Idee, Programmieren durch Verwendung einer bei-

nahe zustandsfreien Programmiersprache zu lernen und dabei auch noch Spa�

zu haben, wird daher im RIS nur auf eine neue, aufregende Art umgesetzt.

In diesem Kontext ist es nicht weiter verwunderlich, da� mit RCX-Code die

Verwendung von mehreren Sensoren an dem gleichen Eingang nicht unterst�utzt

wird. Dadurch ist die Programmierung des Beispielroboters aber kaum m�oglich.

Lediglich Trusty w�urde keine Schwierigkeiten machen, ein Beispielprogramm f�ur

einen Trusty-�ahnlichen Roboter zeigt die Abblidung 3.5.

3.1.3 Robolab

Robolab wird von LEGO Dacta als Steuerungs-Software f�ur den Brick verkauft.

Es l�auft sowohl unter Windows als auch unter MacOS. Robolab zeichnet sich vor

allem durch seine M�oglichkeiten zur Auswertung von Messdaten aus. Die schiere

F�ulle an Symbolen, die zum Aufbau eines Programms auf dem Arbeitsblatt

plaziert werden k�onnen, ist { zumindest am Anfang { kaum zu �uberblicken.

Page 27: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.1. GRAFISCHE PROGRAMMIERSYSTEME 21

Es gibt daher f�unf verschiedene "Schwierigkeitsstufen" und nur in einer steht

einem wirklich das komplette Arsenal an Operationen zur Verf�ugung.

Abbildung 3.6: Ein einfaches Programm in Robolab, welches die Motoren A und C

laufen l�asst, bis der Taster am Eingang 1 gedr�uckt wird.

Es gibt Variablen (sogenannte Container) und alle wichtigen arithmetischen

Operationen. F�ur Motoren und die verschiedenen Sensortypen gibt es gleich

mehrere Bausteine, um diese anzusteuern. Hervozuheben ist die Integration

eines speziellen Sensoradapters �uber den z.B. schlicht eine Spannung gemessen

werden kann.

Die Programmierung erfolgt, indem man Symbole, die f�ur bestimmte Daten,

bzw. Operationen stehen, auf dem Arbeitsblatt plaziert und durch Dr�ahte mit-

einander verbindet. �Uber die Dr�ahte wird in Robolab nicht nur der Programm-,

sondern auch der Daten uss gesteuert. Wie man in Abblidung 3.6 sehen kann,

wird z.B. der Baustein, der einen Motor einschaltet, �uber die Verkn�upfung mit

den Containern 'A', 'C' und '5' kon�guriert. Der eigentliche Kontroll uss bei

der Ausf�uhrung geht entlang der gestricheleten Linien von der gr�unen bis zur

roten Ampel, im Beispiel also von links nach rechts.

Leider ist Robolab nicht in der Lage, einen Sensoreingang des Brick, zu ver-

schiedenen Zeitpunkten des Programmablaufs, f�ur die Verwendung mit mehre-

ren Sensoren, unterschiedlich zu kon�gurieren. M�ochte man also mehrere Sen-

soren �ubereinander an einem Port ansteuern, geht das nur eingeschr�ankt und

etwas umst�andlich. Man mu� sich zum einen auf einen Typ Sensorbaustein be-

schr�anken und au�erdem sind Kombinationen { z.B. mit dem Rotationssensor

{ �uberhaupt nicht m�oglich. Das macht die Entwicklung eines Steuerungspro-

gramms f�ur Ariadne unm�oglich, da die Lego-Version verlangt, insgesamt sechs

Sensoren an den drei vorhanden Anschl�ussen anzusteuern. So h�angt z.B. der

Page 28: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

22 3. PROGRAMMIERSYSTEME F�UR ROBOTER

End-Abschalter von LiSe mit dem Rotationssensor zusammen an einem Ein-

gang.

Aus diesem Grund wird hier auf Beispielprogramme verzichtet. F�ur die Ver-

wendung des Brick zur Erfassung und Auswertung von Messreihen ist Robolab

aber o�enbar sehr gut geeignet und daf�ur ist es wohl in erster Linie auch ge-

dacht. In Bezug auf Threads und Wiederverwendung besitzt Robolab �ahnliche

F�ahigkeiten wie LLWin.

3.2 Textbasierte Programmiersysteme

Textbasierte Programmiersysteme haben gegen�uber den gra�schen oft den Vor-

teil, da� das Format, in welchem der Programm-Code gespeichert wird, einfa-

cher Text ist. Das er�o�net weitreichende M�oglichkeiten die Programmierumge-

bung durch Verwendung weiterer Tools zu verbessern, was im Falle von pro-

priet�aren Formaten schwieriger ist. Besonders naheliegend ist z.B. die Verwen-

dung eines Pr�aprozessors oder eines Tools zur Versionskontrolle. Zudem ist man

als "richtiger" Programmierer einfach daran gew�ohnt, Programme in Form von

Text aufzuschreiben. Vor allem die frei verf�ugbaren Systeme, die meistens aus

purem Enthusiasmus entwickelt wurden, sorgen in diesem Bereich f�ur eine sehr

gro�e Auswahl.

Es existieren im Wesentlichen drei verschiedene Ans�atze, welche hier in ei-

genen Abschnitten vorgestellt werden sollen. Als letztes wird leJOS genauer

diskutiert. Es handelt sich dabei um ein Betriebssystem f�ur den Brick, welches

erlaubt in Java geschriebenen Code auf dem Brick auszuf�uhren.

3.2.1 Fernsteuerungen

In diesem Abschnitt werden einige Systeme vorgestellt, die es erlauben, Pro-

gramme zu schreiben, die auf einem normalen PC ablaufen und die Interface-

Hardware von dort aus fernsteuern.

FishFace

F�ur Fischertechnik unter Windows gibt es FishFace von Ulrich M�uller (http:

//www.ftComputing.de/). Es bietet Zugri� auf alle Ein- und Ausg�ange des

parallelen Interface und des Intelligent Interface. Es enth�alt au�erdem einige

Funktionen, die vor allem den Umgang mit Motoren und Impulsr�adern verein-

fachen.

Zugri� auf Events bekommt man, indem bestimmte Methoden des FishFace-

Objekts �uberschrieben werden. Es gibt aber nur Methoden f�ur die digitalen

Eing�ange und, da es nur ein Interface-Objekt gibt, ist auch nur ein Objekt

als "Listener" verwendbar, n�amlich das FishFace-Objekt selbst. Die Methoden

lauten im einzelnen:

InputImpuls(InputNr as Integer, ImpulsNr as Integer)

PositionChange(PositionListe as Variant)

Page 29: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.2. TEXTBASIERTE PROGRAMMIERSYSTEME 23

InterfaceStatus(Quelle as Integer)

Die ersten beiden dienen zur �Uberwachung des Status der Methoden Wait-

ForChange(InputNr, NrOfChanges) und MoveTo/MoveDelta (Bewegung eines

Motors f�ur eine bestimmte angegeben Anzahl von Impulsen) und werden nur

ausgel�ost, wenn gerade die entsprechende Methode abgearbeitet und dabei ein

Statuswechsel an den digitalen Eing�angen erkannt wird. Die letzte Methode

wird bei jedem erkannten Statuswechsel der igitalen Eing�ange aufgerufen.

Die Dokumentation von FishFace (M�uller, 2000) macht keine explizite Aus-

sage �uber die Implementierung von FishFace im Zusammenhang mit Threads.

Prinzipiell scheint das Interface-Objekt keinen eigenen Thread zu besitzen, der

sich um das Interface k�ummert. Ruft man keine Methode auf, so "verstum-

men" die Motoren des Interfaces bald. Dies w�urde nicht passieren, wenn z.B.

st�andig die Inputs abgefragt w�urden. Daraus folgt, da� diese nur dann abge-

fragt werden, wenn man entweder selbst irgendwelche Methoden aufruft, das

Diagnose-Panel aktiviert oder die Kontrolle durch Ausf�uhrung der Methoden

WaitForChange/Low oder MoveTo/MoveDelta an das Interface abgibt.

Spirit.ocx

Von Lego gibt es das Active-X Control Spirit.ocx (The LEGO Group, 1998)

welches, unter Windows z.B. aus Visual Basic heraus, Zugang zur jeweiligen

Roboterhardware bietet. Es ist ziemlich genau auf die F�ahigkeiten der Standard-

Firmware von Lego abgestimmt, was aber auch nicht weiter verwundert. Da

z.B. auch der Lego Cybermaster eine �ahnliche Firmware enth�alt, funktioniert

Spirit.ocx f�ur diesen ebenfalls. Die Interface-Hardware wird durch ein Objekt

repr�asentiert, welches die gesamte Funktionalit�at enth�alt.

Es gibt nat�urlich Funktionen um die Sensoren abzufragen oder die Motoren

zu beein ussen. Das eigentlich besondere ist aber, da� Spirit.ocx auch einen

Modus kennt, in welchem die aufgerufenen Funktionen nicht sofort ausgef�uhrt,

sondern als Task auf den Brick �ubertragen werden. Da f�ur diesen Modus auch

Funktionen wie "if" und "while" zur Verf�ugung stehen, k�onnen auf diese Weise

"richtige" Programme entwickelt werden. Dieser Code ist zwar nicht mehr sch�on

anzusehen, aber einige Systeme beruhen auf dieser F�ahigkeit und stellen den

Code einfach eleganter dar. So soll z.B. das in Abschnitt 3.1.2 auf Seite 19 vor-

gestellte RCX-Code auf Spirit.ocx beruhen und "Gordon's Brick Programmer"

(http://www.umbra.demon.co.uk/gbp.html) stellt ein solches Programm z.B.

als einen attributierten Baum dar.

Inzwischen stellt Lego einen neueren PC-basierten Treiber namens Ghost

bereit. Dieser konnte jedoch f�ur die vorliegende Arbeit nicht mehr untersucht

werden.

Java-package "ft"

Das Java-package "ft" (Schreiner, 2000b) funktioniert im Prinzip auf allen

Plattformen, f�ur die eine Implementierung des Java Communications API (Sun

Microsystems, 1998) existiert. Dies gilt nur f�ur die Ansteuerung des Intelligent

Interface. Das parallele Interface wird nur unter Windows direkt unterst�utzt.

Page 30: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

24 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Das "ft"-package geht schon recht weit in die Richtung die auch mit dieser

Arbeit angestrebt wird. Es ist bereits eine Bibliothek von mehreren Klassen.

Gra�sche Views und Controls, sowie Model-Objekte f�ur Motoren sowie die ana-

logen und digitalen Eing�ange. Es bietet zudem ein Observer-Modell mit Events

von Motoren und den digitalen und analogen Eing�angen.

Ein Steuerungsalgorithmus ist prim�ar als Unterklasse von ft.Controller

vorgesehen. Eine Abweichung von diesem Schema w�urde sofort zu einem erh�oh-

ten Arbeitsaufwand f�uhren. Eigene Threads und deren Synchronisierung sind

nat�urlich ganz normal wie in Java �ublich verwendbar.

Das "ft"-package liefert jedoch kaum Konzepte f�ur die Wiederverwendung

des Steuerungsalgorithmus, zumindest nicht �uber Modell-, bzw. Interface-Gren-

zen hinweg. Zudem wird die an die Ein- und Ausg�ange angeschlossene Periphe-

rie immer als ein Motor oder ein digitaler, bzw. analoger, Sensor angesehen.

Eine Unterscheidung zwischen z.B. einer Lampe und einem Motor wird nicht

gemacht. Daf�ur ist es aber recht schnell, denn f�ur Windows ist sogar ein eigener

spezialisierter JavaComm-Treiber f�ur die serielle Schnittstelle enthalten, der die

recht langsame Implementierung von Sun umgeht.

3.2.2 Sprachen f�ur die Lego-Firmware

Auf den Brick k�onnen leicht Programme geladen werden, die dort lokal zur

Ausf�uhrung gebracht werden. Dies geschieht entweder unter Verwendung von

Spirit.ocx, oder "per Hand", da das Format, welches die Standard-Firmware

von Lego verwendet, bekannt ist. Darauf werden nun viele Sprachen, bzw. Pro-

grammierumgebungen aufgesetzt. Am bekanntesten ist wohl NQC (http://

www.enteract.com/~dbaum/nqc/), das eine C-�ahnliche Syntax und einen eben-

solchen Pr�aprozessor verwendet und einem praktisch alle M�oglichkeiten er�o�-

net, die in der Original-Firmware von Lego existieren. Lego hat inzwischen

auch eine eigene textbasierte Sprache namens MindScript die auf dem von Le-

go nun in der Version 2.0 ausgelieferten Betriebssystem f�ur den Brick basiert

(http://mindstorms.lego.com/sdk2/). MindScript soll laut Lego zudem als

Zwischenformat f�ur gra�sche Systeme verwendet werden.

Die neue Lego-Firmware bietet kon�gurierbare Events und ist im Zusam-

menhang mit Variablen wesentlich leistungsf�ahiger geworden. Es gibt nun auch

lokale Variablen innerhalb eines Tasks. Diese neuen Features werden auch von

NQC unterst�utzt.

F�ur die Programmierung nach dem Subsumption-Konzept ist die neu ein-

gebaute M�oglichkeit, den Zugri� einzelner Tasks auf bestimmte Ressourcen

abh�angig von deren Priorit�at zu regeln, besonders interessant.

Listing 1:

acquire(acquire turnMotor) {monitor(EVENT MASK(nullPositionReachedEvent)

| EVENT MASK(maxPositionReachedEvent)) {PlayTone(3000, 20);SetDirection(turnMotor, rightDirection);On(turnMotor);

Page 31: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.2. TEXTBASIERTE PROGRAMMIERSYSTEME 25

Listing 1: (Fortsetzung)

do {Wait(10);sees light right(result);

} until(result == 0);} catch {

Off(turnMotor);}

} catch {}

Listing 1 zeigt die Verwendung von Events und der Zugri�skontrolle in NQC.

Es stammt aus dem Beispiel-Programm f�ur LiSe. Mit acquire wird auf die im

Argument angegebene Ressource Zugri� verlangt. Wenn kein anderer Task mit

h�oherer Priorit�at Zugri� auf diese Ressource verlangt, wird der Block hinter

acquire ausgef�uhrt, andernfalls springt die Ausf�uhrung zu dem korrespondie-

renden catch-Block. Der Sprung zum catch erfolgt auch aus dem acquire-

Block heraus, falls sp�ater ein Task mit h�oherer Priorit�at die Ressource f�ur

sich beansprucht. Tasks k�onnen also in gewisser Weise dadurch unterbrochen

werden. Das monitor-Statement funktioniert �ahnlich, zur genaueren Erkl�arung

wird auf das Manual zu NQC verwiesen (Baum, 2001).

3.2.3 Systeme mit eigener Firmware

F�ur den Brick gibt es mehrere alternative Betriebssysteme (Firmware), welche

man verwenden kann, um die Standard-Firmware von Lego zu ersetzen. Der

erste, der es gescha�t hat ein von LEGO unabh�angiges, lau��ahiges System im

Internet bereitzustellen, war wohl Kekoa Proudfoot (Proudfoot, 1998). Zu den

Systemen, die mit einer solchen Ersatz-Firmware kommen, z�ahlen vor allem:

� legOS von Markus L. Noga

� pbForth von Ralph Hempel

� leJOS von Jose L. Solorzano

In diesem Abschnitt werden legOS und pbForth vorgestellt. leJOS wird,

wegen seiner Java-F�ahigkeiten, besonders ausf�uhrlich in Abschnitt 3.2.4 auf

Seite 27 behandelt.

legOS

Das Betriebssystem, welches { in Bezug auf Geschwindigkeit und Speicher-

haushalt { auf dem Brick am besten abschneidet, ist legOS (http://legos.

sourceforge.net/). Es wurde urspr�unglich von Markus L. Noga entwickelt

(Noga, 1999). legOS verwendet eine Version des GNU C-Compilers (gcc) die

Code f�ur den Hitachi H8 Mikroprozessor des Brick erzeugt. F�ur die Verwen-

dung spezieller Peripherie des Brick, wie den Ein- und Ausg�angen, IR-Port,

LCD und Sound enth�alt es entsprechende, spezialisierte Bibliotheken.

Page 32: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

26 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Wo es ging wurde versucht POSIX-Konform zu bleiben. Neue Prozesse wer-

den mit fork() erzeugt und Zeichenketten mit cputs() ausgegeben, um nur ein

paar Beispiele zu nennen. Nat�urlich gibt es au�er der Speichergr�o�e des Brick

keine Beschr�ankungen in Bezug auf die Anzahl oder den Typ von Variablen.

Die direkte Verwendung der Hardware, ohne irgendwelche Umwege, macht le-

gOS so schnell, da� es hei�t, man k�onnte sogar Sprache damit samplen { wenn

einem nicht bereits nach ein paar Sekunden der Speicher ausgehen w�urde.

Die Tools von legOS zur Kommunikation zwischen Brick und PC, die man

braucht um beispielsweise ein ausf�uhrbares Programm zu laden, gibt es lei-

der nur f�ur Windows und Linux. Sowohl MacOS und andere Unix-Systeme als

Linux werden nicht unterst�utzt, da die Tools dort wegen einer anderen I/O-

Schnittstelle bisher nicht laufen (Baum et al., 2000, S. 152).

Neben der Geschwindigkeit ragt als Besonderheit auch noch die Netzwerk-

Schicht LNP3 hervor. Sie unterst�utzt eine paketbasierte Kommunikation zwi-

schen einem PC mit IR-Tower und mehreren addressierbaren Bricks.

Was gegen legOS spricht, sind die Gr�unde, die auch gegen eine Verwendung

von C auf einem Betriebssystem wie Linux sprechen. Es ist einfach schwieriger

in C fehlerfrei zu programmieren, als das z.B. mit Java der Fall ist. Wenn es

also auf eine extrem hohe Geschwindigkeit nicht ankommt und z.B. der Inter-

aktivit�at oder dem Software-Design ein gr�o�erer Stellenwert einger�aumt wird,

dann haben die anderen Systeme wie pbForth und leJOS die Nase vorn.

pbForth

Forth ist eine bereits recht alte Programmiersprache, die speziell daf�ur ent-

wickelt wurde, um Computer mit wenig Ressourcen zu bedienen (Baum et al.,

2000, S. 70�). Forth gibt es daher f�ur eine Vielzahl von kleinen Computersy-

stemen, doch auch f�ur z.B. Linux ist Forth (gForth) verf�ugbar.

Das besondere an pbForth (http://www.hempeldesigngroup.com/lego/

pbForth/homePage.html) gegen�uber allen anderen Betriebssystemen f�ur den

Brick ist seine Interaktivit�at. Wenn man den Brick mit pbForth programmiert,

wird ein PC nur als Terminal f�ur die Konsole von pbForth verwendet. Alles, was

man tippt, landet direkt im Brick und wird dort St�uck f�ur St�uck interpretiert.

Das er�o�net v�ollig neue M�oglichkeiten zum Testen, da man alles direkt "online"

ausprobieren kann und sofort eine R�uckmeldung bekommt.

In Forth verwendet man sogenannte words um Werte auf einem Stack zu

manipulieren. Diese Art zu programmieren ist im Vergleich zu "normalen" Pro-

grammiersprachen recht unkonventionell und erfordert daher in vielen F�allen

eine ganz andere Denkweise. Da Forth interaktiv ist kann man sehr bequem

ausprobieren. Dadurch macht das Lernen mehr Spass.

Man kann neue Funktionen in Form von weiteren words hinzuf�ugen. Mehrere

Threads sind nur mittels kooperativem Scheduling m�oglich und erfordern daher

eine sehr sorgf�altige Planung. Da pbForth eine Stack-Maschine ist, m�usste man

im Prinzip auch andere Sprachen f�ur pbForth �ubersetzen k�onnen.

3'NP' steht f�ur Networking Protocol, �uber die Bedeutung des 'L' gibt es hingegen je nach

Quelle unterschiedliche Au�assungen (Lego, legOS, layered, . . . ).

Page 33: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.2. TEXTBASIERTE PROGRAMMIERSYSTEME 27

3.2.4 leJOS

Auf der ROM interface library librcx von Kekoa Proudfoot (Proudfoot, 1998)

beruht auch die Variante eines Betriebssystems f�ur den Brick die mit Java

programmiert werden kann: leJOS (http://lejos.sourceforge.net/).4

Es gibt noch mindestens ein weiteres Projekt um Java direkt auf dem Brick

ausf�uhrbar zu machen, doch ist es noch in einem sehr unvollst�andigen Stadium

(RCXJVM, http://misc.traveller.com/rcxjvm/). Es sieht zudem so aus,

als h�atte sich dort schon seit l�angerer Zeit nichts mehr getan.

Der Vorl�aufer von leJOS hei�t tinyVM und wird nicht mehr, bzw. nur noch

minimal weiterentwickelt. tinyVM enth�alt weniger Features, hat daf�ur aber auch

einen etwas kleineren footprint : 10KB, gegen�uber 16KB f�ur leJOS. Da der Brick

insgesamt nur �uber 32KB Speicher verf�ugt und das ROM (bzw. das Betriebs-

system) au�erdem eine gewisse Menge zus�atzlichen Speicher braucht, bleiben

f�ur ein Anwendungsprogramm unter leJOS nur etwa 10KB Speicher �ubrig. F�ur

das komplette hier vorgestellte Beispielprogramm f�ur Ariadne ist das bereits zu

knapp, doch dazu am Ende dieses Abschnitts mehr.

Inzwischen (Version 1.0.4.alpha) existiert in der Distribution von leJOS ein

neues package (josx.robotics) welches Klassen zur Navigation eines Roboters

und zur Programmierung nach dem Subsumption-Konzept (siehe 1.2 auf Sei-

te 4) enth�alt. Die Beispielprogramme f�ur Trusty, LiSe und Ariadne verwenden

diese nicht, da bereits eigene (wenn auch einfachere) Klassen f�ur diese Funktio-

nalit�at vorhanden waren. Nichtsdestotrotz zeigt es, da� die im Rahmen dieser

Arbeit verwendeten Beispiele durchaus typische Aufgaben und Probleme adres-

sieren.

Modularisierung & Wiederverwendung

Wenn man einmal von den geringen Ressourcen absieht, die einem unter le-

JOS zur Verf�ugung stehen, hat man (fast) alle M�oglichkeiten die einem die

Sprache Java bietet. Verst�andlicherweise ist aber nicht das komplette API von

Java implementiert, sondern nur die n�otigsten Klassen und auch dort nur die

wichtigsten Methoden.

Es ist aber kein Problem, mehrere Klassen zu erstellen. Alle notwendigen

Java-Features sind vorhanden, auch innere Klassen sind kein Problem (was

aber, angesichts der Tatsache, da� innere Klassen ein Compiler-Feature und kein

Runtime-Feature von Java sind, auch eher verwundern w�urde). Das Einzige was

einem imWeg steht ist der begrenzte Speicher und manche Limitierung des API

zum Zugri� auf die besondernen Eigenschaften des Brick, wie z.B. die Motoren

oder Sensoren (package josx.platform.rcx).

Als Basis f�ur mobile Roboter kann z.B. die folgende Klasse DriveTrain

verwendet werden:

4Und es ist wahrscheinlich das einzige Betriebssystem f�ur den Brick,

das man mit Fug und Recht als "weltraumtauglich" bezeichnen kann. Sie-

he Artikel in der Online-Ausgabe der S�uddeutschen Zeitung vom 14.12.2001:

http://www.sueddeutsche.de/computer/neuetechnik/hardware/32701

Page 34: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

28 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Listing 2: code/leJOS/DriveTrain.java

public class DriveTrain {// note that this is not a josx.platform.rcx.Motorprotected Motor leftMotor;protected Motor rightMotor;

public DriveTrain(Motor leftMotor, Motor rightMotor) {this.leftMotor = leftMotor;this.rightMotor = rightMotor;

}

public void forward() {leftMotor.forward();rightMotor.forward();

}

public void backward() {leftMotor.backward();rightMotor.backward();

}

public void leftSpin() {leftMotor.backward();rightMotor.forward();

}

public void rightSpin() {leftMotor.forward();rightMotor.backward();

}

public void stop() {leftMotor.stop();rightMotor.stop();

}}

In DriveTrain wird die Koordination von zwei Motoren in der Anord-

nung wie bei Trusty gekapselt. Sie bietet einfacher verwendbare und verst�and-

lichere Methoden wie forward(), um den Roboter vorw�arts zu bewegen, oder

leftSpin() um den Roboter linksherum um die eigene Achse zu drehen.

Doch bereits wenn man die Motoren andersherum gepolt anschlie�t, funk-

tioniert diese Klasse nicht mehr, denn forward() ist dann ja die andere Dreh-

richtung. Hat man bei der Polung aus irgendeinem Grund nicht die Wahl (ganz

profan: Das Kabel kann f�ur eine andere Polung manchmal zu kurz sein), m�ochte

man im Grunde DriveTrain daf�ur nicht editieren m�ussen. Es w�are besser die

Polung in Software zu kapseln, indem man einem Motor mitteilen kann, welche

Drehrichtung "forward" sein soll.

Die in leJOS verhandene Klasse zur Ansteuerung eines Motors (josx.plat-

form.rcx.Motor) bietet eine solche M�oglichkeit nicht. Eine �ubliche Vorgehens-

weise um das nachzur�usten w�are, eine Unterklasse von josx.platform.rcx.

Page 35: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.2. TEXTBASIERTE PROGRAMMIERSYSTEME 29

Motor zu entwickeln. Sie besitzt eine neue Methode wie z.B. setReversed(boo-

lean) um die Polung anzugeben und leitet die Aufrufe wie forward() an die

jeweils passende backward()- oder forward()- Methode ihrer Unterklasse wei-

ter.

Da aber alle Methoden von josx.platform.rcx.Motor final deklariert

sind, ist dieser Weg verbaut. Den Grund f�ur die Wahl von final kann man

wohl folgendem Auszug aus den "performance-tips" von tinyVM entnehmen:

"Declare your methods to be either private, �nal or static when-

ever possible."

Man kann Instanzen von josx.platform.rcx.Motor auch gar nicht selbst

erzeugen, da der einzige Konstruktor der Klasse private deklariert ist und es

keine Klassenmethode gibt, die eine indirekte Konstruktion erm�oglichen w�urde.

Es existieren nur die drei Klassenvariablen A, B und C (jeweils vom Typ josx.

platform.rcx.Motor) { eine f�ur jeden Ausgang des Brick. Das Erstellen einer

Unterklasse ist daher nicht m�oglich, da diese auf wenigstens einen Konstruk-

tor zugreifen k�onnen m�usste. Die Klasse josx.platform.rcx.Motor h�atte also

ebensogut final deklariert werden k�onnen.

Aus diesem Grund wurde eine komplett neue Klasse geschrieben, die nicht

von josx.platform.rcx.Motor abstammt und daher auch nicht verwendet

werden kann, als w�are sie ein josx.platform.rcx.Motor { ein wichtiger Me-

chanismus der Objektorientierung ist damit ausgehebelt. Diese Klasse hat einen

josx.platform.rcx.Motor als Ziel, an den sie alle ben�otigten Methoden ex-

plizit weiterleitet und in Bezug auf die Drehrichtung die erw�ahnte Anpassung

vornimmt.

Leider sind diese Probleme auch bei der Sensor-Klasse, sowie der Klasse

Button, mit der die vier Kn�opfe des Brick abgefragt werden k�onnen, vorhanden.

Die meisten anderen Klassen aus dem package josx.platform.rcx, wie z.B.

zum Zugri� auf das eingebaute Display oder zur Ausgabe von T�onen, bieten

nur Klassenmethoden und sehen keine Instanz vor.

Das hei�t, Modularisierung ja, aber Wiederverwendung nur eingeschr�ankt,

da Rechenzeit und Speicher so knapp ist, da� daf�ur o�enbar nicht alle M�oglich-

keiten, die Java bietet, ausgesch�opft werden (k�onnen).

Threads & Synchronisierung

Die Klasse java.lang.Thread ist in leJOS vorhanden und bietet nicht nur die

M�oglichkeit neue Threads zu erzeugen, sondern man kann diesen auch verschie-

dene Priorit�aten zuweisen, sie unterbrechen und ein Thread kann auch �uber

yield() oder sleep() in der Ausf�uhrung zwischendurch anhalten. Es gibt so-

gar daemon-Threads, welche die virtuelle Maschine nicht am laufen halten und

somit daf�ur gedacht sind, "unbemerkt" im Hintergrund ablaufen zu k�onnen.

Verschiedene Threads werden in Java �uber einen Mechanismus synchroni-

siert, bei dem ein Thread einen sogenannten Monitor f�ur ein Objekt besitzen

kann. Diesen Monitor kann zu einem Zeitpunkt nur ein Thread besitzen, womit

die Synchronisierung bewerkstelligt wird. Den Monitor f�ur ein Objekt bekommt

ein Thread, w�ahrend er einen synchronized-Block ausf�uhrt, bzw. wenn er eine

Page 36: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

30 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Methode ausf�uhrt, die mit dem Schl�usselwort synchronized deklariert wur-

de. Das Objekt, auf das synchronisiert wird, ist im Falle der synchronized-

Methode das Objekt dessen synchronized-Methode gerade ausgef�uhrt wird,

bzw. das Klassenobjekt der Klasse die die Methode implementiert, wenn es sich

um eine Klassenmethode handelt. Im Falle des synchronized-Block wird das

Objekt, auf das synchronisiert werden soll, explizit angegeben. Da es in leJOS

keine Klassenobjekte gibt, wird das Synchronisieren auf ein solches, z.B. �uber

eine synchronized deklarierte Klassenmethode, nicht funktionieren.

Die Methoden wait() und notify() sind seit Version 1.0.2 vom 4.9.2001

implementiert, womit einer vollst�andigen Ausnutzung der Synchronisations-

m�oglichkeiten von Java nun nichts mehr im Wege steht. F�ur die Beispielim-

plementierung von Ariadne wurde aber noch keine explizite Synchronisierung

verwendet, so da� hier daf�ur kein Beispiel gezeigt wird, solche m�ussten sich aber

eigentlich in jedem Lehrbuch zu Java �nden lassen.

Um einen Algorithmus mit Subsumption (siehe 1.2 auf Seite 4) zu program-

mieren bieten sich wait() und notify() an. Wer daran Interesse hat, kann z.B.

die f�ur Subsumption im Beispiel verwendete Klasse SubsumptionScheduler

entsprechend umschreiben.

Events

F�ur die Kn�opfe und f�ur die Sensoren des Brick gibt es in leJOS die M�oglichkeit

�ahnlich wie beim AWT von Java sogenannte ButtonListener, bzw. Sensor-

Listener zu verwenden. Sobald eine �Anderung des Werts des jeweiligen Sensors

aufgetreten ist, bzw. der entsprechende Knopf gedr�uckt oder losgelassen wurde,

wird die in den Listener-Interfaces de�nierte Methode aufgerufen. Im Unter-

schied zum AWT gibt es aber keine eigene Klasse, die die zum Event geh�orenden

Daten repr�asentiert, sondern es wird nur die Quelle des Events, sowie bei den

SensorListenern der alte und der neue Wert �ubergeben.

Der Aufruf der Listener-Methoden erfolgt aus einem Thread heraus, wel-

cher automatisch erzeugt wird, wenn er wegen des Vorhandenseins von Listenern

ben�otigt wird. Da die Methoden wait() und notify() inzwischen implemen-

tiert sind, existieren optimale Voraussetzungen, um weitere Threads auf belie-

bige Ereignisse warten zu lassen, ohne da� sie unn�otig Rechenzeit verbrauchen.

Dies kann man z.B. verwenden, wenn man beim Auftreten eines bestimmten

Ereignisses eine l�angere Berechnung "ansto�en" m�ochte. Wie beim AWT auch,

sollten n�amlich die Listener-Methoden recht z�ugig zuende gehen, da f�ur meh-

rere Listener nur ein einziger Thread vorhanden ist.

Ein Design von LiSe mit mehreren Listenern (jede der Verhaltensweisen hat

einen "eigenen" f�ur die von ihr verwendeten Sensoren) st�o�t an eine Grenze. Die

Klassen Button und Sensor erlauben nur maximal vier Listener. Damit wird

aber eine Modularisierung erschwert, denn wenn ein anderes Modul auch Liste-

ner verwendet, so k�onnen es schnell mehr als vier werden, wenn man nicht genau

aufpasst, welches Modul f�ur welchen Sensor wieviele Listener registriert. Damit

werden die Grenzen zwischen den Modulen "verschmiert", da sie im Grunde un-

gewollt aufeinander Ein uss nehmen. Daher ist es bei Algorithmen in Bezug auf

die m�ogliche Wiederverwendung besser, weitestgehend auf die Verwendung von

Page 37: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.2. TEXTBASIERTE PROGRAMMIERSYSTEME 31

Listenern zu verzichten, bzw. einen eigenen Event-Mechanismus zu implemen-

tieren (z.B. mittels der Klasse Poll, die so etwas wie den Unix-Systemaufruf

select f�ur Sensoren darstellt).

Ariadne

Der Algorithmus f�ur den Beispielroboter ist in Klassen f�ur Trusty, LiSe und

Ariadne aufgeteilt, sowie in drei weitere Klassen. Dies sind die bereits gezeigte

Klasse DriveTrain, zur Kapselung des Antriebsmechanismus von Trusty, die

bereits erw�ahnte Klasse Motor, die einen "umpolbaren" Motor repr�asentiert,

und eine Klasse zur Koordination der einzelnen Verhaltensweisen bei Subsump-

tion (siehe Abschnitt 1.2 auf Seite 4). Sowohl Trusty als auch LiSe sind nach

dem Subsumption-Konzept programmiert worden. Einzeln funktionieren LiSe

und Trusty auch sehr gut. Es ist auch sehr sch�on m�oglich, Trusty und LiSe f�ur

Ariadne wiederzuverwenden, doch leider ist die Implementierung von Ariadne

so nicht lau��ahig { leJOS geht schlicht der Speicher aus.

Man kann Ariadne aber trotzdem ausf�uhren. Kurz bevor es zu dem Out-

OfMemoryError kommt, h�alt die Ausf�uhrung an und gibt auf dem Display des

RCX das Resultat von System.freeMemory() aus. Nach einem Druck auf die

"Prgm"-Taste (nach einer kurzen Wartezeit) wird das Ergebnis von System.

totalMemory() ausgegeben. Weiteres Dr�ucken auf "Prgm" (mehrmals) f�uhrt

dazu, da� letztenendes die Ausf�uhrung bei dem OutOfMemoryError ankommt.

Dabei wird ganz rechts im Display des Brick die Zahl, die normalerweise die

Nummer des aktuellen Programms anzeigt, hochgez�ahlt. So kann man, wenn

man dabei den Code der Methode start() in Ariadne.java anschaut, ganz

gut erkennen wo der OutOfMemoryError auftritt:

Listing 3: code/leJOS/Ariadne.java

public void start() {// just show memory and ’step’ by pressing the PRGM-Button// because this method results in an OutOfMemoryError// on leJOS 1.0.4.alphaLCD.showProgramNumber(1);LCD.showNumber((int)System.getRuntime().freeMemory());try {

Button.PRGM.waitForPressAndRelease();} catch (InterruptedException ie) {}LCD.showProgramNumber(2);LCD.showNumber((int)System.getRuntime().totalMemory());try {

Button.PRGM.waitForPressAndRelease();} catch (InterruptedException ie) {}LCD.showProgramNumber(3);try {

lise.start();} catch(OutOfMemoryError e) {

LCD.showProgramNumber(4);➥

Page 38: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

32 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Listing 3: code/leJOS/Ariadne.java (Fortsetzung)

try {Button.PRGM.waitForPressAndRelease();

} catch (InterruptedException ie) {}throw e;

}try {

super.start();} catch(OutOfMemoryError e) {

LCD.showProgramNumber(5);try {

Button.PRGM.waitForPressAndRelease();} catch (InterruptedException ie) {}throw e;

}}

Die Beispiele wurden nicht auf Speicherverbrauch optimiert entwickelt. So

wird z.B. in der Implementierung von Ariadne Speicher "verschwendet", weil

Instanzenvariablen von Trusty neue Objekte zugewiesen bekommen. Die alten

Objekte k�onnten im Grunde aus dem Speicher verschwinden, da sie nicht mehr

gebraucht werden, doch in leJOS ist keine garbage collection implementiert.

Die fehlende garbage collection vereinfacht die Realisierung von leJOS, vor

allem in Bezug auf vorhersagbare Ausf�uhrungs- und damit auch Reaktionszei-

ten. Dies steht aber einer modularen, objektorientierten Entwicklung etwas im

Weg, denn man darf z.B. nicht f�ur jedes Ereignis ein neues Objekt erzeugen.

Der Algorithmus f�ur die garbage collection wird oft mit mark-sweep realisiert

und darf in diesem Fall, wenn die garbage collection erst einmal in Bewegung

gesetzt wurde, nicht mehr unterbrochen werden. Dieses Problem ist f�ur Java in

Bezug auf Echtzeitf�ahigkeit nicht ungew�ohnlich (Brich et al., 2000).

Auf den Abdruck des restlichen Codes wurde verzichtet. Dieser Abschnitt

ist ja auch nicht als Tutorial f�ur die Benutzung von leJOS gedacht. Der in-

teressierte Leser mag aber vielleicht in die beiliegenden Quellen schauen und

seine eigenen Versuche mit leJOS durchf�uhren. Ob es wohl m�oglich ist, einen in

eigenst�andige Trusty- und LiSe-Klassen aufgeteilten Algorithmus zu schreiben,

der f�ur Ariadne wiederverwendet werden kann, so da� trotzdem der Speicher

reicht?

3.3 Vorl�au�ges Fazit

Es ist bereits m�oglich Roboter objektorientiert zu programmieren. M�ogliche Sy-

steme f�ur Lego und Fischertechnik sind z.B. Spirit.ocx/Fishface (Windows/VB,

VC++), legOS (C++), leJOS (Java). Dies gilt aber nur f�ur die grunds�atzlichen

M�oglichkeiten, die die jeweiligen Sprachen bieten. In Bezug auf die Schnittstel-

le zum Roboter werden die M�oglichkeiten von Objektorientierung nicht ausge-

nutzt. Nur leJOS, legOS und das Java-package "ft" bieten echte Klassen f�ur

Page 39: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

3.3. VORL�AUFIGES FAZIT 33

Sensoren und Motoren. Bei leJOS ist aber z.B. keine wirkliche �Unterst�utzung

f�ur Unterklassen davon vorhanden und legOS hat noch nicht einmal richtige

Motor-Klassen. Das ft-package wiederum hat zwar vern�unftige Klassen f�ur Sen-

soren und Motoren, bietet aber nur die allern�otigtste Funktionalit�at und keine

Unterscheidung zwischen verschiedenen Sensoren oder anderen an die Ausg�ange

angeschlossenen Aktuatoren.

Die Unterst�utzung eines Event-Mechanismus nimmt hingegen zu. Selbst das

Standard-System von Lego hat seit der neuesten Verion (RCX 2.0) eine Form

von Events integriert, so da� alle darauf beruhenden Systeme wie z.B. Mind-

Script und NQC die Verwendung von Events unterst�utzen.

Die Verwendung von Threads ist teilweise recht einfach umgesetzt (LL-

Win/leJOS) und wird von praktisch allen Systemen erlaubt. Leider existieren

aber meistens nur unzureichende Kontrollmechanismen (Synchronisierung). An-

dere Systeme als die Java-basierten bieten zwar auch Synchronisierung, sind

aber schwieriger zu benutzen (pbForth/legOS).

Wenn die jeweilige Sprache eine Modularisierung und Abstrahierung un-

terst�utzt, ist diese, solange es auf Performance oder Gr�o�e wirklich ankommt,

wenn �uberhaupt nur unsauber zu realisieren (siehe Performance-Tips zu ti-

nyVM: http://tinyVM.sourceforge.net/userguide.html). Gerade die gra-

�schen Systeme sind jedoch einfach nicht f�ur sehr umfangreiche Software-Pro-

jekte ausgelegt. Wird die Software lokal auf dem Brick ausgef�uhrt, wiegen Fak-

toren wie verf�ugbarer Platz und Rechenkapazit�at in vielen F�allen auch schwerer,

d.h. um m�oglichst weitgehende Modularisierung und Abstraktion zu erm�ogli-

chen, ist f�ur die Roboterhardware von Lego und Fischertechnik eine Steuerung

von einem externen Computer aus notwendig.

In Bezug auf die Hardware-Unabh�angigkeit der Systeme kommt es zum Teil

auf die Sichtweise an: iCon-L/LabView gibt es f�ur verschiedene Hardware und

viele Systeme isolieren die hardware-abh�angige Schnittstelle, wie z.B. leJOS,

das daf�ur ein separates package (josx.platform.rcx) enth�alt. Die eigentliche

Schnittstelle zu der Hardware ist aber nirgendwo abstrahiert. Es wird immer f�ur

ein bestimmtes Zielsystem programmiert, da die Verwendung von Motoren und

Sensoren immer unterschiedlich und sehr auf die konkrete Hardware bezogen

umgesetzt ist. Nat�urlich kann man einige der Systeme mit viel Eigenarbeit auch

benutzen um portabel zu programmieren, man wird dabei aber nicht gezielt

unterst�utzt und w�urde, bei den lokal auf dem Brick ausgef�uhrten Systemen,

auch schnell an Kapazit�atsgrenzen sto�en.

Page 40: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

34 3. PROGRAMMIERSYSTEME F�UR ROBOTER

Page 41: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4

Die Idee des Abstract Robot

Toolkit

Wenn in dieser Arbeit von Robotern die Rede ist, so ist das in gewisser Weise

sehr allgemein gemeint. Zu dem Begri� Roboter wei� die Encyclop�dia Britan-

nica (www.britannica.com) Folgendes zu sagen:

"Any automatically operated machine that replaces human ef-

fort, though it may not resemble human beings in appearance or

perform functions in a humanlike manner. The term is derived from

the Czech word robota, meaning 'forced labour'. Modern use of the

term stems from the play R.U.R., written in 1920 by the Czech aut-

hor Karel Capek, which depicts society as having become dependent

on mechanical workers called robots that are capable of doing any

kind of mental or physical work."

Nach dieser De�nition kann bereits ein Computer als Roboter aufgefa�t

werden. Ein Roboter im Sinn dieser Arbeit besitzt Sensoren (wie z.B. einen

Licht- oder einen Ber�uhrungssensor), mit denen die Umwelt wahrgenommen

wird, und Aktuatoren (wie z.B. einen Motor oder eine Lampe), mit denen auf

die Umwelt Ein u� genommen werden kann. Die Aktuatoren werden von einem

Algorithmus gesteuert, der mehr oder weniger von den Messungen der Senso-

ren abh�angt. Diese Sichtweise auf das, was einen Roboter ausmacht, pa�t gut

zu Robotern wie man sie mit den Lego- und Fischertechnik-Bauk�asten bauen

kann. Die Bauk�asten enthalten Sensoren und Motoren und einen kleinen Com-

puter f�ur den Steuerungsalgorithmus, bzw. ein Hardware-Interface, �uber das ein

"richtiger" PC die Steuerung �ubernehmen kann.

Interessanterweise ist dieses Konzept der Sensoren und Aktuatoren im Grun-

de auch auf jede andere Maschine anwendbar, die genau genommen sogar nicht

einmal computergesteuert sein mu�. Diese Au�assung steht einem auch nicht im

Weg, wenn man sich von dem externen Hardware-Interface entfernt und wieder

den Computer an sich bereits als Roboter au�a�t. Im Grunde sind eine Tasta-

tur und eine Maus auch nichts weiter als Sensoren, genauso wie ein Bildschirm,

Drucker oder Lautsprecher im Prinzip als Aktuatoren aufgefa�t werden k�onnen.

Doch um die Arbeit nicht ausufern zu lassen, werden Sensoren und Aktuatoren

35

Page 42: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

36 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

Actuator

setValue(...)

Algorithmkeeps state

in syncinforms about

state−change

output−state

may depend on

input−state

setting of

Input2

Output1

Output2

Input1

RobotInterface

Sensor

addListener(...)

getValue()

Classes (Software)Robot (Hardware)

Abbildung 4.1: Regelkreis, wie er durch die Modellierung des Roboters in Software ent-

steht.

vorerst haupts�achlich im engeren, "greifbareren" Sinne verwendet und es wird

nicht genauer untersucht, was diese Sichtweise f�ur die Programmierung eines

Computers an sich bedeuten kann.

Ziel der Arbeit ist es, ein System zur Roboter-Programmierung zu scha�en,

mit dem Software-Probleml�osungen f�ur Roboter m�oglichst weitgehend wieder-

verwendbar sind. So wie in dem Lego-Baukasten viele Bausteine enthalten sind,

die sich auf vielf�altige Weise immer wieder neu zusammenstecken lassen, sol-

len in dem Programmiersystem Software-Bausteine { als Objekte realisiert {

vorhanden sein, die sich ebenso zusammenstecken lassen. Au�erdem soll ein

einmal gebautes "Ding" mit einer bestimmten Funktion (z.B. ein Chassis f�ur

ein Fahrzeug) als Modul wiederverwendet werden k�onnen. In Hardware mu�

man das zwar meistens immer wieder neu bauen, da der Vorrat an Bausteinen

normalerweise beschr�ankt ist und man die Steine daher zwischendurch f�ur etwas

anderes gebraucht hat, bei Software ist es aber leicht (und billig) etwas einmal

"Gebautes" aufzuheben, f�ur den Fall, da� man es noch einmal brauchen kann.

Der Steuerungsalgorithmus wird sehr gut wiederverwendbar, wenn m�og-

lichst weit von der konkreten Hardware abstrahiert wird. Dies f�uhrt zwar prak-

tisch immer zu einem gr�o�eren Hardware-Aufwand, bzw. einer langsameren

Steuerung, entspricht aber einer Entwicklung, wie sie auch in anderen Berei-

chen der Softwareentwicklung { wie zum Beispiel bei Programmiersprachen {

statt�ndet, bzw. stattgefunden hat. Es ist einfach wesentlich produktiver, Soft-

ware in einer Umgebung wie Java zu entwickeln, als Maschinencode f�ur einen

bestimmten Prozessor von Hand zu schreiben. Ein gro�er Teil der Rechenkapa-

zit�at heutiger Computer wird in diesem Sinne einer schnelleren und beherrsch-

bareren Softwareentwickung "geopfert", wodurch aber komplexere Software erst

erm�oglicht wird.

4.1 Tutebot

Kommt es mehr auf Geschwindigkeit statt auf Flexibilit�at und Wiederverwend-

barkeit an, so k�onnte man auch ganz auf einen Computer verzichten. Ein Ro-

boter, dessen "Steuerungsalgorithmus" rein aus einer Schaltung von diskre-

ten Bauelementen besteht, wird in Jones et al. (1998) beschrieben. Die fertig

aufgebaute Schaltung, montiert auf einem Fischertechnik-Chassis, ist in Abbil-

Page 43: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.1. TUTEBOT 37

dung 4.3 auf der n�achsten Seite dargestellt; Abbildung 4.2 zeigt das Schaltkreis-

Diagramm. Mit dieser Schaltung l�a�t sich ein Roboter wie Trusty steuern, der

mittels Tastsensoren registrierten Hindernissen ausweicht. Die Steuerung ist

aber nur f�ur einen einzelnen Sensor ausgelegt, so da� nicht zwischen einem

Hindernis auf der rechten oder der linken Seite unterschieden wird. Diese Ver-

haltensweise wird auch als wall-following bezeichnet.

Abbildung 4.2: Der Steuerungs-Algorithmus von Tutebot ist mit dieser diskreten Schal-tung realisiert. (entnommen aus Jones et al. (1998))

Solch eine Robotersteuerung durch eine diskrete Schaltung ist sozusagen

die primitivste Form eines Algorithmus. Sie reagiert sehr schnell, ist billig, ver-

braucht wenig Energie und nimmt kaum Platz ein. Daf�ur ist es aber nicht ein-

fach, sich solch eine Schaltung auszudenken (vor allem dann, wenn die Steue-

rungen komplizierter werden), und sie ist sehr un exibel, was Erweiterungen

oder �Anderungen angeht. Au�erdem steht man vor dem gleichen Problem, das

man bereits mit den Lego-, bzw. Fischertechnik-Bausteinen hat: Der Vorrat an

Bauteilen ist begrenzt und um neue Schaltungen zu bauen, mu� man entwe-

der die alten zerst�oren, um an ihre Bauteile zu kommen, oder man mu� st�andig

neue Bauteile nachkaufen. Hebt man also viele solche "Algorithmen" auf, um sie

sp�ater wieder zur Verf�ugung zu haben, geht das entweder nur als Bauplan oder

ist mit erheblichen Kosten verbunden, da man st�andig neue Bauteile kaufen

mu�.

Wenn also auch die Entwicklungszeit wichtig oder der Algorithmus sehr

Page 44: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

38 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

Abbildung 4.3: Die Wei�e Platine ist der "Steuerungsalgorithmus" des Tutebot ausJones et al. (1998). Rechts oben im Bild sieht man die Sensoren, mit denen der Roboterz.B. Tischkanten registrieren kann.

komplex ist, es einfacher sein soll �Anderungen vorzunehmen oder einmal er-

stellte Algorithmen (f�ur eine eventuelle sp�atere Verwendung) aufgehoben wer-

den sollen, nimmt man einen "richtigen" Computer. In der Verbindung zu den

Sensoren und Aktuatoren wird auch dort wieder auf verschiedenen Abstrakti-

onsebenen agiert. So kann man direkt die elektrischen Signale (bzw. das Pro-

tokoll) programmieren, um die Interface-Hardware dazu zu veranlassen, zum

Beispiel einen Motor an- und auszuschalten. H�au�g gibt es auch eine Software-

Schnittstelle, die von den genauen elektrischen Signalen, bzw. dem Kommuni-

kationsprotokoll, abstrahiert. Diese sind dann aber immer noch sehr stark an

die konkrete Hardware angelehnt. So hat man zum Beispiel bei der Verwen-

dung des Active-X Control Spirit.ocx von Lego eine Funktion zur Steuerung

des Power-Level eines Motors zur Verf�ugung, welche es bei den Fischertechnik-

Treibern FishFace oder 30402Drive (die noch am ehesten als mit Spirit.ocx

vergleichbar angesehen werden k�onnen) nicht gibt, da die Interface-Hardware

von Fischertechnik eine Drosselung der Motoren nicht direkt vorsieht.

Mit dem Abstract Robot Toolkit soll noch weiter abstrahiert werden, um

z.B. zu einem Motor immer die gleiche Schnittstelle zur Verf�ugung stellen, egal

ob dieser nun von Lego, Fischertechnik oder irgendeiner anderen Hardware ge-

steuert wird. Das erfordert nat�urlich, sich dar�uber Gedanken zu machen, was

zum Beispiel einen Motor auszeichnet. Welche Funktionalit�at soll ein Motor z.B.

immer aufweisen und welche nur optional? Welche Basisfunktionalit�at ist not-

wendig um alles weitere darauf aufbauend "in Software" realisieren zu k�onnen?

Dies alles kostet nat�urlich Rechenzeit und Speicherplatz im Computer. Au-

�erdem wird der komplette Vorgang weniger transparent, denn es ist nicht mehr

Page 45: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.2. FISCHERTECHNIK UND LEGO MINDSTORMS 39

so leicht, wirklich alles, jede Komponente, die an der Steuerung beteiligt ist,

zu verstehen. In gewisser Weise ist das eine �ahnliche Entwicklung wie bei Pro-

grammiersprachen: von Assembler �uber C bis Java.

4.2 Fischertechnik und Lego Mindstorms

Axel Schreiner entwickelte im Sommer 1998 eine Art "Java-Treiber" f�ur das

parallele Interface von Fischertechnik und stellte dabei fest, da� sich Konzepte

wie Events, Objekte und Threads fast schon auf nat�urliche Weise im Zusam-

menhang mit den Fischertechnik-Robotern verwenden lie�en.

Bereits kurze Zeit sp�ater kam Lego Mindstorms auf den Markt. Im Gegen-

satz zu dem ersten Computer-Interface von Fischertechnik, das bereits 1984 auf

den Markt kam, entwickelte sich sehr schnell eine gro�e Fan-Gemeinde aus vie-

len Teilen der Welt. Es entstanden recht schnell mehrere, von Lego unabh�angige

Programmiersysteme f�ur den Brick, von denen vor allem NQC und legOS in-

zwischen eine gro�e Bekanntheit und Verbreitung erreicht haben.

Viele Dinge, wie zum Beispiel die Verbindung der Steuerung eines Lego-

Roboters mit einem Programm auf einem normalen PC, kann man mit NQC

oder mit dem im RIS mitgelieferten RCX-Code nicht bewerkstelligen. Dies ist

zwar mit dem von Lego ver�o�entlichten Active-X Control Spirit.ocx m�oglich,

aber nur unter Windows, mit einer der von Microsoft zur Verf�ugung gestellten

Sprachen wie Visual Basic, Visual C++ usw. Auch legOS enth�alt inzwischen

eine integrierte Kommunikations-Schnittstelle, das LNP (siehe Abschnitt 3.2.3

auf Seite 25).

Im Internet war auch Java-Code zu �nden (Dario Laverde, "RCX Java API",

http://www.escape.com/~dario/java/rcx/) mit dem man den Brick steuern

konnte. Das ging zwar nur sehr rudiment�ar, weil man immer noch die Bytecodes

kennen mu�te, die der Brick versteht, aber im Gegensatz zu der Ansteuerung des

Fischertechnik-Interface war man nicht einmal auf plattformabh�angigen C-Code

angewiesen, da es bereits das damals noch relativ neue Java Communications

API verwendete. Die Bytecodes konnte man der Webseite von Kekoa Proudfoot

entnehmen (Proudfoot, 1998).

Mit all diesen Informationen war es schlie�lich m�oglich, eine Lego-Umsetz-

ung f�ur das im Wintersemester 1999/2000 in der Vorlesung "Ober �achen pro-

grammieren" verwendete Beispiel "Niki, der Roboter"1, zu entwickeln. Das ei-

gentliche Beispiel diente dazu, objektorientierte Design-Pattern und deren An-

wendung in der Ober �achenprogrammierung zu demonstrieren. Daher ist der

Roboter dort { rein virtuell { ein Objekt, welches gewisse Aktionen ausf�uhren

und unter anderem mit einer gra�schen Ober �ache dargestellt und gesteuert

werden kann.

Die Lego-Umsetzung wurde in dieses System als eine weitere View (sie-

he Abschnitt 4.7 auf Seite 56) f�ur das Roboter-Objekt integriert, welche die

Aktionen des virtuellen Roboters in der Wirklichkeit nachvollzieht. Dies gesch-

ah alles in Java, da das zu diesem Zeitpunkt bereits die in dieser Vorlesung

1Niki beruht seinerseits auf "Karel the Robot", einer Idee die urspr�unglich aus Pattis (1981)

stammt.

Page 46: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

40 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

haupts�achlich verwendete Programmiersprache war.

Doch die Ansteuerung von Lego aus Java heraus war mit viel Arbeit ver-

bunden. Daraus entstand das Bed�urfnis einen vern�unftigen, universell wieder-

verwendbaren "Java-Treiber" auch f�ur Lego zu entwickeln. Da� dies nicht an

einem Nachmittag zu bewerkstelligen ist, war sp�atestens dann klar, als zudem

eine elegante Repr�asentierung der Elemente eines Roboters in Objekten erreicht

werden sollte. Es ging also gleich um eine ganze Sammlung von Objekten { eine

Klassenbibliothek, bzw. ein objektorientiertes API.

Das Fischertechnik-Interface ist aber viel zu verschieden von dem Brick, als

da� es einfach m�oglich gewesen w�are, die Klassen des ft-package f�ur Fischertech-

nik in dieser Form auch f�ur Lego zu verwenden. Von Java war man aber bereits

gewohnt, da� man Software nicht f�ur jede Plattform neu entwickeln mu�. Da-

her war klar, da� das API auf eine Weise realisiert werden sollte, die es erlaubt,

sowohl f�ur Lego als auch f�ur Fischertechnik die gleichen Klassen zu benutzen.

Das Ziel war nun die Scha�ung einer abstrahierten Schnittstelle zur Steue-

rung von Robotern. Dabei sollten die Vorteile objektorientierter Programmie-

rung ausgenutzt werden. Die Unterst�utzung f�ur eine ereignisgesteuerte Pro-

grammierung, wie sie z.B. auch das Event-Modell des AWT vorsieht, verstand

sich in diesem Zusammenhang beinahe von selbst. Da� daf�ur dann mehrere

Threads verwendet werden (m�ussen) ist klar, sofern eine Programmierung nicht

nur noch ereignisgesteuert m�oglich sein sollte. Grunds�atzlich ist die Idee bei

Ereignissen (Events) ja auch die, da� sie im Prinzip zu jeder Zeit, also auch

gleichzeitig und nicht nur nacheinander auftreten k�onnen. F�ur ein (scheinbar)

gleichzeitiges Auftreten und vor allem f�ur eine gleichzeitige, dabei aber vonein-

ander unabh�angige Behandlung von Events sind Threads daher unerl�a�lich.

Die Implementierung sollte f�ur Lego und f�ur Fischertechnik erfolgen, da dies

die vorhandene Hardware war. Dabei sollte aber darauf geachtet werden, da� die

entwickelten Abstraktionen, Modelle und Abh�angigkeiten eine Implementierung

f�ur andere Plattformen weitgehend o�en halten. Da die Hardware von Lego

und Fischertechnik relativ verschieden ist, ist deren Wahl (auch wenn sie mehr

pragmatische Gr�unde hatte) relativ gut, um die entwickelte Abstraktion auf

ihre Tauglichkeit zu testen.

4.3 Java

Die Implementierung des Abstract Robot Toolkit(ART) wurde in Java rea-

lisiert. Die entwickelten Abstraktionen von den Bestandteilen eines Roboters

sind aber im Prinzip von Java unabh�angig, sie sollten sich auch in anderen ob-

jektorientierten Sprachen umsetzen lassen. Java besitzt jedoch den Vorteil, da�

es �ahnliche Ziele verfolgt wie die, die hinter der Enwicklung ART stehen, denn

Java ist "einfach, objekt-orientiert, [. . . ] architektur-neutral, multi-threaded,

garbage collected, robust, [. . . ] erweiterbar und klar verstanden. Vor allem aber

macht Java Spa�!" (Entnommen aus Schreiner (2000a), dort nach van Ho�,

Shaio und Starbuck).

Einigen dieser Punkte wird man in Bezug auf Java nicht unbedingt in vollem

Umfang zustimmen. Die Vor- und Nachteile der Sprache Java sind auch nicht

Page 47: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.4. DESIGN-PATTERN UND DAS AWT 41

Thema dieser Arbeit. Die Verwendung von Java bildet f�ur ART aber eine gute

Basis, denn bis auf die Abstraktion eines Roboters und dessen Schnittstelle (die

Roboter-Hardware-Unabh�angigkeit), ist weitgehend alles vorhanden was man

braucht.

Der Vorteil einer objektorientierten Sprache liegt in der leichten Zug�ang-

lichkeit in Bezug auf die De�nition und Verwendung von Software-Modulen.

Objektorientierung kann man so verstehen, da� reale Dinge in abgeschlossenen

Softwarest�ucken abgebildet werden, die dann miteinander agieren. So wird ganz

nat�urlich die Menge der Motoren auf eine entsprechende Klasse Motor abgebil-

det und ein einzelner realer Motor auf eine Instanz, ein Objekt dieser Klasse.

Objekte werden verwendet, indem man mit ihnen �uber sogenannte Nachrich-

ten kommuniziert. Durch die Verwendung von Objekten wird ein nichtlinearer

Programmablauf unterst�utzt { eine durch Ereignisse ausgel�oste Interaktion von

miteinander verbundenen Objekten.

Die Idee einer virtuellen Maschine, bzw. von interpretiertem Code und einer

Klassenbibliothek, die eine unabh�angige Schnittstelle zur Hardware bereitstellt,

�ndet sich keineswegs nur bei Java. Bereits Smalltalk-80 beruhte auf einem sol-

chen Konzept (Goldberg und Robson, 1983) und auch Klassen- bzw. Funkti-

onsbibliotheken zur plattform�ubergreifenden Programmierung gibt es mehrere.

Java ist aber einer der modernsten und weitgehendsten dieser Ans�atze und

�ndet vor allem immer breitere Unterst�utzung.

4.4 Design-Pattern und das AWT

Wie der Name schon andeutet, besteht zwischen dem im Rahmen dieser Arbeit

entwickelten Abstract Robot Toolkit (ART) und dem Abstract Window Tool-

kit (AWT) von Java eine gewisse Gemeinsamkeit. Das AWT ist eine Sammlung

von Klassen f�ur die Programmierung eines Graphical User Interface (GUI).

Es erm�oglicht, eigene Unterklassen zu entwickeln und komplexe GUI's wer-

den durch ein Zusammenspiel zwischen vielen einzelnen Objekten verschiede-

ner Klassen realisiert. Instanzen der Klassen werden miteinander verbunden,

gleichsam "zusammengesteckt". Jede Instanz �ubernimmt dabei einen gewissen

Teil in einem komplexen Zusammenspiel, welches im Falle des AWT am Ende

zum Beispiel ein Fenster ergibt { das GUI eben.

Solche Aufteilungen in verschiedene Klassen, die vor allem gemeinsam ihre

volle St�arke ausspielen k�onnen, bzw. dadurch wesentlich besser wiederverwend-

bar werden, sind ein Aspekt des Designs der Software. Aber sogar die Art

der Aufteilung selbst kann man "wiederverwenden" { man spricht dann auch

von einem Design-Pattern. Die klassische Auswahl und Erkl�arung von solchen

Design-Pattern steht in Gamma et al. (1995). Der Aspekt, da� ein Container

f�ur Component-Instanzen selbst eine solche Component-Instanz ist und daher

mit ihm mehrere Komponenten zu einer zusammengefa�t und auch als eine

einzige behandelt werden k�onnen, wird dort als das Composite-Pattern be-

schrieben. Das sogenannte Strategy-Pattern wird mit der Kapselung des Layout-

Algorithmus und der Layout-Daten in separaten Klassen umgesetzt. Dieses Pat-

tern wird auch manchmal als Delegate-Pattern bezeichnet, bzw. ist mit diesem

Page 48: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

42 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

verwandt.

Auch in ART �nden sich solche bekannten Design-Pattern wieder, wobei

nicht gezielt versucht wurde, bestimmte Design-Pattern aus Gamma et al.

(1995) zu verwenden. Vielmehr soll der Verweis auf bestimmte Design-Pattern

dazu dienen einen leichteren Zugang zu ART zu erm�oglichen. So k�onnen Struk-

turen, die einem in der angegebenen Literatur behandelten Design-Pattern

�ahneln, leichter erkl�art werden, da f�ur sie bereits ein Name existiert. Ein Le-

ser, dem diese Begri�e nicht gel�au�g sind, kann in der angegebenen Literatur

nachschlagen. Dies erm�oglicht eine pr�agnantere Darstellung, da nur noch die

konkrete Auspr�agung des Patterns erkl�art werden mu� und die grunds�atzliche

Struktur sozusagen "mit einem Wort" klar ist.

Page 49: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.5. DAS ABSTRACT ROBOT TOOLKIT 43

4.5 Das Abstract Robot Toolkit

Wie bereits erw�ahnt, diente das AWT in gewisser Weise als Vorbild bei der

Implementierung von ART. Das AWT bietet Klassen wie Button oder Window,

welche die entsprechenden GUI-Elemente unabh�angig von der jeweiligen Platt-

form repr�asentieren. Diese Klassen k�onnen leicht, z.B. durch subclassing, um

plattform�ubergreifende Funktionalit�at erweitert werden und Implementierung-

en f�ur weitere Plattformen k�onnen ohne �Anderung an ihnen hinzugef�ugt werden.

Dies ist nat�urlich auch f�ur ART eine w�unschenswerte Eigenschaft. So gibt

es z.B. Klassen f�ur einen BooleanSensor oder einen Motor, welche genau so wie

beim AWT durch die Implementierung von Unterklassen spezialisiert und erwei-

tert werden k�onnen. Dies geschieht unabh�angig von der konkreten Ansteuerung

eines Hardware-Interfaces und kann daher mit jeder Hardware wiederverwendet

werden, auch mit zuk�unftigen Implementierungen f�ur weitere Hardware.

Design-Pattern in der Architektur

Sowohl im AWT als auch in ART wird dies durch Einsatz des sogenannten

Bridge-Pattern erreicht. Dies ist nicht ungew�ohnlich f�ur die Implementierung

eines plattform�ubergreifenden API, da es genau die eben beschriebenen Vor-

teile er�o�net. Die Klassen wie Motor sind eine Art Proxy f�ur die eigentli-

che Hardware-abh�angige Implementierung eines Motor. Ein Motor besitzt dazu

einen Verweis auf ein Objekt, welches die eigentliche Funktionalit�at, n�amlich die

konkrete Hardware anzusteuern, �ubernimmt. Dieses Objekt wird im AWT und

daher auch in ART als der Peer bezeichnet, was sich auch im Klassennamen

MotorPeer widerspiegelt.

Um eine weitgehend exible Implementierung der Peers zu erm�oglichen, sind

deren Schnittstellen in Form von Java-Interfaces de�niert. Welche Implemen-

tierung nun als konkreter Peer verwendet wird, mu� aber irgendwo entschieden

werden. Im Falle des AWT gibt es das sogenannte Toolkit-Objekt, welches

als Factory f�ur alle Peers dient. Im AWT wird die Toolkit-Klasse ihrerseits

als Factory f�ur ein konkretes Toolkit-Objekt verwendet. Die Klassenmethode

getDefaultToolkit() wird dazu verwendet. Welche Unterklasse von Toolkit

diese Methode zur Erzeugung der Toolkit-Instanz verwendet, kann �uber eine

Property (awt.toolkit) gesteuert werden.

Das gew�unschte Toolkit

Im Allgemeinen wird man bei der Verwendung des AWT nicht selbst ange-

ben, welche Toolkit-Implementierung benutzt werden soll. Dies ist auch nicht

notwendig, da die ben�otigte Implementierung im Wesentlichen nur von dem

Betriebssystem, auf dem die Java-Maschine l�auft, abh�angig ist. Eine eventuelle

Verteilung der Applikation, indem zum Beispiel das Fenster einer Applikation

auf einem ganz anderen Rechner erscheint, wird nicht durch Verwendung unter-

schiedlicher Toolkits erreicht, sondern dadurch, da� das entsprechende Toolkit

dieses f�ur die Applikation unmerklich selbst realisiert. Ist sogar die gesamte

Applikation verteilt programmiert, z.B. �uber RMI, dann "lebt" trotzdem jedes

Page 50: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

44 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

Input2

Output1

Output2

Input1

RobotInterface

MotorPeer

stop()

backward()

forward()

ActuatorPort

Motor

stop()

backward()

forward()"Wire"

Ethernet, ...)Bluetooth,

(RS232, I2C,

Robot(Hardware)

creates

& delivers

represents a specific

kind of interpretation

of the actuator−hardware

to the hardware−port

actuator−hardware connected

represents a specific type of

of the hardware−interface

represents a specific portrepresents a

hardware−interface

Abbildung 4.4: Das grunds�atzliche Zusammenspiel und die Bedeutung der Komponentendes ART. Ein Steuerungsalgorithmus verwendet in erster Linie bestimmte Interpreta-tionen der Elemente eines Roboters (in der Gra�k durch Motor dargestellt).

Objekt zu einem bestimmten Zeitpunkt auch nur auf einem Rechner, bzw. in

einer Java-Maschine, und daher werden im Allgemeinen auch nicht mehrere

Toolkit-Implementierungen ben�otigt.

Bei der Ansteuerung von Robotern verh�alt sich das etwas anders. Welche

Roboterhardware einem Programm zur Verf�ugung steht, h�angt nicht mit dem

Betriebssystem oder der jeweiligen Java-Implementierung zusammen. Dies kann

sich im Prinzip sogar w�ahrend eines Programmablaufs �andern.2 Nun k�onnte

man zwar �ahnlich wie bei Toolkit die konkrete Implementierung �uber eine Pro-

perty ausw�ahlbar machen, diese Property m�usste aber dann eigentlich immer

einen Wert enthalten, da es so etwas wie die Standardhardware zur Roboter-

steuerung nicht gibt und folglich auch keine Standardimplementierung gew�ahlt

werden kann.

Die in ART enthaltenen Implementierungen f�ur den Brick und das Intel-

ligent Interface f�ur Fischertechnik k�onnen bis zu einem gewissen Grad auto-

matisch heraus�nden, welche Interface-Hardware angeschlossen ist. Es ist aber

auch vorstellbar, da� man f�ur einen entsprechend aufw�andigen Roboter meh-

rere Interfaces verwenden m�ochte, vielleicht sogar von verschiedenen Typen,

so da� letzten Endes Hardware von z.B. Lego und Fischertechnik gleichzei-

tig verwendet wird. Aus diesem Grund ist die Wahl der konkreten Toolkit-

Implementierung, also der Factory f�ur die Peers von Sensoren und Motoren,

nicht so einfach automatisch zu bewerkstelligen wie beim AWT, wo man sich

damit nicht notwendigerweise auseinandersetzen mu�.

Die meisten Hardware-Interfaces werden au�erdem mehrere Anschl�usse f�ur

Sensoren oder Motoren haben und es mu� daher auch ausgew�ahlt werden, an

welchem dieser Anschl�usse z.B. der entsprechende Motor angeschlossen sein soll.

Den grundlegenden Aufbau illustriert Abbildung 4.4. Damit eine der Frontend-

Klassen zu ihrem Peer kommt sind drei Schritte notwendig:

1. Das Hardware-Interface mu� ausgew�ahlt werden. Ein Objekt der Klas-

2Bevor sich nun jemand falsche Ho�nungen macht: Ein mehr oder weniger automatischer

Wechsel der Roboterhardware zur Laufzeit wird, zumindest zum jetzigen Zeitpunkt, nicht von

ART unterst�utzt.

Page 51: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.5. DAS ABSTRACT ROBOT TOOLKIT 45

se RobotInterfaceFactory hat mehrere Factory-Methoden mit denen

Instanzen der Klasse RobotInterface erzeugt werden k�onnen. Eine In-

stanz von RobotInterface repr�asentiert dann ein Hardware-Interface.3

Viele der Factory-Methoden von RobotInterfaceFactory erzeugen meh-

rere Interfaces, von denen man dann ausw�ahlt, welche man verwenden

m�ochte.

2. Ein RobotInterface besitzt mehrere Anschl�usse, welche durch Instanzen

der Klasse Port repr�asentiert werden. Diese Anschl�usse h�angen aber ih-

rerseits so eng mit der jeweiligen Instanz von RobotInterface zusammen,

da� man sie nicht selbst erzeugt, sondern auch RobotInterface wieder

eine Factory darstellt und zwar f�ur die Port-Objekte.

3. Instanzen von Motor, BooleanSensor usw. kommen �uber ein solches Port-

Objekt an ihren MotorPeer, bzw. BooleanSensorPeer, indem man sie

mit diesem Port verbindet. Erst dann ist die Verbindung komplett, so

da� z.B. die BooleanSensor-Instanz den Zustand eines realen Schalters

widerspiegelt. Somit hat das verwendete Port-Objekt als erstes Ein u�

darauf, welchen Peer z.B. der Motor bekommt.

Diese Aufteilung in mehrere Schritte, bis z.B. ein BooleanSensor auch wirk-

lich komplett benutzbar ist, erscheint eventuell unn�otig umst�andlich. Es gibt

aber einige Argumente, die diese Aufteilung unterst�utzen:

� Diese Aufteilung entspricht sehr gut der Realit�at, was eines der wichtig-

sten Argumente �uberhaupt ist. Dort w�ahlt man auch erst einmal einen

Sensor und eine Interface-Hardware aus und schliesst dann den Sensor an

einen der zur Verf�ugung stehenden Anschl�usse an.

� Um einen der Software-Sensoren wie BooleanSensor mit etwas zu ver-

binden reicht ein Port-Objekt, welches wesentlich weniger komplex als

ein RobotInterface ist. Wenn man also z.B. einen BooleanSensor ha-

ben m�ochte, der gar nicht mit einer realen Hardware in Verbindung steht,

sondern z.B. immer einen konstanten Wert liefert, so kann man das (f�ur

den BooleanSensor v�ollig unmerklich) alleine dadurch erreichen, da� man

einen eigenen Port daf�ur erstellt. Ein ganzes RobotInterface ist in die-

sem Fall nicht n�otig.

Im AWT bekommt ein Button seinen ButtonPeer, indem er einem Con-

tainer (der letzten Endes in einem Window "steckt") hinzugef�ugt wird und

dessen Toolkit �ubernimmt;4 in ART bekommt ein Motor seinen MotorPeer,

indem er mit einem Port verbunden wird. Ein Port-Objekt kann aber nicht

3Eine Implementierung von RobotInterface mu� nicht notwendigerweise mit einer realen

Hardware im Zusammenhang stehen, bzw. genau ein Hardware-Interface repr�asentieren (siehe

Kapitel 6 auf Seite 107).4Falls der Container selbst noch kein Toolkit haben sollte, bekommt der Button erst dann

ein solches, wenn auch der Container eines bekommt. Die Verbindung mit einem Peer, bzw.

die Wahl eines Toolkit, wird in der Regel durch Aufruf der Methode pack() in der Klasse

Frame veranlasst.

Page 52: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

46 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

so direkt erzeugt werden wie zum Beispiel ein Frame, da (wie bereits erw�ahnt)

kein default-RobotInterface zur Verf�ugung steht. Das macht die Handhabung

zwar ein klein wenig aufw�andiger, daf�ur erh�alt man aber eine sichtbare Kontrolle

dar�uber, welcher Anschlu� an welcher Hardware, bzw. welche Implementierung

von RobotInterface, verwendet wird.

Jedem das Seine

Ein weiterer Unterschied zwischen dem AWT und ART besteht darin, da� das

Toolkit des AWT nur Peers von bestimmten festgelegten Klassen erzeugt. Im

wesentlichen gibt es im AWT in der Klasse Toolkit f�ur jedes GUI-Element wie

Button oder TextField eine entsprechende Methode createButton(Button),

bzw. createTextField(TextField). Diese Festlegung gibt es in ART so nicht.

Es gibt genau einen Peer, den jedes RobotInterface, bzw. ein Port-Objekt,

zur Verf�ugung stellen mu� und zwar eine Implementierung von SensorPeer. Es

w�urde gar keinen Sinn machen, wenn jedes RobotInterface jede m�ogliche Form

eines Sensors oder Actuators durch einen entsprechenden Peer zur Verf�ugung

stellt, da sich die Hardware oft viel zu sehr unterscheidet. Manche Sensoren

oder Actuatoren haben auf mancher Hardware einfach keine Unterst�utzung.

Auch in Java gibt es diesen Ansatz seit der Einf�uhrung von Swing. Swing ist

eine Implementierung von GUI-Elementen, die alle auf einem einzigen Peer

f�ur Component beruhen, einem sogenannten LightweightPeer. Dieser stellt im

Wesentlichen nur eine Fl�ache auf dem Bildschirm zur Verf�ugung und verarbeitet

Events des zugrundeliegenden Fenstersystems, so da� z.B. Tastatureingaben

verarbeitet werden k�onnen.

In ART werden beide Ans�atze miteinander kombiniert. Wie bereits erw�ahnt,

mu� eine Implementierung von RobotInterface nur einen SensorPeer bereit-

stellen.5 Dar�uber hinaus hat ein RobotInterface aber die M�oglichkeit, be-

liebige Spezialisierungen eines SensorPeer zur Verf�ugung zu stellen. Je nach-

dem von welcher Klasse das Objekt ist, f�ur das ein Peer ben�otigt wird, oder

auch je nachdem welche Peers bereits erzeugt wurden, k�onnen unterschiedli-

che Peers erzeugt (bzw. geliefert) werden. Es gibt in ART bereits De�nitionen

f�ur solche Spezialisierungen (z.B. MotorPeer oder LightSensorPeer) in Form

von weiteren Java-Interfaces, die das Interface SensorPeer erweitern. Zudem

geh�oren zu jedem dieser Java-Interfaces gewisse Klassen (wie z.B. Motor oder

LightSensor), die mindestens einen SensorPeer ben�otigen aber einen Peer,

der das zugeh�orige Interface implementiert hat, bevorzugen. Wird ein Port eines

bestimmten RobotInterface nun nach einem Peer f�ur ein bestimmtes Sensor-

Objekt gefragt (man beachte, da� auch Motoren als Sensoren f�ur ihren Zustand

aufgefasst werden), dann gilt die folgende Vereinbarung :

� Wenn ein Peer geliefert wird, dann ist es "der Beste" der f�ur diesen Port

zu diesem Zeitpunkt und f�ur dieses Sensor -Objekt geliefert werden kann.

Im schlechtesten Fall ist es ein einfacher SensorPeer.

5Genaugenommen nicht mal das, da ein RobotInterface theoretisch auch 0 Ports haben

kann { nur wird das kaum sinnvoll verwendet werden k�onnen.

Page 53: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.5. DAS ABSTRACT ROBOT TOOLKIT 47

� Welcher von den momentan m�oglichen Peers der Beste ist, wird anhand

der Klasse des Sensor-Objektes entschieden.

Peers f�ur zuk�unftige Sensor-Klassen

Bisher sind in ART die in Abbildung 4.5 enthaltenen Peers de�niert. M�ochte

man bei einer selbst implementierten Sensor-Klasse einen bereits existierenden

Typ Peer bevorzugen, dann mu� die eigene Sensor-Klasse von einer der Sensor-

Klassen abstammen, die zusammen mit dem entsprechenden Peer de�niert wur-

den. Man kann sich zwar auch eigene Peer-Typen in Form von Java-Interfaces

ausdenken, mu� dann aber auch daf�ur sorgen, da� irgendeine Implementierung

von RobotInterface, bzw. Port, diesen Peer auch unterst�utzt (also eine Im-

plementierung davon kennt und zur�uckliefern kann) um etwas davon zu haben.

SensorPeer

StateSensorPeer

CountSensorPeer

AngleSensorPeer

ActuatorPeer

MotorPeer

StepperMotorPeer

ServoPeer

LightSensorPeer

BooleanSensorPeer

For hardware which is able to measure angles

For hardware which can control stepper motors

For hardware which can distinguish between true and false

For counting state−transitions

For hardware which is able to measure light

For discrete values

Base interface − must be implemented by every peer

Base Interface for values that can be set (output of hardware)

For hardware which can control motors

For hardware which can control servo motors

Abbildung 4.5: Die Klassenhierarchie der Peers f�ur die Frontend-Klassen. Die Abstam-mungsverh�altnisse sind die gleichen wie bei den Sensor-Implementierungen (siehe Ab-bildung 4.6 auf Seite 52).

Beispielsweise wird der in ART bereits vorhandene MotorPeer logischer-

weise von der Klasse Motor bevorzugt. Diese Bevorzugung ist aber nicht dy-

namisch, sondern an die Klassen gebunden. Hiermit ist nicht die dynamische

Bindung in einer objektorientierten Sprache gemeint, in der eine Nachricht erst

zur Laufzeit an eine bestimmte Methoden-Implementierung gebunden wird,

sondern der Umstand, da� die Zuordnung Klasse$Peer in die Implementie-

rungen von RobotInterface fest hineincodiert ist. Eine Implementierung von

RobotInterface mu� die Klassen, f�ur die sie einen besonderen Peer liefern

m�ochte, daher kennen. Im momentanen Entwicklungsstadium von ART ist es

Page 54: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

48 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

nicht m�oglich, eine Implementierung von Sensor nach ihren bevorzugten Peer-

Klassen zu fragen, daher ist es bei einer eigenen Klasse, die z.B. einen MotorPeer

bevorzugen m�ochte eben noch notwendig, da� sie von Motor abstammt. Nur

wenn man sich auch mit einem einfachen SensorPeer zufrieden geben kann ist

es m�oglich, von einer beliebigen Klasse abzuleiten, denn Sensor ist ein Java-

Interface und nur dessen Adaptierung ist Vorraussetzung daf�ur, da� ein Objekt

als Sensor im Zusammenhang mit ART verwendet werden kann.

Interpretationen von Werten

Es ist also m�oglich, da� eine Implementierung der Ansteuerung eines Hard-

ware-Interface nur genau die speziellen Peers enth�alt, die f�ur diese Hardware

auch sinnvoll sind. So gibt es zum Beispiel weder f�ur die Ansteuerung von Fi-

schertechnik noch f�ur die Ansteuerung von Lego einen BooleanSensorPeer,

denn ein spezieller "Wahrheitssensor" existiert f�ur diese Hardware h�ochstwahr-

scheinlich nicht. W�are die Interface-Hardware, die man ansteuert, aber z.B. ein

L�ugendetektor, dann k�onnte ein BooleanSensorPeer durchaus Sinn machen.

Ein RobotInterface k�onnte auch spezielle Anschl�usse (Instanzen von Port)

anbieten, die einen Peer liefern der diese Interpretation in true oder false vor-

nimmt. Es ist zum Beispiel denkbar, einen solchen Port anzubieten, um �uber

einen BooleanSensor zu erfahren, ob die Verbindung zwischen der Implementie-

rung von RobotInterface und der eigentlichen Interface-Hardware noch steht

oder ob sie momentan zusammengebrochen ist. �Uberhaupt kann man feststel-

len, da� "Sensoren" f�ur "Werte" ein Konzept ist, das nicht notwendigerweise

mit Dingen aus der "greifbaren" Welt, wie z.B. einem Schalter, zu tun haben

mu�. Im Grunde k�onnen Sensoren auch rein virtuell sein und innerhalb der

Komponenten einer Software zum Datenaustausch dienen.

Grunds�atzlich unterscheiden sich Sensor-Objekte in zwei f�ur die Abstrak-

tion (und den damit verbundenen M�oglichkeiten zur Wiederverwendung) wich-

tigen Punkten: Erstens ist es wichtig, ob sie nur einen Wert, oder sogar einen

Wert mit einer bestimmten Interpretation repr�asentieren, und zweitens, ob die-

ser Wert einer bestimmten Skala entspricht, also bereits kalibriert ist. Eine

Interpretation liefern im Grunde alle Sensoren au�er dem allereinfachsten (in

ART der RawSensor).

Bei einem BooleanSensor ist die Existenz einer gewissen Interpretation am

o�ensichtlichsten, aber auch ein LightSensor steht daf�ur, da� sein Wert der

Intensit�at eines Lichts entspricht. Die Interpretation geht aber unterschiedlich

weit. So ist bei einem LightSensor z.B. noch nicht klar, welche Lichtquelle mit

ihm gemessen wird, oder bei einem StateSensor ist zwar klar, da� sein Wert

einen gewissen (in ART als diskret de�nierten) Zustand ausdr�uckt, doch die

Bedeutung des Zustands kennt er noch nicht. So m�u�te der Zustand eigentlich

noch eine Bedeutung bekommen, wie z.B. Rot, Gr�un, Blau (und je nach Anwen-

dung auch noch "unde�niert") f�ur einen Sensor der eine der drei Grundfarben

des RGB-Modells erkennen soll.

Dies ist deshalb wichtig, weil durch diese Unterscheidung ein Algorithmus

unabh�angig(er) von der konkreten Auspr�agung eines Sensors wird. Ben�otigt ein

Algorithmus einen Sensor f�ur bestimmte Farben, weil er z.B. je nach registrierter

Page 55: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.5. DAS ABSTRACT ROBOT TOOLKIT 49

Grundfarbe eine von drei Aktionen implementiert, so sollte er auch auf einem

"PrimaryColorSensor" beruhen und nicht auf einem StateSensor oder gar ei-

nem LightSensor. So wird n�amlich das Problem, wie z.B. anhand des Werts

eines Lichtsensors entschieden werden kann, welcher Farbe der gemessene Wert

entspricht, nicht verschleppt. Wenn sich dann die Hardware �andert, also der

Lichtsensor auf einmal andere Werte liefert, weil er genauer wird oder weil man

mehrere Sensoren mit Farb�ltern verwendet usw., so braucht man nur die Zu-

ordnung zu den Farben neu zu implementieren, ohne an dem Algorithmus, der

aufgrund der Farben entscheidet, etwas zu ver�andern.

Nat�urlich ist es (gerade f�ur Zust�ande) nicht m�oglich, alle Interpretationen

abzudecken { es gibt unendlich viele. Man m�ochte bestimmt auch nicht st�andig

neue Sensor-Klassen implementieren, so da� man sich im Falle der Zust�ande

oft auch schon zufrieden geben wird, wenn man schlicht in der Dokumentation

des Algorithmus de�niert, wie die Zust�ande, also die "nackten" Zahlen, inter-

pretiert werden. Viel sinnvoller ist die Verwendung spezieller Sensor-Klassen,

wenn durch sie eine bestimmte physikalische Gr�o�e repr�asentiert wird, also z.B.

eine Lichtintensit�at, Temperatur, Strecke oder ein Winkel. Dort wird dann auch

die Skala wichtig (obwohl die Zustands-Interpretation im Grunde auch bereits

eine Art Skala ist).

Im Optimalfall, bei entsprechender Unterst�utzung durch die Hardware, lie-

fert der Sensor bereits richtig kalibrierte Werte. Dies ist zum Beispiel bei dem

Temperatursensor von Lego f�ur den Brick der Fall. Die Lichtsensoren von Lego

und Fischertechnik sind hingegen nicht kalibriert, so da� man dies dort entwe-

der "per Hand" vornehmen mu�, oder ganz darauf verzichtet. Grunds�atzlich

wird bei Sensoren f�ur physikalische Gr�o�en in ART davon ausgegegangen, da�

diese auch kalibriert sind, trotzdem sollte ein Algorithmus aber dokumentie-

ren, inwieweit er von einer Kalibrierung abh�angig ist, damit man einsch�atzen

kann, welche Hardware im Zusammenhang mit dem Algorithmus �uberhaupt

verwendbar ist.

Die Programmierung des Beispielroboters LiSe in Abschnitt 5.6 auf Seite 94

verwendet z.B. nur die Grenzen des messbaren Bereichs sowie die Genauigkeit

der Lichtsensoren. Sie kommt ansonsten allein mit dem Unterschied zwischen

zwei (gleich skalierten) Lichtsensoren aus. Die Genauigkeit ist eine Eigenschaft

die jeder Sensor besitzt und einen messbaren Bereich hat im Grunde jeder phy-

sikalische Sensor.6 Solche Werte, die die Eigenschaften des Sensors beschreiben,

bekommen die Sensor-Objekte in der Regel von ihrem Peer (wenn er den je-

weiligen Wert unterst�utzt). Die Werte k�onnen aber auch manipuliert werden,

um sie an die Erfordernisse eines bestimmten Algorithmus anzupassen. F�ur

den beschriebenen Algorithmus f�ur LiSe ist jedoch nur wichtig, da� die beiden

Lichtsensoren Werte auf der gleichen Skala liefern, also untereinander vergleich-

bar sind { welche Skala das ist, ist nicht relevant. Normalerweise sollte das bei

gleicher Hardware sowieso schon der Fall sein. Verwendet man aber z.B. f�ur

den einen Sensor Fischertechnik- und f�ur den anderen Lego-Hardware, so mu�

man daf�ur selbst sorgen. Welche M�oglichkeiten die in ART enthaltenen Sensor-

Klassen daf�ur unter anderem bieten wird im n�achsten Abschnitt beschrieben.

6Der in ART enthaltene AngleSensor kennt diese Eigenschaft bisher noch nicht.

Page 56: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

50 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

4.6 Die Sensor-Implementierungen in ART

Die in ART existierenden Implementierungen des Java-Interface Sensor sind

darauf ausgelegt, eine exible Nutzung, im Zusammenhang mit den jeweils

m�oglichen Peer-Implementierungen, zu gestatten.

Grundfunktionalit�at SensorPeer

Da jeder Peer eine Implementierung von SensorPeer sein mu�, kann jeder

Sensor im Grunde mit jedem Peer wenigstens soviel anfangen, da� er an einen

Wert kommt. Ein Sensor hat die M�oglichkeit, mit dem Peer, den er bekom-

men hat, das zu simulieren, was er von seinem Wunsch-Peer erwartet h�atte.

Nicht jede Funktionalit�at kann simuliert werden. Wenn z.B. ein Motor nur einen

einfachen SensorPeer und nicht wenigstens einen ActuatorPeer bekommt,

dann kann der Aufruf der Methode on() bei einem solchen Motor-Objekt kei-

nen E�ekt auf die Interface-Hardware haben, denn SensorPeer bietet f�ur das

Setzen eines Werts keine Methode { die gibt es erst bei ActuatorPeer. Ein

ActuatorPeer hingegen reicht dem in ART enthaltenen Motor bereits, um sei-

ne volle Funktionalit�at zu besitzen.

Damit wird weitgehend ein Problem adressiert, da� bei Java unter ande-

rem zur bereits erw�ahnten Entwicklung von Swing gef�uhrt hat. Anfangs wurde

mit dem AWT nur solche Funktionalit�at angeboten, die auf jeder unterst�utzten

Plattform bereits vorhanden ist. Im Gegensatz dazu wird bei Swing (und auch

in ART) versucht, mit dem was jede Plattform bietet, die gr�o�tm�ogliche Funk-

tionalit�at zu erreichen. Statt der Schnittmenge nun also die Vereinigungsmenge.

Es ist klar, da� dieser Ansatz auch seine Grenzen hat. Er bietet aber den Vor-

teil, da� die Klassen des API bereits mit einer relativ geringen Peer-seitigen

Unterst�utzung auskommen. Zumindest in ART bleibt einem trotzdem noch der

Weg o�en, sich bei der Implementierung eines RobotInterface nicht nur auf

die Simulation in der jeweiligen Sensor-Klasse zu verlassen, sondern spezielle

Unterst�utzung, durch entsprechende Peer-Implementierungen, zu liefern.

In den meisten F�allen, in denen die Simulation erforderlich ist, wird es n�otig

sein, dem Sensor dann noch weitere Parameter zur Verf�ugung zu stellen, die

festlegen, wie diese Simulation aussehen soll. So wird z.B. der in ART enthaltene

BooleanSensor, wenn er einen Peer hat, der kein BooleanSensorPeer ist, den

Wert, den er von seinem Peer bekommt, selbst in true oder false umwandeln.

Daf�ur interpretiert er den Wert 0 als false und alle anderen Werte als true.

Dies ist aber nur sein Standard-Verhalten, wenn er f�ur die Interpretation keinen

Delegate hat.7

Basisklasse RawSensor

Alle in ART enthaltenen Implementierungen von Sensor stammen von der Klas-

se RawSensor ab. Die Klasse RawSensor ist bereits ein vollwertiger Sensor. Alle

7In Gamma et al. (1995) wird kein Delegate-Pattern erw�ahnt. Ein vergleichbares Pattern

hei�t dort Strategy. Der Name Delegate, bzw. Delegation wird aber z.B. in Schreiner (1999)

und Gar�nkel und Mahoney (1993) daf�ur verwendet.

Page 57: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.6. DIE SENSOR-IMPLEMENTIERUNGEN IN ART 51

notwendigen Dinge, wie die Verbindung zum Port bzw. SensorPeer herzustel-

len, Events zu verarbeiten und an SensorListener weiterzuleiten sowie ein

paar einfache Kon�gurationsm�oglichkeiten, werden von einem RawSensor zur

Verf�ugung gestellt. Um denWert, der vom Peer (also von der Hardware) kommt,

auf eine spezielle Weise zu verarbeiten, bietet ein RawSensor im Wesentlichen

drei Ansatzpunkte, welche bestimmten Design-Pattern entsprechen:

Template-Method : Zu bestimmten festgelegten Zeitpunkten bei der Verar-

beitung eines Werts vom Peer, werden bestimmte Methoden aufgerufen, die den

Wert umwandeln k�onnen. Wenn z.B. ein Wert vom Peer ankommt, entweder

durch einen Event oder weil der Peer explizit nach seinem Wert gefragt wurde,

dann ruft RawSensor bei sich selbst die Methode convertToIncoming(double)

auf und wandelt damit den gerade erhaltenen Wert um. Das bietet einer Un-

terklasse die M�oglichkeit, diese Methode zu �uberschreiben und eine eigene Um-

wandlung zu implementieren. Gegebenenfalls kann die neue Methode der Un-

terklasse auch die Methode der Oberklasse aufrufen, um ihr auch noch eine

Chance f�ur eine eventuelle Umwandlung zu geben. Bei einem RawSensor ist

dies auch sehr sinnvoll - nicht weil sie eine eigene Umwandlung durchf�uhren

w�urde, sondern weil mit ihr der n�achste Punkt implementiert ist:

Strategy (Delegate): Ein RawSensor kann einen incomingConversionDe-

legate besitzen. Dieser Delegate mu� ein Objekt einer Klasse sein, die das

Java-Interface de.jaetzold.util.Conversion implementiert, welches im We-

sentlichen vorschreibt, da� eine Methode convert(double) existiert, die ihrer-

seits ein double zur�uckliefert. Diese Methode wird dann zum Umwandeln des

Wertes aufgerufen, vorausgesetzt, da� �uberhaupt ein Delegate angegeben wur-

de. Eine Conversion bietet au�erdem noch Methoden, um zu erfahren ob ihre

Umwandlung cacheable ist8 und ob man erwarten kann, da� sie nicht nur ganz-

zahlige Resultate liefert (deliversFloatingPoint). Dies sind Informationen,

die ein Sensor auch in Bezug auf sich selbst liefern m�ochte, und er ist daher

darauf angewiesen, dies auch �uber den Delegate zu wissen, da dieser den Wert

ja umwandelt. Au�erdem ist in RawSensor ein Mechanismus implementiert, der

vom Peer erhaltene Werte sowie eben deren Umwandlungen zwischenspeichert,

um bei h�au�gen Anfragen schneller antworten zu k�onnen. Diese Zwischenspei-

cherung wird aktiviert, wenn der Peer sowieso bei jeder �Anderung des Werts

einen Event verschickt, denn dann mu� er nicht noch extra gefragt werden, wel-

chen Wert er nun momentan hat { es ist einfach der letzte, f�ur den ein Event

angekommen ist.

Decorator : Man kann mehrere Sensor-Instanzen "hintereinanderschalten".

Die Methode getSensorPort() liefert einen SensorPort der, wenn man dort

einen weiteren Sensor anschliesst, diesem einen Peer liefert, der den Wert der

ersten Sensor-Instanz repr�asentiert. Dies ist der einzige Ansatzpunkt f�ur eine

spezielle Behandlung des Sensorwertes, der bereits im Java-Interface Sensor

8Damit ist gemeint, ob sie durch eine unver�anderliche Zuordnungstabelle repr�asentiert

werden kann und daher f�ur ein Argument in Zukunft immer das gleiche Resultat liefert.

Page 58: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

52 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

de�niert ist. Dies hat den Grund, da� �uber diese Schnittstelle das Verhalten

des urspr�unglichen Objektes nicht wirklich beein u�t wird. Angenommen, ein

Sensor wird noch von anderen Objekten verwendet, von denen man vielleicht

nicht einmal etwas wei� (womit man im Grunde immer rechnen sollte), dann

kann es zu Problemen f�uhren, wenn man z.B. auf den Delegate des Sensors

Ein u� nimmt, da dann die Berechnung des Sensorwerts f�ur alle, die diesen

Sensor verwenden, beein u�t wird. Ein Beispiel hierf�ur und wieso das im Falle

des Brick noch weitere Vorteile bietet, steht in Abschnitt 5.5 auf Seite 86.

Unterklassen von RawSensor

Die in ART enthaltenen Sensor-Klassen sind wie gesagt alle als Unterklassen

von RawSensor realisiert. Sie nutzen das Template-Method-Pattern, um f�ur den

Fall, da� sie nicht "ihren" Peer bekommen haben, dessen Funktionalit�at �uber

eine Umwandlung des Wertes zu simulieren. Hat aber z.B. ein LightSensor

einen LightSensorPeer, dann braucht er nicht umzuwandeln, da der Peer be-

reits einen entsprechenden Licht-Wert liefert.

RawSensor

CountSensor

StateSensor

BooleanSensor

LightSensor RawActuator

Servo

Actuator

Sensor

AngleSensor

Motor

StepperMotor

implementing classes interfaces

Abbildung 4.6: Die Klassenhierarchie der Actuator- und Sensorklassen.

Das Strategy-Pattern hingegen dient mehr dazu eine Umwandlung zu ver-

wenden, die von einer bestimmten Sensor-Klasse unabh�angig ist und daher

mit vielen Sensoren verwendet werden kann { z.B. eine einfache Skalierung des

Wertes. Ein Delegate ist aber nicht verp ichtet, �uberhaupt eine Umwandlung

vorzunehmen, die in irgendeiner Beziehung zu dem eigentlichen Wert steht.

Es w�are denkbar, da� ein solcher Delegate z.B. als Resultat immer System.

currentTimeMillis() liefert und pl�otzlich hat man eine Art TimeSensor. F�ur

einen TimeSensor w�are es aber sinnvoller, eine eigene Unterklasse zu erstel-

len, um die Art des Sensorwertes deutlich zu machen. Der Delegate ist besser

daf�ur geeignet, die entsprechenden Skalierungen vorzunehmen, z.B. f�ur den Fall,

da� ein LightSensor keinen LightSensorPeer bekommt und man trotzdem

m�ochte, da� der Wert einer bestimmten Skala entspricht.

Page 59: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.6. DIE SENSOR-IMPLEMENTIERUNGEN IN ART 53

Das Decorator-Pattern kann man auch f�ur eine Umwandlung des Werts nut-

zen. Dies ist vor allem dann wichtig, wenn man nicht ausschlie�en kann, durch

die Umwandlung mit dem Bed�urfnis anderer Objekte, die den Sensor verwen-

den, zu interferieren. Die M�oglichkeit, mehrere Sensoren quasi "hintereinander-

zuschalten", erlaubt einem au�erdem, darauf Ein u� zu nehmen, �uber welchen

Peer ein Sensor letztendlich an seinen Wert kommt. So kann man ganz bewu�t

zum Beispiel einen CountSensor verwenden, der an einen LightSensor ange-

schlossen ist und daher (wenn der LightSensor an einen entsprechenden Port

angeschlossen ist) seinen Wert im Grunde auch von einem LightSensorPeer

erh�alt. Zudem gibt es einen CombinedSensor, welcher die Werte zweier Sensor-

Instanzen �uber eine Implementierung des Java-Interface de.jaetzold.util.

BinaryConversionmiteinander verkn�upft. Die eine dieser Sensor-Instanzen ist

der CombinedSensor aber selbst, d.h. um beliebige Sensoren zu verwenden mu�

man auch den CombinedSensor an den SensorPort eines anderen Sensor an-

schlie�en. Die andere Sensor-Instanz wird dem CombinedSensor als Parameter

�ubergeben. Die Repr�asentation der Verkn�upfung zweier Objekte durch ein Ein-

zelnes, das sich im Prinzip genau so verh�alt wie die Objekte, deren Verkn�upfung

es darstellt, ist ein Beispiel f�ur das bereits angesprochene Composite-Pattern.

Die Peer-Interfaces

Die bisher in ART de�nierten Peer-Interfaces sind in Abbildung 4.5 auf Seite 47

dargestellt. Das Verhalten der Sensor-Klassen in ART bei unterschiedlichen

Peers kann man im Wesentlichen folgenderma�en zusammenfassen:

� Hat ein Sensor einen genau zu ihm passenden Peer, dann wird der Wert,

der vom Peer kommt, im Allgemeinen nicht ver�andert. Je nach Sensor

k�onnen noch weitere Parameter vom Peer �ubernommen werden (so z.B.

der AngleSensor eines Servo oder die Grenzen des Messbereichs bei ei-

nem LightSensor).

� Hat ein Sensor nicht einen Peer, der ihm alle gew�unschte Funktionalit�at

bietet, so �ubernimmt er den Wert so, wie er von der Oberklasse bereits

verarbeitet wurde, und nimmt dann noch eventuell geeignete �Anderun-

gen daran vor. Weitere Parameter haben entweder default-Werte oder

m�ussen in diesem Fall dem Sensor-Objekt �ubergeben werden. Zum Bei-

spiel braucht ein StateSensor in einem solchen Fall ein Objekt, welches

das Interface StateDecider implementiert hat. Den StateDecider ver-

wendet der StateSensor, um aus dem Wert seiner Oberklasse RawSensor

einen Wert zu erhalten, der einen gewissen Zustand repr�asentiert. Solch

ein StateDecider ist im Grunde eine Verkn�upfung von zwei Werten zu ei-

nem, welcher eine Verallgemeinerung einer Zustands�ubergangsmatrix dar-

stellt. Er bekommt den aktuellen Zustandswert sowie den Raw-Wert der

Oberklasse als Parameter und liefert den neuen Zustandswert als Resul-

tat. Ein StateSensor hat nat�urlich auch einen defaultStateDecider,

welcher aber nichts weiter macht, als den Raw-Wert unver�andert zur�uck-

zugeben.

Page 60: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

54 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

� Hat ein Sensor nicht einen passenden Peer und ist die Umwandlung, die

er dann an dem Wert vornimmt, um auch ohne einen speziellen Peer klar-

zukommen, f�ur die gew�unschte Anwendung nicht geeignet, so wird es in

den meisten F�allen ausreichen und auch am einfachsten sein, dem Sensor

eine Conversion als conversionDelegate9 zu �ubergeben. Zumindest die

in ART enthaltenen Sensor-Klassen bieten diese M�oglichkeit, da sie alle

von RawSensor abstammen.

� Es kann auch vorkommen, da� ein Sensor zwar seinen bevorzugten Peer-

Typ bekommt, dessen Wert aber nicht richtig skaliert ist. Der Light-

SensorPeer { in den Implementierungen sowohl f�ur Lego als auch f�ur Fi-

schertechnik { ist solch ein Fall. Die Hardware besitzt zwar Lichtsensoren

und mu� im Falle von Lego den Eingang sogar entsprechend kon�gurie-

ren, diese Sensoren liefern aber keinen Wert der auf eine geeignete Skala

kalibriert ist. F�ur Lichtsensoren w�are wahrscheinlich Lux eine gute phy-

sikalische Einheit, doch konnte keine Quelle gefunden werden, welche die

Werte der jeweiligen Lichtsensoren zu einer solchen Skala in Beziehung

setzt. Man kann wohl auch davon ausgehen, da� die Fertigungstoleranz

und die Abh�angigkeit von der Umgebung (Temperatur, Stromversorgung,

. . . ) bei diesen Bauelementen eher hoch ist, da sie andernfalls sehr viel

teurer w�aren. Aus diesem Grund liefert der LightSensorPeer bei Lego

und Fischertechnik keinen kalibrierten Wert. Ein solcher ist aber trotz-

dem vorhanden um wenigstens die Grenzen des Messbereichs angeben zu

k�onnen. Damit sind zumindest Informationen wie "kein Licht", "Licht"

oder "sehr viel Licht" portabel, also von der Hardware unabh�angig ver-

arbeitbar. Wird doch eine Kalibrierung z.B. auf Lux-Werte gew�unscht,

kann man sich auch hier mit einer entsprechenden Conversion als Dele-

gate helfen.

Ein Port ohne RobotInterface

Da jede der in ART enthaltenen Implementierungen von Sensor auch ohne

ihren bevorzugten Peer auf eine bestimmte Weise versucht trotzdem ihre ge-

samte Funktionalit�at, f�ur die sie gedacht ist, zur Verf�ugung zu stellen, ist

es leicht, diese auch mit einfachen Datenquellen zu verwenden. So stellt die

Klasse ConstantSensorPort zum Beispiel einen Port dar, der einen einfachen

SensorPeer liefert, der immer einen konstanten Wert hat. Mit diesem Port

kann man dann einfach Lichtsensoren, boolesche Sensoren usw. erzeugen, die

ihren Wert nicht ver�andern.

Besondere Beachtung verdient an dieser Stelle auch noch einmal das De-

corator-Pattern. In den Sensor-Klassen ist das dadurch umgesetzt, da� ein

Sensor immer auch einen SensorPort liefern kann, an den weitere Sensoren

angeschlossen werden k�onnen. Diese weiteren Sensoren haben dann einen Peer,

der als Wert immer denWert des Sensors liefert an dessen Port sie angeschlossen

9Genau genommen hat ein RawSensor zwei solche Delegates, einen f�ur die Konvertierung

des Peer-Werts in einen "internen" Wert und einen f�ur die Konvertierung des internen Werts

in den Wert, den er nach au�en hin repr�asentiert (der z.B. von getValue() geliefert wird).

Page 61: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.6. DIE SENSOR-IMPLEMENTIERUNGEN IN ART 55

sind. Da auch die Events weitergeleitet werden, macht es in der Benutzung

am Ende keinen Unterschied, ob ein Sensor-Objekt direkt an den Port eines

RobotInterface angeschlossen ist oder ob da noch weitere Sensor-Objekte

gewisserma�en "zwischengeschaltet" sind. Eine Anwendung dieser Technik w�are

zum Beispiel ein BooleanSensor, der immer dann den Wert true annimmt,

wenn der CountSensor, an den er angeschlossen ist, einen bestimmten Wert

erreicht.

F�ur den Brick, der seine Anschl�usse f�ur die Sensoren unterschiedlich kon-

�gurieren kann (z.B. ob der angeschlossene Sensor mit Strom versorgt wird

oder nicht), ist die Klasse des an einen Port angeschlossenen Sensor-Objektes

ausschlaggebend f�ur die Kon�guration. Schlie�t man nun einen CountSensor

direkt an einen Port der Implementierung von RobotInterface f�ur den Brick

an, so wird der Anschlu� so kon�guriert, wie das im Normalfall f�ur den Ro-

tationssensor von Lego vorgesehen ist. Dies ist nicht immer w�unschenswert,

denn manchmal m�ochte man vielleicht zus�atzlich noch einen Taster anschlie-

�en oder mit dem Rotationssensor etwas anderes machen, als die Rotation zu

messen, wof�ur man dann nicht m�ochte, da� der Brick den Wert des Rotations-

sensors schon vorverabeitet. In diesem Fall kann man direkt an den Port des

RobotInterface einen Sensor anschlie�en, welcher der gew�unschten Kon�gu-

ration entspricht (z.B. einen einfachen RawSensor). An diesen Sensor schlie�t

man wiederum den CountSensor an, den man in diesem Fall nat�urlich "per

Hand" f�ur das Z�ahlen kon�gurieren mu�. Ein Beispiel daf�ur enth�alt der Ab-

schnitt 5.5.2.

Page 62: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

56 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

4.7 Model, View, Controller

Smalltalk-80 (Goldberg und Robson, 1983) enth�alt das ber�uhmte Model-View-

Controller (MVC) Paradigma f�ur die Programmierung von Ober �achen. Eine

Applikation besteht demnach aus drei wesentlichen Bestandteilen:

Ein Model enth�alt die Funktionen und Daten, welche den Kern der An-

wendung ausmachen.

Der Model-Zustand wird auf der Ober �ache von einer View dargestellt.

Der Controller ist schlie�lich f�ur die Interpretation von (meist durch Be-

nutzereingaben ausgel�osten) Events zust�andig und folglich daf�ur verant-

wortlich, wie bestimmte Events von dem Model aufgenommen werden.

ViewModel

Controller

retrieves state

notifies

registers

registers

sends event

manipulates

in response to

events

Abbildung 4.7: Die Beziehungen innerhalb einer Architektur nach Model-View-

Controller.

In Smalltalk-80 war es notwendig, da� Model, View und Controller von

speziellen Klassen abstammen, da auf diese Weise Applikationen besonders ein-

fach in das System integriert werden konnten. Das eigentliche Design-Pattern

dahinter hat sich inzwischen als sehr vorteilhaft erwiesen { auch unabh�angig

von speziellen daf�ur vorgesehenen Basisklassen und Smalltalk. Es de�niert eine

Trennung von Zustandsaufbewahrung (Model) und Zustandsdarstellung (View).

Entsprechend wird durch den Controller die Zuordnung von Operationen auf

dem Zustand (Model) zu den Ausl�osern (Events von der View) exibel.

Das Standardbeispiel f�ur die Demonstration von MVC de�niert zu einem

Model mehrere Views. Diese Views k�onnen v�ollig unabh�angig voneinander ver-

wendet werden, da jede View nichts anderes macht, als den Zustand des Model

darzustellen. Unter Umst�anden bietet sie au�erdem Ansatzpunkte f�ur Benut-

zereingaben, die an den Controller weitergeleitet und von diesem interpretiert

werden. Die Views von dem gleichen Model erscheinen aus Benutzersicht so,

als w�aren sie direkt untereinander verbunden, da eine �Anderung an dem Model

von allen seinen Views wiedergespiegelt wird.

Page 63: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

4.8. SUBSUMPTION-ARCHITEKTUR 57

Obwohl MVC urspr�unglich nur f�ur die Trennung von User-Interface und

Algorithmus entwickelt wurde, ist diese Aufteilung auch in anderen Bereichen

anwendbar. So ist in ART z.B. ein Motor im Grunde eine View f�ur den Zustand

eines ActuatorPeer. Ein Servo ist eine andere View, die an den gleichen Peer

angeschlossen sein kann. Beide Objekte repr�asentieren den gleichen Zustand

und sind, �uber den gemeinsamen ActuatorPeer, aneinander gekoppelt.

Nun kann es aber sinnvoll sein, eine Instanz von Motor wiederum selbst als

ein Model anzusehen, nicht nur weil er (wie ein typisches Model) Methoden

besitzt, um den Zustand des Motors zu manipulieren. Wenn man z.B. in einer

gra�schen Ober �ache, zur Diagnose des Roboters, den Zustand seiner Motoren

darstellen m�ochte, dann ist es vern�unftig (in diesem Kontext) das Motor-Objekt

als Model aufzufassen, dessen Zustand von einer View auf der Ober �ache dar-

gestellt wird.

Meiner Meinung nach mu� die Zuordnung eines Objekts zu einer der drei

Kategorien immer im Verh�altnis zu den anderen Objekten gesehen werden.

Nicht immer ist ein Objekt eindeutig und ausschlie�lich nur ein Model, eine

View oder ein Controller. In den Beziehungen der Objekte untereinander mu�

diese Zuordnung aber eindeutig sein, um den Vorteil von MVC, n�amlich die Un-

abh�angigkeit und Austauschbarkeit der einzelnen Bestandteile, weiter aufrecht

zu erhalten.

4.8 Subsumption-Architektur

Wie bereits in Abschnitt 1.2 auf Seite 4 erw�ahnt ist Subsumption ein von Rod-

ney A. Brooks (Brooks, 1985) erdachtes Konzept zur Steuerung von Robotern.

Aus der Anlehnung an Re exe resultiert, da� die Reaktionen schnell und un-

bewu�t erfolgen sollen. Angewandt auf Roboter bedeutet dieses Konzept, da�

keine langwierigen Berechnungen durchgef�uhrt werden oder ein umfassendes

Weltmodell entworfen wird. Stattdessen werden, f�ur eine einfache Verhaltens-

weise, schnell zu erkennende Zust�ande einer gewissen Teilmenge der Inputs mit

eindeutigen Zust�anden einer gewissen Teilmenge der Outputs verkn�upft. Da die

einzelnen Verhaltensweisen zu verschiedenen Zust�anden f�uhren k�onnen, ist eine

Vorrangregelung notwendig. Durch die Aufteilung in mehrere Verhaltenswei-

sen wird eine gewisse Unabh�angigkeit von Teilbereichen erreicht. Es ist einfach,

neue "Re exe" hinzuzuf�ugen, und f�allt ein Modul aus, so k�onnen die davon

unabh�angigen Teile einfach weiterarbeiten. Die Bedingungen, die zur Aktivie-

rung der Verhaltensweisen f�uhren sowie deren Priorit�aten, sind sogar �uber die

Sofware lernbar (Maes und Brooks, 1990).

Ein gewisses Problem entsteht durch die Forderung nach einem eindeutigen,

schnell zu realisierenden Zustand der Ausg�ange. Teilt man Trusty z.B. in Ver-

haltensweisen auf, so da� eine Verhaltensweise f�ur das Ausweichen zust�andig

ist, so st�o�t man auf genau dieses Problem. Das Ausweichen ist ein Vorgang,

der Zeit ben�otigt und mit einer ganzen Abfolge von Zust�anden der Ausg�ange

realisiert wird.

Prinzipiell ergeben sich hier zwei unterschiedliche L�osungsans�atze:

1. Eine Verhaltensweise wird unterbrechbar. Sie kann dann solange brauchen

Page 64: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

58 4. DIE IDEE DES ABSTRACT ROBOT TOOLKIT

wie sie will, denn wenn sie nicht mehr aktiv sein soll, weil die Bedingungen

sich ge�andert haben, dann wird sie eben unterbrochen. Dies ist, zumindest

in Java, nicht so ohne weiteres realisierbar, da ein Thread nicht einfach

von einem anderen unterbrochen werden darf. Hier mu� man beachten,

da� zwar eine eventuell geeignete Methode (suspend()) existiert, diese

aber seit Version 2 der Java Platform als deprecated gilt, da deren Ver-

wendung leicht zu deadlocks f�uhren kann. Weiterhin sollte ein Thread

mitbekommen k�onnen, wenn er unterbrochen wurde, damit er wei�, da�

der Zustand der Ausg�ange eventuell zwischendurch von au�en ver�andert

wurde.

2. Die Aufteilung in eine Verhaltensweise f�ur das Ausweichen ist nicht ad�a-

quat. F�ur jede Zustands�anderung bei der Durchf�uhrung von Ausweichen

mu� eine eigene Verhaltensweise implementiert werden. So k�onnte zum

Beispiel eine Verhaltensweise a, die Trusty r�uckw�arts fahren l�a�t, durch

das Ausl�osen des Bumpers aktiviert werden und nach dem Ausl�osen f�ur

einen gewissen Zeitraum aktiv sein. Eine weitere Verhaltensweise b k�onnte

als Input f�ur die Entscheidung �uber ihre Aktivierung genau den Aktivie-

rungszustand von a besitzen. Sobald a "lange genug" aktiv war oder von

aktiv auf inaktiv wechselt, wird b aktiv und dreht Trusty ein wenig { dies

nat�urlich wieder nach dem gleichen Prinzip, da� b nicht andere Verhal-

tensweisen w�ahrenddessen blockiert.

F�ur den ersten beschriebenen L�osungsansatz w�are es notwendig, da� eine

Verhaltensweise, die l�anger braucht, h�au�g genug selbst eine M�oglichkeit zur

Unterbrechung von au�en vorsieht. Ob dies dann im Zusammenhang mit Sub-

sumption �uberhaupt noch eine sinnvolle Architektur ist, mu� sich erst zeigen.

Der 2. L�osungsansatz geht zwar konform mit dem Subsumption-Konzept,

ist aber auch nur mit etwas Aufwand zu implementieren. Hier k�onnte eventuell

ein geeigenetes API die Idee, da� manche Verhaltensweisen in einer gewissen

zeitlichen Abfolge geschehen sollen, unterst�utzen.

Page 65: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5

Ariadne & ART - Ein Tutorial

Dieses Kapitel ist in erster Linie ein Tutorial f�ur die Benutzung des Abstract

Robot Toolkit (ART). Es bietet sich aber an, dies mit der Ausarbeitung der

Vor- und Nachteile der Benutzung dieses Systems im Gegensatz zu den Pro-

grammiersystemen aus Kapitel 3 auf Seite 13 zu verbinden.

Anhand einiger kleinerer Beispiele wird zuerst die grunds�atzliche Bedeutung

der Frontend-Klassen erkl�art. Dazu geh�oren alle Klassen, die dazu gedacht sind,

da� ein Algorithmus sie zur Steuerung eines Roboters verwendet, sowie die Klas-

sen, mit denen man eine Verbindung zu der eigentlichen Hardwareansteuerung,

dem Backend, herstellt.

Auf dieser �Ubersicht und den einfachen Beispielen bauen die folgenden Ab-

schnitte auf, in denen es um die Programmierung des Beispielroboters Ariadne

mit seinen Modulen Trusty und LiSe geht. Manch einem Leser wird die Anzahl

der dabei erzeugten Klassen vielleicht unn�otig gro� vorkommen. Sp�atestens bei

der Verbindung von Trusty und LiSe zu Ariadne sollte aber der Vorteil der

verschiedenen Abstraktionsebenen sichtbar werden.

Die vollst�andigen Quelltexte f�ur die Beispiele sind auf der CD zu dieser

Arbeit enthalten und im Internet verf�ugbar. Siehe dazu Abschnitt A.1 auf Sei-

te 136 im Anhang zu dieser Arbeit.

Zum Verst�andnis dieses Kapitels sind Kenntnisse in objektorientierter Pro-

grammierung und der Programmiersprache Java notwendig. Zum Lernen von

Java und zum Nachschlagen kann man z.B. Flanagan (1999), Sun Microsystems

(2001) und Schreiner (2000a) verwenden.

Weiterhin ist es f�ur das Verst�andnis einiger der komplexeren Beispiele hilf-

reich, zu wissen was Subsumption ist, da dieses Programmier-Konzept f�ur Robo-

ter mehrmals zur Anwendung kommt. Eine kurze Einf�uhrung in dieses Konzept

steht in Abschnitt 1.2 auf Seite 4.

5.1 "Hello, Robot!"

Das Standardbeispiel bei der Einf�uhrung in eine neue Programmiersprache ist

"Hello, World!" (Kernighan und Ritchie, 1990, S. 5). Nun geht es hier zwar nicht

um eine neue Sprache, aber doch immerhin um eine neue Klassenbibliothek zur

Steuerung von Robotern. Ein m�oglichst einfaches Programm, das einen Motor

59

Page 66: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

60 5. ARIADNE & ART - EIN TUTORIAL

einschaltet, k�onnte folgenderma�en aussehen:

Listing 4: code/art/examples/HelloRobot.java

package de.jaetzold.art.examples;

import de.jaetzold.art.RobotInterfaceFactory;import de.jaetzold.art.RobotInterface;import de.jaetzold.art.ActuatorPort;import de.jaetzold.art.Motor;

public class HelloRobot {public static void main(String[] argv) {

RobotInterfaceFactory factory = new RobotInterfaceFactory();RobotInterface hardware = factory.getInterface();ActuatorPort port = hardware.getActuatorPorts(0);

Motor motor = new Motor();motor.connectWith(port);

motor.on();

try {Thread.sleep(1000);

} catch(InterruptedException ie) {}

}}

Zum Kompilieren und Ausf�uhren m�ussen nat�urlich alle ben�otigten Klassen

�uber den Klassenpfad erreichbar sein. Falls also eine Fehlermeldung kommt,

da� irgendein Typ nicht de�niert ist oder eine Klasse nicht gefunden wurde,

empfehle ich Abschnitt A auf Seite 135 im Anhang.

Funktioniert alles erwartungsgem�a�, l�auft ein (an dem ersten Ausgang des

Interfaces angeschlossener) Motor kurz an und es erscheint in etwa die folgende

Ausgabe auf der Konsole:

Successfully initialized Fischertechnik-Interface, found onserialport COM2

Erscheint die Ausgabe nicht oder l�auft der Motor nicht an, dann hilft viel-

leicht ein Blick in Anhang B auf Seite 139. Eine eventuelle NullPointer-

Exception weist darauf hin, da� kein Interface gefunden wurde. Eine Array-

IndexOutOfBoundsException hat wahrscheinlich die Ursache, da� das gefunde-

ne Interface keine ActuatorPorts bereitstellt, von denen man aber wenigstens

einen ben�otigt, um den Motor daran anzuschlie�en.

Die NullPointerException entsteht, weil getInterface() einen null-

Verweis liefert, wenn keine Interface-Hardware gefunden werden konnte. Beson-

dere Fehlersituationen werden in Java eigentlich �uber Exceptions signalisiert

und es ist kein guter Stil, wenn dies �uber das Resultat geschieht. In diesem kon-

kreten Fall kann man aber eine Ausnahme machen, da einerseits ausgeschlos-

Page 67: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.1. "HELLO, ROBOT!" 61

sen werden kann, da� f�ur diese Methode null als "regul�ares" Resultat jemals

wirklich gebraucht wird und andererseits das Fehlen einer Interface-Hardware

ja nicht unbedingt als eine Fehlersituation angesehen werden mu�. Insbe-

sondere gibt es noch andere Methoden, wie getInterfaces(), die ein ganzes

Array mit den gefundenen RobotInterface zur�uckliefert. Wird keins gefun-

den, ist es ein Array der L�ange 0. Eine Exception w�are f�ur diese Methode

nicht sinnvoll und entsteht daher auch nicht in den anderen Methoden von

RobotInterfaceFactory die ein RobotInterface als Resultat haben.

Nun zur Beschreibung des Listing 4 auf der vorherigen Seite:

Als erstes wird ein Objekt der Klasse RobotInterfaceFactory aus dem packa-

ge de.jaetzold.art1 erzeugt. Damit f�angt immer alles an bei der Program-

mierung mit ART, denn Roboter haben immer ein Hardware-Interface, das

der Computer ansteuert, und dessen Repr�asentierung, in Form eines Robot-

Interface, bekommt man durch den Aufruf getInterface() von der Robot-

InterfaceFactory.

Eines der Anliegen von ART ist es, von der konkreten Interface-Hardware

zu abstrahieren. Aus diesem Grund wird das Objekt, welches diese Hardware

repr�asentieren soll, nicht vom Programmierer selbst erzeugt. Der Programmie-

rer soll am besten gar nicht wissen, welche Klasse welches Interface an welchem

Anschluss ansteuert.

Objekte der Klasse2 RobotInterfacewerden also nach dem Factory-Muster

erzeugt. Zur n�aheren Erl�auterung dieses Design Patterns siehe Gamma et al.

(1995) oder auch Schreiner (1999).

Will man aus irgendeinem Grund nur einen ganz bestimmten Typ Interface

ansteuern oder legt besonderen Wert auf die Anschl�usse, an denen nach Inter-

faces geschaut wird, kann man das durch einen Parameter zu getInterface()

beein ussen, doch dazu kommen wir erst sp�ater, auf Seite 68 in Abschnitt 5.2.

Jetzt geht's erst einmal weiter mit HelloRobot.

Der Verweis hardware ist also das Objekt, welches das Harware-Interface

repr�asentiert. Um einen Motor zu steuern, mu� dieser aber an die Hardware

angeschlossen werden, genauer, an einen Port des RobotInterface. Genau-

genommen sogar an einen ActuatorPort, denn diese repr�asentieren einzelne

Ausg�ange der Interface-Hardware.

Alle ActuatorPorts eines RobotInterface werden in einem Array gespei-

chert und man kann nach JavaBeans-Manier darauf zugreifen (sogenannte in-

dexed property, siehe Sun Microsystems (1997)). Wenn das erste gefundene In-

terface also �uberhaupt Ausg�ange hat, dann hat das Array der ActuatorPorts

mindestens einen Eintrag, und den ersten davon bekommt man durch die Nach-

richt getActuatorPorts(0) an hardware.

Nun kann ein Objekt der Klasse Motor mit dem port verbunden werden.

Daf�ur schickt man dem motor die Nachricht connectWith mit dem port als

Parameter. Der motor wird hier zwar erst kurz vorher erzeugt, das ist aber

nicht notwendig. Man h�atte den motor auch als allererstes erzeugen k�onnen,

1Im folgenden Text werden, wenn es sich aus dem Kontext bereits erschlie�en l�a�t, keine

vollquali�zierten Klassennamen mehr angegeben.2Genaugenommen ist RobotInterface gar keine Klasse sondern ein Java-interface, an

dieser Stelle kann man aber so tun, als w�are es eine Klasse.

Page 68: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

62 5. ARIADNE & ART - EIN TUTORIAL

noch bevor die Factory erzeugt wird, doch wenn dann gar kein Anschlu� f�ur

den Motor zur Verf�ugung gestanden h�atte, w�are er ja umsonst erzeugt worden.

Sobald ein Motor mit einem ActuatorPort eines RobotInterface erfolg-

reich verbunden wurde, kann er auch schon benutzt werden, um den Zustand

eines realen, mit der Interface-Hardware verbundenen Motors zu manipulieren.

Da die Aufgabe von HelloRobotwar, einen Motor anzuschalten, ist das auch

schon der n�achste Aufruf: motor.on(). Der Rest des Codes dient nur dazu, da�

das Programm nicht sofort wieder zu Ende geht, denn dann w�urde der Motor

unter Umst�anden, sofort nachdem er angeschaltet wurde, wieder ausgehen, weil

die Interfacehardware keine Signale mehr vom Computer erh�alt.

Implementierungen von RobotInterface erzeugen zwar in den meisten F�al-

len eigene Threads zur Kommunikation mit der Interfacehardware, diese sollten

aber Daemon-Threads sein, die die virtuelle Maschine nicht von sich aus am

Laufen halten.

5.2 DriveTrain

Wer sich im vorherigen Abschnitt gefragt hat, wie das denn funktionieren soll

{ einen Roboter zu steuern, ohne etwas �uber ihn zu wissen { ist hier richtig. Es

wird nun auch darum gehen, wie man einen Steuerungsalgorithmus f�ur mehrere

Roboter wiederverwenden kann.

In diesem Abschnitt wird ein Roboter programmiert, der fahren kann. Eine

typische Bauweise f�ur einen einfachen fahrenden Roboter ist, zwei gegen�uberlie-

gende R�ader oder Ketten unabh�angig voneinander durch jeweils einen eigenen

Motor anzutreiben. Auf diese Weise kann der Roboter vorw�arts und r�uckw�arts

fahren, sich auf der Stelle links- und rechtsherum drehen sowie { durch verschie-

den schnelles Drehen der R�ader { richtige Kurven fahren. Die Fortbewegung von

Kettenfahrzeugen, wie z.B. Baggern, funktioniert �ahnlich.

Abbildung 5.1: Zwei einfache fahrende Roboter aus den Bauanleitungen des Lego RIS

1.5 und Fischertechnik Mobile Robots.

Page 69: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.2. DRIVETRAIN 63

Abbildung 5.1 auf der vorherigen Seite zeigt eine solche Konstruktion mit

LEGO sowie mit Fischertechnik. Bauanleitungen f�ur �ahnliche Roboter �ndet

man auch in Knudsen (1999) und Baum (2000).

Das Java-Interface DriveTrain

Letzten Endes ist es doch so, da� man einen Roboter haben m�ochte, der sich

fortbewegen kann { am besten in beliebige Richtungen (vorw�arts, r�uckw�arts,

seitw�arts, hoch, runter, usw.). Au�erdem soll er noch in der Lage sein, seine

Orientierung zu ver�andern (sich drehen). Damit die Bewegung sch�on aussieht,

w�are es au�erdem w�unschenswert, wenn die Fortbewegung nicht nur auf Ge-

raden sondern auch auf Kurven verlaufen k�onnte. Dabei w�are es sinnvoll, dem

Roboter nicht nur sagen zu k�onnen, wie weit er sich bewegen soll, sondern auch

wie schnell.

Das sind alles zusammen ziemlich gro�e Anspr�uche an den Roboter und,

da� sich ein Roboter beliebig im Raum bewegen und orientieren kann, erfor-

dert einen gro�en Konstruktionsaufwand, um den es an dieser Stelle nicht geht.

Um also realistisch zu bleiben, werden die Anforderungen an den Roboter fol-

genderma�en festgelegt:

Der Roboter soll vorw�arts fahren,

r�uckw�arts fahren,

sich auf der Stelle linksherum drehen,

sich auf der Stelle rechtsherum drehen

und anhalten (!)

k�onnen. Au�erdem wird die Angabe einer Strecke und/oder Geschwindigkeit

(zumindest vorerst) der Einfachheit halber au�er Acht gelassen.

Die eben de�nierte Funktionalit�at erfordert einen Algorithmus, der sie im-

plementiert. Au�erdem mu� ein Roboter (wie z.B. in Abbildung 5.1 auf der

vorherigen Seite) her, der diese Funktionen hardware-technisch erm�oglicht. Die

Umsetzung von einem Befehl wie "Vorw�arts" auf Befehle an die Komponenten

des Roboters, wie z.B. die Motoren, h�angt davon ab, wie der Roboter gebaut

wurde. Daher ist es sinnvoll die Anforderungen von der konkreten Umsetzung zu

trennen. In Java macht man dies �uber die De�nition eines sogenannten Interface,

welches dann von verschiedenen Klassen adaptiert (und damit implementiert)

werden kann:3

Listing 5: code/art/examples/DriveTrain.java

package de.jaetzold.art.examples;

public interface DriveTrain {public void forward();

➥3Eine andere M�oglichkeit w�are die De�nition einer Basisklasse.

Page 70: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

64 5. ARIADNE & ART - EIN TUTORIAL

Listing 5: code/art/examples/DriveTrain.java (Fortsetzung)

public void backward();public void leftSpin();public void rightSpin();public void stop();public void resume();

<see Listing 11 on page 73>}

Anhand des Namens der Methoden ist leicht erkennbar, welche der eben de�-

nierten Anforderungen mit ihr umgesetzt werden soll. Die neu hinzugekommene

Methode resume()mu� noch de�niert werden. Aus Gr�unden der �Ubersichtlich-

keit wurde auf die Angabe von JavaDoc-Kommentaren verzichtet.4

Die ersten vier Methoden forward() bis rightSpin() sollen alle daf�ur sor-

gen, da� nicht nur die Bewegungsrichtung festgelegt wird sondern der Roboter

sich dann auch wirklich in Bewegung setzt (falls er vorher still gestanden hat).

Bis auf forward() ist eine Implementierung von DriveTrain aber nicht

verp ichtet, diesen Zustand auch wirklich umzusetzen. Es w�are ja zum Bei-

spiel ein Roboter vorstellbar, der nur vorw�arts und r�uckw�arts fahren, sich aber

nicht drehen kann. Knudsen's Minerva (Knudsen, 1999, S. 82�) z.B. kann nur

vorw�arts fahren und sich in eine Richtung drehen. Aus diesem Grund soll hier

darauf hingewiesen werden, da� die Methoden backward(), leftSpin() und

rightSpin() eine Exception ausl�osen k�onnen. Da keine throws-Klausel an-

gegeben wurde, darf das nur eine RuntimeException sein. Eine java.util.

UnsupportedOperationException bietet sich in diesem Fall an. Ein Algorith-

mus, der DriveTrain benutzt, f�angt diese sinnvollerweise auch nur dann ab,

wenn er auf die fehlende Funktionalit�at selber reagieren m�ochte, indem er es

z.B. mit einer Linksdrehung versucht, falls eine Rechtsdrehung nicht unterst�utzt

wird.

Die Methode stop() h�alt die Bewegung des Roboters an. Die Methode

resume() dient dazu, nach einem oder mehreren aufeinanderfolgenden stop(),

wieder zu dem Zustand vor STOP zur�uckzukehren. Zu Beginn startet Drive-

TrainSimpleAlgorithm im STOP-Zustand und es gibt keinen anderen Zustand

in den resume() zur�uckkehren k�onnte. In diesem Fall bewirkt resume() daher

nichts.

Der Code von DriveTrain wurde in Listing 5 nicht ganz vollst�andig an-

gegeben. Die ausgelassenen Zeilen de�nieren die Zust�ande in denen sich ein

DriveTrain be�nden kann, und eine Methode um selbigen abzufragen. Dies

kann verwendet werden um z.B. eine gra�sche View f�ur DriveTrain-Objekte

zu implementieren (siehe Abschnitt 5.3 auf Seite 73).

Implementierung von DriveTrain

Ein Interface wie DriveTrain beschreibt nur, wie ein Objekt einer Klasse, die

dieses Interface adaptiert, benutzt werden kann. F�ur einen Roboter wie aus

4Die Klassen aus dem package de.jaetzold.art.examples, in denen keine JavaDoc-

Kommentare enthalten sind, werden in diesem Tutorial beschrieben.

Page 71: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.2. DRIVETRAIN 65

Abbildung 5.1 auf Seite 62 soll nun eine einfache Implementierung vorgestellt

werden.

Das entscheidende Kriterium f�ur einen solchen Roboter ist, da� er zwei Mo-

toren hat, einen linken und einen rechten, und da� diese Motoren so eingebaut

und angeschlossen sind, da� folgende Bedingungen erf�ullt sind:

� Sind beide Motoren an und auf "forward" gestellt, f�ahrt der Roboter

vorw�arts.

� Sind beide Motoren an und auf "backward" gestellt, f�ahrt der Roboter

r�uckw�arts.

� Sind beide Motoren an und drehen sich in verschiedene Richtungen, dann

dreht sich auch der Roboter. Er dreht sich linksherum, wenn der linke

Motor auf "backward" gestellt ist. Er dreht sich rechtsherum, wenn es

der rechte Motor ist, der r�uckw�arts l�auft.

Daf�ur, da� die Motoren diese Anforderungen erf�ullen, soll nicht die Drive-

Train-Implementierung zust�andig sein. Vielmehr sollen in dieser Implemen-

tierung erst einmal die Anforderungen des DriveTrain-Interfaces auf solche

Motoren umgesetzt werden:

Listing 6: code/art/examples/DriveTrainSimpleAlgorithm.java (Ref. in Listing 7 S. 66)

protected Motor left;protected Motor right;

protected int state;

public void stop() {right.off();left.off();

setState(state | STOP);}

public void resume() {if(state != STOP) {

right.on();left.on();

setState(state & ˜ STOP);}

}

public void forward() {right.forward();left.forward();

setState(FORWARD);resume();

}➥

Page 72: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

66 5. ARIADNE & ART - EIN TUTORIAL

Listing 6: code/art/examples/DriveTrainSimpleAlgorithm.java (Fortsetzung)

...public void leftSpin() {

right.forward();left.backward();

setState(LEFT SPIN);resume();

}...

Die Programmierung entspricht ziemlich genau der Funktionalit�at, die von

den Motoren verlangt wird. Die Verweise auf die Motoren sind mit left und

right bezeichnet und besitzen Methoden f�ur on(), off(), forward() und

backward(), deren Bedeutung weitgehend selbsterkl�arend ist. Eine genaue Be-

schreibung �ndet sich in der Klassendokumentation zu Motor (Siehe Anhang A.2

auf Seite 137).

Nachdem die Motoren z.B. in der Methode leftSpin() auf entgegengesetzte

Drehrichtung gesetzt wurden, wird der Zustand des DriveTrain durch den

Aufruf von setState(int) neu gesetzt. Auf diese Methode wird in Abschnitt

5.3 eingegangen.

Wichtig ist aber, da� nach dem Setzen der Zust�ande5 der Motoren noch

resume() aufgerufen wird. Die Zust�ande an/aus, sowie vorw�arts/r�uckw�arts ei-

nes Motor-Objekts sind voneinander unabh�angig und ein einfacher Aufruf von

forward() f�uhrt nicht dazu, da� sich der entsprechende Motor einschaltet, son-

dern nur dazu, da� er sich vorw�arts dreht, wenn er bereits an ist bzw. sobald

er angeschaltet wird.

Die Methode resume() schaltet die Motoren an, sofern sich DriveTrain

nicht in einem reinen STOP-Zustand be�ndet. Ein eventuell trotzdem vorhan-

denes STOP-Bit in der Variable state, welche den aktuellen Zustand speichert,

wird gel�oscht. Entsprechend werden in stop() die Motoren ausgeschaltet und

das STOP-Bit gesetzt.

Die Stellen mit ". . . " markieren Auslassungen der Methoden backward()

und rightSpin(), weil diese analog zu den abgedruckten Methoden imple-

mentiert sind, sowie Stellen, die f�ur ein Verst�andnis der Implementierung nicht

unbedingt notwendig sind. Der interessierte Leser wird ermuntert, selbst einen

Blick in die Quellen zu werfen.

Es fehlt noch der Teil des Codes, in dem das DriveTrainSimpleAlgorithm-

Objekt initialisiert wird, der Konstruktor :

Listing 7: code/art/examples/DriveTrainSimpleAlgorithm.java

package de.jaetzold.art.examples;

import de.jaetzold.art.Motor;...

5Die Erkl�arung der dabei verwendeten Konstanten wie RIGHT SPIN und STOP be�ndet sich

bei Listing 11 auf Seite 73.

Page 73: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.2. DRIVETRAIN 67

Listing 7: code/art/examples/DriveTrainSimpleAlgorithm.java (Fortsetzung)

public class DriveTrainSimpleAlgorithm implements DriveTrain {public DriveTrainSimpleAlgorithm(Robot robot) {

this.left = robot.getLeftMotor();this.right = robot.getRightMotor();setState(STOP);stop();

}<see Listing 8 on page 67><see Listing 6 on page 65><see Listing 13 on page 75>...

}

An dieser Stelle kommen wir der eigentlichen Roboterhardware n�aher. Der

Konstruktor mu� irgendwie die beiden Motor-Verweise left und right initia-

lisieren. Dazu wird ein Robot-Objekt �ubergeben, das man nach den Motoren

fragen kann.

Damit DriveTrainSimpleAlgorithm korrekt funktioniert, m�ussen die Mo-

toren den Anforderungen gen�ugen, die auf Seite 65 festegelegt wurden. Welcher

Motor an welchem Anschlu� der Hardware angeschlossen ist, sowie die Polung

der Motoren, ist f�ur den Algorithmus DriveTrainSimpleAlgorithm jedoch gar

nicht interessant. Es reicht v�ollig aus, wenn der Algorithmus bereits richtig

angeschlossene und kon�gurierte Motoren bekommt und wei�, welcher rechts

und welcher links ist. Daher de�niert der Algorithmus ein Interface Robot.

Dieses Interface beschreibt damit sozusagen Roboter, die von dem Algorithmus

gesteuert werden k�onnen.

Listing 8: code/art/examples/DriveTrainSimpleAlgorithm.java (Ref. in Listing 7 S. 66)

public static interface Robot {public Motor getLeftMotor();public Motor getRightMotor();

}

Ein Interface legt eigentlich nur die Signaturen, sowie die Resultattypen von

Methoden fest. Trotzdem gibt es f�ur jede De�nition eine Vereinbarung dar�uber,

was von ihr erwartet wird. Diese Vereinbarung sollte, z.B. durch einen JavaDoc-

Kommentar, explizit gemacht werden, damit klar ist, wof�ur das Interface genau

steht. Nur durch Angabe einer Signatur und des Resultattyps ist zwar klar, wie

eine Methode benutzt werden kann, aber nicht wof�ur. Um ein m�oglichst gleich-

artiges und vorhersagbares Verhalten von verschiedenen Implementierungen ei-

nes Interfaces zu gew�ahrleisten ist es unerl�a�lich, dieses Verhalten zusammen

mit dem Interface zu de�nieren. F�ur DriveTrainSimpleAlgorithm.Robothei�t

das, da� die Methoden Motor-Objekte als Resultat liefern sollten, die den An-

forderungen gen�ugen von Seite 65 gen�ugen.

Eine solche Robot-Implementierung be�ndet sich auf einer "niedrigeren"

Abstraktionsebene in Bezug auf den zu steuernden Roboter. Sie h�angt st�arker

als der vorher gezeigte Algorithmus von dem konkreten Roboter ab, den man

Page 74: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

68 5. ARIADNE & ART - EIN TUTORIAL

steuern m�ochte. Wichtig ist zum Beispiel, an welchen ActuatorPort welcher

Motor angeschlossen werden mu�, ob �uberhaupt echte Motor-Objekte erzeugt

werden, oder etwa eine Unterklasse davon. Schlie�lich mu� auch die Drehrich-

tung eventuell an das Modell angepasst werden, damit "vorw�arts" auch die

korrekte Bedeutung f�ur den Roboter erh�alt.

Hier soll ein Beispiel f�ur eine Implementierung von DriveTrainSimple-

Algorithm.Robot gegeben werden, die davon ausgeht, da� bei dem zu steuern-

den Roboter die entsprechenden, ganz normalen Motoren an den Ausg�angen 0

und 1 angeschlossen sind. Welche Anschl�usse damit an der jeweiligen Hardware

gemeint sind, h�angt nat�urlich von der Implementierung von RobotInterface

ab. Bei der in ART enthaltenen Implementierung f�ur Fischertechnik sind das

M1 und M2, beim Cybermaster die beiden eingebauten Motoren und beim Brick

die Anschl�usse 1 und 2. Die Drehrichtung wird in diesem Beispiel noch nicht

angepasst. Im weiteren Verlauf dieses Kapitels wird aber auch darauf R�ucksicht

genommen.

Listing 9: code/art/examples/DriveTrainSimpleRobot.java

package de.jaetzold.art.examples;

import de.jaetzold.art.Motor;import de.jaetzold.art.ActuatorPort;import de.jaetzold.art.RobotInterface;import de.jaetzold.art.RobotInterfaceDefinition;import de.jaetzold.art.RobotInterfaceStringDefinition;

public class DriveTrainSimpleRobotimplements DriveTrainSimpleAlgorithm.Robot

{protected Motor leftMotor;protected Motor rightMotor;

public DriveTrainSimpleRobot(RobotInterface iface) {ActuatorPort[] ports = iface.getActuatorPorts();if(ports.length < 2) {

throw new IllegalArgumentException("RobotInterface "+iface+" provides only "+ports.length+" Ports, minimum is 2.");

}

leftMotor = new Motor();leftMotor.connectWith(ports[0]);

rightMotor = new Motor();rightMotor.connectWith(ports[1]);

}

public Motor getLeftMotor() {return leftMotor;

Page 75: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.2. DRIVETRAIN 69

Listing 9: code/art/examples/DriveTrainSimpleRobot.java (Fortsetzung)

}public Motor getRightMotor() {

return rightMotor;}public DriveTrainSimpleRobot(RobotInterfaceDefinition definition) {

this(new de.jaetzold.art.RobotInterfaceFactory().getInterface(definition));

}public DriveTrainSimpleRobot(String interfacePortName) {

this(new RobotInterfaceStringDefinition(interfacePortName));}public DriveTrainSimpleRobot() {

this(System.getProperty(className +".portName", "ALL"));}private static String className =

"de.jaetzold.art.examples.DriveTrainSimpleRobot";...

}

Eine Implementierung f�ur einen weiteren, etwas anderen Roboter zeigt Lis-

ting 10 auf Seite 71. Die hier gezeigte Implementierung besitzt mehrere Kon-

struktoren, um auf verschiedenen Ebenen in die Erzeugung des RobotInterface

eingreifen zu k�onnen:

Der erste Konstruktor erwartet bereits ein fertiges RobotInterface, das

nichts weiter aufweisen mu� als zwei Ports, um die Motoren daran anzuschlie-

�en. Wie das genau geht, wurde bereits in Abschnitt 5.1 auf Seite 59 erl�autert.

Der an Port 0 angeschlossene Motor mu� der linke sein, der an Port 1 ange-

schlossene der rechte.

Der zweite Konstruktor von DriveTrainSimpleRobot gibt einem die M�og-

lichkeit, �uber ein String-Objekt festzulegen, welches Interface an welchem

Port f�ur den Anschlu� der Motoren verwendet werden soll. RobotInterface-

Definition ist ein Interface, welches keine Methoden vorschreibt. Objekte

von Klassen, die dieses Interface adaptiert haben, k�onnen aber der Robot-

InterfaceFactory als Parameter f�ur die Konstruktion eines RobotInterface

�ubergeben werden. Damit kann eingeschr�ankt werden, welche Implementierung-

en von RobotInterface die Factory zur�uckliefert.

Von einer Implementierung von RobotInterfaceDefinition wird nichts

Besonderes erwartet, es h�atten auch schlicht Objekte vom Typ Object ver-

langt werden k�onnen, doch w�are damit der Sinn dieses Parameters schwieriger

zug�anglich gewesen. Welche Implementierung von RobotInterfaceDefinition

ben�otigt wird, h�angt von den Implementierungen von RobotInterface, die

einen speziell interessieren, ab und sollte in deren Beschreibung dokumentiert

sein.

Die bereits vorhandenen Implementierungen f�ur LEGO und Fischertechnik

reagieren auf Strings, welche von einer RobotInterfaceStringDefinition ge-

kapselt werden. Zur einfacheren Benutzung wird daher auch gleich noch ein

Konstruktor mit einem String als Parameter zur Verf�ugung gestellt.

Strings als RobotInterfaceDefinition bieten den Vorteil, da� �uber soge-

Page 76: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

70 5. ARIADNE & ART - EIN TUTORIAL

nannte Properties wie z.B. im dritten, parameterlosen Konstruktor leicht ge-

steuert werden kann, welches Interface genommen werden soll. Dieser String

beginnt mit einer Kennzeichnung f�ur das Interface, welches man haben m�ochte,

und darauf folgt (optional) der Name des (seriellen) Ports, an dem nach dem

Interface gesucht werden soll. Beispiele:

"FT" { die Implementierung von Fischertechnik sucht auf allen m�oglichen Ports

nach einem Interface

"MSCOM2" { auf dem von JavaComm6 mit COM2 bezeichneten seriellen Port wird

nach einem Brick gesucht

"CM/dev/ttyS0" { auf dem Port mit Namen /dev/ttyS0 wird nach einem

Cybermaster-Interface gesucht7

"RCX1" { auf COM1, /dev/ttyS0 sowie dem ersten von JavaComm gelieferten

Portnamen f�ur einen seriellen Port wird nach einem Cybermaster oder

einem Brick gesucht

Das letzte Beispiel steht f�ur eine besondere Interpretation des Portnamens

durch die Implementierungen f�ur Lego und Fischertechnik. Besteht der Port-

name ausschlie�lich aus einer Zahl "n", werden als Portnamen die beiden vor-

de�nierten Namen COMn und /dev/ttySn genommen und au�erdem der n-te

Name eines seriellen Ports aus der Liste von Portnamen, die man von Java-

Comm als Enumeration geliefert bekommt. Es ist zwar nicht genau spezi�ziert,

aber bei Tests wurden die seriellen Ports bisher immer in der Reihenfolge an-

gegeben, wie sie auch vom jeweiligen System nummeriert werden. Die Namens-

gebung ist jedoch von der verwendeten Implementierung des Java Communi-

cations API abh�angig. Die Implementierung von Sun f�ur Windows, sowie die

Implementierung von IBM f�ur Linux und f�ur Windows, nennen serielle Ports

COM1, COM2 usw. Die freie Implementierung "rxtx" ( http://www.rxtx.org )

nennt serielle Ports unter Linux wie die entsprechenden Device-Namen, also z.B.

/dev/ttyS0, /dev/ttyS1 usw. Eine Einf�uhrung in das Java Communications

API gibt J�atzold (1999).

Tests zeigen, da� die Implementierung von Sun unter Windows extrem lang-

sam ist. Die in Schreiner (2000b) beschriebenen Geschwindigkeitsprobleme tre-

ten sowohl mit rxtx unter Linux als auch mit der Implementierung von IBM

unter Windows und Linux nicht auf.

Zum Testen, ob alles funktioniert, kann die Klasse DriveTrainSimpleRobot

auch direkt ausgef�uhrt werden. Die main-Methode erzeugt sogar aus einem �uber-

gebenen Argument die verwendete RobotInterfaceStringdefinition. Alter-

nativ kann auch "von Hand" die Property de.jaetzold.art.examples.Drive-

TrainSimpleRobot.portName gesetzt werden:

$ java -Dde.jaetzold.art.examples.DriveTrainSimpleRobot.port➥

6Java Communications API. Siehe Sun Microsystems (1998) und J�atzold (1999).7Der Cybermaster wird in der aktuellen Version von ART nicht mehr unterst�utzt. Zuk�unf-

tige Versionen k�onnten diese Unterst�utzung aber m�oglicherweise wieder enthalten.

Page 77: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.2. DRIVETRAIN 71

Name=RCX2 de.jaetzold.art.examples.DriveTrainSimpleRobot

Successfully initialized LEGO-Mindstorms Interface, found onserialport COM2$

Kommt eine vergleichbare Meldung, dann hat alles wie erwartet geklappt.

Kommt aber zum Beispiel eine Exception, hilft ein Blick in den Anhang, Ab-

schnitt B auf Seite 139 und/oder der Abschnitt A auf Seite 135, m�oglicherweise

weiter. Das Fenster, das bei erfolgreicher Ausf�uhrung ge�o�net wird, kann man

schon mal zum Testen verwenden. Wieso dieses Fenster �uberhaupt auftaucht,

wird am Ende dieses Abschnitts und in dem darauf Folgenden n�aher erl�autert.

Hat man aus irgendeinem Grund bereits ein fertiges Robotermodell, bei

dem die Motoren nicht so angeschlossen sind, da� DriveTrainSimpleRobot f�ur

DriveTrainSimpleAlgorithm geeignet ist, mu� man nicht unbedingt das ge-

samte Interface DriveTrainSimpleAlgorithm.Robot neu implementieren. Man

kann sich die F�ahigkeiten von objektorientierter Programmierung zunutze ma-

chen und einfach eine Unterklasse von DriveTrainSimpleRobot implementie-

ren, die die Motoren auf geeignete Weise manipuliert.

Der f�ur diese Arbeit gebaute Beispielroboter hat in seiner Lego-Version die

Motoren anders angeschlossen:

Listing 10: code/art/examples/DriveTrainSimpleMSDemoRobot.java

public class DriveTrainSimpleMSDemoRobotextends DriveTrainSimpleRobot

{public DriveTrainSimpleMSDemoRobot(RobotInterface iface) {

super(iface);// the Motors on the MS-Robot are on different sidesMotor tmp = leftMotor;leftMotor = rightMotor;rightMotor = tmp;// the Motors on the MS-Robot turn the other way roundleftMotor.setReversed(true);rightMotor.setReversed(true);

}public DriveTrainSimpleMSDemoRobot(String interfacePortName) {

this(new de.jaetzold.art.RobotInterfaceFactory().getInterface(interfacePortName));

}public DriveTrainSimpleMSDemoRobot() {

this(System.getProperty(className +".portName", "MS"));}private static String className =

"de.jaetzold.art.examples.DriveTrainSimpleMSDemoRobot";...

}

Da die Motoren aber auch an den ersten und den zweiten Ausgang ange-

schlossen sind, ist es nicht n�otig neue Motor-Objekte zu erzeugen. Die Vorhan-

Page 78: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

72 5. ARIADNE & ART - EIN TUTORIAL

denen werden einfach vertauscht und auf die umgekehrte Drehrichtung gesetzt.

Ansonsten kann weiterhin zur Steuerung DriveTrainSimpleAlgorithmverwen-

det werden.

DTSA.Robot

getRightMotor()

getLeftMotor()

DTSRobot

Motor

stop()

backward()

forward()

DTSAlgorithm

leftMotor

ActuatorPort

(e.g. CountSensor)Virtual Sensors:

SwitchSensor2

AnalogSensor1

Motor1

Motor2

Motor3

Motor4

SwitchSensor1

AnalogSensor2

SwitchSensor8

RobotInterface

"Wire"

Ethernet, ...)Bluetooth,(RS232, I2C,

state−changeinforms about

retrieved fromRobotInterface

withinitialized

is a

(implements)retrieved

from factory

connects Motorwith interface

with port& connects

& deliversMotor

configurescreates,

DTSA = DriveTrainSimpleAlgorithm

DTS = DriveTrainSimple

Abbildung 5.2: Ein m�ogliches Design-Pattern f�ur die Programmierung mit ART. Der

Algorithmus kann unterschiedliche "Roboter" steuern, sofern f�ur diese eine geeignete

Implementierung des Robot-Interface vorliegt.

Diese Aufteilung, in einen Algorithmus sowie eine Ansammlung von Para-

metern in Form eines Java-Interface, hat den Vorteil, da� der Algorithmus f�ur

verschiedene Roboter wiederverwendet werden kann.

Der Algorithmus DriveTrainSimpleAlgorithm kann mit jedem Roboter

verwendet werden, f�ur den eine Implementierung des Java-Interface Drive-

TrainSimpleAlgorithm.Robot existiert (bzw. erzeugt werden kann), die si-

cherstellt, da� die auf Seite 65 beschriebenen Anforderungen an die Motoren

erf�ullt sind.

Die Abbildung 5.2 veranschaulicht die Verbindungen, Zusammenh�ange und

Verantwortlichkeiten dieses Design-Patterns auf gra�sche Weise. Da die Klas-

sennamen sehr lang sind, wurden Abk�urzungen in Form von Buchstabenfol-

gen verwendet, deren Bedeutung in der Gra�k angegeben ist. Das dargestell-

te RobotInterface entspricht in etwa der Implementierung f�ur Fischertech-

nik. Auf die Anzahl und Art der dort angegebenen Motoren und Sensoren

kommt es jedoch nicht an, sie dienen nur als Beispiel, zur Verdeutlichung wof�ur

RobotInterface steht.

Eine genauere Beschreibung von RobotInterface und dem Zusammenspiel

zwischen diesem mit Motor, MotorPeer, ActuatorPort usw. be�ndet sich in

Kapitel 6. Eine genauere Erkl�arung, wof�ur die Klassen jeweils stehen gibt au-

�erdem Kapitel 4.

Auch die Klasse DriveTrainSimpleMSDemoRobot aus Listing 10 auf der vor-

herigen Seite hat eine main-Methode, die man zum Testen direkt ausf�uhren

kann. Die �Ubergabe eines Parameters f�ur das gew�unschte Interface ist dies-

mal weggelassen, da DriveTrainSimpleMSDemoRobot sowieso als default ein

Mindstorms-Interface verlangt (der zweite Parameter zu System.getProper-

Page 79: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.3. UND WIE BENUTZT MAN DAS NUN? 73

ty() gibt den default-Wert an und lautet "MS").

$ java de.jaetzold.art.examples.DriveTrainSimpleMSDemoRobot

Successfully initialized LEGO-Mindstorms Interface, found onserialport COM2$

Im folgenden Text wird nun nicht mehr jedesmal auf die M�oglichkeit der

Ausf�uhrung zum Testen hingewiesen und ein Beispiel gezeigt. Fast alle Klassen

aus dem package de.jaetzold.art.examples, welche das Wort "Robot" im

Namen enthalten, sind auf diese Weise ausf�uhrbar.

5.3 Und wie benutzt man das nun?

Im letzten Abschnitt wurden viele Klassen, bzw. Interfaces geschrieben, aber

nichts hat sich bewegt. Objekte der Klasse DriveTrainSimpleAlgorithm ma-

chen von alleine ja nicht viel, sie steuern den Roboter nur, wenn sie durch einen

Methodenaufruf explizit dazu aufgefordert werden.

Abbildung 5.3: Testfenster f�ur DriveTrain

Nur wer vorhin wirklich die vorgestellten Roboter-Implementationen zur

Ausf�uhrung gebracht hat, wird wahrscheinlich bemerkt haben (wenn alles ge-

klappt hat), da� in diesem Fall ein Fenster auf der Ober �ache erscheint, welches

in etwa so aussieht wie das in Abbildung 5.3 gezeigte.

In diesem Abschnitt wird diese einfache View f�ur DriveTrain-Objekte auf

Basis des AWT vorgestellt. Sie ist aufgeteilt in zwei Klassen. Die Klasse Drive-

TrainView stellt den Zustand eines DriveTrain in einem Textfeld dar. Die

andere Klasse (DriveTrainCommands) bietet eine Art Armaturenbrett um einen

DriveTrain zu beein ussen. Beide sind als Unterklassen von Panel realisiert

und daher leicht in eine beliebige Ober �ache integrierbar.

Welche Zust�ande es gibt, wurde bereits im Interface DriveTrain de�niert:

Listing 11: code/art/examples/DriveTrain.java (Ref. in Listing 5 S. 63)

public int getState();

public static final int FORWARD = 1;public static final int BACKWARD = 2;

Page 80: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

74 5. ARIADNE & ART - EIN TUTORIAL

Listing 11: code/art/examples/DriveTrain.java (Fortsetzung)

public static final int LEFT SPIN = 3;public static final int RIGHT SPIN = 4;public static final int STOP = 8;

Der Zustand kann mit getState() abgefragt werden und �uber die Konstan-

ten kann eine Zuordnung des dabei erhaltenen int-Werts, zu einer bestimmten

Bedeutung, erfolgen.

Die eine View macht nichts weiter, als den Zustand eines DriveTrain-

Objekts in einen String umzuwandeln und diesen in einem Textfeld auszugeben:

Listing 12: code/art/examples/DriveTrainView.java

package de.jaetzold.art.examples;

import java.awt.Panel;import java.awt.TextField;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent;

public class DriveTrainView extends Panelimplements PropertyChangeListener

{protected TextField stateOutput = new TextField("", 15);

public void propertyChange(PropertyChangeEvent pce) {if(pce.getSource() instanceof DriveTrain

&& pce.getPropertyName().equals("state")&& pce.getNewValue() instanceof Number) {

String stateName = "";int state = ((Number)pce.getNewValue()).intValue();switch(state & ˜ DriveTrain.STOP) {

case DriveTrain.FORWARD:stateName = "forward";break;

...default:

stateName = "";}if((state & DriveTrain.STOP) == DriveTrain.STOP) {

stateName = "stop " +stateName;}stateOutput.setText(stateName);

}}

...}

Die DriveTrainView ist ein PropertyChangeListener und versucht den

neuenWert eines PropertyChangeEvent als Zustand eines DriveTrain-Objekts

zu interpretieren, sofern der Event von einem DriveTrain-Objekt kommt und

die zugeh�orige Property den Namen state hat.

Page 81: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.3. UND WIE BENUTZT MAN DAS NUN? 75

Nicht jedes DriveTrain-Objekt mu� einen PropertyChangeListener f�ur

die Beobachtung seines Zustands haben k�onnen, daher sind die Methoden zum

Hinzuf�ugen oder Entfernen eines solchen nicht bereits im Interface DriveTrain

enthalten. Das hat den Grund, da� das Hinzuf�ugen von Views in der Regel am

besten dort geschieht, wo das DriveTrain-Objekt erzeugt wurde. Daher reicht

es, wenn nur die implementierenden Klassen die entsprechenden Methoden bie-

ten:

Listing 13: code/art/examples/DriveTrainSimpleAlgorithm.java (Ref. in Listing 7 S. 66)

protected PropertyChangeSupport changes =new PropertyChangeSupport(this);

public void addPropertyChangeListener(PropertyChangeListener l) {changes.addPropertyChangeListener(l);

}public void removePropertyChangeListener(PropertyChangeListener l) {

changes.removePropertyChangeListener(l);}

protected void setState(int state) {int previousState = this.state;this.state = state;changes.firePropertyChange("state", previousState, state);

}public int getState() {

return state;}

Das Setzen eines Zustands in DriveTrainSimpleAlgorithm sollte immer

�uber die Methode setState(int) geschehen, damit eventuelle java.beans.

PropertyChangeListener automatisch informiert werden. Den n�otigen java.

beans.PropertyChangeEvent erzeugt die mit changes bezeichnete Instanz von

java.beans.PropertyChangeSupport. Dieses Vorgehen entspricht (bis auf die

Verwendung von PropertyChangeSupport) dem Design-Pattern, wie es von

der JavaBeans Speci�cation 1.01 (Sun Microsystems, 1997) in Bezug auf soge-

nannte Bound-Properties vorgeschrieben ist. Zu ART im Zusammenhang mit

JavaBeans siehe Abschnitt 7.8.

Die DriveTrainView ist zum Beobachten des Zustands eines DriveTrain-

Objektes da. Damit etwas passiert, mu� dieser Zustand aber auch manipuliert

werden k�onnen. F�ur eine gra�sche Ober �ache bietet die Klasse DriveTrain-

Commands diese M�oglichkeit:

Listing 14: code/art/examples/DriveTrainCommands.java

package de.jaetzold.art.examples;

import java.awt.Panel;import java.awt.Button;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

Page 82: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

76 5. ARIADNE & ART - EIN TUTORIAL

Listing 14: code/art/examples/DriveTrainCommands.java (Fortsetzung)

public class DriveTrainCommands extends Panel {public DriveTrainCommands(DriveTrain driveTrain) {

this();setDriveTrain(driveTrain);

}public DriveTrainCommands() {

Button stop = new Button("stop");stop.addActionListener(

new ActionListener() {public void actionPerformed(ActionEvent ae) {

if(dt != null) {dt.stop();

}}

});add(stop);

...}

protected DriveTrain dt;public void setDriveTrain(DriveTrain dt) {

this.dt = dt;}

}

DriveTrainCommands stammt genau wie die DriveTrainView von Panel

ab, damit sie leicht in eine Ober �ache integriert werden kann. F�ur jede Me-

thode von DriveTrain, die dessen Zustand beein usst, gibt es einen Button,

�uber den die entsprechende Methode aufgerufen werden kann. Textfelder oder

andere M�oglichkeiten zur weiteren Dateneingabe sind nicht n�otig, da die ent-

sprechenden Methoden alle parameterlos sind. Der Code f�ur die Konstruktion

der anderen Kn�opfe wurde hier im Text aus Gr�unden der �Ubersichtlichkeit

weggelassen.

Die Klasse DriveTrainSimpleAlgorithm besitzt zum Testen eine main-

Methode, die eine DriveTrainView und ein -Commands mit einem Objekt von

sich verbindet und in einem Frame darstellt:

$ java de.jaetzold.art.examples.DriveTrainSimpleAlgorithm RCX

Successfully initialized LEGO-Mindstorms Interface, found onserialport COM2$

Welche Implementierung des Robot-Interface verwendet wird, kann man

auch hier wieder �uber eine Property steuern (de.jaetzold.art.examples.

DriveTrainSimpleAlgorithm.robotClass). Per Voreinstellung wird ansonsten

die Klasse DriveTrainSimpleRobot genommen. Der Aufruf bringt das in Abb-

lidung 5.3 auf Seite 73 gezeigte Fenster zum Vorschein, mit dem die Klasse

schon ganz gut ausprobiert werden kann.

Page 83: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.4. TRUSTY 77

5.4 Trusty

Bisher wurden in diesem Tutorial nur Motoren, also Ausg�ange eines Roboters

gesteuert. Ein "richtiger" Roboter mu� aber auch Eing�ange haben, Sensoren mit

denen die Umwelt wahrgenommen werden kann. Wie in Kapitel 2 beschrieben,

hat Trusty daf�ur zwei Bumper mit denen er Hindernisse registrieren kann. Daher

soll anhand seiner Programmierung der einfache Umgang mit Sensoren in ART

demonstriert werden.

Zun�achst ist der prinzipielle Aufbau von Trusty wieder �ahnlich wie bei

DriveTrain, um eine m�oglichst weitgehende Unabh�angigkeit des Algorithmus

zu erreichen. Es gibt ein Interface, das die F�ahigkeiten von Trusty de�niert:

Listing 15: code/art/examples/Trusty.java

package de.jaetzold.art.examples;

public interface Trusty {public void move();public void stop();public void avoidLeft();public void avoidRight();

...}

Die F�ahigkeiten von Trusty umfassen also ein irgendwie geartetes Fortbe-

wegen (move()), Anhalten (stop()) sowie nach links bzw. rechts Ausweichen

(avoidLeft(), avoidRight()).

Die Zuordnung des Verhaltens "ausweichen" zu einem entsprechenden Ereig-

nis, wie z.B. dem Ausl�osen eines der Bumper, wird an dieser Stelle vorerst au�er

Acht gelassen. Durch diese Trennung erreicht man eine gr�o�ere Flexibilit�at im

Umgang mit den entwickelten Algorithmen, da die dann nur lose miteinander

gekoppelten Verhaltensweisen und Ereignisse leichter neu gruppiert, sowie in

einem anderen Kontext verwendet werden k�onnen. Dies wird aber auch durch

eine weitere Verteilung des Codes auf noch mehr Klassen erkauft, was nicht nur

Vorteile mit sich bringt. Weil die Zusammenh�ange nicht mehr zentral festgelegt

werden, sind diese auch nicht immer sofort ersichtlich.

Die einfache Beispiel-Implementierung von Trusty ist TrustySimpleAlgo-

rithm, welche eine spezielle Form eines DriveTrain verwendet, die eine Anga-

be von Strecken bzw. Winkeln als Parameter zu Methoden wie forward bzw.

leftSpin() erlaubt:

Listing 16: code/art/examples/NormalizedDriveTrain.java

package de.jaetzold.art.examples;

public interface NormalizedDriveTrain extends DriveTrain {public void forward(double meters);

...}

Wird bei einem NormalizedDriveTrain z.B. forward mit einem Parameter

Page 84: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

78 5. ARIADNE & ART - EIN TUTORIAL

aufgerufen, dann wird von einer Implementierung erwartet, da� sich der Robo-

ter die entsprechende Strecke in Metern vorw�arts bewegt und danach anh�alt.

Entsprechendes gilt f�ur die Methoden zum Drehen des Roboters, die Ma�einheit

sind in diesem Fall ganze Umdrehungen. Ein Aufruf von backward(0.1) bewegt

den Roboter also um 10cm nach hinten und ein Aufruf von leftSpin(0.25)

dreht den Roboter um 90Æ nach links. Die Wahl der Ma�einheit ist reine Ge-

schmackssache.

Die zugeh�orige Implementierung ist in der Klasse NormalizedDriveTrain-

SimpleAlgorithm enthalten, welche auch ein eigenes Robot-Interface de�niert.

Dieses Interface schreibt zus�atzlich zu den Methoden aus DriveTrainSimple-

Algorithm.Robot noch zwei weitere vor:

Listing 17: code/art/examples/NormalizedDriveTrainSimpleAlgorithm.java

public interface Robot extends DriveTrainSimpleAlgorithm.Robot {public int getMeterMilliseconds();public int getFullTurnMilliseconds();

}

Diese Methoden dienen dazu, die Zeitdauer anzugeben, die der jeweilige Ro-

boter braucht, um einen Meter vorw�arts zu kommen bzw. eine volle Umdrehung

zu machen. Damit ist eine einfache Implementierung von NormalizedDrive-

Train m�oglich, die f�ur die entsprechende Zeitdauer das gew�unschte Verhalten

"einstellt" und danach anh�alt:

Listing 18: code/art/examples/NormalizedDriveTrainSimpleAlgorithm.java

public void forward(double meters) {if(meters<0) {

backward(meters*-1);}forward();try {

Thread.sleep((long)(meterMilliseconds*meters));} catch(InterruptedException ie) {}stop();

}

Auf die Angabe des restlichen Codes, insbesondere der Initialisierung, wird

verzichtet, da dieser nach den nun bereits bekannten Schemata realisiert ist.

Eine gra�sche �Ubersicht �uber die Zusammenh�ange zeigt Abbildung 5.4 auf der

n�achsten Seite. Wie es zu der Verbindung zum eigentlichen Roboter kommt,

wurde bereits in Abbildung 5.2 auf Seite 72 gezeigt und ist an dieser Stelle

zugunsten einer besseren �Ubersichtlichkeit ausgespart worden.

Es wird in diesem Zusammenhang vielleicht noch ein weiterer Vorteil der Zu-

sammenfassung der Parameter des Algorithmus zu einem Java-Interface deut-

lich: Die Parameter sind nicht voneinander unabh�angig und m�ussen daher als

Einheit angesehen werden, was sich auf diese Weise auch syntaktisch widerspie-

gelt. Welche Zeit der Roboter z.B. f�ur das Zur�ucklegen der Strecke von einem

Meter braucht und in welchem Verh�altnis diese zu der Zeit f�ur eine ganze Um-

Page 85: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.4. TRUSTY 79

DTSRobot

DTSMSDemoRobot

DTSAlgorithm DriveTrain

forward()

leftSpin()

NDTSBaseRobot

NDTSMSDemoRobot

NormalizedDT

forward(meters)

leftSpin(turns)

NDTSAlgorithm

DTSA.Robot

getRightMotor()

getLeftMotor()

NDTSA.Robot

getTurnMillis()

getMeterMillis()

NDTSFTDemoRobot

& initializesextends

extends

& initializes

extends

implements

extendsextends

initializes

defines &

with

defines &

withinitializes

implements

implements

implements

NDTSA = NormalizedDriveTrainSimpleAlgorithm

NDTS = NormalizedDriveTrainSimple

DTSA = DriveTrainSimpleAlgorithm

DTS = DriveTrainSimple

extends& initializes

uses

to forward

Abbildung 5.4: Design der Beispielimplementierung von NormalizedDriveTrain.

drehung steht, h�angt zum Beispiel direkt mit der konkreten Implementierung

der verwendeten Motoren zusammen und kann daher auch nicht unabh�angig

von dieser sinnvoll verwendet werden.

Zudem w�are es vorstellbar, da� ein Parameter erst erzeugt bzw. berechnet

wird, wenn er gebraucht wird (d.h. wenn die Interface-Implementierung danach

gefragt wird). Davon wird zwar bei keinem der Beispiele in diesem Kapitel

Gebrauch gemacht, man sollte diese M�oglichkeit aber im Hinterkopf behalten,

wenn man mit einem solchen Robot-Interface arbeitet. Vielleicht �andern sich

manche Parameter ja sogar (noch w�ahrend einer Programmausf�uhrung) mit

der Zeit?

Ich m�ochte auch noch auf eine Schwachstelle der gezeigten Implementierung

von NormalizedDriveTrain hinweisen. Sie geht davon aus, da� die Zeit, die der

Roboter zum Fahren einer Strecke braucht, in einem linearen Zusammenhang

mit der Strecke steht. Genau genommen ist es sogar so, da� die angenommene

Zeit ein Vielfaches der gew�unschten Strecke ist. Da ein Roboter aber auch Zeit

zum Beschleunigen braucht, bzw. die Kommandos wie forward() oder stop()

einen gewissen zeitlichen "overhead" haben k�onnen, ist diese Implementierung

nicht sehr pr�azise. Dies wird sich sp�ater bei der Implementierung von Trusty

f�ur den Lego-Roboter noch als ein Problem herausstellen.8

Doch nun wieder zur�uck zu der Implementierung von Trusty, dem eigent-

lichen Anliegen in diesem Abschnitt. Mit einem NormalizedDriveTrain ist

zum Beispiel eine einfache Implementierung von avoidLeft() folgenderma�en

m�oglich:

Listing 19: code/art/examples/TrustySimpleAlgorithm.java (Ref. in Listing 20 S. 80)

public void avoidLeft() {➥

8Das Problem mit dem Brick liegt in der Zeit, die vergeht, bis ein Befehl an den Motor

auch im Roboter angekommen und umgesetzt ist.

Page 86: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

80 5. ARIADNE & ART - EIN TUTORIAL

Listing 19: code/art/examples/TrustySimpleAlgorithm.java (Fortsetzung)

setState(AVOID LEFT);driveTrain.backward(backupMeters);driveTrain.rightSpin(turnAngle);stop();

}

Es wird einfach eine gewisse Strecke zur�uckgefahren und dann eine Rechts-

drehung vollzogen. Wie weit zur�uckgefahren wird und der Umfang der Drehung

sind Parameter die wieder, ebenso wie driveTrain, bei der Konstruktion des

TrustySimpleAlgorithm in Form eines entsprechenden Robot-Objektes �uber-

geben und auf diese Weise initialisiert wurden:

Listing 20: code/art/examples/TrustySimpleAlgorithm.java

package de.jaetzold.art.examples;...public class TrustySimpleAlgorithm implements Trusty {

protected NormalizedDriveTrain driveTrain;protected double backupMeters;protected double turnAngle;

public TrustySimpleAlgorithm(Robot robot) {driveTrain = robot.getNormalizedDriveTrain();backupMeters = robot.getBackupMeters();turnAngle = robot.getTurnAngle();

}public static interface Robot {

public NormalizedDriveTrain getNormalizedDriveTrain();public double getBackupMeters();public double getTurnAngle();

}<see Listing 19 on page 79>...

}

In diesem Fall werden (wie schon bei NormalizedDriveTrain) gar keine

Objekte mehr, die direkt aus ART stammen, �ubergeben, sondern einfach nur

statische Parameter f�ur den Algorithmus, sowie ein weiterer Algorithmus (in die-

sem Fall ein NormalizedDriveTrain), auf dem der Algorithmus arbeitet. Diese

werden wieder, um das bisherige Robot-Design-Pattern beizubehalten, mittels

einer interface-De�nition gruppiert (siehe Abbildung 5.5 auf der n�achsten

Seite).

Damit sind die grunds�atzlichen Aktionen von Trusty bereits implementiert

und k�onnen auch durch Ausf�uhrung der jeweiligen Robot-Implementierung ge-

testet werden. Zur Erinnerung: Die hier besprochenen Robot-Beispielimplemen-

tierungen enthalten alle eine main-Methode, welche eine Ober �ache zum Vor-

schein bringt, mit der man den Algorithmus f�ur den jeweiligen Roboter testen

kann.

In diesem Zusammenhang sei f�ur eigene Gehversuche nochmals darauf hin-

gewiesen, da� die in ART enthaltenen Implementierungen von RobotInterface

Page 87: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.4. TRUSTY 81

TSAlgorithmTSBaseRobot Trusty

move()

avoidLeft()

TS = TrustySimple

TSA = TrustySimpleAlgorithm

NDT = NormalizedDriveTrain

DT = DriveTrain

TSA.Robot

getNDT()

getTurnAngle()

TSMSDemoRobot TSFTDemoRobot

NormalizedDT

forward(meters)

leftSpin(turns)

initializes

defines &

with

implementsimplements

appropriate

creates/delivers

appropriate

creates/delivers

extends extends

& initializes& initializes

Abbildung 5.5: Design der Beispielimplementierung von Trusty. Eine vorhandene Im-

plementierung von NormalizedDriveTrain wird wiederverwendet.

zwar eigene Threads erzeugen, diese aber allesamt sogenannte daemon-Threads

sind, welche die Java-Maschine nicht von sich aus am Laufen halten. Damit

wird die Tatsache, da� �uberhaupt eigene Threads verwendet werden, besser

versteckt, denn ein Programm, das ART verwendet, geht genau auf die gleiche

Weise zu Ende, wie das ohne die Verwendung von ART der Fall w�are. Ansonsten

m�u�te man entweder System.exit() aufrufen, um ein Programm zu beenden

{ wie das z.B. bei Verwendung des AWT notwendig ist { oder in ART eine ei-

gene Methode zur Verf�ugung stellen, mit der man die erzeugten nicht-daemon

Threads beenden kann.

Einer dieser Threads ist daf�ur zust�andig, die Events, die eventuelle Ver�ande-

rungen an den Hardware-Sensoren repr�asentieren, an die Komponenten (die

Sensoren "in Software") auszuliefern, die an den zugeh�origen Port angeschlossen

sind. An diese Sensor-Objekte k�onnen wiederum SensorListener angeschlos-

sen sein, die ihrerseits dann auch von einem Thread informiert werden, indem

bei ihnen die Methode processEvent(SensorEvent) aufgerufen wird. Bei den

in ART vorhandenen Implementierungen von Sensoren ist dieser Thread nor-

malerweise derselbe wie der, mit dem der Sensor selbst benachrichtigt wurde.

Sensoren wurden in diesem Kapitel bisher noch gar nicht direkt behan-

delt. Trusty hat aber zwei "Bumper". Um die gew�unschte Verhaltensweise von

Trusty zu erreichen, da� er einem auf diese Weise registrierten Hindernis au-

tomatisch ausweicht, mu� der Event, da� Trusty irgendwo angesto�en ist, dem

entsprechenden Ausweich-Verhalten zugeordnet werden.

Der Zustand, ob Trusty mit einem seiner Bumper irgendwo angesto�en ist,

wird am einfachsten �uber einen BooleanSensor repr�asentiert. Ein Boolean-

Sensor interpretiert den von einem Sensor erhaltenen Wert per Voreinstellung

so, da� der Wert 0 false bedeutet und alle anderen Werte (insbesondere 1)

true zugeordnet werden. Ist also der BooleanSensor f�ur den linken Bumper

im Zustand true, dann soll links ausgewichen werden, entsprechendes gilt f�ur

den Sensor f�ur den rechten Bumper.

Man kann dieses Verhalten auch so darstellen, da� Trusty im allgemeinen

geradeaus f�ahrt und nur dann ausweicht, wenn ein Event, der true entspricht,

von einem der Sensoren eintri�t. Das Ausweich-Verhalten �uberdeckt dann das

Page 88: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

82 5. ARIADNE & ART - EIN TUTORIAL

normale Fahrverhalten { es hat eine h�ohere Priorit�at.

Trusty eignet sich daher als ein einfaches Beispiel f�ur Subsumption. Auf

Subsumption wird in Abschnitt 1.2 auf Seite 4 genauer eingegangen, an dieser

Stelle soll mehr die Anwendung f�ur Trusty mittels der Hilfsklasse de.jaetzold.

art.subsumption.SchedulerTask im Vordergrund stehen.

Das Robot-Interface von SubsumptionTrusty liefert einen Trusty, sowie

zwei BooleanSensor-Objekte, welche links und rechts zugeordent sind:

Listing 21: code/art/examples/SubsumptionTrusty.java

public interface Robot {public Trusty getTrusty();public BooleanSensor getLeftSensor();public BooleanSensor getRightSensor();

}

Die Implementierung dieses Interface gestaltet sich genauso einfach wie bis-

her. Der Anschlu� von Sensoren unterscheidet sich nur in den verwendeten Ports

von dem Anschlu� von Motoren:9

Listing 22: code/art/examples/SubsumptionTrustyBaseRobot.java

public SubsumptionTrustyBaseRobot( Trusty trusty,RobotInterface iface)

{this.trusty = trusty;

SensorPort[] ports = iface.getSensorPorts();if(ports.length < 2) {

throw new IllegalArgumentException("RobotInterface " +iface+" provides only "+ports.length+" SensorPorts"+", minimum is 2.");

}

leftSensor = new BooleanSensor();leftSensor.connectWith(ports[0]);

rightSensor = new BooleanSensor();rightSensor.connectWith(ports[1]);

}

Wieder wird in dieser Basis-Implementierung davon ausgegangen, da� die

Sensoren an den ersten beiden SensorPorts angeschlossen werden m�ussen und

keiner weiteren Kon�guration bed�urfen. Wie Sensoren kon�guriert werden m�us-

sen und worauf man dabei achten mu�, bzw. welche M�oglichkeiten man hat,

erkl�art Abschnitt 5.5.

Die booleschen Sensoren k�onnen im Konstruktor von SubsumptionTrusty

direkt dazu verwendet werden, die Verhaltensweisen f�ur das Ausweichen zu dem

SchedulerTask hinzuzuf�ugen:

9Genau genommen ist sogar jeder Motor ein Sensor f�ur seinen eigenen Zustand.

Page 89: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.4. TRUSTY 83

Listing 23: code/art/examples/SubsumptionTrusty.java

// behavior for avoiding left side obstaclesavoidLeft = new Task() {

public Event perform() {trusty.avoidLeft();return null;

}};scheduler.addBehaviorFor(new Double(1),

robot.getLeftSensor(),avoidLeft);

Als Priorit�at erwartet SchedulerTask ein Comparable. Als aktiviert gilt

eine Verhaltensweise dann, wenn der zugeh�orige BooleanSensor den Zustand

true hat. Ausgef�uhrt wird eine Verhaltensweise �uber den zugeh�origen Task.

Das Hinzuf�ugen f�ur den rechten Sensor geschieht analog. Man verwendet ei-

nem Task der entsprechend avoidRight() aufruft und eine andere Priorit�at

hat. Ob h�oher, gleich oder niedriger ist in diesem Fall zwar egal, die Klasse

SchedulerTask ist aber so implementiert, da� sie pro Priorit�at nur einen Ein-

trag erlaubt.

Exkurs: de.jaetzold.util.Task Das Interface Task beschreibt im Grunde

eine Art Runnable mit dem Unterschied, da� die Methode zum Ausf�uhren des

Task perform() hei�t und ein de.jaetzold.util.Event-Objekt als Resultat

haben kann. Dieser Unterschied ist hier zwar bisher nicht von Bedeutung, da

SchedulerTask dieses Resultat nicht weiter verarbeitet, wird aber an anderer

Stelle (bei den Implementierungen von RobotInterface, siehe Kapitel 6 auf

Seite 107) gebraucht.

Man kann sich nun fragen: Wieso dann �uberhaupt Task und nicht Runnable?

Der Vorteil liegt in dem Umstand begr�undet, da� { wie der Name schon an-

deutet { SchedulerTask selbst ein Task ist. Damit wird es m�oglich, mehre-

re SchedulerTask-Instanzen zu verschachteln. Die Methode SchedulerTask.

perform() w�ahlt von allen eingetragenen Verhaltensweisen, deren Boolean-

Sensor den Zustand true hat, diejenige mit der h�ochsten Priorit�at und f�uhrt

deren Task �uber perform() aus. Dies k�onnte dann nat�urlich auch ein weiterer

SchedulerTask sein.

Die Methode perform() einer Implementierung von Task darf au�erdem {

im Gegensatz zu run() von Runnable { jede Exception verursachen, da dies

bereits von Task.perform() so deklariert wird.

F�ur Task-Instanzen gibt es au�erdem die M�oglichkeit diese �uber einen de.

jetzold.util.TaskPerformer und eine zugeh�orige de.jaetzold.util.Queue

auszuf�uhren:

Listing 24: code/art/examples/SubsumptionTrusty.java

Queue taskQueue = new Queue();schedulerPerformer = new TaskPerformer(taskQueue);// schedulerPerformer.start(); // start the performer from the outside

Page 90: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

84 5. ARIADNE & ART - EIN TUTORIAL

Listing 24: code/art/examples/SubsumptionTrusty.java (Fortsetzung)

schedulerPerformer.haltPerforming(true);taskQueue.post(new RequeueTask(scheduler, taskQueue));

Ein TaskPerformer wird mit einer Queue initialisiert. Sobald die Queue ein

Element enth�alt, versucht der TaskPerformer dieses als Task zu interpretieren

und f�uhrt es gegebenenfalls aus.

Zu einer Queue werden Elemente mittels post(Object) hinzugef�ugt. Ein

TaskPerformer kann mittels haltPerforming(boolean) angehalten werden.

Ist das Argument true, so wird au�erdem dem ausf�uhrenden Thread des Task-

Performer die Nachricht interrupt() geschickt. Au�erdem geht die Methode

in diesem Fall erst dann zu Ende, wenn der TaskPerformer auch wirklich keinen

Task mehr ausf�uhrt.

Um einen Task wiederholt zur Ausf�uhrung zu bringen, kann man wie in dem

Beispiel einen de.jaetzold.util.RequeueTask benutzen, welcher den �uberge-

benen Task ausf�uhrt und sich selbst danach immer wieder zu der Queue hin-

zuf�ugt.

F�ur den hier genannten Zweck h�atte man eventuell auch java.util.Timer

und java.util.TimerTask verwenden k�onnen, doch die Klassen Task, Task-

Performer und Queue bieten dar�uber hinaus noch ein paar weitere Methoden,

welche sie von der Klasse Timer und einem TimerTask unterscheiden. Au�erdem

sind Timer und TimerTask erst seit Version 1.3 im API der Java Platform

enthalten. Die hier verwendeten Klassen sind aber mindestens mit Java 1.1

kompatibel und eignen sich daher auch zur Verwendung auf einer Maschine

wie dem TINI-Board (siehe 7.6 auf Seite 130), die im wesentlichen nur diese

Java-Version bietet.

Weiter mit SubsumptionTrusty: Au�er den Verhaltensweisen f�ur das Aus-

weichen mu� auch noch eine Verhaltensweise f�ur das normale Geradeausfahren

hinzugef�ugt werden:

Listing 25: code/art/examples/SubsumptionTrusty.java

// standard always-active behavior ’ move’BooleanSensor constantTrue = new BooleanSensor();constantTrue.connectWith(new ConstantSensorPort(1));move = new Task() {

public Event perform() {trusty.move();return null;

}};scheduler.addBehaviorFor(new Double(0), constantTrue, move);

Diese in Listing 25 gezeigte Verhaltensweise hat die niedrigste Priorit�at (in-

nerhalb von SubsumptionTrusty) und kommt daher immer dann zum Zuge,

wenn Trusty nicht ausweichen "will". Eigentlich m�u�te sie daher gar nicht ex-

tra aktiviert werden, weil sie immer aktiviert ist. Am einfachsten tr�agt man

diesem Umstand Rechnung, indem ihr ein BooleanSensor zugeordent wird,

Page 91: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.4. TRUSTY 85

der immer true ist.

Zur Verwendung von Sensoren und der Klasse SensorPort ohne ein direkt

zugeordentes RobotInterface, kann man auch in Abschnitt 5.5 und in Kapitel

4 mehr erfahren.

STBaseRobot SubsumptionTrustyST.Robot

getTrusty()

getLeftSensor()

Trusty

move()

avoidLeft()

STFTDemoRobot

STMSDemoRobot

Trusty

move()

avoidLeft()

BooleanSensor

getValue()

addSListener()

initializes

defines &

with

implements implements

& initializes

extends

2x

uses to

implement behavior uses to

decide

what behavior

to exhibitappropriate

creates/delivers

creates/delivers appropriate

S = SensorST = SubsumptionTrusty

Abbildung 5.6: Design der Beispielimplementierung von Trusty, welche auch

selbst�andig �uber ein eventuelles Ausweich-Verhalten entscheiden kann. Eine vorhan-

dene Implementierung von Trusty wird wiederverwendet.

Die Zusammenh�ange der Roboter-Klassen bei SubsumptionTrusty wird in

Abbildung 5.6 dargestellt. Bekommt SubsumptionTrusty die Nachricht move()

wird der zugeh�orige TaskPerformermit dem in einen RequeueTask verpackten

SchedulerTask gestartet:

Listing 26: code/art/examples/SubsumptionTrusty.java

public void move() {// start algorithmif(!schedulerPerformer.isAlive()) {

// it’ either has not been started yettry {

schedulerPerformer.start();} catch(IllegalThreadStateException itse) {

// or already finished execution}

}schedulerPerformer.resumePerforming();

}public void stop() {

// stop algorithmschedulerPerformer.haltPerforming();try {

schedulerPerformer.waitForHalt();} catch(InterruptedException ie) {}trusty.stop();

}public void avoidLeft() {

Page 92: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

86 5. ARIADNE & ART - EIN TUTORIAL

Listing 26: code/art/examples/SubsumptionTrusty.java (Fortsetzung)

// TBD: instead of stopping subsumption, the corresponding// BooleanSensor could deliver true, to initiate an ’ avoid’stop();trusty.avoidLeft();

}

Da der TaskPerformer schedulerPerformer nicht schon bei der Initiali-

sierung gestartet wird, haben eventuelle Unterklassen von SubsumptionTrusty

die M�oglichkeit schedulerPerformer als daemon-Thread zu starten, bzw. ihn

vielleicht sogar durch einen anderen TaskPerformer zu ersetzen.

Die anderen vom Interface Trusty vorgeschriebenen Methoden halten die

Ausf�uhrung von schedulerPerformer an und leiten den Methodenaufruf an-

sonsten zu dem eigentlichen Trusty weiter.

Wie immer kann nat�urlich auch dieser Roboter getestet werden. Ein Bild

des Demo-Roboters aus Fischertechnik und aus Lego zeigt Abbildung 2.3 auf

Seite 10 aus Kapitel 2.

5.5 Kon�gurierte Sensoren

Die Verwendung von Sensoren wurde bisher nur sehr knapp behandelt. Die-

ser Abschnitt zeigt zuerst, worauf bei der Implementierung des Subsumption-

Trusty.Robot f�ur den Beispielroboter auf Lego-Basis geachtet werden mu�te,

damit an dem gleichen Anschlu� auch noch "Platz" f�ur die Lichtsensoren von

LiSe bleibt.

Darauf folgt eine Beschreibung, wie man durch geschickte Kon�guration

eines CountSensor den Rotationssensor aus dem Lego-Mindstorms Programm

selbst zum z�ahlen benutzen kann, ohne einen Brick daf�ur zu ben�otigen.

Zuletzt wird noch eine Hilfsklasse vorgestellt, mit der es auf einfache Weise

m�oglich ist, die Z�ahlrichtung bei der Verwendung eines Fischertechnik-Impuls-

rads mit der Drehrichtung eines Fischertechnik-Motors zu koppeln.

5.5.1 SubsumptionTrustyMSDemoRobot

Wie bereits eingangs erw�ahnt, sollen bei dem Beispielroboter aus Lego die Licht-

sensoren f�ur LiSe an die gleichen Eing�ange des Brick angeschlossen werden, wie

die Ber�uhrungssensoren f�ur Trusty.

Bei einem Aufruf von connectWith(Port) bei einem Sensor wird dieser mit

"dem Besten" Peer verbunden, den der Port f�ur diese Sensor-Klasse zu bieten

hat. Was "der Beste" jeweils genau zu bedeuten hat, sollte in der Dokumen-

tation der jeweiligen Implementierung von RobotInterface, von der man das

Port-Objekt erhalten hat, spezi�ziert sein. F�ur bisherigen Implementierungen

steht das auch in Kapitel 4.

F�ur die in ART enthaltene Implementierung f�ur den Brick bedeutet das im

Falle eines BooleanSensor, da� der entsprechende Anschlu� des Brick auf den

Standard-Modus f�ur die normalen Lego-Ber�uhrungssensoren kon�guriert wird

(zur Kon�guration von Sensoren im Brick siehe: The LEGO Group (1998) sowie

Page 93: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.5. KONFIGURIERTE SENSOREN 87

alle B�ucher �uber Lego-Mindstorms in der Literaturliste usw.). Das bedeutet,

der Sensor wird nicht mit Strom versorgt und der eigentliche Sensorwert wird

in einen booleschen Wert verwandelt, welcher durch die Zahlenwerte 1 und 0

repr�asentiert wird.

F�ur diesen BooleanSensor wird aber nicht der normale Sensor-Wert ausge-

lesen, sondern der Wert des Registers mit der Standard-Umwandlung in einen

booleschen Wert. Dieses Register ist f�ur jede Sensorkon�guration g�ultig (Baum,

2001). Auf diese Weise liefert der Sensor auch dann noch einen (mehr oder we-

niger) sinnvollen Wert, falls der Anschlu� sp�ater noch umkon�guriert werden

sollte.

Diese Standard-Umwandlung ist aber im Falle einer Kon�guration des An-

schlusses f�ur einen Lichtsensor nicht geeignet, um den Zustand des Ber�uhrungs-

sensors zu erfahren. Vielmehr mu� der unver�anderte Sensorwert ausgelesen und

dann entsprechend interpretiert werden:

Listing 27: code/art/examples/SubsumptionTrustyMSDemoRobot.java

public SubsumptionTrustyMSDemoRobot(Trusty trusty,RobotInterface iface)

{super(trusty, iface);

// switch left and rightBooleanSensor tmp = leftSensor;leftSensor = rightSensor;rightSensor = tmp;

// in anticipation of LiSe the BooleanSensor’ s have to be// configured to handle the Raw value since they are connected// to the same ports as the LightSensor’ s of LiSePort leftPort = leftSensor.getPort();Port rightPort = rightSensor.getPort();leftSensor.disconnect();rightSensor.disconnect();

// put a RawSensor in-betweenRawSensor leftRaw = new RawSensor();RawSensor rightRaw = new RawSensor();leftRaw.connectWith(leftPort);rightRaw.connectWith(rightPort);leftSensor.connectWith(leftRaw.getSensorPort());rightSensor.connectWith(rightRaw.getSensorPort());

// first Range is for 0, second for 1 and third is hysteresis// these are non-standard RCX-values because Light-Sensors// can deliver values as low as 320leftSensor.setStateDecider(

new RCXRawSwitchStateDecider(new SingleRange(220),new SingleRange(0, 190),new SingleRange(190, 220)

Page 94: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

88 5. ARIADNE & ART - EIN TUTORIAL

Listing 27: code/art/examples/SubsumptionTrustyMSDemoRobot.java (Fortsetzung)

));rightSensor.setStateDecider(

new RCXRawSwitchStateDecider(new SingleRange(220),new SingleRange(0, 190),new SingleRange(190, 220)

));// a different contructor could be nice here, which only needs// one Range which is the hysteresis

}

Als erstes wird der linke mit dem rechten Sensor vertauscht, da das f�ur den

Demo-Roboter erforderlich ist.

Danach wird jeweils ein RawSensor mit dem Port verbunden, an dem die

Sensoren bisher angeschlossen waren. Der Anschlu� eines RawSensor f�uhrt da-

zu, da� der entsprechende Anschlu� am Brick auf den Raw -Modus kon�guriert

wird. Als Wert bekommt ein solcher Sensor den Inhalt des Registers f�ur den

unver�anderten Sensorwert geliefert, welches genauso wie die boolesche Umwand-

lung auch f�ur jede Kon�guration des Port g�ultig ist.

An diesen RawSensor, welcher nun (egal wie der Anschlu� sp�ater noch kon-

�guriert wird) immer den an dem Anschlu� gemessenen Wert unverarbeitet

bekommt, wird nun ihrerseits die entsprechende BooleanSensor-Instanz ange-

schlossen.

Jeder Sensor liefert mit getPort() den Port, an dem er selber angeschlos-

sen ist und mit getSensorPort() einen SensorPort, an den man weitere Sen-

soren anschlie�en kann, die dann den von ihm bereits verarbeiteten Wert be-

kommen.

Es wurde also sozusagen ein RawSensor "zwischendrin" eingef�ugt. Damit

wird erreicht, da� der BooleanSensor den Wert des Raw-Registers aus dem

Brick bekommt und selbst zu einem booleschen Wert umwandeln kann.

Die Umwandlung geschieht hier durch eine Wandlung des Sensorwertes in

den Zustand 0 oder 1, welcher dann von dem BooleanSensor normal interpre-

tiert wird (0 ist false, 1 ist true). Sie wird von der Hilfsklasse RCXRawSwitch-

StateDecider vorgenommen, welche drei Range-Instanzen bekommt. Eine f�ur

den Wert 0, eine f�ur die Hysterese (siehe z.B. Baum (2000)) und eine f�ur den

Wert 1.

Instanzen der Klasse SingleRange repr�asentieren Intervalle von (reellen)

Zahlen. Wird eine SingleRange wie in dem Beispiel nur mit einer Zahl in-

itialisiert, geht das Intervall von dieser Zahl bis Double.POSITIVE_INFINITY.

Wird sie mit zwei Zahlen initialisiert bezeichnet der erste Parameter die unte-

re Schranke und der zweite Parameter die obere Schranke eines geschlossenen

Intervalls. O�ene Intervalle sind auch m�oglich, wer mehr wissen will, schaue

sich die JavaDoc-Dokumentation der entsprechenden Range-Klassen aus den

package de.jaetzold.util an.

Page 95: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.5. KONFIGURIERTE SENSOREN 89

5.5.2 Der Lego-Rotationssensor

Wenn man einen Lego-Rotationssensor ganz normal mit dem Brick verwen-

den m�ochte, ist das einfach. Man braucht nur einen CountSensor mit einem

SensorPort des entsprechenden RobotInterface zu verbinden und der Ein-

gang wird automatisch richtig kon�guriert. Der CountSensor liefert dann den

vom Brick bereits berechneten Wert.

Ein CountSensor kann aber auch f�ur beliebige Ports zum Z�ahlen benutzt

werden, auch wenn diese gar nicht speziell f�ur einen CountSensor gedacht sind.

Daf�ur mu� der CountSensor entsprechend kon�guriert werden.

Um dem CountSensor erst einmal den unverarbeiteten Sensorwert zu lie-

fern, wird dieser mit dem SensorPort eines RawSensor verbunden (welcher

nat�urlich seinerseits auch mit einem Port verbunden werden mu�). Das ge-

schieht genau so wie bei den BooleanSensor-Instanzen von Subsumption-

TrustyMSDemoRobot in Abschnitt 5.5.1 auf Seite 86:

RawSensor raw = new RawSensor();CountSensor count = new CountSensor();count.connectWith(raw.getSensorPort());

Von der Oberklasse StateSensor von CountSensor wird der vom Robot-

Interface erhaltene Wert ohne weitere Verarbeitung als Zustand (State) inter-

pretiert. Der CountSensor wiederum z�ahlt in seiner Voreinstellung den Abso-

lutwert der Di�erenz zwischen zwei Zustands-Werten. Ein StateSensor beginnt

im Zustand 0, das hei�t, kommt vom RobotInterface z.B. als erstes der Wert

3 und dann der Wert 1, hat der CountSensor bereits bis 5 gez�ahlt. Kommt

dann noch der Wert -5, ist der CountSensor bereits bei 11 mit dem Z�ahlen

angelangt.

Sowohl StateSensor als auch CountSensor haben einen Delegate der Klas-

se StateDecider (stateDecider und countDecider genannt). Der Delegate

vom StateSensor bekommt den aktuellen (letzen) state-Wert des Sensors so-

wie den neuen Wert vom RobotInterface als Parameter und berechnet einen

neuen state-Wert. Der Delegate vom CountSensor bekommt auch den aktuel-

len (letzen) state-Wert des Sensors, sowie den neuen bereits in einen state-Wert

umgewandelten Wert vom StateSensor als Parameter und berechnet die Di�e-

renz zum aktuellen count-Wert. Diese Di�erenz wird immer zu dem letzten Wert

hinzuaddiert, das hei�t, soll der count-Wert kleiner werden mu� die Di�erenz

negativ sein.10

Um nun den raw-Wert des Rotationssensors zu verarbeiten, soll dieser erst

einmal in einen von vier Zust�anden umgewandelt werden (der Rotationssensor

erzeugt immer einen Wert in einem von vier engen Wertebereichen):

Listing 28: code/art/examples/RCXRotationSensorStateDecider.java

public class RCXRotationSensorStateDecider implements StateDecider {protected StateDecider target;

10Ist der Sensor auf reversed eingestellt, wird die Di�erenz abgezogen anstatt hinzugez�ahlt

Page 96: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

90 5. ARIADNE & ART - EIN TUTORIAL

Listing 28: code/art/examples/RCXRotationSensorStateDecider.java (Fortsetzung)

public RCXRotationSensorStateDecider() {target = new RangeStateDecider(

new Range[] {null,new SingleRange(352,366),new SingleRange(520,535),new SingleRange(1020,1024),new SingleRange(770,785)});

}

public double nextStateValue(double actualState, double value) {double newState = target.nextStateValue(actualState, value);if(newState == 0) {

// The standard rcx-interpretation of such// ’ false’ values seems to simply ignore themreturn actualState;

} else {return newState;

}}

...}

Der bei der Initialisierung erzeugte RangeStateDecider liefert als Resul-

tat von nextStateValue(double,double) immer den Index der ersten Range

in dem �ubergebenen Array, die nicht null ist und die den zweiten Parame-

ter zu nextStateValue(double,double) (welcher der neu erhaltene Wert ist)

enth�alt. Enth�alt keine der Range-Instanzen denWert, so liefert ein RangeState-

Decider das Resultat 0.

Der RCXRotationSensorStateDecider wird dem CountSensor als State-

Decider-Delegate �ubergeben:

count.setStateDecider(new RCXRotationSensorStateDecider());

Die vier Zust�ande des RCXRotationSensorStateDecider werden nun von

einem weiteren StateDecider in die Di�erenz zum alten count-Wert umgewan-

delt:

Listing 29: code/art/examples/RCXRotationCountStateDecider.java

public class RCXRotationCountStateDeciderextends TransitionMatrixStateDecider

{private static int[][] countMatrix =

new int[][]{/* l\n 0, 1, 2, 3, 4 *//* 0*/ { 0, 0, 0, 0, 0},/* 1*/ { 0, 0, 1, 0,-1},/* 2*/ { 0,-1, 0, 1, 0},/* 3*/ { 0, 0,-1, 0, 1},/* 4*/ { 0, 1, 0,-1, 0}};

Page 97: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.5. KONFIGURIERTE SENSOREN 91

Listing 29: code/art/examples/RCXRotationCountStateDecider.java (Fortsetzung)

public RCXRotationCountStateDecider() {super(countMatrix);

}}

Die Bereiche f�ur die vier Zust�ande wurden so gew�ahlt, da� ein �Ubergang

von 1 nach 2, von 2 nach 3 usw., sowie von 4 nach 1 bedeutet, da� der count-

Wert um 1 hochgez�ahlt werden muss. Zustands�uberg�ange von 4 nach 3, 3 nach

2 usw., sowie von 1 nach 4 m�ussen eine Verringerung des count-Wertes um 1

nach sich ziehen, damit das gleiche Resultat wie im Brick erreicht wird.

Zust�ande von 0, sowie gr�o�ere Spr�unge werden ignoriert, was dem beobacht-

baren Verhalten des Brick in diesem Fall entspricht.

Zust�ande von 0 k�onnen zum Beispiel auftreten, wenn ein Ber�uhrungssensor

an den gleichen Eingang wie der Rotationssensor angeschlossen ist, weil dieser

auch Werte au�erhalb der 4 Bereiche des Rotationssensors liefern kann.

Ob gr�o�ere Spr�unge vom Brick wirklich ignoriert werden, kann nicht sicher

best�atigt werden, es ist aber so, da� zumindest ab einer Geschwindigkeit von

etwa 1000 U/min der vom Brick berechnete count-Wert nicht mehr korrekt ist.

Bei der hier vorgestellten Variante nat�urlich bereits viel fr�uher (sch�atzungsweise

so etwa im Bereich von 4-40 U/min, je nach sonstiger Rechnerauslastung).

Mehr zu Sensoren f�ur den Brick, vor allem auf Hardware-Ebene, �ndet man

unter Gasperi (1998) und in Baum et al. (2000).

5.5.3 Rotationsmessung mit den Fischertechnik-Impulsr�adern

Um mit Fischertechnik die Rotation einer Achse zu messen, benutzt man �uber-

licherweise die daf�ur vorgesehenen Impulsr�ader. Abbildung 5.7 zeigt das Im-

pulsrad von LiSe.

Abbildung 5.7: Der schwarze Taster ist zusammen mit dem Impulsrad (das ist das kleineschwarze Zahnrad in der Mitte mit nur vier Z�ahnen) so montiert, da� eine Drehungan dem Rad den Taster fortlaufend bet�atigt.

Page 98: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

92 5. ARIADNE & ART - EIN TUTORIAL

Leider ist man damit nicht in der Lage, automatisch die Richtung, in die sich

die Achse dreht, zu bestimmen. Z�ahlt man nur die am Schalter auftretenden

Impulse, so wird der daraus resultierende Wert immer gr�o�er, egal in welche

Richtung sich die Achse dreht.

H�au�g ist solch eine Achse aber an einen Motor angeschlossen und in die-

sem Fall wei� man eigentlich, in welche Richtung sich die Achse dreht. Da-

mit nun die Z�ahlrichtung nicht immer per Hand eingestellt werden mu�, kann

man einen StateDecider wie im folgenden Beispiel als countDecider f�ur den

CountSensor verwenden:

Listing 30: code/art/examples/FTRotationCountStateDecider.java

package de.jaetzold.art.examples;...public class FTRotationCountStateDecider

extends StateDeciderLinkedStateDecider{...

public FTRotationCountStateDecider(Sensor directionSensor) {try {

setFirstDecider(new SensorStateDecider( directionSensor,true));

setSecondDecider(new BinaryOperatorStateDecider(

new BinaryOperator() {public double combine( double first,

double second){

return Math.abs(first-second);}

},true

));

setLinkDecider(new BinaryOperatorStateDecider(

new BinaryOperator() {private int seq;private int last;public double combine( double first,

double second){

if(first>0) {last = 1;

} else if(first<0) {last = -1;

} else {...

}return last*second;

Page 99: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.5. KONFIGURIERTE SENSOREN 93

Listing 30: code/art/examples/FTRotationCountStateDecider.java (Fortsetzung)

}},true

));

} catch(PropertyVetoException pve) {}

}}

Die Klasse FTRotationCountStateDecider stammt von der Klasse State-

DeciderLinkedStateDecider ab, welche ihrerseits drei StateDecider-Instan-

zen besitzt, an die die Entscheidung �uber den neuen Zustand delegiert wird.

Die ersten beiden Instanzen (firstDecider und secondDecider) bekom-

men die Parameter zu nextStateValue(double,double) jeweils direkt �uber-

geben. Die dritte Instanz (linkDecider), bekommt das Resultat von first-

Decider als ersten und das Resultat von secondDecider als zweiten Parameter

�ubergeben.

Bei der Initialisierung bekommt ein FTRotationCountStateDecider einen

Sensor mit (das kann auch ein Motor sein, denn die sind Sensoren f�ur ihren

Zustand), erzeugt damit einen SensorStateDecider und initialisiertmit diesem

wiederum den firstDecider der Oberklasse. Ein SensorStateDecider ist ein

StateDecider der als Resultat immer den Wert des Sensors liefert.

Als secondDecider wird ein StateDecider erzeugt, wie ihn ein Count-

Sensor auch als Voreinstellung benutzt. Die absolute Di�erenz zwischen ak-

tuellem Zustand (Parameter first zu combine(double,double) des Binary-

Operator) und dem neuen Wert (Parameter second, der dann sinnvollerweise

auch ein Zustand sein sollte) liefert dieser als Resultat.

Verbunden werden die Resultate der beiden ersten StateDecider �uber den

dritten, welcher { je nachdem ob der Sensorwert gerade positiv oder negativ ist {

die Di�erenz unver�andert als Resultat �ubergibt oder vorher mit -1 multipliziert.

Ein Sonderfall tritt auf, wenn der Sensor den Wert 0 liefert. Damit der

CountSensor in diesem Fall trotzdem z�ahlt, wird einfach angenommen, da�

in die gleiche "Richtung" wie beim letzten Aufruf gez�ahlt werden soll. Damit

wird dem Umstand Rechnung getragen, da� die Events von dem Sensor f�ur das

Impulsrad zu einem Zeitpunkt ankommen k�onnen, zu dem der Motor bereits

wieder aus ist.

Diesen StateDecider kann man nun auf einfache Weise verwenden, um ein

Impulsrad mit einem Motor zu koppeln:

CountSensor count = new CountSensor();Sensor motor = new Motor();count.setCountDecider(new FTRotationCountStateDecider(motor));

Nat�urlich m�ussen motor und count auch noch mit einem Port verbunden

werden. Das d�urfte mittlerweile aber klar sein.

Page 100: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

94 5. ARIADNE & ART - EIN TUTORIAL

5.6 LiSe

Die Programmierung von LiSe (und im folgenden Abschnitt auch Ariadne) wird

l�angst nicht so ausf�uhrlich behandelt wie das bei den bisherigen Beispielen der

Fall war. Wer daran weitergehendes Interesse hat, sollte inzwischen auch in

der Lage sein, den Code der Beispielimplementierungen selbst zu verstehen.

Das Konzept ist im Grunde das gleiche wie auch schon bei DriveTrain und

Trusty.

Trotzdem gibt es einige Besonderheiten und Elemente des ART, die vorher

noch nicht zu Tage getreten sind, so da� auf diese hier noch eingegangen wird.

LiSe ist besonders interessant als Beispiel f�ur die Verwendung von Sensoren.

Ein BooleanSensor wird f�ur den Endabschalter verwendet, ein AngleSensor

f�ur die Position des Turms, sowie zwei Objekte der Klasse LightSensor mit

denen die Taschenlampe "gefunden" werden kann.

Zur Bewegung des Turmes mit den Lichtsensoren benutzt LiSe einen Servo.

Nun bieten sowohl der Brick, als auch das Intelligent Interface von Fischertech-

nik keine Anschlu�m�oglichkeit f�ur echte Servos. Da der Turm sich aber nicht

beliebig weit drehen l�a�t und LiSe ihn nicht nur bewegen, sondern auch �uber die

(absolute) Position Bescheid wissen m�ochte, w�are ein Servo eigentlich besonders

gut f�ur die Turmbewegung geeignet.

Um diese h�au�g verwendete Konstruktionsweise (Motor mit Rotationssensor

und Endabschalter) besonders einfach steuerbar zu machen, kann die Klasse

Servo die Funktion eines echten Servo simulieren. Wird eine Servo-Instanz mit

einem Port verbunden, der keine echten Servos unterst�utzt, so mu� man sie nur

mit

� einem AngleSensor zur Positionsmessung

� einem BooleanSensor zur Kalibrierung der Position

� einer "Richtung", in die sich der Servo (Servo ist eine Unterklasse von

Motor) drehen soll, um die Position des BooleanSensor anzufahren

� einer unteren und einer oberen Schranke f�ur den Bewegungsbereich des

Servo

versorgen und kann sie danach ganz normal wie einen Servo verwenden, das

hei�t, zumindest einigerma�en so wie einen Servo. Im allgemeinen wird ein

Servo wesentlich pr�aziser und schneller als diese Simulation mit einem Motor

usw. sein.

Andere Implementierungen von RobotInterface k�onnten aber durchaus

auch echte Servos unterst�utzen. Was dabei unter anderem zu beachten ist be-

schreibt Abschnitt 6.

Die Beispielimplementierung LiSeSimpleAlgorithm verlangt eine Imple-

mentierung des folgenden Interface zur Initialisierung:

Listing 31: code/art/examples/LiSeSimpleAlgorithm.java

public interface Robot {➥

Page 101: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.6. LISE 95

Listing 31: code/art/examples/LiSeSimpleAlgorithm.java (Fortsetzung)

public double getMaxRightAngle();public double getMaxLeftAngle();public double getSearchSpeed();public double getFollowSpeed();public Servo getTurnServo();

}

Die Werte maxRightAngle und maxLeftAngle bezeichnen die Grenzen des

Bereiches, in dem gesucht werden soll. Au�erdem wird dar�uber festgelegt, ob

negative Winkel links oder rechts sind.

Mit searchSpeed und followSpeed wird die Geschwindigkeit der Tower-

bewegung zum Suchen des Lichtes und um einem bereits gefundenen Licht zu

folgen angegeben. Ich bin mir nicht sicher, ob echte Servos normalerweise eine

Regelung der Geschwindigkeit mit der sie sich bewegen zulassen. Die �uber die

Motoren simulierten tun das auf jeden Fall.

Es macht aber nichts, hier eine Geschwindigkeit zu verwenden, denn nach

der De�nition von ART ist jeder Servo auch ein Motor (Die Klasse Servo ist

eine Unterklasse von Motor) und bietet daher die M�oglichkeit, eine Geschwin-

digkeit anzugeben. Genau genommen ist es sogar so, da� die Geschwindigkeit

erst bei einem StepperMotor angegeben werden kann und bei einem Motor

nur die Kraft (power), das hat aber bei den Implementierungen f�ur Lego und

Fischertechnik die gleichen Auswirkungen, da sie StepperMotor nicht direkt

unterst�utzen.11

Damit k�onnen die vom Interface LiSe (siehe Sourcecode) vorgeschriebenen

Methoden folgenderma�en implementiert werden:

Listing 32: code/art/examples/LiSeSimpleAlgorithm.java

private boolean searchRight;public synchronized void seeLeft() {

servo.setSpeed(robot.getFollowSpeed());servo.setValue(robot.getMaxLeftAngle());searchRight = false;setState(SEE LEFT);

}public synchronized void seeRight() {

servo.setSpeed(robot.getFollowSpeed());servo.setValue(robot.getMaxRightAngle());searchRight = true;setState(SEE RIGHT);

}public synchronized void search() {

// important for direction-change when reaching MaxAnglesetState(SEARCH);

if(servo.isPositionedAt(robot.getMaxRightAngle())) {➥

11F�ur weitere Informationen, insbesondere zu StepperMotor, dient die JavaDoc API-

Dokumentation von ART.

Page 102: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

96 5. ARIADNE & ART - EIN TUTORIAL

Listing 32: code/art/examples/LiSeSimpleAlgorithm.java (Fortsetzung)

searchRight = false;} else if(servo.isPositionedAt(robot.getMaxLeftAngle())) {

searchRight = true;}

servo.setSpeed(robot.getSearchSpeed());if(searchRight) {

servo.setValue(robot.getMaxRightAngle());} else {

servo.setValue(robot.getMaxLeftAngle());}

}public synchronized void seeCenter() {

servo.keepCurrentPosition();setState(SEE CENTER);

}public synchronized void stop() {

servo.keepCurrentPosition();setState(STOP);

}public synchronized boolean isSeeing() {

switch(getState()) {case STOP:case SEARCH:

return false;default:

return true;}

}public AngleSensor getAngleSensor() {

return servo.getAngleSensor();}

Die Methoden seeLeft() und seeRight() implementieren das Verhalten,

einem Licht das bereits erkannt wurde nach links, bzw. rechts zu folgen. In der

Variable searchRight wird die letzte Richtung, in der das Licht gesehen wurde

festgehalten, damit in dieser Richtung von der Methode search() auch zuerst

gesucht wird.

Die Methoden seeCenter() und stop() halten die (eventuelle) Bewegung

des Servos an und stellen ihn auf die aktuelle Position ein. Sie unterscheiden

sich nur in dem Zustand von LiSe.

Der Zustand, ob LiSe im Moment �uberhaupt ein Licht "sieht", kann man

�uber isSeeing() erfragen. Der R�uckgabewert gibt damit an, ob der Wert des

AngleSensor von LiSe als die Position eines Lichtes interpretiert werden kann.

Die Methode search() bewegt den Tower in der aktuellen Suchrichtung bis

an den Rand des Suchbereiches. Damit LiSe dort umdreht und den Tower an

den anderen Rand bewegt, ist (indirekt) bei dem Servo ein SensorListener

registriert, welcher search() bei Erreichen des Randes im SEARCH-Zustand ein-

fach erneut aufruft:

Page 103: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.6. LISE 97

Listing 33: code/art/examples/LiSeSimpleAlgorithm.java

final BooleanSensor borderSensor = servo.getPositionReachedSensor();borderSensor.addSensorListener(

new SensorListener() {public void processEvent(SensorEvent se) {

synchronized(LiSeSimpleAlgorithm.this) {boolean reached =

borderSensor.convertToBoolean(se.getValue());if(debug.debug) {

debug.printInfo("reached=" +reached+", value=" +se.getValue()+", state=" +state);

}

if(reached && (state == SEARCH)) {search();

}}

}}

);

Dies zeigt ein besonderes Konzept: Sensoren in ART stehen immer f�ur einen

Wert der eindimensional, also z.B. in einer Variable vom Typ double, abgebildet

werden kann. Ist das nicht m�oglich, wird von dem eigentlichen Sensor nur eine

einzige Dimension abgebildet und f�ur alle weiteren kann man spezielle Sensoren

von dem eigentlichen Sensor bekommen. Dies ist bei Servo z.B. f�ur den Zustand,

ob er sich an der zugewiesenen Position be�ndet der Fall. Da der Sensorwert

des Servo selbst den Bewegungszustand des Servo repr�asentiert, um mit Motor

kompatibel zu bleiben, gibt es f�ur die Position einen weiteren Sensor, den man

�uber getAngleSensor() erhalten kann.

Die Sensoren, sowie der Servo werden (wie �ublich) in einer Basisimplemen-

tierung des Interface (LiSeSimpleAlgorithm.Robot) hinterlegt. Entsprechende

Unterklassen f�ur den Beispielroboter aus Lego, sowie f�ur den aus Fischertechnik

erzeugen, verbinden und kon�gurieren diese dann auf geeignete Weise.

In der Fischertechnik-Variante von LiSe sieht das folgenderma�en aus:

Listing 34: code/art/examples/LiSeSimpleFTDemoRobot.java

public class LiSeSimpleFTDemoRobot extends LiSeSimpleBaseRobot {public LiSeSimpleFTDemoRobot(RobotInterface ft) {

// fake parameters and set them afterwardssuper(null, 0, 0, 0, 0);

Port endSwitchPort = ft.getPort("E7");Port countSensorPort = ft.getPort("E8");Port motorPort = ft.getPort("M4");

// gear ratio Tower:Sensor = 1:6➥

Page 104: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

98 5. ARIADNE & ART - EIN TUTORIAL

Listing 34: code/art/examples/LiSeSimpleFTDemoRobot.java (Fortsetzung)

double countsPerFullTurn = 48;AngleSensor turnSensor = new AngleSensor(countsPerFullTurn);

int endSwitchDirection = 1;BooleanSensor endSwitch = new BooleanSensor();

// Angles are measured in full turnsdouble positiveBorder = 21/48.0;double negativeBorder = -20/48.0;double endSwitchAngle = positiveBorder;

maxRightAngle = 0.33;maxLeftAngle = -0.25;searchSpeed = 1;followSpeed = 0.33;

turnServo = new Servo(turnSensor,endSwitch,endSwitchAngle,positiveBorder,negativeBorder,endSwitchDirection);

turnSensor.setCountDecider(new FTRotationCountStateDecider(turnServo));

endSwitch.connectWith(endSwitchPort);turnSensor.connectWith(countSensorPort);turnServo.connectWith(motorPort);

// let the servo be a bit more sloppy in positioning// (that (mostly) prevents it from occasionally moving// back and forth around the desired position)turnServo.setPrecision(turnServo.getPrecision()*2);

}...

}

Die nicht deklarierten Variablen maxRightAngle, maxLeftAngle, search-

Speed, followSpeed und turnServo sind die, die von einem LiSeSimple-

Algorithm.Robot geliefert werden sollen und stammen aus der Basisklasse

LiSeSimpleBaseRobot, wo auch die zugeh�origen get-Methoden implementiert

sind.

Die Port-Objekte f�ur den Anschlu� des Endabschalters, des Impulsrades

und des Motors werden hier auf eine sehr intuitive Art von dem Interface erfragt.

Da an dieser Stelle eigentlich sowieso nur ein RobotInterface f�ur Fischertech-

nik benutzt werden soll, kann man die Ports auch anhand ihrer Bezeichnung

identi�zieren.

Welche Bezeichnungen g�ultig sind und mit welchem Anschlu� an der Hard-

ware sie korrespondieren, ist in der Dokumentation f�ur die jeweilige Implemen-

tierung von RobotInterface beschrieben. Im Allgemeinen entspricht sie einem

Page 105: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.6. LISE 99

eventuellen Aufdruck auf der Hardware oder der Bezeichnung der Anschl�usse,

wie sie in der Dokumentation der Hardware verwendet werden.

Auf diese Weise ist die Zuordnung eines von einem RobotInterface erhal-

tenen Port zu einem Anschlu� an der Hardware am intuitivsten (und damit

potentiell nicht fehlerbehaftet) handhabbar.

Als n�achstes wird der AngleSensor mit der Anzahl von Impulsen, die einer

ganzen Umdrehung entsprechen initialisiert. Damit kann der count-Wert der

Oberklasse CountSensor auch ohne spezielle Unterst�utzung durch das Robot-

Interface in einen Winkel umgerechnet werden. Das Standardma� f�ur Winkel

in ART sind ganze Umdrehungen von 360Æ.

Schlie�lich wird der Servo mit dem Endabschalter, dem Impulsrad und den

sonstigen (vom Robotermodell abh�angigen) n�otigen Werten initialisiert.

Damit turnSensor auftretende Impulse je nach der aktuellen Bewegungs-

richtung des Servo korrekt zum count-Wert dazuz�ahlt oder abzieht, wird er

au�erdem mit einer Instanz des im Abschnitt 5.5 auf Seite 86 besprochenen

FTRotationCountStateDecider als Delegate zum Z�ahlen versorgt.

Als Letztes wird der mangelnden Geschwindigkeit bei der Auslieferung von

Events Rechnung getragen, indem die Pr�azision des Servo halbiert wird. Die

Eigenschaft precision repr�asentiert die Genauigkeit in Form des erwartbaren

Fehlers des Sensorwertes und ist daher bei einer geringeren Pr�azision gr�o�er.

Wenn man diese Einstellung nicht vornimmt, kommt es h�au�ger vor, da�

der Motor erst zum Stillstand kommt, wenn er bereits �uber die gew�unschte

Position hinaus gefahren ist. Das registriert der Servo nat�urlich und bewegt

ihn wieder ein St�uck zur�uck. Das kann wieder zu weit sein und sich theoretisch

endlos hinziehen. Es w�are gut, wenn Servo in der N�ahe der gew�unschten Posi-

tion die Geschwindigkeit drosseln w�urde, um diesen E�ekt zu vermeiden, diese

Funktionalit�at ist in Servo aber (noch) nicht integriert.

Eine entsprechende Implementierung von LiSeSimpleAlgorithm.Robot exi-

stiert auch f�ur die Lego-Variante von LiSe. Diese wird hier nicht gezeigt, da sie

nichts wirklich Neues enth�alt.

Nat�urlich kann auch diese Beispielimplementierung wieder auf dem �ubli-

chen Weg getestet werden (was darunter zu verstehen ist wurde am Ende von

Abschnitt 5.2 und in Abschnitt 5.3 auf Seite 73 n�aher beschrieben).

SubsumptionLiSe

Es fehlt noch die Integration der Lichtsensoren, damit LiSe auch automa-

tisch einem Licht folgen kann. Das wird auf die gleiche Weise bewerkstelligt

wie schon bei SubsumptionTrusty. Nur ist es diesmal mit etwas mehr Auf-

wand verbunden, die n�otigen BooleanSensor-Objekte f�ur die Initialisierung

des SchedulerTask mit den unterschiedlichen Verhaltensweisen zu erzeugen.

Diese m�ussen beide Lichtsensoren in Betracht ziehen. Stellvertretend wird hier

nur eine Konstruktion gezeigt:

Listing 35: code/art/examples/SubsumptionLiSe.java

// behavior for seeing light on the left side➥

Page 106: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

100 5. ARIADNE & ART - EIN TUTORIAL

Listing 35: code/art/examples/SubsumptionLiSe.java (Fortsetzung)

final LightSensor leftSensor = robot.getLeftSensor();final LightSensor rightSensor = robot.getRightSensor();BinaryOperator seeLeftOperator =

new BinaryOperator() {public double combine( double leftValue,

double rightValue) {// at least one of them has to ’ see’ somethingif(leftValue >= leftSensor.getMeasurableMin()

|| rightValue >= rightSensor.getMeasurableMin()) {// Standard BooleanConversion: only 0 is falsereturn leftValue>rightValue ? 1 : 0;

}return 0;

}};

CombinedSensor seeLeftSensor = new CombinedSensor();seeLeftSensor.connectWith(leftSensor.getSensorPort());seeLeftSensor.setOperator(seeLeftOperator);seeLeftSensor.setOperand(rightSensor);

BooleanSensor seeLeftActivator = new BooleanSensor();seeLeftActivator.connectWith(seeLeftSensor.getSensorPort());

seeLeftTask = new Task() {public Event perform() {

lise.seeLeft();return null;

}};scheduler.addBehaviorFor(new Double(1),

seeLeftActivator,seeLeftTask);

Ein CombinedSensor verkn�upft den Wert, den er von seinem eigenen An-

schlu� bekommt mit dem Wert, den er von einem weiteren Sensor (operand)

bekommt, �uber einen BinaryOperator (operator).

Ein BinaryOperator ist hier als lokale anonyme innere Klasse realisiert. Die

Methode combine(double,double) bekommt als ersten Parameter den Wert

des linken LightSensor und als zweiten Parameter den des rechten Light-

Sensor und liefert 1, falls einer der beiden Werte gr�o�er ist, als der Wert der Ei-

genschaft measurableMin des jeweiligen LightSensor und au�erdem der Wert

f�ur links gr�o�er ist als der Wert f�ur rechts.

Die Werte measurableMin und measurableMax eines LightSensor bezeich-

nen die Grenzen des Bereichs in dem der LightSensor Werte liefert, die (im

Rahmen seiner precision) genau sind. Im Prinzip sollte LightSensor inner-

halb dieses Bereiches Werte liefern, die dem tats�achlich gemessenen Lux-Wert

entsprechen.

In combine() wird measurableMin daf�ur genutzt, um herauszu�nden, ob

der Sensor �uberhaupt ein st�arkeres Licht, wie z.B. von einer Taschenlampe, regi-

Page 107: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.7. ARIADNE 101

striert hat. Daf�ur ist es notwendig, da� measurableMin auch den momentanen

Lichtverh�altnissen entspricht. Man kann diesen Wert, genauso wie measurable-

Max f�ur einen Lichtsensor, auch festlegen { LightSensor bietet daf�ur eine Me-

thode. Wird der Wert nicht festgelegt, liefert LightSensor das, was das Robot-

Interface, an dem er �uber einen Port angeschlossen wurde, liefert, sofern dieses

einen LightSensor �uberhaupt direkt unterst�utzt. Ist beides nicht der Fall, ist

der Wert von beiden Eigenschaften 0.

An den CombinedSensormu� nun nur noch ein BooleanSensor angeschlos-

sen werden. Dieser konvertiert in der Voreinstellung den Wert 0 zu false und

alle anderen Werte zu true, was bei der Implementierung des BinaryOperator

ein paar Zeilen dar�uber ausgenutzt wurde. Man kann einem BooleanSensor

auch einen Delegate BooleanConversion f�ur die Konvertierung mitgeben, falls

man das m�ochte.

Die Erzeugung des Task und das Hinzuf�ugen der Verhaltensweise zu dem

SchedulerTask scheduler geschieht ansonsten auf die gleiche Weise wie schon

bei SubsumptionTrusty und wurde dort bereits erkl�art. Neu bei Subsumption-

LiSe ist nur die Art und Weise wie der BooleanSensor, der das Verhalten

aktiviert, erzeugt bzw. angeschlossen wurde.

5.7 Ariadne

Nun ist es soweit: Trusty und LiSe werden miteinander verkn�upft, damit sie

zusammen Ariadne ergeben. Die Verkn�upfung soll im Ergebnis dazu f�uhren, da�

Ariadne auf ein Licht zuf�ahrt und dabei eventuellen Hindernissen ausweicht.

Um dies zu erreichen, kann Ariadne sich an dem Winkel, in dem ein Licht

ausgemacht wurde orientieren, indem der NormalizedDriveTrain (der auch

von Trusty verwendet wird) um den entsprechenden Winkel gedreht wird, so

da� danach eine Bewegung nach vorne, in Richtung des Lichts geht.

Wieder beginnt das Beispiel mit einem interface Ariadne, das die Schnitt-

stelle zu der F�ahigkeit von Ariadne, sich an einem Winkel zu orientieren, de�-

niert:

Listing 36: code/art/examples/Ariadne.java

package de.jaetzold.art.examples;

public interface Ariadne {public void orientByAngle(double angle);

...}

Die Beispielimplementierung AriadneSimpleAlgorithm wird (wieder �uber

ein Robot-Interface) mit einem NormalizedDriveTrain, sowie einem Winkel

initialisiert. Dieser Winkel stellt die Richtung dar, in die Ariadne gerne aus-

gerichtet w�are. Die Methode orientByAngle(double) macht nun nichts wei-

ter, als den �ubergebenen Wert als die momentane Orientierung aufzufassen,

und daher den NormalizedDriveTrain um die entsprechende Di�erenz zu dem

Winkel, mit dem AriadneSimpleAlgorithm initialisiert wurde, zu drehen:

Page 108: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

102 5. ARIADNE & ART - EIN TUTORIAL

Listing 37: code/art/examples/AriadneSimpleAlgorithm.java

public void orientByAngle(double angle) {setState(ORIENTING);if((angle - orientationAngle)*leftDirection > 0) {

driveTrain.leftSpin(Math.abs(angle - orientationAngle));} else if((angle - orientationAngle)*leftDirection < 0) {

driveTrain.rightSpin(Math.abs(angle - orientationAngle));}setState(ORIENTED);

}

Der Wert leftDirection stammt auch von AriadneSimpleAlgorithm.

Robot und sagt aus, ob negative Winkelwerte links oder rechts sind.

Das m�u�te inzwischen alles sehr einfach anmuten, da das Prinzip immer

noch dasselbe ist und AriadneSimpleAlgorithm nichts enth�alt, was nicht schon

mal behandelt worden ist. Daher wird auch keine der Robot-Implementierungen

(AriadneSimpleMSDemoRobot usw.) gezeigt. Diese sind aber vorhanden, so da�

man bei Interesse selbst nachschauen kann.

Interessanter ist die Steuerung mit SubsumptionAriadne, welche als Unter-

klasse von SubsumptionTrusty realisiert wurde. Das zugeh�orige Robot-Inter-

face ist auch eine Erweiterung von SubsumptionTrusty.Robot und kann daher

einfach an den entsprechenden Konstruktor der Oberklasse �ubergeben werden:

Listing 38: code/art/examples/SubsumptionAriadne.java (Ref. in Listing 40 S. 103)

public interface Robot extends SubsumptionTrusty.Robot {public Ariadne getAriadne();public LiSe getLiSe();public long getMinOrientInterval();

}

Der Konstruktor von SubsumptionAriadne macht nicht mehr, als eine wei-

tere Verhaltensweise in den SchedulerTask der Oberklasse einzuf�ugen, diese ist

aber etwas schwieriger zu realisieren, da die Methode orientByAngle(double)

diesmal einen Parameter braucht:

Listing 39: code/art/examples/SubsumptionAriadne.java (Ref. in Listing 40 S. 103)

double angle;long lastOrientMillis;boolean oneShot;Object oneShotMonitor = new Object();Task behavior = new Task() {

public Event perform() {double localAngle;synchronized(oneShotMonitor) {

// be sure to only orient once by each angleif(!oneShot) {

return null;}lastOrientMillis = System.currentTimeMillis();

Page 109: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.7. ARIADNE 103

Listing 39: code/art/examples/SubsumptionAriadne.java (Fortsetzung)

localAngle = angle;oneShot = false;

}ariadne.orientByAngle(localAngle);// since it depends on some values// (lastOrientMillis, oneShot) it is better// not to assume that there will be an event// from liseAngle soon enoughactivator.update();

return null;}

};

Dieser Parameter wird in der Variable angle gespeichert, wenn der zugeh�ori-

ge BooleanSensor die Verhaltensweise aktivieren m�ochte. Die Orientierung soll

aber nur genau einmal statt�nden und danach erst neu aktiviert werden. Daher

ruft der Task behavior die Methode orientByAngle(double) nur dann auf,

wenn oneShot true ist und setzt oneShot danach auf false. Damit behavior

also �uberhaupt etwas macht, mu� der BooleanSensor au�er selbst den Wert

true anzunehmen auch noch oneShot auf true setzen:

Listing 40: code/art/examples/SubsumptionAriadne.java

public class SubsumptionAriadne extends SubsumptionTrustyimplements Ariadne,

Trusty{

protected Ariadne ariadne;public SubsumptionAriadne(final Robot robot) {

super(robot);this.ariadne = robot.getAriadne();final LiSe lise = robot.getLiSe();final AngleSensor liseAngle = lise.getAngleSensor();

// construct orient-behavior// behavior and activator need to exchange informationSchedulerTask.Entry entry = new SchedulerTask.Entry() {

<see Listing 39 on page 102>BooleanSensor activator = new BooleanSensor();{

activator.connectWith(liseAngle.getSensorPort());activator.setBooleanConversionDelegate(

new BooleanConversion() {public boolean convertToBoolean(double value) {

synchronized(oneShotMonitor) {// only if lise sees something at all:if(!lise.isSeeing()) {

return false;}

// Future Idea: don’ t orient if lise sees➥

Page 110: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

104 5. ARIADNE & ART - EIN TUTORIAL

Listing 40: code/art/examples/SubsumptionAriadne.java (Fortsetzung)

// light inthe direction we already are// or only orient if the seeing-angle// differs enough from the orient-to-angle (0)

if((System.currentTimeMillis()- lastOrientMillis) >=

robot.getMinOrientInterval()){

angle = value;oneShot = true;

}return oneShot;

}}public boolean isCacheable() {

return false;}

});

}...

};// insert orient-behavior into scheduler of superclass:scheduler.add(entry);

}<see Listing 38 on page 102>...

}

Der Roboter soll nicht st�andig neu orientiert werden, sondern Subsumption-

Trusty soll zwischendurch auch ein wenig Zeit zum Fahren bekommen. Daher

wird der BooleanSensor activator nur dann true, wenn der letzte Aufruf von

orientByAngle(double) lange genug her ist. Welcher Zeitraum hier sinnvoll

ist, h�angt vom Roboter und der Implementierung von Trusty ab und ist daher

auch eine Eigenschaft des Robot-Interface (minOrientInterval).

Der Austausch zwischen activator und behavior �uber die Variablen one-

Shot, angle und lastOrientMillis erfordert, da� diese f�ur beide Objekte

sichtbar sind. Daher sind Task, BooleanSensor und Comparable in einem

SchedulerTask.Entry zusammengefa�t und werden als dieser gemeinsam an

scheduler �ubergeben.

Die neu hinzugef�ugte Verhaltensweise bekommt die Priorit�at 0.5. Das ist

niedriger als die Priorit�aten von SubsumptionTrusty f�ur das Ausweichen, aber

h�oher als f�ur das geradeaus Fahren.

Die Implementierung von SubsumptionAriadne.Robot gestaltet sich sehr

einfach, da nur die in den vorausgegangenen Abschnitten besprochenen Bei-

spielalgorithmen mit den jeweiligen Robot-Implementierungen erzeugt werden

m�ussen. Eine weitere Kon�guration ist (bis auf minOrientInterval) nicht

mehr notwendig. Aus diesem Grund wird auf den Abdruck hier verzichtet.

Nat�urlich kann auch SubsumptionAriadne auf die �ublicheWeise durch einen

Aufruf wie zum Beispiel

Page 111: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

5.7. ARIADNE 105

$ java de.jaetzold.art.examples.SubsumptionAriadne

Successfully initialized LEGO-Mindstorms Interface, found onserialport COM1$

auf die �ubliche Weise getestet werden. Die vorhandenen Beispiel-Imple-

mentierungen SubsumptionAriadneFTDemoRobot sowie SubsumptionAriadne-

MSDemoRobot erzeugen dabei ein (recht gro�es) Fenster, in dem die "State"- und

"Commands"-Views f�ur NormalizedDriveTrain, Trusty, LiSe sowie Ariadne

enthalten sind (siehe Abbildung 5.8. Damit SubsumptionAriadne loslegt, mu�

man wie bei SubsumptionTrusty auch, auf den Knopf move dr�ucken, was da-

zu f�uhrt, da� bei SubsumptionAriadne (die ja ein Trusty ist) der Thread f�ur

Subsumption gestartet wird.

Abbildung 5.8: Testfenster f�ur die Komponenten von SubsumptionAriadne

Page 112: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

106 5. ARIADNE & ART - EIN TUTORIAL

Page 113: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6

Implementierung eines

RobotInterface

In der aktuellen Version von ART sind "Treiber" f�ur das Intelligent Interface

von Fischertechnik und den Brick aus dem Robotics Invention System von Le-

go implementiert. Das parallele Interface von Fischertechnik, der Scout oder

der Cybermaster sowie die Ansteuerung des Brick �uber den neuen Tower mit

USB-Anschlu�, wie er im aktuellen RIS 2.0 enthalten ist, wird nicht direkt

unterst�utzt.

Dieses Kapitel zeigt wie eine solche Unterst�utzung implementiert wird. Die

M�oglichkeiten dazu sind nat�urlich nicht auf die eben genannten Beipiele be-

schr�ankt, sondern ART wurde mit dem Anspruch entwickelt, m�oglichst jede

Form von Roboter-Hardware unterst�utzen zu k�onnen.

In ART besteht ein solcher Treiber im wesentlichen aus einer Implementie-

rung des Java-Interface RobotInterface und einer geeigneten Menge von Port

und SensorPeer-Klassen. Ein RobotInterface repr�asentiert aus der Sicht von

ART ein logisches Hardware-Interface. Die komplette Treiberimplementierung

kann trotzdem aus mehreren Klassen bestehen und es ist auch m�oglich, da�

eine Implementierung mehrere echte Hardware-Interfaces nur logisch als eine

Einheit repr�asentiert. Genau genommen mu� es sich nicht einmal um echte

Hardware handeln. Zu Testzwecken z.B., kann es sogar sehr n�utzlich sein, wenn

die Roboter-"Hardware" nur virtuell im Computer existiert, denn so werden

manche Tests einfacher, billiger und vor allem risikoloser. Es kann in solch ei-

nem Fall keine teure Roboter-Hardware zerst�ort werden, wenn der zu testende

Steuerungsalgorithmus Fehler enth�alt.

6.1 Ein virtuelles RobotInterface

Die Implementierung eines virtuellen RobotInterface dient in diesem Kapitel

als Beispiel. Es ist sehr einfach aufgebaut und nicht dazu gedacht, die Low-

Level Ansteuerung von Roboterhardware z.B. �uber den seriellen Port in Java

zu beschreiben. Das Beispiel zeigt lediglich, wie sich eine solche Ansteuerung in

ART integrieren l�a�t und worauf man dabei achten mu�.

Im allgemeinen wird man z.B. mit mehreren Threads hantieren m�ussen und

107

Page 114: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

108 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

Abbildung 6.1: Screenshot der Ober �ache von AWTRobotInterface. Rechts sind dieTextfelder f�ur die Ausgabe (Actuatoren) zu sehen, die Werte wurden durch den Steue-rungsalgorithmus von Trusty gesetzt, der "Roboter" dreht sich also gerade.

Byte-Str�ome codieren und decodieren. Die hier gezeigte Beispielimplementie-

rung AWTRobotInterface nutzt zur Ein- und Ausgabe (als Gegenst�uck zu Sen-

soren und Aktuatoren) einfache Textfelder in einem Fenster des AWT. Sensor-

werte tr�agt man schlicht in das entsprechende Textfeld ein und �uber die Text-

felder f�ur die Aktuatoren kann man deren Zustand beobachten. Es mu� nicht

einmal ein eigener Thread erzeugt werden, der die Events zustellt, denn ein sol-

cher existiert im AWT schon. Ein ActionEvent der von einem der Textfelder

kommt wird entsprechend von dem zugeh�origen SensorPeer als SensorEvent

an die angeschlossenen Sensor-Instanzen weitergeleitet.

Bei einer Implementierung f�ur eine echte Roboterhardware ist es nicht un-

bedingt empfehlenswert, einen der Threads, die mit der Interface-Hardware di-

rekt kommunizieren, auf diese Weise zu verwenden. Der Thread, der die Events

zustellt, wird sozusagen "in die freie Wildbahn" hinausgelassen und wird be-

liebigen Code ausf�uhren, �uber den man, als Programmierer des entsprechenden

RobotInterface, keine Kontrolle mehr hat. Die Implementierungen der Klas-

sen de.jaetzold.art.platform.fischertechnik.Fischertechnik und de.

jaetzold.art.platform.lego.Mindstorms nehmen eine solche Trennung der

Threads vor, bei Interesse empfehle ich dem Leser, direkt in die entsprechenden

Quelldateien hineinzusehen. F�ur die Erkl�arung, wie ein neues RobotInterface

implementiert und in ART integriert werden kann, ist dies nicht notwendig.

Listing 41: code/art/examples/AWTRobotInterface.java

package de.jaetzold.art.examples;

// lots of imports...

public class AWTRobotInterface extends RobotInterfaceAdapter {private static Debug debug =

new Debug("de.jaetzold.art.platform.awt.AWTRobotInterface");

protected TextField in0 = new TextField("0.0");➥

Page 115: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.1. EIN VIRTUELLES ROBOTINTERFACE 109

Listing 41: code/art/examples/AWTRobotInterface.java (Fortsetzung)

protected TextField in1 = new TextField("0.0");protected TextField out0 = new TextField("0.0");protected TextField out1 = new TextField("0.0");

// RobotInterfaceDefinition:<see Listing 46 on page 117>

// Factory-Method for creating an AWTRobotInterface:<see Listing 50 on page 121>

// Factory-Methods for creating the Peers:<see Listing 48 on page 119>

// isConnected:<see Listing 43 on page 112>

// isAlive:<see Listing 49 on page 120>

// Factory-Methods for the Ports:<see Listing 47 on page 118>

// Inner classes for the Ports:<see Listing 45 on page 114>

// Inner class for the SensorPeer:// maybe put outside of class because it is of more general use?

<see Listing 42 on page 110>

// Inner class for the ActuatorPeer:<see Listing 44 on page 113>

}

Listing 41 auf der vorherigen Seite zeigt den groben K�orper der Beispielim-

plementierung AWTRobotInterface. Neben dem eigentlichen RobotInterface

m�ussen aber auch noch Port- und SensorPeer-Klassen implementiert werden.

Diese sind f�ur dieses Beispiel alle als innere Klassen von AWTRobotInterface

realisiert worden. Die Verweise in Listing 41 f�uhren unter anderem zu deren

Implementierungen.

AWTRobotInterface stammt von RobotInterfaceAdapter ab. Das ist zwar

nicht notwendig, da nur das Java-Interface RobotInterface implementiert wer-

den m�u�te, aber diese Basisklasse enth�alt Hilfsmethoden in der Behandlung von

seriellen Ports. Serielle Ports werden f�ur das Beispiel nicht ben�otigt. Interface-

Hardware mit seriellem Anschlu� ist jedoch nicht un�ublich und in den Imple-

mentierungen f�ur Lego und Fischertechnik wird von den Hilfsmethoden Ge-

brauch gemacht. Ansonsten enth�alt RobotInterfaceAdapter bereits imple-

mentierte Methoden, um Port-Objekte des RobotInterface �uber ein bestimm-

tes Identi�er -Object (siehe Dokumentation von Port.conformsTo(Object))

oder einen Index, im Stil einer indexed property von JavaBeans, auszuw�ahlen.

Die Technik, sowohl ein Java-Interface als auch eine implementierende Ba-

Page 116: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

110 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

sisklasse zu verwenden, wird unter anderem in Flanagan (1999, S. 115) vorge-

schlagen. Sie wird zum Beispiel auch bei den { in der Java 2 Plattform neuen

{ Collection-Klassen angewandt. Ein Problem von Interfaces in Java ist, da�

man an ihnen kaum etwas �andern kann, ohne implementierende Klassen anpas-

sen zu m�ussen. Daher hat ein zwischengeschalteter Adapter einen weiteren Vor-

teil: Wenn das Java-Interface ge�andert wird, dann reicht es (unter Umst�anden)

den Adapter zu �andern und alle davon abgeleiteten Klassen funktionieren sofort

wieder, auch mit dem ge�anderten Java-Interface.

6.2 Die Peers

Damit das Beispiel-RobotInterface auch ausreicht, um z.B. die Trusty-Algo-

rithmen darauf laufen zu lassen, mu� es mindestens zwei Anschl�usse f�ur Senso-

ren und zwei f�ur Aktuatoren zur Verf�ugung stellen. In dem Beispiel werden

nur die einfachsten Peers implementiert. Die ActuatorPorts liefern "reine"

ActuatorPeer- und die SensorPorts "reine" SensorPeer-Instanzen. Es sind

keine Spezialisierungen enthalten, wie z.B. ein BooleanSensorPeer, der auf der

Seite der Ober �ache z.B. durch einen Button oder eine Checkbox repr�asentiert

werden k�onnte.

Auf der Ober �ache (siehe Abbildung 6.1 auf Seite 108) kann man den Zu-

stand der Actuatoren beobachten und auf den Wert der Sensoren Ein u� neh-

men, indem man in das entsprechende Textfeld einen neuen Wert eintr�agt und

mit Enter best�atigt. Das l�ost bei einem TextField im AWT einen ActionEvent

aus und dieser wird von einer zugeh�origen Instanz der inneren Klasse Text-

FieldSensorPeer verarbeitet:

Listing 42: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

protected class TextFieldSensorPeer extends BaseSensorPeer {protected TextField input;public TextFieldSensorPeer(TextField input) {

this.input = input;

input.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent ae) {try {

double oldValue = currentValue;currentValue = Double.parseDouble(

ae.getActionCommand());

processEvent(new SensorEvent(this,// source

null, // descriptorSystem.currentTimeMillis(),oldValue,currentValue,true, // isFloatingPointnull) // propagationId

Page 117: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.2. DIE PEERS 111

Listing 42: code/art/examples/AWTRobotInterface.java (Fortsetzung)

);} catch(NumberFormatException nfe) {

TextFieldSensorPeer.this.input.setText("" +currentValue);

}}

});

}

protected double currentValue;public double getValue() {

return currentValue;}

public boolean isConnected() {return AWTRobotInterface.this.isConnected();

}}

Bei Abstammung von der abstrakten Klasse BaseSensorPeer, ist die einzi-

ge Methode, die implementiert werden mu�, getValue(). F�ur die meisten F�alle

wird es au�erdem sinnvoll sein, die Methode isConnected() an das entspre-

chende RobotInterface weiterzuleiten.

Wichtig ist au�erdem getPrecision(). Der R�uckgabewert dieser Methode

soll dem maximal erwarteten Fehler des Sensors entsprechen, der von diesem

Peer repr�asentiert wird. Die Voreinstellung von BaseSensorPeer ist ein Wert

von 0 f�ur precision { im Zusammenhang mit realen Sensoren wird dieser

Wert sicherlich gr�o�er ausfallen. In dem Beispiel hier ist die Voreinstellung aus-

reichend, da die Werte, die in das Textfeld eingetragen werden, ja so "genau"

sind wie man m�ochte. Zudem ist es ein guter Test f�ur eventuelle Algorithmen,

ob diese auch mit diesem Extremwert klarkommen. Man mu� bedenken, da�

precision nur als Anhaltspunkt daf�ur angesehen werden kann, wie genau der

Sensor ist. Nicht f�ur jeden Sensor existieren genaue Spezi�kationen und dann ist

man auf Sch�atzwerte und eigene Tests angewiesen. Der Sensor kann zudem von

verschiedenen Faktoren, wie z.B. der Umgebungstemperatur, auf unvorherge-

sehene (oder zwar auf vorhergesehene, aber in der Peer-Implementierung nicht

in Betracht gezogene) Weise beein u�t werden, so da� ein Algorithmus keine

"lebenswichtigen" Funktionen von dessen Korrektheit abh�angen lassen sollte.

Ereignisse wie die �Anderung eines Werts f�ur einen Sensor werden in Form

von SensorEvent-Objekten dargestellt. Diese werden an alle SensorListener,

die sich f�ur solche Ereignisse interessieren, weitergeleitet. Die Verteilung von

Events und die Verwaltung von Listenern wird bereits in BaseSensorPeer

soweit geregelt, da� dies f�ur das Beispiel ausreicht. �Uber einen Aufruf von

processEvent(SensorEvent) wird der �ubergebene SensorEvent an alle bei

diesem Peer registrierten Listener weitergeleitet.

An das TextField ist ein ActionListener angeschlossen. Er steht in Form

einer anonymen lokalen inneren Klasse im Konstruktor von TextFieldSensor-

Page 118: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

112 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

Peer. Die Methode actionPerformed(ActionEvent)des ActionListenerwan-

delt den Inhalt des Textfelds in eine double um und verpackt diesen Wert in

einen SensorEvent. Dieser Event enth�alt neben dem neuen und dem alten Wert

{ die durchaus auch gleich sein k�onnen { einen Verweis auf seinen Ursprung und

den Zeitpunkt zu dem er aufgetreten ist. Die anderen Parameter sind (bisher)

nur von untergeordneter Bedeutung:

� descriptor ist vom Typ SensorEventDescriptor und wird momentan

noch nicht wirklich ben�otigt. Er soll sp�ater dazu dienen, verschiedene

Events bestimmten Gruppen zuzuordnen, so da� man als SensorEvent-

Listener angeben kann, nur bestimmte Events zu bekommen, bzw. da�

ein Peer nur bestimmte Events �uberhaupt generiert (siehe SensorPeer.

enableEvents(SensorEventDescriptor)).

� isFloatingPoint gibt an, ob der Event von einem Sensor stammt, von

dem prinzipiell echte oatingpoint-Werte kommen k�onnen. Ist dieser Pa-

rameter false bedeutet das, da� ein Wert, der durch diesen Event re-

pr�asentiert wird, ohne Genauigkeitsverlust auf int gecastet werden kann.

� propagationId wird ben�otigt, wenn ein SensorEvent als ein Property-

ChangeEvent weitergeleitet wird (siehe JavaBeans API De�nition: java.

beans.PropertyChangeEvent.getPropagationId()).

Zu guter Letzt wird der Wert in dem TextField auf den vorherigen Wert

zur�uckgesetzt, wenn der String aus dem TextField nicht korrekt in eine double

umgewandelt werden kann. Der jeweils letzte erfolgreich in eine double umge-

wandelte Wert steht in currentValue, daher kann dieser Wert in der Methode

getValue() auch direkt zur�uckgegeben werden, ohne da� das Textfeld nochmal

"gefragt" werden mu�. Somit wird auch kein String umgewandelt, den man

z.B. gerade in dem Textfeld am editieren ist.

Die Methode isConnected() dient dazu herauszu�nden, ob der Peer noch

eine Verbindung zu dem Hardware-Sensor hat, den er repr�asentiert. In der Re-

gel wird das solange der Fall sein, wie noch Kontakt zur Interface-Hardware

besteht. Es ist daher im Prinzip richtig diesen Methodenaufruf an die Imple-

mentierung von RobotInterface (also in diesem Fall AWTRobotInterface) wei-

terzuleiten. In diesem konkreten Fall w�are es eventuell auch richtig gewesen

z.B. das zugeh�orige TextField zu fragen, ob es �uberhaupt noch sichtbar ist

(isShowing()). Die genaue Bedeutung von isConnected() h�angt von der je-

weiligen Implementierung ab. Mit dem Peer verbundene Sensoren fragen diesen

Wert ab, wenn sie ihrerseits nach isConnected() gefragt werden. Im Falle des

AWTRobotInterface ist der Wert immer true, da das Fenster sowieso so lange

auf dem Bildschirm bleibt wie die Java-Maschine l�auft:

Listing 43: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

public boolean isConnected() {return true; // maybe use Frame.isDisplayable() ?

}

Page 119: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.2. DIE PEERS 113

F�ur Aktuatoren, wie z.B. einen Motor, wird ein weiterer Peer (Actuator-

Peer) ben�otigt, da hier der Wert nicht nur abgefragt, sondern auch gesetzt

werden kann:

Listing 44: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

protected class TextFieldActuatorPeer extends TextFieldSensorPeerimplements ActuatorPeer

{protected TextField output;public TextFieldActuatorPeer(TextField output) {

super(output);this.output = output;

}

public void setValue(double value) {setValue(value, true);

}public synchronized void setValue( double value,

boolean waitMode){

String tmp = "" +value;

double oldValue = getValue();output.setText(tmp);// beware if the TextField is changed by someone else// in this momentif(oldValue != value) {

ActionEvent ae =new ActionEvent(output,

ActionEvent.ACTION PERFORMED,tmp);

// output.dispatchEvent(ae); // Don’ t let this Thread// process the Event!

// This way the Thread processing the Event is the// real AWT-Event-Thread:output.getToolkit().getSystemEventQueue()

.postEvent(ae);}

}}

Der Parameter waitMode besagt (wenn er false ist), da� bei R�uckkehr der

Methode die eigentliche Operation, n�amlich das Setzen des neuen Werts, noch

nicht unbedingt abgeschlossen sein mu�. Dies kann z.B. dann m�oglich sein,

wenn sich ein anderer Thread um die Fertigstellung k�ummert. Da das Setzen

des neuen Werts in dem Beispiel aber sowieso kaum Zeit in Anspruch nimmt,

wird waitMode nicht weiter beachtet.

Falls sich der Wert ge�andert haben sollte, wird au�erdem daf�ur gesorgt, da�

vom Event-Thread des AWT ein entsprechender ActionEvent verarbeitet wird.

Damit bekommt die Oberklasse auf "nat�urliche" Weise mit, da� sich der Wert

ge�andert hat und kann eventuelle SensorListener, mittels eines SensorEvent,

Page 120: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

114 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

�uber die �Anderung in Kenntnis setzen.

Dieser Event wird nur bei einer �Anderung des Werts erzeugt, da ansonsten

der Event-Thread ziemlich �uberlastet werden kann. Manche Algorithmen (z.B.

Trusty mit Subsumption) setzen in manchen Situationen ziemlich schnell nach-

einander den gleichenWert. Das vom Algorithmus verwendete Actuator-Objekt

leitet den Wert trotzdem jedesmal an den Peer weiter, da es ja sein kann, da�

jemand anderes zwischendurch den Wert beim Peer ge�andert hat, ohne da� der

Actuator es (schon) wei�. Der Peer selbst kann den neuen Wert dann verwer-

fen, wenn sichergestellt ist, da� eine �Anderung an dem Textfeld nicht vonstatten

geht, ohne da� er informiert wird. Dies kann am einfachsten dadurch geschehen,

da� f�ur jedes Textfeld nur ein Peer erzeugt wird. Trotzdem sollte die Methode

synchronized sein, denn sonst kann es sein, da� die ActionEvents in einer

anderen Reihenfolge verarbeitet werden als die Ver�anderung an dem Inhalt des

Textfeldes.

Der ActionEvent ist notwendig, damit die Oberklasse merkt, da� sich an

dem Inhalt des Textfeldes etwas ge�andert hat. Auf diese Weise kann dort der

gleiche Mechanismus verwendet werden, der auch schon beim normalen edi-

tieren mit der Hand daf�ur sorgt, da� ein neuer Wert zu einem SensorEvent

f�uhrt.

Man k�onnte sich �uberlegen, ob man nicht verschiedene Peers implemen-

tiert, die je nach dem, welcher Sensor angeschlossen wird, verwendet werden.

Ein StateSensor k�onnte dann z.B. durch eine Instanz von Choice abgebildet

werden und ein BooleanSensor mit einer Checkbox.

6.3 Die Ports

Au�er den Peers geh�oren zu einer Implementierung von RobotInterface auch

entsprechende Implementierungen von SensorPort, bzw. ActuatorPort. Es

kann auch weitere Port-Typen geben, die dann aber noch zu de�nieren w�aren.

Listing 45: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

protected class AWTSensorPort extends BaseSensorPort {AWTSensorPort(String portName,

int portNumber,double minimumValue,double maximumValue,long granularity,Port[] excludedPorts) {

super(AWTRobotInterface.this,portName,portNumber,minimumValue,maximumValue,granularity,excludedPorts);

}

Page 121: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.3. DIE PORTS 115

Listing 45: code/art/examples/AWTRobotInterface.java (Fortsetzung)

public SensorPeer getPeerFor(Sensor sensor) {SensorPeer peer = getSensorPeer(this, sensor);return peer;

}}

protected class AWTActuatorPort extends BaseActuatorPort {AWTActuatorPort(String portName,

int portNumber,String type,double minimumValue,double maximumValue,long granularity,Port[] excludedPorts) {

super(AWTRobotInterface.this,portName,portNumber,type,minimumValue,maximumValue,granularity,excludedPorts);

}

public SensorPeer getPeerFor(Sensor sensor) {ActuatorPeer peer = getActuatorPeer(this, sensor);return peer;

}public ActuatorPeer getPeerFor(Actuator actuator) {

ActuatorPeer peer = getActuatorPeer(this, actuator);return peer;

}}

Die Klassen BaseSensorPort und BaseActuatorPort werden nicht extra

beschrieben. Sie kapseln im Grunde nur die Parameter eines Ports, die dem Kon-

struktor �ubergeben werden. Dazu geh�ort auch die Instanz von RobotInterface,

zu der sie geh�oren. Die jeweiligen Port-Objekte sind daf�ur zust�andig, die Peer-

Objekte zu liefern, wenn ein Sensor-Objekt mit ihnen verbunden wird.

Bis es zu einem Peer kommt, werden folglich mehrere Stufen eines Factory-

Pattern (Gamma et al., 1995) durchlaufen: Die RobotInterfaceFactory er-

zeugt das RobotInterface welches wiederum die Ports erzeugt, die dann ih-

rerseits die Peer-Objekte liefern. Wie der entsprechende Peer genau erzeugt

wird ist dem Port, bzw. dem zugeh�origen RobotInterface �uberlassen. In dem

Beispiel werden die Peers gar nicht direkt von einem Port erzeugt, sondern die

Ports verwenden ihrerseits wieder "ihr" RobotInterface als Factory. Wichtig

ist nur, da� der Typ des Port aussagt, welchen Typ Peer man (mindestens)

erwarten kann.

In ART sind bisher nur SensorPort und ActuatorPort de�niert. Ein Axiom

der Port-Klassen soll es sein, da� sie jeweils einen bestimmten Peer-Typ garan-

Page 122: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

116 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

tieren. F�ur den SensorPort kann dieser Peer-Typ noch als Resultat der Me-

thode getPeerFor(Sensor) direkt angegeben werden. F�ur ActuatorPort, als

von SensorPort abgeleitetes Java-Interface, funktioniert das f�ur die gleiche Me-

thode nat�urlich nicht mehr. Dort mu� man dann entweder glauben bzw. �uber-

pr�ufen, da� der zur�uckgegebene SensorPeer auch wirklich ein ActuatorPeer

ist, oder man verwendet gleich die Methode getPeerFor(Actuator).

Mit "mindestens" ist in diesem Zusammenhang gemeint, da� je nach den

Umst�anden (wie z.B. dem Typ des Objektes f�ur das der Peer erzeugt wird),

auch eine entsprechende Unterklasse als Peer erzeugt werden kann. So liefert

ein ActuatorPort der Implementierung f�ur den Brick einen MotorPeer, wenn

ein Motor (oder eine Unterklasse davon) an den ActuatorPort angeschlossen

wird.1

Die restlichen Parameter der Konstruktoren f�ur die Ports sind:

portName: eine Bezeichnung f�ur den Port, die analog zur Bezeichnung der

Interface-Hardware f�ur diesen Anschluss (wenn eine solche existiert) lau-

ten sollte, um eine m�oglichst einfache Zuordnung durch einen Anwender

zu erm�oglichen.

portNumber: eine weitere Bezeichnung zur Identi�zierung des Ports innerhalb

der Implementierung von RobotInterface.

type: eine Bezeichnung anhand derer die Art des Actuators identi�ziert wer-

den kann. Bisher wird dies noch nicht weiter verwendet und dient nur

dazu, zus�atzliche Informationen �uber den ActuatorPort anzugeben, die

beispielsweise f�ur einen Benutzer ausgegeben werden k�onnen (z.B. ob der

Ausgang Gleich- oder Wechselstrom verwendet).

minimumValue: der kleinste Wert, der von einem Peer geliefert w�urde, den

Sensor-Objekte bekommen, �uber deren Klasse sonst nichts weiter be-

kannt ist (also die, die keinen speziellen Peer bekommen).

maximumValue: entsprechend minimumValue, nur eben der gr�o�te Wert.

granularity: die Anzahl von Abstufungen, die zwischen minimumValue und

maximumValue f�ur diesen "einfachsten" Peer existieren.

excludedPorts: ein Array von Port-Objekten, die Anschl�usse repr�asentieren,

die nicht gleichzeitig mit dem Anschlu� dieses Port-Objekts verwendet

werden k�onnen.

1MotorPeer ist ein subinterface von ActuatorPeer (siehe Abbildung 4.5 auf Seite 47 und

Abschnitt 4.6 auf Seite 50)

Page 123: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.4. DIE METHODEN VON ROBOTINTERFACE 117

6.4 Die Methoden von RobotInterface

In diesem Abschnitt geht es vor allem um die Methoden, die von dem Java-

Interface RobotInterface vorgeschrieben werden.

RobotInterfaceDe�nition

Wie bereits in Kapitel 5 auf Seite 59 beschrieben wurde, kann man bestimmte

Instanzen von RobotInterface �uber die Angabe einer RobotInterfaceDefi-

nition ausw�ahlen:

Listing 46: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

private static String definitionPrefix = "AWT";private RobotInterfaceDefinition definition;

public RobotInterfaceDefinition getInterfaceDefinition() {return definition;

}

public boolean conformsTo(RobotInterfaceDefinition definition) {if(this.definition.equals(definition)

|| new RobotInterfaceStringDefinition(definitionPrefix).equals(definition)) {

return true;} else {

return false;}

}

private AWTRobotInterface(int interfaceNumber) {String definitionString = definitionPrefix +interfaceNumber;definition =

new RobotInterfaceStringDefinition(definitionString);...

}

Jedes RobotInterface besitzt eine Instanz von RobotInterfaceDefini-

tion, die dazu geeignet w�are, genau diese Instanz von RobotInterface aus-

zuw�ahlen. Diese RobotInterfaceDefinition bekommt man �uber getInter-

faceDefinition() und sie sollte eindeutig einer einzigen Instanz vom Typ

RobotInterface zugeordnet sein, in dem Sinne, da� nur eine einzige (erfolg-

reich erzeugte) Instanz vom Typ RobotInterface, bei Aufruf von conforms-

To(RobotInterfaceDefinition) den Wert true zur�uckliefert. Auf diese Wei-

se bekommt man von RobotInterfaceFactory, bei Aufruf von getInter-

face(RobotInterfaceDefinition), f�ur diese eine RobotInterfaceDefini-

tion, immer die gleiche Instanz pr�asentiert. F�ur diese Eindeutigkeit mu� man in

dem Beispiel beim Aufruf des Konstruktors sorgen. Da dieser private markiert

ist, ist er aber nur innerhalb dieser Klasse �uberhaupt sichtbar. Er wird von der

Klassenmethode getInterfaces(RobotInterfaceDefinition[]) aufgerufen,

welche in Abschnitt 6.5 auf Seite 120 n�aher beschrieben wird.

Page 124: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

118 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

Im Gegenzug hei�t das jedoch nicht, da� es keine RobotInterfaceDefini-

tion geben kann, f�ur die sich auch mehrere Instanzen vom Typ RobotInterface

"zust�andig" f�uhlen k�onnen. Im Beispiel w�are das f�ur eine RobotInterface-

StringDefinition der Fall, wenn diese den String "AWT" repr�asentiert. Robot-

InterfaceDefinition ist nur ein sogenanntes tagging-interface, welches kei-

ne Methoden vorschreibt. Welche Klasse als RobotInterfaceDefinition ver-

wendet wird, bleibt voll und ganz der jeweiligen Implementierung von Robot-

Interface �uberlassen. Im Beispiel { entsprechend den anderen bereits in ART

vorhandenen RobotInterface-Implementierungen { wird die Klasse Robot-

InterfaceStringDefinition verwendet, welche f�ur die meisten F�alle ausrei-

chen sollte.

Erzeugen der Ports

Die Ports eines RobotInterface braucht man, um Sensoren anschlie�en zu

k�onnen. Von RobotInterface werden Methoden de�niert, mit denen die Port-

Instanzen erfragt werden k�onnen. Diese sind nicht weiter aufw�andig, es werden

nur entsprechend initialisierte Sensor- bzw. ActuatorPort-Objekte zur�uckge-

geben:

Listing 47: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

public SensorPort[] getSensorPorts() {return new SensorPort[]{

new AWTSensorPort( "TextFieldInput0",0,Double.NEGATIVE INFINITY,Double.POSITIVE INFINITY,-1,null),

new AWTSensorPort( "TextFieldInput1",1,Double.NEGATIVE INFINITY,Double.POSITIVE INFINITY,-1,null)};

}

public ActuatorPort[] getActuatorPorts() {return new ActuatorPort[]{

new AWTActuatorPort("TextFieldOutput0",0,"",Double.NEGATIVE INFINITY,Double.POSITIVE INFINITY,-1,null),

new AWTActuatorPort("TextFieldOutput1",1,"",Double.NEGATIVE INFINITY,

Page 125: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.4. DIE METHODEN VON ROBOTINTERFACE 119

Listing 47: code/art/examples/AWTRobotInterface.java (Fortsetzung)

Double.POSITIVE INFINITY,-1,null)};

}

Eine Erkl�arung der Bedeutung der einzelnen Parameter, der Konstruktoren

f�ur die Ports, wurde bereits in Abschnitt 6.3 auf Seite 114 gegeben.

Erzeugen der Peers

Die Methoden zur Erzeugung der Peer-Instanzen in AWTRobotInterface sind

nicht public und werden von dem Java-Interface RobotInterface auch nicht

vorgegeben:

Listing 48: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

private TextFieldSensorPeer inPeer0;private TextFieldSensorPeer inPeer1;SensorPeer getSensorPeer(SensorPort port, Sensor sensor) {

switch(port.getPortNumber()) {case 0:

if(inPeer0 == null) {inPeer0 = new TextFieldSensorPeer(in0);

}return inPeer0;

case 1:if(inPeer1 == null) {

inPeer1 = new TextFieldSensorPeer(in1);}return inPeer1;

default:return null;

}}

private TextFieldActuatorPeer outPeer0;private TextFieldActuatorPeer outPeer1;ActuatorPeer getActuatorPeer(ActuatorPort port, Sensor sensor) {

switch(port.getPortNumber()) {case 0:

if(outPeer0 == null) {outPeer0 = new TextFieldActuatorPeer(out0);

}return outPeer0;

case 1:if(outPeer1 == null) {

outPeer1 = new TextFieldActuatorPeer(out1);}return outPeer1;

default:return null;

Page 126: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

120 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

Listing 48: code/art/examples/AWTRobotInterface.java (Fortsetzung)

}}

In diesen beiden Methoden mu� der Port nicht darauf �uberpr�uft werden, ob

er "einer von uns" ist, da die Methode keinen public-access besitzt und daher

nicht von beliebigem Code aus aufgerufen werden kann. Wie bereits erw�ahnt

sollen Peer-Instanzen nur �uber die jeweiligen Port-Objekte "nach au�en" ge-

langen. Auf diese Weise ist der konkrete Vorgang, wie ein Port zu dem Peer f�ur

einen Sensor kommt, vor dem Anwender versteckt. Damit bekommt man die

Freiheit, die Peers dort zu erzeugen wo man es f�ur sinnvoll h�alt.

Es w�are durchaus denkbar, da� die Port-Klassen von AWTRobotInterface

die Peer-Instanzen direkt selbst erzeugen. Dies ist nur eine Stil- und Designfrage

innerhalb der Implementierung von RobotInterface. Die Verwendung zentraler

Methoden hat den Vorteil, da� die Erzeugung der Peers nicht �uber mehrere Stel-

len verteilt geschieht. Wenn man z.B. eine Unterklasse von AWTRobotInterface

erstellt, in der man auf die Erzeugung der Peers Ein u� nehmen will, so mu�

man nur eine der beiden Factory-Methods (Gamma et al., 1995) �uberschreiben.

W�urde man daf�ur neue Port-Klassen erstellen, so m�u�te man au�erdem alle

die Stellen �andern, an denen Instanzen dieser Klassen erzeugt werden.

Die Bedeutung der Methode isConnected wurde bereits in Abschnitt 6.2

auf Seite 110 behandelt. Sie ist daher dort abgedruckt (Listing 43 auf Seite 112).

Die letzte zu implementierende Methode isAlive() hat eine damit verwandte

Bedeutung:

Listing 49: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

public boolean isAlive() {return true;

}

Die Methode isAlive() dient dazu herauszu�nden, ob die Interface-Hard-

ware noch wie erwartet antwortet, ob die Verbindung also nicht nur physikalisch,

sondern auch logisch in Ordnung ist. Das ist bei Textfeldern im AWT im Prinzip

immer der Fall.

6.5 Die Einbindung in ART: RobotInterfaceFactory

Instanzen vom Typ RobotInterface erzeugt man in ART nicht direkt. Daf�ur

ist die Klasse RobotInterfaceFactory vorgesehen. Diese hat mehrere Metho-

den, die alle eine oder mehrere Instanzen vom Typ RobotInterface zur�uck-

liefern. Welche das sind, kann man haupts�achlich �uber die Angabe von einer

(oder mehreren) RobotInterfaceDefinition beein ussen, denen die zur�uck-

gelieferten Instanzen gen�ugen m�ussen (siehe die Beschreibung zu Listing 46 auf

Seite 117).

Die Klasse RobotInterfaceFactory besitzt daf�ur eine Liste von Klassen,

denen sie die Gelegenheit gibt, Instanzen f�ur die entsprechende Menge von

RobotInterfaceDefinitions zu erzeugen. Die Methode die RobotInterface-

Page 127: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.5. DIE EINBINDUNG IN ART: ROBOTINTERFACEFACTORY 121

Factory bei diesen Klassen daf�ur aufruft ist getInterfaces(RobotInterface-

Definition[]):

Listing 50: code/art/examples/AWTRobotInterface.java (Ref. in Listing 41 S. 108)

..public static synchronized RobotInterface[]

getInterfaces(RobotInterfaceDefinition[] ports){

// ’ search’ port-array for the AWT-onesVector interfaces = new Vector();for(int i=0; i<ports.length; i++) {

...// don’ t accept String ’ ALL’ , only return an// AWTInterface if explicitly asked for

...iface =

new AWTRobotInterface(interfaceNumber);// was initialization successful ?if(iface.isConnected()) {

interfaces.add(iface);portNamesToInterfaces

.put(new Integer(interfaceNumber),iface);

} else {if(debug.debug) {

debug.printInfo(iface+" is not connected,"+" not adding.");

}}

...}

RobotInterface[] result =new RobotInterface[interfaces.size()];

interfaces.copyInto(result);return result;

}

Diese Implementierung stammt aus dem Beispiel AWTRobotInterface. Der

gr�o�te Teil ist hier f�ur eine bessere �Ubersichtlichkeit nicht abgedruckt, da er zum

grunds�atzlichen Verst�andnis nicht notwendig ist. Wenn man wirklich ein eigenes

RobotInterface implementieren m�ochte, oder einfach nur Interesse daran hat,

kann man ja selbst in die Quelldatei schauen.

Wichtig ist, da� die Methode ein Array von RobotInterface-Objekten

zur�uckliefert, die alle soweit erfolgreich initialisiert werden konnten. F�ur jedes

zur�uckgelieferte RobotInterface sollte sichergestellt sein, da� f�ur wenigstens

eine RobotInterfaceDefinition in dem Array ports die conformsTo(Robot-

InterfaceDefinition)-Methode den Wert true liefert, damit die semantische

Konsistenz gewahrt bleibt.

Zudem sollte die Methode versuchen, m�oglichst f�ur alle angegebenen Robot-

Page 128: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

122 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

InterfaceDefinition, die zu der entsprechenden Implementierung von Robot-

Interface geh�oren, eine Instanz zu liefern. Daf�ur kann es notwendig sein, sich

bei fr�uheren Aufrufen erzeugte Instanzen zu merken und bei Bedarf erneut

zur�uckzuliefern. Wenn z.B. ein echtes Hardware-Interface im Spiel ist, w�are es

wohl meistens nicht praktikabel mehrere Instanzen von RobotInterface zu er-

zeugen, die sich alle um dieselbe Hardware "k�ummern" wollen. Es kann aber

durchaus sein, da� ein und dasselbe RobotInterface von verschiedenen Pro-

grammteilen verwendet wird, die durch unterschiedliche Anfragen an Robot-

InterfaceFactory, Zugri� auf dieselbe Hardware bekommen m�ochten.

Die Liste der Klassen, die von RobotInterfaceFactory gefragt werden,

stammt aus der Property

de.jaetzold.art.RobotInterfaceFactory.platforms

Diese Property sollte eine durch whitespace getrennte Liste von voll quali-

�zierten Klassennamen enthalten. Alle diese Klassen werden �uber re ect dar-

auf untersucht, ob sie die Klassenmethode getInterfaces(RobotInterface-

Definition[]) besitzen. Diese werden dann dazu verwendet, die Instanzen von

RobotInterface zu erzeugen. Daf�ur geht die RobotInterfaceFactory davon

aus, da� der R�uckgabetyp der Methode RobotInterface[] ist.

Abbildung 6.2: Der Algorithmus von Trusty steuert einen virtuellen Roboter mit dem

AWTRobotInterface.

Um also das Beispiel AWTRobotInterface auch �uber die RobotInterface-

Factory zug�anglich zu machen, mu� man nur die Property entsprechend setzen.

Es gibt daf�ur einerseits die Kon�gurationsdatei de.jaetzold.art.properties,

die von RobotInterfaceFactory gelesen wird, andererseits werden auch even-

tuelle System-Properties ausgewertet, und zwar mit Vorrang vor dem Inhalt

der Kon�gurationsdatei. F�ur einen Test reicht es also v�ollig, die Property beim

Aufruf von java mit dem Parameter -D zu setzen:

$ java -Dde.jaetzold.art.RobotInterfaceFactory.platforms=de.jaetzold.art.examples.AWTRobotInterface de.jaetzold.art.examples.SubsumptionTrustyAWTDemoRobot

Genauso, wie f�ur die Implementierungen f�ur Fischertechnik und den Brick,

gibt es im package de.jaetzold.art.examples f�ur die Beispielalgorithmen,

Page 129: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

6.5. DIE EINBINDUNG IN ART: ROBOTINTERFACEFACTORY 123

die f�ur Trusty mit Subsumption ben�otigt werden, Implementierungen f�ur deren

Robot Java-Interface, die mit dem AWTRobotInterface funktionieren.

Auf der erscheinenden Ober �ache (siehe Abbildung 6.2 auf der vorherigen

Seite) kann man dann, wie schon in Kapitel 5 auf Seite 59, die Funktionen

von Trusty aufrufen bzw. mit move den Subsumption-Algorithmus in Bewe-

gung setzen. Im Fenster des AWTRobotInterface kann man die Ver�anderung

der Motoren beobachten und durch Eingabe von 1 in den Textfeldern f�ur die

Sensoren, Trusty's Ausweichverhalten ausl�osen, denn der Wert 1 wird von ei-

nem BooleanSensor standardm�a�ig als texttttrue interpretiert und daher von

den Trusty-Algorithmen wie ein gedr�uckter Schalter verstanden.

Page 130: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

124 6. IMPLEMENTIERUNG EINES ROBOTINTERFACE

Page 131: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

7

Zusammenfassung

Neben einem kurzen Fazit wird in diesem Kapitel das Abstract Robot Toolkit

nochmal gegen�uber den Systemen aus Kapitel 3 abgegrenzt. Zudem wird auf

die Punkte n�aher eingegangen, in deren Zusammenhang fruchtbar erscheinende

Entwicklungsperspektiven existieren.

7.1 Ergebnis

Die Beispiele aus Kapitel 5 haben gezeigt, da� es mit ART m�oglich ist, einen

Algorithmus zur Robotersteuerung auf verschiedenen Hardware-Plattformen

wiederzuverwenden. Es wurden daf�ur teilweise eigene, objektorientierte De-

signs entwickelt, mit denen weitgehend unabh�angig von der konkreten Aus-

pr�agung der Komponenten des jeweiligen Roboters, ein Steuerungsalgorithmus

entwickelt werden kann. Die Verwendung von Objekten zur Repr�asentation der

Komponenten eines Roboters ist elegant und eine event-getriebene Programmie-

rung unter Verwendung von mehreren Threads erweist sich f�ur die Abstraktion

des Roboters und seines Verhaltens als sehr tauglich.

Im Fachbereich Wirtschaftswissenschaften an der Universit�at Osnabr�uck

wird ART seit Oktober 2001 eingesetzt. In dem Projekt "Virtuelles Seminar"

(http://vsem.oec.uni-osnabrueck.de/) werden �uber ein Fischertechnik-In-

terface Kameras undMikrofone geschaltet, sowie "Meldungen" von Teilnehmern

registriert. ART wird dort verwendet, weil es die einzige bekannte Java-L�osung

ist, die auch das Expansion-Modul zum Intelligent Interface von Fischertechnik

ansteuern kann.

7.2 Geschwindigkeit

Wenn an manchen Stellen, im Design und in der Implementierung, Kompromis-

se zwischen Performance und Flexibilit�at eingegangen werden mussten, wurde

meistens auf Kosten der Performance entschieden. So wird z.B. bei jeder re-

gistrierten �Anderung eines Sensorwerts mindestens ein neues Event-Objekt er-

zeugt. Das logische Design und die strukturellen M�oglichkeiten standen immer

im Vordergrund.

125

Page 132: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

126 7. ZUSAMMENFASSUNG

F�ur Anwendungen, bei denen es wirklich auf Geschwindigkeit ankommt, ist

aber schon die gesamte Umgebung ungeeignet, da das normale Java Develop-

ment Kit von Sun nicht echtzeitf�ahig ist. Es existieren zwar bereits Bestrebun-

gen f�ur eine standardisierte Echtzeit-Erweiterung (Bollella et al., 2000), doch

Implementierungen davon sind zumindest bisher nicht frei verf�ugbar. Zudem ist

in diesem Zusammenhang z.B. die Kommunikation mit der Interface-Hardware

�uber Infrarot, wie das beim Brick der Fall ist, problematisch. Au�erdem mu�

nicht nur Java, sondern auch das zugrunde liegende Betriebssystem echtzeitf�ahig

sein, was zumindest f�ur Linux und Windows spezielle Erweiterungen erfordert.

Mit der Performance eines Systems wie legOS kann ART auf keinen Fall

mithalten, obwohl bestimmt noch einige M�oglichkeiten zur Optimierung der

Performance, in den Implementierungen f�ur den Brick und das Intelligent In-

terface, vorhanden sind. Kommt es auf einigerma�en schnelle Reaktionszeiten

an, ist ART im Zusammenhang mit Lego bisher nicht verwendbar, was aber

zu einem erheblichen Teil an der langsamen und unzuverl�assigen Infrarotkom-

munikation liegt. Bei der Ansteuerung des Brick vergeht dort viel Zeit. Bis ein

Befehl an den Brick angekommen und umgesetzt ist, k�onnen leicht 100 Milli-

sekunden vergehen. In Kombination mit der Tatsache, da� der Brick eigentlich

drei Befehle ben�otigt, um den kompletten Zustand eines Motors zu beschreiben,

ist es z.B. kaum m�oglich zwei Motoren ann�ahernd gleichzeitig zu starten oder

zu stoppen. Zum Teil k�onnten aber auch noch bessere Strategien entwickelt

werden, vor allem in der Ansteuerung der Motoren.

Die F�ahigkeit des Brick, eigene Prozesse auszuf�uhren, wird nicht genutzt.

Zusammen mit der existierenden M�oglichkeit, Speicherpl�atze f�ur Variablen im

Brick zu lesen und zu schreiben, kann man im Grunde ein eigenes Kommuni-

kationsprotokoll zur Ansteuerung der Motoren entwickeln. Damit l�asst sich das

Problem, da� die Motoren nicht synchron geschaltet werden k�onnen, ganz gut

umgehen. F�ur die Steuerung eines fu�ballspielenden Lego Cybermaster, wurde

diese Technik bereits einmal verwendet (J�atzold, 2002). Sie wurde jedoch nicht

allgemein in ART integriert.

Die Ansteuerung von Fischertechnik geht hingegen recht schnell. Trotzdem

ist f�ur Zeiten unter 20 Millisekunden selbst Fischertechnik nicht mehr ausrei-

chend. Das kann an der seriellen Kommunikation in Java liegen, wie der Unter-

schied zum parallelen Interface in Schreiner (2000b) zeigt.

7.3 Flexibilit�at

Es hat sich gezeigt, da� die Menge von Dingen, die man mit Sensoren und Ac-

tuatoren abbilden kann, �uber die Komponenten eines Roboters hinausgeht. Dies

ist aber nur folgerichtig, wenn man bedenkt, da� es das Ziel von ART war, von

der konkreten Roboter-Hardware zu abstrahieren. So wird ein BooleanSensor

verwendet, um dem Scheduler f�ur Subsumption die Bereitschaft einer Verhal-

tensweise zu signalisieren. Konstante Werte werden, durch einen Constant-

SensorPort, f�ur beliebige Sensoren verf�ugbar gemacht. Die M�oglichkeiten sind

sehr weitgehend und k�onnen wahrscheinlich noch zu sehr interessanten Ergeb-

nissen f�uhren.

Page 133: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

7.4. ARCHITEKTUR 127

Das Ariadne-Beispiel f�ur leJOS ist wesentlich einfacher gestrickt als Ariad-

ne f�ur ART. Das h�angt vor allem damit zusammen, da� der Speicher auf dem

Brick sehr begrenzt ist und daher in leJOS nur sehr kleine Teile des norma-

len Java-API verf�ugbar sein k�onnen. Daher konnten auch viele f�ur das ART-

Beispiel verwendete Hilfsklassen nicht, bzw. nicht ohne weiteres, �ubernommen

werden. leJOs ist zwar schneller in den Reaktionszeiten, aber was Speicher,

Klassenbibliothek und Rechengeschwindigeit angeht ist die ART-L�osung auf

einem modernen PC wesentlich leistungsf�ahiger.

Das entwickelte Toolkit bietet eine sehr bequeme M�oglichkeit, um einfache

Fernsteuerungen von Lego und/oder Fischertechnik von einem PC aus in Java

zu realisieren { beispielsweise die Bewegung einer Webcam. Andere Java-L�osun-

gen, die auf Interna der verwendeten Roboter-Hardware beruhen, sind deutlich

schwieriger zu benutzen, zumindest wenn man die Interna erst kennen lernen

mu�.

Naivere Verwendung: Bis man in ART soweit ist, da� man einen Sensor

auch wirklich verwenden kann, sindmehrere Schritte erforderlich. Dies erschwert

eine sehr naive Verwendung von Sensoren ein wenig. Ein Sensor mu� immer

mit einem Port verbunden werden, sonst hat er keinen SensorPeer. Der Port

wiederum wird, in den meisten F�allen, von einem RobotInterface stammen,

das seinerseits von einer Factory erzeugt wurde.

Im Prinzip ist es m�oglich, da� ein Sensor-Objekt, wenn es erzeugt wird,

von selbst versucht, eine Verbindung zu einem geeigneten Peer herzustellen.

Es bleibt o�en nach welchen Regeln dieser Peer dann ausgew�ahlt wird. Es ist

bisher nicht klar, inwieweit diese Regeln kon�gurierbar sein m�ussten, damit eine

eindeutige und trotzdem exible Verbindung zwischen den Sensor-Objekten der

Software und den Sensoren der Hardware m�oglich bleibt.

7.4 Architektur

F�ur die Verwendung mit Lego und Fischertechnik ist die entwickelte Archi-

tektur von Sensor-Klassen gut geeignet. Es wurde au�erdem weitgehend auf

m�ogliche andere Hardware-Plattformen R�ucksicht genommen. So existiert z.B.

f�ur einen Servo ein eigener ServoPeer, obwohl weder Lego noch Fischertechnik

Servomotoren auf der Hardware-Seite direkt unterst�utzen.

Es m�u�te nun untersucht werden inwieweit die Architektur anderen Plattfor-

men gerecht wird. Es ist nicht m�oglich auszuschlie�en, da� sich manches, insbe-

sondere Teile der Hierarchie der Sensor-Klassen, f�ur eine bestimmte Hardware-

Plattform als schwierig herausstellt.

Die Klasse AngleSensor ist m�oglicherweise nicht ideal in die Hierarchie

der Sensor-Klassen eingeordnet. So ist ein AngleSensor in ART eine Unter-

klasse von CountSensor und damit auch von StateSensor. Ein StateSensor

repr�asentiert aber diskrete Zust�ande, ein AngleSensor hingegen eine physi-

kalische Gr�o�e. Die momentane Position von AngleSensor in der Klassen-

Hierarchie ist vor allem der Hardware von Lego und Fischertechnik angemessen,

da bei beiden Winkel durch Rotationen und diese wiederum durch Folgen von

Page 134: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

128 7. ZUSAMMENFASSUNG

Zustands�anderungen gemessen werden. Somit ist ein AngleSensor als Unter-

klasse von CountSensor, welcher f�ur das Z�ahlen der Zustands�anderungen ge-

dacht ist, sehr praktisch. Es ist aber auch vorstellbar, da� ein Winkel z.B. durch

ein Potentiometer gemessen wird. Das hat mit Zust�anden und deren �Anderun-

gen nichts mehr zu tun. Eine erneute Implementierung sollte wohl besser einen

AngleSensor de�nieren, der an einen CountSensor angeschlossen werden kann,

anstatt einen, der ein CountSensor ist.

Weiterhin k�onnen die bisher de�nierten, beschreibenden Eigenschaften der

Sensoren, wie z.B. die Genauigkeit oder der Messbereich, wahrscheinlich nicht

allen m�oglichen F�allen gerecht werden. Vor allem die Genauigkeit ist auch inso-

fern ein Problem, da praktisch jeder Algorithmus von ihr abh�angt, wenn auch

in unterschiedlichem Ausma�. Ein einzelner Wert, zur Beschreibung der Ge-

nauigkeit eines Sensors, ist aber selbst schon ungenau, denn ein Sensor kann

z.B. in unterschiedlichen Messbereichen oder Umgebungsbedingungen unter-

schiedlich genau sein. Daher m�u�te die Genauigkeit durch eine Funktion mit

vielen Parametern beschrieben werden und nicht nur durch einen einzelnen

Wert. Eventuell f�uhrt das aber nun zu weit und man hat eine der Grenzen der

hardware-unabh�angigen Steuerung von Robotern gefunden.

Programmierbare Tasks: Die F�ahigkeiten des Brick wurden nicht komplett

umgesetzt. Es gibt bisher z.B. keine eigene Klasse f�ur den Temperatursensor.

Dies w�are aber notwendig, wenn man den Eingang des Brick speziell daf�ur

kon�gurieren k�onnen will. Das Betriebssystem von Lego f�ur den Brick bietet

eine Umrechnungsmethode f�ur boolesche Sensorwerte an, die bisher auch nicht

erreichbar ist (EdgeCount). Auf die M�oglichkeit sogenannte Messages zu ver-

schicken, auf lokale Variablen des Brick zuzugreifen oder gar eigene Tasks zu

laden und auf dem Brick zur Ausf�uhrung zu bringen, mu� man bisher verzich-

ten.

Programme zu de�nieren und auf die Interface-Hardware zu �ubertragen,

ist mit ART bisher nicht m�oglich. Analog zu den M�oglichkeiten von Spirit.ocx

(siehe 3.2.1 auf Seite 23) k�onnte man aber eventuell ein Task-Objekt entwickeln.

Vielleicht ist die Programmierung von Tasks auch �uber eine entsprechende

Erweiterung der Eigenschaft "waitForCompletion" m�oglich. So k�onnten even-

tuell Befehle, die man z.B. an einen Motor sendet, erst einmal gesammelt und

dann als Block auf das Interface �ubertragen und ausgef�uhrt werden.

Eine Integration der F�ahigkeit des Bricks, eigene Tasks auszuf�uhren, d�urfte

aber sehr interessant werden. Eventuell kann man damit viele der bisherigen

Geschwindigkeitsprobleme mit dem Brick in den Gri� bekommen. Es stellt sich

hier jedoch die Frage, inwieweit diese Technik wirklich plattformunabh�angig

realisierbar ist. Eventuell ist es am geschicktesten, daf�ur eine eigene einfache

Sprache zu entwickeln, die je nach Zielsystem entsprechend interpretiert werden

kann.

Page 135: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

7.5. SICHERHEIT 129

7.5 Sicherheit

Sowohl das Intelligent Interface von Fischertechnik, als auch das �altere Interface

mit einem Anschluss f�ur die parallele Schnittstelle, haben eine Sicherheitsfunk-

tion eingebaut. Werden vom PC aus an das Interface f�ur eine gewisse Zeit (etwa

300-500 Millisekunden) keine Daten mehr verschickt, so werden alle Ausg�ange

abgeschaltet. Dies ist solange der Fall bis das Interface wieder einen Befehl vom

PC erh�alt.

Eine solche Schutzfunktion ist im Grunde wichtig. Software enth�alt leider

auch Fehler. Wenn solch ein Fehler dann dazu f�uhrt, da� der Roboter v�ollig

unkontrollierte Aktionen ausf�uhrt und sich selbst (oder sogar seine Umgebung)

"zerlegt", kann das teuer werden.

Der Brick hat eine solche Schutzfunktion nicht. Auch Fischertechnik ist

nat�urlich durch die beschriebene Technik nicht vor allen Fehlern gesch�utzt.

Wenn z.B. ein wichtiger Schalter nicht richtig angeschlossen ist, oder die Soft-

ware zwar mit dem Interface kommuniziert, aber eben nicht wie erwartet, so

greift der Schutzmechanismus nicht. Gerade beim Brick w�are diese Funktion

aber bei der Steuerung vom PC aus hilfreich, denn allzuoft passiert es, da� er

aus dem Sendebereich des Towers herausf�ahrt oder aus irgendeinem anderen

Grund die Infrarotkommunikation gest�ort ist.

In ART ist solch eine Schutzfunktion bisher nicht implementiert. Auch der

eingebaute Schutz von Fischertechnik wird teilweise ausgehebelt, da es durch-

aus sein kann, da� der Steuerungsalgorithmus stehengeblieben oder abgest�urzt

ist, ohne die Threads, die bei Fischertechnik mit der Interface-Hardware kom-

munizieren, in Mitleidenschaft gezogen zu haben.1

Um eine solche Schutzfunktion zur Verf�ugung zu stellen, w�are es also not-

wendig, da� eine Implementierung von RobotInterface regelm�a�ig gewisse Be-

dingungen �uberpr�uft und gegebenenfalls einige oder alle Ausg�ange abschaltet.

Im Optimalfall w�urden nur genau die Ausg�ange stillgelegt, f�ur die ein steu-

ernder Algorithmus in irgendeiner Form nicht mehr "richtig" funktioniert. Falls

der Steuerungsalgorithmus sich wieder aufrappeln sollte, oder ein anderer daf�ur

sorgt, da� die Ausg�ange vern�unftige Werte haben, w�are es w�unschenswert wenn

die Ausg�ange auch wieder aktiviert w�urden.

Ob der Algorithmus noch korrekt funktioniert, kann { wenn �uberhaupt {

nur der Algorithmus selbst wissen. Zum Beispiel k�onnte ein Algorithmus re-

gelm�a�ig checken, ob er sich noch in einem konsistenten Zustand be�ndet oder

alle seine Threads noch laufen. Wenn er sich aber nicht mehr in einem konsi-

stenten Zustand be�ndet und erst recht wenn keiner seiner Threads mehr aktiv

ist, kann er sich wahrscheinlich nicht mehr von sich aus "melden". Damit nun

aber nicht jeder Algorithmus darauf achten mu�, z.B. alle 300 Millisekunden

eine Nachricht an das RobotInterface zu schicken, kann man auch den umge-

kehrten Weg gehen: Das RobotInterface, bzw. die Actuator-Objekte, fragen

den Algorithmus von sich aus regelm�a�ig danach, ob noch alles in Ordnung ist.

Dies ist wieder ein typischer Fall f�ur das Delegate-Design-Pattern, welches

1Genaugenommen werden die Threads, die mit der Interface-Hardware kommunizieren,

sogar niemals durch das Versagen eines Steuerungsalgorithmus gest�ort.

Page 136: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

130 7. ZUSAMMENFASSUNG

auch schon bei der Beschreibung der Sensor-Klassen, in Abschnitt 4.6 auf Sei-

te 50, erw�ahnt wurde. Ein RobotInterface (bzw. ein Actuator, wenn man

eine feinere "Au �osung" haben m�ochte) k�onnte eine Art aliveDelegate besitzen.

Dieser w�urde dann regelm�a�ig gefragt ob noch alles in Ordnung ist und falls

nicht, w�urde sich das RobotInterface, bzw. der Actuator, tempor�ar abschal-

ten, bis eine Anfrage an den Delegate ergibt, da� wieder alles in Ordnung ist.

M�oglicherweise w�urde der oben beschriebene optimale Fall auch noch weitere

Kon�gurationsm�oglichkeiten oder Delegate-Methoden erfordern.

Solch ein Delegate wird von ART bisher nicht unterst�utzt. Vor allem die

Umsetzung f�ur den Brick w�urde einen Mehraufwand erfordern, f�ur den einfach

keine Zeit mehr vorhanden war.

7.6 Andere Hardware

Es existiert heute Hardware, die einerseits zwar immer noch klein ist und we-

niger Rechenkapazit�at als ein moderner PC besitzt, auf der anderen Seite aber

deutlich schneller ist und vor allem mehr Speicher enth�alt, als dies f�ur den

Brick der Fall ist. So gibt es f�ur viele aktuelle Mobiltelefone oder die sogenann-

ten PDA's (Personal Digital Assistant) eine Implementierung der J2ME (Java

2 Platform, Micro Edition). Speziell f�ur die Verwendung von Java auf einem

embedded device innerhalb eines Netzwerks, ist auch das TINI-Board (http:

//www.ibutton.com/TINI/) geeignet. Es zeichnet sich durch einen integrier-

ten seriellen Anschluss, seine Ethernetf�ahigkeit (TCP/IP inkl. FTP-, HTTP-

und Telnet-Server) und durch die Unterst�utzung weiterer Bussysteme aus. Das

TINI-Board gibt es mit 0.5 oder 1.0 MB Speicher und einer beinahe komplet-

ten Implementierung der Java-packages java.lang, java.io, java.net und

java.util. Kann man etwas l�oten oder kommt man mit einem der bereits vor-

handenen Bussysteme aus, so sollte es sich gut f�ur die Steuerung von Robotern

verwenden lassen. Ein naiver Versuch das Abstract Robot Toolkit auf TINI zu

�ubertragen, war nicht erfolgreich. Zur Fehlersuche kann man zwar ganz normal,

aus dem Programm heraus, Text zur Ablaufverfolgung ausgeben, jedoch wird

speziell durch diese Art von I/O-Operationen das TINI-Board besonders stark

beansprucht. Aus diesem Grund �andert sich das Zeitverhalten signi�kant. Dies

ist aber bei der verwendeten Interface-Hardware von schwerwiegender Bedeu-

tung, denn das Intelligent Interface schaltet sich z.B. ab, wenn es f�ur etwa 300

Millisekunden nichts mehr �uber die serielle Leitung empfangen hat.

7.7 Subsumption

Im Rahmen dieser Arbeit wurde Subsumption (siehe Abschnitt 1.2) zwar an-

gewandt, als wichtiges Konzept, das eventuell ganz neue M�oglichkeiten er�o�-

net, aber nur gestreift. F�ur die Programmierung mit ART ist die Klasse de.

jaetzold.art.subsumption.SchedulerTask ein Ansatz, um auf einfache Wei-

se Subsumption als Design-Pattern f�ur verhaltensbasierte Robotersteuerung zu

verwenden.

Page 137: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

7.8. JAVABEANS 131

Es k�onnte sich durchaus als fruchtbar erweisen, in dieser Richtung ein ei-

genes API zu entwickeln. Das mu� nicht unbedingt sehr umfangreich sein,

aber wenn die Schnittstellen zu den Verhaltensweisen und dem Scheduler wohl-

de�niert sind, dann ist eine Wiederverwendung der Verhaltensweisen { und

nat�urlich auch des Schedulers { leichter. So k�onnte sich mit der Zeit eine ganze

Bibliothek von fertigen Verhaltensweisen ansammeln.

Die M�oglichkeit, einen Roboter zu programmieren, indem bereits fertige

Algorithmen praktisch "zusammengesteckt" werden, ist vor allem auch im Hin-

blick auf die Programmierung mittels einer gra�schen Ober �ache sehr attraktiv.

Subsumption wird nicht nur f�ur die Programmierung echter, physikalischer

Roboter verwendet, sondern z.B. auch im Bereich der agentenbasierten Mo-

dellierung (Wooldridge, 1999). Aus diesem Grund w�are es vorteilhaft, wenn

das gleiche API { im Optimalfall sogar die gleichen Verhaltensweisen { sowohl

f�ur die Simulation im Computer als auch f�ur die Steuerung echter Roboter-

Hardware verwendet werden kann. Mit ART existiert daf�ur eine Basis. In Ka-

pitel 6 wurde gezeigt, da� die Algorithmen f�ur Trusty ohne gro�en Aufwand

auch mit dem rein softwarebasierten AWTRobotInterface verwendet werden

k�onnen.

Inwieweit aber ansonsten zwischen echten Robotern und Softwareagenten

�uberhaupt Gemeinsamkeiten bestehen, die eine Verwendung von Algorithmen

in beiden Bereichen rechtfertigen, be�ndet sich au�erhalb des Themas dieser

Arbeit.

7.8 JavaBeans

Nach der Spezi�kation von Sun (Sun Microsystems, 1997) bezeichnet das Ja-

vaBeans API eine Menge von Design-Pattern und Hilfsklassen und soll als

Komponentenmodell f�ur Java dienen. Das Ziel sind portable, wiederverwend-

bare Softwarekomponenten, die als solche verkauft werden k�onnen und vom

K�aufer je nach Anforderungen zu fertigen Applikationen zusammengebaut wer-

den { am besten in einem (gra�schen) Editor. Dies erinnert an die Paletten

f�ur den Interface-Builder unter OpenStep (Gar�nkel und Mahoney, 1993) und

nun MacOS-X. Au�erdem sollen Beans als eine Art Plugin dienen um Appli-

kationen zu erweitern. Diese Funktionalit�at kann auch in plattformabh�angige

Komponentenarchitekturen wie OpenDoc, OLE, COM, Active-X usw. integriert

werden.

Im Zusammenhang mit der Programmierung von Robotern halte ich vor

allem das Arrangement und die Manipulation von Komponenten in einem gra-

�schen Editor f�ur interessant. Nicht von ungef�ahr werden von Lego und Fi-

schertechnik in erster Linie gra�sche Programmierumgebungen zur Ansteue-

rung ihrer Interface-Hardware angeboten. Die gr�o�eren Geschwister von Robo-

Lab und LLWin (LabView und iCon-L) werden in Labors zur Datenerfassung

und Auswertung sowie zur Industrieautomation eingesetzt. Es besteht also of-

fenbar Bedarf an M�oglichkeiten zur gra�schen Programmierung von Robotern.

Dabei bieten Beans noch den Vorteil, da� sie auf ganz normalen Java-Klassen

beruhen und daher auch auf "konventionellem" Wege als Bibliothek von Objek-

Page 138: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

132 7. ZUSAMMENFASSUNG

ten verwendet werden k�onnen. Zudem k�onnen die M�oglichkeiten der gra�schen

Umgebung durch Entwicklung weiterer Beans leicht erweitert werden.

Eines der Ziele von ART ist die M�oglichkeit der Wiederverwendung von

Steuerungsalgorithmen f�ur verschiedene Roboter. Solch ein Roboter mu� dann

aber gewisse, vom Algorithmus de�nierte Anforderungen erf�ullen. So mu� ein

Trusty-Roboter z.B. irgendwelche Motoren haben, mit denen der Roboter be-

wegt werden kann, sowie Sensoren um Hindernisse zu registrieren. Der Algorith-

mus de�niert, was passieren soll, wenn die Motoren auf gewisse Weise gesteuert

werden, und welche Sensoren er ben�otigt bzw. wie deren Wert interpretiert wird.

Dazu kann es notwendig sein, die Motor- und Sensor-Objekte vor der �Ubergabe

an den Algorithmus geeignet zu kon�gurieren. Au�erdem mu� festgelegt wer-

den, an welchem Anschluss und (aufgrund der Hardware-Unabh�angigkeit von

ART) an welcher Hardware der Motor angeschlossen ist. Dies kann sicherlich in

vielen F�allen, auch bei erfahrenen Programmierern, am einfachsten mit einem

gra�schen Tool geschehen.

Es ist aber auch denkbar, da� der Algorithmus selbst als Bean realisiert ist.

So k�onnen nicht nur die Hardware-Komponenten des Roboters, sondern auch

seine gesamte Steuerung, in solch einem Tool gleichsam "zusammengeklickt"

werden. Mit Subsumption (siehe Abschnitt 4.8 auf Seite 57) gibt es sogar ein

Konzept, das die Kombination von vielen (einfachen) Steuerungsalgorithmen

zu einem komplexen Verhalten vereinfacht, so da� es m�oglich sein sollte, mit

zunehmendem Vorrat an Steuerungsalgorithmen immer mehr L�osungen allein

durch das "zusammenstecken" von bereits vorhandenen Komponenten zu rea-

lisieren.

Die Vorteile einer gra�schen Umgebung sehe ich in der leichteren Zug�ang-

lichkeit f�ur Neulinge, dem schnelleren "eben mal" Ausprobieren auch f�ur erfah-

renere Entwickler, f�ur Demos und rapid Prototyping, da man praktisch "onli-

ne" einfache Algorithmen zusammenklicken kann, w�ahrend man z.B. mit einem

Kunden f�ur die Software (bzw. den Roboter) die Anforderungen diskutiert. Zu-

mindest im Bereich der Ober �achenprogrammierung haben sich gra�sche Tools

inzwischen in den meisten IDE's einen festen Platz erobert.

Neben all den Vorteilen, die man von Beans hat, die sich vor allem aus

der exiblen Wiederverwendung ergeben, steht { wie so oft { der Nachteil, da�

sie einen recht hohen Entwicklungsaufwand ben�otigen. Dieser ist sogar noch

gr�o�er als bei einer normalen Software-Bibliothek, da f�ur jede Eigenschaft ei-

ner Komponente bestimmte Design-Pattern eingehalten werden m�ussen, um

die gr�o�tm�ogliche Interaktion und Integration von (sich im Grunde v�ollig unbe-

kannten) Objekten zu erreichen. Genauer f�uhre ich die Design-Pattern und die

Verwendung der Hilfsklassen hier nicht aus, verweise aber auf das Tutorial von

Sun (Campione et al., 1998) sowie einen Seminarvortrag (von Toschanowitz,

1999) in dem ich zum ersten mal N�aheres �uber JavaBeans erfahren habe.

7.9 XML

Die Implementierungen der Robot Java-Interfaces, die einen konkreten Robo-

ter f�ur einen bestimmten Steuerungsalgorithmus zug�anglich machen, kapseln

Page 139: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

7.10. PERSISTENZ 133

h�au�g nur statische Informationen �uber den jeweiligen Roboter. So wird dort

z.B. festgelegt, welche Klassen f�ur die Aktuatoren und Sensoren an welchen Port

angeschlossen sind und wie diese kon�guriert werden sollen. Nat�urlich k�onnen

auch noch weitere Parameter f�ur den Algorithmus enthalten sein, wie das z.B.

bei der gezeigten Implementierung f�ur NormalizedDriveTrainder Fall ist. Dort

wurde die Zeit, die der Roboter braucht, um einen Meter weit zu fahren bzw. ei-

ne ganze Umdrehung durchzuf�uhren, in der Implementierung des Java-Interface

NormalizedDriveTrainSimpleAlgorithm.Robot gespeichert.

Solche Implementierungen sollten aber eigentlich auch automatisch gene-

rierbar sein, wenn die entsprechenden Informationen in einem entsprechenden

Format gespeichert sind { zum Beispiel in XML. Am elegantesten stelle ich mir

eine L�osung vor, in der man den Roboter gra�sch zusammenklickt und kon�-

guriert. Ob die so erstellte Information dann in XML oder wie bei JavaBeans

�ublich, als Strom von persistenten Objekten, gespeichert wird { oder in einem

ganz anderen Format { beruht letzten Endes auch auf der Frage, inwieweit es

Tools gibt, die einen bei der Verwendung des jeweiligen Formats unterst�utzen.

F�ur JavaBeans und XML gibt es bereits gra�sche Editoren und insbesondere

XML strebt an, durch eine immer gleiche Syntax, das Format der Zukunft f�ur

die Speicherung und den Austausch von Dokumenten zu werden.

7.10 Persistenz

Wenn etwas in einem Editor erstellt wurde, dann m�ochte man diese Arbeit

auch speichern k�onnen und zu einem sp�ateren Zeitpunkt auf einem anderen

Rechner weiter be- bzw. verarbeiten. Im Falle von Beans sind das Objekte

sowie deren Kon�guration und Abh�angigkeiten untereinander, die gespeichert

werden m�ussen. Sie zusammen bilden z.B. das Programm, welches man gra�sch

erstellt hat.

Da die Beans im Editor echte "lebendige" Objekte sind, kann man sie dort,

noch w�ahrend man mit ihnen eine Applikation erstellt, gleich richtig verwenden.

Jede Kon�guration und Verbindung die man erstellt, kann sofort ausprobiert

werden, so da� das Programm, bzw. der Programmteil, den man im Editor

erstellt, dort im Grunde schon l�auft. Nun k�onnte man zwar im Prinzip alle

Arbeitsschritte, die zu diesem "Bean-Dokument" gef�uhrt haben, abspeichern

und immer wiederholen, wenn man dieses "Dokument" braucht, man kann aber

auch den aktuellen Zustand der Objekte abspeichern und dann sp�ater genau

so restaurieren, wie er vorher im Editor war. Letzteres bezeichnet man mit

Persistenz.

Die Notwendigkeit, da� JavaBeans persistent (serialisierbar) sein m�ussen, ist

der haupts�achliche Grund daf�ur, da� die Objekte von ART (noch) keine Beans

sind. Wie eine Serialisierung von Objekten, die einen Roboter repr�asentieren,

�uberhaupt aussehen kann, mu� noch untersucht werden. Da diese Roboter-

Objekte z.B. von zus�atzlicher Hardware abh�angen, die nicht auf jedem Com-

puter gleich (bzw. unter Umst�anden gar nicht) vorhanden ist, mu� bei der De-

serialisierung irgendwie die Verbindung zur Roboter-Hardware neu hergestellt

werden.

Page 140: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

134 7. ZUSAMMENFASSUNG

Inwieweit sich eine Serialisierung von Roboter-Objekten umsetzen l�asst und

wieviel zus�atzliche (Benutzer-)Information daf�ur erforderlich ist, wurde im Rah-

men dieser Arbeit nicht weiter verfolgt. Die Design-Pattern zum Zugri� auf

Events und Properties wurden in ART aber an den meisten Stellen bereits

ber�ucksichtigt, so da� bereits eine gute Grundlage zur Entwicklung echter Ja-

vaBeans f�ur Roboter gescha�en wurde.

Page 141: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

Anhang A

Installation des Abstract

Robot Toolkit

Dieser Abschnitt gibt eine Schritt-f�ur-Schritt �Ubersicht �uber die notwendigen

Schritte und Voraussetzungen, damit das Abstract Robot Toolkit verwendet

werden kann.

Java ART braucht Java um lau��ahig zu sein. ART wurde vor allem mit dem

jdk1.3 von IBM unter Linux entwickelt. Au�erdem wurde es auf die grund-

s�atzliche Lau��ahigkeit in Verbindung mit dem jdk1.2.2 von Sun unter

Linux und dem jdk1.3 von IBM unter Windows getestet.

Java Development Kits oder Java Runtime Environments f�ur verschiedene

Plattformen in unterschiedlichen Versionen bekommt man z.B. unter

http://java.sun.com/j2se/ oder

http://www.ibm.com/developerworks/java/jdk/index.html

In Bezug auf die Installation mu� deren eigene Dokumentation konsultiert

werden.

Das jdk1.3 von IBM wird f�ur ART empfohlen, denn vor allem unter Win-

dows kann man so am einfachsten Schwierigkeiten mit den seriellen Ports

umgehen.

JavaComm ART beruht auf dem Java Communications API in Bezug auf die

Ansteuerung der seriellen Schnittstelle. Dieses API ist nicht in jeder Java-

Installation enthalten, man mu� eine Version w�ahlen die zum installierten

Java passt.

F�ur das jdk1.3 von IBM kann man eine Implementierung des CommAPI

an der gleichen Stelle bekommen wie das jdk selbst:

http://www.ibm.com/developerworks/java/jdk/index.html

F�ur Windows und Solaris bietet Sun eine Implementierung an:

http://java.sun.com/products/javacomm/index.html

F�ur Linux (und wahrscheinlich auch Windows) gibt es eine freie Imple-

mentation:

http://www.rxtx.org/

135

Page 142: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

136 ANHANG A. INSTALLATION DES ABSTRACT ROBOT TOOLKIT

Auch hier wird f�ur die Installation auf die in den Paketen enthaltene

Dokumentation verwiesen.

ART Das Archiv art.jar enth�alt die bereits compilierten Klassendateien und

ist auf der CD zu dieser Arbeit enthalten. Neuere Versionen sind �uber das

Internet (http://www.jaetzold.de/art/) zu bekommen. Unter der Vor-

aussetzung, da� Java ab Version 1.2 und das Java Communications API

installiert sind, mu� man, um ART verwenden zu k�onnen, im Prinzip

nichts weiter tun als das Archiv art.jar in den Klassenpfad aufzuneh-

men.

Man mu� jedoch darauf achten, da� die property de.jaetzold.art.

RobotInterfaceFactory.platforms die gew�unschte Liste von Klassen-

namen f�ur die Treiber-Implementierungen enth�alt. Wenn die Datei de.

jaetzold.art.properties im aktuellen Pfad vorhanden ist wird ver-

sucht die entsprechende property aus dieser Datei zu laden. Eine Version

dieser Datei be�ndet sich an den gleichen Stellen wie auch art.jar. An-

sonsten hat man noch die M�oglichkeit die System-Property de.jaetzold.

art.RobotInterfaceFactory.platforms z.B. beim Start der Java-Ma-

schine �uber den Parameter -D zu setzen.

Die Quelldateien zu ART sind ausgepackt im Verzeichnis code/art auf

der CD oder als Archiv im Verzeichnis archive zu �nden. Auch von

den Quelldateien werden neuere Versionen �uber http://www.jaetzold.

de/art/ zum download bereit stehen. Es existiert ein make�le, dessen

Pfade per Hand an das jeweilige System, auf dem �ubersetzt werden soll,

angepasst werden m�ussen.

Roboter Momentan kann man mit ART den gelben "Brick", manchmal auch

"RCX" genannt, aus dem Lego-Mindstorms Robotics Invention System

und das Intelligent Interface von Fischertechnik steuern. F�ur die Steue-

rung des Brick ist der Infrarot-Tower in der Variante mit einem seriellen

Anschluss n�otig. Ob und wann weitere Systeme unterst�utzt werden, ist

nicht bekannt. �Uber http://www.jaetzold.de/art/ werden diese gege-

benenfalls bekannt gemacht.

Sonst Im Allgemeinen wird man auch die Dokumentation zu ART ben�otigen,

siehe dazu Abschnitt A.2 auf der n�achsten Seite.

A.1 Installation der Beispiele

Die Beispiele f�ur die Systeme aus Kapitel 3 be�nden sich in entsprechend be-

nannten Unterverzeichnissen auf der CD zu dieser Arbeit. Sie sind nicht all-

gemein im Internet verf�ugbar sondern nur auf Anfrage. Sie k�onnen mit dem

jeweiligen Programmiersystem direkt geladen, bzw. verwendet werden.

Die ART-Beispiele aus den Kapiteln 5 und 6 be�nden sich ebenfalls auf der

CD zu dieser Arbeit. Sie liegen im Verzeichnis code/art/examples. Alternativ

kann man diese auch aus dem WWW laden (http://www.jaetzold.de/art/)

oder als gepacktes Archiv dem Verzeichnis archive auf der CD entnehmen.

Page 143: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

A.2. KLASSENDOKUMENTATION 137

Die ART-Beispiele erfordern nicht mehr Installation als andere Java-Klassen

auch, vorausgesetzt, da� ART bereits korrekt l�auft. Die Klassen m�ussen �uber-

setzt und �uber den Klassenpfad erreichbar sein.

A.2 Klassendokumentation

Einerseits stellt das vorliegende Dokument eine Dokumentation von ART dar,

doch existiert auch eine direkte JavaDoc-Dokumentation der Klassen von ART.

Sie ist auf der CD �uber die Datei java/index.html erreichbar. Zus�atzlich ist

sie auch im Verzeichnis archive archiviert.

Eine druckbare Postscript- und eine PDF-Version der wichtigsten packages

stellt die Datei package-docs.ps, bzw. package-docs.pdf dar. Sie wurde mit

dem LATEX-doclet von 2C Technologies, Inc. generiert (http://www.c2-tech.

com/java/TexDoclet/).

Im Zusammenhang mit neueren Versionen von ART kann die entsprechende

neue Dokumentation nat�urlich auch wieder �uber die Web-Seite http://www.

jaetzold.de/art/ bezogen werden.

Page 144: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

138 ANHANG A. INSTALLATION DES ABSTRACT ROBOT TOOLKIT

Page 145: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

Anhang B

Troubleshooting

Dieses Kapitel stellt die h�au�gsten Fragen bei Problemen in der Verwendung

von ART zusammen und gibt Antworten. Nat�urlich k�onnen nicht alle Fragen

und Probleme vorausgesehen werden. Taucht eine wichtige Frage bzw. eine Ant-

wort hier nicht auf, kann man unter http://www.jaetzold.de/art/ nach einer

Antwort suchen. Dort wird dieser Abschnitt St�uck f�ur St�uck vervollst�andigt.

Die Antworten hier sind nicht ersch�opfend, sondern sollten nur helfen, die

Ursache f�ur ein Problem zu erkennen. Es kann unter Umst�anden erforderlich

sein, um z.B. zu verstehen was ein Klassenpfad ist, weiter Dokumentationen zu

Rate zu ziehen.

F�ur weitere Fragen und Anregungen steht der Autor unter der e-mail

[email protected]

zur Verf�ugung. F�ur jeden Hinweis im Zusammenhang mit dieser Arbeit und

dem Abstract Robot Toolkit an diese Adresse ist er dankbar.

B.1 Exceptions

de.jaetzold.util.NotConnectedException: No driver selected.

Check value of property de.jaetzold.art.RobotInterfaceFactory.

platforms

Kommt diese Exception konnte die RobotInterfaceFactory keine Treiber-

klassen laden, weil die property de.jaetzold.art.RobotInterfaceFactory.

platforms leer ist. Entweder man setzt diese property explizit, z.B. beim Start

der Java-Maschine �uber die Option -D, oder erstellt eine Datei de.jaetzold.

art.properties, die �uber den aktuellen Pfad erreichbar ist (siehe auch Ab-

schnitt 6.5 auf Seite 120). Eine Version dieser Datei mit den aktuellen Treibern

bekommt man �uberall dort, wo man auch ART herbekommt, also z.B. unter

http://www.jaetzold.de/art/.

Wenn diese Exception mit einer anderen Meldung kommt, dann stimmt

etwas mit der Verbindung zwischen einem Software-Sensor, seinem Peer und

dem zugeh�origen RobotInterface nicht. Es kann auch sein, da� der Kontakt

zur Interface-Hardware unterbrochen wurde. Die jeweilige Meldung sollte einen

Anhaltspunkt f�ur die genaue Ursache liefern.

139

Page 146: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

140 ANHANG B. TROUBLESHOOTING

java.lang.NoClassDefFoundError: <irgendein Klassenname>

Das liegt in den allermeisten F�allen an einem falschen Klassenpfad. Den Klas-

senpfad setzt man z.B. mit der Option -classpath beim Aufruf der Java-

Maschine. Alternativ kann man auch die System-Variable CLASSPATH verwen-

den. Der Kassenpfad mu� alle jar-Archive enthalten, sowie alle Verzeichnisse

in denen Java-Klassen in den ihren package-Namen entsprechenden Unterver-

zeichnissen enthalten sind.

Es kann auch sein, da� der Klassenpfad zwar richtig ist, aber die Klasse

noch gar nicht kompiliert wurde. Es soll auch vorkommen, da� man sich bei der

Angabe des Klassennamens vertippt . . .

Zu guter Letzt kann es auch sein, da� das Java Communications API nicht

richtig installiert wurde. In diesem Fall weist der in der Fehlerausgabe angege-

bene Klassenname auf die Ursache hin.

java.lang.NullPointerException

java.lang.ArrayIndexOutOufBoundsException

Dies kann ein Hinweis darauf sein, da� keine Interface-Hardware gefunden wur-

de. Siehe dazu die Erkl�arungen in Abschnitt B.3.

B.2 Geschwindigkeit

Probleme mit der Geschwindigkeit k�onnen verschiedene Ursachen haben. Einige

wurden z.B. in Abschnitt 7.2 auf Seite 125 beschrieben. F�ur viele Geschwindig-

keitsprobleme gibt es momentan keine einfache L�osung. Die besten Erfahrun-

gen wurden aber mit dem jdk1.3 von IBM und der zugeh�origen CommAPI-

Implementierung gemacht, daher wird empfohlen es erst einmal damit zu ver-

suchen. Es sind manchmal durchaus Steigerungen um den Faktor 10 m�oglich.

B.3 Automatische Erkennung

Es kann sein, da� kein Hardware-Interface gefunden wird, bzw. da� das falsche

Hardware-Interface gefunden wird. In diesem Fall kann es helfen, den Strom

der Interface-Hardware abzuschalten. Vor allem das Intelligent Interface kann

in einen Zustand geraten, in dem es nicht mehr antwortet und aus dem es nur

durch einen solchen Reset wieder herauszubekommen ist.

Um nur ein ganz bestimmtes Interface zu bekommen, kann man bei Robot-

InterfaceFactory bestimmte Parameter angeben. Damit kann man verhin-

dern, da� die automatische Erkennung nach bestimmten Hardware-Interfaces

sucht. Die Parameter sind in der Klassendokumentation zu RobotInterfaceFactory

und in Abschnitt 5.2 auf Seite 70 beschrieben.

Page 147: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

Abbildungsverzeichnis

2.1 Schema von Trusty . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.2 Schema von LiSe . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.3 Ariadne aus LEGO und Fischertechnik . . . . . . . . . . . . . . . 10

3.1 Synchronisation in LLWin (Initialisierung) . . . . . . . . . . . . . 15

3.2 Semaphore mit LLWin . . . . . . . . . . . . . . . . . . . . . . . . 16

3.3 Synchronisation in LLWin (Subsumption) . . . . . . . . . . . . . 17

3.4 Positionsmessung in LLWin . . . . . . . . . . . . . . . . . . . . . 18

3.5 RIS/RCX-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.6 Robolab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.1 Regelkreis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.2 Schaltplan von Tutebot . . . . . . . . . . . . . . . . . . . . . . . 37

4.3 Tutebot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

4.4 Das grunds�atzliche Zusammenspiel der Komponenten des ART . 44

4.5 Hierarchie der Peers . . . . . . . . . . . . . . . . . . . . . . . . . 47

4.6 Hierarchie der Frontend-Klassen . . . . . . . . . . . . . . . . . . 52

4.7 Model, View, Controller . . . . . . . . . . . . . . . . . . . . . . . 56

5.1 Einfacher fahrender Roboter aus Lego oder Fischertechnik . . . . 62

5.2 Design-Pattern f�ur die Programmierung mit ART . . . . . . . . . 72

5.3 Testfenster f�ur DriveTrain . . . . . . . . . . . . . . . . . . . . . 73

5.4 Design von NormalizedDriveTrain . . . . . . . . . . . . . . . . 79

5.5 Design von Trusty . . . . . . . . . . . . . . . . . . . . . . . . . . 81

5.6 Design von SubsumptionTrusty . . . . . . . . . . . . . . . . . . . 85

5.7 Impulsrad von Fischertechnik . . . . . . . . . . . . . . . . . . . . 91

5.8 Testfenster f�ur die Komponenten von SubsumptionAriadne . . . 105

6.1 Screenshot der Ober �ache von AWTRobotInterface . . . . . . . . 108

6.2 Die Trusty-Steuerung und das AWTRobotInterface . . . . . . . 122

141

Page 148: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

142 ABBILDUNGSVERZEICHNIS

Page 149: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

Literaturverzeichnis

Baum, D., (2000). Dave Baum's de�nitive guide to LEGO MINDSTORMS.

Apress.

Baum, D., (2001). NQC Programmers Guide, Version 2.3. http://www.

enteract.com/~dbaum/nqc/doc/NQC_Guide.pdf.

Baum, D., M. Gasperi, R. Hempel und L. Villa, (2000). Extreme MIND-

STORMS: An Advanced Guide to LEGO MINDSTORMS. Apress.

Bollella, G., J. Gosling, B. M. Brosgol, P. Dibble, S. Furr, D. Har-

din und M. Turnbull, (2000). The Realtime Speci�cation for Java. Addi-

son Wesley.

Brich, P., G. Hinsken und K.-H. Krause, (2000). Echtzeitprogrammierung

in JAVA : Automatisieren im Millisekundenbereich. Publicis MCD Verlag,

erste Au .

Brooks, R. A., (1985). A Robust Layered Control System for a Mobile Robot.

http://www.ai.mit.edu/people/brooks/papers/AIM-864.pdf.

Campione, M., K. Walrath, A. Huml et al., (1998). The Java Tutorial.

Sun Microsystems. http://java.sun.com/docs/books/tutorial/.

Dijkstra, E. W., (1965). Co-operating Sequential Processes. In F. Genuys

(Hrsg.), Programming Languages. London : Academic Press.

Ferrari, M. und G. Ferrari, (2002). Building Robots with Lego Mindstorms

: The Ultimate Tool for Mindstorms Maniacs! Syngress Publishing, Inc.

Flanagan, D., (1999). Java in a nutshell. O'Reilly, dritte Au .

Gamma, E., R. Helm, R. Johnson und J. Vlissides, (1995). Design Pat-

terns : Elements of Reusable Object-Oriented Software. Addison Wesley.

Garfinkel, S. L. und M. K. Mahoney, (1993). Nextstep Programming :

Step One, Object-Oriented Applications. Springer-Verlag New York.

Gasperi, M., (1998). Mindstorms Sensor Input. http://www.plazaearth.

com/usr/gasperi/lego.htm.

Goldberg, A. und D. Robson, (1983). Smalltalk-80 : The Language and its

Implementation. Addison Wesley, erste Au .

143

Page 150: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

144 LITERATURVERZEICHNIS

Gosling, J., B. Joy, G. Steele und G. Bracha, (2000). The Java Language

Speci�cation. Addison Wesley, zweite Au .

J�atzold, S., (1999). JavaComm, Das Java Communications API. http://

www.vorlesungen.uos.de/informatik/javaapi/javacomm/index.html.

J�atzold, S., (2002). Programming Robots with Java. http://www.jaetzold.

de/talks/2002-01-rit/.

Jones, J. L., A. M. Flynn und B. A. Seiger, (1998). Mobile Robots :

Inspiration to Implementation. A.K. Peters Ltd., zweite Au .

Kernighan, B. W. und D. M. Ritchie, (1990). Programmieren in C. Carl

Hanser Verlag M�unchen Wien, zweite Au .

Knudsen, J., (1999). The UnoÆcial Guide to LEGO MINDSTORMS Robots.

O'Reilly.

Lindholm, T. und F. Yellin, (1999). The Java Virtual Machine Speci�cati-

on. Addison Wesley, zweite Au .

Maes, P. und R. A. Brooks, (1990). Learning to coordinate behaviors. http:

//www.ai.mit.edu/people/brooks/papers/learning.pdf.

M�uller, U., (2000). FishFace Handbuch, Version 3.1. http://www.

ftComputing.de/zip/fishma31.zip.

Nievergelt, J., (1999). Roboter programmieren { ein Kinderspiel : Bewegt

sich auch etwas in der Allgemeinbildung? Informatik Spektrum.

Noga, M. L., (1999). Designing the legOS Multitasking Operating System :

An OS for the Hitachi H8 microcontroller. Dr. Dobb's Journal. http://www.

noga.de/legOS.

Papert, S., (1999). Mindstorms : Children, Computers, and Powerful Ideas.

Basic Books, zweite Au .

Pattis, R. E., (1981). Karel the Robot: A Gentle Introduction to The Art of

Programming with Pascal. Wiley and Sons, erste Au .

Proudfoot, K., (1998). RCX Internals. http://graphics.stanford.edu/~

kekoa/rcx/.

Schreiner, A.-T., (1999). Ober �achen benutzen und programmieren : Java

und die Yellow Box. http://www.vorlesungen.uos.de/informatik/c99/

html/skript.html.

Schreiner, A.-T., (2000a). Programmieren mit Java (1.)2. http://

www.vorlesungen.uos.de/informatik/java00/html/skript/0_Preface%

.htmld/index.html.

Schreiner, A.-T., (2000b). Roboter programmieren. http://www.

vorlesungen.uos.de/informatik/robot00/html/skript.html.

Page 151: UNIVERSIT - Institut für Informatikfsjaetzo/archive/art.pdf · hester Institute of T ec hnology, im Zusammenhang mit dieser Ar-b eit, bin ic h der Univ ersit ... he Mindscript en

LITERATURVERZEICHNIS 145

Sun Microsystems, (1997). JavaBeans 1.01 Speci�cation. http://java.sun.

com/products/javabeans/docs/spec.html.

Sun Microsystems, (1998). Java Communications API. http://java.sun.

com/products/javacomm/.

Sun Microsystems, (2001). Java 2 Platform, Standard Edition, v 1.3.1 API

Speci�cation. http://java.sun.com/j2se/1.3/docs/api/index.html.

Tanenbaum, A. S., (1990). Betriebssysteme - Entwurf und Realisierung. Wien

: Hanser.

The LEGO Group, (1998). Controlling LEGO Programmable Bricks : Spi-

rit.ocx technical reference. http://www.legomindstorms.com/sdk.

von Toschanowitz, K. T., (1999). JavaBeans. http://www.vorlesungen.

uos.de/informatik/javaapi/javabeans/index.html% .

Wooldridge, M., (1999). Intelligent Agents. In G. Weiss (Hrsg.), Multiagent

Systems : A Modern Approach to Distributed Arti�cial Intelligence, S. 27{77.

MIT Press, zweite Au .