Creating virtual RCX robots

Creating virtual RCX robots

A virtual RCX-robot of the LMS gets defined by a file in the XML format. In this file, there are described information about the measurements, the behaviour in case of collision, the motor/sensor-relations and the programming of the robots. This Tutorial focuses on creating a simple robot with 2 driving motors. This robot gets completed with 2 light sensors and one touch sensor. Finally, additional possible elements get explained.

Below the general structure of such a RCX file. You can use it as a pattern while creating your own robots. The particular tags will be explained below.

<?xml version="1.0" encoding="UTF-8"?>  Definition of the XML file. Identical for all files.

<RCX ...> The RCX tag
 <WorldObject ...>
<ParentTransferGroup ...>
<ChildTransferGroup ...>
<Box .../> The Box tag
</ChildTransferGroup>
</ParentTransferGroup>
</WorldObject>
  <Motor .../>                          Definition of the motors
<Motor .../>
  <Sensor .../>                         Describtion of sensors (particular tags)

<Lejos ...>
<JarFilename>
... Programming
</JarFilename>
</Lejos>
</RCX>

In the follwing explanations, %lms-home% names the LMS root directory (e.g. C:\Programme\lms).
In the example, we create a robot named myRCX.xml in the directory %lms-home%/scenario/myScenario.

The XML tag

The XML tag defines the XML file. It is idetical for all scenes.

<?xml version="1.0" encoding="UTF-8"?>

The RCX tag

At this entry, the definition of a RCX robot begins by naming it. In order to define the correct structure of the XML file, a xsd file (xsd=XML Scheme Definition) gets intgrated. This works as follows:
<RCX Name=�MyRCX� xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="RCX.xsd">
The xsd file is located in the directory %lms-home%/config/Project. If you store your scene file into this directory, you can copy the RCX tag like it is given above. If your scene file is located in another directory, you can either copy the file �RCX.xsd� into this directory or create a relative path starting at the RCX file and pointing to the scheme definition. The latter case looks as follows:

<RCX Name="Linienverfolger" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../config/RCX/RCX.xsd">

The RCX tag is closed at the end of the file:

</RCX>

WorldObjects

The WorldObjects integrate particular parts of the robot and determine the behaviour in case of collision by the parameter �UseCollisionDetection�. There are various TransformGroups embedded in the WorldObjects (see below).

Nesting hierarchy of Objects

The actual parts of a robot (defined by the tag <Box ...>) are embedded in a ChildTransformGroup. This ChildTransformGroup is ranked among a ParentTransformGroup, which is an integral part of a WorldObject. Here, you see an example of a yellow box in the centre of the floor. It represents a simple robot. The centre of this robot is located 5cm above the floor.

<WorldObject UseCollisionDetection="true">
<ParentTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0"
Value21="0" Value22="1" Value23="0" Value24="0"
Value31="0" Value32="0" Value33="1" Value34="0.05"
Value41="0" Value42="0" Value43="0" Value44="1">
<ChildTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0"
Value21="0" Value22="1" Value23="0" Value24="0"
Value31="0" Value32="0" Value33="1" Value34="0"
Value41="0" Value42="0" Value43="0" Value44="1">
<Box Width=".05" Length=".08" Height=".035"
Red="200" Green="200" Blue="020"/>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>

The particular parameters of the Box tag represent the width, the length and the height as well as the colour of the robot. A lot more complex is the 4x4 matrix, that gets defined in the ChildTransformGroups. Using this matrix, you can position and rotate the boxes.

Transform Groups: Positioning and Arranging an Object

The Tutorial �Lego Minstorms Simulator � Creating LMS Scenes� explains the adjustments to be done in order to move and rotate boxes.

Define Motors

Motors get defined by a Motor tag. It determines the port by which the motor is connected to the RCX (A,B or C). Furthermore, a force vector is defined. The force of the motor operates by the direction of this vector.
In this example, there is a simple robot with two motors that are fixed below the RCX. On each motor, there is attached a drive gear:

...
</WorldObject>
<Motor Connection="A" ForceX="1" ForceY="1" ForceZ="0"/>
<Motor Connection="B" ForceX="1" ForceY="-1" ForceZ="0"/>

Remarkable are the force vectors of the two motors. As you can see, their forces do not work just in the same direction like the robot's running direction, but directly opposed and diagonal (figure 1).

Figure 1
Figure 2

This unordinary structure of the force vectors can be visualised easily: On the one hand, the motors are located exactly across from each other. If both motors get the command �forward�, then one wheel moves by the direction of the y-axis and the other one oppositely (because both motors move anticlockwise). In order to move forward, motor B needs to move backwards. Consequently, it gets the force vector that you can see in figure 2. (Annotation: In reality, this problem is solved by reversing the motor ports.)
If both motors are switched on, the x-components of the vectors cancel out each other and the RCX moves forward. However, if just one motor is working, in reality the moving direction by the x-axis changes, too. In order to simulate this, the both motors have an additional force working by the x-direction.
Indeed, merely by these forces the rotation of the robot is not described completely.

The Motor Connector

In order to simulate the rotation of the robot correctly, we connect the two robots with the MotorConnector tag. The tag has 7 parameters. The first two of them state the two involved Motor objects. The following 3 parameters specify the direction by which the robot moves by the time both motors are moving. In our case, this is the y-direction.
The last two parameters give the transmission (GearFactor) of the connected wheel (depends on the size of the wheel and the gear mechanism) and the steering factor . The steering factor directly influences how fast the robot rotates (depends on the distance between the wheels).

...
<Motor Connection="A" ForceX="1" ForceY="1" ForceZ="0"/>
<Motor Connection="B" ForceX="1" ForceY="-1" ForceZ="0"/>
<MotorConnector
LeftMotor="A" RightMotor="B"
ForceX="0" ForceY="1" ForceZ="0"
GearFactor="1.6" SteerFactor="12"/>

So, our first robot is almost completed. We just need to worry about its programming.

The Lejos tag

The Lejos tag is used to integrate a program. In this Lejos tag the Jar file that contains the program gets integrated by the tag �JarFilename�. It is created uncompressed after compiling and it must contain a manifest file that refers to the class with the main function.
Example: In the directory %lms-home%/scenario/myScenario is located a file named MyRobot.java and some other classes. The �MyRobot�-class has the main function. In the same directory there is the manifest file manifest.txt with the following content:

Manifest-Version: 1.0
Main-Class: Robot

Compiling and creating the Jar file works with the following calls:

lejosc *.java 
jar cvfm0 myrobot.jar manifest.txt *.class

Please mind that the bin directories of Java and Lejos are located in the environment variable �Path�.
In our example, the created Jar file gets integrated as follows:

<Lejos enable="true">
<JarFilename>scenario/myScenario/myrobot.jar</JarFilename>
</Lejos>

Here, the given path of the Jar file is relative to the lms main directory, too.
So, our first robot is finished. It has two motors (A and B) and it can move in a scene (however, it can not interact with it).

Touch Sensors

Touch Sensors provide the simple opportunity to register the collision of the robot with an obstacle of the scene or with another robot. There can be detected all collisions of WorldObjects, that are defined with the attribute UseCollisionDetection="true".
If a robot collides with a wall of the simulation, it stops and gets stuck with it. If the environment of a robot is bordered by a wall or includes obstacles, a touch sensor can detect collisions and respond to them.

The two touch sensors of LEGO
Sample robot with a touch sensor

Here, the characteristic definition of a touch sensor:

<TouchSensor Connection="B">
<WorldObject UseCollisionDetection="true">
<ParentTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0.0"
Value21="0" Value22="1" Value23="0" Value24="0.12"
Value31="0" Value32="0" Value33="1" Value34="0.005"
Value41="0" Value42="0" Value43="0" Value44="1">
<ChildTransformGroup>
<Box Width="0.1" Length="0.004" Height="0.004"
Red="20" Green="20" Blue="20"/>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</TouchSensor>

As you can see, the sensor gets initiated by the TouchSensor tag. In the tag, the used port gets defined. There, the ports �A�, �B� and �C� correspond to the sensor ports �1�, �2� und �3� of the RCX brick.
Now, we create a WorldObject with CollisionDetection. It contains a ParentTransformGroup that determines the position of the touch sensor.
The following ChildTransformGroup defines the actual sensor (meaning the technical construction the sensor is linked with).
In this example, a strait box above the hithterto robot is defined. It corresponds to the black bar in the picture showing the sample robot.
Please note: The box objects of the touch sensors need to be mounted freely. They may not touch any other object with collision detection included the robot itself and the floor.

Light Sensors

Light sensors that are directed to the floor can detect the brightness of the floor. They get defined by the FloorLightSensor tag, which has a port as its parameter (like the touch sensor). Also like the touch sensor, it contains a WorldObject that includes a ParentTransformGroup, a ChildTransformGroup and a Box.
A characteristic definition of a light sensor looks as follows:

<FloorLightSensor Connection="A">
<WorldObject UseCollisionDetection="false">
<ParentTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0.0"
Value21="0" Value22="1" Value23="0" Value24="0.1"
Value31="0" Value32="0" Value33="1" Value34="-0.01"
Value41="0" Value42="0" Value43="0" Value44="1">
<ChildTransformGroup>
<Box Width="0.0125" Length="0.0125" Height="0.025"
Red="20" Green="20" Blue="200"/>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</FloorLightSensor>

So, the structure is analogue to the structure of the touch sensor.
In our example, the light sensor is located between the touch sensor and the RCX and it is coloured blue.

The so far explained constructs cover the most utilised types of robots. Indeed, not all types of robots can be simulated with the LMS, but some further facilities are provided for the user. Here, we will describe the most important ones:

Rotation Sensors and their Interconnection with Motors

Often, it can be helpful to detect the motor rotations using Rotation sensors (not contained in the construction kid). For instance in the case study 'high rack warehouse' the position of the rack feeder is controlled by rotation sensors.
A rotation sensor is defined by the rotation sensor tag. The LinearMotorConnector provides interconnection of rotation sensors with motors. The following example shows a shortened extract of the rack feeder of the high rack warehouse case study. We will come back to this later in order to explain nesting of motor controlled subsystems:

<Motor Connection="A" ForceX="1" ForceY="1" ForceZ="0" GearFactor="1"/>
<Motor Connection="B" ForceX="1" ForceY="1" ForceZ="0" GearFactor="1"/>
<Motor Connection="C" ForceX="1" ForceY="1" ForceZ="0" GearFactor="1"/>

<RotationSensor Connection="A"/>
<RotationSensor Connection="B"/>
<RotationSensor Connection="C"/>

<LinearMotorConnectorName="Slide"
Motor="A" RotationSensor="A"
RotationGear="0.6" MovementSpeed="1.77">
<Beam>
<WorldObject>
<ParentTransformGroup Value11="1" ...>
<ChildTransformGroup Value11="1" ...>
<Box .../>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</Beam>
<Plattform>
<WorldObject>
<ParentTransformGroup Value11="1" ...>
<ChildTransformGroup Value11="1" ...>
<Box .../>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</Plattform>
<!--*****************************->
<LinearMotorConnector Name="Lift"
Motor="B" RotationSensor="B"
RotationGear="0.6" MovementSpeed="1.42">
<Beam>
<WorldObject>
<ParentTransformGroup Value11="-0.0002" ...>
<ChildTransformGroup Value11="1" ...>
<Box .../>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</Beam>
<Plattform>
<WorldObject>
<ParentTransformGroup Value11="1" ...>
<ChildTransformGroup Value11="1" ...>
<Box .../>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</Plattform>
<!--*****************************->
...
<!--*****************************->
</LinearMotorConnector>
</LinearMotorConnector>

As you can see, the LinearMotorConnector has the parameters �Name� (for debug outputs), Motor and RotationSensor. The parameter �RotationSensor describes the factor to be multiplied with the number of motor rotations to get the sensor rotations. Thereby, a gear transmission or a gear reduction of the motor axis and the axis of the rotation sensor is modelled. The bigger this factor is chosen, the higher are the values of the sensor. Chosing a negative factor makes the sensor turn reversed. The default value is 1.
The attribute �MovementSpeed� describes the factor to be multiplied with the speed of the motor to get the resulting speed of the platform. Thereby, also a gear transmission or a gear reduction is modelled. The bigger this factor is chosen, the faster the platform moves. Chosing a negative factor makes the platform move reverse. The default value is 1. The movement speed has no influence on the values created by the rotation sensor, because these values just depend on the speed of the motor.

Motor controlled Robotic Subsystems

The example above makes clear the nesting og the subsystems "Slide" and "Lift". Everytime the slide moves, the lift moves, too. Therefore, the LinearMotorConnector of the lift is embedded in the one of the slide.
The
LinearMotorConnector always contains a beam tag, which describes the interface between the systems. In the case study 'high rack warehouse' these beams are easily noticeable by its green colour (good to see in camera perspective 4). The orientation of the beams (in the ParentTransferGroup) indicates the direction of movement. Thus, they have to be rotated correctly (see also the tutorial "Lego Mindstorms Simulator - Creating LMS Scenes). The platform tags define the actual subsystems.

Summary:

In this tutorial, we have learned to equip a simple robot with two drive motors, touch and light sensors and to connect it with the LeJOS library and the LeJOS programms. Furthermore, rotation sensors and the nesting of subsystems have been explained regarding the case study 'high rack warehouse'.

Appendix:

The complete RCX file �myRCX.xml�.

<?xml version="1.0" encoding="UTF-8"?>
<RCX Name="Linienverfolger" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../config/RCX/RCX.xsd">
  <WorldObject UseCollisionDetection="true">
<ParentTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0"
Value21="0" Value22="1" Value23="0" Value24="0"
Value31="0" Value32="0" Value33="1" Value34="0.05"
Value41="0" Value42="0" Value43="0" Value44="1">
<ChildTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0"
Value21="0" Value22="1" Value23="0" Value24="0"
Value31="0" Value32="0" Value33="1" Value34="0"
Value41="0" Value42="0" Value43="0" Value44="1">
<Box Width=".05" Length=".08" Height=".035"
Red="200" Green="200" Blue="020"/>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
  <Motor Connection="A" ForceX="1" ForceY="1" ForceZ="0"/>
<Motor Connection="B" ForceX="1" ForceY="-1" ForceZ="0"/>
<MotorConnector
LeftMotor="A" RightMotor="B"
ForceX="0" ForceY="1" ForceZ="0"
GearFactor="1.6" SteerFactor="12"/>
  <TouchSensor Connection="B">
<WorldObject UseCollisionDetection="true">
<ParentTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0.0"
Value21="0" Value22="1" Value23="0" Value24="0.12"
Value31="0" Value32="0" Value33="1" Value34="0.005"
Value41="0" Value42="0" Value43="0" Value44="1">
<ChildTransformGroup>
<Box Width="0.1" Length="0.004" Height="0.004"
Red="20" Green="20" Blue="20"/>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</TouchSensor>
  <FloorLightSensor Connection="A">
<WorldObject UseCollisionDetection="false">
<ParentTransformGroup
Value11="1" Value12="0" Value13="0" Value14="0.0"
Value21="0" Value22="1" Value23="0" Value24="0.1"
Value31="0" Value32="0" Value33="1" Value34="-0.01"
Value41="0" Value42="0" Value43="0" Value44="1">
<ChildTransformGroup>
<Box Width="0.0125" Length="0.0125" Height="0.025"
Red="20" Green="20" Blue="200"/>
</ChildTransformGroup>
</ParentTransformGroup>
</WorldObject>
</FloorLightSensor>
  <Lejos enable="true">
<JarFilename>scenario/mySceanrio/myrobot.jar</JarFilename>
</Lejos>
</RCX>

Imprint | Webmaster | Recent changes: 04.10.2007