URDF (Unified Robot Description Format) for Humanoids
URDF (Unified Robot Description Format) is an XML format for representing a robot model. URDF is used extensively in ROS to describe robots in terms of their joints, links, visual and collision properties, and more. When designing humanoid robots, URDF plays a crucial role in specifying the physical structure and kinematic properties.
What is URDF?
URDF stands for Unified Robot Description Format. It is an XML file format used to describe robots in ROS. A URDF file contains information about:
- Robot's physical structure (links)
- How parts are connected (joints)
- Visual appearance (collision and visual properties)
- Kinematic properties (inertial properties)
- Sensors attached to the robot
URDF Structure for Humanoid Robots
A humanoid robot URDF typically contains multiple limbs (arms, legs), a torso, and a head. Each limb is modeled as a series of links connected by joints.
Basic URDF Elements
<?xml version="1.0"?>
<robot name="humanoid_robot">
<!-- Links define the physical parts of the robot -->
<link name="base_link">
<visual>
<geometry>
<box size="0.2 0.1 0.1"/>
</geometry>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.2 0.1 0.1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
</link>
<!-- Joints define how links connect -->
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0.1 0 0" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1"/>
</joint>
<link name="link1">
<!-- Link definition similar to base_link -->
</link>
</robot>
Designing a Humanoid Robot in URDF
Basic Structure
A humanoid robot typically includes:
- Torso / Pelvis (base link)
- Two legs (hip, knee, ankle, foot)
- Two arms (shoulder, elbow, wrist, hand)
- Neck and head
Example URDF for a Simple Humanoid
<?xml version="1.0"?>
<robot name="simple_humanoid">
<!-- Torso / Base Link -->
<link name="torso">
<visual>
<geometry>
<box size="0.2 0.3 0.4"/> <!-- Width x Depth x Height -->
</geometry>
<origin xyz="0 0 0.2"/>
<material name="gray">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.2 0.3 0.4"/>
</geometry>
<origin xyz="0 0 0.2"/>
</collision>
<inertial>
<mass value="5"/>
<inertia ixx="0.3" ixy="0" ixz="0" iyy="0.2" iyz="0" izz="0.1"/>
</inertial>
</link>
<!-- Head -->
<link name="head">
<visual>
<geometry>
<sphere radius="0.1"/>
</geometry>
<material name="skin">
<color rgba="0.8 0.6 0.4 1"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="0.02" ixy="0" ixz="0" iyy="0.02" iyz="0" izz="0.02"/>
</inertial>
</link>
<!-- Joint connecting torso and head -->
<joint name="neck_joint" type="revolute">
<parent link="torso"/>
<child link="head"/>
<origin xyz="0 0 0.4"/>
<axis xyz="0 0 1"/>
<limit lower="-0.5" upper="0.5" effort="1" velocity="2"/>
</joint>
<!-- Left Arm -->
<link name="left_shoulder">
<visual>
<geometry>
<box size="0.1 0.15 0.15"/>
</geometry>
<material name="gray"/>
</visual>
<collision>
<geometry>
<box size="0.1 0.15 0.15"/>
</geometry>
</collision>
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001"/>
</inertial>
</link>
<!-- Joint connecting torso and shoulder -->
<joint name="left_shoulder_joint" type="revolute">
<parent link="torso"/>
<child link="left_shoulder"/>
<origin xyz="0.15 0.1 0.2"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="5" velocity="3"/>
</joint>
<!-- Right arm, legs, and other body parts would follow similar pattern -->
</robot>
Advanced URDF Features for Humanoids
Transmission Elements
To connect the robot to a control system, transmission elements are added:
<transmission name="left_shoulder_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="left_shoulder_joint">
<hardwareInterface>PositionJointInterface</hardwareInterface>
</joint>
<actuator name="left_shoulder_motor">
<hardwareInterface>PositionJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
Gazebo-Specific Elements
For simulation in Gazebo, additional elements are often needed:
<gazebo reference="torso">
<material>Gazebo/Gray</material>
<mu1>0.2</mu1>
<mu2>0.2</mu2>
</gazebo>
URDF Tools and Verification
Using check_urdf
After creating a URDF file, verify its validity:
check_urdf path/to/robot.urdf
Using urdf_to_graphiz
Visualize the robot structure:
urdf_to_graphviz path/to/robot.urdf
Best Practices for Humanoid URDF
- Use proper units: All dimensions in meters, mass in kilograms
- Realistic inertial properties: Accurate mass and inertia values improve simulation
- Joint limits: Define appropriate limits for each joint
- Collision vs. Visual: Use simple shapes for collision and detailed for visuals
- Naming convention: Use consistent naming across all links and joints
- Kinematic chain: Ensure proper parent-child relationships
- Mounting points: Define attachment points for accessories
Creating URDF with Python
While URDF is an XML format, it can be programmatically generated using Python:
import xml.etree.ElementTree as ET
def create_simple_link(name, mass, geometry_type="box", size=[0.1, 0.1, 0.1]):
link = ET.Element("link", name=name)
# Visual element
visual = ET.SubElement(link, "visual")
vis_geom = ET.SubElement(visual, "geometry")
ET.SubElement(vis_geom, geometry_type, size=" ".join(map(str, size)))
# Collision element
collision = ET.SubElement(link, "collision")
coll_geom = ET.SubElement(collision, "geometry")
ET.SubElement(coll_geom, geometry_type, size=" ".join(map(str, size)))
# Inertial element
inertial = ET.SubElement(link, "inertial")
ET.SubElement(inertial, "mass", value=str(mass))
ET.SubElement(inertial, "inertia",
ixx="0.01", ixy="0", ixz="0",
iyy="0.01", iyz="0", izz="0.01")
return link
# Example usage
robot = ET.Element("robot", name="humanoid")
torso = create_simple_link("torso", 5.0, "box", [0.2, 0.3, 0.4])
robot.append(torso)
Integration with ROS
Once the URDF is created, it can be used in ROS nodes:
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import JointState
from tf2_ros import TransformBroadcaster
import math
class URDFRobotNode(Node):
def __init__(self):
super().__init__('urdf_robot_node')
# Initialize joint state publisher
self.joint_pub = self.create_publisher(JointState, 'joint_states', 10)
# Initialize TF broadcaster
self.br = TransformBroadcaster(self)
# Timer for publishing state
self.timer = self.create_timer(0.1, self.publish_joint_states)
# Sample joint positions
self.joint_names = ['left_shoulder_joint', 'neck_joint']
self.joint_positions = [0.0, 0.0]
def publish_joint_states(self):
# Create joint state message
msg = JointState()
msg.name = self.joint_names
msg.position = self.joint_positions
msg.header.stamp = self.get_clock().now().to_msg()
msg.header.frame_id = "base_link"
self.joint_pub.publish(msg)
Summary
URDF is a critical component in modeling humanoid robots for ROS. Properly constructed URDF files enable accurate simulation, kinematic analysis, and motion planning. Understanding how to effectively describe complex human-like structures in URDF is essential for developing humanoid robots in ROS.
Exercises
- Create a URDF file for a simplified humanoid with at least 6 degrees of freedom
- Add transmission elements to your URDF for position control
- Visualize your URDF using RViz
- Simulate your humanoid in Gazebo