Started:Formats
From OpenRAVE
OpenRAVE uses XML to store all robot and scene descriptions. The XML format is flexible enough to link one XML file from another like including already created objects/robots in an environment. It is also possible to specify vrml or iv formatted files within it to import models.
All interface types can be created. Furthermore, an <environment> tag can optionally be specified to put all bodies/interfaces in.
- Environment - specify multiple objects and robots. Can also define some GUI properties like camera start location and background color. The environment allows the creation of any OpenRAVE interfaces. Each interface can take the type attribute specifying the interface type and can define custom XML readers.
- KinBody - The basic object that all other objects derive from. A kinematic body consists of a collection of rigid bodies and joints that connect these bodies.
- Robot - The basic robot that derives from KinBody. Usually every Robot has at least one KinBody declaration inside it. A robot can also hold a list of Manipulator and AttachedSensor objects describing the manipulation/sensing capabilities of the robot. Since plugin authors can create different robots, it is also possible to define custom fields in Robot to hold other information like balance control parameters for humanoids.
Contents |
KinBody
<KinBody name="TestKinBody"> <!-- Create a rigid body named Body1 and declare it as 'dynamic'.--> <!-- 'dynamic' bodies are subject to physics laws, 'static' bodies will never move--> <!-- due to physical forces. It is recommended EVERYTHING is declared as 'dynamic' --> <Body name="Body1" type="dynamic"> <!-- Note that the body transforms affects all geometry objects attached. --> <!-- translation of the body--> <Translation>0 0 0</Translation> <!--rotation of the body specified as a rotation axis. First three numbers are the axis.--> <RotationAxis>1 0 0 90</RotationAxis> <!-- defines mass properties for the entire kinbody. possible mass types are--> <!-- mimicgeom - <density>. Adds a mass equivalent to all the geometry--> <!-- objects. trimesh and plane are not supported.--> <!-- box - <density>(or <mass>), <extents> Adds a simple box--> <!-- sphere - <density>(or <mass>), <radius>--> <Mass type="mimicgeom"> <density>1000</density> </Mass> <!-- Define a geometry object attached to the body. The functionality of --> <!-- geometry objects is to define the collision and render geometries of the body. --> <!-- All geometry types have Rotation(Mat/Quat), Translation, and Render components.--> <!-- Possible geom types are box, sphere, trimesh, plane.--> <!-- *box - extents--> <!-- *sphere - radius--> <!-- *cylinder - radius, height (axis is along y)--> <!-- *trimesh - data--> <Geom type="box"> <!-- extents of the box - half width, height, length--> <Extents>1 1 1</Extents> <!-- set the translation and rotation of the box. Note that the transforamtions--> <!-- are all relative to the parent body.--> <Translation>1 0 0</Translation> <RotationAxis>0 1 0 45</RotationAxis> </Geom> <!-- Can create multiple geometries per body--> <Geom type="box"> <Extents>2 1 2</Extents> <Translation>0 1 0</Translation> <!-- RotationMat is a 3x3 rotation matrix specified as rows first--> <RotationMat>1 0 0 0 1 0 0 0 1</RotationMat> <!-- Set the transparency of the geometry, 0 is opaque--> <transparency>0.4</transparency> </Geom> </Body> <Body name="Body2" type="dynamic"> <!-- change the mass properties of the body--> <Mass type="mimicgeom"> <!-- specify the total mass--> <total>0.40605</total> <!-- specify the 3x3 inertia matrix--> <inertia>2 0 0 0 3 0 0 0 5</inertia> <!-- specify the center of mass (if using ODE physics engine, should be 0)--> <com>0.008842 -0.000018 0.07367</com> </Mass> <!-- create a sphere--> <Geom type="sphere"> <!-- although the underlying collision geometry will be a sphere,--> <!-- render it as a coffee pot--> <Render>models/objects/coffeepot.iv</Render> <Translation>0 -1.5 0</Translation> <Radius>1.5</Radius> </Geom> <!-- create a triangle mesh--> <Geom type="trimesh"> <Render>models/objects/cup.iv 0.01</Render> <!-- use the cup triangles for collision detection.--> <!-- The last number is the scale, in case the iv files are scaled improperly.--> <data>models/objects/cup.iv 0.01</data> <Translation>1.5 -2 0</Translation> </Geom> </Body> <!-- Create a joint between the two bodies.--> <!-- Possible joint types are: hinge, slider, universal, hinge2, and spherical.--> <!-- Hinges are the most common joint type used in robots.--> <!-- For amotors, can specify mode, axis1, axis2, axis3. For each axis, first 3 values are the axis and the last value is the relative coord system (see ODE documentation).--> <!-- Every joint can have certain properties:--> <!-- <maxforce> are in number of degrees of freedom.--> <!-- <maxvel>, <resolution> are scalar and apply to all DOFs.--> <!-- <limits>, <limitsdeg>, <limitsrad> specify the joint limits --> <Joint name="j1" type="hinge"> <!-- Specify the names of the bodies, names are not case sensitive.--> <Body>Body1</Body> <Body>Body2</Body> <!-- anchor and axis of the hinge--> <Anchor>0 0 0</Anchor> <Axis>0 1 0</Axis> <!-- Weight for configuration distance, mostly used in planners.--> <!-- for joints with > 1 DOF, specify 2+ values--> <Weight>1.0</Weight> </Joint> </KinBody>
Models Directory
By default, the root directory for all models files is the folder openrave is launched at. To change this, <modelsdir> can be used to specify model files relative to where the current xml file is. For example:
<KinBody> <modelsdir>../mymodels</modelsdir> <Body> <Geom type="box"> <render>kitchen/myfile.wrl</render> </Geom> </Body> </KinBody>
Circular Joints
Sometimes joints will have the upper and lower limits identified, meaning that as soon as the joint gets past one limit it will wrap around to the other. Infinitely revolving hinge joints are the most common example of circular joints where the − π and π limits are identified. In openrave, it is possible to set a joint as circular like this:
<joint circular="true" ...> ... </joint>
Adjacent Links
Robot self-collision usually checks all pairs of non-adjacent links for collision; links are adjacent if they are connected to a joint. In order to reduce self-collision computation time and spurious collisions of small links, it is possible to force pairs of links to be treated as adjacent by specifying an <adjacent> tag.
Robot
A simple 3DOF planar arm in XZ
<Robot name="3DOFRobot"> <KinBody> <!-- Create the base body, it should never move--> <!-- Note that all translations and rotations are with respect to this base--> <!-- For example, the robot at the identity transformation is equivalent to the identity transformation of the first body.--> <Body name="Base" type="dynamic"> <Translation>0.0 0.0 0.0</Translation> <Geom type="cylinder"> <radius>0.03</radius> <height>0.02</height> <diffuseColor>0.05 0.05 0.05</diffuseColor> </Geom> </Body> <!-- the first movable link--> <Body name="Arm0" type="dynamic"> <!-- Offset from is a fast way of specifying that the translation and rotation of this--> <!-- body should be relative to another link--> <offsetfrom>Base</offsetfrom> <!-- Translation relative to Base--> <Translation>0 0.005 0</Translation> <Geom type="box"> <Translation>0.08 0 0</Translation> <Extents>0.08 0.005 0.01</Extents> </Geom> </Body> <!-- declare a circular hinge joint (circular joints have no limits) --> <Joint circular="true" name="Arm0" type="hinge"> <Body>Base</Body> <Body>Arm0</Body> <offsetfrom>Arm0</offsetfrom> <weight>4</weight> <limitsdeg>-180 180</limitsdeg> <axis>0 1 0</axis> <maxvel>3</maxvel> <resolution>1</resolution> </Joint> <!-- the second movable link--> <Body name="Arm1" type="dynamic"> <offsetfrom>Arm0</offsetfrom> <Translation>0.14 0.01 0</Translation> <Geom type="box"> <Translation>0.08 0.0 0</Translation> <Extents>0.08 0.005 0.0075</Extents> </Geom> </Body> <!-- declare a circular hinge joint (circular joints have no limits) --> <Joint circular="true" name="Arm1" type="hinge"> <Body>Arm0</Body> <Body>Arm1</Body> <offsetfrom>Arm1</offsetfrom> <weight>3</weight> <limitsdeg>-180 180</limitsdeg> <axis>0 1 0</axis> <maxvel>4</maxvel> <resolution>1</resolution> </Joint> <!-- the third movable link--> <Body name="Arm2" type="dynamic"> <offsetfrom>Arm1</offsetfrom> <Translation>0.14 0.01 0</Translation> <Geom type="box"> <Translation>0.04 0 0</Translation> <Extents>0.04 0.005 0.005</Extents> </Geom> </Body> <!-- declare a circular hinge joint (circular joints have no limits) --> <Joint circular="true" name="Arm2" type="hinge"> <Body>Arm1</Body> <Body>Arm2</Body> <offsetfrom>Arm2</offsetfrom> <weight>3</weight> <limitsdeg>-180 180</limitsdeg> <axis>0 1 0</axis> <maxvel>2</maxvel> <resolution>2</resolution> </Joint> <!-- Create the gripper joints:--> <!-- right gripper--> <Body name="RClaw" type="dynamic"> <offsetfrom>Arm2</offsetfrom> <Translation>0.08 0.005 0</Translation> <RotationMat>0 1 0 0 0 -1 -1 0 0</RotationMat> <Geom type="trimesh"> <Data>models/puma/RClaw.iv</Data> <Render>models/puma/RClaw.iv</Render> </Geom> </Body> <Joint name="j1" type="hinge"> <Body>Arm2</Body> <Body>RClaw</Body> <offsetfrom>RClaw</offsetfrom> <weight>0.2</weight> <limitsdeg>-56 16</limitsdeg> <axis>0 0 1</axis> <maxvel>0.4</maxvel> <resolution>3</resolution> </Joint> <!--left gripper--> <Body name="LClaw" type="dynamic"> <Translation>0.08 0.005 0</Translation> <offsetfrom>Arm2</offsetfrom> <RotationMat>0 1 0 0 0 -1 -1 0 0</RotationMat> <Geom type="trimesh"> <Data>models/puma/LClaw.iv</Data> <Render>models/puma/LClaw.iv</Render> </Geom> </Body> <Joint name="j2" type="hinge"> <Body>Arm2</Body> <Body>LClaw</Body> <offsetfrom>LClaw</offsetfrom> <weight>0.2</weight> <limitsdeg>-56 16</limitsdeg> <axis>0 0 -1</axis> <maxvel>0.4</maxvel> <resolution>3</resolution> </Joint> <!-- set the transparency of every geometry in the KinBody--> <transparency>0.1</transparency> </KinBody> <!-- Specifying the manipulator structure--> <Manipulator name="arm"> <effector>Arm2</effector> <!-- last link where end effector is attached--> <base>Base</base> <!-- base link--> <joints>j1 j2</joints> <!-- the gripper joints used for contact--> <armjoints>Arm0 Arm1 Arm2</armjoints> <!-- the joints composing of the arm--> <!-- the id of the inverse kinematics solver, it is not necessary to--> <!-- specify an ik solver for every robot. But if there is one,--> <!-- use iksolver field to identity it.--> <iksolver>MyTriDOFSolver</iksolver> <!-- joint values of the closed and opened positions--> <closingdirection>1 1</closingdirection> <palmdirection>1 0 0</palmdirection> <!-- grasp goal with respect to the effector--> <Translation>0.125 0 0</Translation> <RotationAxis>1 0 0 90</RotationAxis> </Manipulator> </Robot>
Defining Manipulators
A robot manipulator defines a kinematic chain of the robot joint hierarchy along with optional gripper joint values that are not used in the inverse kinematics computation but are needed for grasping purposes (chains for heads, legs do not need the joint values). A manipulator defines a new frame of reference with respect to the end effector link; all inverse kinematics computations are computed using it. Furthermore, a manipulator can have a <direction> tag specifying an axis for approaching objects or line-of-sight. For example the robots/barrettwam.robot.xml gripper is defined by
<Manipulator name="arm"> <base>wam0</base> <effector>wam7</effector> <Translation>0 0 0.22</Translation> <joints>JF1 JF2 JF3 JF4</joints> <closingdirection>1 1 1 0</closingdirection> <direction>0 0 1</direction> <iksolver>WAM7ikfast 0.05</iksolver> </Manipulator>
The manipulator can optionally define a <iksolver> tag specifying the iksolver interface that is used for getting IK solutions, or a shared object (DLL) to load an ikfast solver from.
Attaching Robot Sensors
Every robot can be attached a number of sensors onto it. The way to specify this in XML is:
<Robot> <!-- ... usual robot definitions ... --> <!-- Specify an attached sensor--> <AttachedSensor name="MyFirstLaser"> <link>wam1</link> <!-- the robot link that the sensor is attached to. As the robot moves, the sensor will move with it--> <translation>0 0.2 0.4</translation> <!-- the local translation in the attached link's frame--> <rotationaxis>1 0 0 45</rotationaxis> <!-- the local rotation in the attached link's frame--> <!-- specify the real sensor attached--> <!-- 'type' is the sensor interface identifier--> <!-- 'args' are the arguments passed to SensorBase::Init--> <sensor type="BaseLaser2D" args=""> <!-- The rest are specific fields to BaseLaser2D, these change as the type changes--> <!-- The best way to find out what fields are supported is to look for the documentation--> <!-- for the type of sensor using--> <minangle>-135</minangle> <!-- degrees --> <maxangle>135</maxangle> <!-- degrees --> <resolution>0.35</resolution> <!-- degrees between laser points--> <maxrange>5</maxrange> <!-- max range of robot--> </sensor> </AttachedSensor> </Robot>
Environment Example
This example is part of the bin/data/intel/lab1.env.xml file. The most important thing to note about this example is the use of the file= attribute to import other XML files. The filename specified with file= has to be relative to the current directory where the file calling it resides. Note the differences between segway.kinbody.xml and barrettwam.robot.xml.
<Environment> <!-- set the background color of the environment--> <bkgndcol>0.3 0.7 0.8</bkgndcol> <!-- set the initial camera translation--> <camtrans>1.418 -1.234 2.963</camtrans> <!-- set the initial camera rotation specified by rotation-axis--> <camrotaxis>0.724 0.302 0.619 68</camrotaxis> <!-- import the segway model and place it somewhere--> <KinBody file="data/segway.kinbody.xml"> <Translation>-0.0671 -0.0819 0.7550</Translation> </KinBody> <!-- import a robot file and add an additional body for a cylindrical base--> <Robot file="../../robots/barrettwam.robot.xml" name="BarrettWAM"> <KinBody> <Translation>-.22 -.14 -.346</Translation> <Body type="dynamic"> <Geom type="cylinder"> <RotationAxis>1 0 0 -90</RotationAxis> <radius>0.08</radius> <height>0.6</height> <diffusecolor>0.3 0.3 0.3</diffusecolor> <Translation> 0.2286 0.1397 -0.346</Translation> </Geom> </Body> </KinBody> <translation>-0.754 0.3265 1.036</translation> </Robot> <!-- add the floor as a box--> <KinBody name="floor"> <!-- floor should never move, so make it static--> <Body type="static"> <Geom type="box"> <extents>2 2 0.005</extents> <diffuseColor>.6 .6 .6</diffuseColor> <ambientColor>0.6 0.6 0.6</ambientColor> </Geom> </Body> </KinBody> </Environment>
Robot Composition
The way we recommend managing robots composed of several sub-robots (like a humanoid composed of arms, legs, hands, etc) is to first create separate .kinbody files for just the kinematics and geometry of each separate part (ie a hand.kinbody.xml and a arm.kinbody.xml). Then create a robot file that includes both the kinematics and defines the manipulators, sensors, and controllers:
<robot> <kinbody file="arm.kinbody.xml"/> <kinbody file="hand.kinbody.xml"/> <attachedsensor> .... </attachedsensor> <manipulator> .... </manipulator> </robot>
Sometimes for grasp planning, the hand needs to be treated as a robot, so we create a hand.robot.xml file as follows:
<robot> <kinbody file="hand.kinbody.xml"/> <manipulator> .... </manipulator> </robot>
1. A robot can reference other robots through:
<Robot> <Robot file="a.robot.xml"/> <Robot file="b.robot.xml"/> </Robot>
Both a's and b's <Manipulator> and <AttachedSensor> tags will be used in the parent robot, so you don' t have to copy their definitions.
2. It is possible to prefix the links and joints of a child robot by using the 'prefix' attribute:
<Robot> <KinBody prefix="left_" file="arm.kinbody.xml"/> <KinBody prefix="right_" file="arm.kinbody.xml"/> </Robot>
Now all links and joints will either start with left_ or right_.
3. When the xml parser sees a body with the same name as another body, it 'appends' the specified geometries to the original body. This allows the same link to be referenced/defined in multiple robot files (Note that it is not possible to change the original body coordinate system).
Attaching Separate Links
When a robot is composed of multiple parts defined in different files, it is necessary to attach links from the different files together so that the robot hierarchy can be complete. This is done by defining disabled dummy joints that attach two links together. These disabled joints do not show up in the robot's description and are only present to maintain the relative transformation between two links. For example, the robot robots/pa10schunk.robot.xml is composed of robots/pa10.kinbody.xml and robots/schunk_manip.kinbody.xml, in order to join the two, the robot is defined in the following way:
<KinBody file="pa10.kinbody.xml"> <KinBody file="schunk_manip.kinbody.xml"/> <Joint name="dummy" type="hinge" enable="False"> <body>link7</body> <body>gripper_base</body> <limits>0 0</limits> </Joint> </KinBody>
where link7 is a link of the pa10 arm and gripper_base is a link of the gripper. The lower and upper joint limits are all 0, which OpenRAVE recognizes as a dummy joint.
Joining COLLADA Files
It is possible to load robots and bodies from COLLADA files by specifying the collada filename through the file attribute. For example, the following robot is a combination of an arm defined in OpenRAVE XML and a hand defined in COLLADA (download schunkSDHHand from OpenGrasp). The dummy joint is used to join the arm end effector with the hand base.
<robot> <robot file="robots/kuka-kr5-r650.robot.xml"></robot> <robot prefix="hand_" file="schunkSDHhand.dae"></robot> <kinbody> <body name="hand_root"> <offsetfrom>link6</offsetfrom> <translation>0.03 0 0</translation> <rotationaxis>0 1 0 90</rotationaxis> </body> <joint type="hinge" enable="false"> <body>link6</body> <body>hand_root</body> <limits>0 0</limits> </joint> </kinbody> </robot>
Dual-arm example
Here is an example file of having a robot composed of two arms attached to a common link named chest.
<Robot name="schunk-dualarm"> <KinBody> <body name="chest"> <geom type="box"> <extents>0.1 0.1 0.4</extents> <translation>0 0 0.4</translation> </geom> </body> <!-- left arm --> <KinBody prefix="l_" file="schunk-lwa3.kinbody.xml"> <RotationAxis>1 0 0 90</RotationAxis> <translation>0 -0.1 0.7</translation> </KinBody> <!-- right arm --> <KinBody prefix="r_" file="schunk-lwa3.kinbody.xml"> <RotationAxis>1 0 0 -90</RotationAxis> <translation>0 0.1 0.7</translation> </KinBody> <!-- connect the two arms with dummy joints --> <joint name="leftdummy" type="hinge" enable="false"> <body>chest</body> <body>l_base</body> <limits>0 0</limits> </joint> <joint name="rightdummy" type="hinge" enable="false"> <body>chest</body> <body>r_base</body> <limits>0 0</limits> </joint> </KinBody> <!-- define the manipulators --> <Manipulator name="leftarm"> <base>l_base</base> <effector>l_link7</effector> <armjoints>l_j0 l_j1 l_j2 l_j3 l_j4 l_j5 l_j6</armjoints> </Manipulator> <Manipulator name="rightarm"> <base>r_base</base> <effector>r_link7</effector> <armjoints>r_j0 r_j1 r_j2 r_j3 r_j4 r_j5 r_j6</armjoints> </Manipulator> </Robot>
Scale
The first thing when importing a new model is to check that all the units are in meters (it is very common for robots to be in millimeters), otherwise the visualization model and the collision model will be in a different scale. to check this, open the robot and go to View->Geometry->Collision, this will show the collision model. If it is not the same scale, you need to go inside your model files and change the units. You can also enter a scale factor after model filenames like this:
<data>mydata.iv 0.001</data> <render>mydata.iv 0.001</render>
this will scale the models by 0.001.
Custom XML
Openrave provides much more flexibility in creating and defining custom XML readers for interfaces. First the <environment> XML tag supports creating any interface type and supports loading plugins. For example:
<Environment> <plugin>libcustomreader</plugin> <robot name="wam" file="robots/barrettwam.robot.xml"/> <controller type="CustomController" robot="wam" args=""> ..custom data.... </controller> <probleminstance type="basemanipulation" args="wam"/> </Environment>
In this example, openrave will first load the plugin, then will create a robot, and then will create a controller that is attached to the robot, then will create the basemanipulation problem instance giving it the robot name as the argument.
Furthermore, using EnvironmentBase::RegisterXMLReader, it is possible to set a parser for custom XML tags for each interface type. For those curious on how to take advantage of custom readers, please refer to examples/plugincpp/customreader.cpp on how to attach a custom XML reader to a controller.
These changes will allow people to setup all their specific environment settings in the XML files without having to rely on external scripts or other programs to do it. Note that OpenRAVE processes tags in depth first order.
XML Reference
Note: All XML handling is done in src/libopenrave-core/xmlreaders.cpp. If there's any parameters that are not explained well, make sure to check out that source file for further reference.
Here's a list of all possible fields the XML supports in a hierarchical structure.
environment - attributes: file bkgndcolor - 3 floats camrotaxis - 4 floats camtrans - 3 floats kinbody - attributes: name, file robot - attributes: name, file planner - attributes: type, file sensorsystem - attributes: type, file controller - attributes: type, file, robot, args probleminstance - attributes: type, file inversekinematicssolver - attributes: type, file physicsengine - attributes: type, file sensor - attributes: type, file collisionchecker - attributes: type, file trajectory - attributes: type, file viewer - attributes: type, file server - attributes: type, file
kinbody - attributes: name, file, prefix, type, makejoinedlinksadjacent
adjacent - 2 body names
body - attributes: name, type (dynamic, static)
geom - attributes: name, type (box, sphere, trimesh, cylinder), render (true,false), modifiable (true,false)
ambientcolor - 3 float
data - string
diffusecolor - 3 float
extents - 3 float [box]
height - float [cylinder]
quat - 4 float
radius - float [cylinder, sphere]
render - string
rotationaxis - 4 float
rotationmat - 9 float
translation - 3 float
transparency - 1 float
vertices - 9*N floats where each 9 values defines 1 triangle with 3 vertices
mass - attributes: type (box, sphere, custom)
com - 3 float
density - float
inertia - 9 float
radius - float
total - float
joint - attributes: enable (true, false), mimic (joint_name c0 c1), type (hinge, slider, universal, hinge2, spherical), circular(true, false)
anchor - 3 floats [hinge, hinge2, universal, spherical]
axis - 3 floats [hinge, slider]
axis1 - 3 floats [hinge2, universal]
axis2 - 3 floats [hinge2, universal]
body - string
limits - 2*dof floats in radians if applicable (first two specify first joint limits, etc)
limitsdeg - 2*dof floats in degrees if applicable (first two specify first joint limits, etc)
limitsrad - 2*dof floats in radians if applicable (first two specify first joint limits, etc)
maxvel - dof floats
mode - int [amotor]
offsetfrom - link name
resolution - float
weight - dof floats
jointvalues
kinbody - attributes: name, file, prefix
mass - attributes: type (box, sphere, custom)
density - float
radius - float
total - float
modelsdir - string
offsetfrom - bodyname
quat - 4 float
rotationaxis - 4 float
rotationmat - 9 float
translation - 3 float
transparency - 1 float
robot - attributes: name, file, prefix, type (robot plugin type)
attachedsensor - attributes: name
link
quat
rotationaxis
rotationmat
translation
sensor - attributes: type, arguments
... - fields defined by SensorBase class instantiated by type
controller - controllertype arguments
jointvalues
kinbody - name
manipulator - attributes: name
armjoints - n joint names
base - link name
closed - k floats
effector - link name
iksolver - string
gripperjoints - k joint names
closingdirection - k floats
palmdirection - 3 floats
quat - 4 floats
rotationaxis - 4 floats
rotationmat - 9 floats
translation - 3 floats
quat - 4 float
robot - name, file, type
rotationaxis - 4 float
rotationmat - 9 float
translation - 3 float

