C++ Advanced · Lesson 18 of 23
URDF and robot_state_publisher
Describing links and joints, and publishing the robot's transforms from joint states.
Estimated time · 90–120 min
Learning goals
What you will understand
- Explain urdf and robot_state_publisher in your own words
- Use it in a small robotics example
- Verify the result instead of assuming it worked
Understand the idea first
The mental model
URDF is an XML description of a robot: links (rigid bodies with shape, mass and inertia) connected by joints (fixed, revolute, prismatic) with limits. robot_state_publisher reads the URDF and the /joint_states topic and publishes the TF frames for every link.
Check a URDF with check_urdf, view it in RViz2, and move its joints with joint_state_publisher_gui. Keep the description in its own package, use xacro for repeated parts, and always include limits, inertia and collision shapes if you plan to simulate it.
Guided lesson
Work through these steps
- 1.
Read the urdf and robot_state_publisher example and identify what each line owns or changes.
- 2.
Create a small source file, compile with -std=c++17 and warnings enabled, and run it.
- 3.
Change one input, predict the result before running, then compare the output.
- 4.
Record one compiler or runtime error and explain the correction in your own words.
Worked example
Read it before you run it
<robot name="mini_arm">
<!-- Root element naming the robot. -->
<link name="base_link"/>
<!-- The fixed base of the arm. -->
<link name="upper_arm"/>
<!-- A moving link. -->
<joint name="shoulder" type="revolute">
<!-- A joint that rotates within limits. -->
<parent link="base_link"/>
<!-- The joint connects to the base... -->
<child link="upper_arm"/>
<!-- ...and moves the upper arm. -->
<axis xyz="0 0 1"/>
<!-- Rotate around the vertical Z axis. -->
<limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
<!-- Range in radians, max torque in N·m and max speed in rad/s. -->
</joint>
<!-- End of the joint. -->
</robot>
<!-- End of the robot description. -->What the example is doing
- 1.Read declarations from right to left: identify each value's type, name, and initial value.
- 2.Follow the data through each expression before considering syntax shortcuts.
- 3.Compile with warnings enabled; a clean build is part of the result, not an optional polish step.
Watch it run · Robot arm
See what this code does
The terminal types this lesson's practice solution and runs it. The scene shows the kind of robot behaviour that code drives. It plays by itself and loops.
Demo for URDF and robot_state_publisher. Expected result: check_urdf mini_arm.urdf -> robot name is: mini_arm
Practice code
Now type it yourself
Copy the starter into your ROS 2 package, replace every TODO, then build with colcon build and run it from a sourced terminal.
<!-- mini_arm.urdf -->
<robot name="mini_arm">
<link name="base_link"/>
<link name="upper_arm"/>
<!-- TODO: add a revolute joint "shoulder" from base_link to upper_arm, rotating about Z, limited to +-1.57 rad -->
</robot>Expected output
check_urdf mini_arm.urdf -> robot name is: mini_armStuck? Show the full solution (try it yourself first)
<!-- mini_arm.urdf -->
<robot name="mini_arm">
<link name="base_link"/>
<link name="upper_arm"/>
<joint name="shoulder" type="revolute">
<parent link="base_link"/>
<child link="upper_arm"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
</joint>
</robot>Expected result
How you know it worked
- After adding the shown fragment to the guided exercise with its listed headers and surrounding program, the finished program builds with -Wall -Wextra -Wpedantic.
- Changing the stated input produces the result you predicted.
Practical exercise
Apply the lesson
Extend mini_arm with an elbow joint and a forearm link, validate it with check_urdf, run robot_state_publisher with it, publish /joint_states with joint_state_publisher_gui, and watch the frames in RViz2.
Before you continue
- The program builds with -std=c++17 and no warnings
- You can explain the key rule without reading the example
- The normal and edge cases both have recorded results
If something goes wrong
Start at the first error. Check spelling, required #include lines, and whether the declaration appears before use.
Print the inputs and intermediate values, then check conversions, units, and collection order.