Skip to main content

URDF (Unified Robot Description Format) for Humanoids

Learning Objectives​

By the end of this chapter, you will be able to:

  • Create URDF files to describe robot kinematics, dynamics, and visual properties
  • Integrate URDF models into ROS 2 for simulation and visualization
  • Implement advanced URDF concepts for complex humanoid structures
  • Understand joint limits, transmissions, and sensor attachments

Introduction to URDF​

Unified Robot Description Format (URDF) is an XML format for representing a robot model. It describes the physical and visual properties of a robot, including its links, joints, and the relationships between them. URDF is widely used in ROS and ROS 2 for robot simulation, visualization, and kinematic analysis.

Basic URDF Structure​

A basic URDF file consists of:

  • Links: Rigid bodies with physical properties (mass, inertia, visual, collision)
  • Joints: Connections between links with kinematic properties (type, limits, axis)
  • Materials: Visual properties (color, texture)

Basic URDF Example​

<?xml version="1.0"?>
<robot name="simple_robot">
<!-- Base link -->
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.6" radius="0.2"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.6" radius="0.2"/>
</geometry>
</collision>
<inertial>
<mass value="10"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>

<!-- Attachment link -->
<link name="attachment">
<visual>
<geometry>
<box size="0.1 0.1 0.1"/>
</geometry>
<material name="red">
<color rgba="0.8 0 0 1"/>
</material>
</visual>
</link>

<!-- Joint connecting the links -->
<joint name="base_to_attachment" type="fixed">
<parent link="base_link"/>
<child link="attachment"/>
<origin xyz="0 0 0.3" rpy="0 0 0"/>
</joint>
</robot>

Links represent rigid bodies in the robot. Each link can have multiple properties:

Visual Properties​

  • Define how the link appears in simulation and visualization
  • Include geometry, material, and origin

Collision Properties​

  • Define the collision boundaries for physics simulation
  • Can be different from visual geometry for performance

Inertial Properties​

  • Define the mass and inertia tensor for dynamics simulation
  • Required for physics simulation
<link name="link_name">
<!-- Visual representation -->
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<!-- Options: box, cylinder, sphere, mesh -->
<box size="1 1 1"/>
</geometry>
<material name="material_name">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>

<!-- Collision representation -->
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="1 1 1"/>
</geometry>
</collision>

<!-- Inertial properties -->
<inertial>
<mass value="1.0"/>
<origin xyz="0 0 0" rpy="0 0 0"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>

Joints in URDF​

Joints define the kinematic relationships between links. Common joint types include:

  • revolute: Rotational joint with limits
  • continuous: Rotational joint without limits
  • prismatic: Linear sliding joint with limits
  • fixed: No movement between links
  • floating: 6-DOF joint (not commonly used in URDF)

Joint Definition Example​

<joint name="joint_name" type="revolute">
<parent link="parent_link_name"/>
<child link="child_link_name"/>
<origin xyz="0 0 1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="100" velocity="1"/>
</joint>

URDF for Humanoid Robots​

Humanoid robots have complex kinematic structures with multiple limbs. Here's a simplified example of a humanoid leg:

<?xml version="1.0"?>
<robot name="humanoid_leg">
<!-- Hip joint -->
<link name="hip">
<visual>
<geometry>
<box size="0.1 0.1 0.1"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
</link>

<!-- Upper leg -->
<link name="upper_leg">
<visual>
<geometry>
<cylinder length="0.5" radius="0.05"/>
</geometry>
<material name="gray">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.5" radius="0.05"/>
</geometry>
</collision>
<inertial>
<mass value="2.0"/>
<inertia ixx="0.05" ixy="0.0" ixz="0.0" iyy="0.05" iyz="0.0" izz="0.005"/>
</inertial>
</link>

<!-- Lower leg -->
<link name="lower_leg">
<visual>
<geometry>
<cylinder length="0.5" radius="0.05"/>
</geometry>
<material name="gray">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.5" radius="0.05"/>
</geometry>
</collision>
<inertial>
<mass value="1.5"/>
<inertia ixx="0.04" ixy="0.0" ixz="0.0" iyy="0.04" iyz="0.0" izz="0.004"/>
</inertial>
</link>

<!-- Foot -->
<link name="foot">
<visual>
<geometry>
<box size="0.2 0.1 0.05"/>
</geometry>
<material name="black">
<color rgba="0.1 0.1 0.1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.2 0.1 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0.0" ixz="0.0" iyy="0.002" iyz="0.0" izz="0.002"/>
</inertial>
</link>

<!-- Hip to upper leg joint -->
<joint name="hip_joint" type="revolute">
<parent link="hip"/>
<child link="upper_leg"/>
<origin xyz="0 0 -0.05" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="100" velocity="1"/>
</joint>

<!-- Upper leg to lower leg joint (knee) -->
<joint name="knee_joint" type="revolute">
<parent link="upper_leg"/>
<child link="lower_leg"/>
<origin xyz="0 0 -0.5" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="0" upper="2.35" effort="100" velocity="1"/>
</joint>

<!-- Lower leg to foot joint (ankle) -->
<joint name="ankle_joint" type="revolute">
<parent link="lower_leg"/>
<child link="foot"/>
<origin xyz="0 0 -0.5" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit lower="-0.785" upper="0.785" effort="50" velocity="1"/>
</joint>
</robot>

Advanced URDF Concepts​

Transmissions​

Transmissions define the relationship between joints and actuators:

<transmission name="joint1_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="joint1">
<hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
</joint>
<actuator name="joint1_motor">
<hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>

Gazebo-Specific Tags​

For simulation in Gazebo:

<gazebo reference="link_name">
<material>Gazebo/Blue</material>
<mu1>0.2</mu1>
<mu2>0.2</mu2>
</gazebo>

Sensors​

Adding sensors to URDF:

<link name="camera_link">
<visual>
<geometry>
<box size="0.05 0.05 0.05"/>
</geometry>
</visual>
</link>

<joint name="camera_joint" type="fixed">
<parent link="head"/>
<child link="camera_link"/>
<origin xyz="0.1 0 0" rpy="0 0 0"/>
</joint>

<gazebo reference="camera_link">
<sensor type="camera" name="camera1">
<pose>0 0 0 0 0 0</pose>
<visualize>true</visualize>
<update_rate>30.0</update_rate>
<camera name="head">
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>800</width>
<height>600</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
</camera>
</sensor>
</gazebo>

Integrating URDF with ROS 2​

Robot State Publisher​

To publish the robot's joint states and TF transforms:

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import JointState
from geometry_msgs.msg import TransformStamped
from tf2_ros import TransformBroadcaster
import math

class RobotStatePublisher(Node):
def __init__(self):
super().__init__('robot_state_publisher')

# Create joint state publisher
self.joint_pub = self.create_publisher(JointState, 'joint_states', 10)

# Create transform broadcaster
self.tf_broadcaster = TransformBroadcaster(self)

# Create timer to publish states
self.timer = self.create_timer(0.1, self.publish_joint_states)

def publish_joint_states(self):
# Create joint state message
msg = JointState()
msg.name = ['joint1', 'joint2', 'joint3']
msg.position = [math.sin(self.get_clock().now().nanoseconds * 1e-9),
math.cos(self.get_clock().now().nanoseconds * 1e-9),
0.0]
msg.header.stamp = self.get_clock().now().to_msg()
msg.header.frame_id = 'base_link'

self.joint_pub.publish(msg)

def main(args=None):
rclpy.init(args=args)
node = RobotStatePublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()

if __name__ == '__main__':
main()

URDF Best Practices​

  1. Mass and Inertia: Always define realistic mass and inertia properties
  2. Joint Limits: Set appropriate limits for safety and realism
  3. Collision Models: Use simplified geometries for collision detection
  4. Naming Conventions: Use consistent naming for links and joints
  5. Testing: Validate URDF with tools like check_urdf

Exercises​

  1. Create a URDF model for a simple 2-link manipulator
  2. Build a humanoid arm with shoulder, elbow, and wrist joints
  3. Add sensors to your URDF model and test in simulation
  4. Create a complete humanoid model with multiple limbs

Summary​

URDF is a powerful tool for describing robot models in ROS 2. Understanding how to create and structure URDF files is essential for simulation, visualization, and control of robotic systems. For humanoid robots, special attention must be paid to the complex kinematic chains and the integration with ROS 2's state publishing mechanisms.