Skip to content

Robot Operating System: How to Create a Robot Simulation Model (Part 2)

By Sebastian Günther

Posted in Robots, Ros

In the last article, I showed how to model a 4-wheel robot with the Robot Operating System. We explored how to model a robot with the main concepts of links, shapes in the form of boxes, spheres or cylinders, and of joints, which define the connection and the positioning of the links. This model is expressed as an URDF file, an XML file format. The final model is very verbose and has lots of repetitions.

In this article, I will explain how to optimize this file by using an XML macro language called XACRO. Optimization means: We will shrink down the model from 101 lines of code to only 66 lines, we define macros that, similar to functions in a programming language, can be reused, and we prepare the model for adding additional properties.

The Robot Model

The final robot model that we created in the last article is the following URDF file (some overly repetitive tasks are left out):

<?xml version="1.0"?>
<robot name="bot">
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0 0 0"/>
      </geometry>
      <material name="red">
        <color rgba="1 0 0 1"/>
      </material>
    </visual>
  </link>

  <link name="torso">
    <visual>
      <geometry>
        <box size="0.6 0.3 0.1"/>
      </geometry>
      <material name="green">
        <color rgba="0 1 0 1"/>
      </material>
    </visual>
  </link>

  <joint name="base_link_torso" type="continuous">
    <parent link="base_link" />
    <child link="torso" />
    <origin xyz="0 0 0" rpy="0 0 0"/>
  </joint>

  <link name="left_wheel_frontside">
    <visual>
      <geometry>
        <cylinder radius="0.04" length="0.05" />
      </geometry>
      <material name="red">
        <color rgba="1 0 0 1"/>
      </material>
    </visual>
  </link>

  <joint name="base_link_left_wheel_frontside" type="continuous">
    <parent link="base_link" />
    <child link="left_wheel_frontside" />
    <origin xyz="0.2 0.2 -0.05" rpy="1.570796 0 0"/>
  </joint>

  <!-- 
      ...
   -->
</robot>

Let’s identify the key aspects to improve:

  • wheel properties: All wheels share the same <cylinder> and <material> declaration. If I want to change e.g. the size of the wheel, I need to change 4 different spaces of the wheel
  • wheel declaration: The complete <link> declaration is repetitive, it only differs in the name
  • joints declaration: Similarly, the <joint> declaration is repetitive, it differs in the name of the links and where to place the links with the <origin> property.

We will improve the model with regard to these aspects. Let’s start with defining the wheel properties as variables.

Variables

A XACRO file is an XML file that must use the xacro namespace declaration. A minimal file is:

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="bot">
  <!-- .... -->
</robot>

Let’s define some variables in XACRO. These are defined as <xacro:property> , with a name and value attribute. The variable names need to use underscores instead of hyphens.

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="bot">
  <xacro:property name="wheel_radius" value="0.04" />
  <xacro:property name="wheel_length" value="0.05" />
  <xacro:property name="wheel_color_name" value="red" />
  <xacro:property name="wheel_color_rgb" value="1 0 0 1" />
</robot>

Macros

Macros are a powerful construct: They allow you to define complex XML structures that can be instantiated with the passed parameters.

The following macro contains a parameterized form of the wheel definition that we showed at the beginning of this article.

<xacro:macro name="wheel" params="wheel_name">
  <link name="${wheel_name}">
    <visual>
      <geometry>
        <cylinder radius="${wheel_radius}" length="${wheel_length}" />
      </geometry>
      <material name="${wheel_color_name}">
        <color rgba="${wheel_color_rgb}"/>
      </material>
    </visual>
  </link> 
</xacro:macro>

In Line 2, the macro's name wheel is defined, along with a list of parameters. We only need one parameter - name - because everything else is defined as properties. In macros, parameters and properties are referenced as ${param-name}. For example, in line 2, we reference the given name parameter, and in line 4, we reference the defined wheel properties of wheel radius and wheel name.

These templates are instantiated by using the name of the template in the tag name, and parameters are defined as attributes. This will look like this:

  <xacro:wheel name="right_wheel_frontside" />

Running XACRO from the Command Line

XACRO files can be manually rendered via the command line.

$> rosrun xacro xacro bot.xacro 

<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from bot.xacro                      | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="bot">
  <link name="right_wheel_frontside">
    <visual>
      <geometry>
        <cylinder length="0.05" radius="0.04"/>
      </geometry>
      <material name="red">
        <color rgba="1 0 0 1"/>
      </material>
    </visual>
  </link>

As we can see in the output, the wheel macro is successfully applied: It uses the passed wheel name, and the defined parameters for radius, length and color.

You can manually store the output by providing the -o filename.urdf parameter, but the preferred method is to reference it from a Launch File.

Running XACRO form a Launch File

In a ROS launch file, instead of referencing the URDF, you can also process the XASCRO file directly. We only need to make one change of the parameter robot_description.

<launch>
    <param name="robot_description" command="xacro $(find car-robot)/urdf/bot.xacro" />
    <!-- ... -->
</launch>

Finalizing the model: Adding Torso, Base Link, and Joints

For now, we just modeled the wheel. To complete the robot, we also need to add the base_link, the torso, and all the connecting joints.

the base_link and the torso will be rendered by a similarly defined macro.

 <xacro:macro name="box_link" params="name size color color_rgb" >
  <link name="${name}">
    <visual>
      <geometry>
        <box size="${size}"/>
      </geometry>
      <material name="${color}">
        <color rgba="${color_rgb}"/>
      </material>
    </visual>
  </link>
</xacro:macro>

And invoked as follows.

<xacro:box_link name="base_link" size="0 0 0" color="red" color_rgb="1 0 0 1" />
<xacro:box_link name="torso" size="0.6 0.3 0.1" color="green" color_rgb="0 1 0 1" />

The many definitions of the joints can also be simplified to a great degree.

<xacro:macro name="static_joint" params="name parent child">
  <joint name="${name}" type="continuous">
    <parent link="${parent}" />
    <child link="${child}" />
    <origin xyz="0 0 0" rpy="0 0 0"/>
  </joint>
</xacro:macro>

<xacro:macro name="wheel_joint" params="name parent child xyz ">
  <joint name="${name}" type="continuous">
    <parent link="${parent}" />
    <child link="${child}" />
    <origin xyz="${xyz}" rpy="1.570796 0 0"/>
  </joint>
</xacro:macro>

And instantiated:

<xacro:wheel name="right_wheel_frontside" />
<xacro:wheel_joint name="base_link_right_wheel_frontside" parent="base_link" child="right_wheel_frontside" xyz="0.2 -0.2 -0.05" />

<xacro:wheel name="right_wheel_backside" />
<xacro:wheel_joint name="base_link_right_wheel_backside" parent="base_link" child="right_wheel_backside" xyz="-0.2 -0.2 -0.05" />

<xacro:wheel name="left_wheel_frontside" /> 
<xacro:wheel_joint name="base_link_left_wheel_frontside" parent="base_link" child="left_wheel_frontside" xyz="0.2 0.2 -0.05" />

<xacro:wheel name="left_wheel_backside" /> 
<xacro:wheel_joint name="base_link_left_wheel_backside" parent="base_link" child="left_wheel_backside" xyz="-0.2 0.2 -0.05" />

That’s it - our URDF models is no completely expressed with XACRO.

Conclusion

In the Robot Operating System, robot models are expressed with XML files in the URDF format. This article showed how a verbose and repetitive model can be significantly compressed by using the XML macro language XACRO. XACRO allows to define variables and whole XML block templates. These templates can be instantiated with different values, which facilitates handling complex models. In the next blog post, we will continue to use XACRO when defining the dynamic aspects of our robot - stepping closer to the next evolution of our model, simulating how the robot can move and navigate within its world.