Im Folgenden der generelle Aufbau einer solchen RCX-Datei. Beim Erstellen eigener Roboter, kann sie als Schablone benutzt werden. Die einzelnen Tags werden im Anschluss erläutert.
<?xml version="1.0" encoding="UTF-8"?> Definition der XML-Datei. Bei allen Dateien identisch. <WorldObject ...> <Motor .../> Definition der Motoren <Sensor .../> Sensorenbeschreibung (verschiedene Tags) |
In folgenden Erläuterungen bezeichnet %lms-home% das LMS-Stammverzeichnis
(z.B. C:\Programme\lms).
Im Beispiel legen wir einen Roboter mit dem Namen myRCX.xml in dem Ordner
%lms-home%/scenario/myScenario an.
Der xml-Tag definiert die XML-Datei. Er ist bei allen Umgebungen identisch.
<?xml version="1.0" encoding="UTF-8"?> |
Bei diesem Eintrag beginnt die Definition eines RCX-Roboters. Es wird ein
Name für den Roboter festgelegt und um den korrekten Aufbau der XML-Datei
zu definieren, wird auf eine xsd-Datei (xsd=XML Schema Definition) eingebunden.
Dies sieht wie folgt aus:
<RCX Name=“MyRCX“ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="RCX.xsd">
Die xsd-Datei (RCX.xsd) findet man im Verzeichnis %lms-home%/config/RCX. Wenn
Sie Ihre RCX-Datei in diesem Verzeichnis ablegen, können Sie den RCX-Tag,
wie er oben angegeben ist, genau so übernehmen. Falls Ihre Umgebungsdatei
in einem anderen Ordner liegt, können Sie entweder die Datei „RCX.xsd“
in diesen Ordner kopieren oder einen relativen Pfad (von der RCX-Datei aus)
auf die Schema-Definition anlegen. Im letzten Fall sieht die Szene-Definition
wie folgt aus:
<RCX Name="Linienverfolger" |
Der RCX-Tag wird am Ende der Datei wieder geschlossen:
</RCX> |
Die WorldObjects fassen einzelne Teile des Roboters zusammen und legen mit dem Parameter „UseCollisionDetection“ das Kollisionsverhalten fest. In den WorldObjects sind verschiedene TransformGroups (s.u.) eingebettet.
Die eigentlichen Teile eines Roboters (Definiert durch den Tag <Box ...>) werden in einer ChildTransformGroup eingebettet. Diese wiederum unterliegt einer ParentTransformGroup, welche wiederum Bestandteil eines WoldObjects ist. Hier nun zunächst ein Beispiel für eine gelbe Box in der Mitte des Untergrundes. Sie soll einen einfachen Roboter darstellen. Der Mittelpunkt dieses Roboters liegt 5cm über dem Boden.
<WorldObject UseCollisionDetection="true"> |
Die einzelnen Parmeter des Box-Tags stellen die Breite, Länge und Höhe sowie die Farbe des Roboters dar. Deutlich komplizierter sind dagegen die 4x4 Matrizen, die in den ChildTransformGroups definiert werden. Mit Hilfe dieser Matrizen können die Boxen positioniert und gedreht werden.
In dem Tutorial „Lego Minstorms Simulator – Erstellen von Umgebungen“ ist beschrieben, welche Veränderungen vorgenommen werden müssen, um Boxen zu verschieben und zu drehen.
Motoren werden durch einen Motor-Tag definiert. Er beschreibt, an welchem
Anschluss des RCX der Motor angeschlossen ist (A, B oder C). Außerdem wird
ein Kraftvektor definiert. Die Kraft des Motors wirkt in die Richtung dieses
Vektors.
In unserem Beispiel haben wir einen einfachen Roboter mit zwei Motoren, die
unter dem RCX befestigt sind und an denen jeweils ein Antriebsrad aufgesteckt
ist:
... |
Bemerkenswert sind hierbei die Kraftvektoren der beiden Motoren. Wie man deutlich sieht, arbeiten ihre Kräfte nicht ausschließlich in Richtung der Fahrtrichtung des Roboters, sondern entgegengesetzt diagonal (Bild 1).
![]() |
![]() |
Bild 1 |
Bild 2 |
Dieser seltsame Aufbau der Kraftvektoren lässt sich einfach veranschaulichen.
Zum einen liegen die Motoren direkt gegenüber. Wenn beiden Motoren das Kommando
„vorwärts“ gegeben wird, so bewegt sich ein Rad in Richtung der
y-Achse, das andere Rad aber entgegengesetzt (da ja beide Motoren links herum
drehen). Zum vorwärts fahren muss Motor B also rückwärts drehen. Dadurch bekommt
er den Kraftvektor, der in Bild 2 zu sehen ist. (Anmerkung: In der Realität
wird dieses Problem umgangen, indem man die Motoranschlüsse umdreht)
Sind beide Motoren eingeschaltet, so heben sich die x-Komponenten der Vektoren
auf und der RCX bewegt sich nach vorn. Ist jedoch nur einer der Motoren aktiv,
verändert sich in der Realität auch die Bewegungsrichtung in der x-Achse.
Um dies zu simulieren haben die beiden Motoren eine zusätzliche Kraft in x-Richtung.
Allein durch diese Kräfte wird allerdings noch nicht die Drehung des Roboters
beschrieben.
Mit dem MotorConnector-Tag verbinden wir nun die beiden Roboter, damit auch
die Drehung des Roboters richtig simuliert wird. Der Tag hat 7 Parameter.
Die ersten beiden Parameter geben die beiden beteiligten Motor-Objekte an.
Die folgenden 3 Parameter geben die Richtung an, in die sich der Roboter bewegt,
wenn sich beide Motoren bewegen. In unserem Fall ist dies die y-Richtung.
Die letzten beiden Parameter geben die Übersetzung des angeschlossenen Rades
(abhängig von Radgröße, Getriebe) und den Lenkfaktor an. Dieser hat direkten
Einfluss darauf, wie schnell sich der Roboter dreht (abhängig davon, wie weit
die Räder auseinander stehen).
... |
Damit ist unser erster Roboter fast fertig. Wir müssen uns nur noch um seine Programmierung kümmern.
Um ein Programm einzubinden, wird der Lejos-Tag benutzt. In diesem Lejos-Tag
wird mit dem Tag „JarFilename“die Jar-Datei eingebunden, die das
Programm enthält. Sie wird nach dem Kompilieren unkomprimiert erzeugt und
muss eine Manifest-Datei beinhalten, die auf die Klasse mit der Main-Funktion
referiert.
Beispiel: Im Verzeichnis %lms-home%/scenario/myScenario liegt eine Datei MyRobot.java
und einige weitere Klassen. Die „MyRobot“-Klasse hat die Main-Funktion.
Im gleichen Verzeichnis liegt die Manifest-Datei manifest.txt mit folgendem
Inhalt:
Manifest-Version: 1.0 |
Das Kompilieren und erzeugen der Jar-Datei erfolgt durch folgende Aufrufe:
lejosc *.java |
Es ist darauf zu achten, dass die bin-Verzeichnisse von Java und von Lejos
in der Umgebungsvariable “Path” stehen.
In unserem Beispiel wird die so erzeugte Jar-Datei nun wie folgt eingebunden:
<Lejos enable="true"> |
Der angegebene Pfad zu der Jar-Datei ist auch hier relativ zum lms-Hauptverzeichnis.
Damit ist unser erster kleiner Roboter fertig. Er hat zwei Motoren (A und
B) und kann sich in einer Umgebung bewegen - jedoch nicht mit ihr interagieren.
Berührungssensoren bieten eine einfache Möglichkeit, den Zusammenstoß des
Roboters mit einem Hindernis aus der Umgebung oder mit einem anderen Roboter
zu erfassen. Kollisionen werden unter allen Weltobjekten wahrgenommen, die
mit dem Attribut UseCollisionDetection="true" definiert sind.
Wenn ein Roboter mit einer Wand in der Simulation kollidiert bleibt er stehen
und bleibt darin stecken. Ist die Umgebung des Roboters z.B. durch eine Wand
begrenzt oder weist Hindernisse auf, so kann man diese Kollisionen mit einem
Berührungssensor wahrnehmen und darauf reagieren.
![]() ![]() |
![]() |
Die zwei Berührungssensoren von LEGO |
Beispielroboter mit Berührungssensor |
Hier die typische Definition eines Berührungssensors:
<TouchSensor Connection="B"> |
Wie man sieht, wird der Sensor durch den TouchSensor-Tag eingeleitet. In
dem Tag wird der benutzte Anschluss definiert. Dabei stehen die Anschlüsse
„A“, „B“ und „C“ in der Definition für
die Sensoranschlüsse „1“, „2“ und „3“
des RCX-Bausteins.
Nun wird ein Weltobjekt mit CollisionDetection erstellt, in dem sich eine
ParentTransformGroup befindet. Sie legt die Lage des Berührungssensors fest.
Es folgt eine ChildTransformGroup, in der der eigentliche Sensor (bzw. das
technische Konstrukt, mit dem der Sensor verbunden ist) definiert wird.
In dem Beispiel wird eine schmale Box oberhalb des bisherigen Roboters definiert.
Sie entspricht der schwarzen Stange auf dem Bild mit dem Beispielroboter.
Achtung: Die Box-Objekte der Berührungssensoren müssen frei schwebend sein.
Sie dürfen kein anderes Objekt mit Collisiondetection berühren, auch nicht
den Roboter selbst oder den Untergrund.
Lichtsensoren, die auf den Boden gerichtet sind, können die Untergrundhelligkeit
erfassen. Sie werden durch den FloorLightSensor-Tag definiert, der als Parameter
einen Anschluss hat (wie beim Berührungssensor). Auch er beinhaltet ein WorldObject,
das eine ParentTransformGroup, eine ChildTransformGroup und eine Box hat.
Eine typische Leichtsensordefinition sieht wie folgt aus:
<FloorLightSensor Connection="A"> |
Der Aufbau ist also ganz analog zu dem Aufbau des Berührungssensors.
In unserem Beispiel liegt der Lichtsensor zwischen Berührungssensor und RCX
und hat eine blaue Farbe.
Mit den bisher beschriebenen Konstrukten sind die meist genutzten Arten von Robotern abgedeckt. Zwar können mit dem LMS nicht sämtliche Arten von Robotern simuliert werden, aber einige weitere Möglichkeiten stehen dem Benutzer zur Verfügung. Die wichtigsten werden nun kurz beschrieben.
Oft kann es sich als hilfreich erweisen, die Motorumdrehungen mit Hilfe von
Rotationssensoren (nicht im Baukasten enthalten) zu erfassen. So wird zum
Beispiel in der Fallstudie Hochregallager die Position des Regalbediengerätes
mit Hilfe von Rotationssensoren gesteuert.
Ein Rotationssensor wird mit dem RotationSensor-Tag definiert. Mit dem LinearMotorConnector
können Motoren an Rotationssensoren gekoppelt werden. Das folgende Beispiel
ist ein gekürzter Ausschnitt aus dem Regalbediengerätes der Fallstudie Hochregallager
und wird später aufgegriffen, um die Schachtelung motorgesteuerter Teilsysteme
zu erläutern:
<Motor Connection="A" ForceX="1" ForceY="1" ForceZ="0" GearFactor="1"/> |
Wie man erkennt, hat der LinearMotorConnector die Parameter „Name“
(für Debug-Ausgaben), Motor und RotationSensor.
Der Parameter „Rotationssensor“ beschreibt den Faktor zwischen
der Motorumdrehung und den Werten des Rotationssensors. Dadurch wird eine
Über- oder Untersetzung zwischen der Motorachse und der Achse des Rotationssensors
modelliert. Je größer dieser Faktor ist, desto höhere Werte liefert der Sensor.
Durch einen negativen Faktor wird die Drehrichtung des Sensors umgedreht.
Der Standardwert beträgt 1.
Das Attribut „MovementSpeed“ beschreibt den Faktor zwischen der
Motorgeschwindigkeit und der daraus resultierenden Geschwindigkeit der Plattform.Dadurch
wird ebenfalls eine Über- oder Untersetzung modelliert. Je größer dieser Faktor
ist, desto schneller bewegt sich die Plattform. Durch einen negativen Faktor
wird die Bewegungsrichtung umgedreht. Der Standardwert beträgt 1. Die Bewegungsgeschwindigkeit
hat keine Auswirkungen auf die vom Rotationssensor erzeugten Werte, da diese
nur von der Geschwindigkeit des Motors abhängen.
Am Beispiel von oben kann man deutlich die Schachtelung der Teilsysteme „Schlitten“
(Slide) und „Lift“ erkennen. Bewegt sich der Schlitten, so bewegt
sich auch der Lift. Daher ist der LinearMotorConnector des Lifts in dem des
Schlittens eingebettet.
Der LinearMotorConnector beinhaltet dabei immer einen Beam-Tag. Er stellt
die Schnittstelle zwischen den Systemen dar. In der Fallstudie Hochregallager
fallen diese Beams sehr gut durch ihre grüne Farbe auf (gut zu erkennen in
Kameraperspektive 4). Die Ausrichtung der Beams (in der ParentTransferGroup)
gibt dabei die Bewegungsrichtung an. Sie müssen also korrekt rotiert werden
(siehe auch Tutorial „Lego Minstorms Simulator – Erstellen von
Umgebungen“). Die Platform-Tags definieren die eigentlichen Teilsysteme.
In diesem Tutorial haben wir gelernt, einen einfachen Roboter mit zwei Antriebsmotoren,
Berührungs- und Lichtsensoren auszustatten und ihn mit der LeJOS-Bibliothek
und mit LeJOS-Programmen zu verknüpfen.
Weiterhin wurden Rotationssensoren sowie die Schachtelung von Teilsystemen
anhand der Fallstudie Hochregallager erläutert.
Die komplette RCX-Datei „myRCX.xml“.
<?xml version="1.0" encoding="UTF-8"?> <RCX Name="Linienverfolger" <WorldObject UseCollisionDetection="true"> <Motor Connection="A" ForceX="1" ForceY="1" ForceZ="0"/> <TouchSensor Connection="B"> <FloorLightSensor Connection="A"> <Lejos enable="true"> </RCX> |