How to Create the URDF in a Correct Way.

Ultron Inverse
5 min readJul 29, 2023

--

Introduction

Almost all of you are familiar with ROS. ROS uses URDF (Unified Robot Description Format) to define the kinematic model and visual representation of a robot. While many open-source URDF files are available for commonly used robots in the robotic industry, you often need to create your own custom URDF file from scratch for your robot. Here are some points I would like to share with you that will help you create and maintain URDF files for your robot.

Positioning Links and Joints

As you know, the URDF file contains <link> elements that are connected with each other using <joint> element. Both elements have <origin> elements that define the position of their parent element (in <link>, <origin> appears in each of the <inertia>, <visual> and <collision> elements).

A common mistake that I often see my peers make (and myself) is wrongly defining the <origin> element. Let me explain this with example of a simple mobile robot.

I am considering a simple mobile robot with 4 wheels (for simplicity all four wheels are driven wheel and they do not have any steering angle).

Image-1: ROBOT-1
image-2: ROBOT-2

The dimensions of the Robots in the image-1 and image-2 are same and positions of the wheels are also same. At least visually they look same but their urdf-files are different.

The <origin> elements of wheels are described differently.

• For the robot in image-1 the displacement of the wheels w.r.t. to body is defined in <origin> inside the <joint> element.

•For the robot in the image-2 the displacement of the wheels w.r.t. to body is defined in the <origin> inside the <link> element.

Have a look at their URDFs

Robot-1 (correct way)

<!-- Correct Robot Description -->

<link name="front_left_wheel">
<visual>
<origin xyz="0 0 0" rpy="1.57 0 0"/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
</visual>
<collision>
<origin xyz="0 0 0" rpy="1.57 0 0"/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
</collision>
</link>
<joint name="front_left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="front_left_wheel"/>
<origin xyz="0.4 -0.5 -0.1"/>
<axis xyz="0 1 0"/>
</joint>

Robot-2 (wrong way)

<!-- wrong Robot Description -->

<link name="front_left_wheel">
<visual>
<origin xyz="0.4 -0.5 -0.1" rpy="1.57 0 0"/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
</visual>
<collision>
<origin xyz="0.4 -0.5 -0.1" rpy="1.57 0 0"/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
</collision>
</link>
<joint name="front_left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="front_left_wheel"/>
<origin xyz="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>

Wrong TF

The problem with robot-2 is that its tf (Transform) will be published incorrectly and it would not be simulated properly in Gazebo. To understand this better, let’s visualize the tf frames in gazebo for both the robots.

image-3: ROBOT-1 tf frames
image-4: ROBOT-2 tf frames

As you can see the tf frames of wheel in image-3 are properly situated at wheel centers. But in the image-4, all the tf frames are located at the body-link.

lets rotate the wheels slightly and zoom in to see all tf frames.

image-5: ROBOT-2 tf frames on body link.

Thats why Pay attention to <origin> elements when creating your robot URDF

Use Xacro

Xacro (XML Macros) is a powerful tool used to simplify the creation and maintenance of URDF (Unified Robot Description Format) files in ROS (Robot Operating System). It comes when you install the ROS in your system. for some reason if its not there, you can install it with the following command, Replace <distro> with the ROS-distribution name (e.g., melodic, noetic, foxy):

sudo apt install ros-<distro>-xacro

Here are some benifits of using xacro to create your robot’s description:

  1. Modularity and Reusability (most useful)

Suppose you have two robots, R100 and R500 for two different payload category but both robots use the same payload attachment. Instead of defining the payload attachment in both robot’s urdf files, you can create a seperate file for payload-attachment and include it in robot’s urdf file.

File structure:

urdf/
├── payload_attachment.xacro
├── R100.xacro
└── R500.xacro

R100.xacro file:

<robot>
<!-- Other robot links and joints -->

<!-- Include the attachment macro -->
<xacro:include filename="payload_attachment.xacro" />
<xacro:payload_attachment name="pa100" />
</robot>

R500.xacro file:

<robot>
<!-- Other robot links and joints -->

<!-- Include the attachment macro -->
<xacro:include filename="payload_attachment.xacro" />
<xacro:payload_attachment name="pa500" />
</robot>

2. Parameterization

You can parameterized any value and modify them later. Also these parameters can be modified from launch file or command line arguments. see the example below where joint velocity and effort limits are parameterized.

3. Maintaince and Updates

e.g.

<robot>
<xacro:param name="max_vel" default="1.0" />
<xacro:param name="max_effort" default="30" />

<joint name="my_joint_1" type="continuous">
<origin xyz="0 0 1" rpy="0 0 3.1416"/>
<parent link="body"/>
<child link="wheel_1"/>

<limit effort="${max_effort}" velocity="${max_vel}" />
</joint>


<!-- definition for join 2 and joint 3 -->

<joint name="my_joint_4" type="continuous">
<origin xyz="0 0 1" rpy="0 0 3.1416"/>
<parent link="body"/>
<child link="wheel_4"/>

<limit effort="${max_effort}" velocity="${max_vel}" />
</joint>

</robot>

4. Conditional Inclusion

You can use xacro to include a perticular file in your description based on if certain conditions satisfy. e.g. :

<robot>
<xacro:param name="include_gripper" default="true" />

<!-- Robot links and joints -->

<!-- Conditionally include the gripper -->
<xacro:if value="${include_gripper}">
<xacro:include filename="gripper.xacro" />
<xacro:gripper_link name="robot_gripper" />
</xacro:if>
</robot>

Integration for gazebo

If you need to simulate your robot in Gazebo (you can use other simulator from many available ones), you have to make some changes in your robot’s description file. Gazebo is independent of ROS and uses SDF (Simulation Description Format), but it also has support for urdf. To properly organize your robot’s description file, it’s better not to have gazebo related elements in your robot’s main description file. Create a seperate file for gazebo related elements and use xacro to include that in you robot’s main description.

File structure:

urdf/
├── my_robot.gazebo
└── my_robot.xacro

inside your my_robot.gazebo file:

<robot>
<gazebo>
<!-- gazebo element details -->
</gazebo>
<!-- other gazebo elements -->
</robot>

inside your `my_robot.xacro` file:

<robot>
<!-- Other robot links and joints -->

<!-- Include the attachment macro -->
<xacro:include filename="my_robot.gazebo" />
</robot>

One more thing need to take care of that gazebo requires to have <inertia> element inside each <link> element of robot description. I would suggest to include this element in your robot’s description irrespective of whether you need to use Gazebo or not.

--

--

Ultron Inverse

Technology Enthusiast | Let us Explore the Technology in More Insightful Manner | Contents are More Than Just Information |