Masterarbeit
Transcription
Masterarbeit
Fachhochschule Köln University of Applied Sciences Fakultät 07 Informations-, Medien- und Elektrotechnik Institut für Nachrichtentechnik Studiengang Master of Science Technische Informatik Masterarbeit Spezifikation einer Robotic Task Definition Language (RTDL) Student: Marcus Teske Matrikelnummer: 1104 1133 Referent: Prof. Dr. phil. Gregor Büchel Koreferent: Prof. Dr.-Ing. Georg Hartung Abgabedatum: 17. Januar 2011 Hiermit versichere ich, dass ich die Masterarbeit selbständig angefertigt und keine anderen als die angegebenen und bei Zitaten kenntlich gemachten Quellen und Hilfsmittel benutzt habe. Marcus Teske Inhaltsverzeichnis 1 Einleitung 2 2 Roboter 3 2.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Stationäre Roboter . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.3 Mobile Roboter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.3.1 Mobile ferngesteuerte Roboter . . . . . . . . . . . . . . . . . . 4 2.3.2 Mobile autonome Roboter . . . . . . . . . . . . . . . . . . . . 4 Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.4.1 Sensoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.4.2 Aktoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.4.3 Kommunikationsgeräte . . . . . . . . . . . . . . . . . . . . . . 7 Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.4 2.5 3 Roboterplattformen 9 3.1 CokeRob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Surveyor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3 3.2.1 Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2.2 Surveyor Architektur . . . . . . . . . . . . . . . . . . . . . . . 11 3.2.3 Capabilities des Surveyor Roboters (Services) . . . . . . . . . 13 RobotTI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4 JAUS 4.1 9 15 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 i 4.2 JAUS Volume I: Domain Model . . . . . . . . . . . . . . . . . . . . . 16 4.3 JAUS Volume II: Reference Architecture . . . . . . . . . . . . . . . . 17 4.3.1 Architecture Framework . . . . . . . . . . . . . . . . . . . . . 17 4.3.2 Message Definition . . . . . . . . . . . . . . . . . . . . . . . . 18 4.3.3 Message Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.3.4 Compliance Specification . . . . . . . . . . . . . . . . . . . . . 20 4.4 Surveyor als JAUS-System . . . . . . . . . . . . . . . . . . . . . . . . 22 4.5 Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5 Existierende Taskbeschreibungssprachen 27 5.1 PDDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.2 Task Definition Language for Virtual Agents . . . . . . . . . . . . . . 30 5.2.1 Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 5.2.2 Virtuelle Umgebung . . . . . . . . . . . . . . . . . . . . . . . 30 5.2.3 Die Task Definition Language . . . . . . . . . . . . . . . . . . 31 5.2.4 Aktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 5.2.5 Literals, Variablen und Funktionen . . . . . . . . . . . . . . . 33 5.2.6 Tasks definieren . . . . . . . . . . . . . . . . . . . . . . . . . . 35 5.2.7 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 6 Robotic Task Definition Language 38 6.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 6.2 Tasks und Anforderungen an die RTDL . . . . . . . . . . . . . . . . . 38 6.3 Taskzuweisung an Roboter . . . . . . . . . . . . . . . . . . . . . . . . 39 6.4 Aufbau von RTDL Taskbeschreibungen . . . . . . . . . . . . . . . . . 41 ii 6.5 Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 6.6 Definition der Robotic Task Definition Language . . . . . . . . . . . . 43 6.6.1 Funktionssyntax - Form . . . . . . . . . . . . . . . . . . . . . 43 6.6.2 Funktionssyntax - Aufbau . . . . . . . . . . . . . . . . . . . . 44 6.6.3 Funktionssyntax - Erweiterte Ausführungskonstrukte . . . . . 45 6.6.4 Funktionssyntax - Abfangen des Scheiterns einer Task . . . . . 46 6.7 Robotic Task Definition Language XML-Syntax . . . . . . . . . . . . 47 6.8 Beispiel für eine Task: fetchWater(Glass g, Tap t) . . . . . . . . . . . 52 7 Roboter Simulationsumgebung 55 7.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 7.2 Simulationsumgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 7.3 7.2.1 Weltmodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 7.2.2 Sensoren, Aktoren und Kommunikationsgeräte . . . . . . . . . 56 Implementierung der Simulationsumgebung . . . . . . . . . . . . . . . 57 7.3.1 WorldPosition . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 7.3.2 WorldObject . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7.3.3 Wall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 7.3.4 Waypoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 7.3.5 Robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 7.3.6 WorldLocation . . . . . . . . . . . . . . . . . . . . . . . . . . 61 7.3.7 World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 7.3.8 RobotSim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 7.3.9 MyXmlParser . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 7.3.10 Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 iii 7.4 7.5 Erweiterung der Simulationsumgebung . . . . . . . . . . . . . . . . . 66 7.4.1 DrinkingGlass . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 7.4.2 Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 7.4.3 Tap 7.4.4 Robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 7.4.5 WorldObject . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 7.4.6 RobotSim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 7.4.7 Testen der Erweiterungen . . . . . . . . . . . . . . . . . . . . 70 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 RTDL Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 7.5.1 Klasse RtdlParser . . . . . . . . . . . . . . . . . . . . . . . . . 72 7.5.2 Parsen einer Taskbeschreibung . . . . . . . . . . . . . . . . . . 72 8 Fazit 75 A Modellierungsansatz 76 A.1 Functional Capability (FC) . . . . . . . . . . . . . . . . . . . . . . . 76 A.2 Informational Capability (IC) . . . . . . . . . . . . . . . . . . . . . . 78 A.3 Device Groups (DG) . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 A.4 Übersichtsgrafik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 B Liste ausgewählter JAUS-Komponenten 81 B.1 Command and Control Klasse . . . . . . . . . . . . . . . . . . . . . . 81 B.1.1 System Commander (ID 40) . . . . . . . . . . . . . . . . . . . 81 B.1.2 Subsystem Commander (ID 32) . . . . . . . . . . . . . . . . . 81 B.2 Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 B.2.1 Communicator (ID 35) . . . . . . . . . . . . . . . . . . . . . . 81 iv B.3 Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 B.3.1 Global Pose Sensor (ID 38) . . . . . . . . . . . . . . . . . . . 82 B.3.2 Local Pose Sensor (ID 41) . . . . . . . . . . . . . . . . . . . . 82 B.3.3 Velocity State Sensor (ID 42) . . . . . . . . . . . . . . . . . . 82 B.3.4 Primitive Driver (ID 33) . . . . . . . . . . . . . . . . . . . . . 83 B.3.5 Reflexive Driver (ID 43) . . . . . . . . . . . . . . . . . . . . . 83 B.3.6 Global Vector Driver (ID 34) . . . . . . . . . . . . . . . . . . 83 B.3.7 Local Vector Driver (ID 44) . . . . . . . . . . . . . . . . . . . 83 B.3.8 Global Waypoint Driver (ID 45) . . . . . . . . . . . . . . . . . 84 B.3.9 Local Waypoint Driver (ID 46) . . . . . . . . . . . . . . . . . 85 B.3.10 Global Path Segment Driver (ID 47) . . . . . . . . . . . . . . 85 B.3.11 Local Path Segment Driver (ID 38) . . . . . . . . . . . . . . . 85 B.4 Environment Sensor Components . . . . . . . . . . . . . . . . . . . . 85 B.4.1 Visual Sensor (ID 37) . . . . . . . . . . . . . . . . . . . . . . . 85 B.4.2 Range Sensor (ID 50) . . . . . . . . . . . . . . . . . . . . . . . 86 B.4.3 World Model Vector Knowledge Store (ID 61) . . . . . . . . . 86 B.5 Planning Components . . . . . . . . . . . . . . . . . . . . . . . . . . 87 B.5.1 Mission Planner (keine ID) . . . . . . . . . . . . . . . . . . . . 87 B.5.2 Mission Spooler (ID 36) . . . . . . . . . . . . . . . . . . . . . 87 C Liste ausgewählter JAUS-Nachrichten 88 C.1 Platform Subgroup Command Class (Code 0400-05FF) . . . . . . . . 88 C.2 Platform Subgroup Query Class (Code 2400-25FF) . . . . . . . . . . 88 C.3 Platform Subgroup Inform Class (Code 4400-45FF) . . . . . . . . . . 89 v D Quelltexte 90 D.1 DrinkingGlass.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 D.2 Main.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 D.3 MyXmlparser.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 D.4 Robot.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 D.5 RobotSim.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 D.6 RtdlParser.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 D.7 Source.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 D.8 Tap.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 D.9 Wall.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 D.10 Waypoint.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 D.11 World.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 D.12 WorldLocation.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 D.13 WorldObject.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 D.14 WorldPosition.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 D.15 fetchWater.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 D.16 rtdl.xsl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 D.17 rtdl.dtd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 D.18 example.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 vi Abbildungsverzeichnis 1 CokeRob - Quelle: [Cok10] . . . . . . . . . . . . . . . . . . . . . . . . 2 Surveyor - Quelle: [Erd09] . . . . . . . . . . . . . . . . . . . . . . . . 11 3 Surveyor Gesamtarchitektur . . . . . . . . . . . . . . . . . . . . . . . 12 4 JAUS Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5 JAUS Topologie - Quelle: [JAU07a] . . . . . . . . . . . . . . . . . . . 17 6 Einteilung von JAUS-Klassen nach Command Code - Quelle: [JAU07b] 19 7 Surveyor als JAUS-System . . . . . . . . . . . . . . . . . . . . . . . . 25 8 PDDL als Mindmap . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 9 RobotSim Weltmodell . . . . . . . . . . . . . . . . . . . . . . . . . . 56 10 RTDL Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 vii 9 Abstract Roboter finden in der heutigen Zeit bereits in vielen Bereichen ihre Einsatzgebiete. Zu diesen Bereichen gehören die Industrie, wo Roboter hauptsächlich für filigrane, zu monotone oder gefährliche Arbeiten Anwendung finden. Ein weiterer wichtiger Bereich ist die militärische Aufklärung und das Aufspüren von Personen in schwer zugänglichen Gebieten, wie nach einer Umweltkatastrophe. All diese Roboter haben gemeinsam, dass sie bestimmte Aufgaben ausführen, für welche sie entwickelt wurden. Das Ziel dieser Arbeit ist die Definition einer allgemeinen Aufgaben-Beschreibungssprache, die nicht an einen einzelnen Roboter gebunden ist, sondern für alle möglichen Arten von Robotern einsetzbar ist. Dieses Ziel soll mit Hilfe der Robotic Task Definition Language erreicht werden. Die Robotic Task Definition Language (RTDL) ist eine Sprache, die an der Fachhochschule Köln im Rahmen des Instituts-übergreifenden Projektes “Verteilte Mobile Applikationen (VMA)” entwickelt wird. Die Aufgabe der RTDL besteht darin, eine allgemein gültige Aufgabenbeschreibungssprache für unterschiedlichste Roboter zu definieren. Mit einer solchen Aufgabenbeschreibungssprache ist es möglich, die Steuerungssoftware verschiedener Roboter in einer einheitlichen Sprache zu beschreiben und in einem weiteren Schritt auch umzusetzen. 1 Kapitel 1: Einleitung 1 Einleitung Die Spezifikation einer Robotic Task Definition Language (RTDL) schafft eine Abstraktionsebene in der Steuerungssoftware von Robotern. Innerhalb dieser Ebene werden Aufgaben (Tasks) in einer abstrakten Form als Hierarchie von primitiven Roboteraktionen und untergeordneten Tasks beschrieben. Die Motivation für die Spezifikation einer RTDL liegt in dem Wunsch nach der Fähigkeit, Tasks unabhängig von einem bestimmten Roboter zu definierten. Erweitert man die Steuerungssoftware von verschiedenen Robotern um die Fähigkeit, eine Taskdefinition die in der RTDL formuliert worden ist, zu interpretieren, so schafft man eine Wiederverwendbarkeit von Taskdefinitionen, die es ermöglichen, definierte Tasks von einem konkreten Roboter auf andere Roboter zu übertragen. Im Rahmen dieser Arbeit wird eine Sprache für die Beschreibung von Robotertasks entwickelt. Hierzu werden zunächst existierende Sprachen zur Taskbeschreibung analysiert. Aus den Ergebnissen dieser Analyse wird eine neue Sprache erzeugt. Zusätzlich wird eine einfache Simulationsumgebung für Roboter entwickelt, die unter anderem als Testumgebung für die RTDL dient. Diese Arbeit beginnt mit einigen Grundlagenkapiteln in denen das Umfeld dieserArbeit eingeführt wird. In Kapitel 2 dieser Arbeit werden zunächst Roboter von einem allgemeinen Standpunkt aus betrachtet. Das darauf folgende Kapitel 3 liefert eine Übersicht, über bereits existierende Roboter der Fakultät für Informations-, Medien- und Elektrotechnik der Fachhochschule Köln, wo diese Arbeit entstanden ist. In Kapitel 4 wird die Joint Architecture for Unmanned Systems (JAUS) eingeführt. Hierbei handelt es sich um einen Standard für die Beschreibung von Roboterarchitekturen. Nachdem die Grundlagen für diese Arbeit in den ersten Kapiteln gelegt wurden, wird ein Fokus auf Taskssprachen gelegt. In Kapitel 5 werden bereits existierende Sprachen zur Taskdefinition betrachtet. Diese Sprachen dienen als Grundlagen für Kapitel 6, wo die RTDL beschrieben wird. In Kapitel 7 wird eine Simulationsumgebung für die beispielhafte Implementierung und Testmöglichkeit der RTDL beschrieben. Zum Abschluss dieser Arbeit wird in Kapitel 8 ein Fazit gezogen. 2 Kapitel 2: Roboter 2 Roboter 2.1 Einleitung Der Begriff Roboter stammt von dem tschechischen Schriftsteller Karl Čapek, der diesen Begriff für sein 1921 erschienenes Bühnenstück “R.U.R. Rossum’s universal robots” vom tschechischen Wort für Zwangsarbeit “robota” ableitete. Da Roboter in teils sehr unterschiedlichen Bereichen eingesetzt werden, lassen sie sich auch in mehrere Kategorien einteilen. Zu oberst können sie in stationäre und mobile Roboter unterschieden werden. 2.2 Stationäre Roboter Stationäre Roboter besitzen keine Möglichkeit, sich in ihrer Umgebung zu bewegen. Zu stationären Robotern lassen sich beispielsweise Industrieroboter zählen. Einem Industrieroboter werdenoftmalsWerkstückevorgesetzt,sei es manuell oderautomatisiert durch ein Förderband. Der Industrieroboter nutzt dann einen oder mehrere mechanische Arme, an denen bestimmte Werkzeuge wie beispielsweise Schweißgeräte oder Greifer befestigt sind, um das vor ihm liegende Werkstück zu bearbeiten. Die wichtigsten Vorzüge eines stationären Roboters sind: • Roboter ermüden nicht und liefern stets eine gleich bleibend hohe Qualität. • Roboter können sehr präzise arbeiten, oftmals präziser als Menschen. • Roboter können Tätigkeiten ausführen, die für Menschen zu gefährlich sind. 2.3 Mobile Roboter Mobile Roboter besitzen die Fähigkeit, sich in ihrer Umgebung zu bewegen. Dieser Umstand stellt einen mobilen Roboter jedoch vor weitere Herausforderungen: So muss ein mobiler Roboter sich in seiner Umgebung orientieren können. Dies setzt voraus dass er seine Umgebung über Sensoren erfassen und intern abbilden kann. Des weiteren muss ein mobiler Roboter bei der Bewegung durch seine Umgebung auf Hindernisse reagieren, das heißt diese erfassen, erkennen und ausweichen können. 3 Kapitel 2: Roboter Bei mobilen Robotern ist eine weitere Unterteilung nach ferngesteuerten und autonomen Systemen sinnvoll. 2.3.1 Mobile ferngesteuerte Roboter Ein mobiler ferngesteuerter Roboter besitzt die Fähigkeit, sich in seiner Umgebung zu bewegen und, je nach Art der zusätzlich installierten Werkzeuge, diese auch manipulieren zu können. Wie der Name jedoch bereits vermuten lässt, wird ein solcher Roboter dabei von einer entfernten Instanz über einen Kommunikationskanal ferngesteuert. Alle Entscheidungen werden von der entfernten Instanz getroffen, wobei es sich in den häufigsten Fällen um einen Menschen mit einer Fernsteuerung handelt. Diese Entscheidungen werden in Form von Anweisungen über den Kommunikationskanal an den Roboter übertragen, der diese Anweisungen dann als Aktionen umsetzt. Bei ferngesteuerten Robotern benötigt die entfernte Instanz wichtige Informationen über die Umgebung, in welcher der ferngesteuerte Roboter eingesetzt wird. Es ist häufig so, dass die entfernte InstanzVideodaten von am Roboter angebrachten Kameras verwendet, um die aktuelle Situation des ferngesteuerten Roboters erfassen und Entscheidungen über weitere Aktionen treffen zu können.Alternativ kann sich die entfernte Instanz an einer Position befinden, von der aus sie die relevanten Teile der Umgebung des Roboters überblicken kann. Ein Beispiel für einen mobilen ferngesteuerten Roboter findet man bei Firmen, die Abwasserrohre sanieren. Hierbei wird ein kleiner fahrender Roboter mit einer Kamera in ein Kanalrohr abgelassen. Der Mitarbeiter, der den Roboter steuert, kann mit Hilfe der Kamera an dem Roboter schadhafte Stellen in einem Abwasserrohr aufspüren und gegebenenfalls reparieren. 2.3.2 Mobile autonome Roboter Ein mobiler autonomer Roboter, auch mobiles autonomes System genannt, ist ein Roboter, der in der Lage ist, selbstständig in seiner Umgebung zu navigieren und diese zu manipulieren. Er benötigt keine entfernte Instanz, welche ihn direkt fernsteuert. Auch wenn ein autonomer Roboter selbstständig agieren kann, ist es dennoch oftmals sinnvoll einen Kommunikationskanal zu einer entfernten Instanz zu verwenden. Ein solcher Kommunikationskanal wird häufig verwendet um Informationen 4 Kapitel 2: Roboter über bestimmte Situationen zu versenden. Des weiteren kann man auf diesem Wege eine Art Failsafe bereitstellen, über welchen der Roboter in bestimmten kritischen Situationen deaktiviert oder zwangsweise ferngesteuert werden kann. Ein interessantes Einsatzgebiet für mobile autonome Roboter ist der kooperative Einsatz mehrerer Roboter zur Erfüllung einer gemeinsamen Mission. Ein Beispiel für kooperierende mobile autonome Systeme ist der RoboCup Wettbewerb [Rob11], bei dem mehrere Roboter als Team gegen eine gegnerisches Roboter-Team ein Fußballspiel bestreiten. Das ehrgeizige Ziel dieses Wettbewerbs ist es, bis 2050 die Roboter soweit zu entwickeln, dass diese in der Lage sind, den dann amtierenden Weltmeister nach den gültigen Fußballregeln zu besiegen. Innerhalb dieser Arbeit wird der Fokus auf mobile autonome Roboter gelegt, da diese als einzige von einer Task-Beschreibungssprache profitieren. 2.4 Hardware Zur Hardware eines Roboters zählen alle Komponenten, die physikalisch vorhanden sind und dem Roboter zur Ausübung seiner Fähigkeiten dienen. Man unterscheidet hierbei zwischen Sensoren, Aktoren und Kommunikationsgeräten. 2.4.1 Sensoren Sensoren ermöglichen es einem Roboter, die Umwelt, in der er sich befindet, zu erfassen. Die Sensoren erzeugen entweder permanent oder auf Anfrage Sensordaten, die auf dem Roboter weiterverarbeitetwerden müssen.Beider Verarbeitungder Sensordatenwerdenrelevante Informationen aus diesen Daten in eine symbolische Form übersetzt, die einem internen Datenformat des Robotersentsprechen. DerRoboter nutzt diese Informationen dann, um bestimmte Gegebenheiten seiner Umgebung darstellen zu können und dienen der Planung von zukünftigen Aktionen oder als Feedback zu aktuell durchgeführten Aktionen. Reelle Sensoren sind fast immer fehlerbehaftet, was dazu führt, dass Entscheidungen, die auf Basis solcher Daten getroffen werden, ebenfalls fehlerbehaftet oder gar völlig falsch sind. Bei reellen Robotern gehören diese Aspekte zum Umgang mit unsicherem Wissen. Hierzu gehört sowohl die Einschätzung der Abweichung von Sensordaten zum tatsächlichen Ereignis als auch die Wahrscheinlichkeit, dass ein Sensorwert 5 Kapitel 2: Roboter gänzlich verfälscht ist. Aus diesem Grund werden Entscheidungen eines Roboters oftmals nicht allein auf Basis eines einzigen Sensorwertes getroffen. Statt dessen werden mehrere Sensorwerte von unterschiedlichen Sensoren ausgewertet und deren Informationen zusammengefasst. Diesen Vorgang nennt man Merging (nach dem englischen Wort für zusammenfassen: to merge sth.). Auf diese Art lassen sich Fehler, die in bestimmten Situationen bei bestimmten Sensoren auftreten, kompensieren. Üblicherweise verändern Sensoren die Umgebung des Roboters nicht, sondern dienen lediglich der Erfassung von Daten. Im folgenden ist eine Liste von ausgewählten Sensoren und der Art ihrer erfassten Daten dargestellt: • Ein Kompass kann die aktuelle Orientierung des Roboters anhand des magnetischen Nordpols der Erde bestimmen. • Ein Ultraschallsensor kann das Vorhandensein und gegebenenfalls den Abstand eines Objektes in der Nähe des Roboters ermitteln. • Ein Radenkoder kann die über Rollen oder Raupen zurückgelegte Strecke des Roboters über die Anzahl der Radumdrehungen ermitteln. • Ein RFID-Reader kann RFID-Tags in seiner unmittelbaren Umgebung auslesen, auf deren Basis die aktuelle Position des Roboters ermittelt werden kann. • Eine Kamera kann Umgebungsbilder erfassen, auf deren Basis eine Positionsbestimmung und Hinderniserkennung möglich ist. • Ein auf den Boden gerichteter optischer Mousesensor kann die zurückgelegte Strecke eines Roboters ermitteln. • Ein GPS-Empfänger kann durch Triangulation von Signalen mehrerer GPSSatelliten zur Positionsbestimmung genutzt werden. 2.4.2 Aktoren Aktoren sind Hardware-Geräte, die es dem Roboter ermöglichen sich in seiner Umgebung fort zu bewegen oder Objekte in der Umgebung zu manipulieren. Oftmals werden Aktoren unter sensorischer Überwachung betrieben, damit der Roboter eine Rückmeldung über die Manipulation durch die Aktoren erhält. 6 Kapitel 2: Roboter • Fortbewegungsaktoren: Hierunter fallen alle Aktoren, die es dem Roboter ermöglichen seine Position und Ausrichtung zu verändern. In den meisten Fällen handelt es sich hierbei um Räder oder Raupenketten zur Fortbewegung auf dem Boden, Schrauben für die Fortbewegung auf oder unter dem Wasser und Propeller oder Düsen für die Bewegung in der Luft. • Objektmanipulatoren: Unter diesen Begriff fallen alle Aktoren die Objekte in der Umgebung manipulieren können. Diese Aktoren können vielfältiger Natur sein: Beispielsweise gibt es Greifarme, die Objekte greifen, verdrehen, ziehen, drücken und quetschen können. Aber auch Werkzeuge wie Nietenpistolen oder Schweißgeräte sind denkbar. Diese sind oftmals an einen beweglichen Arm gekoppelt. Beim RoboCup dienen beispielsweise die Beine der Roboter, welche primär für die Fortbewegung gedacht sind, zusätzlich als Abschusseinrichtung für den Fußball. 2.4.3 Kommunikationsgeräte Wie bei der Vorstellung der unterschiedlichen Roboterarten bereits angeführt, besitzen Roboter oftmals einen Kommunikationskanal zu einer entfernten Instanz. Auf welche Art und Weise dieser Kanal zustande kommt ist hierbei abhängig von der verwendeten Technologie, die für die Kommunikation eingesetzt wird. Eine solche Technologie ist beispielsweise WLAN. WLAN steht für Wireless Local Area Network und ist in den IEEE Drafts 802.11 standardisiert. Auf WLAN wird dann häufig das IP-Protokoll (Internet Protocol) und das TCP- (Transmission Control Protocol) oder UDP-Protokoll (User Datagram Protokoll) verwendet, um die Daten vom Roboter zur entfernten Instanz und zurück zu übertragen. Es sind jedoch auch andere Technologien, wie zum Beispiel proprietäre (nicht-standardisierte) Funkgeräte, zur Realisierung eines Kommunikationskanal denkbar. 2.5 Software Neben der Hardware spielt auch die Software bei einem Roboter eine entscheidende Rolle. Bei einem Roboter ist die Software ähnlich aufgebaut wie bei einem PC. 1. Auf der untersten Ebene befindet sich die Hardware. 2. Auf der Hardware läuft ein Betriebssystem 7 Kapitel 2: Roboter (a) Der zentrale Teil eines Betriebssystems ist der Betriebssystemkern, auch Kernel genannt. (b) An den Kernel angebunden sind auf der untersten Ebene die Treiber, welche einen Zugriff auf die Hardware ermöglichen. (c) Auf der obersten Ebene des Betriebssystems befindet sich ein API (Application Programming Interface), mit dessen Hilfe Systemtools und Anwendungsprogramme mit dem Betriebssystem interagieren können. 3. Die Systemtools dienen der Verwaltung des Betriebssystems. 4. Anwendungsprogramme bilden dann die eigentlichen Dienste aus, die ein Roboter erbringen soll. Abbildung 3 auf Seite 12 verdeutlicht den Zusammenhang von Hardware und Software nochmals an Hand des Roboters Surveyor. Ein entscheidendes Anwendungsprogramm bei einem Roboter ist die Steuerungssoftware. Bei einem mobilen autonomen System legt sie die Fähigkeiten und das Verhalten des Roboters fest. Die Steuerungssoftware nutzt die Daten der Sensoren um die Aktoren zur steuern. Des weiteren kann sie unter Verwendung der Kommunikationsgeräte mit anderen Robotern und Systemen in der Umgebung kommunizieren. All dies dient dem Roboter als Grundlage um bestimmte Aufgaben selbstständig erfüllen zu können. Oftmals sind die Fähigkeiten eines Roboters, also dessen Funktionalitäten, in Form von Funktionsaufrufen in der Steuerungssoftware implementiert. 8 Kapitel 3: Roboterplattformen 3 3.1 Roboterplattformen CokeRob Der CokeRob [Cok10] gehört zur Kategorie der stationären Roboter. Er besteht aus einer Tisch-großen Fläche, die von einer externen Kamera überwacht wird, einem Steuerungsrechner und einem aus Lego-Steinen aufgebauten mobilen Roboter. Der mobile Roboter kann sich lediglich auf der kleinen Fläche frei und autonom bewegen und da die Fläche ihrerseits nicht mobil ist, ist das Gesamtsystem des CokeRobs eher als stationärer Roboter zu betrachten. Der einzige Sensor des CokeRob ist die Kamera. Die Daten der Kamera werden in dem externen Steuerungsrechner mit Bilderkennungssoftware ausgewertet und per drahtloser Kommunikationsschnittstelle an den mobilen Roboter gesendet. Legt man nun eine Münze auf diese Fläche, erkennt der CokeRob diese und positioniert seinen Greifarm darüber. Dann lässt er den Arm herab und schiebt die Münze an eine definierte Position. Dort wird die Münze von der Kamera erfasst und identifiziert. Dann schiebt der CokeRob die Münze in einen Kassenbereich. Im nächsten Schritt betätigt der CokeRob einen Schalter, der eine Dose Cola freigibt. Abbildung 1: CokeRob - Quelle: [Cok10] 9 Kapitel 3: Roboterplattformen 3.2 Surveyor 3.2.1 Übersicht Der Surveyor ist derzeit die meist genutzte Entwicklungsplattform innerhalb der Fakultät 07 der FH Köln. Es handelt sich dabei um einen autonomen mobilen Roboter, dessen primäres Ziel die Wegfindung in einer Flurwelt ist. Der Aufbau des Surveyors wird im folgenden stichpunktartig beschrieben: • Die zentrale Datenverarbeitungseinheit ist ein Blackfin Board. • Aktoren – Zwei differential angesteuerte Räder vorne und zwei nachlaufende Räder hinten, verbunden durch eine Gummikette. • Sensoren – RFID-Reader für die Erkennung der auf dem Boden verklebten RFIDTags als Positionsmarker. – Kompass für die Bestimmung der Ausrichtung der Plattform. – Ultraschallsensor für die Hinderniserkennung und Kollisionsvermeidung. – Laseremitter gekoppelt mit einer Kamera zur Abstandsmessung. • Kommunikationsschnittstellen – Zwei serielle Schnittstellen, wobei eine davon an einen WLAN-Adapter gekoppelt ist, wodurch eine drahtlose serielle Kommunikation ermöglicht wird. Wie bereits in Kapitel 2.4.1 erwähnt, sind Sensoren oftmals fehlerbehaftet. Beim Surveyor führt das zu den folgenden Problemen: • Der Surveyor kann seine Position nicht immer genau bestimmen, da er lediglich weiß, welches RFID-Tag er als letztes gelesen hat. Es kann also nur vermutet werden dass der Surveyor sich nahe des zuletzt gelesenen Tags befindet. Dieser Fehler ist nicht direkt auf einen Sensorenfehler zurückzuführen sondern ist durch das Design der Positionsbestimmung mit Hilfe von RFID-Tags bedingt. 10 Kapitel 3: Roboterplattformen • Der Kompass liefert eine maximale Genauigkeit von 1/10 Grad, jedoch wird der Messwert durch Stahlträger und andere metallische Körper in seiner Umgebung stark verfälscht. Dies führt dazu dass der Kompass in einigen Regionen die Ausrichtung sehr gut und anderen sehr unzuverlässig ermittelt. • Dem Ultraschallsensor ist derzeit nicht im Einsatz. Deswegen liegen derzeit noch keine Erkenntnisse über mögliche Fehlerquellen vor. Abbildung 2: Surveyor - Quelle: [Erd09] 3.2.2 Surveyor Architektur Die Surveyor Architektur besteht im Groben aus zwei Bestandteilen. Der erste Bestandteil ist der Surveyor Roboter bestehend aus der Hardware, wie sie in Kapitel 3.2.1 beschrieben ist, und der Steuerungssoftware. Als Betriebssystem wird uClinux verwendet, eine Linuxvariante für eingebettete Systeme. Die gesamte Software ist auf einem Flash-Speicher abgelegt. Innerhalb des uClinux existieren Treiber für die Zugriffe auf die Hardwaregeräte. Des weiteren bietet das Betriebssystem eine Eingabeaufforderung, die sogenannte Shell an, mit welcher über eine entfernte TelnetVerbindung Kommandos auf dem Surveyor Roboter ausgeführt werden können. Auf dieser Shell laufen eine Reihe von Programmen, die vordefinierte Aktionen auf dem Roboter ausführen. Diese Programme sind vergleichbar mit vordefinierten Tasks, 11 Kapitel 3: Roboterplattformen die intern aus Funktionsaufrufen bestehen, die ihrerseits Kommandos über die Treiber an die Hardware absetzen. Der Surveyor besitzt unter anderem zwei serielle Schnittstellen, von der eine an einen WLAN-Adapter angeschlossen ist. Die zweite Komponente ist der sogenannte Proxy. Der Proxy ist ein normaler PC der über eine WLAN-Schnittstelle mit dem Surveyor Roboter kommuniziert. Auf dem Proxy befindet sich zum einen die Entwicklungsumgebung für den Surveyor, mit dessen Hilfe ein verändertes uClinux-Image erzeugt und in den Flash-Speicher vom Surveyor geschrieben werden kann. Abbildung 3: Surveyor Gesamtarchitektur Zum anderen besteht der Proxy aus dem sogenannten Benutzer-PC. Der BenutzerPC bietet eine Schnittstelle an, um auf dem Surveyor über den Kommunikationskanal eine Task auszuführen. Eine solche Task ist zum Beispiel das Anfahren eines bestimmten RFID-Tags auf einer Teststrecke. Der Benutzer-PC ist zudem an eine Flurwelt-Datenbank angeschlossen. In dieser Datenbank befinden sich die Positionsinformationen der verklebten RFID-Tags. Über den Kommunikationskanal erhält der Surveyor Zugriff auf diese Datenbank und ist in der Lage auf Basis dieser Daten einen Pfad von einem Start zu einem Endpunkt zu erzeugen und diesem zu folgen. 12 Kapitel 3: Roboterplattformen 3.2.3 Capabilities des Surveyor Roboters (Services) Im folgenden werden die wichtigsten Fähigkeiten (Capabilities, siehe Kapitel 6.5) des Surveyor Roboters aufgelistet, die durch die Kombination von Steuerungssoftware, Sensoren und Aktoren in Form von Funktionsaufrufen bereit gestellt werden. Motorsteuerung (Aktoren zur Fortbewegung) Der Surveyor ist in der Lage sich auf einer ebenen Fläche fahrend fort zu bewegen. Hierzu sind die folgenden Funktionen implementiert: • Geradeausfahrt: motor forward(); • anhalten: motor stop(); • nach rechts drehen (90◦ ): motor turnright(); • nach links drehen (90◦ ): motor turnleft(); • beliebig drehen: motor turn(int direction); RFID-Funktionen (Sensoren zur Positionsbestimmung)) Einen Großteil der Navigation erreicht der Surveyor durch das Auslesen von RFID-Tags, die auf dem Boden der Teststrecke verklebt sein müssen. RFID-Tags (Radio Frequency Identification) sind passive Transponder, die, wenn sie durch die Radiowellen eines RFIDLesegeräts angeregt werden, eine Information aussenden, die dann von dem Lesegerät ausgelesen werden kann. Der Surveyor besitzt ein solches Lesegerät und stellt die folgenden Funktionen zum Umgang mit RFID-Tags zur Verfügung: • Tag auswählen: rfid selecttag(); • bei Tag authentifizieren: rfid authenticate(); • Tag-Block 1 auslesen: rfid readblock1(); • Tag auslesen: rfid gettag(); • Block x in Tag t beschreiben: rfid writeblock(int x, rfidtag t); Kompass-Funktionen (Sensor zur Bestimmung der Ausrichtung) Der zweite wichtige Bestandteil der Navigationsfähigkeit des Surveyors, wird durch einen 13 Kapitel 3: Roboterplattformen Kompass erbracht. Der Kompass erlaubt es dem Surveyor seine Ausrichtung in Bezug auf eine bekannte Umgebung zu ermitteln. Der Surveyor unterstützt die folgenden Funktionen im Umgang mit dem Kompass: • auf eine bestimmte Gradzahl drehen: fahren drehenzu(int gradzahl); • um eine bestimmte Gradzahl drehen: fahren drehenum(int gradzahl); Höhere Funktionen Der Surveyor verknüpft einige seiner Basis-Fähigkeiten und bietet diese gekapselt als eine höhere Funktion an. So bildet eine Kombination aus RFID-, Kompass- und Fahr-Funktionen gekoppelt mit einem Modell der Umgebung in Form einer Datenbank die Grundlage für autonome Fahrten innerhalb der Umgebung. Durch die Ermittlung der aktuellen Position durch ein gelesenes RFID-Tag und der Ausrichtung durch den Kompass, kann mit Hilfe des Umgebungsmodell in der Datenbank ein Vektor zu einem Ziel-Tag ermittelt werden. Dieser Vektor wird dann mit Hilfe der Fahrfunktionen abgefahren. Während dieser Fahrt ist es wahrscheinlich, dass der Surveyor andere RFID-Tags passiert. In dem Fall liest er die Tags aus und prüft, ob sie mit dem berechneten Vektor der autonomen Fahrt übereinstimmen und korrigiert seinen Kurs gegebenenfalls automatisch. Die autonome Fahrt kann durch Aufruf der folgenden Funktion gestartet werden: • autonome Fahrt zu einer Koordinate: fahren drivetoxy(int x, int y); 3.3 RobotTI Man kann den RobotTI als den großen Bruder des Surveyor bezeichnen. Er ist durch seine Dimensionen in der Lage, ein Notebook als lokalen Verarbeitungsrechner an Bord zu transportieren. Hierdurch kann der RobotTI auf ein enormes Datenverarbeitungspotential zurückgreifen, wie sie höher integrierte Roboterplattformen wie der Surveyor nicht besitzen. Ähnlich verhält es sich mit dem Aspekt der Software. Dadurch dass der RobotTI gebräuchliche PC- bzw. -Notebook-Hardware verwendet, können auch unmodifizierte gebräuchliche Betriebssysteme für den lokalen Verarbeitungsrechner verwendet werden. 14 Kapitel 4: JAUS 4 JAUS 4.1 Einführung Die Joint Architecture for Unmanned Systems (JAUS) war ein offener Standard der JAUS Working Group (WG), der eine gemeinsame Architektur für unbemannte Systeme definierte. Die letzte veröffentlichte Version des JAUS Standards datiert auf den 27.06.2007. Danach wurde die JAUS WG in die Society of Automotive Engineers (SAE) eingegliedert und die Arbeit in nicht-öffentlicher Form fortgesetzt. Trotz dieser Entwicklung von JAUS liefern die alten Version dieses Standards sehr interessante Ansätze zum Entwurf und zur Beschreibung von unbemannten System beliebiger Art. Der Begriff “unbemanntes System” oder “unmanned System”, wie er im Original heißt, umfasst im Grunde das gleiche, wie der Begriff des mobilen autonomen Systems, wie er in Kapitel 2.3.2 eingeführt worden ist. JAUS legt dabei jedoch einen großen Fokus auf die Architektur eines solchen unbemannten Systems und weniger auf dessen Einsatzgebiet oder Verhalten. Dieser Fokus ist bei JAUS jedoch gewollt, da sich der Standard auf eine möglichst große Bandbreite von unbemannten Systemen beziehen will und in keiner Weise Voraussetzungen oder Einschränkungen auf die Bereiche Einsatzgebiet und Verhalten auferlegen möchte. Der JAUS-Standard besteht aus mehreren Dokumenten, die sich mit jeweils unterschiedlichen Aspekten des Standards befassen: • JAUS Volume I: Domain Model v3.2 [JAU05] • JAUS Volume II Part 1-3: Reference Architecture v3.3 [JAU07a], [JAU07b] und [JAU07a] • JAUS Compliance Specification v1.1 [JAU06] [Tes10] liefert eine ins Deutsche übersetzte Zusammenfassung des JAUS Standards, doch für eine ausführliche Betrachtung der Details sei auf die direkten Quellen zurückzugreifen. Abbildung 4 zeigt den JAUS-Standard in einer Übersichtsgrafik. Für Details hierzu sei auf die folgenden Unterkapitel verwiesen. 15 Kapitel 4: JAUS Abbildung 4: JAUS Übersicht 4.2 JAUS Volume I: Domain Model Das Domain Model von JAUS [JAU05] vermittelt die generelle Idee, die sich hinter JAUS versteckt: Die Standardisierung einer Architektur für beliebige unbemannte Systeme, die zwar bestimmte Aspekte dringend vorschreibt, aber dennoch die Einsetzbarkeit des Standards in keiner Weise beschränkt. Als erstes werden Anforderungen an die Architektur spezifiziert und mit einigen ausgewählten bereits bestehenden Standards verglichen. Im Verlauf dieses Vergleichs werden die Schwachstellen der anderen Standards aufgedeckt und in JAUS berücksichtigt. Als Ergebnis dieser Spezifikation werden die folgenden Stützpfeiler von JAUS festgehalten: 1. JAUS ist einsetzbar für alle Arten von Robotern und Fahrzeugplattformen. 2. JAUS erzeugt keine Beschränkungen für die Missionen, die ein unbemanntes System ausführen kann. 3. JAUS ist unabhängig von bestimmten Computer Ressourcen. 4. JAUS ist unabhängig von bestimmten eingesetzten Technologien. 5. JAUS erzeugt keine Einschränkungen für den Anwender bzw. Bediener eines unbemannten Systems. 16 Kapitel 4: JAUS Im JAUS Domain Model werden im Bereich des Modellierungsansatzes zusätzlich eine Reihe von Fähigkeiten (Capabilities) definiert, über die ein unbemanntes System verfügen kann. Diese Fähigkeiten sind sehr ausführlich spezifiziert. Eine Übersicht über diese Fähigkeiten findet sich in Anhang A. 4.3 JAUS Volume II: Reference Architecture Die Referenzarchitektur von JAUS besteht aus drei Teilen: • Part 1: Architecture Framework • Part 2: Message Definition • Part 3: Message Set 4.3.1 Architecture Framework Der erste Teil, das Architecture Framework [JAU07a] stellt eine technische Spezifikation dar, nach welcher ein JAUS-konformes System entworfen und entwickelt werden sollte. Hierzu gehört die Einführung einer Topologie, die zwischen verschiedenen JAUS-Elementen besteht. Diese Topologie ist in der folgenden Grafik dargestellt und in den folgenden Unterkapiteln etwas näher beschrieben. Abbildung 5: JAUS Topologie - Quelle: [JAU07a] JAUS-Component Die JAUS-Component oder JAUS-Komponente stellt das kleinste Element bei JAUS dar. Komponenten sind definiert als eine Einheit, die eine Menge an Operationen mit einer logischen Gruppierung innerhalb des gegebenen Kontextes ausführen. Ein wichtiges Merkmal einer JAUS-Komponente ist, dass Informationen zwischen ihnen lediglich über definierte JAUS- Nachrichten ausgetauscht werden dürfen. 17 Kapitel 4: JAUS Die Kommunikation zu einer Komponente, die nicht in JAUS definiert ist, darf über beliebige Nachrichten erfolgen. Jede JAUS-Komponente besitzt eine Komponenten Schnittstelle (component interface), die als die Menge aller gültigen JAUS-Nachrichten dieser Komponente definiert ist. Im Architecture Framework sind bereits viele JAUS-Komponenten für bestimmte Aufgaben vordefiniert. Für eine ausführliche Liste sei auf [JAU07a] verwiesen. Eine Liste von ausgewählten JAUS-Komponenten, die bei der Beschreibung der meisten unbemannten Systeme vorhanden sind, befindet sich im Anhang B. Node Eine Node ist definiert als eine Komposition aus allen Hardwaregeräten und Softwarekomponenten, die für eine oder mehrere wohldefinierte Verarbeitungsfähigkeiten benötigt werden. Es ist möglich, Nodes als Hardware Blackboxen zu betrachten, auf denen die benötigten Komponenten laufen. Subsystem Ein Subsystem in JAUS ist eine unabhängige und unterscheidbare Einheit, die aus einer Menge von Komponenten besteht die auf einer oder mehreren Nodes laufen, um eine oder mehrere spezifizierte Aufgaben zu erfüllen. System Ein System in JAUS ist eine Gruppierung von einem oder mehreren Subsystemen. Ein System wird häufig aus Subsystemen gewählt, bei denen die Kooperation untereinander einen Vorteil erbringt. 4.3.2 Message Definition Der zweite Teil der Referenzarchitektur, die Message Definition [JAU07b] oder Nachrichten Definition, legt das JAUS- spezifische Protokoll für die Übermittlung von JAUS-Nachrichten fest. Die Nachrichten Definition beschreibt den Aufbau der Nachrichtenheader der einzelnen definierten JAUS-Nachrichten und die Festlegungen, die für einzelne Felder im Nachrichtenheader gelten. JAUS-Nachrichten sind einer der wichtigsten Bestandteile von JAUS, denn sie sorgen für einen wohl-definierten Nachrichtenaustausch zwischen JAUS-Komponenten und werden für das Auslösen von Aktionen und Ereignissen verwendet. 18 Kapitel 4: JAUS In JAUS werden Nachrichten in Nachrichtenklassen eingeteilt. Die Verwendung von Nachrichtenklassen dient der Ordnung von Nachrichten. Die Nachrichtenklassen werden durch den Command Code, also dem Typ einer Nachricht, spezifiziert und lauten wie folgt: Message Class Offset Range (0000h to FFFFh) Command 0000h – 1FFFh Query 2000h – 3FFFh Inform 4000h – 5FFFh Event Setup 6000h – 7FFFh (Deprecate v4.0) Event Notification 8000h – 9FFFh (Deprecate v4.0) Node Management A000h – BFFFh Reserved C000h – CFFFh Experimental Message D000h – FFFFh Abbildung 6: Einteilung von JAUS-Klassen nach Command Code - Quelle: [JAU07b] 1. Command Class Messages werden verwendet, um den Systemmodus zu verändern, zur Bestätigungskontrolle, um den Status einer Komponente oder eines Subsystems zu verändern oder um eine Aktion zu starten. 2. Query Class Messages werden verwendet, um Informationen von anderen Komponenten einzuholen. 3. Inform Class Messages sind das Gegenstück zu Query Class Messages. Sie erlauben es Komponenten, Daten wie z.B. Statusberichte, geographische Positionen und weitere Arten von Informationen untereinander auszutauschen. 4. Event Setup Class Messages werden verwendet, um die Parameter für eine Event Notification Nachricht vorzubereiten und um eine andere Komponente zu veranlassen auf ein Triggerevent zu warten. Eine Event Notice Nachricht wird immer dann erzeugt, wenn Parameter in einer Event Setup Nachricht gesetzt werden. Diese Nachrichtenklasse sollte ab JAUS v4.0 wegfallen. 5. Event Notification Class Messages kommunizieren das Auftreten eines Ereignisses wie z.B. Motorüberhitzung, Ölüberdruck usw. Diese Nachrichtenklasse sollte ab JAUS v4.0 wegfallen. 19 Kapitel 4: JAUS 6. Node Management Class Messages werden nur von der Node Management Task verwendet. Diese Nachrichten werden für die Node-spezifische Kommunikation wie das Durchschleifen von Konfigurationsinformationen und die Komponentenregistrierung verwendet. 7. Experimental Class Messages werden als Grundlage für die Experimentierung mit neuen Nachrichten, die noch nicht in der JAUS Reference Architecture definiert sind, verwendet. Die Idee dabei ist, dass experimentelle Nachrichten in einer späteren Version der JAUS Reference Architecture in diese einfließen. Wenn eine Experimental Class Message in die JAUS Reference Architecture einfließt, wird ihr ein Command Code von den anderen Standardklassen zugewiesen. Die Anzahl dieser experimentellen Nachrichten sollen zwecks einer guten Interoperabilität möglichst gering gehalten werden. Weitere Information zur Message Definition von JAUS befinden sich in [Tes10] und [JAU07b]. 4.3.3 Message Set Das Message Set von JAUS [JAU07c] beschreibt alle in JAUS definierten Nachrichten inklusive ihres Inhaltes. Der Fokus liegt dabei auf den Domänen-spezifischen Semantiken des Nachrichtenaustauschs. Da die Menge, der in JAUS definierten Nachrichten bereits sehr groß ist, wird hier auf eine ausführliche Beschreibung aller Nachrichten verzichtet. Im Anhang C befindet sich eine Menge ausgewählter JAUS-Nachrichten. Für eine vollständige Beschreibung aller JAUS-Nachrichten sei auf [JAU07c] verwiesen. 4.3.4 Compliance Specification Über die JAUS Compliance Specification [JAU06] kann mit Hilfe der Domain Model Spezifikation und der Referenzarchitektur bestimmt werden, ob ein System die Voraussetzungen von JAUS in so weit erfüllt, dass das System als JAUS-konform bezeichnet werden kann. Die JAUS Compliance ist definiert als die Verifikation, dass der Nachrichtenverkehr zwischen JAUS-Komponenten der Reference Architecture Spezifikation ent- 20 Kapitel 4: JAUS spricht. JAUS ist eine nachrichtenbasierte Architektur, welche sich für eine Konformitätsprüfung besonders gut eignet. Es gibt drei Konformitäts-Ebenen, in denen Elemente geprüft werden können. Diese Ebenen lauten wie folgt: • Level I: Inter-Subsystem Compliance • Level II: Inter-Nodal Compliance • Level III: Inter-Component Compliance Die Erfüllung der JAUS Compliance auf einer der Ebenen ist unabhängig von der Compliance der anderen Ebenen und liefert diesbezüglich auch keinen Rückschluss auf deren Status. Die JAUS Compliance unterscheidet zudem zwischen der Standards Compliance und der Applications Compliance. Der Unterschied zwischen diesen beiden Arten der Konformität ist, dass bei der Standards Compliance nur die im JAUS Standard definierten Nachrichten betrachtet werden, während bei der Applications Appliance auch benutzerdefinierte Nachrichten (user defined messages) herangezogen werden, die entweder die Anforderungen des JAUS Standards erweitern oder aber mit diesen in Konflikt stehen. Hierbei muss ein Element die folgenden Regeln einhalten: 1. Alle unterstützten eingehenden und ausgehenden Nachrichten des betreffenden Elements sind explizit aufgelistet. 2. Alle unterstützten ausgehenden Nachrichten dieses Elements geben ausdrücklich die Version der Referenzarchitektur an. 3. Alle unterstützten ausgehenden Nachrichten befolgen die JAUS Konventionen, Definitionen, Formate und Regeln für Nachrichten, so wie sie in der Referenzarchitektur definiert sind. 4. Alle festgelegten Toleranzen für Timing und Latenz werden eingehalten. 5. Alle unterstützten Inform-Nachrichten sollen auf die entsprechenden QueryNachrichten antworten. 6. Alle unterstützten Event Notification Nachrichten sollen auf die entsprechenden Event Setup Nachrichten antworten. 7. Eine benutzerdefinierte Nachricht darf keine in JAUS definierte Nachricht umgehen oder duplizieren. 21 Kapitel 4: JAUS 4.4 Surveyor als JAUS-System Da der JAUS Standard gut geeignet ist, um die Architektur eines unbemannten Systems zu beschreiben und es sich bei dem Roboter Surveyor der Fachhochschule Köln um ein unbemanntes System handelt, wurde versucht dieses System mit Elementen aus JAUS zu beschreiben. Ein Ansatz um den Surveyor mit Elementen aus JAUS zu beschreiben, ist dass man der Topologie von JAUS, wie in Kapitel 4.3.1 beschrieben folgt und dann die einzelnen Ebenen der Topologie denjenigen Elementen des Surveyors zuweist, die am besten auf die Definition der einzelnen Ebenen passen. Auf der obersten Ebene hat man dann das System Surveyor, welches sich aus den beiden Subsystemen Surveyor und OCU zusammensetzt, die durch das Subsystem Network verbunden sind. Das Subsystem Network entspricht beim Surveyor dann dem WLAN Netzwerk, das der Roboter und der Proxy zur Kommunikation nutzen. Das Subsystem Surveyor bildet hierbei den Roboter Surveyor selbst ab. Es besteht aus der Node Blackfin, die dem Blackfin Mainboard des Surveyors und der daran angeschlossenen Sensoren und Aktoren entspricht. Da der Surveyor Roboter nur aus dieser einen Node besteht, entfällt auch die Notwendigkeit eines Node Networks. Das Subsystem OCU entspricht dem Proxy des Surveyors. Das Kürzel OCU steht für Operator Control Unit und bezeichnet in JAUS ein Element, dass ein unbemanntes System mit steuert. Steuern bedeutet in diesem Zusammenhang allerdings nicht fernsteuern, sondern eher, dass das unbemannte System Missionen, der JAUS-Begriff für Tasks, zugewiesen bekommt. Das Subsystem OCU besteht aus den beiden Nodes Bedien-PC und Entwickler-PC, die durch ein Node-Network miteinander verbunden sind. Auf der Node-Ebene sind nun drei verschiedene Nodes identifiziert worden: 1. Das Blackfin-Board mit den angeschlossenen Sensoren und Aktoren, 2. der Bedien-PC 3. und der Entwickler-PC. Innerhalb jeder dieser Nodes befinden sich die beiden Pflichtkomponenten Communicator und Node Manager. 22 Kapitel 4: JAUS Die Komponente Communicator bildet den Zugangspunkt zum Subsystem Network. Im Falle des Surveyor Roboters ist dies die Wireless LAN Schnittstelle mit welcher der Roboter mit dem Proxy kommuniziert. Die Communicator der beiden anderen Nodes sind entweder auch Wireless LAN Schnittstellen oder aber kabelgebundene Schnittstellen zu einem Wireless LAN Access Point. Für JAUS sind beide Alternativen gleichwertig, da die konkrete Implementierung des Subsystem Networks in JAUS nicht abgebildet wird. Die andere Komponente ist der Node Manager. Der Node Manager dient den Nodes als Kommunikationsschnittstelle innerhalb eines Subsystems, dem Node Network. Im Falle des Surveyor Subsystems gibt es nur eine Node, weswegen das Node Network nicht verwendet wird. Im Falle der beiden Nodes im OCU Subsystem, ist das NodeNetwork physikalisch das selbe wie das Subsystem Network. JAUS unterscheidet diese beiden Netzwerke jedoch logisch voneinander, weswegen sie hier beide erwähnt werden. Innerhalb der Node Blackfin gibt es nun mehrere Komponenten, die für die Umsetzung der Fähigkeiten des Surveyors zuständig sind: Die Komponente System Commander, die auch auf der Node Bedien-PC vorhanden ist, bildet die Befehlsquelle des Systems. Beim Surveyor wird über eine Benutzerschnittstelle ein Wegpunkt angegeben und das System fährt autonom zu diesen Wegpunkt. Der System Commander ist die Benutzerschnittstelle, über welche dieser Wegpunkt von einem Bediener eingegeben werden kann. Der Local Waypoint Driver nimmt den Wegpunkt (Desired Global Waypoint) und eine Geschwindigkeitsangabe (Desired Global Speed) von System Commander entgegen und berechnet einen Kurs zu diesem Wegpunkt. Hierzu bedient sich der Waypoint Driver der Daten des Global Pose Sensors. Der Global Pose Sensor nutzt den RFID Reader als Sensor für die Bestimmung der aktuellen Position und den Kompass als Sensor für die Bestimmung der momentanen Ausrichtung der Plattform. Diese beiden Informationen bilden zusammen die sogenannte Pose, welche vom Global Pose Sensor an den Local Waypoint Driver geschickt wird. Der Reflexive Driver erhält vom Local Waypoint Driver einen Bewegungsbefehl (Commanded Wrench Effort), welcher die Plattform zum nächsten Wegpunkt führen soll. 23 Kapitel 4: JAUS Der Reflexive Driver nimmt diese Information prüft mit dem Ultraschallsensor, ob sich ein Hindernis in der Fahrtrichtung befindet und passt den Bewegungsbefehl dementsprechend an, um die Sicherheit der Plattform nicht zu gefährden. Dieser abgeänderte Befehl (Modified Wrench Effort) wird dann an den Primitive Driver weitergegeben. Der Primitive Driver bildet die eigentlich Motorsteuerung ab. Er erhält vom Reflexive Driver eine modifiziertes Steuerkommando und führt dieses aus. Der Node Bedien-PC besitzt, wie bereits erwähnt, einen weitere Komponente vom Typ System Commander, über welche ein Benutzer dem Roboter einen Wegpunkt angeben kann. Des weiteren beinhaltet diese Node eine Komponente vom Typ World Model Vector Store, in welcher das System Zugriff auf ein Weltmodell der Testumgebung hat. Das Weltmodell besteht derzeit aus einem Koordinatensystem, dessen Punkte die jeweiligen RFID-Tags repräsentieren. Der Zugriff auf die Informationen auf die Daten in der Flurwelt-Datenbank geschieht dann über Vector Knowledge Store Objects, die über die entsprechenden Query- und Inform-Nachrichten angefragt und verschickt werden. Der Entwickler-PC dient dem Erzeugen eines neuen uClinux Betriebssystemimages für den Surveyor Roboter. Diese Funktion ist hier als Nicht-JAUS-Komponente OS-Flasher abgebildet. Die Komponente überträgt das Image bei Bedarf über das Subsystem Network auf den Roboter. Abbildung 7 fasst den Surveyor als JAUS-Architektur nochmals zusammen. 4.5 Bewertung Der Joint Architecture for Unmanned Systems (JAUS) Standard ist vorrangig für die Beschreibung und den Entwurf der Architektur von unbemannten Systemen oder mobilen autonomen Robotern geeignet. JAUS hat zu diesem Zweck bereits viele vordefinierte Komponenten und Nachrichten für den Informationsaustausch zwischen diesen an Bord. Hierdurch ist es möglich, eine sehr große Auswahl an verschiedenen unbemannten Systemen mit den Möglichkeiten von JAUS in einer Art Baukastensystem zu spezifizieren. Hierbei legt JAUS einen Fokus auf die Kernbereiche der Architektur in dem die Verarbeitung von Sensoren- und Aktorendaten geschieht. Die Randbereiche der Architektur, an denen Sensoren und Aktoren an das System angebunden werden sind absichtlich nicht festgelegt um die Auswahl der Techno24 Kapitel 4: JAUS Abbildung 7: Surveyor als JAUS-System logie der Sensoren und Aktoren nicht einzuschränken. Wenn man die Verwendung von JAUS für den Entwurf der Steuerungssoftware bei verschiedenen unbemannten Systemen stringent durchführt, kann man erreichen, dass auch teils sehr unterschiedliche Systeme mit oftmals auch sehr unterschiedlichen Einsatzgebieten, dennoch eine gemeinsame Plattform, bestehend aus standardisierten Softwarekomponenten, besitzen. Allerdings gibt es auch Punkte die gegen eine Verwendung von JAUS sprechen. Dazu gehört zum einen die Entscheidung, den JAUS Standard nicht weiter in einer offenen Form zu entwickeln, wodurch es schwieriger wird an verbesserte Versionen des Standards zu gelangen. Es könnte sogar passieren, dass die Interessen der SAE dazu führen, dass die Plattformunabhängigkeit von JAUS zugunsten einiger weniger Plattformen aufgegeben wird. Des weiteren ist der JAUS-Standard in seiner letzten frei verfügbaren Version zwar schon recht umfangreich, aber einige wichtige Aspekte, wie die Planung von Missionen wurden bisher noch nicht spezifiziert. Es finden sich zudem einige Festlegungen in der untersuchten JAUS Standard Version, die als veraltet markiert sind und im damals nächsten geplanten Major-Release entfernt werden sollten. Dies zeigt, dass der JAUS Standard auch noch nicht frei von unnötigem Ballast ist. 25 Kapitel 4: JAUS Ein anderer Punkt, den man bei JAUS beachten muss, ist dass die Verwendung von JAUS-Komponenten einen gewissen Overhead mit sich bringt, den man sich auf hoch integrierten Systemen oftmals nicht leisten kann, da hierdurch mehr Ressourcen benötigt werden, als bei einer monolithischen Umsetzung der Steuerungssoftware. Zusammenfassend kann man festhalten, dass es gute Gründe gibt, den JAUS Standard für die Spezifikation von Architekturen bei unbemannten Systemen zu verwenden, vor allem wenn man diese Architekturen einheitlich und erweiterbar halten möchte. 26 Kapitel 5: Existierende Taskbeschreibungssprachen 5 Existierende Taskbeschreibungssprachen 5.1 PDDL Die Planning Domain Description Language, kurz PDDL, ist ein Standard für Planning Domains und Problembeschreibungen. Sie wurde 1998 von Drew McDermott entwickelt und mit Hilfe von Planungswettbewerben (International Planning Competitions) weiter entwickelt [McD11]. Der bekannteste Teil der PDDL ist STRIPS. Die Abkürzung STRIPS steht für Stanford Research Institute Problem Solver. Man bezeichnet hiermit sowohl den Solver, also eine Software zur Lösung eines Problems, als auch dessen formale Eingabesprache. Im folgenden wird die Eingabesprache kurz umrissen: • In STRIPS werden Domänen (engl: domains) definiert. Eine Domäne hat folgende Bestandteile: – Prädikate (engl.: predicates): Ein Prädikat ist eine Funktion mit einem bool’schen Ergebniswert. Der Ergebniswert eines Prädikats ist wahr (true), wenn die abgefragte Bedingung erfüllt ist. – Aktionen (engl.: actions): Aktionen haben Vorbedingungen und Nachbedingungen. Eine Aktion kann ausgeführt werden wenn die Vorbedingungen erfüllt sind und erfüllt die Nachbedingungen nach Ausführung der Aktion. ∗ Vor- und Nachbedingungen bestehen aus einer Reihe von Prädikaten. • Planungsprobleme werden als Instanz einer Domäne beschrieben. Zu jeder Instanz gehören: – ein Initialzustand, – eine Menge deklarierter Objekte, auf welche sich die Prädikate beziehen, – und eine Menge von möglichen Endzuständen, für welche das beschriebene Problem gelöst ist. Im folgenden ist ein sehr einfaches Beispiel für eine STRIPS-Instanz gegeben: In diesem Beispiel wird die Domäne “robotmovement” definiert. Hierzu wird der Text aus dem Beispiel in einer Textdatei “robotmovement.pddl” abgelegt. 27 Kapitel 5: Existierende Taskbeschreibungssprachen 1 ; PDDL / STRIPS Domain B e i s p i e l 2 ; D e f i n i t i o n d e r Domain robotmovement 3 ; Die Domain b e s c h r e i b t d i e M o e g l i c h k e i t e n d e r M a n i p u l a t i o n d e r Objekte . 4 5 ( d e f i n e ( domain robotmovement ) 6 7 ; Deklaration der Praedikate − ( room ? r ) == true , wenn d e r Raum r e x i s t i e r t . 8 ; ( room ? r ) − ( at−room ? s ) == true , wenn s i c h d e r Roboter im 9 ; ( at−room ? s ) 10 ; Raum s a u f h a e l t . 11 12 (: predicates 13 ( room ? r ) ( at−room ? s ) 14 ) 15 16 ; Aktionen / O p e r a t i o n e n d e f i n i e r e n 17 ; B e s c h r e i b u n g : Der Roboter bewegt s i c h von Raum a nach Raum b . 18 ; Vorbedingung : Die Raeume a und b e x i s t i e r e n und d e r Roboter b e f i n d e t 19 ; s i c h i n Raum A. 20 ; E f f e k t : 21 ; ( at−room ? a ) wird f a l s e ( at−room ?b ) wird true 22 23 ( : a c t i o n move 24 : parameters 25 : p r e c o n d i t i o n ( and ( ? a ?b ) 26 ( and ( room ? a ) ( room ?b ) ) 27 ( and ( at−room ? a ) not ( at−room ?b ) ) 28 ) 29 : effect 30 ( and ( at−room ?b ) ( not ( at−room ? a ) ) 31 ) 32 ) 33 ) Listing 1: robotmovement.pddl Im ersten Schritt wird ein Problem namens “roomchange” in der Domäne “robotmovement” definiert. Die Beschreibung des Problems verwendet zur Lösung die Objekte ra und rb stellvertretend für die Räume a und b aus der Domänendefinition. Bei der Initialisierung des Startzustandes befindet sich der Roboter im Raum ra und nicht im Raum rb. Der Zielzustand ist dadurch definiert, dass der Roboter sich im Raum rb und nicht mehr im Raum ra befindet. 28 Kapitel 5: Existierende Taskbeschreibungssprachen Hierdurch ist das Problem innerhalb der Domäne beschrieben. Um das Problem nun zu lösen, kann man die beiden Dateien an einen STRIPS-Solver übergeben, welcher dann versucht das gegebene Problem vom Initialzustand mit Hilfe der definierten Actions der zugeordneten Domänendefinition in den Endzustand zu überführen. Der Solver kann angewiesen werden den gesamten oder nur einen Teil des Lösungsweges auszugeben. Für dieses Beispiel sieht die Lösung des Solvers wie folgt aus: 1 ( 2 ( move r a rb ) 3 ) Listing 2: roomchange solved.txt Die PDDL wird in Abbildung 8 noch einmal kurz zusammengefasst. Abbildung 8: PDDL als Mindmap 29 Kapitel 5: Existierende Taskbeschreibungssprachen 5.2 5.2.1 Task Definition Language for Virtual Agents Übersicht Die Task Definition Language for Virtual Agents basiert auf SimHuman, einer Plattform für die Darstellung und Animation von virtuellen Agenten in Echtzeit. Virtuelle Agenten sind eine Möglichkeit in virtuellen Umgebungen Aktivitäten stattfinden zu lassen, die nicht direkt von einem oder mehreren Benutzern abhängig sind. Bei virtuellen Umgebungen spricht man auch häufig von virtueller Realität (VR = Virtual Reality). Ein virtueller Agent kann als autonome Entität in einer virtuellen Umgebung betrachtet werden, der nicht nur das Aussehen, sondern auch das Verhalten, von einem lebenden Organismus nachahmt. Innerhalb einer virtuellen Umgebung ist ein virtueller Agent in der Lage, bestimmte Aktionen auszuführen. Werden mehrere Aktionen miteinander in einer hierarchischen oder prozedualen Struktur kombiniert, so lassen sich damit Aufgaben, die sogenannten Tasks, definieren. Durch einen geeigneten Aufbau der Tasks kann auf die Verwendung eines rechenintensiven Planers bei der Ausführung der Tasks verzichtet werden. Ein Planer wird dann lediglich auf einer höheren Ebene für den Wechsel zwischen unterschiedlichen Tasks eines virtuellen Agents benötigt. Das Ziel der Task Definition Language ist es, Tasks in einer kontextunabhängigen Hochsprache definieren zu können, wodurch ein hoher Grad an Wiederverwendbarkeit erreicht werden kann. 5.2.2 Virtuelle Umgebung Die virtuelle Umgebung, auch Welt oder World genannt, bildet ein übergeordnetes Objekt in dem die Menge aller Entitäten enthalten sind, die in der entsprechenden Welt existieren. Eine Entität (Entity) ist entweder ein Agent oder ein Objekt, wobei der Unterschied darin liegt, dass ein Agent die Möglichkeit hat, den aktuellen Zustand der Welt zu erfassen und Aktionen (Actions) in ihr auszuführen. Der aktuelle Zustand einer Welt setzt sich zusammen aus der Kombination der Zustände der in ihr enthaltenen Entitäten. Der Zustand einer Entität kann durch Aktionen eines Agenten verändert werden. Neben dem lebendigen Verhalten, das Agenten in einer virtuellen Umgebung zeigen können, kann es auch reaktive Objekte geben. Ein Beispiel hierfür ist ein fahrendes Auto. 30 Kapitel 5: Existierende Taskbeschreibungssprachen In einer virtuellen Umgebung der Task Definition Language for Virtual Agents besitzen alle Entitäten eine eigene Geometrie. Es ist möglich, mehrere Entitäten in einer baumartigen Struktur miteinander zu verknüpfen, wobei eine geometrische Transformation einer Entität dieser Struktur sich auf die Entitäten in den Ebenen darunter auswirken kann. Eine weitere Eigenschaft der virtuellen Umgebung und der Entitäten darin sind Attribute. Es wird hierbei zwischen globalen Attributen und lokalen Attributen unterschieden. Globale Attribute sind der Umgebung als ganzes zugeordnet und stehen allen Entitäten innerhalb dieser Umgebung zur Verfügung. Lokale Attribute hingegen sind innerhalb von Entitäten definiert und stehen nur über den gemeinsamen Aufruf mit dem zugehörigen Entitätsnamen zur Verfügung. Der allgemeine Aufbau eines Attributs lautet: <name, type, value> wobei der Name der eindeutige Name, Type der Datentyp und Value der eigentliche Wert des Attributs ist. Der Aufruf von Variablen wird in Kapitel 5.2.5 näher erläutert. 5.2.3 Die Task Definition Language Die Task Definition Language verbindet einen Entscheidungsprozess auf oberster Ebene mit den Bewegungs- und Interaktions-Möglichkeiten eines virtuellen Agenten in einer virtuellen Umgebung. Sie ermöglicht es, Tasks als Kombinationen von parallel, sequentiell oder bedingt ausgeführten Aktionen zu beschreiben, ohne dabei alle Implementierungsdetails explizit kennen und formulieren zu müssen. Diese kontextunabhängige Art der Beschreibung bringt einen hohen Grad an Wiederverwendbarkeit mit sich. Definiert ist eine Task im Rahmen der Task Definition Language for Virtual Agents als “Eine Kombination von Aktionen eines virtuellen Agenten, die ein bestimmtes Ziel erfüllt”. Jede Task hat hierbei einen eindeutigen Namen und eine definierte Menge an Argumenten. 5.2.4 Aktionen Eine Aktion (Action) ist ein Vorgang, ausgelöst oder durchgeführt durch einen virtuellen Agenten, der eine Änderung des Zustands der virtuellen Umgebung respek31 Kapitel 5: Existierende Taskbeschreibungssprachen tive ihrer Entitäten bewirkt. Jede Aktion benötigt eine bestimmte Dauer für die Durchführung. Die Dauer wird in Zeitrahmen (time frames) gemessen. Eine Aktion hat entweder eine fest definierte Dauer oder sie ist variabel und zielorientiert, das heißt, die Aktion endet wenn ein bestimmter Zustand bei einer oder mehreren Entitäten erreicht worden ist. Primitive Aktionen sind innerhalb eines Zeitrahmens ausführbar. Zu den primitiven Aktionen gehört zum Beispiel das Ändern einer geometrischen Eigenschaft, das Hinzufügen oder Entfernen einer Entität oder das Versenden von Nachrichten. Es liegt in der Verantwortlichkeit der virtuellen Umgebung die Aktionen letztendlich auszuführen und die resultierenden Effekte zu erzeugen. Komplexere Aktionen sind oftmals eine Kombination aus mehreren primitiven Aktionen. Ein wichtiges Feature für die lebhafte Darstellung von Agenten in einer virtuellen Umgebung ist das sogenannte Keyframing. Hierbei handelt es sich um die Ausführung von vordefinierten Animationssequenzen. Ein weiteres wichtiges Feature ist die Locomotion. Die Locomotion bezeichnet die Fähigkeit des Agenten sich in der virtuellen Umgebung zu bewegen. Wichtige Aktionen beinhalten: • zu einer bestimmten Position bewegen, • sich in eine bestimmte Richtung drehen, • in eine bestimmte Richtung gehen • oder einem bestimmten Pfad zu folgen. Positionen und Orientierungen in bestimmte Richtungen sind jeweils als Vektoren gegeben. Die Locomotion Engine verwendet jedoch keine Körperteil-Bewegungen sondern ein Zustandsmodell mit dem beliebige Bewegungsabläufe möglich sind. Um die Interaktion des Agenten mit Objekten zu animieren, kann neben vordefinierten Animationen auch auf die inverse Kinematik zurückgegriffen werden. Hierbei handelt es sich um eine Reihe von Objekten die entlang einer Reihe von Vektoren bewegt werden. Neben dem Aufruf einer einzelnen Aktion, ist es möglich eine vollständige Task mit entsprechenden Argumenten aufzurufen und damit auszuführen. Bei der Task 32 Kapitel 5: Existierende Taskbeschreibungssprachen handelt es sich in dem Fall um eine Kombination aus Aktionen und Subtasks, die zusammen ein bestimmtes Ziel erfüllen sollen. Manche Aktionen haben bei ihrer Ausführung keinen direkten Einfluss auf die Umgebung. Zu diesen Aktionen gehört das Kopieren von Daten zwischen einzelnen Variablen oder das Hinzufügen einer weiteren Annahme über die Umgebung im virtuellen Agenten. 5.2.5 Literals, Variablen und Funktionen Funktionen können mit Argumenten aufgerufen werden. Die Argumente können dabei direkte Werte, Variablen eines festgelegten Datentyps oder wiederum Funktionen sein, wobei der Rückgabewert der Argumentfunktion dem Datentyp des Arguments entsprechen muss. Gültige Datentypen für Argumente sind: • bool • integer • float • string • entity • list of entities • vector • list of vectors • relation Bei Relations handelt es sich um zusammengesetzte Dateitypen bestehend aus einem eindeutigen Namen und einer Reihe von zusammenhängenden Daten von beliebigen Datenformaten, ähnlich einem Array in anderen Programmiersprachen. Ein Beispiel für eine Relation vom Typ Person kann wie folgt aussehen: person(’John’, 28, 1.80, ’single’) 33 Kapitel 5: Existierende Taskbeschreibungssprachen Durch die Möglichkeit Funktionen wiederum Funktionen als Argumente übergeben zu können, ist ein verschachtelter Aufruf von mehreren Funktionen durch den Aufruf einer einzigen Funktion möglich. In einer virtuellen Umgebung gibt es vier verschiedene Variablenmengen: • Attribute des Agenten • Argumente der Task • Interne Variablen einer Task • Attribute der Entität Der Zugriff auf diese Variablen geschieht über folgenden Aufruf: [<entity name>]<variable name> Hierbei muss der ¡entity name¿ nur angegeben werden, wenn es sich um Attribute aus einer anderen als der Entität handelt, aus welcher die Abfrage gestartet wird. Es gibt spezielle Funktionen um die räumliche Abhängigkeit zwischen zwei Entitäten zu bestimmen: • near(e1,e2) • on(e1,e2) • front of(e1,e2) • behind(e1,e2) • left of(e1,e2) • right of(e1,e2) • above(e1,e2) • below(e1,e2) • intersect(e1,e2): Kollisionserkennung 34 Kapitel 5: Existierende Taskbeschreibungssprachen Diese Funktionen bestimmen einen bool’schen Rückgabewert über den Vergleich von Position, Größe und Ausrichtung zweier Entitäten, die als Argumente übergeben werden. Des weiteren gibt es Funktionen, die eine neue Position in einer vorher festgelegten Distanz relativ zu einer gegebenen Position erzeugen können. Diese lauten: • left • right • front • behind • above • below • on Zusätzlich sind die folgenden Logikfunktionen definiert: • and • or • not Die Funktion exists(ent,f) stellt eine weitere Besonderheit dar. Sie liefert den Wert true zurück, wenn in der Welt die Funktion f mit dem Argument ent und deren Argumenten, den Wert true zurückgibt. 5.2.6 Tasks definieren Eine Task besteht aus drei Teilen: 1. Task Definition: TASK name(type1, arg1, type2, arg2, , typen, argn) 35 Kapitel 5: Existierende Taskbeschreibungssprachen 2. Dem String #Variables gefolgt von der Variablendeklaration: type name = value 3. Dem String #Body gefolgt von einem oder mehreren Kommandos. Dieser Block wird abgeschlossen durch den String #end. Mögliche Kommandos sind: • <action>: eine einzelne Aktion • PAR(<block b1>, <block b2>): Gleichzeitige Ausführung von b1 und b2. • DO(<block b>) UNTIL c: Der Block b wird solange ausgeführt bis die Bedingung c erfüllt ist. • IF <bool c> THEN(<block b1>) ELSE (<block b2>): Wenn die Bedingung c wahr ist, führe b1 aus, sonst führe b2 aus. Sollte irgendein Kommando innerhalb einer Task scheitern, so scheitert ebenfalls die gesamte Task. Bei PAR dürfen die beiden Blöcke nicht zur gleichen Zeit auf die selben kritischen Ressourcen zugreifen, da die Aktionen ansonsten scheitern würden. Eine Besonderheit bei DO UNTIL ist, dass die Bedingung nach der Ausführung jedes einzelnen Schritts im Verarbeitungsblock ausgewertet wird und nicht erst wenn der ganze Block verarbeitet worden ist. Hierdurch ist ein Verlassen der DO UNTIL Schleifen quasi jederzeit möglich. 5.2.7 Beispiel Ein Agent in einem Restaurant sucht einen freien Tisch an den er sich setzen kann. 1 TASK s i t o n f r e e t a b l e ( ) 2 #V a r i a b l e s 3 e n t i t y Table ’ ’ 4 e n t i t y Chair ’ ’ 5 e n t i t y Human ’ ’ 6 #Body 7 DO ( 8 t a s k walk around ( ) 9 ) UNTIL e x i s t s ( Table , and ( 10 11 12 13 14 eq ( [ Table ] c l a s s , ’ t a b l e ’ ) , not ( e x i s t s ( Chair , and ( eq ( [ Chair ] c l a s s , ’ c h a i r ’ ) , and ( n e a r ( Chair , Table ) , e x i s t s ( Human , 36 Kapitel 5: Existierende Taskbeschreibungssprachen 15 and ( eq ( [ Human ] c l a s s , ’ human ’ ) , 16 i n t e r s e c t ( Human , Chair ) ) 17 ) 18 ) 19 ) 20 ) 21 22 ) ) 23 ) ; 24 t a s k g o a n d s i t ( Table ) 25 #end Listing 3: sit on free table.task Der Agent läuft den Raum mittels eines bestimmten Pfades ab (walk around()) bis er einen Tisch sieht an dem sich Stühle befinden, auf denen kein Mensch sitzt. Dabei impliziert diese Taskbescheibung, dass sich an jedem Tisch auch Stühle befinden. Hat er einen solchen Tisch gefunden, setzt er sich an diesen Tisch (go and sit(Table)). 37 Kapitel 6: Robotic Task Definition Language 6 6.1 Robotic Task Definition Language Einführung Die Robotic Task Definition Language, kurz RTDL, ist eine Sprache, mit welcher Tasks definiert und beschrieben werden können. Die Tasks, die mit Hilfe der RTDL beschrieben werden können, werden speziell für Roboter definiert, welche diese Taskbeschreibungen dann mit Hilfe eines Interpreters auswerten und ausführen können. In diesem Kapitel werden zunächst der Begriff der Task und die Anforderungen an die RTDL festgelegt. Den Abschluss dieses Kapitels bildet die Definition der RTDL und ihrer Elemente. 6.2 Tasks und Anforderungen an die RTDL Eine Task stellt eine spezifische Anweisung dar, die von einem Roboter ausgeführt werden soll. Da es sich bei einer Task um die Zuweisung einer Aufgabe an einen Roboter handelt, lassen sich bestimmte Parallelen zur Kommandierung einer Aufgabe zwischen Menschen finden. Wenn es in einer zwischenmenschlichen Konstellation zu einer Situation kommt, in welcher ein Mensch einem anderen Menschen eine Anweisung gibt, welche der zweite Mensch ausführen soll, so geschieht dies oftmals über den Weg der natürlichen Sprache. Dies umfasst sowohl die mündliche, als auch die schriftliche Art der Aufgabenzuteilung. Im Kern der Anweisung steht immer ein Verb, das eine Tätigkeit beschreibt. Zudem ist es oftmals notwendig, noch weitere Informationen in die Anweisung zu packen, um diese präzise zu formulieren. Die Anweisung “gehe in die Küche” beschreibt die gewünschte Tätigkeit mit dem Verb “gehen” und ist parametriert mit der Entität “Küche”, die das Ziel der Bewegung ausmacht. Damit eine Roboter eine bestimmte Task ausführen kann, müssen bestimmte Gegebenheiten geschaffen werden. Zum einen muss eine Tätigkeit für einen Roboter in einer geeigneten Art und Weise formuliert sein, damit der Roboter die notwendigen Informationen zur Durchführung einer Tätigkeit erhält. Diese Informationen erhält der Roboter durch eine Taskbeschreibung. Eine Anforderung an eine solche Taskbeschreibungssprache ist, dass sie ihr Ein38 Kapitel 6: Robotic Task Definition Language satzgebiet nicht selbst einschränkt. Dies beinhaltet insbesondere, dass eine Taskbeschreibungssprache für Roboter sowohl unabhängig von der konkreten Hardware eines Roboters, als auch unabhängig von der Plattform, also der Softwareumgebung, eines konkreten Roboters sein soll. Einschränkungen bezüglich der Möglichkeit der Durchführung einer Task dürfen sich nur aus den Kombination von Roboter und gestellten Aufgabe ergeben, jedoch nicht aus der Art der Beschreibung der Tätigkeit. Eine weitere Anforderung an die RTDL ist es, dass die Elemente, aus denen eine Taskbeschreibung aufgebaut ist, eine Blockstrukturierung aufweisen. Hierdurch lassen sich sowohl die beschriebene Task selbst, als auch ihre Elemente, also die enthaltenen Aktionen, aus gleichartigen Bausteinen aufbauen, die sogar ineinander verschachtelt sein können. Ein weiterer Vorteil von Blöcken ist, dass sie sich sowohl seriell als auch parallel abarbeiten lassen, wodurch eine potentielle Effizienzsteigerung in der Ausführung einer Task erreicht werden kann. Schließlich sollte die RTDL noch über eine XML-basierte (eXtensible Markup Language) Repräsentation einer Taskbeschreibung verfügen, weil dadurch eine Vielzahl von Verarbeitungsmöglichkeiten mit bekannten und ausgereiften Werkzeugen möglich ist. Zu diesen Werkzeugen gehört die Möglichkeit der Prüfung der Wohlgeformtheit (wellformed XML) und der Validität über eine Document Type Definition (DTD) (valid XML). Außerdem bietet die XML Transformation Stylesheet Language (XSLT) die Möglichkeit, eine Taskbeschreibung im XML-Format in ein beliebiges anderes Format zu transformieren. 6.3 Taskzuweisung an Roboter Bei der Taskzuweisung wird ein Roboter vor einige Herausforderungen gestellt, die ein Mensch eher intuitiv zu lösen weiß. So ist nicht jeder Roboter in der Lage auf gesprochene Kommandos zu reagieren, da er hierfür über eine robuste Spracherkennung verfügen muss. Eine robuste Spracherkennung kann gesprochene Sätze in die Schriftform überführen, man spricht hierbei von Text-to-Speech. In [Hol10] werden die Fähigkeit der robusten Spracherkennung und der Sprachsynthese genannt. Bei der Spracherkennung muss der Roboter gesprochene Sätze erkennen und analysieren können. Darüber hinaus muss der Roboter entscheiden, ob es sich bei einem gesprochenem Satz um eine Anweisung an ihn handelt oder nicht. Ebenso wichtig ist in diesem Zusammenhang eine gute Sprachsynthese, damit der Roboter qualifizierte Rückmeldungen zu einer Anweisung geben kann. Diese 39 Kapitel 6: Robotic Task Definition Language Fähigkeiten sind für einen Roboter vor allem in einer Umgebung, in der er für oder mit Menschen arbeiten soll, sinnvoll. Dies gilt vor allem in Bezug auf die Effizienz, Flexibilität und Akzeptanz seiner kooperativen Arbeit mit Menschen, da die Zuweisung von Tasks an einen Roboter unmittelbar vor Ort und ohne Hilfsmittel vorgenommen werden kann. Aber selbst wenn gesprochene Sätze in ihrer Schriftform vorliegen, sind weitere Hürden für den Roboter zu nehmen. Menschen sprechen in einer natürlichen Sprache. In [MT10] werden einige Schwierigkeiten, welche die Verwendung von natürlicher Sprache bei Maschinen mit sich bringt, erläutert. Zunächst ist die natürliche Sprache voller Mehrdeutigkeiten und selten präzise genug formuliert, um von einer Maschine direkt verarbeitet werden zu können. Zudem sprechen Menschen oftmals Sätze, die in einem bestimmten Kontext vorliegen. Bei der zwischenmenschlichen Kommunikation ist der Kontext der Kommunikationspartner oftmals der selbe. Ist dies nicht der Fall, so entstehen häufig große Missverständnisse in der Kommunikation, wie jeder Mensch sicher schon einmal leidvoll erfahren musste. Für einen Roboter existiert ein solcher Kontext jedoch oftmals nicht. Somit müssen auch Anweisungen in der Schriftform oftmals weiter analysiert und verarbeitet werden, bevor ein Roboter diese als geeignete Anweisung ausführen kann. In seiner Arbeit beschreibt [Bud09] einen Küchenroboter, der Küchenrezepte, die in natürlicher Sprache geschrieben sind, mit Hilfe einer Satzanalyse in Anweisungen zerlegt und in Tätigkeiten umsetzt, welche das Rezept virtuell “nachkochen”. Bei der Domäne eines Küchenroboters ist der Kontext der natürlichsprachlichen Anweisungen von Rezepten jedoch vollständig bekannt, ein Luxus den ein generischer Roboter nicht hat. Bei der Entwicklung der RTDL wurde aus diesem Grund auf die Verwendung der natürlichen Sprache zur Taskbeschreibung und -zuweisung verzichtet und stattdessen eine Funktionssyntax für Aktionen definiert, in welcher Tasks beschreiben werden können. Aus [MT10] wurde die folgende Liste erstellt, welche eine Reihe von Fragestellungen bezüglich der Zuweisung von Tasks an Roboter bildet. • Besitzt ein Roboter das gesamte Wissen, dass für die Erfüllung einer Aufgabe notwendig ist und wie erhält er dieses Wissen? Hierzu gehört: – Bestimmung der involvierten Objekte bei der Ausführung einer Aktion. 40 Kapitel 6: Robotic Task Definition Language – Korrekte Positionierung eines Roboters zu einem bestimmten Objekt. – Spezifische Parameter bei der Manipulation eines Objekts wie zum Beispiel die verwendete Kraft beim Greifen und der sichere Ablauf von Armbewegungen an einem Objekt. – Bestimmung des Zustands von Objekten. – Das Ziehen von Schlüssen aus bestimmten Gegebenheiten in der Umgebung des Roboters oder eines Objekts. • Auf was begründet ein Roboter die symbolischen Repräsentationen in seinem Weltmodell? • Wie soll ungenaues Wissen abgebildet und wie soll damit umgegangen werden. • Was ist eine geeignete Repräsentation von Wissen, die sowohl ausdrucksstark ist, als auch ein schnelles Schließen (Reasoning) ermöglicht? • Wie erhält der Roboter ein Bewusstsein über Aktionen und wie können Auswirkungen von Aktionen vorhergesagt werden? All diese Punkte gilt es beim Einsatz von Robotern zu beachten, während sie für einen Menschen oftmals intuitiv erschlossen und einbezogen werden. Die hier genannten Punkte befassen sich vorwiegend mit der Fragestellung wie eine bestimmte Aktion ausgeführt werden soll und weniger mit der Frage, welche Aktionen eine Task ausmachen. Somit sind diese Punkte eher für die Entwicklung eines Roboters als für die Entwicklung einer Taskbeschreibungssprache von Belang. 6.4 Aufbau von RTDL Taskbeschreibungen Im letzten Unterkapitel wurde auf die Schwierigkeit der Verwendung von natürlicher Sprache für die Taskzuweisung bei Robotern eingegangen. Diese Umstände haben dazu geführt, dass bei der RTDL ein anderer Ansatz für die Beschreibung von Tasks gewählt wurde. Die verwendete Funktionssyntax verwendet bei der Definition einer Task einen Funktionsnamen und eine Menge von Parametern zu genaueren Spezifikation der Task. Der Funktionsname wird hierbei durch die englische Version jenes Verbs gebildet, welches den Kern einer Anweisung bildet. Angehängt an den Funktionsnamen wird 41 Kapitel 6: Robotic Task Definition Language eine in runde Klammern gefasste und durch Kommata getrennte Liste von Parametern. Die einzelnen Parameter bestehen wiederum aus einem Entitätstypen und einem Parameternamen. Das folgende Beispiel zeigt die Anweisung “Gehe in die Küche” in der Funktionssyntax: moveTo(kitchen); Hierbei bezeichnet “moveTo” das Verb für Bewegung und “kitchen” das Ziel der Bewegung. Definiert ist die Funktion “moveTo” allgemein als: moveTo(location loc); Hierbei ist “location” der Entitätstyp des ersten und einzigen Parameters und “loc” die Referenz auf den übergebenen Wert dieses Parameters. Zur Beschreibung einer Task ist neben der Definition der Signatur, also des Aufrufs der Task, auch deren Umsetzung von Bedeutung. Jede Task besteht intern aus einer Abfolge von Aktionen (actions), die von einem Roboter ausgeführt werden müssen, um das Ziel der Task zu erreichen. Anders als bei der PDDL, vgl. Kapitel 5.1, ist das Ziel einer RTDL Task nicht explizit beschrieben, sondern wird durch die Ausführung der Task erreicht. Das bedeutet: Eine Task gilt als erfolgreich ausgeführt, wenn alle Aktionen innerhalb der Taskbeschreibung erfolgreich ausgeführt werden konnten. Eine Aktion, innerhalb einer Taskbeschreibung kann dabei entweder eine primitive Aktion sein, die von einem Roboter unmittelbar umgesetzt werden kann, oder aber eine bereits definierte Task. Aus diesem Grund wird eine Aktion genauso wie eine Task durch eine Signatur mit einem Funktionsnamen und einer Parameterliste beschrieben. Da eine Task auch im Rahmen der Beschreibung einer anderen Task aufgerufen werden kann, lassen sich Taskhierarchien aufbauen, die jedoch auf der untersten Ebene immer auf primitiven Aktionen von Robotern basieren, denn nur diese sind von einem Roboter direkt ausführbar. 6.5 Capabilities Die Capabilities eines Roboters sind die Fähigkeiten, die der Roboter besitzt, seine Umgebung zu erfassen, zu verändern und sich in ihr zu bewegen. Sie werden be42 Kapitel 6: Robotic Task Definition Language stimmt über die Kombination seiner Sensoren, Aktoren und der verwendeten Steuerungssoftware. Im Kontext der RTDL sind die Capabilities eines Roboters gegeben durch die Menge der primitiven Aktionen (actions), die ein Roboter über die Steuerungssoftware als Funktionen anbietet. So ist beispielsweise ein Roboter mit angetriebenen Rädern und ausreichenden Sensoren zur Kollisionserkennung physikalisch in der Lage, sich über bestimmte Terrains zu bewegen. Es wird jedoch eine Schnittstelle benötigt, um diese Fähigkeiten nutzen zu können. Diese Schnittstelle muss durch die Steuerungssoftware angeboten werden, beispielsweise in Form einer API (Application Programming Interface), welche diese Funktionalität als Software-Funktion anbietet. Führt ein Roboter eine RTDL Task aus, die auf einer oder mehreren Aktionen basiert, welche nicht als Capability in der Steuerungssoftware angeboten werden und die auch nicht als definierte RTDL Task vorhanden ist, so scheitert diese Task. Ist diese Task nun Teil einer höherrangigen Taskdefinition so scheitern alle höherrangigen Tasks ebenfalls. 6.6 6.6.1 Definition der Robotic Task Definition Language Funktionssyntax - Form In diesem Unterkapitel wird der Aufbau der RTDL festgelegt. Ein RTDL-Dokument ist eine Textdatei, in welcher Tasks in Form einer Funktionssyntax spezifiziert werden. Innerhalb einer RTDL-Taskbeschreibung dürfen ausschließlich Zeichen aus dem ASCII-Zeichensatz (American Standard Code for Information Interchange) [Wik10] verwendet werden. In einer Programmiersprache sind Kommentare ein weit verbreitetes und probates Mittel, um ein Programm für einen Menschen einfacher lesbar zu gestalten. Die RTDL definiert ebenfalls Kommentare in der gleichen Form wie in der Programmiersprache Java: /* * Ich bin ein Kommentar und ich erstrecke mich über eine * oder mehrere Zeilen. */ 43 Kapitel 6: Robotic Task Definition Language Die RTDL ist flexibel im Umgang mit Leerzeichen, Tabulatoren und Zeilenumbrüchen. RTDL-Elemente müssen durch Abstandshalter voneinander getrennt werden. Der Standard-Abstandshalter ist das Leerzeichen. Es ist jedoch auch möglich anstatt eines einzelnen Leerzeichens beliebig viele Leerzeichen, Tabulatoren oder Zeilenumbrüche oder eine Kombination aus diesen zu erzeugen. 6.6.2 Funktionssyntax - Aufbau Ein RTDL-Dokument beginnt immer mit der folgenden obligatorischen Zeile: rtdl <Versionsnummer> Hiermit wird angezeigt dass es sich um ein RTDL-Dokument in der Version <Versionsnummer> handelt. Da die RTDL hier erstmalig definiert wird, ist hier bislang nur der Wert 1.0 gültig. Somit sieht die erste Zeile wie folgt aus: rtdl 1.0 In einem RTDL-Dokument dürfen Kommentare an beliebigen Stellen verwendet werden, außer in der ersten Zeile vor der RTDL-Versionsdeklaration. Nach der ersten Zeile folgt eine Taskdefinition, die wie folgt beginnt: task <Taskname>(<Argtyp1> <Argname1>, ..., <ArgtypN> <ArgnameN>) { <Body> } Das Schlüsselwort task leitet die Taskdefinition ein und wird gefolgt von einem Tasknamen. An den Tasknamen wird unmittelbar eine in Klammern gefasste und durch Kommata getrennten Liste von Argumenten angehängt, die ihrerseits aus dem Entitätstypen und einem eindeutigen Namen des Arguments bestehen. Der in geschweifte Klammern gefasste Body der Task bildet die Implementierung der Task und wird im folgenden näher beschrieben. Als erstes wird eine optionale Menge von benannten Enititäten, die für die Ausführung der Task benötigt werden, erzeugt. Diese Menge wird definiert durch mehrere Strings mit dem folgenden Aufbau: 44 Kapitel 6: Robotic Task Definition Language entity <Entitätstyp> <Entitätsname>; Das Schlüsselwort entity zeigt an, dass eine benannte Entität definiert werden soll. Der Entitätstyp und der Entitätsname sind selbsterklärend. Abgeschlossen werden diese Definitionen durch ein Semikolon. Eine Entität oder Entity bezeichnet im Sinne der RTDL ein irgendwie geartetes Objekt, mit dem ein Roboter auf eine beliebige Art interagieren kann. Jede Entität ist genauer durch einen Entitätstypen spezifiziert, der angibt um welche Art von Objekt es sich handelt. Oftmals sind mit bestimmten Entitätstypen bestimmte Eigenschaften und Interaktionsmöglichkeiten verknüpft. Wenn ein Roboter einen bestimmten Entitätstypen kennt, so besitzt er häufig eine Menge von möglichen Interaktionen, die er auf diesem Entitätstypen ausführen kann. Im letzten und wichtigsten Abschnitt einer RTDL-Taskbeschreibung wird die eigentliche Task durch eine Menge von Operationen beschrieben. Zu diesen Operationen gehört der Aufruf von primitiven Aktionen und bereits definierten Tasks. Ein Aufruf einer Aktion oder Task mit ihren entsprechenden Argumenten hat folgenden Aufbau: <Taskname>(<Argname1>, ..., <ArgnameN>); Der Aufruf einer Task oder Aktion besteht aus dem Aufruf des Namens der Task oder Aktion gefolgt durch eine Liste von Argumenten, abgeschlossen durch ein Semikolon. 6.6.3 Funktionssyntax - Erweiterte Ausführungskonstrukte Neben der seriellen Ausführung von Tasks oder Aktionen, ermöglicht die RTDL, die Ausführung durch Konstrukte, wie man sie in anderen Programmiersprachen vorfindet. Eine While-Schleife ist ein solches Konstrukt, bei dem eine Liste von Tasks oder Aktionen so lange ausgeführt wird, solange eine boolsche Laufzeitbedingung wahr ist. Ist <Bedingung> nicht erfüllt, so wird die Ausführung nach dem While-Block fortgesetzt. In der RTDL hat eine While-Schleife den folgenden Aufbau: while(<Bedingung>) do 45 Kapitel 6: Robotic Task Definition Language <Liste von Tasks oder Aktionen> done Ein weiteres Konstrukt ist die bedingte Ausführung durch if. Hierbei wird eine Bedingung geprüft. Eine Liste von Tasks oder Aktionen wird nur dann ausgeführt, wenn eine bestimmte boolsche Bedingung erfüllt ist, ansonsten wird der If-Block übersprungen. Innerhalb der RTDL hat ein If-Konstrukt den folgenden Ausbau: if(<Bedingung>) <Liste von Tasks oder Aktionen> endif In bestimmten Situationen ist ein gleichzeitiges Ausführen von mehreren Tasks oder Aktionen notwendig. Diese Möglichkeit wird durch das Par-Konstrukt gegeben, bei dem zwei Blöcke von Anweisungen zeitgleich ausgeführt werden. Der Aufbau des Par-Konstrukts ist wie folgt: par <Liste von Tasks oder Aktionen> to <Liste von Tasks und Aktionen> endpar 6.6.4 Funktionssyntax - Abfangen des Scheiterns einer Task Generell gilt, dass wenn eine Task oder Aktion innerhalb einer Taskdefinition bei deren Ausführung scheitert, so scheitert die gesamte definierte Task. Dieses Verhalten wurde in [SV03] ähnlich definiert. Diese Einschränkung gilt nicht für Bedingungen im Kopf von While- oder If-Blöcken. Jedoch bedeutet dies für die Ausführung einer Task, dass es eine oftmals hohe Wahrscheinlichkeit gibt, dass diese Task während ihrer Ausführung scheitert und damit eine ganze Hierarchie von Tasks und Aktionen scheitert. Um diese Problematik etwas abzuschwächen, gibt es verschiedene Lösungsansätze. Es ist beispielsweise möglich, dass die Ausführung einer Task zu einem bestimmten Zeitpunkt scheitert, kurz darauf jedoch möglicherweise erfolgreich ausgeführt werden könnte. Um sich diesen Umstand nutzbar zu machen, kann man den Aufruf von 46 Kapitel 6: Robotic Task Definition Language bestimmten Tasks eine Schleife packen, die eine bestimmte Anzahl an Versuchen hintereinander versucht, diese Task auszuführen. Ein solches Konstrukt hat den folgenden Aufbau: retry(int retries) <Liste von Tasks oder Aktionen> endtry Darüber hinaus kann man auch die Anzahl der Ausführungsversuche für alle Tasks und Aktionen innerhalb einer Taskdefinition global festlegen. Dies kann man beispielsweise über die folgende Anweisung innerhalb des Bodys einer Taskdefinition festlegen: retrycount(int tries); Innerhalb einer Taskdefinition kann es neben den notwendigen Ausführung auch die Möglichkeit der optionalen Ausführung von Tasks und Aktionen geben. Wenn eine solche optionale Task oder Aktion scheitert, hat dieses keinen Einfluss auf die Ausführung der Task als ganze. Die optionale Ausführung einer Task oder Aktion erreicht man durch das Schlüsselwort optional vor der Ausführung: optional <taskname>(<argument1>, ..., <argumentN>); 6.7 Robotic Task Definition Language XML-Syntax Neben der Funktionssyntax der Robotic Task Definition Language, wie sie in Kapitel 6.6 definiert wurde, wurde eine äquivalente XML-Repräsentation definiert. Der Aufbau einer Taskbeschreibung in der XML-Syntax ist im Grunde der selbe wie bei der Funktionssyntax: Die erste Zeile hat stets den folgenden Aufbau: <?xml version="1.0" encoding="UTF-8"?> Diese Zeile wird gefolgt von der Deklaration des XML-Stylesheets, mit welchem die XML-Syntax in die Funktionssyntax transformiert werden kann. Das Stylesheet ist als Quellcode in Listing 22 auf Seite 144 integriert. 47 Kapitel 6: Robotic Task Definition Language <?xml-stylesheet type="text/xml" href="rtdl.xsl" version="1.0"?> Nach der Deklaration des XML-Stylesheets kann man optional noch die Document Type Definition (DTD) einbinden. Die DTD müsste sich bei diesem Beispiel im selben Verzeichnis wie die Taskbeschreibung befinden und kann eingebunden werden durch die folgende Zeile: <!DOCTYPE rtdl SYSTEM "rtdl.dtd"> Das eigentliche RTDL Dokument ist in das folgende Wurzeltag gefasst: <rtdl version="1.0"> </rtdl> Innerhalb des Wurzeltags und auch innerhalb der weiteren Tags können Kommentare mit dem folgenden Tag eingeleitet werden: <comment>This is a comment.</comment> Die Definition einer Task wird umschlossen von: <task name="exampleTask"> </task> Innerhalb der Taskdefinition werden als erstes die Argumente der Task als Var-Tags mit ihren Entitätstypen aufgelistet: <taskargs> <var type="FirstArg">a1</var> <var type="SecondArg">a2</var> </taskargs> Die globale Anzahl der Ausführungsversuche (Standardwert: 1) jeder Aktion wird durch das folgende optionale Tag überschrieben: <retrycount>1</retrycount> 48 Kapitel 6: Robotic Task Definition Language Als nächstes folgt die Aufzählung der Entitäten, die während der Taskbeschreibung verwendet werden, in Form von Var-Tags: <entities> <var type="Entity">entity1</var> <var type="Entity">entity2</var> <var type="Entity">entity3</var> </entities> Der interne Ablauf der Task wird durch ein Block-Tag eingeleitet: <block> </block> Innerhalb eines Block-Elements können nun die verschiedenen Elemente zur Beschreibung des Ablaufs einer Task in beliebiger Reihenfolge und Anzahl verwendet werden. Zu diesen Elementen gehören: Die Aktion mit ihrem Namen und ihren zugehörigen Parametern. Die Parameter einer Aktion werden in Arg-Tags gefasst. Arg-Tags sind vergleichbar mit Var-Tags, jedoch wird hierbei kein Entitätstyp angegeben. <action> <name>Task1</name> <args> <arg>entity1</arg> <arg>entity2</arg> <arg>entity3</arg> </args> </action> Die bedingte Ausführung eines Blocks durch ein If-Konstrukt: <if> <cond>condition</cond> <block> </block> </if> 49 Kapitel 6: Robotic Task Definition Language Die Ausführung eines Blocks in einer While-Schleife: <while> <cond>condition</cond> <block> </block> </while> Die parallele Ausführung zweier Blöcke block und block2: <par> <block> </block> <block2> </block2> </par> Die Ausführung eines Blocks mit mehreren Wiederholungsversuchen: <retry count="5"> <block> </block> </retry> Die optionale Ausführung einer Aktion, bei der ein Scheitern keine Auswirkung auf den Erfolg der definierten Task hat: <action optional="true"> </action> Durch die Verwendung des Block-Tags ist eine Verschachtelung von beliebiger Tiefe bei der Beschreibung einer Task möglich. Die Struktur einer RTDL Taskbeschreibung ist zusätzlich in Form einer Document Type Definition (DTD) festgehalten. Diese hat den folgenden Aufbau: 1 <!−− RTDL v1 . 0 Document Type D e f i n i t i o n −−> 2 50 Kapitel 6: Robotic Task Definition Language 3 <!ELEMENT r t d l ( comment ∗ , task , comment ∗ )> 4 <!ATTLIST r t d l 5 v e r s i o n CDATA #REQUIRED 6> 7 <!ELEMENT comment (#PCDATA)> 8 <!ELEMENT t a s k ( comment ∗ , 9 taskargs , 10 comment ∗ , 11 retrycount ? , 12 comment ∗ , 13 entities , 14 comment ∗ , 15 b lock , 16 comment∗ 17 )> 18 <!ATTLIST t a s k 19 name CDATA #REQUIRED 20 > 21 <!ELEMENT t a s k a r g s ( var | comment )∗> 22 <!ELEMENT var (#PCDATA)> 23 <!ATTLIST var 24 type CDATA #REQUIRED 25 > 26 <!ELEMENT r e t r y c o u n t (#PCDATA)> 27 <!ELEMENT e n t i t i e s ( var | comment )∗> 28 <!ELEMENT b l o c k ( a c t i o n | par | i f | while | r e t r y | comment )∗> 29 <!ELEMENT a c t i o n ( comment ∗ , name , comment ∗ , a r g s ? , comment ∗ )> 30 <!ATTLIST a c t i o n 31 o p t i o n a l CDATA #IMPLIED 32 > 33 <!ELEMENT name (#PCDATA)> 34 <!ELEMENT a r g s ( a r g | comment )∗> 35 <!ELEMENT a r g (#PCDATA)> 36 <!ELEMENT par ( b lock , b l o c k 2 )> 37 <!ELEMENT i f ( cond , b l o c k )> 38 <!ELEMENT cond (#PCDATA)> 39 <!ELEMENT while ( cond , b l o c k )> 40 <!ELEMENT r e t r y ( b l o c k )> 41 <!ATTLIST r e t r y 42 count CDATA #REQUIRED 43 > Listing 4: rtdl.dtd 51 Kapitel 6: Robotic Task Definition Language Die Einbinden einer DTD in Verbindung mit einem XML-Parser erlaubt die Validierung einer in der XML-Syntax formulierten RTDL Taskbeschreibung. 6.8 Beispiel für eine Task: fetchWater(Glass g, Tap t) Das folgende Beispiel zeigt wie eine Task fetchWater(Glass g, Tap t) in der Funktionssyntax aufgebaut sein könnte. Bei dem Beispiel soll ein Roboter einem Benutzer ein Glas gefüllt mit Wasser holen, wobei er das Wasser aus einem Wasserhahn besorgt. In einer natürlichsprachlichen Formulierung würde man sagen: “Fetch me a glass of water from the tap!”. Aus dem Verb “fetch” leitet sich der Name der Task ab. Der Zusatz “water” im Tasknamen gibt der Task einen Namen mit mehr Aussagekraft. Die Substantive “glass” und “tap” werden zu den Argumenten der Task. Eine Besonderheit bei dieser Task ist, dass sie zwei Argumente verwendet. Das erste Argument “Glass g” bezeichnet den Gegenstand, mit dem der Roboter das Wasser transportieren soll. Das zweite Argument “Tap t” bezeichnet die Quelle, an welcher der Roboter das Wasser erhält. Der Ablauf dieser Task wird im Folgenden beschrieben. Der Roboter befindet sich anfänglich an einem bestimmten Ausgangsort und muss sich als erstes ein Glas besorgen. Dazu fährt er zu dem Glas hin und greift es. Dieses Glas wird dann zu einem Wasserhahn transportiert und mit Wasser gefüllt. Danach fährt der Roboter wieder zu seinem Ausgangsort zurück, wo er das Glas absetzt. Im folgenden wird dieses Beispiel in Form einer RTDL-Taskbeschreibung in der Funktionssyntax beschrieben. Die Umsetzung beschränkt sich hierbei jedoch auf die oberste Ebene der Taskdefinition und lässt die Definition der aufgerufenen Tasks und Aktionen weg. 1 rtdl 1.0 2 3 /∗ In d i e s e r Task s o l l e i n Roboter mit einem Greifarm und d e r M ö g l i c h k e i t 4 ∗ s i c h i n s e i n e r Umgebung zu bewegen e i n Glas Wasser b e s o r g e n und am 5 ∗ Ausgangspunkt a b s t e l l e n . 6 ∗/ 7 t a s k f e t c h W a t e r ( G l a s s g , Tap t ) { 8 /∗ Wegpunkt f ü r d i e A u s g a n g s p o s i t i o n . ∗/ 9 e n t i t y Waypoint s t a r t ; 52 Kapitel 6: Robotic Task Definition Language 10 11 /∗ Merke d i e A u s g a n g s p o s i t i o n ∗/ 12 setCurrentPosition ( start ) ; 13 /∗ L o k a l i s i e r e das Glas und f a h r e zu d e s s e n P o s i t i o n ∗/ 14 move ( g ) ; 15 /∗ G r e i f e das Glas ∗/ 16 grip (g) ; 17 /∗ L o k a l i s i e r e den Wasserhahn und f a h r e zu d e s s e n P o s i t i o n ∗/ 18 move ( t ) ; 19 /∗ S t e l l e das Glas ab ∗/ 20 ungrip ( g ) ; 21 /∗ Benutze den Wasserhahn mit dem Glas , um e s zu f u e l l e n ∗/ 22 f i l l ( Tap1 , G l a s s 1 ) ; 23 /∗ G r e i f e das Glas ∗/ 24 grip (g) ; 25 /∗ Fahre zum Ausgangspunkt z u r u e c k ∗/ 26 move ( s t a r t ) ; 27 /∗ S t e l l e das Glas ab ∗/ 28 ungrip ( g ) ; 29 } Listing 5: fetchWater.rtdl Um diese Task ausführen zu können, muss ein Roboter die folgenden Tasks oder Aktionen ausführen können: • setCurrentPosition(Waypoint w); Der Roboter merkt sich die aktuelle Position in Form eines Wegpunktes w. • move(entity e); Der Roboter lokalisiert die Position einer Entität e und bewegt sich zu dieser hin. Wenn e nicht gefunden oder nicht erreicht werden kann, scheitert diese Task. • grip(entity e); Der Roboter greift die greifbare Entität e. Wenn e nicht gegriffen werden kann, scheitert diese Task. • ungrip(entity e); Der Roboter setzt die Entität e, die er in einem seiner Greifarme hält, an der aktuellen Position ab. Wenn e nicht abgesetzt werden kann, scheitert diese Task. 53 Kapitel 6: Robotic Task Definition Language • fill(source s, container c); Der Roboter befindet sich an einer WorldPosition, an der sich zusätzlich ein WorldObject abgeleitet von source und ein WorldObject abgeleitet von container befinden. Der Roboter lässt dann beide WorldObjects so interagieren, dass das von container abgeleitete WorldObject mit dem Ausstoß des von source abgeleiteten WorldObjects gefüllt wird. In diesem Beispiel ist t abgeleitet von source und g abgeleitet von container. • wait(int timeframes); Der Robooter wartet so viele vordefinierte Zeitrahmen ab, wie der Task übergeben wurden. Diese Task kann nicht scheitern. • check(entity e, condition c); Der Roboter nutzt seine Sensoren um den Wahrheitswert der Bedingung c einer Entität e zu prüfen. Ist die Bedingung nicht erfüllt, so liefert check ein false zurück. Dieses Beispiel, jedoch in der XML-Syntax definiert, befindet sich in den Quelltexten im Anhang in Kapitel 20. 54 Kapitel 7: Roboter Simulationsumgebung 7 7.1 Roboter Simulationsumgebung Einleitung Die Roboter-Simulationsumgebung bildet den praktischen Teil dieser Masterarbeit. Sie besteht aus einer einfachen Robotersimulation und einem RTDL-Parser. Die Simulationsumgebung hat den Zweck, das Verhalten eines virtuelles Roboters zu verdeutlichen, der eine in der RTDL spezifizierte Task ausführt. Die eigentliche Simulation ist auf Textnachrichten beschränkt, welcher der virtuelle Roboter ausgibt anstatt reale Aktionen auszuführen. Durch den Einsatz einer Simulationsumgebung ist es möglich, sowohl während der Entwicklung, als auch nach Fertigstellung der RTDL-Spezifikation die Auswirkungen von Tasks zu verdeutlichen. 7.2 Simulationsumgebung Im folgenden wird der Aufbau der Simulationsumgebung beschrieben. Sie setzt sich zusammen aus einem Weltmodell und einem Roboter der als die Summe seiner Sensor-, Aktor- und Kommunikationskomponenten gesehen wird. 7.2.1 Weltmodell Das verwendete Weltmodell repräsentiert einen dreidimensionalen Raum, welcher aus diskreten Orten, den sogenannten WorldLocations, besteht. Innerhalb des Weltmodells befinden sich Weltobjekte, die sogenannten WorldObjects. Der virtuelle Roboter basiert ebenfalls auf einem WorldObject. Die grobmaschige Einteilung der Welt in Form eines dreidimensionalen Gitters wurde gewählt, da die Simulationsumgebung lediglich als Hilfsmittel für die Entwicklung der RTDL gedacht ist. Zwar würde eine realistischere Simulationsumgebung gerade bei komplexen Tasks einen größeren Nutzen bieten, sie wäre allerdings auch mit einem erheblich größeren Entwicklungsaufwand verbunden, was letztendlich sogar die Entwicklung der RTDL in den Schatten stellen würde. Im folgenden wird das verwendete Weltmodell anhand von Abbildung 9 erläutert: Das Weltmodell der Simulationsumgebung besteht aus diskreten Punkten, die einen dreidimensionalen Raum aufspannen. Zur besseren Übersicht wird in Abbildung 9 55 Kapitel 7: Roboter Simulationsumgebung Abbildung 9: RobotSim Weltmodell lediglich eine zweidimensionale Fläche zur Erläuterung verwendet. Jeder Punkt in der Abbildung entspricht einer WorldLocation, also einem eindeutigen Ort innerhalb der Welt. Jede WorldLocation besitzt eine eindeutige dreidimensionale Koordinate. An jeder WorldLocation können sich beliebig viele WorldObjects befinden. In der Abbildung sind diese als Kreise dargestellt. Es besteht eine Beziehung mit einer 1:n Kardinalität zwischen den Orten und den Objekten. Das bedeutet, dass ein WorldObject sich lediglich an genau einer WorldLocation befinden kann, jede WorldLocation jedoch 0 bis n WorldObjects beinhalten kann. Ein WorldObject entspricht einer Entität in der simulierten Welt. Jedes WorldObject wird durch einen eindeutigen Namen referenziert und besitzt einen definierten Typen, entsprechend dem Entitätstypen in der RTDL. 7.2.2 Sensoren, Aktoren und Kommunikationsgeräte Im Rahmen der Simulationsumgebung werden Fehler in Sensordaten weder betrachtet noch modelliert. Der Grund hierfür ist, dass die Simulationsumgebung bewusst einfach gehalten werden soll. In der hier verwendeten Simulationsumgebung werden Aktionen der Aktoren als 56 Kapitel 7: Roboter Simulationsumgebung Meldungen dargestellt, die anzeigen, ob die gewünschte Aktion erfolgreich durchgeführt wurde oder nicht. Diese Simulationsumgebung definiert in der aktuellen Version keine Kommunikationsgeräte, da dies für die Entwicklung der RTDL keine Relevanz besitzt. 7.3 Implementierung der Simulationsumgebung Die Roboter-Simulationsumgebung ist in der Programmiersprache Java implementiert. Bei der Entwicklung wurde Wert auf eine einfache Erweiterbarkeit gelegt. In ihrer Basisversion verfügt ein simulierter Roboter über die Möglichkeiten sich in einer Welt zwischen den einzelnen WorldLocations zu bewegen. Ferner wurden Wände implementiert, die einem Roboter das beschreiten bestimmter WorldLocations verbieten. Die Simulationsumgebung verfügt derzeit über keine Benutzerschnittstelle. Wenn ein bestimmter Aufbau der Welt erzeugt werden soll, so müssen die einzelnen WorldObjects von Hand mit Hilfe von definierten Java-Methoden an die entsprechenden WorldLocations gesetzt werden. Dies geschieht im Quelltext der Simulationsumgebung. Hiernach muss das Programm neu kompiliert werden, was jedoch nur wenige Sekunden dauert. Die Entscheidung auf eine Benutzeroberfläche zu verzichten, ist begründet in dem Aufwand diese ständig mit der Simulationsumgebung anzupassen, sofern man diese erweitert. Um nun die Benutzerfreundlichkeit etwas zu erhöhen wurde eine Funktion in das Programm übernommen, die es erlaubt, den Aufbau einer definierten Welt in eine XML-Datei zu sichern, die später auch wieder geladen werden kann. Für die Implementierung der Basisversion der Roboter-Simulationsumgebung wurden folgende Klassen erzeugt: • WorldPosition.java • WorldLocation.java • WorldObject.java • World.java • Wall.java • Robot.java 57 Kapitel 7: Roboter Simulationsumgebung • RobotSim.java • MyXmlParser.java • Main.java Die wichtigsten Implementierungsdetails der einzelnen Klassen werden in den folgenden Unterkapiteln erläutert. 7.3.1 WorldPosition Eine WorldPosition ist eine einfache Klasse, um die Position innerhalb einer Welt durch eine X-, Y- und Z-Koordinate zu bestimmen. Die Koordinatenwerte sind als Datentyp long implementiert, wodurch die Welt lediglich aus diskreten Punkten besteht. Neben den obligatorischen Getter- und Setter-Methoden sind die folgenden Methoden erwähnenswert: • public long getOffsetX(WorldPosition wp) Diese Methode erhält als Argument ein WorldPosition-Objekt und gibt den Abstand der X-Koordinaten der aktuellen zur übergebenen WorldPosition zurück. Wenn die übergebene WorldPosition einen höheren oder den gleichen X-Koordinatenwert besitzt, wie die aktuelle WorldPosition, so ist der Rückgabewert positiv beziehungsweise Null, ansonsten ist er negativ. • public long getOffsetY(WorldPosition wp) analog zu public long getOffsetX(WorldPosition wp) • public long getOffsetZ(WorldPosition wp) analog zu public long getOffsetX(WorldPosition wp) • public boolean equals(WorldPosition wp) Diese Methode gibt true zurück, wenn alle drei Koordinatenwerte der aktuellen WorldPosition mit denen der übergebenen WorldPosition übereinstimmen, ansonsten wird false zurückgegeben. 58 Kapitel 7: Roboter Simulationsumgebung 7.3.2 WorldObject Die Klasse WorldObject bildet die Basisklasse für alle Typen von Weltobjekten, die innerhalb dieser Simulationsumgebung definiert sind. Jedes WorldObject besitzt einen eindeutigen Namen und eine Reihe von Prädikaten. In der Basisversion sind folgende Prädikate vordefiniert: • protected boolean canMove = false Dieses Prädikat legt fest, ob ein WorldObject in der Lage ist sich selbstständig innerhalb der Welt zu bewegen. • protected boolean grippeable = false Dieses Prädikat legt fest, ob ein WorldObject greifbar ist. • protected boolean passable = true Dieses Prädikat legt fest, ob ein WorldObject durch ein sich bewegendes Objekt passierbar ist (true), oder ob es sich um ein Hindernis handelt (false). In der Klasse WorldObject können weitere Prädikate definiert werden, sollte dies für die Implementierung eines neuen WorldObject Typs notwendig sein. Ferner werden relevante Prädikate in Ableitungen von WorldObjects überschrieben. Neben den obligatorischen Getter- und Setter-Methoden gibt es weitere relevante Methoden: • public String getObjectType() Diese Methode liefert den Typ eines abgeleiteten WorldObjects als String zurück. Darüber hinaus können in dieser Klasse Platzhalter-Methoden für jene Methoden definiert werden, die in abgeleiteten WorldObjects implementiert wurden. Ein Beispiel hierfür ist die Methode public boolean move(World w, int x, int y, int z). Durch den Aufruf dieser Methode eines abgeleiteten WorldObject soll sich dieses in der Welt w an die WorldLocation bewegen, die durch die übergebenen X-, Y- und Z-Koordinaten spezifiziert ist. Da der Standardwert für das Prädikat canMove allerdings false ist, muss im abgeleiteten WorldObject sowohl dieses Prädikat auf true 59 Kapitel 7: Roboter Simulationsumgebung gesetzt als auch diese Methode überschreiben werden , so dass eine Bewegung innerhalb der Welt möglich wird. Für alle anderen abgeleiteten WorldObjects wird die Methode der Oberklasse WorldObject aufgerufen, die lediglich eine Fehlermeldung ausgibt, dass sich das aktuelle Objekt nicht innerhalb der Welt bewegen kann. 7.3.3 Wall Die Klasse Wall ist eine einfache Ableitung der Klasse WorldObject und als Unterklasse von WorldObject definiert. Der Konstruktor Wall(String objectName) erzeugt ein Objekt der Klasse Wall, setzt den Objektnamen entsprechend dem Argument und setzt das Prädikat passable auf false, wodurch eine Wall zu einem Hindernis wird. 7.3.4 Waypoint Die Klasse Waypoint ist eine weitere einfache Ableitung der Klasse WorldObject. Der Konstruktor Waypoint(String objectName) erzeugt ein Objekt der Klasse Waypoint und setzt den Objektnamen entsprechend dem Argument. Die Klasse Waypoint repräsentiert einen Wegpunkt in der Welt. Ein Wegpunkt bezeichnet einen benannten Ort. 7.3.5 Robot Im Vergleich zur Klasse Wall ist die Klasse Robot eine ungleich kompliziertere Ableitung der Oberklasse WorldObject. In der Basisversion implementiert die Klasse Robot einen Roboter, der in der Lage ist, sich innerhalb der Welt frei zu bewegen, sofern er nicht auf Hindernisse stößt. Ein Roboter verfügt wie jedes WorldObject über einen eindeutigen Namen. Zusätzlich ist eine Blickrichtung implementiert, die an die einfache Welt aus diskreten Punkten angepasst ist. So kann ein Roboter entweder nach Norden, Süden, Osten, Westen, Oben oder Unten schauen. Die Änderung der Blickrichtung ist jederzeit über den Aufruf entsprechender Methoden möglich. In der Basisversion der Simulationsumgebung ist die wichtigste Fähigkeit des Roboters sich in der Welt zu bewegen. Hierzu wurde die Methode public boolean move(World w, int x, int y, int z) der Oberklasse WorldObjects entsprechend 60 Kapitel 7: Roboter Simulationsumgebung angepasst. Diese Methode verwendet einen sehr einfachen Algorithmus, um von der aktuellen Position zu einer Zielposition zu gelangen. Alle weiteren Methoden in der Basisversion dienen als Hilfsmethoden für die Methode public boolean move(World w, int x, int y, int z). Der Algorithmus bestimmt zunächst die Differenz der X-Koordinaten der aktuellen und der Zielposition. Dann bewegt sich der Roboter so lange entlang der X-Achse bis die Koordinaten übereinstimmen oder er auf ein unpassierbares Hindernis gestoßen ist. Das gleiche wiederholt der Roboter dann entlang der Y- und dann entlang der Z-Achse. In einem Raum ohne Hindernisse erreicht der Roboter stets sein Ziel, sofern das Ziel innerhalb der definierten Welt liegt. Beim Vorhandensein von Hindernissen zeigt der einfache Algorithmus sehr schnell seine Schwächen, da er in vielen Szenarien den Zielpunkt oftmals nicht erreicht, obwohl das über einen Umweg möglich gewesen wäre. Die offene Architektur der Simulationsumgebung erlaubt es jedoch, diesen Algorithmus jederzeit durch einen besseren zu ersetzen. 7.3.6 WorldLocation Eine WorldLocation bezeichnet einen eindeutigen Ort innerhalb der Welt. Die Position einer WorldLocation wird durch ein WorldPosition Objekt festgelegt. Darüber hinaus verfügt eine WorldLocation über eine HashMap in welcher die WorldObjects, die sich an diesem Ort befinden, über ihren eindeutigen Namen referenziert sind. Neben den obligatorischen Getter- und Setter-Methoden sind die folgenden Methoden erwähnenswert: • public void removeWorldObject(String name) Diese Methode entfernt das WorldObject mit dem eindeutigen Namen name. • public boolean isPassable() Diese Methode liefert false zurück, wenn sich an diesem Ort mindestens ein WorldObject befindet, dass nicht passierbar ist, ansonsten gibt sie true zurück. 7.3.7 World ie Klasse World repräsentiert die Welt der Simulationsumgebung. Der Konstruktor World(int x, int y, int z) erzeugt ein Java-Objekt vom Typ World. Die Argu61 Kapitel 7: Roboter Simulationsumgebung mente int x, int y und int z bestimmen hierbei die Ausdehnung der Welt entlang der jeweilige Koordinatenachsen. Jedes Argument muss mindestens den Wert 1 besitzen, da die Welt sonst nicht erzeugt werden kann. Innerhalb einer Welt befinden sich alle WorldLocations in Form eines dreidimensionalen Arrays. Über die Koordinaten der Position ist dann ein direkter Zugriff auf das entsprechende Objekt im dreidimensionalen Array aller WorldObjects möglich. Ferner bietet die Klasse World einen vereinfachten Zugriff auf alle WorldObjects in allen WorldLocations innerhalb der Welt über deren eindeutigen Namen. Dies wird durch die Verwendung einer HashMap, die zu dem eindeutigen Namen eines WorldObjects dessen Position innerhalb der Welt ablegt, erreicht. Im folgenden sind die wichtigsten Methoden der Klasse World aufgeführt: • public WorldObject getWorldObjectByName(String name) Gibt das WorldObject, das durch den übergebenen Namen referenziert wird, zurück. • public String getWorldObjectType(String name) Gibt den Typ des WorldObjects, das durch den übergebenen Namen referenziert wird, zurück. Der Typ bezeichnet hierbei den Klassennamen der von WorldObject abgeleiteten Klasse. • public boolean removeWorldObjectByName(String name) Entfernt das WorldObject, das durch den übergebenen Namen referenziert wird, aus der Welt. • public boolean contains(String name) Prüft, ob ein WorldObject mit dem Namen name in der Welt existiert. • public String[] getWorldObjectNames() Gibt die Namen aller in der Welt befindlichen WorldObjects als String-Array zurück. 7.3.8 RobotSim Die Klasse RobotSim bildet die eigentlich Simulationsumgebung ab. Diese Klasse ist hauptsächlich ein Wrapper um ein Java-Objekt vom Typ World mit Methoden, 62 Kapitel 7: Roboter Simulationsumgebung die den Zugriff auf die Welt vereinfachen. • public boolean createWorldObject(String type, String name, int x, int y, int z) Diese Methode erzeugt ein Objekt der Klasse type und dem Namen name an der Position in der Welt, die durch die Koordinaten x, y und z spezifiziert wird. Der Typ type ist hierbei eine definierte Unterklasse der Klasse WorldObject. • public boolean createRobot(String RobotName, int x, int y, int z) Diese Methode entspricht einem Aufruf der Methode public boolean createWorldObject(String type, String name, int x, int y, int z) mit Type Robot. • public WorldObject getObject(String name) Diese Methode gibt Zugriff auf das WorldObject, dass durch name referenziert wird. • public boolean removeObject(String name) Diese Methode entfernt das WorldObject, das durch name referenziert wird, aus der Welt. • public boolean place(String name, int x, int y, int z) Diese Methode platziert das WorldObject, das durch name referenziert wird, direkt an die Position, die durch x, y und z gegeben ist. • public boolean move(String name, String destination) Diese Methode ruft die Methode public boolean move(World w, int x, int y, int z) des WorldObjects, das durch name referenziert wird, mit den Argumenten x, y und z auf. Die Argumente x, y und z ergeben sich aus den Koordinaten, an denen sich das WorldObject mit dem Namen aus der Variablen destination befindet. • public String toXmlString() Diese Methode erzeugt auf der Konsole die Ausgabe eines aktuellen Abbildes der Welt mit ihren Dimensionen und allen WorldLocations inklusive aller in ihnen enthaltenen WorldObjects im XML-Format. 63 Kapitel 7: Roboter Simulationsumgebung 7.3.9 MyXmlParser Diese Klasse ermöglicht es den Zustand einer Welt, wie er mit der Methode public String toXmlString() erzeugt wurde, aus einer Textdatei zu laden und die Welt entsprechend zu rekonstruieren. Der Konstruktor MyXmlParser(String filename) bekommt hierzu als filename den Pfad zu der Datei übergeben, in welcher der Zustand der Welt als XML-Beschreibung abgelegt worden ist. Das Parsen der Datei wird durch einen angepassten XMLStreamreader erledigt. 7.3.10 Main Die Klasse Main bildet den Eingabeteil der Benutzerschnittstelle der Roboter-Simulationsumgebung ab. In ihr wird ein RobotSim- und ein MyXmlParser-Objekt definiert. In der ausführbaren Methode public static void main(String[] args) kann dann entweder die Simulationsumgebung durch den Aufruf von Methoden der Klasse RobotSim manuell erzeugt und gesichert werden oder alternativ durch Aufruf des MyXmlParsers aus einer bereits bestehenden Umgebungsbeschreibung rekonstruiert werden. Manuelle Erzeugung der Simulationsumgebung Das folgende Beispiel der Methode public static void main(String[] args) erzeugt ein neues RobotSim Objekt mit den Dimensionen x=10, y=10, z=1. Innerhalb dieser Simulation wird ein WorldObject mit eben jenen Dimensionen automatisch erzeugt. Danach wird ein Roboter namens “Robot1” an der Position [0, 0, 0] erzeugt, der sich in einem weiteren Schritt zur Position [5, 5, 0] bewegen soll. Anschließend soll der aktuelle Zustand der Umgebung als XML-Beschreibung auf die Konsole ausgegeben werden. public static void main(String[] args) { // Erzeugung der Simulationsumgebung rs = new RobotSim(10, 10, 1); // Erzeugung eines Roboters rs.createRobot("Robot1", 0, 0, 0); // Bewegung des Roboters zu Position [5, 5, 0] 64 Kapitel 7: Roboter Simulationsumgebung rs.move("Robot1", 5, 5, 0); // Sicherung des aktuellen Zustands der Welt. echo(rs.toXmlString()); } Der gesicherte Zustand der Welt sieht dann wie folgt aus: <world> <sizex>10</sizex> <sizey>10</sizey> <sizez>1</sizez> <objects> <object> <name>Robot1</name> <type>Robot</type> <x>5</x> <y>5</y> <z>0</z> </object> </objects> </world> Rekonstruktion der Simulationsumgebung Das folgende Beispiel der Methode public static void main(String[] args) lädt eine bereits definierte Simulationsumgebung aus der lokalen Datei ‘‘C:\RobotSim.xml’’ auf einem WindowsSystem: public static void main(String[] args) { // Beispiel Import try { MyXmlParser parser = new MyXmlParser("C:\\RobotSim.xml"); rs = parser.parse(rs); } catch (Exception e) { System.err.println("ERROR beim Parsen!"); } 65 Kapitel 7: Roboter Simulationsumgebung // Manipulation der rekonstruierten Umgebung // ... } Hierbei wird ein neuer MyXmlParser mit der Datei C:\RobotSim.xml erzeugt und gestartet. Zu beachten ist, dass alle Blackslashes “\” im Windows-Pfad durch ein weiteres Backslash-Zeichen escapet werden müssen. 7.4 Erweiterung der Simulationsumgebung Die Roboter-Simulationsumgebung wurde im Hinblick auf einfache Erweiterbarkeit entworfen. Um das Beispiel aus Kapitel 6.8 umsetzen zu können, muss die Simulationsumgebung um mehrere Bestandteile erweitert werden. In diesem Kapitel werden die Erweiterungen an Hand dieses Beispiels erläutert. Die Task fetchWater(DrinkingGlass glass, Tap tap) besteht aus den folgenden Aktionen: 1. moveTo(posGlass) 2. grip(glass) 3. moveTo(posTap) 4. ungrip(glass) 5. fill(tap, glass) 6. grip(glass) 7. moveTo(posStart) Hierbei bezeichnet posGlass die Position von einem Glas glass in der Welt, posTap die Position eines Wasserhahns tap und posStart die Startposition des Roboters. Da die Task moveTo(position p) bereits in der Basisversion der Simulationsumgebung implementiert ist, ist hier keine Erweiterung notwendig. Im folgenden werden die hierzu notwendigen Erweiterungen beschrieben. Zunächst werden die neuen Weltobjekt Typen definiert und dann in die Simulationsumgebung integriert. 66 Kapitel 7: Roboter Simulationsumgebung 7.4.1 DrinkingGlass Die Klasse DrinkingGlass repräsentiert ein Wasserglas in der Simulationsumgebung. Der Konstruktor DrinkingGlass(String objectName) setzt beim Instanzieren den Objektnamen und einige Prädikate: • super.isContainer = true; Dieses Prädikat gibt an, ob es sich bei dem WorldObject um einen Container handelt, der etwas beinhalten kann. • super.isGrippeable = true; Dieses Prädikat gibt an, ob das WorldObject greifbar ist. Neben dem Objektnamen und den Prädikaten wird zusätzlich eine neue interne Variable this.contentType = new String() deklariert. Der contentType gibt an, mit welcher Art von Inhalt ein Container-artiges WorldObject gefüllt ist. Die Klasse DrinkingGlass definiert zusätzlich zwei neue Methoden: • public boolean fillContainer(World w, String source) Diese Methode füllt das DrinkingGlass mit dem Erzeugnis einer Quelle source. • public boolean emptyContainer() Diese Methode leert das DrinkingGlass. Diese Klasse wurde direkt von der Oberklasse WorldObject abgeleitet. Die nächsten beiden Kapitel geben ein Beispiel, wie ein Weltobjekt indirekt von der Oberklasse WorldObject abgeleitet definiert werden kann 7.4.2 Source Die Klasse Source repräsentiert eine Quelle, die einen gewissen Ausstoß produziert. Der Konstruktor Source(String objectName, String sourceType) setzt zum einen den Objektnamen der Source und definiert zusätzlich das Prädikat isSource, das angibt, ob es sich bei dem WorldObject um eine Source handelt und die Variable sourceType, welche die Art des Quellenausstoßes bezeichnet. 67 Kapitel 7: Roboter Simulationsumgebung 7.4.3 Tap Die Klasse Tap repräsentiert einen Wasserhahn in der Simulationsumgebung. Der Tap ist abgeleitet von der Oberklasse Source, die ihrerseits von der Oberklasse WorldObject abgeleitet ist. Der Konstruktor public Tap(String objectName) setzt den Objektnamen und den Quellentyp hartkodiert auf water. 7.4.4 Robot Um mit den Objekten der neu definierten Klassen interagieren zu können, muss der Roboter erweitert werden. Im ersten Schritt erhält der Roboter einen Arm, der ein greifbaren WorldObject fassen kann: private WorldObject arm; Des weiteren erhält der Roboter neue Methoden um greifbare WorldObjects greifen und wieder abstellen zu können: • public boolean grip(World w, String name) Diese Methode lässt den Roboter ein Object name greifen, wenn dieses das Prädikat isGrippeable erfüllt und wenn der Roboter sich an der selben Position wie das benannte Objekt befindet. • public boolean ungrip(World w, String name) Mit dieser Methode stellt der Roboter das mit name benannte Objekt an seiner aktuellen Position ab, sofern es sich beim Methodenaufruf in seinem Greifarm befindet. 7.4.5 WorldObject Da in der Definition der Klassen DrinkingGlass, Source und Tap neue Prädikate und Methoden definiert worden sind, müssen diese in die Klasse WorldObject übernommen werden. Die zusätzlichen Prädikate werden einfach zu den bereits existierenden Prädikaten hinzugefügt: 68 Kapitel 7: Roboter Simulationsumgebung /* Die bereits definierten Prädikate */ protected boolean canMove = false; protected boolean isGrippeable = false; protected boolean isPassable = true; /* Die neu hinzugefügen Prädikate */ protected boolean isContainer = false; protected boolean isSource = false; Die zusätzlichen Methoden grip(World w, String name) und ungrip(World w, String name) werden als Dummy-Methoden implementiert, die lediglich eine Fehlermeldung ausgeben. 7.4.6 RobotSim Um nun einen einheitlichen Zugriff auf die Erweiterungen der Roboter-Simulationsumgebung zu erreichen muss die RobotSim Klasse noch angepasst werden. Zunächst muss die Methode public boolean createWorldObject(String type, String name, int x, int y, int z) angepasst werden, so dass auch WorldObjects von Typ DrinkingGlass und Tap instanziert werden können. Danach müssen die folgenden Methoden in der RobotSim Klasse definiert werden: • public boolean grip(String agent, String entity) Diese Methode lässt einen agent, zum Beispiel einen Roboter, ein WorldObject entity greifen, wenn entity greifbar ist und sich agent an der selben Position wie entity befindet. • public boolean ungrip(String agent, String entity) Diese Methode lässt einen agent, zum Beispiel einen Roboter, ein WorldObject entity an seiner aktuellen Position absetzen, sofern sich entity zum Zeitpunkt des Methodenaufrufs in seinem Greifarm befindet. • public boolean fill(String agent, String source, String container) Diese Methode lässt einen agent, zum Beispiel einen Roboter, einen Container container mit dem Ausstoß einer Quelle source füllen. Hierzu müssen sich agent, source und container an der selben Position befinden. 69 Kapitel 7: Roboter Simulationsumgebung 7.4.7 Testen der Erweiterungen Zum Testen der Erweiterungen kann man das Beispiel fetchWater(DrinkingGlass Glass1, Tap Tap1) aus Kapitel 6.8 als Reihe von Anweisungen in die Klasse Main der Roboter-Simulationsumgebung eingeben. Für dieses Beispiel wird eine Welt mit den Dimensionen [10, 10, 1] erzeugt. Danach werden verschiedene WorldObjects gesetzt: • Ein Roboter Robot1 an die Position [0, 0, 0]. • Ein Tap Tap1 an die Position [3, 3, 0]. • Ein DrinkingGlass Glass1 an die Position [6, 6, 0]. Danach lässt man Robot1 zu Glass1 fahren, es greifen und zu Tap1 fahren. An Tap1 angekommen, wird Glass1 abgesetzt und von Robot1 mit dem Ausstoß von Tap1 gefüllt. Danach greift Robot1 das Objekt Glass1 erneut und fährt es zur Startposition [0, 0, 0] wo er Glass1 absetzt. Als Implementierung der Methode public static void main(String[] args) ergibt das den folgenden Quellcode: public static void main(String[] args) { // Erzeugung der Simulationsumgebung rs = new RobotSim(10, 10, 1); // Erzeugen eines Roboters rs.createRobot("Robot1", 0, 0, 0); // Erzeugen eines Waypoints am Startpunkt [0, 0, 0] rs.createWorldObject("Waypoint", "Start", 0, 0, 0); // Erzeugen eines Wasserhahns an Position [3, 3, 0] rs.createWorldObject("Tap", "Tap1", 3, 3, 0); // Positionieren eines Wasserglases an Position [6, 6, 0] rs.createWorldObject("DrinkingGlass", "Glass1", 6, 6, 0); 70 Kapitel 7: Roboter Simulationsumgebung // Bewegung des Roboters zu Position [6, 6, 0] rs.move("Robot1", "Glass1"); // Greifen von Glass1 rs.grip("Robot1", "Glass1"); // Zu Tap1 bewegen rs.move("Robot1", "Tap1"); // Glass1 abstellen rs.ungrip("Robot1", "Glass1"); // Glass1 mit Ausstoss von Tap1 fuellen rs.fill("Robot1", "Tap1", "Glass1"); // Greifen von Glass1 rs.grip("Robot1", "Glass1"); // Zur Ausgangsposition fahren rs.move("Robot1", "Start"); // Glass1 absetzen rs.ungrip("Robot1", "Glass1"); } Nach dem Kompilieren und Ausführen der Simulation wurden folgende Ausgaben auf der Konsole ausgegeben: Robot1 has moved to [6,6,0]. Robot1 has gripped Glass1. Robot1 has moved to [3,3,0]. Robot1 has ungripped Glass1. Robot1 fills Glass1 at Tap1. Glass1 is now filled with water. Robot1 has gripped Glass1. Robot1 has moved to [0,0,0]. Robot1 has ungripped Glass1. 71 Kapitel 7: Roboter Simulationsumgebung 7.5 RTDL Parser Nachdem die Roboter Simulationsumgebung durch die in Kapitel 7.4 beschriebenen Änderungen erweitert worden ist, ist sie in der Lage das Beispiel fetchWater(Glass g, Tap t) aus Kapitel 6.8 als eine Serie von Kommandos der Simulationsumgebung zu beschreiben und auszuführen, wie in Kapitel 7.4.7 gezeigt. Der letzte noch verbleibende notwendige Schritt zu einer RTDL-fähigen Roboter Simulationsumgebung ist die Verschmelzung von RTDL und Simulationsumgebung. Dies soll durch die Integration eines RTDL Parsers in die Roboter Simulationsumgebung geschehen. 7.5.1 Klasse RtdlParser Um den RTDL Parser zu implementieren, wurde eine neue Klasse RtdlParser erzeugt. Der Konstruktor RtdlParser(String filename) erzeugt ein neues RtdlParser Objekt und erhält als Argument den Pfad zu einer RTDL Taskbeschreibung im XML-Format übergeben. Intern besteht die Klasse RtdlParser aus einer angepassten Instanz eines XMLStreamReaders, ähnlich der Klasse MyXmlParser aus Kapitel 7.3.9. Die wichtigste Methode des RtdlParsers ist die Methode public RobotSim parse(RobotSim rs, String robot). Diese Methode parst die im Konstruktor übergebene Taskbeschreibung und führt die Aktionen als jener Roboter, der durch das Argument robot übergeben wird, in der übergebenen Instanz der Klasse RobotSim aus. Im Anschluss an diesen Vorgang wird die modifizierte RobotSim Instanz zurückgegeben. 7.5.2 Parsen einer Taskbeschreibung Der in den Klassen RtdlParser und MyXMLParser verwendete XMLStreamReader agiert ereignisgesteuert. Der Parser durchläuft ein XML-Dokument und erzeugt bei jedem Auftreten eines XML-Elements ein Event. Die für den RTDL Parser wichtigsten Events sind der Beginn START ELEMENT und das Ende END ELEMENT jener XML-Elemente. Die Validität einer Taskbeschreibung muss derzeit noch durch den Benutzer festgestellt werden, da aus Zeitmangel auf die Implementierung eines XML Validierers in 72 Kapitel 7: Roboter Simulationsumgebung den RTDL Parser verzichtet wurde. Der Parser prüft zunächst, ob das Attribut version des rtdl Elements den Wert 1.0 hat, wenn nicht wird die Ausführung der Simulationsumgebung beendet. Als zweites wird beim Betreten eines task Elements dessen Attribute name ausgewertet und zwischengespeichert. Im dritten Schritt werden Aktionen, gegeben durch action Elemente, ausgewertet. Zunächst wird der Name einer Aktion aus dem name Element zwischengespeichert. Danach werden die Argumente der Aktion, gegeben durch arg Elemente, ausgewertet und in einem String Array zwischengespeichert. Beim Verlassen eines action Elements wird auf Basis des action Namens ein entsprechendes Kommando in der übergebenen RobotSim Klasse ausgeführt. Die Argumente der action werden als Argumente des RobotSim Kommandos mit übergeben. Aus Zeitmangel gegen Ende der Arbeit wurde kein vollständiger RTDL Parser geschrieben, so dass es einige Einschränkungen bei der Verwendung zu beachten gibt: 1. Der RTDL kann keine Elemente verarbeiten, die bisher nicht in diesem Kapitel genannt wurden. Hierzu zählen: (a) If-Konstrukte (b) While-Schleifen (c) Par-Konstrukte (d) Retrycount Elemente (e) Retry-Blöcke 2. Der RTDL Parser kann keine Entitätsdefinitionen auswerten, weswegen alle Entitäten, die bei der Ausführung von Aktionen beteiligt sind, vor der Ausführung einer Taskbeschreibung in der RobotSim Klasse angelegt sein müssen. 3. Der RTDL Parser kann keine Taskargumente der Taskdefinition auswerten. Das bedeutet, dass Tasksbeschreibungen derzeit keine lokalen Entitätsnamen verwenden dürfen, sondern nur solche, die bereits gültig in der RobotSim Klasse definiert wurden, vgl. Punkt 2. 4. Der RTDL Parser führt keine Validierung von Taskbeschreibungen gegen die RTDL Document Type Definition durch. 73 Kapitel 7: Roboter Simulationsumgebung 5. Der RTDL Parser bricht die Ausführung einer Task nicht ab, wenn eine Aktion innerhalb der Task scheitert, unabhängig von optional und retry Statements. 6. Der RTDL Parser kann derzeit maximal fünf Argumente je Aktion bei der Ausführung einer Task zwischenspeichern. 74 Kapitel 8: Fazit 8 Fazit Im Rahmen dieser Masterarbeit wurde mit der Spezifikation der Robotic Task Definition Language (RTDL) der Grundstein für eine neue Sprache der Taskbeschreibung für mobile autonome Systeme geschaffen. Die RTDL in ihrer jetzigen Version kann nur als Prototyp angesehen werden, da bisher nur eine kleine Implementierung in Form der Roboter-Simulationsumgebung existiert. Dennoch hat die RTDL das Potential durch Weiterentwicklung zu einem einfachen und dennoch effizienten Weg der plattformunabhängigen Beschreibung von Roboter-Tasks zu werden. Das gleiche gilt für die Roboter-Simulationsumgebung, welche durch ihren einfachen aber strukturierten Aufbau die Simulation von komplexeren Szenarien der RoboterSimulation in Zukunft ermöglichen könnte. Aber auch andere interessante Aspekte, die nicht unmittelbar in die Entwicklung der RTDL mit eingeflossen sind, wurden in dieser Arbeit betrachtet. Hier ist zum Beispiel die Joint Architecture for Unmanned Systems (JAUS) zu nennen. JAUS ist ein Standard, der gut geeignet ist, um die Architektur der Steuerungssoftware von unbemannten Systemen beliebiger Art zu entwerfen und umzusetzen. Auch wenn noch ein weiter Weg vor den Entwicklern von Robotern liegt, bis das Ziel von selbstständig agierenden und mit Menschen kooperierenden Robotern erreicht ist, so ist die Einführung einer plattformunabhängigen Task-Schicht dennoch einen weiterer wichtiger Schritt hin zu diesem Ziel. 75 Kapitel A: Modellierungsansatz A Modellierungsansatz (Dies ist ein Auszug aus [Tes10] Eine ausführliche Beschreibung der Capabilities befindet sich in [JAU07a, S.17ff.]). Der Modellierungsansatz von JAUS unterteilt sich in drei verschiedene Bereiche: 1. Functional Capabilities (FC): Was der Kunde/Benutzer tut. 2. Informational Capabilities (IC): Was der Kunde/Benutzer weiß. 3. Device Groups (DG): Womit der Kunde/Benutzer interagiert, die Schnittstellen. Die funktionalen (FC) und informellen Fähigkeiten (IC) können mit den GeräteGruppen (DG) gekoppelt sein, jedoch wird das JAUS Domain Model diese Schnittstellen nicht spezifizieren. Diese Schnittstellen sind offene Standards und werden entweder durch die Joint Technical Architecture (JTA) oder den Original Equipment Manufacturer (OEM) definiert. A.1 Functional Capability (FC) Funktionale Fähigkeiten sind eine Menge von Fähigkeiten mit ähnlichem funktionalem Zweck. Das Domain Model unterteilt die funktionalen Fähigkeiten in elf Kategorien, die festlegen, welche Funktionen das unbemannte System ausführen kann. Die funktionalen Fähigkeiten sind jedoch nicht auf die genannten elf Kategorien beschränkt. 1. Command Capabilities erstellen Pläne, passen Daten an, treffen Entscheidungen, weisen Aufgaben zu und behandeln unerwartete Ereignisse. (a) Vehicle Commander (b) Team Commander (c) Team-of-Teams Commander 2. Maneuver Capabilities kommunizieren mit allen externen maneuvering control devices und können eine Menge von Sensoren beinhalten. Die Maneuver Capability besitzt eine mehrschichtige Menge von intelligenten Komponenten, die verschiedene Stufen von Manöveranweisungen akzeptieren. 76 Kapitel A: Modellierungsansatz (a) Primitive Maneuver Capability (b) Vector Maneuver Capability (c) Waypoint Maneuver Capability (d) Feature-Following Capability (e) Leader-Follower Capability 3. Navigational Capabilities sind verantwortlich für die Pfadplanung des unbemannten Systems zwischen zwei oder mehreren geographischen Orten. (a) Intelligent Navigation (b) Primitive Navigation (c) Semi-autonomous Navigation (d) Autonomous Navigation 4. Communication Capabilities sind verantwortlich für die Behandlung der Kommunikation zwischen dem unbemannten System und verschiedenen OCUs. OCUs sind Operator Control Units, Steuerungseinheiten für unbemannte Systeme. 5. Payload Capabilities sind für die Aufrechterhaltung der Kontrolle und der Statusüberwachung der Payloads zuständig. (a) Articulation i. Primitive Articulation ii. Repeating-path Articulation iii. Position and Attitude Articulation (b) Reconnaissance/Surveillance/Target Acquisition & Identification (RSTAI) i. Primitive RSTA-I ii. Semi-autonomous RSTA-I iii. Autonomous RSTA-I (c) Weapon Payload i. Weapon Payload Primitive Capability ii. Area Engagement Capability iii. Target Engagement Capability 77 Kapitel A: Modellierungsansatz (d) Environmental Sensing (e) Manipulation 6. Safety Capabilities sind verantwortlich für die Betriebssicherheit des unbemannten Systems. (a) Primitive Safety Capability (b) Intelligent Safety Capability 7. Security Capabilities verhindern den unautorisierten Zugriff auf das unbemannte System. 8. Resource Management Capabilities verwalten die wichtigsten Ressourcen des unbemannten Systems wie zum Beispiel Treibstoff und Energie. 9. Maintenance Capabilities sind verantwortlich für die Systemwartung und können mit externen Test-Equipments kommunizieren. 10. Training Capabilities bieten Trainingsmöglichkeiten für Anwender an. 11. Automatic Configuration Capabilities minimieren die notwendige Konfiguration des unbemannten Systems durch einen Anwender. A.2 Informational Capability (IC) Informale Fähigkeiten sind Gruppen von ähnlichen Informationstypen. Es handelt sich hierbei um globale Repositories mit Systemdaten. Sie sind nach ihrem Datentyp benannt und spezifizieren, welche Informationen das unbemannte System über sich selbst besitzt. Die ICs stellen einen kontrollierten Zugang zu diesen Informationen für das gesamte unbemannte System zur Verfügung. 1. Vehicle Status Capabilities sind verantwortlich für die Bereitstellung des Fahrzeugstatus an andere Capabilities. Dies umfasst die Parameter: Position, sichtbare und hörbare Daten, Kalender, u.a. (a) Platform position and attitude (b) Engine Data 2. World Model Capabilities unterhalten ein Repository an interessanten Weltobjekten einschließlich freundlicher und feindlicher Einheiten, Hindernisse, Treppenbereiche, Karten, Routen, Wegpunkte und Aktionen. 78 Kapitel A: Modellierungsansatz (a) Topographic layouts (b) Building layouts and blueprints (c) Terrain feature information (d) Object of interest (last known and predicted location, last known and predicted path) 3. Library Capabilities verwalten Referenzmaterial, Prozeduren und Leistungsdaten. (a) Mission specific i. Procedures and tactics ii. Rules of Engagement iii. Mission planning (assembly areas, mobility areas, avoidance areas, potential target locations, etc.) (b) Platform specific i. Maintenance manuals ii. Online help iii. Training tutorials iv. Vehicle capability lists 4. Log Capabilities haben die Verantwortlichkeit der Aufzeichnung von Einsatz-, Wartungs- und Trainingsdaten. (a) System failures (vehicle and payload) (b) Operator commands (c) Events during mission execution (d) Collaborative information 5. Time/Date Capabilities bieten Datums- und Zeitdienste für das unbemannte System an. A.3 Device Groups (DG) Gerätegruppen sind Gruppierungen von Sensoren und/oder Aktoren die für ähnliche Funktionen verwendet werden. Spezifische Geräte werden nicht innerhalb von Gerätegruppen definiert. 79 Kapitel A: Modellierungsansatz A.4 Übersichtsgrafik Abbildung 10: RTDL Capabilities 80 Kapitel B: Liste ausgewählter JAUS-Komponenten B Liste ausgewählter JAUS-Komponenten B.1 Command and Control Klasse B.1.1 System Commander (ID 40) • Koordination der Subsysteme • Kommandierung • Statusabfrage • Diese Funktion kann von einem Menschen oder einer Maschine ausgefüllt werden. Bei einem Menschen gehören hierzu alle Elemente einer Benutzerschnittstelle, die zur Erbringung der Funktionalitäten dieser Komponente notwendig sind. B.1.2 Subsystem Commander (ID 32) • Verantwortlich für Mission Planing • Kommandierung, also das Übergeben von Anweisungen an das unbemannte System. • Statusabfrage • Diese Funktion kann von einem Menschen oder einer Maschine ausgefüllt werden. Bei einem Menschen gehören hierzu alle Elemente einer Benutzerschnittstelle, die zur Erbringung der Funktionalitäten dieser Komponente notwendig sind. B.2 B.2.1 Communication Communicator (ID 35) • Single point of entry für jedes Subsystem • Beinhaltet alle Data Links zu anderen Subsystemen 81 Kapitel B: Liste ausgewählter JAUS-Komponenten B.3 Platform B.3.1 Global Pose Sensor (ID 38) • Bestimmung der globalen Pose (Position und Ausrichtung) der Plattform • Werte werden angegeben in Form von Longitude (Längengrad), Latitude (Breitengrad) und Elevation (Erhöhung). B.3.2 Local Pose Sensor (ID 41) • Vergleichbar zum Global Pose Sensor • Bestimmung der lokalen Pose anhand eines kartesischen Koordinatensystems (x, y, z) angegeben in Relation zu einem definierten Referenzrahmen der Plattform. B.3.3 Velocity State Sensor (ID 42) • Ermittelt die aktuelle Geschwindigkeit der Plattform • Die Geschwindigkeit wird bestimmt als die Summe der Teilgeschwindigkeiten eines definierten Punktes entlang der X-, Y- und Z-Achse des definierten Referenzrahmens der Plattform. Die hierfür verwendeten JAUS-Nachrichten sind: – velocity x – velocity y – velocity z • Zusätzlich kann die Änderung der Ausrichtung bzw. Deren Winkelgeschwindigkeit über die folgenden Nachrichten angegeben werden: – omega x – omega y – omega z 82 Kapitel B: Liste ausgewählter JAUS-Komponenten B.3.4 Primitive Driver (ID 33) • Beinhaltet alle Basisfunktionen zum Fahren inklusive Hilfsmitteln. • Der Freiheitsgrad der Fortbewegung entspricht der Bewegung und Drehung entlang der X-, Y- und Z-Achse des definierten Referenzrahmens. • Striktes open loop Verhalten (Steuerung), wobei keine Geschwindigkeit vorgegeben wird, da diese nicht ohne Geschwindigkeitssensor geregelt werden kann. • Die genauen Aktoren-Kommandos sind nicht Teil der JAUS-Spezifikation. B.3.5 Reflexive Driver (ID 43) • Eine Art Filter vor dem Primitive Driver, bei dem Kommandos gefiltert und modifiziert werden können. Anwendung findet dies immer dann, wenn eine Operation die Sicherheit der Plattform gefährden könnte, zum Beispiel durch zu hohe kommandierte Geschwindigkeiten usw. • Es werden hierfür oftmals zusätzliche Sensoren an der Plattform angebracht, welche die Ausführung und den Zustand einer Plattform überwachen. Auf Basis dieser Sensordaten werden die gegebenen Kommandos entsprechend modifiziert, dass die Sicherheit der Plattform nicht gefährdet wird. • Die genaue Art der Sensoren ist nicht Teil der JAUS-Spezifikation. B.3.6 Global Vector Driver (ID 34) • Closed loop control (Regelung) von Richtung, Höhe und Geschwindigkeit einer Plattform • Die Komponente legt anhand des globlen Koordonatensystems die Änderung der Richtung und Geschwindigkeit zum gegebenen Zielpunkt fest und gibt diesen Befehl dann an den Primitive Driver oder Reflexive Driver. B.3.7 Local Vector Driver (ID 44) • Gleiche Funktion wie der Global Vector Driver unter Verwendung eines lokalen Koordinatensystems 83 Kapitel B: Liste ausgewählter JAUS-Komponenten • Informationen beinhalten: – heading (Richtung) – pitch (Neigung) – roll (Neigung um Längst-Achse) – speed (Geschwindigkeit) • Verwendet Daten von folgenden Sensoren: – Local Pose Sensor – Velocity State Sensor • Verwendete Nachrichten – Set Wrench Effort B.3.8 Global Waypoint Driver (ID 45) • Bestimmt den neuen Wrench (Verschiebung) der Plattform aus den folgenden Größen: – Ziel-Wegpunkt – gewünschte Reisegeschwindigkeit – Pose – aktuelle Geschwindigkeit • Ein Wegpunkt setzt sich aus den folgenden Informationen zusammen: – Position – Ausrichtung • Wenn die Plattform den letzten Wegpunkt einer Liste erreicht hat, so muss sie in einen Standby Status übergehen. • Verwendete Nachrichten: – Set Global Waypoint – Set Travel Speed – Report Global Pose – Report Velocity State 84 Kapitel B: Liste ausgewählter JAUS-Komponenten B.3.9 Local Waypoint Driver (ID 46) • Gleiche Funktionalität, wie der Global Waypoint Driver, jedoch mit einem lokalen Koordinatensystem als Referenz. • Verwendete Nachrichten: – Set Local Waypoint – Set Travel Speed – Report Local Pose – Report Velocity State B.3.10 Global Path Segment Driver (ID 47) • Closed loop Control (Regelung) von Position und Geschwindigkeit einer Plattform entlang eines festgelegten Pfades • Der Unterschied zum Waypoint Driver liegt darin, dass der exakte Pfad zwischen zwei Wegpunkten strikt definiert ist und nicht nur aus einer generellen Richtungsangabe besteht. • Ein Pfad wird durch drei Punkte (P0, P1, P2) und einem Gewichtskoeffizienten (w) bestimmt. Hierbei ist P0 oft der Startpunkt und P2 der Zielpunkt. Der Pfad zwischen P0 und P2 wird nun so berechnet, dass der Weg zwischen P0 und P2 entlang dem gewichteten Punkt P1 verläuft. Ist w=0, fällt der Punkt P1 aus der Gleichung heraus und der Pfad ist die direkte Verbindung zwischen P0 und P2. Wird w¿0 gebildet, so verformt sich der Pfad zu einer Kurve die je nach Größe von w in Richtung von P1 gekrümmt wird. B.3.11 Local Path Segment Driver (ID 38) • Laut Beschreibung in JAUS, gibt es keinen erkennbaren Unterschied zum Global Path Segment Driver. B.4 B.4.1 Environment Sensor Components Visual Sensor (ID 37) • Steuert eine oder mehrere Kameras und deren Blickrichtungen 85 Kapitel B: Liste ausgewählter JAUS-Komponenten • Zuständig für die Kamera-Einstellungen, Bildformate, Audio usw. • Jeder Kamera wird ein lokales Kooridatensystem zugeordnet. B.4.2 Range Sensor (ID 50) • Steuert einen oder mehrere Abstandssensoren pro Komponente. • Abstandsinformationen relativ zum lokalen Koordinatensystem der Plattform. • Abstandswerte müssen von den Sensoren in einer festgelegten Genauigkeit ermittelt werden. B.4.3 World Model Vector Knowledge Store (ID 61) • Zentrales Repository für vektorformatierte geospatiale Daten für die Elemente aller Ebenen der JAUS-Topologie. • Speichern und Verteilen der Daten im Vektorformat. Vektorisierte Positionsund Richtungsangaben sind speicherplatzeffizient. • Objekte können aus Punkten, Linien, Polylinien und Polygone bestehen. • Objekte können einen Region Buffer besitzen. Das ist eine Umgebung (angegeben in Metern) um ein Objekt herum, die es einer Plattform erlaubt sich in die Nähe eines Objekts zu positionieren um dort Operationen ausführen zu können. • Verwendete Nachrichten: – Create Vector Knowledge Store Objects – Set Vector Knowledge Store Feature Class Metadata – Delete vector Knowledge Store Objects – Query Vector Knowledge Store Objects – Query Vector Knowledge Store Feature Class Metadata – Query Vector Knowledge Store Bounds – Terminate Vector Knowledge Store Data Transfer – Report Vector Knowledge Store Object(s) Creation – Report Vector Knowledge Store Feature Class Metadata 86 Kapitel B: Liste ausgewählter JAUS-Komponenten – Report Vector Knowledge Store Objects – Report Vector Knowledge Store Bounds – Report Vector Knowledge Store Data Transfer Termination B.5 Planning Components B.5.1 Mission Planner (keine ID) • Missionplaner ist in der vorliegenden JAUS-Version v3.3 der Referenzarchitektur noch nicht definiert. B.5.2 Mission Spooler (ID 36) • Zentraler Ort für Missionspläne während der Ausführung oder kurz davor. • Aufgabe ist die Aufteilung von Planbestandteilen in einzelne Elmente und deren Auslieferungen an die entsprechenden Maschinenteile. • Eine Mission ist definiert als eine Menge von JAUS-Nachrichten. 87 Kapitel C: Liste ausgewählter JAUS-Nachrichten C Liste ausgewählter JAUS-Nachrichten C.1 Platform Subgroup Command Class (Code 0400-05FF) • Code 0405h: Set Wrench Effort • Code 0407h: Set Global Vector • Code 0408h: Set Local Vector • Code 040A: Set Travel Speed • Code 040Ch: Set Global Waypoint • Code 040Dh: Set Local Waypoint • Code 040Fh: Set Global Path Segment • Code 0410h: Set Local Path Segment C.2 Platform Subgroup Query Class (Code 2400-25FF) • Code 2402h: Query Global Pose • Code 2403h: Query Local Pose • Code 2404h: Query Velocity State • Code 2405h: Query Wrench Effort • Code 2407h: Query Global Vector • Code 2408h: Query Local Vector • Code 240Ah: Query Travel Speed • Code 240Ch: Query Global Waypoint • Code 240Dh: Query Local Waypoint • Code 240Fh: Query Global Path Segment • Code 2410h: Query Local Path Segment 88 Kapitel C: Liste ausgewählter JAUS-Nachrichten C.3 Platform Subgroup Inform Class (Code 4400-45FF) • Code 4402h: Report Global Pose • Code 4403h: Report Local Pose • Code 4404h: Report Velocity State • Code 4405h: Report Wrench Effort • Code 4407h: Report Global Vector • Code 4408h: Report Local Vector • Code 440Ah: Report Travel Speed • Code 440Ch: Report Global Waypoint • Code 440Dh: Report Local Waypoint • Code 440Fh: Report Global Path Segment • Code 4410h: Report Local Path Segment 89 Kapitel D: Quelltexte D Quelltexte D.1 DrinkingGlass.java 1 /∗ ∗ 2 ∗ DrinkingGlass . java 3 ∗ A drinking glass container . 4 ∗ 5 ∗ @author Marcus Teske 6 ∗/ 7 package r t d l ; 8 9 public c l a s s D r i n k i n g G l a s s extends WorldObject { 10 11 private S t r i n g contentType ; 12 13 /∗ ∗ 14 ∗ Constructor 15 ∗ @param objectName Name o f t h e d r i n k i n g g l a s s . 16 ∗/ 17 D r i n k i n g G l a s s ( S t r i n g objectName ) { 18 super . setObjectName ( objectName ) ; 19 super . i s C o n t a i n e r = true ; 20 super . i s G r i p p e a b l e = true ; 21 t h i s . contentType = new S t r i n g ( ) ; 22 } 23 24 /∗ ∗ 25 ∗ F i l l the drinking glass . 26 ∗ @param w The World t h e t a k e s p l a c e i n . 27 ∗ @param s o u r c e The s o u r c e t h a t f i l l s t h i s container with i t s output . 28 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 29 ∗/ 30 @Override 31 public boolean f i l l C o n t a i n e r ( World w, S t r i n g s o u r c e ) { i f (w . getWorldObjectByName ( s o u r c e ) . i s S o u r c e ) { 32 33 S o u r c e s = ( S o u r c e ) w . getWorldObjectByName ( s o u r c e ) ; 34 t h i s . contentType = s . getSourceType ( ) ; 35 } 36 System . out . p r i n t l n ( t h i s . getObjectName ( ) + ” i s now f i l l e d with ” 37 + contentType + ” . ” ) ; 38 39 return true ; } 90 Kapitel D: Quelltexte 40 /∗ ∗ 41 42 ∗ Emptying t h e d r i n k i n g g l a s s . 43 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 44 ∗/ 45 @Override 46 public boolean emptyContainer ( ) { 47 t h i s . contentType = ” ” ; 48 return true ; } 49 50 } Listing 6: DrinkingGlass.java D.2 Main.java 1 /∗ ∗ 2 ∗ Main . j a v a 3 ∗ A programm t h a t i n s t a n t i a t e s a RobotSim o b j e c t and l e t ’ s t h e programmer p l a y 4 ∗ around w i t h i t . 5 ∗ 6 ∗ @author Marcus Teske 7 ∗/ 8 package r t d l ; 9 10 public c l a s s Main { 11 // S i m u l a t i o n p a r a m e t e r s 12 13 14 // Anfang A t t r i b u t e 15 private s t a t i c MyXmlParser mxp ; 16 private s t a t i c RobotSim r s ; 17 private s t a t i c R t d l P a r s e r r t d l p ; 18 // Ende A t t r i b u t e 19 20 21 22 // Anfang Methoden 23 public s t a t i c void main ( S t r i n g [ ] a r g s ) { 24 25 26 // Example f o r Import o f World try { mxp = new MyXmlParser ( ”C: \ \ temp \\ world . xml” ) ; 91 Kapitel D: Quelltexte 27 r s = mxp . p a r s e ( r s ) ; 28 } catch ( E x c e p t i o n e ) { 29 System . e r r . p r i n t l n ( ”ERROR beim Parsen ! ” ) ; } 30 31 32 33 // Erzeugen d e r S im u l ati o n su m g e bu n g 34 // r s = new RobotSim ( 1 0 , 10 , 1) ; 35 36 // Erzeugen e i n e s R o b o t e r s 37 // r s . c r e a t e R o b o t (” Robot1 ” , 0 , 0 , 0) ; 38 39 // Erzeugen e i n e s Wasserhahns an P o s i t i o n [ 3 , 3 , 0 ] 40 // r s . c r e a t e W o r l d O b j e c t (” Tap ” , ”Tap1 ” , 3 , 3 , 0) ; 41 42 // P o s i t i o n i e r e n e i n e s W a s s e r g l a s e s an P o s i t i o n [ 6 , 6 , 0 ] 43 // r s . c r e a t e W o r l d O b j e c t (” D r i n k i n g G l a s s ” , ” G l a s s 1 ” , 6 , 6 , 0) ; 44 45 // Task p a r s e n und ausf à 14 hren . 46 try { 47 r t d l p = new R t d l P a r s e r ( ”C: \ \ temp \\ f e t c h W a t e r . xml” ) ; 48 r s = r t d l p . p a r s e ( r s , ” Robot1 ” ) ; 49 } catch ( E x c e p t i o n e ) { 50 System . e r r . p r i n t l n ( ”ERROR beim Parsen : \ n” + e . t o S t r i n g ( ) ) ; 51 52 } 53 54 55 // // Bewegung d e s R o b o t e r s z u r P o s i t i o n [ 6 , 6 , 0 ] r s . move (” Robot1 ” , ” G l a s s 1 ”) ; 56 // 57 // r s . g r i p (” Robot1 ” , ” G l a s s 1 ”) ; 58 // 59 // r s . move (” Robot1 ” , ”Tap1 ”) ; 60 // 61 // r s . u n g r i p (” Robot1 ” , ” G l a s s 1 ”) ; 62 // 63 // r s . f i l l (” Robot1 ” , ”Tap1 ” , ” G l a s s 1 ”) ; 64 // 65 // r s . g r i p (” Robot1 ” , ” G l a s s 1 ”) ; 66 // 67 // r s . move (” Robot1 ” , ” S t a r t ”) ; 68 // 69 // r s . u n g r i p (” Robot1 ” , ” G l a s s 1 ”) ; 70 92 Kapitel D: Quelltexte 71 // Example f o r s a v i n g t h e World . try { 72 // 73 // echo ( r s . t o X m l S t r i n g ( ) ) ; 74 // } catch ( NullPointerException e ) { 75 // } 76 } 77 78 private s t a t i c void echo ( S t r i n g s ) { 79 80 System . out . p r i n t l n ( s ) ; 81 } 82 // Ende Methoden 83 } Listing 7: Main.java D.3 MyXmlparser.java 1 /∗ ∗ 2 ∗ MyXmlParser . j a v a 3 ∗ h t t p : / /www. i k s . hs−merseburg . de /˜ u s c h r o e t / L i t e r a t u r / J a v a L i t / JAVA Insel / j a v a i n s e l 1 5 0 0 4 . htm#m j d 0 d b b 5 3 e 7 2 e 3 b 5 3 b 0 1 1 e 1 5 c 2 0 0 5 4 0 7 8 f 4 ∗ 5 ∗ @author Marcus Teske 6 ∗/ 7 package r t d l ; 8 9 import j a v a . i o . ∗ ; 10 import j a v a x . xml . stream . XMLInputFactory ; 11 import j a v a x . xml . stream . XMLStreamReader ; 12 import j a v a x . xml . stream . XMLStreamException ; 13 import j a v a x . xml . stream . XMLStreamConstants ; 14 15 public c l a s s MyXmlParser { 16 17 XMLStreamReader p a r s e r ; 18 19 /∗ P a rs e r v a r i a b l e s ∗/ 20 private int s i z e X = 0 ; // h o l d s t h e s i z e a l o n g x o f t h e w o r l d . 21 private int s i z e Y = 0 ; // h o l d s t h e s i z e a l o n g x o f t h e w o r l d . 22 private int s i z e Z = 0 ; // h o l d s t h e s i z e a l o n g x o f t h e w o r l d . 23 private boolean i n O b j e c t = f a l s e ; 93 Kapitel D: Quelltexte 24 private S t r i n g name = ” ” ; // h o l d s t h e name o f t h e c u r r e n t WorldObject . 25 private S t r i n g type = ” ” ; // h o l d s t h e t y p e o f t h e c u r r e n t WorldObject . 26 private int x = 0 ; // h o l d s t h e x−c o o r d i n a t e o f t h e c u r r e n t WorldObject . 27 private int y = 0 ; // h o l d s t h e y−c o o r d i n a t e o f t h e c u r r e n t WorldObject . 28 private int z = 0 ; // h o l d s t h e z−c o o r d i n a t e o f t h e c u r r e n t WorldObject . 29 30 MyXmlParser ( S t r i n g f i l e n a m e ) 31 throws FileNotFoundException , XMLStreamException { 32 p a r s e r = XMLInputFactory . n e w I n s t a n c e ( ) . createXMLStreamReader ( 33 34 new F i l e I n p u t S t r e a m ( f i l e n a m e ) ) ; } 35 36 public RobotSim p a r s e ( RobotSim r s ) throws XMLStreamException { 37 38 39 40 41 while ( p a r s e r . hasNext ( ) ) { switch ( p a r s e r . getEventType ( ) ) { case XMLStreamConstants .START DOCUMENT: break ; 42 43 case XMLStreamConstants .END DOCUMENT: 44 parser . close () ; 45 break ; 46 47 48 case XMLStreamConstants .NAMESPACE: break ; 49 50 51 case XMLStreamConstants .START ELEMENT: i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” s i z e x ” ) ) { 52 s i z e X = I n t e g e r . p a r s e I n t ( p a r s e r . getElementText ( ) ) ; 53 } 54 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” s i z e y ” ) ) { 55 s i z e Y = I n t e g e r . p a r s e I n t ( p a r s e r . getElementText ( ) ) ; 56 } 57 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” s i z e z ” ) ) { 58 59 s i z e Z = I n t e g e r . p a r s e I n t ( p a r s e r . getElementText ( ) ) ; } 60 61 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” o b j e c t ” ) ) { 62 System . out . p r i n t l n ( ”DEBUG: i n s i d e o b j e c t ” ) ; 94 Kapitel D: Quelltexte 63 i n O b j e c t = true ; } 64 65 i f ( i n O b j e c t == true ) { 66 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ”name” ) ) { 67 68 name = p a r s e r . getElementText ( ) ; } e l s e i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” type ” ) ) { 69 70 type = p a r s e r . getElementText ( ) ; } e l s e i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ”x” ) ) { 71 72 x = I n t e g e r . p a r s e I n t ( p a r s e r . getElementText ( ) ) ; } e l s e i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ”y” ) ) { 73 74 y = I n t e g e r . p a r s e I n t ( p a r s e r . getElementText ( ) ) ; } e l s e i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” z ” ) ) { 75 76 z = I n t e g e r . p a r s e I n t ( p a r s e r . getElementText ( ) ) ; } 77 78 } 79 break ; 80 81 case XMLStreamConstants .CHARACTERS: 82 break ; 83 84 case XMLStreamConstants .END ELEMENT: 85 // Check i f s i z e s a r e s e t and c r e a t e RobotSim 86 i f ( r s == null && s i z e X > 0 && s i z e Y > 0 && s i z e Z > 0 ) { 87 r s = new RobotSim ( sizeX , sizeY , s i z e Z ) ; 88 } 89 i f ( i n O b j e c t == true && p a r s e r . getLocalName ( ) . e q u a l s ( ” o b j e c t ” )) { 90 System . out . p r i n t l n ( ”DEBUG( RobotSim ) : c r e a t e W o r l d O b j e c t ( ” + type 91 + ” , ” + name + ” , ” + x + ” , ” + y + ” , ” + z + ” ) ”) ; 92 r s . c r e a t e W o r l d O b j e c t ( type , name , x , y , z ) ; 93 inObject = false ; 94 } 95 break ; 96 default : 97 break ; 98 } 99 p a r s e r . next ( ) ; 100 } 101 return r s ; 102 } 103 } 95 Kapitel D: Quelltexte Listing 8: MyXmlparser.java D.4 Robot.java 1 /∗ ∗ 2 ∗ Robot . j a v a 3 ∗ An e x t e n s i o n o f t h e WorldObject c l a s s t h a t r e s e m b l e s a v i r t u a l Robot that is 4 ∗ a b l e t o a c t i n s i d e a v i r t u a l World . 5 ∗ 6 ∗ @author Marcus Teske 7 ∗/ 8 package r t d l ; 9 10 public c l a s s Robot extends WorldObject { 11 12 private int f a c i n g D i r e c t i o n ; 13 private s t a t i c f i n a l int NORTH = 0 ; 14 private s t a t i c f i n a l int EAST = 9 0 0 ; 15 private s t a t i c f i n a l int SOUTH = 1 8 0 0 ; 16 private s t a t i c f i n a l int WEST = 2 7 0 0 ; 17 private s t a t i c f i n a l int UP = 1 0 0 0 0 ; 18 private s t a t i c f i n a l int DOWN = −10000; 19 private WorldObject arm ; 20 21 /∗ ∗ 22 ∗ Constructor 23 ∗ @param objectName Name o f t h e r o b o t . 24 ∗ @param f a c i n g D i r e c t i o n I n i t i a l f a c i n g d i r e c t i o n . 25 ∗/ 26 Robot ( S t r i n g objectName , int f a c i n g D i r e c t i o n ) { 27 super . setObjectName ( objectName ) ; 28 super . canMove = true ; 29 this . f a c i n g D i r e c t i o n = f a c i n g D i r e c t i o n ; 30 } 31 32 /∗ ∗ 33 ∗ Constructor 34 ∗ @param objectName Name o f t h e r o b o t . 35 ∗/ 36 Robot ( S t r i n g objectName ) { 96 Kapitel D: Quelltexte 37 super . setObjectName ( objectName ) ; 38 t h i s . f a c i n g D i r e c t i o n = NORTH; 39 } 40 41 /∗ ∗ 42 ∗ The d i r e c t i o n t h e r o b o t i s f a c i n g a t . 43 ∗ @return D i r e c t i o n t h e r o b o t i s f a c i n g a t . 44 ∗/ 45 public int g e t F a c i n g D i r e c t i o n ( ) { 46 47 return t h i s . f a c i n g D i r e c t i o n ; } 48 49 /∗ ∗ 50 ∗ Turn t h e r o b o t t o a g i v e n f a c i n g d i r e c t i o n . 51 ∗ @param d i r e c t i o n new f a c i n g d i r e c t i o n . 52 ∗/ 53 public void s e t F a c i n g D i r e c t i o n ( int d i r e c t i o n ) { 54 55 this . f a c i n g D i r e c t i o n = d i r e c t i o n ; } 56 57 /∗ ∗ 58 ∗ Turning t h e r o b o t t o t h e r i g h t a b o u t 90 d e g r e e . 59 ∗/ 60 public void t u r n R i g h t ( ) { 61 t h i s . f a c i n g D i r e c t i o n += 9 0 0 ; 62 this . f a c i n g D i r e c t i o n = this . f a c i n g D i r e c t i o n % 3600; 63 } 64 65 /∗ ∗ 66 ∗ Turning t h e r o b o t t o t h e l e f t a b o u t 90 d e g r e e . 67 ∗/ 68 public void t u r n L e f t ( ) { 69 t h i s . f a c i n g D i r e c t i o n −= 9 0 0 ; 70 this . f a c i n g D i r e c t i o n = this . f a c i n g D i r e c t i o n % 3600; 71 } 72 73 /∗ ∗ 74 ∗ Get t h e W o r l d P o s i t i o n o f t h e Robot . 75 ∗ @param w The w o r l d . 76 ∗ @return The c u r r e n t p o s i t i o n o f t h e r o b o t . 77 ∗/ 78 79 public W o r l d P o s i t i o n g e t P o s i t i o n ( World w) { return w . getWorldLocationByWorldObjectName ( super . getObjectName ( ) ) . getPos ( ) ; 97 Kapitel D: Quelltexte 80 } 81 82 /∗ ∗ 83 ∗ Determins t h e p o s i t i o n n e x t t o t h e r o b o t s f r o n t . 84 ∗ @param w The w o r l d i n which t h e a c t i o n t a k e s p l a c e 85 ∗ @return The p o s i t i o n n e x t t o t h e r o b o t s f r o n t . 86 ∗/ 87 public W o r l d P o s i t i o n l o o k i n g A t ( World w) { 88 W o r l d P o s i t i o n pos = new W o r l d P o s i t i o n ( 89 t h i s . g e t P o s i t i o n (w) . getX ( ) , 90 t h i s . g e t P o s i t i o n (w) . getY ( ) , 91 t h i s . g e t P o s i t i o n (w) . getZ ( ) ) ; switch ( t h i s . f a c i n g D i r e c t i o n ) { 92 93 case NORTH: 94 pos . setY ( pos . getY ( ) + 1 ) ; 95 break ; 96 case EAST: 97 pos . setX ( pos . getX ( ) + 1 ) ; 98 break ; 99 case SOUTH: 100 pos . setY ( pos . getY ( ) − 1 ) ; 101 break ; 102 case WEST: 103 pos . setX ( pos . getX ( ) − 1 ) ; 104 break ; 105 case UP: 106 pos . s e t Z ( pos . getZ ( ) + 1 ) ; 107 break ; 108 case DOWN: 109 pos . s e t Z ( pos . getZ ( ) − 1 ) ; 110 break ; 111 } 112 return pos ; 113 } 114 115 /∗ ∗ 116 ∗ Moves t h i s r o b o t one s t e p f o r w a r d a l o n g h i s f a c i n g d i r e c t i o n , i f 117 ∗ @param w The World where t h e a c t i o n t a k e s p l a c e . 118 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 119 ∗/ possible . 120 public boolean moveForward ( World w) { 121 W o r l d P o s i t i o n pos = t h i s . l o o k i n g A t (w) ; 122 i f (w . i s P a s s a b l e ( pos ) ) { 98 Kapitel D: Quelltexte i f (w . s e t W o r l d O b j e c t ( this , pos ) ) { 123 124 return true ; } else { 125 126 System . e r r . p r i n t l n ( ”ERROR: moveForward ( ) f a i l e d ! ” ) ; 127 return f a l s e ; } 128 129 } 130 System . e r r . p r i n t l n ( ”WARNING: Cannot move t o [ ” + pos . getX ( ) + ” , ” 131 + pos . getY ( ) + ” , ” + pos . getZ ( ) + ” ] : L o c a t i o n i m p a s s a b l e . ” ); 132 133 return f a l s e ; } 134 135 /∗ ∗ 136 ∗ Turn t h e r o b o t so he f a c e s n o r t h . 137 ∗/ 138 public void f a c e N o r t h ( ) { 139 140 t h i s . f a c i n g D i r e c t i o n = NORTH; } 141 142 /∗ ∗ 143 ∗ Turn t h e r o b o t so he f a c e s e a s t . 144 ∗/ 145 public void f a c e E a s t ( ) { 146 147 t h i s . f a c i n g D i r e c t i o n = EAST; } 148 149 /∗ ∗ ∗ Turn t h e r o b o t so he f a c e s s o u t h . 150 ∗/ 151 152 public void f a c e S o u t h ( ) { 153 154 t h i s . f a c i n g D i r e c t i o n = SOUTH; } 155 156 /∗ ∗ 157 ∗ tun t h e r o b o t so he f a c e s w e s t . 158 ∗/ 159 public void faceWest ( ) { 160 161 t h i s . f a c i n g D i r e c t i o n = WEST; } 162 163 /∗ ∗ 164 ∗ Turn t h e r o b o t so he f a c e s up . 165 ∗/ 99 Kapitel D: Quelltexte 166 public void faceUp ( ) { 167 168 t h i s . f a c i n g D i r e c t i o n = UP; } 169 170 /∗ ∗ 171 ∗ Turn t h e r o b o t so he f a c e s down . 172 ∗/ 173 public void faceDown ( ) { 174 175 t h i s . f a c i n g D i r e c t i o n = DOWN; } 176 177 /∗ ∗ 178 ∗ Returns a g r e e t i n g message . 179 ∗ @return G r e e t i n g message 180 ∗/ 181 public S t r i n g g r e e t i n g ( ) { 182 return t h i s . getObjectName ( ) + ” : H e l l o I am ” + t h i s . getObjectName () 183 184 + ”!”; } 185 186 /∗ ∗ ∗ Checks w h e t h e r t h e n e x t p o s i t i o n t h e r o b o t i s f a c i n g a t i s 187 passable . 188 ∗ @param w The World . 189 ∗ @return True i f t h e p o s i t i o n t h e r o b o t i s f a c i n g a t i s p a s s a b l e , otherwise 190 ∗ false . 191 ∗/ 192 public boolean a h e a d P a s s a b l e ( World w) { 193 W o r l d P o s i t i o n wp = t h i s . l o o k i n g A t (w) ; 194 i f ( ! w . l o c a t i o n V a l i d (wp) ) { 195 System . e r r . p r i n t l n ( ”ERROR: ” + t h i s . getObjectName ( ) + ” cannot move t o [ ” 196 + wp . getX ( ) + ” , ” + wp . getY ( ) + ” , ” + wp . getZ ( ) + 197 ” ] : Location i n v a l i d ! ” ) ; 198 return f a l s e ; 199 } 200 return w . i s P a s s a b l e (wp) ; 201 } 202 203 204 /∗ ∗ ∗ L e t s t h e Robot w a l k a l o n g a s i m p l e p a t h t o a new l o c a t i o n . The Robot 100 Kapitel D: Quelltexte 205 ∗ f o l l o w s t h e x−a x i s u n t i l i t f i t s , t h e n t h e y−a x i s u n t i l i t f i t s and 206 ∗ f i n a l l y t h e z−a x i s u n t i l i t f i t s . 207 ∗ @param w The World i n which t h e o p e r a t i o n t a k e s p l a c e . 208 ∗ @param x x−c o o r d i n a t e 209 ∗ @param y y−c o o r d i n a t e 210 ∗ @param z z−c o o r d i n a t e 211 ∗ @return True i f t h e movement was s u c c e s s f u l , f a l s e i f not . 212 ∗/ 213 @Override 214 public boolean move ( World w, int x , int y , int z ) { 215 i f ( !w. l o c a t i o n V a l i d (x , y , z ) ) { 216 System . e r r . p r i n t l n ( ”ERROR: ” + t h i s . getObjectName ( ) 217 + ” cannot move t o [ ” + x + ” , ” + y + ” , ” + z 218 + ” ] : Location i n v a l i d ! ” ) ; 219 return f a l s e ; 220 } 221 W o r l d P o s i t i o n tp = new W o r l d P o s i t i o n ( x , y , z ) ; // t a r g e t WorldPosition 222 W o r l d P o s i t i o n cp = t h i s . g e t P o s i t i o n (w) ; // c u r r e n t W o r l d P o s i t i o n 223 224 i f ( cp . e q u a l s ( tp ) ) { 225 return true ; 226 } 227 f o r ( long i = cp . g e t O f f s e t X ( tp ) ; i != 0 ; ) { // U n t i l x−c o o r d i n a t e matches . i f ( i > 0 ) { // T a r g e t e a s t 228 i f ( ! t h i s . moveEast (w) ) { 229 230 break ; 231 } 232 i −−; } e l s e { // T a r g e t w e s t 233 i f ( ! t h i s . moveWest (w) ) { 234 235 break ; 236 } 237 i ++; } 238 239 } 240 f o r ( long i = cp . g e t O f f s e t Y ( tp ) ; i != 0 ; ) { // U n t i l y−c o o r d i n a t e matches . 241 242 i f ( i > 0 ) { // T a r g e t n o r t h i f ( ! t h i s . moveNorth (w) ) { 243 244 break ; } 101 Kapitel D: Quelltexte i −−; 245 } e l s e { // T a r g e t s o u t h 246 i f ( ! t h i s . moveSouth (w) ) { 247 248 break ; 249 } 250 i ++; } 251 252 } 253 f o r ( long i = cp . g e t O f f s e t Z ( tp ) ; i != 0 ; ) { // U n t i l z−c o o r d i n a t e matches . i f ( i > 0 ) { // T a r g e t ab o ve 254 i f ( ! t h i s . moveUp (w) ) { 255 256 break ; 257 } 258 i −−; } e l s e { // T a r g e t b e l o w 259 i f ( ! t h i s . moveDown (w) ) { 260 261 break ; 262 } 263 i ++; } 264 265 } 266 cp = t h i s . g e t P o s i t i o n (w) ; 267 return true ; 268 } 269 270 271 /∗ ∗ ∗ Gets t h e n e x t p o s s i b l e s t e p f o r t h e Robot on h i s way t o a t a r g e t position . 272 ∗ @param w World 273 ∗ @param x x−c c o r d i n a t e o f t a r g e t 274 ∗ @param y y−c c o r d i n a t e o f t a r g e t 275 ∗ @param z z−c c o r d i n a t e o f t a r g e t 276 ∗ @return P o s i t i o n o f t h e n e x t p o s s i b l e s t e p 277 ∗/ 278 279 public W o r l d P o s i t i o n n e x t S t e p ( World w, int x , int y , int z ) { W o r l d P o s i t i o n cp = t h i s . g e t P o s i t i o n (w) ; 280 281 i f ( cp . getX ( ) == x && cp . getY ( ) == y && cp . getZ ( ) == z ) { 282 return cp ; 283 } 284 i f ( cp . getX ( ) < x ) { 285 this . faceEast () ; 286 } e l s e i f ( cp . getX ( ) > x ) { 102 Kapitel D: Quelltexte 287 t h i s . faceWest ( ) ; 288 } 289 i f (w . l o c a t i o n V a l i d ( t h i s . l o o k i n g A t (w) ) && w . i s P a s s a b l e ( t h i s . l o o k i n g A t (w) ) ) { 290 291 return t h i s . l o o k i n g A t (w) ; } else { 292 293 i f ( cp . getY ( ) < y ) { 294 this . faceNorth ( ) ; } e l s e i f ( cp . getY ( ) > y ) { 295 296 this . faceSouth ( ) ; 297 } 298 i f (w . l o c a t i o n V a l i d ( t h i s . l o o k i n g A t (w) ) && w . i s P a s s a b l e ( t h i s . l o o k i n g A t (w) ) ) { 299 300 return t h i s . l o o k i n g A t (w) ; } else { 301 i f ( cp . getZ ( ) < z ) { 302 303 t h i s . faceUp ( ) ; } e l s e i f ( cp . getZ ( ) > z ) { 304 305 t h i s . faceDown ( ) ; 306 } 307 i f (w . l o c a t i o n V a l i d ( t h i s . l o o k i n g A t (w) ) && w . i s P a s s a b l e ( t h i s . l o o k i n g A t (w) ) ) { 308 309 return t h i s . l o o k i n g A t (w) ; } else { 310 311 return null ; } 312 } 313 314 } 315 316 } 317 318 /∗ ∗ 319 ∗ T r i e s t o move t h e r o b o t one p o s i t i o n t o t h e n o r t h . 320 ∗ @param w World . 321 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 322 ∗/ 323 public boolean moveNorth ( World w) { 324 this . faceNorth ( ) ; 325 return t h i s . moveForward (w) ; 326 } 327 328 /∗ ∗ 329 ∗ T r i e s t o move t h e r o b o t one p o s i t i o n t o t h e s o u t h . 330 ∗ @param w World . 103 Kapitel D: Quelltexte 331 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 332 ∗/ 333 public boolean moveSouth ( World w) { 334 this . faceSouth ( ) ; 335 return t h i s . moveForward (w) ; 336 } 337 338 /∗ ∗ 339 ∗ T r i e s t o move t h e r o b o t one p o s i t i o n t o t h e e a s t . 340 ∗ @param w World . 341 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . ∗/ 342 343 public boolean moveEast ( World w) { 344 this . faceEast () ; 345 return t h i s . moveForward (w) ; 346 } 347 348 /∗ ∗ 349 ∗ T r i e s t o move t h e r o b o t one p o s i t i o n t o t h e w e s t . 350 ∗ @param w World . 351 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 352 ∗/ 353 public boolean moveWest ( World w) { 354 t h i s . faceWest ( ) ; 355 return t h i s . moveForward (w) ; 356 } 357 358 /∗ ∗ 359 ∗ T r i e s t o move t h e r o b o t one p o s i t i o n up . 360 ∗ @param w World . 361 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 362 ∗/ 363 public boolean moveUp ( World w) { 364 t h i s . faceUp ( ) ; 365 return t h i s . moveForward (w) ; 366 } 367 368 /∗ ∗ 369 ∗ T r i e s t o move t h e r o b o t one p o s i t i o n down . 370 ∗ @param w World . 371 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 372 ∗/ 373 374 public boolean moveDown ( World w) { t h i s . faceUp ( ) ; 104 Kapitel D: Quelltexte 375 376 return t h i s . moveForward (w) ; } 377 378 /∗ ∗ 379 ∗ Gets t h e WorldObject t h e Robot has i n h i s arm . 380 ∗ @return O b j e c t i n t h e r o b o t ’ s arm . 381 ∗/ 382 @Override 383 public WorldObject getArmPayload ( ) { 384 385 return t h i s . arm ; } 386 387 /∗ ∗ 388 ∗ The Robot g r i p s an g r i p p e a b l e WorldObject . 389 ∗ @param w The w o r l d t h e a c t i o n t a k e s p l a c e i n . 390 ∗ @param name Name o f t h e WorldObject t o g r i p . 391 ∗ @return True i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 392 ∗/ 393 @Override 394 public boolean g r i p ( World w, S t r i n g name ) { 395 W o r l d P o s i t i o n myPos = t h i s . g e t P o s i t i o n (w) ; 396 W o r l d P o s i t i o n oPos = w . getWorldLocationByWorldObjectName ( 397 name ) . getPos ( ) ; 398 // I f t h e WorldObject i s a t my p o s i t i o n 399 i f ( myPos . e q u a l s ( oPos ) ) { i f (w . getWorldObjectByName ( name ) . i s G r i p p e a b l e ) { 400 401 t h i s . arm = w . takeObjectByName ( name ) ; 402 System . out . p r i n t l n ( t h i s . getObjectName ( ) + ” has g r i p p e d ” 403 + name + ” . ” ) ; 404 return true ; } 405 } 406 407 408 System . e r r . p r i n t l n ( ”ERROR: Grip f a i l e d : Object ” + name 409 + ” not found a t p o s i t i o n [ ” + myPos . getX ( ) + ” , ” + myPos . getY ( ) 410 + ” , ” + myPos . getZ ( ) + ” ] ! ” ) ; 411 412 return f a l s e ; } 413 414 /∗ ∗ 415 ∗ The Robot p u t s down t h e named WorldObject a h i s c u r r e n t p o s i t i o n . 416 ∗ @param w The World t h e a c t i o n t a k e s p l a c e i n . 417 ∗ @param name Name o f t h e WorldObject t o p u t down 105 Kapitel D: Quelltexte 418 ∗ @return True i f t h e o p e r a t i o n i s s u c c e s s f u l , f a l s e o t h e r w i s e . 419 ∗/ 420 @Override 421 public boolean u n g r i p ( World w, S t r i n g name ) { i f ( t h i s . arm != null ) { 422 i f ( t h i s . arm . getObjectName ( ) . e q u a l s ( name ) ) { 423 424 System . out . p r i n t l n ( t h i s . getObjectName ( ) + ” has u n g r i p p e d ” 425 + name + ” . ” ) ; 426 return w . s e t W o r l d O b j e c t ( t h i s . arm , t h i s . g e t P o s i t i o n (w) ) ; } 427 428 } 429 System . e r r . p r i n t l n ( ”ERROR: Ungrip f a i l e d : ” + t h i s . getObjectName ( ) 430 + ” d o e s not c a r r y o b j e c t ” + name + ” ! ” ) ; 431 return f a l s e ; } 432 433 } Listing 9: Robot.java D.5 RobotSim.java 1 /∗ ∗ 2 ∗ RobotSim . j a v a 3 ∗ A s i m u l a t i o n environment f o r v i r t u a l r o b o t s . I t c o n s i s t s o f e x a c t l y one World 4 ∗ and o f f e r s methods t h a t c a p s u l a t e t h e o p e r a t i o n s on t h e World and i t ’s 5 ∗ contained WorldObjects . 6 ∗ 7 ∗ @author Marcus Teske 8 ∗/ 9 package r t d l ; 10 11 // i m p o r t com . t h o u g h t w o r k s . xstream . ∗ ; 12 public c l a s s RobotSim { 13 14 private World w ; // The World where e v e r y t h i n g t a k e s p l a c e . 15 16 /∗ ∗ 17 ∗ Constructor to i n s t a n c i a t e a RobotSimulation . 18 ∗ @param x Amount o f WorldLocation a l o n g t h e X−a x i s , s t a r t i n g a t 0 . 19 ∗ @param y Amount o f WorldLocation a l o n g t h e Y−a x i s , s t a r t i n g a t 0 . 20 ∗ @param z Amount o f WorldLocation a l o n g t h e Z−a x i s , s t a r t i n g a t 0 . 106 Kapitel D: Quelltexte ∗/ 21 22 RobotSim ( int x , int y , int z ) { 23 24 t h i s . w = new World ( x , y , z ) ; } 25 26 /∗ ∗ ∗ C r e a t e s an O b j e c t w i t h a s p e c i f i e d t y p e and name a t a s p e c i f i e d 27 location . 28 ∗ @param t y p e Type o f t h e O b j e c t . 29 ∗ @param name Name o f t h e O b j e c t . 30 ∗ @param x P l a c e a t t h i s x−c c o r d i n a t e . 31 ∗ @param y P l a c e a t t h i s y−c c o r d i n a t e . 32 ∗ @param z P l a c e a t t h i s z−c c o r d i n a t e . 33 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e i f not . 34 ∗/ 35 public boolean c r e a t e W o r l d O b j e c t ( S t r i n g type , S t r i n g name , int x , int y, int z ) { 36 i f ( ! w . c o n t a i n s ( name ) ) { 37 i f ( this .w. l o c a t i o n V a l i d ( x , y , z ) ) { 38 i f ( ” Robot ” . e q u a l s ( type ) ) { 39 40 return t h i s . w . s e t W o r l d O b j e c t (new Robot ( name ) , x , y , z ) ; 41 // } e l s e i f (” RfidTag ” . e q u a l s ( t y p e ) ) { 42 // r e t u r n t h i s . w . s e t W o r l d O b j e c t ( new RfidTag ( name ) , x , y , z ) ; } e l s e i f ( ” Wall ” . e q u a l s ( type ) ) { 43 44 return t h i s . w . s e t W o r l d O b j e c t (new Wall ( name ) , x , y , z ) ; } e l s e i f ( ” D r i n k i n g G l a s s ” . e q u a l s ( type ) ) { 45 46 return t h i s . w . s e t W o r l d O b j e c t (new D r i n k i n g G l a s s ( name ) , x , y , 47 z) ; } e l s e i f ( ”Tap” . e q u a l s ( type ) ) { 48 49 return t h i s . w . s e t W o r l d O b j e c t (new Tap ( name ) , x , y , z ) ; } e l s e i f ( ” Waypoint ” . e q u a l s ( type ) ) { 50 51 return t h i s . w . s e t W o r l d O b j e c t (new Waypoint ( name ) , x , y , z ) ; 52 } 53 return f a l s e ; 54 } 55 return f a l s e ; } else { 56 57 System . e r r . p r i n t l n ( ”ERROR: Cannot c r e a t e WorldObject ” + name 58 + ” ! An Object by t h a t name a l r e a d y e x i s t s ! ” ) ; 59 return f a l s e ; } 60 61 } 62 107 Kapitel D: Quelltexte 63 /∗ ∗ 64 ∗ C r e a t e s a WorldObject o f a s p e c i f i c t y p e and w i t h a s p e c i f i c name 65 ∗ World ’ s o r i g i n . 66 ∗ @param t y p e Type o f t h e WorldObject [ Robot ] 67 ∗ @param name Name o f t h e WorldObject . 68 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e i f not . 69 ∗/ at the 70 public boolean c r e a t e W o r l d O b j e c t ( S t r i n g type , S t r i n g name ) { i f ( ” Robot ” . e q u a l s ( type ) ) { 71 72 return t h i s . w . s e t W o r l d O b j e c t (new Robot ( name ) , 0 , 0 , 0 ) ; } else { 73 74 return f a l s e ; } 75 76 } 77 78 /∗ ∗ 79 ∗ Simple Wrapper t o c r e a t e a r o b o t a t t h e w o r l d ’ s o r i g i n . 80 ∗ @param RobotName Name o f t h e Robot . 81 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e i f not . ∗/ 82 83 public boolean c r e a t e R o b o t ( S t r i n g RobotName ) { 84 85 return t h i s . c r e a t e W o r l d O b j e c t ( ” Robot ” , RobotName ) ; } 86 87 /∗ ∗ ∗ Wrapper t o c r e a t e a Robot w i t h a u n i q u e name a t a s p e c i f i e d 88 position . 89 ∗ @param RobotName Name o f t h e Robot . 90 ∗ @param x x−c o o r d i n a t e . 91 ∗ @param y x−c o o r d i n a t e . 92 ∗ @param z x−c o o r d i n a t e . 93 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e i f not . 94 ∗/ 95 public boolean c r e a t e R o b o t ( S t r i n g RobotName , int x , int y , int z ) { 96 97 return t h i s . c r e a t e W o r l d O b j e c t ( ” Robot ” , RobotName , x , y , z ) ; } 98 99 /∗ ∗ 100 ∗ Gets an WorldObject by i t ’ s name 101 ∗ @param name Name o f t h e WorldObject . 102 ∗ @return t h e WorldObject o b j e c t . 103 ∗/ 104 public WorldObject g e t O b j e c t ( S t r i n g name ) { 108 Kapitel D: Quelltexte 105 106 return t h i s . w . getWorldObjectByName ( name ) ; } 107 108 /∗ ∗ 109 ∗ Simple Wrapper f o r g e t t i n g r o b o t s . 110 ∗ @param name Name o f t h e r o b o t 111 ∗ @return t h e r o b o t o b j e c t . 112 ∗/ 113 public Robot getRobot ( S t r i n g name ) { 114 115 return ( Robot ) t h i s . w . getWorldObjectByName ( name ) ; } 116 117 /∗ ∗ 118 ∗ Removes an O b j e c t from t h e World . 119 ∗ @param name Name o f t h e O b j e c t . 120 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 121 ∗/ 122 public boolean removeObject ( S t r i n g name ) { 123 124 return t h i s . w . removeWorldObjectByName ( name ) ; } 125 126 /∗ ∗ 127 ∗ Gets t h e P o s i t i o n o f an WorldObject as W o r l d P o s i t i o n o b j e c t . 128 ∗ @param name name o f t h e WorldObject . 129 ∗ @return t h e p o s i t i o n . 130 ∗/ 131 public W o r l d P o s i t i o n g e t P o s i t i o n ( S t r i n g name ) { 132 133 return t h i s . w . getWorldLocationByWorldObjectName ( name ) . getPos ( ) ; } 134 135 /∗ ∗ 136 ∗ Gets t h e P o s i t i o n o f an WorldObject as S t r i n g [ x , y , z ] . 137 ∗ @param name name o f t h e WorldObject . 138 ∗ @return t h e p o s i t i o n . 139 ∗/ 140 public S t r i n g g e t P o s i t i o n S t r i n g ( S t r i n g name ) { 141 W o r l d P o s i t i o n wp = t h i s . g e t P o s i t i o n ( name ) ; 142 143 return ” P o s i t i o n o f ” + name + ” : [ ” + wp . getX ( ) + ” , ” + wp . getY ( ) + ” ,” 144 145 + wp . getZ ( ) + ” ] ” ; } 146 147 /∗ ∗ 109 Kapitel D: Quelltexte 148 ∗ P l a c e s an WorldObject d i r e c t l y a t t h e s p e c i f i e d l o c a t i o n . 149 ∗ @param name Name o f t h e WorldObject . 150 ∗ @param x x−c c o r d i n a t e 151 ∗ @param y y−c c o r d i n a t e 152 ∗ @param z z−c c o r d i n a t e 153 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 154 ∗/ 155 public boolean p l a c e ( S t r i n g name , int x , int y , int z ) { 156 return t h i s . w . s e t W o r l dO b j e c t ( t h i s . g e t O b j e c t ( name ) , x , y , z ) ; 157 158 159 } 160 161 /∗ ∗ 162 ∗ Wrapper t h a t l e t s an WorldObject move a l o n g a s i m p l e p a t h t o a new 163 ∗ location . 164 ∗ The WorldObject a t f i r s t moves a l o n g t h e x−a x i s , t h e n a l o n g t h e y− axis 165 ∗ and a t l a s t a l o n g t h e z−a x i s . 166 ∗ @param name Name o f t h e WorldObject t o move 167 ∗ @param x x−c c o r d i n a t e 168 ∗ @param y y−c o o r d i n a t e 169 ∗ @param z z−c o o r d i n a t e 170 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 171 ∗/ 172 public boolean move ( S t r i n g name , int x , int y , int z ) { i f ( ! t h i s . w . c o n t a i n s ( name ) ) { 173 174 System . e r r . p r i n t l n ( ”ERROR: Move f a i l e d : Object ” + name 175 + ” not found ! ” ) ; 176 return f a l s e ; 177 } 178 i f ( t h i s . g e t O b j e c t ( name ) . move ( t h i s . w, x , y , z ) ) { 179 System . out . p r i n t l n ( name + ” has moved t o [ ” + x + ” , ” + y + ” , ” + z 180 + ” ] . ”) ; 181 return true ; 182 } 183 System . e r r . p r i n t l n ( ”ERROR: Moving t o [ ” + x + ” , ” + y + ” , ” + z 184 + ” ] failed ! ”) ; 185 186 return f a l s e ; } 187 188 /∗ ∗ 110 Kapitel D: Quelltexte ∗ Wrapper t h a t l e t s an WorldObject name w a l k a l o n g a s i m p l e p a t h t o 189 the 190 ∗ l o c a t i o n o f a n o t h e r WorldObject d e s t i n a t i o n . 191 ∗ @param name Name o f WorldObject t o move . 192 ∗ @param d e s t i n a t i o n Name o f t h e d e s t i n a t i o n WorldObject . 193 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 194 ∗/ 195 public boolean move ( S t r i n g name , S t r i n g d e s t i n a t i o n ) { 196 WorldLocation d e s t L o c ; 197 d e s t L o c = w . getWorldLocationByWorldObjectName ( d e s t i n a t i o n ) ; 198 i f ( d e s t L o c == null ) { 199 System . e r r . p r i n t l n ( ”ERROR: Moving t o ” + d e s t i n a t i o n + ” f a i l e d ! ” 200 + ” No such WorldObject . ” ) ; 201 System . e x i t ( 1 ) ; 202 } 203 int x = d e s t L o c . getX ( ) ; 204 int y = d e s t L o c . getY ( ) ; 205 int z = d e s t L o c . getZ ( ) ; 206 207 208 return t h i s . move ( name , x , y , z ) ; } 209 210 /∗ ∗ 211 ∗ Moves an WorldObject one P o s i t i o n t o t h e North . Only Robots . 212 ∗ @param name Name o f The O b j e c t . 213 ∗ @param s t e p s The amount o f s t e p s t o move . 214 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 215 ∗/ 216 public boolean moveNorth ( S t r i n g name , int s t e p s ) { i f ( t h i s . g e t O b j e c t ( name ) . getObjectType ( ) . e q u a l s ( ” Robot ” ) ) { 217 218 Robot r = ( Robot ) t h i s . g e t O b j e c t ( name ) ; 219 while ( s t e p s > 0 ) { 220 s t e p s −−; 221 i f ( ! r . moveNorth (w) ) { 222 System . e r r . p r i n t l n ( ”ERROR: MovingNorth f a i l e d ! ” ) ; 223 return f a l s e ; } 224 225 } 226 return true ; 227 } 228 return f a l s e ; 229 } 230 231 /∗ ∗ 111 Kapitel D: Quelltexte 232 ∗ Moves an WorldObject s e v e r a l P o s i t i o n t o t h e South . Only Robots . 233 ∗ @param name Name o f The O b j e c t . 234 ∗ @param s t e p s The amount o f s t e p s t o move . 235 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 236 ∗/ 237 public boolean moveSouth ( S t r i n g name , int s t e p s ) { i f ( t h i s . g e t O b j e c t ( name ) . getObjectType ( ) . e q u a l s ( ” Robot ” ) ) { 238 239 Robot r = ( Robot ) t h i s . g e t O b j e c t ( name ) ; 240 while ( s t e p s > 0 ) { 241 s t e p s −−; 242 i f ( ! r . moveSouth (w) ) { 243 System . e r r . p r i n t l n ( ”ERROR: MovingSouth f a i l e d ! ” ) ; 244 return f a l s e ; } 245 246 } 247 return true ; 248 } 249 return f a l s e ; 250 } 251 252 /∗ ∗ 253 ∗ Moves an WorldObject one P o s i t i o n t o t h e East . Only Robots . 254 ∗ @param name Name o f The O b j e c t . 255 ∗ @param s t e p s The amount o f s t e p s t o move . 256 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l l , f a l s e i f not . 257 ∗/ 258 public boolean moveEast ( S t r i n g name , int s t e p s ) { i f ( t h i s . g e t O b j e c t ( name ) . getObjectType ( ) . e q u a l s ( ” Robot ” ) ) { 259 260 Robot r = ( Robot ) t h i s . g e t O b j e c t ( name ) ; 261 while ( s t e p s > 0 ) { 262 s t e p s −−; 263 i f ( ! r . moveEast (w) ) { 264 System . e r r . p r i n t l n ( ”ERROR: MovingEast f a i l e d ! ” ) ; 265 return f a l s e ; } 266 267 } 268 return true ; 269 } 270 return f a l s e ; 271 } 272 273 /∗ ∗ 274 ∗ Moves an WorldObject one P o s i t i o n t o t h e West . Only Robots . 275 ∗ @param name Name o f The O b j e c t . 112 Kapitel D: Quelltexte 276 ∗ @param s t e p s The amount o f s t e p s t o move . 277 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e i f not . ∗/ 278 279 public boolean moveWest ( S t r i n g name , int s t e p s ) { i f ( t h i s . g e t O b j e c t ( name ) . getObjectType ( ) . e q u a l s ( ” Robot ” ) ) { 280 281 Robot r = ( Robot ) t h i s . g e t O b j e c t ( name ) ; 282 while ( s t e p s > 0 ) { 283 s t e p s −−; 284 i f ( ! r . moveWest (w) ) { 285 System . e r r . p r i n t l n ( ”ERROR: MovingWest f a i l e d ! ” ) ; 286 return f a l s e ; } 287 288 } 289 return true ; 290 } 291 return f a l s e ; 292 } 293 294 /∗ ∗ 295 ∗ L e t s an a g e n t g r i p an g r i p p e a b l e WorldObject e n t i t y a t h i s c u r r e n t 296 ∗ position . 297 ∗ @param a g e n t Robot t o g r i p t h e e n t i t y . 298 ∗ @param e n t i t y G r i p p e a b l e WorldObject t o g r i p . 299 ∗ @return True i f t h e o p e a r t i o n i s s u c c e s s f u l , f a l s e i f not . 300 ∗/ 301 public boolean g r i p ( S t r i n g agent , S t r i n g e n t i t y ) { i f ( ! this .w. c o n t a i n s ( agent ) ) { 302 303 System . e r r . p r i n t l n ( ”ERROR: Grip f a i l e d : Agent ” + a g e n t 304 + ” not found ! ” ) ; 305 return f a l s e ; 306 } 307 i f ( ! this .w. c o n t a i n s ( e n t i t y ) ) { 308 System . e r r . p r i n t l n ( ”ERROR: Grip f a i l e d : E n t i t y ” + e n t i t y 309 + ” not found ! ” ) ; 310 return f a l s e ; 311 } 312 i f ( t h i s . g e t O b j e c t ( a g e n t ) . g r i p ( t h i s . w, e n t i t y ) ) { 313 return true ; 314 } 315 return f a l s e ; 316 } 317 318 319 /∗ ∗ ∗ L e t s an a g e n t p u t down t h e named WorldObject e n t i t y a t h i s c u r r e n t 113 Kapitel D: Quelltexte 320 ∗ position . 321 ∗ @param a g e n t Robot t o p u t down t h e e n t i t y . 322 ∗ @param e n t i t y G r i p p e a b l e WorldObject t o p u t down . 323 ∗ @return True i f t h e o p e r a t i o n i s s u c c e s s f u l , f a l s e i f not . 324 ∗/ 325 public boolean u n g r i p ( S t r i n g agent , S t r i n g e n t i t y ) { i f ( ! this .w. c o n t a i n s ( agent ) ) { 326 327 System . e r r . p r i n t l n ( ”ERROR: Ungrip f a i l e d : Agent ” + a g e n t 328 + ” not found ! ” ) ; 329 return f a l s e ; 330 } 331 i f ( ! t h i s . g e t O b j e c t ( a g e n t ) . getArmPayload ( ) . getObjectName ( ) . e q u a l s ( entity ) ) { 332 System . e r r . p r i n t l n ( ”ERROR: Ungrip f a i l e d : E n t i t y ” + e n t i t y 333 + ” not found ! ” ) ; 334 return f a l s e ; 335 } 336 i f ( t h i s . g e t O b j e c t ( a g e n t ) . u n g r i p ( t h i s . w, e n t i t y ) ) { 337 return true ; 338 } 339 System . e r r . p r i n t l n ( ”ERROR: ” + a g e n t + ” f a i l e d p u t t i n g down ” + entity ) ; 340 341 return f a l s e ; } 342 343 344 /∗ ∗ ∗ An a g e n t f i l l s a c o n t a i n e r w i t h t h e o u t p u t o f a s o u r c e . Agent , s o u r c e and 345 ∗ c o n t a i n e r have t o be a t t h e same p o s i t i o n . 346 ∗ @param a g e n t The a g e n t t o i n i t i a t e t h e f i l l i n g . 347 ∗ @param s o u r c e The s o u r c e t o f i l l t h e c o n t a i n e r . 348 ∗ @param c o n t a i n e r The c o n t a i n e r t o be f i l l e d w i t h t h e o u t p u t o f t h e source . 349 ∗ @return True i f t h e o p e r a t i o n i s s u c c e s s f u l , f a l s e i f not . 350 ∗/ 351 352 public boolean f i l l ( S t r i n g agent , S t r i n g s o u r c e , S t r i n g c o n t a i n e r ) { i f ( ! this .w. c o n t a i n s ( agent ) ) { 353 System . e r r . p r i n t l n ( ”ERROR: F i l l f a i l e d : Agent ” + a g e n t 354 + ” not found ! ” ) ; 355 return f a l s e ; 356 } 357 i f ( ! this .w. c o n t a i n s ( source ) ) { 358 359 System . e r r . p r i n t l n ( ”ERROR: F i l l f a i l e d : S o u r c e ” + s o u r c e + ” not found ! ” ) ; 114 Kapitel D: Quelltexte 360 return f a l s e ; 361 } 362 i f ( ! this .w. c o n t a i n s ( c o n t a i n e r ) ) { 363 System . e r r . p r i n t l n ( ”ERROR: F i l l f a i l e d : C o n t a i n e r ” + c o n t a i n e r 364 + ” not found ! ” ) ; 365 return f a l s e ; 366 } 367 W o r l d P o s i t i o n agentPos = 368 t h i s . w . getWorldLocationByWorldObjectName ( a g e n t ) . getPos ( ) ; 369 WorldPosition sourcePos = 370 t h i s . w . getWorldLocationByWorldObjectName ( s o u r c e ) . getPos ( ) ; 371 WorldPosition containerPos = 372 t h i s . w . getWorldLocationByWorldObjectName ( c o n t a i n e r ) . getPos () ; 373 // The a g e n t n ee d s t o be a t t h e same p o s i t i o n as t h e s o u r c e . 374 i f ( agentPos . e q u a l s ( s o u r c e P o s ) ) { i f ( sourcePos . equals ( containerPos ) ) { 375 376 System . out . p r i n t l n ( a g e n t + ” f i l l s ” + c o n t a i n e r + ” a t ” 377 + source + ” . ”) ; 378 return t h i s . w . getWorldObjectByName ( c o n t a i n e r ) . f i l l C o n t a i n e r ( t h i s . w, s o u r c e ) ; } else { 379 380 System . e r r . p r i n t l n ( ”ERROR: F i l l f a i l e d : C o n t a i n e r ” + c o n t a i n e r 381 + ” i s not a t t h e same p o s i t i o n a s s o u r c e ” + s o u r c e 382 + ” . ”) ; } 383 } else { 384 385 System . e r r . p r i n t l n ( ”ERROR: F i l l f a i l e d : Agent ” + a g e n t 386 + ” i s not a t t h e same p o s i t i o n a s s o u r c e ” + s o u r c e + ” . ”) ; 387 } 388 return f a l s e ; 389 } 390 391 /∗ ∗ 392 ∗ C r e a t e s an xml r e p r e s e n t a t i o n o f t h e w o r l d and i t s c o n t e n t s . 393 ∗ @return xml r e p r e s e n t a t i o n o f t h e w o r l d . 394 395 ∗/ public S t r i n g toXmlString ( ) throws N u l l P o i n t e r E x c e p t i o n { 396 S t r i n g [ ] o b j e c t s = t h i s . w . getWorldObjectNames ( ) ; 397 S t r i n g xml = new S t r i n g ( ) ; 398 xml += ”<world >\n” ; 399 xml += ” <s i z e x >” + t h i s . w . g e t S i z e X ( ) + ”</ s i z e x >\n” ; 400 xml += ” <s i z e y >” + t h i s . w . g e t S i z e Y ( ) + ”</ s i z e y >\n” ; 115 Kapitel D: Quelltexte 401 xml += ” <s i z e z >” + t h i s . w . g e t S i z e Z ( ) + ”</ s i z e z >\n” ; 402 xml += ” <o b j e c t s >\n” ; 403 404 f o r ( int i = 0 ; i < o b j e c t s . l e n g t h ; i ++) { 405 406 xml += ” <o b j e c t >\n” ; 408 xml += ” <name>” ; 409 xml += o b j e c t s [ i ] ; 410 xml += ”</name>\n” ; 407 411 412 xml += ” 413 xml += t h i s . w . getWorldObjectByName ( o b j e c t s [ i ] ) . getObjectType ( ) ; <type>” ; 414 xml += ”</type >\n” ; 415 416 xml += ” <x>” ; 417 xml += t h i s . w . getWorldLocationByWorldObjectName ( o b j e c t s [ i ] ) . getX () ; 418 xml += ”</x>\n” ; 419 420 xml += ” 421 xml += t h i s . w . getWorldLocationByWorldObjectName ( o b j e c t s [ i ] ) . getY <y>” ; () ; 422 xml += ”</y>\n” ; 423 424 xml += ” <z>” ; 425 xml += t h i s . w . getWorldLocationByWorldObjectName ( o b j e c t s [ i ] ) . getZ () ; 426 xml += ”</z>\n” ; 427 428 xml += ” </ o b j e c t >\n” ; 429 } 430 xml += ” 431 xml += ”</world>” ; </ o b j e c t s >\n” ; 432 433 return xml ; } 434 435 } Listing 10: RobotSim.java D.6 RtdlParser.java 116 Kapitel D: Quelltexte 1 /∗ ∗ 2 ∗ RtdlParser . java 3 ∗ h t t p : / /www. i k s . hs−merseburg . de /˜ u s c h r o e t / L i t e r a t u r / J a v a L i t / JAVA Insel / j a v a i n s e l 1 5 0 0 4 . htm#m j d 0 d b b 5 3 e 7 2 e 3 b 5 3 b 0 1 1 e 1 5 c 2 0 0 5 4 0 7 8 f 4 ∗ 5 ∗ @author Marcus Teske 6 ∗/ 7 package r t d l ; 8 9 import j a v a . i o . ∗ ; 10 import j a v a x . xml . stream . XMLInputFactory ; 11 import j a v a x . xml . stream . XMLStreamReader ; 12 import j a v a x . xml . stream . XMLStreamException ; 13 import j a v a x . xml . stream . XMLStreamConstants ; 14 15 public c l a s s R t d l P a r s e r { 16 17 XMLStreamReader p a r s e r ; 18 S t r i n g taskName ; 19 boolean inTaskArgs = f a l s e ; 20 S t r i n g actionName ; 21 int a r g s c n t ; 22 S t r i n g [ ] a c t i o n A r g s = new S t r i n g [ 5 ] ; 23 24 RtdlParser ( String filename ) 25 throws FileNotFoundException , XMLStreamException { 26 p a r s e r = XMLInputFactory . n e w I n s t a n c e ( ) . createXMLStreamReader ( 27 28 new F i l e I n p u t S t r e a m ( f i l e n a m e ) ) ; } 29 30 public RobotSim p a r s e ( RobotSim r s , S t r i n g r o b o t ) throws XMLStreamException , 31 InterruptedException { 32 33 34 35 36 while ( p a r s e r . hasNext ( ) ) { switch ( p a r s e r . getEventType ( ) ) { case XMLStreamConstants .START DOCUMENT: break ; 37 38 case XMLStreamConstants .END DOCUMENT: 39 parser . close () ; 40 break ; 41 117 Kapitel D: Quelltexte 42 43 case XMLStreamConstants .NAMESPACE: break ; 44 45 case XMLStreamConstants .START ELEMENT: 46 // Version c h e c k i n g , o n l y 1 . 0 i s v a l i d 47 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” r t d l ” ) ) { f o r ( int i = 0 ; i < p a r s e r . g e t A t t r i b u t e C o u n t ( ) ; i ++) { 48 49 i f ( parser . getAttributeLocalName ( i ) . equals ( ” v e r s i o n ” ) && p a r s e r . g e t A t t r i b u t e V a l u e ( i ) . e q u a l s ( ” 1 . 0 ” ) ) { 50 51 System . out . p r i n t l n ( ”RTDL V e r s i o n ” 52 + p a r s e r . g e t A t t r i b u t e V a l u e ( i ) + ” OK! ” ) ; } else { 53 54 System . e r r . p r i n t l n ( ”RTDL V e r s i o n ” 55 + parser . getAttributeValue ( i ) 56 + ” invalid . ”) ; 57 System . e x i t ( 1 ) ; } 58 } 59 60 } 61 62 // E x t r a c t t a s k name 63 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” t a s k ” ) ) { f o r ( int i = 0 ; i < p a r s e r . g e t A t t r i b u t e C o u n t ( ) ; i ++) { 64 i f ( parser . getAttributeLocalName ( i ) . equals ( ” task ” ) ) { 65 66 taskName = p a r s e r . g e t A t t r i b u t e V a l u e ( i ) ; 67 System . out . p r i n t l n ( ” P a r s i n g t a s k ” + taskName ) ; } 68 } 69 70 } 71 72 // E x t r a c t a c t i o n name 73 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ”name” ) ) { 74 actionName = p a r s e r . getElementText ( ) ; 75 System . out . p r i n t ( r o b o t + ” : ” + actionName + ” ( ” ) ; 76 } 77 78 // R e s e t a r g s c o u n t e r on e n t e r i n g a r gs −e l e m e n t . 79 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” a r g s ” ) ) { a r g s c n t = −1; 80 81 } 82 83 // E x t r a c t a c i o n a r g s 84 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” a r g ” ) ) { 85 a r g s c n t ++; 118 Kapitel D: Quelltexte 86 a c t i o n A r g s [ a r g s c n t ] = p a r s e r . getElementText ( ) ; 87 i f ( a r g s c n t == 0 ) { 88 System . out . p r i n t ( ’ ” ’ + a c t i o n A r g s [ a r g s c n t ] + ’ ” ’ ) ; } else { 89 90 System . out . p r i n t ( ” , ” + ’ ” ’ + a c t i o n A r g s [ a r g s c n t ] + ’ ” ’ ) ; } 91 92 } 93 94 break ; 95 96 97 case XMLStreamConstants .CHARACTERS: break ; 98 99 case XMLStreamConstants .END ELEMENT: 100 // Mark l e a v i n g o f t a s k a r g s t a g 101 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” t a s k a r g s ” ) ) { 102 103 inTaskArgs = f a l s e ; } 104 105 // E x e c u t e a c t i o n s w i t h e x a c t l y one argument and c l e a n up 106 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” a c t i o n ” ) ) { 107 System . out . p r i n t l n ( ” ) ; ” ) ; 108 i f ( actionName . e q u a l s ( ”move” ) ) { 109 r s . move ( robot , a c t i o n A r g s [ 0 ] ) ; 110 Thread . s l e e p ( 1 0 0 0 ) ; 111 } e l s e i f ( actionName . e q u a l s ( ” g r i p ” ) ) { 112 r s . g r i p ( robot , a c t i o n A r g s [ 0 ] ) ; 113 Thread . s l e e p ( 1 0 0 0 ) ; 114 } e l s e i f ( actionName . e q u a l s ( ” u n g r i p ” ) ) { 115 r s . u n g r i p ( robot , a c t i o n A r g s [ 0 ] ) ; 116 Thread . s l e e p ( 1 0 0 0 ) ; 117 } e l s e i f ( actionName . e q u a l s ( ” f i l l ” ) ) { 118 r s . f i l l ( robot , a c t i o n A r g s [ 0 ] , a c t i o n A r g s [ 1 ] ) ; 119 Thread . s l e e p ( 1 0 0 0 ) ; 120 } e l s e i f ( actionName . e q u a l s ( ” s e t C u r r e n t P o s i t i o n ” ) ) { 121 r s . c r e a t e W o r l d O b j e c t ( ” Waypoint ” , 122 actionArgs [ 0 ] , 123 ( int ) r s . g e t P o s i t i o n ( r o b o t ) . getX ( ) , 124 ( int ) r s . g e t P o s i t i o n ( r o b o t ) . getY ( ) , 125 ( int ) r s . g e t P o s i t i o n ( r o b o t ) . getZ ( ) ) ; 126 Thread . s l e e p ( 1 0 0 0 ) ; 127 } 128 actionName = ”” ; 129 a r g s c n t = −1; 119 Kapitel D: Quelltexte } 130 131 132 // R e s e t a c t i o n c o u n t e r . 133 i f ( p a r s e r . getLocalName ( ) . e q u a l s ( ” a r g s ” ) ) { 134 } 135 136 break ; 137 default : 138 break ; 139 } 140 p a r s e r . next ( ) ; 141 } 142 return r s ; } 143 144 } Listing 11: RtdlParser.java D.7 Source.java 1 /∗ ∗ 2 ∗ Source . j a v a 3 ∗ A s o u r c e t h a t p r o d u c e s some o u t p u t o f a sourceType . 4 ∗ Examples a r e a t a p or a power s o c k e t . 5 ∗ 6 ∗ @author Marcus Teske 7 ∗/ 8 package r t d l ; 9 10 public c l a s s S o u r c e extends WorldObject { 11 12 protected S t r i n g sourceType ; 13 14 S o u r c e ( S t r i n g objectName , S t r i n g sourceType ) { 15 super . setObjectName ( objectName ) ; 16 super . i s S o u r c e = true ; 17 t h i s . sourceType = sourceType ; 18 } 19 20 public S t r i n g getSourceType ( ) { 21 22 return t h i s . sourceType ; } 23 } 120 Kapitel D: Quelltexte Listing 12: Source.java D.8 Tap.java 1 /∗ ∗ 2 ∗ Tap . j a v a 3 ∗ A t a p t h a t can be used t o f i l l c o n t a i n e r −l i k e W o r l d O b j e c t s w i t h an output . 4 ∗ 5 ∗ @author Marcus Teske 6 ∗/ 7 package r t d l ; 8 9 public c l a s s Tap extends S o u r c e { 10 11 public Tap ( S t r i n g objectName ) { 12 super ( objectName , ” water ” ) ; } 13 14 } Listing 13: Tap.java D.9 Wall.java 1 /∗ ∗ 2 ∗ Wall . j a v a 3 ∗ A simple obstacle . 4 ∗ @author Marcus Teske 5 ∗/ 6 package r t d l ; 7 8 public c l a s s Wall extends WorldObject { 9 10 Wall ( S t r i n g objectName ) { 11 super . setObjectName ( objectName ) ; 12 super . i s P a s s a b l e = f a l s e ; 13 } 14 } Listing 14: Wall.java 121 Kapitel D: Quelltexte D.10 Waypoint.java 1 /∗ ∗ 2 ∗ Waypoint . j a v a 3 ∗ A simple waypoint . 4 ∗ @author Marcus Teske 5 ∗/ 6 package r t d l ; 7 8 public c l a s s Waypoint extends WorldObject { 9 Waypoint ( S t r i n g objectName ) { 10 11 super . setObjectName ( objectName ) ; } 12 13 } Listing 15: Waypoint.java D.11 World.java 1 /∗ ∗ 2 ∗ World . j a v a 3 ∗ A World i s an environment c o n s i s t i n g o f m u l t i p l e WorldLocations arranged in a 4 ∗ 3D c o o r d i n a t e system . The World may c o n t a i n an a r b i t r a r y number o f different 5 ∗ W o r l d O b j e c t s o f d i f f e r e n t t y p e s t h a t a r e r e f e r e n c e d by u n i q u e names . 6 ∗ 7 ∗ @author Marcus Teske 8 ∗/ 9 package r t d l ; 10 11 import j a v a . u t i l . HashMap ; 12 import j a v a . u t i l . A r r a y L i s t ; 13 14 public c l a s s World { 15 /∗ HashMap h o l d i n g W o r l d P o s i t i o n s ( c o o r d i n a t e s ) r e f e r e n c e d by 16 WorldObjectNames . ∗/ 17 18 19 20 private HashMap<S t r i n g , WorldLocation> p o s i t i o n s = new HashMap<S t r i n g , WorldLocation >() ; /∗ Array h o l d i n g WorldLocations ( which c o n t a i n W o r l d O b j e c t s ) r e f e r e n c e d by 122 Kapitel D: Quelltexte 21 t h e i r c o o r d i n a t e s . ∗/ 22 private WorldLocation w o r l d L o c a t i o n s [ ] [ ] [ ] ; 23 private int s i z e X ; 24 private int s i z e Y ; 25 private int s i z e Z ; 26 27 /∗ ∗ 28 ∗ Constructor 29 ∗ @param x Spread o f t h e World a l o n g t h e x−a x i s . 30 ∗ @param y Spread o f t h e World a l o n g t h e y−a x i s . 31 ∗ @param z Spread o f t h e World a l o n g t h e z−a x i s . ∗/ 32 33 World ( int x , int y , int z ) { 34 this . sizeX = x ; 35 this . sizeY = y ; 36 this . sizeZ = z ; 37 38 w o r l d L o c a t i o n s = new WorldLocation [ x ] [ y ] [ z ] ; 39 f o r ( int i = 0 ; i < x ; i ++) { f o r ( int j = 0 ; j < y ; j ++) { 40 f o r ( int k = 0 ; k < z ; k++) { 41 42 w o r l d L o c a t i o n s [ i ] [ j ] [ k ] = new WorldLocation ( i , j , k ) ; } 43 } 44 } 45 46 } 47 48 /∗ ∗ 49 ∗ Get t h e WorldLocation where t h e WorldObject w i t h name ”name” i s 50 ∗ @param name Name o f t h e WorldObject t h a t r e f e r e n c e s t h e located . WorldLocation . 51 ∗ @return TODO 52 ∗/ 53 public WorldLocation getWorldLocationByWorldObjectName ( S t r i n g name ) { i f ( t h i s . c o n t a i n s ( name ) ) { 54 55 return p o s i t i o n s . g e t ( name ) ; 56 } 57 return null ; 58 } 59 60 /∗ ∗ 61 ∗ Get t h e WorldObject w i t h t h e name ”name” 62 ∗ @param name Name o f t h e WorldObject . 123 Kapitel D: Quelltexte ∗/ 63 64 public WorldObject getWorldObjectByName ( S t r i n g name ) { i f ( t h i s . c o n t a i n s ( name ) ) { 65 66 WorldLocation wl = t h i s . getWorldLocationByWorldObjectName ( name ) ; 67 return t h i s . w o r l d L o c a t i o n s [ wl . getX ( ) ] [ wl . getY ( ) ] [ wl . getZ ( ) ] 68 . getWorldObject ( name ) ; } else { 69 70 return null ; } 71 72 } 73 74 /∗ ∗ 75 ∗ Gets t h e t y p e / c l a s s n a m e o f t h e WorldObject r e f e r e n c e d by ”name ” . 76 ∗ @param name Unique name o f t h e WorldObject . 77 ∗ @return Type/ c l a s s n a me o f t h e WorldObject . 78 ∗/ 79 public S t r i n g getWorldObjectType ( S t r i n g name ) { 80 81 return t h i s . getWorldObjectByName ( name ) . getObjectType ( ) ; } 82 83 /∗ ∗ 84 ∗ Remove t h e WorldObject w i t h name ”name” from t h e World . 85 ∗ @param name Name o f t h e WorldObject t o remove . 86 ∗/ 87 public boolean removeWorldObjectByName ( S t r i n g name ) { i f ( t h i s . c o n t a i n s ( name ) ) { 88 89 WorldLocation wl = t h i s . getWorldLocationByWorldObjectName ( name ) ; 90 // Remove t h e WorldObject i t s e l f . 91 w o r l d L o c a t i o n s [ wl . getX ( ) ] [ wl . getY ( ) ] [ wl . getZ ( ) ] . removeWorldObject 92 // Remove t h e e n t r y from t h e p o s i t i o n s 93 t h i s . p o s i t i o n s . remove ( name ) ; 94 return true ; ( name ) ; } else { 95 96 System . e r r . p r i n t l n ( ”ERROR: Cannot remove WorldObject ” + name 97 + ” ! I t d o e s not e x i s t s ! ” ) ; 98 return f a l s e ; } 99 100 } 101 102 103 /∗ ∗ ∗ Remove t h e WorldObject w i t h name ”name” from t h e w o r l d and r e t u r n it . 104 ∗ @param name Name o f t h e WorldObject t o remove . 124 Kapitel D: Quelltexte 105 ∗ @return The WorldObject t h a t has been removed from t h e World . 106 ∗/ 107 public WorldObject takeObjectByName ( S t r i n g name ) { 108 WorldObject wo = t h i s . getWorldObjectByName ( name ) ; 109 i f ( removeWorldObjectByName ( name ) ) { 110 return wo ; 111 } 112 return null ; 113 } 114 115 /∗ ∗ 116 ∗ P l a c e a WorldObject a t t h e WorldLocation s p e c i f i e d by wl . 117 ∗ @param wo WorldObject t o p l a c e . 118 ∗ @param wl WorldLocation where t h e WorldObject s h o u l d be p l a c e d . 119 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 120 ∗/ 121 public boolean s e t W o r l d O b j e c t ( WorldObject wo , WorldLocation wl ) { 122 123 return t h i s . s e t W o r l d O b j e c t ( wo , wl . getX ( ) , wl . getY ( ) , wl . getZ ( ) ) ; } 124 125 /∗ ∗ 126 ∗ P l a c e a WorldObject a t t h e WorldLocation s p e c i f i e d by wp . 127 ∗ @param wo WorldObject t o p l a c e . 128 ∗ @param wp WorldLocation where t h e WorldObject s h o u l d be p l a c e d . 129 ∗ @return t r u e i f t h e o p e r a t i o n was s u c c e s s f u l , f a l s e o t h e r w i s e . 130 ∗/ 131 public boolean s e t W o r l d O b j e c t ( WorldObject wo , W o r l d P o s i t i o n wp) { 132 return t h i s . s e t W o r l d O b j e c t ( wo , 133 ( int ) wp . getX ( ) , 134 ( int ) wp . getY ( ) , 135 ( int ) wp . getZ ( ) ) ; 136 } 137 138 /∗ ∗ 139 ∗ P l a c e a WorldObject a t t h e WorldLocation s p e c i f i e d by x , y and z . 140 ∗ @param wo WorldObject t o p l a c e . 141 ∗ @param x X−c o o r d i n a t e o f t h e L o c a t i o n . 142 ∗ @param y Y−c o o r d i n a t e o f t h e L o c a t i o n . 143 ∗ @param z Z−c o o r d i n a t e o f t h e L o c a t i o n . 144 ∗ @return Returns t r u e i f t h e WorldObject has been p l a c e d , f a l s e i f not . 145 146 147 ∗/ public boolean s e t W o r l d O b j e c t ( WorldObject wo , int x , int y , int z ) { i f ( this . l o c a t i o n V a l i d (x , y , z ) ) { 125 Kapitel D: Quelltexte 148 t h i s . p o s i t i o n s . put (wo . getObjectName ( ) , new WorldLocation ( x , y , z ) ); 149 t h i s . w o r l d L o c a t i o n s [ x ] [ y ] [ z ] . s e t W o r l d O b j e c t (wo) ; 150 return true ; } else { 151 152 return f a l s e ; } 153 154 } 155 156 /∗ ∗ 157 ∗ Checks i f a WorldObject w i t h ObjectName ”name” e x i s t s i n t h e w o r l d 158 ∗ @param name Unique name o f t h e WorldObject . 159 ∗ @return True i f t h e O b j e c t e x i s t s , F a l s e o t h e r w i s e . 160 ∗/ . 161 public boolean c o n t a i n s ( S t r i n g name ) { 162 163 return t h i s . p o s i t i o n s . c o n t a i n s K e y ( name ) ; } 164 165 /∗ ∗ 166 ∗ Gets t h e names o f a l l O b j e c t s i n t h e World as s t r i n g a r r a y . 167 ∗ @return S t r i n g a r r a y w i t h t h e names o f a l l W o r l d O b j e c t s i n t h i s world . ∗/ 168 169 public S t r i n g [ ] getWorldObjectNames ( ) { 170 S t r i n g [ ] s a = new S t r i n g [ t h i s . p o s i t i o n s . k e y S e t ( ) . s i z e ( ) ] ; 171 int i = 0 ; 172 for ( S t r i n g s : this . p o s i t i o n s . keySet ( ) ) { 173 sa [ i ] = s ; 174 i ++; 175 } 176 return s a ; 177 } 178 179 /∗ ∗ 180 ∗ Checks w h e t h e r a WorldLocation / W o r l d P o s i t i o n i s v a l i d or not . 181 ∗ @param x x−c c o r d i n a t e o f t h e WorldLocation / W o r l d P o s i t i o n . 182 ∗ @param y y−c c o r d i n a t e o f t h e WorldLocation / W o r l d P o s i t i o n . 183 ∗ @param z z−c c o r d i n a t e o f t h e WorldLocation / W o r l d P o s i t i o n . 184 ∗ @return True i f t h e c o o r d i n a t e s a r e v a l i d , F a l s e i f not . 185 ∗/ 186 187 public boolean l o c a t i o n V a l i d ( int x , int y , int z ) { i f ( x >= t h i s . s i z e X | | x < 0 ) { 126 Kapitel D: Quelltexte 188 System . e r r . p r i n t l n ( ”ERROR: WordLocation [ ” + x + ” , ” + y + ” , ” + z 189 + ” ] i n v a l i d : X−c o o r d i n a t e i s ” + ” o u t s i d e o f t h i s world ’ s ” 190 + ” boundaries ! ” ) ; 191 return f a l s e ; 192 } 193 i f ( y >= t h i s . s i z e Y | | y < 0 ) { 194 System . e r r . p r i n t l n ( ”ERROR: WordLocation [ ” + x + ” , ” + y + ” , ” + z 195 + ” ] i n v a l i d : Y−c o o r d i n a t e i s ” + ” o u t s i d e o f t h i s world ’ 196 + ” boundaries ! ” ) ; s ” 197 return f a l s e ; 198 } 199 i f ( z >= t h i s . s i z e Z | | z < 0 ) { 200 System . e r r . p r i n t l n ( ”ERROR: WordLocation [ ” + x + ” , ” + y + ” , ” + z 201 + ” ] i n v a l i d : Z−c o o r d i n a t e i s ” + ” o u t s i d e o f t h i s world ’ s ” 202 + ” boundaries ! ” ) ; 203 return f a l s e ; 204 } 205 return true ; 206 } 207 208 /∗ ∗ 209 ∗ Checks w h e t h e r a WorldLocation / W o r l d P o s i t i o n i s v a l i d or not . 210 ∗ @param wp W o r l d P o s i t i o n t o c h e c k . 211 ∗ @return True i f t h e c o o r d i n a t e s a r e v a l i d , F a l s e i f not . 212 ∗/ 213 public boolean l o c a t i o n V a l i d ( W o r l d P o s i t i o n wp) { 214 return t h i s . l o c a t i o n V a l i d ( ( int ) wp . getX ( ) , ( int ) wp . getY ( ) , ( int ) wp . getZ ( ) ) ; 215 } 216 217 public int g e t S i z e X ( ) { 218 219 return s i z e X ; } 220 221 public int g e t S i z e Y ( ) { 222 223 return s i z e Y ; } 224 127 Kapitel D: Quelltexte public int g e t S i z e Z ( ) { 225 226 return s i z e Z ; } 227 228 /∗ ∗ 229 230 ∗ Gets a l l W o r l d O b j e c t s from t h e s p e c i f i e d WorldLocation . 231 ∗ @param x x−c c o r d i n a t e o f t h e l o c a t i o n 232 ∗ @param y y−c c o r d i n a t e o f t h e l o c a t i o n 233 ∗ @param z z−c c o r d i n a t e o f t h e l o c a t i o n 234 ∗ @return A l l O b j e c t s from t h a t l o c a t i o n 235 ∗/ 236 public A r r a y L i s t <WorldObject> g e t A l l O b j e c t s F r o m L o c a t i o n ( int x , int y , int z ) { 237 return t h i s . w o r l d L o c a t i o n s [ x ] [ y ] [ z ] . g e t O b j e c t s ( ) ; } 238 239 /∗ ∗ 240 241 ∗ Returns w h e t h e r a l o c a t i o n i s p a s s a b l e or not . 242 ∗ @param x x−c c o r d i n a t e o f t h e l o c a t i o n 243 ∗ @param y y−c c o r d i n a t e o f t h e l o c a t i o n 244 ∗ @param z z−c c o r d i n a t e o f t h e l o c a t i o n 245 ∗ @return t r u e i f t h e l o c a t i o n i s p a s s a b l e , f a l s e o t h e r w i s e 246 ∗/ public boolean i s P a s s a b l e ( int x , int y , int z ) { 247 248 return t h i s . w o r l d L o c a t i o n s [ x ] [ y ] [ z ] . i s P a s s a b l e ( ) ; } 249 250 /∗ ∗ 251 252 ∗ Returns w h e t h e r a l o c a t i o n i s p a s s a b l e or not . 253 ∗ @param pos P o s t i o n o f t h e l o c a t i o n 254 ∗ @return t r u e i f t h e l o c a t i o n i s p a s s a b l e , f a l s e o t h e r w i s e 255 ∗/ public boolean i s P a s s a b l e ( W o r l d P o s i t i o n pos ) { 256 257 return t h i s . w o r l d L o c a t i o n s [ ( int ) pos . getX ( ) ] [ ( int ) pos . getY ( ) ] [ ( int ) pos 258 . getZ ( ) ] . i s P a s s a b l e ( ) ; } 259 260 } Listing 16: World.java D.12 WorldLocation.java 128 Kapitel D: Quelltexte 1 /∗ ∗ 2 ∗ WorldLocation . j a v a 3 ∗ A WorldLocation i s a l o c a t i o n w i t h i n a World . I t c o n t a i n s a u n i q u e 4 ∗ L o c a t i o n and can h o l d an a r b i t r a r y number o f named W o r l d o b j e c t s . 5 ∗ 6 ∗ @author Marcus Teske 7 ∗/ 8 package r t d l ; 9 10 import j a v a . u t i l . HashMap ; 11 import j a v a . u t i l . A r r a y L i s t ; 12 13 public c l a s s WorldLocation { 14 /∗ The W o r l d P o s i t i o n o f t h i s WorldLocation . ∗/ 15 16 W o r l d P o s i t i o n pos ; 17 /∗ A map where W o r l d O b j e c t s l o c a t e d i n t h i s L o c a t i o n a r e s t o r e d and referenced 18 ∗ by t h e i r u n i q u e name . 19 ∗/ 20 HashMap<S t r i n g , WorldObject> o b j e c t s = new HashMap<S t r i n g , WorldObject >() ; 21 22 /∗ ∗ 23 ∗ C o n s t r u c t o r o f WorldLoction 24 ∗ @param x The x−c o o r d i n a t e . 25 ∗ @param y The y−c o o r d i n a t e . 26 ∗ @param z The z−c o o r d i n a t e . 27 ∗/ 28 WorldLocation ( int x , int y , int z ) { 29 30 pos = new W o r l d P o s i t i o n ( ( long ) x , ( long ) y , ( long ) z ) ; } 31 32 /∗ ∗ 33 ∗ Get t h e named WorldObject r e f e r e n c e d by i t s u n i q u e name . 34 ∗ @param name The u n i q u e name o f t h e named WorldObject . 35 ∗ @return The named WorldObject . 36 ∗/ 37 public WorldObject getWorldObject ( S t r i n g name ) { 38 39 return ( WorldObject ) o b j e c t s . g e t ( name ) ; } 40 41 /∗ ∗ 129 Kapitel D: Quelltexte ∗ S t o r e a WorldObject i n d e x e d by i t s u n i q u e name i n t h e l o c a t i o n ’ s 42 object 43 ∗ pool . 44 ∗ @param wo WorldObject t o s t o r e . 45 ∗/ 46 public void s e t W o r l d O b j e c t ( WorldObject wo) { 47 t h i s . o b j e c t s . put (wo . getObjectName ( ) , wo) ; 48 } 49 50 /∗ ∗ 51 ∗ Gets t h e p o s t i o n o f t h i s WorldLocation as p o s i t i o n o b j e c t . 52 ∗ @return P o s i t i o n as p o s i t i o n o b j e c t . 53 ∗/ 54 public W o r l d P o s i t i o n getPos ( ) { 55 56 return pos ; } 57 58 /∗ ∗ 59 ∗ S e t s a new p o s i t i o n f o r t h i s WorldLocation . 60 ∗ @param pos new p o s i t i o n f o r t h i s WorldLocation . ∗/ 61 62 public void s e t P o s ( W o r l d P o s i t i o n pos ) { 63 64 t h i s . pos = pos ; } 65 66 /∗ ∗ ∗ Gets t h e d i s t a n c e from t h e o r i g i n a l o n g t h e x−a x i s o f t h i s 67 WorldLocation . ∗ @return D i s t a n c e t o t h e o r i g i n a l o n g t h e x−a x i s . 68 ∗/ 69 70 public int getX ( ) { 71 72 return ( int ) t h i s . pos . getX ( ) ; } 73 74 /∗ ∗ ∗ Gets t h e d i s t a n c e from t h e o r i g i n a l o n g t h e y−a x i s o f t h i s 75 WorldLocation . 76 ∗ @return D i s t a n c e t o t h e o r i g i n a l o n g t h e y−a x i s . 77 ∗/ 78 public int getY ( ) { 79 80 return ( int ) t h i s . pos . getY ( ) ; } 81 82 /∗ ∗ 130 Kapitel D: Quelltexte ∗ Gets t h e d i s t a n c e from t h e o r i g i n a l o n g t h e z−a x i s o f t h i s 83 WorldLocation . 84 ∗ @return D i s t a n c e t o t h e o r i g i n a l o n g t h e z−a x i s . 85 ∗/ 86 public int getZ ( ) { 87 88 return ( int ) t h i s . pos . getZ ( ) ; } 89 90 /∗ ∗ 91 ∗ Remove t h e WorldObject w i t h name ”name ” . 92 ∗ @param name Name o f t h e WorldObject t o remove . ∗/ 93 94 public void removeWorldObject ( S t r i n g name ) { 95 96 t h i s . o b j e c t s . remove ( name ) ; } 97 98 /∗ ∗ ∗ Get t h e t y p e / c l a s s n a m e o f an named o b j e c t s e l e c t e d by i t s u n i q u e 99 name . 100 ∗ @param name Unique name o f an named o b j e c t i n t h e World . 101 ∗ @return The t y p e / c l a s s n a m e o f t h e named o b j e c t . 102 ∗/ 103 public S t r i n g getWorldObjectType ( S t r i n g name ) { 104 105 return t h i s . getWorldObject ( name ) . getObjectType ( ) ; } 106 107 /∗ ∗ 108 ∗ Gets a l l o b j e c t s o f t h i s l o c a t i o n as A r r a y L i s t <WorldObject> 109 ∗ @return A l l O b j e c t s as A r r a y L i s t ∗/ 110 111 public A r r a y L i s t <WorldObject> g e t O b j e c t s ( ) { 112 113 return new A r r a y L i s t <WorldObject >( t h i s . o b j e c t s . v a l u e s ( ) ) ; } 114 115 /∗ ∗ 116 ∗ Returns w h e t h e r t h i s l o c a t i o n c o n t a i n s any i m p a s s a b l e o b j e c t s . 117 ∗ @return t r u e i f a l l o b j e c t s a r e p a s s a b l e , f a l s e o t h e r w i s e . 118 119 ∗/ public boolean i s P a s s a b l e ( ) { 120 A r r a y L i s t <WorldObject> wos = t h i s . g e t O b j e c t s ( ) ; 121 f o r ( WorldObject wo : wos ) { 122 i f ( ! wo . i s P a s s a b l e ) { 123 124 return f a l s e ; } 131 Kapitel D: Quelltexte 125 } 126 return true ; } 127 128 } Listing 17: WorldLocation.java D.13 WorldObject.java 1 /∗ ∗ 2 ∗ WorldObject . j a v a 3 ∗ A c l a s s t h a t r e p r e s e n t s the g e n e r a l f e a t u r e s of a l l WorldObjects . These 4 ∗ f e a t u r e s a r e t h e u n i q u e name o f an o b j e c t and t h e t y p e o f an o b j e c t . 5 ∗ 6 ∗ @author Marcus Teske 7 ∗/ 8 package r t d l ; 9 10 public c l a s s WorldObject { 11 12 private S t r i n g objectName ; 13 // WorldObject ’ s p r e d i c a t e s 14 protected boolean canMove = f a l s e ; 15 protected boolean i s G r i p p e a b l e = f a l s e ; 16 protected boolean i s P a s s a b l e = true ; 17 protected boolean i s C o n t a i n e r = f a l s e ; 18 protected boolean i s S o u r c e = f a l s e ; 19 20 /∗ ∗ 21 ∗ Get t h e name o f t h i s WorldObject . 22 ∗ @return The name o f t h i s o b j e c t . 23 ∗/ 24 public S t r i n g getObjectName ( ) { 25 26 return objectName ; } 27 28 /∗ ∗ 29 ∗ S e t s t h e name o f an WorldObject . 30 ∗ @param name The new name t o s e t . 31 32 33 ∗/ public void setObjectName ( S t r i n g name ) { t h i s . objectName = name ; 132 Kapitel D: Quelltexte 34 } 35 36 /∗ ∗ 37 ∗ Gets t h e c l a s s n a m e / t y p e o f t h i s WorldObject . 38 ∗ @return The ObjectType o f t h i s WorldObject as S t r i n g . 39 ∗/ 40 public S t r i n g getObjectType ( ) { 41 42 return t h i s . g e t C l a s s ( ) . getSimpleName ( ) ; } 43 44 /∗ ∗ 45 ∗ P l a c e h o l d e r method f o r moving i n s i d e t h e w o r l d . 46 ∗ @param w The w o r l d t h e a c t i o n t a k e s p l a c e i n . 47 ∗ @param x The x−c o o r d i n a t e o f t h e d e t i n a t i o n . 48 ∗ @param y The y−c o o r d i n a t e o f t h e d e t i n a t i o n . 49 ∗ @param z The z−c o o r d i n a t e o f t h e d e t i n a t i o n . 50 ∗ @return f a l s e 51 ∗/ 52 public boolean move ( World w, int x , int y , int z ) { i f ( ! t h i s . canMove ) { 53 54 System . e r r . p r i n t l n ( ”WARNING: A ” + t h i s . getObjectType ( ) 55 + ” cannot move ! ” ) ; } else { 56 57 System . e r r . p r i n t l n ( ”WARNING: Movement o f ” + t h i s . getObjectType ( ) 58 + ” not y e t implemented ! ” ) ; 59 } 60 return f a l s e ; 61 } 62 63 public WorldObject getArmPayload ( ) { 64 System . e r r . p r i n t l n ( ”WARNING: A ” + t h i s . getObjectName ( ) 65 + ” has no arm ! ” ) ; 66 67 return null ; } 68 69 /∗ ∗ 70 ∗ P l a c e h o l d e r method f o r f i l l i n g a c o n t a i n e r WorldObject w i t h a 71 ∗ content type . 72 ∗ @param c o n t e n t T y p e Type o f c o n t e n t t o f i l l t h e c o n t a i n e r w i t h . 73 ∗ @return f a l s e 74 ∗/ c e r t a i n# 75 76 public boolean f i l l C o n t a i n e r ( World w, S t r i n g contentType ) { i f ( ! this . isContainer ) { 133 Kapitel D: Quelltexte 77 System . e r r . p r i n t l n ( ”WARNING: A ” + t h i s . getObjectType ( ) 78 + ” i s not a c o n t a i n e r ! ” ) ; } else { 79 80 System . e r r . p r i n t l n ( ”WARNING: F i l l i n g o f ” + t h i s . getObjectType ( ) 81 + ” not y e t implemented ! ” ) ; 82 } 83 return f a l s e ; } 84 85 /∗ ∗ 86 87 ∗ P l a c e h o l d e r method f o r emptying a c o n t a i n e r WorldObject . 88 ∗ @return f a l s e 89 ∗/ public boolean emptyContainer ( ) { 90 i f ( ! this . isContainer ) { 91 92 System . e r r . p r i n t l n ( ”WARNING: A ” + t h i s . getObjectType ( ) 93 + ” i s not a c o n t a i n e r ! ” ) ; } else { 94 95 System . e r r . p r i n t l n ( ”WARNING: Emptying o f ” + t h i s . getObjectType ( ) 96 + ” not y e t implemented ! ” ) ; 97 } 98 return f a l s e ; } 99 100 public boolean g r i p ( World w, S t r i n g name ) { 101 102 return f a l s e ; } 103 104 public boolean u n g r i p ( World w, S t r i n g name ) { 105 106 return f a l s e ; } 107 108 } Listing 18: WorldObject.java D.14 WorldPosition.java 1 /∗ ∗ 2 ∗ WorldPosition . java 3 ∗ A W o r l d P o s i t i o n i s a P o i n t w i t h i n a World t h a t i s s p e c i f i e d by i t s x 4 ∗ z−c o o r d i n a t e i n a 3D c o o r d i n a t e system . 5 ∗ −, y− and 134 Kapitel D: Quelltexte 6 ∗ @author Marcus Teske 7 ∗/ 8 package r t d l ; 9 10 public c l a s s W o r l d P o s i t i o n { 11 12 private long x ; 13 private long y ; 14 private long z ; 15 16 /∗ ∗ 17 ∗ Constructor of WorldPosition . 18 ∗ @param x The x−c o o r d i n a t e . 19 ∗ @param y The y−c o o r d i n a t e . 20 ∗ @param z The z−c o o r d i n a t e . 21 ∗/ 22 public W o r l d P o s i t i o n ( long x , long y , long z ) { 23 this . x = x ; 24 this . y = y ; 25 this . z = z ; 26 } 27 28 /∗ ∗ ∗ Gets t h e d i s t a n c e from t h e o r i g i n a l o n g t h e x−a x i s o f t h i s 29 WorldLocation . 30 ∗ @return D i s t a n c e t o t h e o r i g i n a l o n g t h e x−a x i s . 31 ∗/ 32 public long getX ( ) { 33 34 return x ; } 35 36 /∗ ∗ ∗ S e t s t h e d i s t a n c e from t h e o r i g i n a l o n g t h e x−a x i s o f t h i s 37 WorldLocation . ∗/ 38 39 public void setX ( long x ) { 40 41 this . x = x ; } 42 43 44 /∗ ∗ ∗ Gets t h e d i s t a n c e from t h e o r i g i n a l o n g t h e y−a x i s o f t h i s WorldLocation . 45 ∗ @return D i s t a n c e t o t h e o r i g i n a l o n g t h e y−a x i s . 46 ∗/ 135 Kapitel D: Quelltexte 47 public long getY ( ) { 48 49 return y ; } 50 51 /∗ ∗ ∗ S e t s t h e d i s t a n c e from t h e o r i g i n a l o n g t h e y−a x i s o f t h i s 52 WorldLocation . ∗/ 53 54 public void setY ( long y ) { 55 56 this . y = y ; } 57 58 /∗ ∗ ∗ Gets t h e d i s t a n c e from t h e o r i g i n a l o n g t h e z−a x i s o f t h i s 59 WorldLocation . 60 ∗ @return D i s t a n c e t o t h e o r i g i n a l o n g t h e z−a x i s . 61 ∗/ 62 public long getZ ( ) { 63 64 return z ; } 65 66 /∗ ∗ ∗ S e t s t h e d i s t a n c e from t h e o r i g i n a l o n g t h e z−a x i s o f t h i s 67 WorldLocation . ∗/ 68 69 public void s e t Z ( long z ) { 70 71 this . z = z ; } 72 73 public long g e t O f f s e t X ( W o r l d P o s i t i o n wp) { return wp . getX ( ) − t h i s . getX ( ) ; 74 75 } 76 77 public long g e t O f f s e t Y ( W o r l d P o s i t i o n wp) { return wp . getY ( ) − t h i s . getY ( ) ; 78 79 } 80 81 public long g e t O f f s e t Z ( W o r l d P o s i t i o n wp) { return wp . getZ ( ) − t h i s . getZ ( ) ; 82 83 } 84 85 86 87 public boolean e q u a l s ( W o r l d P o s i t i o n wp) { return ( t h i s . getX ( ) == wp . getX ( ) && t h i s . getY ( ) == wp . getY ( ) && t h i s . getZ ( ) == wp . getZ ( ) ) ; 136 Kapitel D: Quelltexte } 88 89 } Listing 19: WorldPosition.java D.15 fetchWater.xml 1 <?xml v e r s i o n=” 1 . 0 ” e n c o d i n g=”UTF−8”?> 2 <?xml−s t y l e s h e e t type=” t e x t /xml” h r e f=” r t d l . x s l ” v e r s i o n=” 1 . 0 ”?> 3 <r t d l v e r s i o n=” 1 . 0 ”> 4 5 <t a s k name=” f e t c h W a t e r ”> <t a s k a r g s > 6 <var type=” D r i n k i n g G l a s s ”>Glass1 </var> 7 <var type=”Tap”>Tap1</var> 8 </ t a s k a r g s > 9 <e n t i t i e s > 10 <var type=” Waypoint ”>s t a r t </var> 11 </ e n t i t i e s > 12 <blo ck > 13 <a c t i o n > 14 <name>s e t C u r r e n t P o s i t i o n </name> 15 <a r g s > 16 <arg>S t a r t </arg> 17 </a r g s > 18 </a c t i o n > 19 <a c t i o n > 20 <name>move</name> 21 <a r g s > 22 <arg>Glass1 </arg> 23 </a r g s > 24 </a c t i o n > 25 <a c t i o n > 26 <name>g r i p </name> 27 <a r g s > 28 <arg>Glass1 </arg> 29 </a r g s > 30 </a c t i o n > 31 <a c t i o n > 32 <name>move</name> 33 <a r g s > 34 <arg>Tap1</arg> 35 </a r g s > 36 </a c t i o n > 137 Kapitel D: Quelltexte 37 <a c t i o n > 38 <name>ungrip </name> 39 <a r g s > 40 <arg>Glass1 </arg> 41 </a r g s > 42 </a c t i o n > 43 <a c t i o n > 44 <name> f i l l </name> 45 <a r g s > 46 <arg>Tap1</arg> 47 <arg>Glass1 </arg> 48 </a r g s > 49 </a c t i o n > 50 <a c t i o n > 51 <name>g r i p </name> 52 <a r g s > 53 <arg>Glass1 </arg> 54 </a r g s > 55 </a c t i o n > 56 <a c t i o n > 57 <name>move</name> 58 <a r g s > 59 <arg>S t a r t </arg> 60 </a r g s > 61 </a c t i o n > 62 <a c t i o n > 63 <name>ungrip </name> 64 <a r g s > 65 <arg>Glass1 </arg> 66 </a r g s > 67 </a c t i o n > 68 69 </bloc k > </task > 70 </ r t d l > Listing 20: fetchWater.xml D.16 rtdl.xsl 1 <?xml v e r s i o n=” 1 . 0 ” e n c o d i n g=”UTF−8”?> 2 <x s l : s t y l e s h e e t 3 v e r s i o n=” 2 . 0 ” 4 xmlns : x s l=” h t t p : / /www. w3 . o r g /1999/XSL/ Transform ” 138 Kapitel D: Quelltexte 5 xmlns : w=” h t t p : / / w i z z a r d . dyndns . i n f o ” 6> 7 <x s l : output method=” html ” i n d e n t=” y e s ”/> 8 9 <!−− This s t y l e s h e e t t r a n s f o r m s t h e xml r e p r e s e n t a t i o n o f an d e f i n e d RTDL t a s k 10 i n t o i t the f u n c t i o n a l syntax . 11 Author : Marcus Teske 12 Date : 2011−01−11 13 −−> 14 15 <!−− S t a r t s t h e t r a n s f o r m a t i o n . −−> 16 <x s l : t e m p l a t e match=” / ”> 17 18 <html> <head> 19 < t i t l e ><x s l : v alue −o f s e l e c t=” / r t d l / t a s k /@name”/></ t i t l e > 20 <s t y l e > 21 p { 22 margin− l e f t : 2em ; 23 f o n t −f a m i l y : monospace ; f o n t −s i z e : 12 px ; 24 25 } 26 p . root { 27 margin− l e f t : 0em ; } 28 29 </ s t y l e > 30 </head> 31 <body> 32 33 34 35 <x s l : apply−t e m p l a t e s /> </body> </html> </ x s l : template > 36 37 <!−− C r e a t e t h e ” r t d l <v e r s i o n >” l i n e . −−> 38 <x s l : t e m p l a t e match=” r t d l ”> 39 40 41 <p c l a s s=” r o o t ”> <x s l : t e x t >r t d l </ x s l : t e x t > <x s l : v alue −o f s e l e c t=” @ v e r s i o n ”/> 42 </p> 43 <x s l : apply−t e m p l a t e s/> 44 </ x s l : template > 45 46 <!−− Transforms t h e comment e l e m e n t s . −−> 47 <x s l : t e m p l a t e match=”comment”> 139 Kapitel D: Quelltexte 48 <p c l a s s=” r o o t ”> 49 <x s l : t e x t >/∗ </ x s l : t e x t > 50 < x s l : v a l u e −o f s e l e c t =”.”/> 51 < x s l : t e x t > ∗/</ x s l : t e x t > 52 53 </p> </ x s l : template > 54 55 <!−− C r e a t e s t h e s i g n a t u r e o f t h e d e f i n e d t a s k . −−> 56 <x s l : t e m p l a t e match=” t a s k ”> 57 <p c l a s s=” r o o t ”> 58 <x s l : v alue −o f s e l e c t=”@name”/> 59 <x s l : t e x t >(</ x s l : t e x t > 60 <x s l : for−each s e l e c t=” t a s k a r g s / var ”> 61 <x s l : v alue −o f s e l e c t=” @type ”/> 62 <x s l : t e x t > </ x s l : t e x t > 63 <x s l : apply−t e m p l a t e s/> 64 <x s l : i f t e s t=” not ( p o s i t i o n ( )=l a s t ( ) ) ”> 65 66 <x s l : t e x t >, </ x s l : t e x t > </ x s l : i f > 67 </ x s l : for−each> 68 <x s l : t e x t >) {</ x s l : t e x t > 69 <br/> 70 <x s l : apply−t e m p l a t e s s e l e c t=” r e t r y c o u n t ”/> 71 <br/> 72 <x s l : apply−t e m p l a t e s s e l e c t=” e n t i t i e s ”/> 73 <br/> 74 <x s l : apply−t e m p l a t e s s e l e c t=” b l o c k ” /> 75 <br/> 76 <x s l : t e x t >}</ x s l : t e x t > 77 78 </p> </ x s l : template > 79 80 <!−− C r e a t e comma s e p a r a t e d l i s t o f arguments and t h e i r t y p e s . −−> 81 <x s l : t e m p l a t e match=” a r g s ”> 82 83 <x s l : for−each s e l e c t=” var ”> <x s l : v alue −o f s e l e c t=” @type ”/> 84 <x s l : t e x t > </ x s l : t e x t > 85 <x s l : apply−t e m p l a t e s/> 86 <x s l : i f t e s t=” not ( p o s i t i o n ( )=l a s t ( ) ) ”> 87 88 89 90 <x s l : t e x t >, </ x s l : t e x t > </ x s l : i f > </ x s l : for−each> </ x s l : template > 91 140 Kapitel D: Quelltexte 92 <!−− C r e a t e comma s e p a r a t e d l i s t o f arguments w i t h o u t t h e i r t y p e s . −−> 93 94 <x s l : t e m p l a t e match=” a r g s ”> <x s l : for−each s e l e c t=” var ”> 95 <x s l : apply−t e m p l a t e s/> 96 <x s l : i f t e s t=” not ( p o s i t i o n ( )=l a s t ( ) ) ”> 97 <x s l : t e x t >, </ x s l : t e x t > 98 99 100 </ x s l : i f > </ x s l : for−each> </ x s l : template > 101 102 <!−− Transforms t h e r e t r y c o u n t e l e m e n t . −−> 103 <x s l : t e m p l a t e match=” r e t r y c o u n t ”> 104 <p> 105 <x s l : t e x t >r e t r y c o u n t (</ x s l : t e x t > 106 <x s l : v alue −o f s e l e c t=” . ”/> 107 <x s l : t e x t >);</ x s l : t e x t > 108 109 </p> </ x s l : template > 110 111 <!−− C r e a t e f o r each e n t i t y a l i n e ” e n t i t y <type> <name>;” . −−> 112 <x s l : t e m p l a t e match=” e n t i t i e s ”> 113 <x s l : for−each s e l e c t=” var ”> 114 <p> 115 <x s l : t e x t >e n t i t y </ x s l : t e x t > 116 <x s l : v alue −o f s e l e c t=” @type ”/> 117 <x s l : t e x t > </ x s l : t e x t > 118 <x s l : apply−t e m p l a t e s/> 119 <x s l : t e x t >;</ x s l : t e x t > 120 121 122 </p> </ x s l : for−each> </ x s l : template > 123 124 <!−− Transforms b lock −e l e m e n t s . −−> 125 <x s l : t e m p l a t e match=” b l o c k ”> 126 <x s l : apply−t e m p l a t e s s e l e c t=” a c t i o n ”/> 127 <x s l : apply−t e m p l a t e s s e l e c t=” w h i l e ”/> 128 <x s l : apply−t e m p l a t e s s e l e c t=” i f ”/> 129 <x s l : apply−t e m p l a t e s s e l e c t=” par ”/> 130 </ x s l : template > 131 132 <!−− Transforms r e t r y −e l e m e n t s . −−> 133 <x s l : t e m p l a t e match=” r e t r y ”> 134 <p> 141 Kapitel D: Quelltexte 135 <x s l : t e x t >r e t r y (</ x s l : t e x t > 136 <x s l : v alue −o f s e l e c t=” @count ”/> 137 <x s l : t e x t >)</ x s l : t e x t > 138 <x s l : apply−t e m p l a t e s/> 139 <x s l : t e x t >endtry </ x s l : t e x t > 140 </p> 141 </ x s l : template > 142 143 <!−− t r a n s f o r m s a c t i o n s t o a f u n c t i o n c a l l . −−> 144 <x s l : t e m p l a t e match=” a c t i o n ”> 145 <p> 146 <x s l : i f t e s t=” @ o p t i o n a l =’ t r u e ’ ”> 147 <x s l : t e x t >o p t i o n a l </ x s l : t e x t > 148 </ x s l : i f > 149 <x s l : v alue −o f s e l e c t=”name”/> 150 <x s l : t e x t >(</ x s l : t e x t > 151 <x s l : for−each s e l e c t=” a r g s / a r g ”> 152 <x s l : apply−t e m p l a t e s/> 153 <x s l : i f t e s t=” not ( p o s i t i o n ( )=l a s t ( ) ) ”> 154 <x s l : t e x t >, </ x s l : t e x t > 155 </ x s l : i f > 156 </ x s l : for−each> 157 <x s l : apply−t e m p l a t e s s e l e c t=” a r g s ”/> 158 <x s l : t e x t >);</ x s l : t e x t > 159 160 </p> </ x s l : template > 161 162 <!−− Transforms while−b l o c k s . −−> 163 <x s l : t e m p l a t e match=” w h i l e ”> 164 <p> 165 <x s l : t e x t >while</ x s l : t e x t > 166 <x s l : t e x t >(</ x s l : t e x t > 167 <x s l : apply−t e m p l a t e s s e l e c t=” cond ”/> 168 <x s l : t e x t >)</ x s l : t e x t > 169 <br/> 170 <x s l : t e x t >do</ x s l : t e x t > 171 <x s l : apply−t e m p l a t e s s e l e c t=” b l o c k ”/> 172 173 174 <x s l : t e x t >done</ x s l : t e x t > </p> </ x s l : template > 175 176 <!−− Transforms c o n d i t i o n o f a while b l o c k a s i s . −−> 177 <x s l : t e m p l a t e match=” cond ”> 178 <x s l : v alue −o f s e l e c t=” . ”/> 142 Kapitel D: Quelltexte 179 </ x s l : template > 180 181 <!−− Transforms i f −b l o c k . −−> 182 <x s l : t e m p l a t e match=” i f ”> 183 <p> 184 <x s l : t e x t >i f </ x s l : t e x t > 185 <x s l : t e x t >(</ x s l : t e x t > 186 <x s l : apply−t e m p l a t e s s e l e c t=” cond ”/> 187 <x s l : t e x t >)</ x s l : t e x t > 188 <br/> 189 <x s l : apply−t e m p l a t e s s e l e c t=” b l o c k ”/> 190 191 192 <x s l : t e x t >e n d i f </ x s l : t e x t > </p> </ x s l : template > 193 194 <!−− Transforms par−b l o c k s . −−> 195 <x s l : t e m p l a t e match=” par ”> 196 <p> 197 <x s l : t e x t >par </ x s l : t e x t > 198 <br/> 199 <x s l : apply−t e m p l a t e s s e l e c t=” b l o c k ”/> 200 <x s l : t e x t >to </ x s l : t e x t > 201 <br/> 202 <x s l : apply−t e m p l a t e s s e l e c t=” b l o c k 2 ”/> 203 <x s l : t e x t >endpar </ x s l : t e x t > 204 205 </p> </ x s l : template > 206 207 <!−− Transforms f i r s t b l o c k o f par . −−> 208 <x s l : t e m p l a t e match=” b l o c k 1 ”> 209 210 <x s l : apply−t e m p l a t e s/> </ x s l : template > 211 212 <!−− Transforms s e c o n d b l o c k o f par . −−> 213 <x s l : t e m p l a t e match=” b l o c k 2 ”> 214 215 <x s l : apply−t e m p l a t e s/> </ x s l : template > 216 217 </ x s l : s t y l e s h e e t > Listing 21: rtdl.xsl D.17 rtdl.dtd 143 Kapitel D: Quelltexte 1 <!−− RTDL v1 . 0 Document Type D e f i n i t i o n −−> 2 3 <!ELEMENT r t d l ( comment ∗ , task , comment ∗ )> 4 <!ATTLIST r t d l 5 v e r s i o n CDATA #REQUIRED 6> 7 <!ELEMENT comment (#PCDATA)> 8 <!ELEMENT t a s k ( comment ∗ , 9 taskargs , 10 comment ∗ , 11 retrycount ? , 12 comment ∗ , 13 entities , 14 comment ∗ , 15 b lock , 16 comment∗ 17 )> 18 <!ATTLIST t a s k 19 name CDATA #REQUIRED 20 > 21 <!ELEMENT t a s k a r g s ( var | comment )∗> 22 <!ELEMENT var (#PCDATA)> 23 <!ATTLIST var 24 type CDATA #REQUIRED 25 > 26 <!ELEMENT r e t r y c o u n t (#PCDATA)> 27 <!ELEMENT e n t i t i e s ( var | comment )∗> 28 <!ELEMENT b l o c k ( a c t i o n | par | i f | while | r e t r y | comment )∗> 29 <!ELEMENT a c t i o n ( comment ∗ , name , comment ∗ , a r g s ? , comment ∗ )> 30 <!ATTLIST a c t i o n 31 o p t i o n a l CDATA #IMPLIED 32 > 33 <!ELEMENT name (#PCDATA)> 34 <!ELEMENT a r g s ( a r g | comment )∗> 35 <!ELEMENT a r g (#PCDATA)> 36 <!ELEMENT par ( b lock , b l o c k 2 )> 37 <!ELEMENT i f ( cond , b l o c k )> 38 <!ELEMENT cond (#PCDATA)> 39 <!ELEMENT while ( cond , b l o c k )> 40 <!ELEMENT r e t r y ( b l o c k )> 41 <!ATTLIST r e t r y 42 count CDATA #REQUIRED 43 > 144 Kapitel D: Quelltexte Listing 22: rtdl.dtd D.18 example.xml 1 <?xml v e r s i o n=” 1 . 0 ” e n c o d i n g=”UTF−8”?> 2 <?xml−s t y l e s h e e t type=” t e x t /xml” h r e f=” r t d l . x s l ” v e r s i o n=” 1 . 0 ”?> 3 4 <!DOCTYPE r t d l SYSTEM ” r t d l . dtd ”> 5 6 <r t d l v e r s i o n=” 1 . 0 ”> 7 <comment>This i s a comment.</comment> 8 <t a s k name=” exampleTask ”> 9 <t a s k a r g s > 10 <var type=” F i r s t A r g ”>a1</var> 11 <var type=” SecondArg ”>a2</var> 12 </ t a s k a r g s > 13 <r e t r y c o u n t >3</r e t r y c o u n t > 14 <e n t i t i e s > 15 <var type=” E n t i t y ”>e n t i t y 1 </var> 16 <var type=” E n t i t y ”>e n t i t y 2 </var> 17 <var type=” E n t i t y ”>e n t i t y 3 </var> 18 </ e n t i t i e s > 19 <blo ck > 20 <a c t i o n > 21 <name>Task1</name> 22 <a r g s > 23 <arg>e n t i t y 1 </arg> 24 <arg>e n t i t y 2 </arg> 25 <arg>e n t i t y 3 </arg> 26 </a r g s > 27 </a c t i o n > 28 <a c t i o n > 29 <name>Task2</name> 30 <a r g s > 31 <arg>e n t i t y 1 </arg> 32 <arg>e n t i t y 2 </arg> 33 <arg>e n t i t y 3 </arg> 34 </a r g s > 35 </a c t i o n > 36 <while> 37 <cond>c o n d i t i o n 1 </cond> 145 Kapitel D: Quelltexte 38 39 <blo ck > <a c t i o n > 40 <name>Task3</name> 41 <a r g s > 42 <arg>e n t i t y 1 </arg> 43 </a r g s > 44 </a c t i o n > 45 </bloc k > 46 </while> 47 <i f > 48 <cond>c o n d i t i o n 2 </cond> 49 <blo ck > 50 <a c t i o n > 51 52 53 <name>Task4</name> </a c t i o n > </bloc k > 54 </ i f > 55 <par> 56 57 58 <blo ck > <a c t i o n > <name>Task5</name> 59 </a c t i o n > 60 <par> 61 <blo ck > 62 <a c t i o n > 63 <name>Task6</name> 64 </a c t i o n > 65 </bloc k > 66 <blo ck > 67 <a c t i o n > 68 <name>Task7</name> 69 70 </a c t i o n > </bloc k > 71 </par> 72 </bloc k > 73 <blo ck > 74 75 76 77 <a c t i o n > <name>Task8</name> </a c t i o n > </bloc k > 78 </par> 79 <r e t r y count=” 5 ”> 80 81 <blo ck > <a c t i o n o p t i o n a l=” t r u e ”> 146 Kapitel D: Quelltexte 82 <name>o p t i o n a l T a s k </name> 83 </a c t i o n > 84 85 86 87 </bloc k > </ r e t r y > </bloc k > </task > 88 </ r t d l > Listing 23: example.xml 147 LITERATUR Literatur [Bud09] Budde, Henning: Wissensakquisition und maschinelle Task-Generierung für einen virtuellen Küchenroboter. , Fachhochschule Köln, 2009. Masterthesis. [Cok10] CokeRob: Ein Blickfang am Tag der offenen Tür 2004, Aufruf: 9. November 2010. http://www.nt-rt.fh-koeln.de/News/n006.html. [Erd09] Erdmann, Ralph: Steuerung eines autonom fahrenden Roboters auf der Basis von RFID-Positionsmarken und Richtungsinformationen. , Fachhochschule Köln, 2009. Bachelorthesis. [Hol10] Holz, Dirk: Effiziente Kartopraghie und Navigation für mobile Service Roboter. Informatik Spektrum, 04/2010. Springer Verlag. [JAU05] JAUS WG: JAUS Volume I: Domain Model, 20. März 2005. v3.2. [JAU06] JAUS WG: JAUS Compliance Specification, 26. Oktober 2006. v3.2. [JAU07a] JAUS WG: JAUS Volume II: Reference Architecture: Part 1 Architecture Framework, 27. Juni 2007. v3.3. [JAU07b] JAUS WG: JAUS Volume II: Reference Architecture: Part 2 Message Definition, 27. Juni 2007. v3.3. [JAU07c] JAUS WG: JAUS Volume II: Reference Architecture: Part 3 Message Set, 27. Juni 2007. v3.3. [McD11] McDermott, Drew V.: Planning Domain Definition Language, Aufruf: 11. Januar 2011. http://cs-www.cs.yale.edu/homes/dvm/. [MT10] Moritz Ternorth, Dominik Jain, Michael Beetz: Knowledge Processing for Cognitive Robots. Künstliche Intelligenz, Nr. 24:233–240, 2010. [Rob11] RoboCup, Aufruf: 11. Januar 2011. http://www.robocup.org. [SV03] Spyros Vosinakis, Themis Panayiotopoulos: A Task Definition Language for Virtual Agents. , Universität von Piräus, Griechenland, 2003. http://wscg.zcu.cz/wscg2003/Papers_2003/D03.pdf. [Tes10] Teske, Marcus: The Joint Architecture for Unmanned Systems (JAUS): Eine Übersicht. v1.1, 3. Juni 2010. 148 LITERATUR [Wik10] Wikipedia Enzyklopädie: American Standard Code for Information Interchange, Aufruf: 2. Dezember 2010. http://de.wikipedia. org/w/index.php?title=American_Standard_Code_for_Information_ Interchange&oldid=82181574. 149