Format:XML

From OpenRAVE
Jump to: navigation, search


OpenRAVE Custom XML Format

Openrave robots.jpg

TODO: Decide on the versioning scheme

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.

Transformations

Most tags for links/bodies/robots hold a transformation. The following fields modify this transformation:

<source lang="xml"> <translation>0 1 0</translation>

<quat>1 0 0 0</quat>

<rotationmat>1 0 0 0 1 0 0 0 1</rotationmat>

<rotationaxis>1 0 0 90</rotationaxis>

</source>

Multiple of the same tags can be specified, resulting in the transformations being compounded. During compounding, the translation and rotation are treated separately.

KinBody

<source lang="xml"> <KinBody name="TestKinBody">

 <Body name="Body1" type="dynamic">
   
   <Translation>0 0 0</Translation>
   <RotationAxis>1 0 0 90</RotationAxis>
   
   <Mass type="mimicgeom">
     <density>1000</density>
   </Mass>
   
   <Geom type="box">
     <Extents>1 1 1</Extents>
     <Translation>1 0 0</Translation>
     <RotationAxis>0 1 0 45</RotationAxis>
   </Geom>
   <Geom type="box">
     <Extents>2 1 2</Extents>
     <Translation>0 1 0</Translation>
     <RotationMat>1 0 0 0 1 0 0 0 1</RotationMat>
     <transparency>0.4</transparency>
   </Geom>
 </Body>
 
 <Body name="Body2" type="dynamic">
   <Mass type="mimicgeom">
     <total>0.40605</total>
     <inertia>2 0 0 0 3 0 0 0 5</inertia>
     <com>0.008842 -0.000018 0.07367</com>
   </Mass>
   <Geom type="sphere">
     <Render>models/objects/coffeepot.iv</Render>
     <Translation>0 -1.5 0</Translation>
     <Radius>1.5</Radius>
   </Geom>
   <Geom type="trimesh">
     <Render>models/objects/cup.iv 0.01</Render>
     <collision>models/objects/cup.iv 0.01</collision>
     <Translation>1.5 -2 0</Translation>
   </Geom>
 </Body>
 
 <Joint name="j1" type="hinge">
   <Body>Body1</Body>
   <Body>Body2</Body>
   <Anchor>0 0 0</Anchor>
   <Axis>0 1 0</Axis>
   <Weight>1.0</Weight>
   <maxtorque>10</maxtorque>
 </Joint>

</KinBody> </source>

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:

<source lang="xml"> <KinBody>

 <modelsdir>../mymodels</modelsdir>
 <Body>
   <Geom type="box">
     <render>kitchen/myfile.wrl</render>
   </Geom>
 </Body>

</KinBody> </source>

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 <math>-\pi</math> and <math>\pi</math> limits are identified. In openrave, it is possible to set a joint as circular like this: <source lang="xml"> <joint circular="true" ...> ... </joint> </source>

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.

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:

<source lang="xml"> <collision>mydata.iv 0.001</collision> <render>mydata.iv 0.001</render> </source>

this will scale the models by 0.001.

Modifiable Geometry

When avoiding collision obstacles, OpenRAVE can optionally use convex decompositions to speed up the environment collision checking and pad the geometry with safety regions. By default, all geometry is modifiable, but the user can turn it off so that the mesh is never changed by setting modifiable="false" attribute in the <geom> tag.

Geometry that can make contact with the environment usually should not be modified. For example:

- gripper links since contact points are important

- markers and other place-holders used for tracking

Robot

A simple 3DOF planar arm in XZ

<source lang="xml"> <Robot name="3DOFRobot">

 <KinBody>
   <Body name="Base" type="dynamic">
     <Translation>0.0  0.0  0.0</Translation>
     <Geom type="cylinder">
       <rotationaxis>1 0 0 90</rotationaxis>
       <radius>0.03</radius>
       <height>0.02</height>
       <diffuseColor>0.05 0.05 0.05</diffuseColor>
     </Geom>
   </Body>
   
   <Body name="Arm0" type="dynamic">
     <offsetfrom>Base</offsetfrom>
     <Translation>0 0 0.005</Translation>
     <Geom type="box">
       <Translation>0.08 0 0</Translation>
       <Extents>0.08 0.01 0.005</Extents>
     </Geom>
   </Body>
   <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 0 1</axis>
     <maxvel>3</maxvel>
     <resolution>1</resolution>
   </Joint>
   
   <Body name="Arm1" type="dynamic">
     <offsetfrom>Arm0</offsetfrom>
     <Translation>0.14 0 0.01</Translation>
     <Geom type="box">
       <Translation>0.08 0.0 0</Translation>
       <Extents>0.08 0.0075 0.005</Extents>
     </Geom>
   </Body>
   <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 0 1</axis>
     <maxvel>4</maxvel>
     <resolution>1</resolution>
   </Joint>
   
   <Body name="Arm2" type="dynamic">
     <offsetfrom>Arm1</offsetfrom>
     <Translation>0.14 0 0.01</Translation>
     <Geom type="box">
       <Translation>0.04 0 0</Translation>
       <Extents>0.04 0.005 0.005</Extents>
     </Geom>
   </Body>
   <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 0 1</axis>
     <maxvel>2</maxvel>
     <resolution>2</resolution>
   </Joint>
   
   <Body name="RClaw" type="dynamic">
     <offsetfrom>Arm2</offsetfrom>
     <Translation>0.08 0 0.005</Translation>
     <rotationaxis>0 0 1 -90</rotationaxis>
     <Geom type="trimesh">
       models/puma/RClaw.iv
       <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>
   
   <Body name="LClaw" type="dynamic">
     <Translation>0.08 0.005 0</Translation>
     <rotationaxis>0 0 1 -90</rotationaxis>
     <offsetfrom>Arm2</offsetfrom>
     <Geom type="trimesh">
       models/puma/LClaw.iv
       <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>
   <transparency>0.1</transparency>
 </KinBody>
 
 <Manipulator name="arm">
   <effector>Arm2</effector>   
   <base>Base</base>           
   <joints>j1 j2</joints>      
   <closingdirection>1 1</closingdirection>
   <direction>1 0 0</direction>
   <Translation>0.125 0 0</Translation>
 </Manipulator>

</Robot> </source>

3DOFRobot Robot: Tridof.jpg

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 (<effector>); 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

<source lang="xml"> <Manipulator name="arm">

 <base>wam0</base> 
 <effector>wam7</effector> 
 <Translation>0 0 0.22</Translation>     
 <rotationaxis>1 0 0 90</rotationaxis> 
 <joints>JF1 JF2 JF3 JF4</joints> 
 <closingdirection>1 1 1 0</closingdirection>   
 <direction>0 0 1</direction> 
 <iksolver>WAM7ikfast 0.05</iksolver> 

</Manipulator> </source>

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.

Closed-chains and Mimic Joints

OpenRAVE allows closed-chains and complex kinematics to be simulated using mimic joints. A mimic joint's position, velocity, and acceleration values are computed from user-specified formulas using the values of other joints. OpenRAVE uses the Function Parser library to allow any formula to be specified. Refer to the documentation for more information here.

A mimic joint requires at least the position equation and its partial derivatives (for velocity) to be manually entered.

For example, the Barrett Hand mimic joints are defined as:

<source lang="xml"> <Joint type="hinge" name="JF1">

 ...

</Joint> <Joint name="JF1mimic" type="hinge" enable="false" mimic_pos="JF1/3+0.8727" mimic_vel="|JF1 0.33333">

 ....

</Joint> </source>

Of course, it is possible to have a mimic joint depend on more than one other joint:

<source lang="xml"> <Joint type="hinge" name="a">

 ...

</Joint> <Joint type="hinge" name="b">

 ...

</Joint> <Joint name="c" type="hinge" mimic_pos="a+b+atan(a)" mimic_vel="|a 1 + 1/(1+a*a) |b 1" mimic_accel="|a -2*a/((1+a*a)*(1+a*a)) |b 0">

 ....

</Joint> </source>

When using mimic joints, it is important to still make all the correct joint connections so that loops are discovered and forces can be computed correctly.

If a joint has more than one degree of freedom, attach the axis index at the end. For example: "mimic_pos0", "mimic_pos1", "mimic_vel0", "mimic_vel1", "mimic_accel0", and "mimic_accel1".

Attaching Robot Sensors

Every robot can be attached a number of sensors onto it. The way to specify this in XML is:

<source lang="xml"> <Robot>

 <AttachedSensor name="MyFirstLaser">
   <link>wam1</link> 
   <translation>0 0.2 0.4</translation> 
   <rotationaxis>1 0 0 45</rotationaxis> 
   <sensor type="BaseLaser2D">
     <minangle>-135</minangle> 
     <maxangle>135</maxangle> 
     <resolution>0.35</resolution> 
     <maxrange>5</maxrange> 
   </sensor>
 </AttachedSensor>

</Robot> </source>

Setting joint values for initial state

Sometimes the robot's initial state is not when all the joints are at 0. Instead of transforming each of the geometry to the zero pose, it is possible to set the initial angle to use using the <initial> tag inside the <joint>. The definition for setting the initial angle to pi/2 radius is:

<source lang="xml"> <joint type="hinge">

 <body>link0</body>
 <body>link1</body>
 <initial>1.570796326794</initial>

</joint> </source>

Changing the Body Coordinate System

Barrettwam coordchange.png

Sometimes the robot origin and rotation should be defined in a different coordinate system. It is possible to create a new robot file that references the old one and changes its origin. This requires adding a new root link before the robot is defined. For example, consider the robots/barrettwam.robot.xml file whre the first link's name is 'wam0':

<source lang="xml"> <robot>

 <kinbody>
   <body name="root">
   </body>
 </kinbody>
 <robot file="robots/barrettwam.robot.xml"> 
   <kinbody>
     <body name="wam0">
       <rotationaxis>1 0 0 90</rotationaxis>
       <translation>0.3 0.4 0.3</translation>
     </body>
     <joint name="dummy" type="hinge">
       <body>root</body>
       <body>wam0</body>
       <limitsdeg>0 0</limitsdeg>
     </joint>
   </kinbody>
 </robot>

</robot> </source>

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.

<source lang="xml"> <Environment>

 <bkgndcolor>0.3 0.7 0.8</bkgndcolor>
 <camtrans>1.418 -1.234 2.963</camtrans>
 <camrotaxis>0.724 0.302 0.619 68</camrotaxis>
 
 <KinBody file="data/segway.kinbody.xml">
   <Translation>-0.0671   -0.0819    0.7550</Translation>
 </KinBody>
 
 <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>
 
 <KinBody name="floor">
   <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> </source>

Setting Robot Joint Values

It is possible to set the joint values of the kinbody in the scene using the <jointvalues> tag. The order of the values should be the order of the DOF indices of each joint (passive/mimic joints are ignored).

<source lang="xml"> <environment>

 <robot file="robots/barrettwam.robot.xml">
   <jointvalues>1 1 0 0 0 0 0 0.5 0 0 0</jointvalues>
 </robot>

</environment> </source>

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:

<source lang="xml"> <robot>

<kinbody file="arm.kinbody.xml"/>
<kinbody file="hand.kinbody.xml"/>
<attachedsensor>
    ....
</attachedsensor>
<manipulator>
  ....
</manipulator>

</robot> </source>

Sometimes for grasp planning, the hand needs to be treated as a robot, so we create a hand.robot.xml file as follows:

<source lang="xml"> <robot>

<kinbody file="hand.kinbody.xml"/>
<manipulator>
  ....
</manipulator>

</robot> </source>

1. A robot can reference other robots through:

<source lang="xml"> <Robot>

<Robot file="a.robot.xml"/>
<Robot file="b.robot.xml"/>

</Robot> </source>

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:

<source lang="xml"> <Robot>

<KinBody prefix="left_" file="arm.kinbody.xml"/>
<KinBody prefix="right_" file="arm.kinbody.xml"/>

</Robot> </source>

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:

<source lang="xml">

 <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>

</source>

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 A Robot Arm and Hand

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.

<source lang="xml"> <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>
<manipulator name="arm">
  <base>base</base>
  <effector>link6</effector>
  <joints>hand_Bone_B1_Joint hand_Bone_B2_Joint hand_Bone_B3_Joint hand_Bone_A1_Joint hand_Bone_A2_Joint hand_Bone_A3_Joint hand_Bone_C1_Joint hand_Bone_C2_Joint hand_Bone_C3_Joint</joints>
  <closingdirection>0 1 1 0 1 1 0 1 1</closingdirection>
  <direction>1 0 0</direction>
</manipulator>

</robot> </source>

Final robot: Collada sdh kuka.jpg

Dual-arm example

Here is an example file of having a robot composed of two arms attached to a common link named chest.

<source lang="xml"> <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>
   <KinBody>
     <KinBody prefix="l_" file="schunk-lwa3.kinbody.xml"></KinBody>
     <RotationAxis>1 0 0 90</RotationAxis>
     <translation>0 -0.1 0.7</translation>
   </KinBody>
   <KinBody>
     <KinBody>prefix="r_" file="schunk-lwa3.kinbody.xml"></KinBody>
     <RotationAxis>1 0 0 -90</RotationAxis>
     <translation>0 0.1 0.7</translation>
   </KinBody>
   <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>
 <Manipulator name="leftarm">
   <base>l_base</base>
   <effector>l_link7</effector>
 </Manipulator>
 <Manipulator name="rightarm">
   <base>r_base</base>
   <effector>r_link7</effector>
 </Manipulator>

</Robot> </source>

Single arm: Schunk-lwa3.jpg

Dual arm: Schunk-lwa3-dual.jpg

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:

<source lang="xml"> <Environment>

 <plugin>libcustomreader</plugin>
 <robot name="wam" file="robots/barrettwam.robot.xml"/>
 <controller type="CustomController" robot="wam" args="">
   ..custom data....
 </controller>
 <module type="basemanipulation" args="wam"/>

</Environment> </source>

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 module 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.

Sensor

It is possible to have XML files that declare a sensor and its internal parameters. For example, data/camera.sensor.xml can look like:

<source lang="xml"> <sensor type="BaseCamera">

 <KK>640 640 320 240</KK>
 <width>640</width>
 <height>480</height>
 <framerate>5</framerate>
 <color>0.5 0.5 1</color>

</sensor> </source>

In order to attach a sensor defined by a file to a robot link do:

<source lang="xml"> <Robot>

 <AttachedSensor name="MyCamera">
   <sensor file="camera.sensor.xml">
   </sensor>
 </AttachedSensor>

</Robot> </source>

It is also possible to put a sensor directly in the environment without a robot. Such a sensor will not have any geometry associated with it, and will only act as a sensing source.

<source lang="xml"> <Environment>

 <sensor name="mysensor" file="camera.sensor.xml">
   <translation>0 1 0</translation>
   <rotationaxis>1 0 0 45</rotationaxis>
 </sensor>

</Environment> </source>


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
  module - 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), file, skipgeometry, scalegeometry, enable
    geom - attributes: name, type (box, sphere, trimesh, cylinder), render (true,false), modifiable (true,false)
      ambientcolor - 3 float
      collision - attributes: file, scale
      diffusecolor - 3 float
      extents - 3 float [box]
      height - float [cylinder]
      quat - 4 float
      radius - float [cylinder, sphere]
      render - attributes: file, scale
      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
    offsetfrom - body/link name
  joint - attributes: enable (true, false), type (hinge, slider, universal, hinge2, spherical), circular(true, false), mimic_pos (math equation), mimic_vel (math equation), mimic_accel (math equation)
    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
    maxveldeg - dof floats
    maxaccel - dof floats
    maxacceldeg - dof floats
    mode - int [amotor]
    offsetfrom - body/link name
    resolution - float
    weight - dof floats
    initial - dof floats
    maxtorque - 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
      ... - fields defined by SensorBase class instantiated by type
  controller - type args
  jointvalues
  kinbody - name
  manipulator - attributes: name
    base - link name
    closed - k floats
    effector - link name
    iksolver - string
    gripperjoints - k joint names
    closingdirection - k floats
    direction - 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