Introduction to URDF - LCAS/RBT1001 GitHub Wiki
The Unified Robotics Description Format (URDF) is an XML specification to model multi-body systems, such as robotic manipulators and mobile robots. URDF is "unified" because allows to specify multiple properties:
- kinematic chain structure
- visual appearance (shape and colour)
- collision zones
- physical properties (dynamics, inertia, contact coefficients, etc)
- other elements, such as controllers and plug-ins
The main elements (or tags) of interest are <robot>
, <link>
and <joint>
, which are nested in a hierarchical structure. <link>
and <joint>
are children of the <robot>
element, conversely <robot>
is a parent of the other two elements.
<robot>
<link>
...
</link>
<link>
...
</link>
<joint>
...
</joint>
</robot>
Each <link>
represent one part of the robot structure, and defines its characteristics. For example:
<robot name="simple_robot" xmlns:xacro="http://www.ros.org/wiki/xacro"> <!-- We need to specify the macro xml language we are using -->
<link name="world"/>
<link name="base_link"> <!-- Each link should have a name to distinguish and refer to them -->
<visual>
<geometry>
<box size="0.2 0.2 0.2"/> <!-- This specifies the shape of the link -->
</geometry>
<material name="base_material"> <!-- You need to give a name to the material -->
<color rgba="0.5 0.5 0.5 1"/> <!-- This specifies the color of the link -->
</material>
</visual>
</link>
<link name="link_1">
<visual>
<geometry>
<cylinder length="0.6" radius="0.1"/>
</geometry>
<material name="link1_material">
<color rgba="0 1 0 1"/>
</material>
</visual>
</link>
</robot>
A <joint>
defines how links are connected to one another they , e.g.:
<robot name="simple_robot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<link name="world"/>
<link name="base_link">
...
</link>
<link name="link_1">
...
</link>
<joint name="fixed" type="fixed"> <!-- it's a fixed frame because we do not want the base to move -->
<parent link="world"/> <!-- parent, because in the chain sequence comes before the child -->
<child link="base_link"/> <!-- This is the child, connected by the joint to the parent -->
</joint>
<joint name="base_to_link_1" type="continuous"> <!-- Continuous, meaning it can rotate without upper/lower limits -->
<parent link="base_link"/>
<child link="link_1"/>
</joint>
</robot>
Try it yourself:
- Create a file named
simple_robot.urdf.xacro
insideRBT1001/src/week2/description/urdf/
- Add two links and a joint to the urdf (based on the example above)
- Run
rebuild
- Visualise the model:
ros2 launch week2 view_robot.launch.py description_file:=simple_robot.urdf.xacro
. Note here we have passed thedescription_file
argument with the name of the model you have created. - The Joint State Publisher window, allows you to modify the q of each joint in the model.
As you can observe, the two robot parts are overlapping and they are both centred in the world origin <0,0,0>. That is because we have not specified their frames.
Refer to the documentation, https://wiki.ros.org/urdf/XML/link and https://wiki.ros.org/urdf/XML/joint, for all the possible link and joint elements and arguments.
By default, the origin of each link and joint frames are in the fixed frame <0,0,0>.
Let's modify the URDF to have the following 1 DOF arm:
First, we need to "correct" the visual geometry position as, by default most geometries have their origin in the centre of the shape (see the documentation for link above). We can modify the visual origin with:
<link name="base_link">
<visual>
<origin xyz="0 0 0.1" rpy="0 0 0"/><!-- This way we offset the position of the box's centre-->
<geometry>
<box size="0.2 0.2 0.2"/>
</geometry>
...
</link>
<link name="link_1">
<visual>
<origin xyz="0 0 0.3" rpy="0 0 0"/> <!-- This way we offset the position of the cylinder's centre-->
<geometry>
<cylinder length="0.6" radius="0.1"/>
</geometry>
...
</link>
Try it yourself:
- Modify the URDF as above
- Compile and visualise as before
Now we need to act on the joint. This allows to specify the pose of the frame q1 and the axis of rotation for revolute joints (or translation for prismatic joints).
<joint name="base_to_link_1" type="continuous">
<origin xyz="0 0 0.2" rpy="${pi/2} 0 0"/> <!-- Rotate and offset the link (not its geometry) -->
<axis xyz="0 1 0"/> <!-- This is the axis of rotation, by default rotation is on the x axis-->
<parent link="base_link"/>
<child link="link_1"/>
</joint>
Try it yourself:
-
Modify the URDF as above
-
Compile and visualise as before
-
On RVIZ, click "Add" (on the bottom left):
-
Add an "Axes" object:
-
You can now change the link frame shown by selecting a different "Reference Frame" (from the left bar):
Finally, we now need to define the origin position of the base link of our robot with respect to the world frame base on the requirements of the problem.
<joint name="fixed" type="fixed">
<origin xyz="2.5 -1 0" rpy="0 0 0"/>
<parent link="world"/>
<child link="base_link"/>
</joint>
Try it yourself:
- Modify the URDF as above
- Compile and visualise as before
- On a terminal, run:
ros2 launch week2 view_robot.launch.py
. This will open the configuration of a 2 DOF arm with two revolute joints. - On the VSCode editor, open the file
RBT1001/src/robots_description/rrbot/urdf/rrbot_descriprion.urdf.xacro
to visualise the robot description. - See how in URDF you can specify macro arguments to avoid inserting "magic numbers" (bad practice!); e.g.,
<xacro:property name="height1" value="2" />
- See how URDF allows to specify collision areas and inertia parameters for the links; joint limits and dynamic parameters for the joints.