Skip to content
  • Home
  • About the Blog
  • About the Author
  • Sitemap

Abdur Rosyid's Blog

Just a few notes on mechanical engineering and robotics

Using xacro to simplify URDF

July 13, 2021 by Abdur Rosyid

xacro is a language defined in ROS to be used to:

  • simplify URDF; make URDF cleaner
  • make it easier to change the URDF’s parameters
  • create a modular URDF

xacro:property

Use case 1:

Using xacro:property, we can use constants as variables so that it is easier to change them or to avoid redundancy (repetition) in their use.

Step 1: Declare the xacro:property. The syntax of the declaration is the following:

1
<xacro:property name="variable_name" value="variable_value" />

Step 2: Use it. We can use the defined “xacro:property” by using ${ } construct.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<xacro:property name="width" value="0.2" />
<xacro:property name="bodylen" value="0.6" />
<link name="base_link">
    <visual>
        <geometry>
            <cylinder radius="${width}" length="${bodylen}"/>
        </geometry>
        <material name="blue"/>
    </visual>
    <collision>
        <geometry>
            <cylinder radius="${width}" length="${bodylen}"/>
        </geometry>
    </collision>
</link>

Use case 2:

We can also use xacro:property for naming. First we declare the property and afterwards we can use it by using ${ } construct.

Example:

1
2
<xacro:property name=”robotname” value=”marvin” />
<link name=”${robotname}_base_link” />

This will generate:

1
<link name=”marvin_base_link” />

Use case 3:

We can also use xacro:property to perform some basic mathematics operations such as +, -, *, /, sin, cos, and parentheses.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<xacro:property name="width" value="0.2" />
<xacro:property name="bodylen" value="0.6" />
<xacro:property name="reflect" value="1" />
 
<link name="base_link">
    <visual>
        <geometry>
            <cylinder radius="${bodylen/2}" length="${bodylen}"/>
        </geometry>
        <material name="blue"/>
        <origin xyz="${reflect*(width+.02)} 0 0.25" />
    </visual>
    <collision>
        <geometry>
            <cylinder radius="${bodylen/2}" length="${bodylen}"/>
        </geometry>
    </collision>
</link>

In the example above, we perform two maths:

1
2
${bodylen/2}
${reflect*(width+.02)}

xacro:macro

Using xacro:macro, we can provide modularity in the robot description.

Simple xacro:macro

Step 1: Declare the xacro:macro

1
2
3
4
5
<xacro:macro name="macro_name">
   ...
   [macro content]
   ...
</xacro:macro>

Step 2: Use it, by calling the xacro:macro.

1
<xacro:macro_name />

For example, first we declare the xacro:macro:

1
2
3
4
5
<xacro:macro name="default_color">
  <material name="blue">
    <color rgba="0 0 0.8 1"/>
  </material>
</xacro:macro>

Subsequently, we can call the xacro:macro by writing:

1
<xacro:default_color />

Parametrized xacro:macro

Step 1: Declare the xacro:macro

1
2
3
4
5
<xacro:macro name="macro_name" params="my_parameter_1 ... my_parameter_n">
   ...
   [macro content]
   ...
</xacro:macro>

Step 2: Use it, by calling the xacro:macro and specifying the parameter value:

1
<xacro:macro_name my_parameter_1="value" ... my_parameter_n="value"/>

For example, first we declare we declare a xacro:macro with mass being parametrized:

1
2
3
4
5
6
7
8
    <xacro:macro name="default_inertial" params="mass">
        <inertial>
                <mass value="${mass}" />
                <inertia ixx="1.0" ixy="0.0" ixz="0.0"
                     iyy="1.0" iyz="0.0"
                     izz="1.0" />
        </inertial>
    </xacro:macro>

Subsequently, we can use the xacro:macro by calling it and specifying a certain value of the mass:

1
<xacro:default_inertial mass="10"/>

Using xacro:macro to construct a modular robot description

We need to have the main part (which basically uses/integrates the xacro:macro(s)) and one or more child parts. The child parts may consist of URDF and xacro files.

For example, we have a URDF file called “base_link”. We want to connect another module to the “base_link”. The module, in this case, can be conveniently written as a xacro file.

Let’s say we have the URDF file namely “my_urdf_file.urdf” which looks like this:

1
2
3
4
5
6
<?xml version="1.0"?>
<robot name="my_urdf">
  <link name="base_link">
    ...
  </link>
</robot>

The xacro child part is written in a file called “my_xacro_child_file.xacro” which looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<robot  xmlns:xacro="http://ros.org/wiki/xacro" name="name_of_child_part">
  <xacro:macro name="my_xacro_child_part" params="connected_to">
    <link name="additional_link">
      ...
    </link>
    <joint name="connection_joint" type="revolute">
      <parent link="${connected_to}"/>
      <child link="additional_link"/>
      ...
    </joint>
    ...
  </xacro:macro>
</robot>

We can see that the connection between the base_link and the additional_link is performed in the xacro_child part above.

The main part is written in a file called “main_file.xacro” which looks like this:

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="name_of_main_part">
  <!-- URDF child_part -->
  <xacro:include filename="$(find my_robot_description)/urdf/my_urdf_file.urdf" />
  <!-- xacro child part -->
  <xacro:include filename="$(find my_robot_description)/urdf/my_xacro_child_file.xacro" />
  <xacro:my_xacro_child_part connected_to="base_link"/>
</robot>

We can see that both the main and child xacro files should declare the xacro inside the <robot> tags.

For the main xacro, we can see that it consists of two parts:

  • xacro:include –> this is to include all the files used.
  • xacro:name_of_child_xacro –> this is to call the xacro_child_part.

In building such modularity, it is important to track the order of the links and joints, i.e. to pay attention to which one is the base part and which one is the child part connected to the base part, etc.

Running xacro:macro

To run the “main_file.xacro” in the terminal, use the following command:

1
rosrun xacro xacro ./src/my_robot_description/urdf/main_file.xacro > ./src/my_robot_description/urdf/main_file.urdf

To run the “main_file.xacro” inside a launch file (which also runs “robot_state_publisher”, “joint_state_publisher”, and “rviz” nodes), we write a launch file that looks like this:

1
2
3
4
5
6
7
8
9
<launch>
  <arg name="gui" default="true"/>
  <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find my_robot_description)/urdf/main_file.xacro'" />
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
  <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
    <param name="use_gui" value="$(arg gui)"/>
  </node>
  <node name="rviz" pkg="rviz" type="rviz" if="$(arg gui)"/>
</launch>

Notice: It is quite common to name a xacro file as “my_xacro.urdf.xacro”. This does not matter since only what comes after the last dot is considered as the extension of the file. This quite common practice is probably to indicate that the xacro file contains URDF.

Post navigation

Previous Post:

Writing URDF

Next Post:

Using URDF in Gazebo Simulation

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • STEM 101
  • Robotics
  • Kinematics
  • Dynamics
  • Control
  • Robot Operating System (ROS)
  • Robot Operating System (ROS2)
  • Software Development
  • Mechanics of Materials
  • Finite Element Analysis
  • Fluid Mechanics
  • Thermodynamics

Recent Posts

  • Pull Request on Github
  • Basics of Git and Github
  • Conda vs Docker
  • A Conda Cheat Sheet
  • Installing NVIDIA GPU Driver on Ubuntu

Archives

  • June 2025
  • July 2021
  • June 2021
  • March 2021
  • September 2020
  • April 2020
  • January 2015
  • April 2014
  • March 2014
  • March 2012
  • February 2012
  • June 2011
  • March 2008
© 2025 Abdur Rosyid's Blog | WordPress Theme by Superbthemes