Humanoid Robot in Gazebo
Introduction
Simulating humanoid robots in Gazebo allows developers to test bipedal locomotion, balance control, and manipulation algorithms in a safe, repeatable environment before deploying to physical hardware.
Learning Objectives:
- Load and spawn humanoid robot models in Gazebo
- Understand URDF structure for humanoid robots
- Control joints and monitor sensor data
- Test balance and walking controllers in simulation
Theory
Why Simulate Humanoid Robots?
Humanoid robots present unique simulation challenges:
Complexity:
- 20-50+ degrees of freedom (joints)
- Complex kinematic chains (legs, arms, torso, head)
- Underactuated systems (fewer actuators than DOF during flight phase)
Balance Requirements:
- Center of mass management
- Zero-moment point (ZMP) stability
- Dynamic gait generation
Contact Dynamics:
- Foot-ground contact modeling
- Friction and slip
- Impact forces during walking
Benefits of Gazebo for Humanoids:
- Test controllers without hardware damage
- Iterate gait parameters rapidly
- Simulate sensor feedback (IMU, joint encoders, force sensors)
- Debug balance failures safely
Humanoid Robot URDF Structure
A URDF (Unified Robot Description Format) defines the robot's:
<robot name="humanoid">
<!-- Base Link (Torso) -->
<link name="base_link">
<inertial>...</inertial>
<visual>...</visual>
<collision>...</collision>
</link>
<!-- Joint connecting torso to left hip -->
<joint name="left_hip_yaw" type="revolute">
<parent link="base_link"/>
<child link="left_hip"/>
<axis xyz="0 0 1"/>
<limit effort="100" lower="-0.5" upper="0.5" velocity="5.0"/>
</joint>
<!-- Continue for all joints: hips, knees, ankles, arms, neck -->
</robot>
Key Components:
- Links: Rigid bodies (torso, thighs, shins, feet, arms)
- Joints: Connections with motion constraints (revolute, prismatic)
- Inertia: Mass distribution for dynamics
- Collision: Simplified geometry for physics
- Visual: Detailed meshes for rendering
Gazebo Plugins for Humanoid Control
Gazebo uses plugins to interface with ROS 2:
1. Joint State Publisher
- Publishes joint positions, velocities, efforts
- Topic:
/joint_states
2. Joint Trajectory Controller
- Accepts trajectory commands
- Controls multiple joints simultaneously
- Topic:
/trajectory_controller/command
3. IMU Plugin
- Simulates inertial measurement unit
- Provides orientation, angular velocity, linear acceleration
- Topic:
/imu/data
4. Contact Sensor Plugin
- Detects foot-ground contact
- Critical for gait state estimation
- Topic:
/contact_sensor
Practical Example: Loading a Humanoid in Gazebo
Step 1: Install Dependencies
# Install Gazebo and ROS 2 packages
sudo apt install ros-humble-gazebo-ros-pkgs
sudo apt install ros-humble-joint-state-publisher
sudo apt install ros-humble-robot-state-publisher
Step 2: Create a Simple Humanoid URDF
Create simple_humanoid.urdf:
<?xml version="1.0"?>
<robot name="simple_humanoid">
<!-- Base Link (Torso) -->
<link name="torso">
<inertial>
<mass value="20.0"/>
<inertia ixx="0.5" ixy="0" ixz="0" iyy="0.5" iyz="0" izz="0.5"/>
</inertial>
<visual>
<geometry>
<box size="0.3 0.2 0.5"/>
</geometry>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.3 0.2 0.5"/>
</geometry>
</collision>
</link>
<!-- Left Hip Joint -->
<joint name="left_hip_pitch" type="revolute">
<parent link="torso"/>
<child link="left_thigh"/>
<origin xyz="0 0.1 -0.25" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit effort="100" lower="-1.57" upper="1.57" velocity="10"/>
</joint>
<!-- Left Thigh -->
<link name="left_thigh">
<inertial>
<mass value="5.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.01"/>
</inertial>
<visual>
<geometry>
<cylinder radius="0.05" length="0.4"/>
</geometry>
<material name="gray">
<color rgba="0.5 0.5 0.5 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.05" length="0.4"/>
</geometry>
</collision>
</link>
<!-- Add more joints and links for complete humanoid -->
<!-- Right leg, arms, head, etc. -->
</robot>
Step 3: Create Launch File
Create humanoid_gazebo.launch.py:
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
import os
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
# Path to URDF file
urdf_file = os.path.join(
get_package_share_directory('my_humanoid_description'),
'urdf',
'simple_humanoid.urdf'
)
# Read URDF content
with open(urdf_file, 'r') as file:
robot_desc = file.read()
# Spawn robot in Gazebo
spawn_entity = Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=[
'-entity', 'simple_humanoid',
'-topic', '/robot_description',
'-x', '0',
'-y', '0',
'-z', '1.0' # Spawn 1m above ground
],
output='screen'
)
# Robot state publisher
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_desc}]
)
# Launch Gazebo
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
os.path.join(get_package_share_directory('gazebo_ros'),
'launch', 'gazebo.launch.py')
])
)
return LaunchDescription([
gazebo,
robot_state_publisher,
spawn_entity
])
Step 4: Launch Simulation
# Source ROS 2
source /opt/ros/humble/setup.bash
# Launch Gazebo with humanoid
ros2 launch my_humanoid_description humanoid_gazebo.launch.py
Controlling the Humanoid
Method 1: Joint Position Commands
# Publish joint commands
ros2 topic pub /joint_commands sensor_msgs/msg/JointState \
"{name: ['left_hip_pitch', 'right_hip_pitch'], \
position: [0.5, -0.5]}"
Method 2: ROS 2 Control
Use ros2_control for trajectory tracking:
# controller_config.yaml
controller_manager:
ros__parameters:
update_rate: 100 # Hz
joint_trajectory_controller:
type: joint_trajectory_controller/JointTrajectoryController
joint_trajectory_controller:
ros__parameters:
joints:
- left_hip_pitch
- left_knee
- left_ankle
- right_hip_pitch
- right_knee
- right_ankle
command_interfaces:
- position
state_interfaces:
- position
- velocity
Monitoring Sensor Data
View Joint States
# Monitor joint positions and velocities
ros2 topic echo /joint_states
View IMU Data
# Monitor orientation and angular velocity
ros2 topic echo /imu/data
Visualize in RViz
# Launch RViz to visualize robot state
ros2 run rviz2 rviz2
In RViz:
- Set Fixed Frame to
torso - Add RobotModel display
- Add TF display to see coordinate frames
Common Challenges
Issue 1: Robot Falls Immediately
Cause: Incorrect initial pose or unstable spawn position
Solution:
- Spawn with feet on ground (
z = foot_height) - Ensure center of mass is above support polygon
- Use initial joint positions for balanced pose
Issue 2: Jittery Motion
Cause: Physics timestep too large or PID gains not tuned
Solution:
<!-- In Gazebo world file -->
<physics type="ode">
<max_step_size>0.001</max_step_size> <!-- 1ms timestep -->
<real_time_factor>1.0</real_time_factor>
</physics>
Issue 3: Unrealistic Contact
Cause: Default friction coefficients
Solution:
<!-- Add to foot link collision -->
<collision>
<surface>
<friction>
<ode>
<mu>1.0</mu> <!-- Coefficient of friction -->
<mu2>1.0</mu2>
</ode>
</friction>
</surface>
</collision>
Exercises
- Spawn a humanoid: Use an existing URDF (e.g., from robotics tutorials) and spawn it in Gazebo
- Command joint positions: Move the robot's arms to specific angles using
ros2 topic pub - Monitor IMU: Tilt the robot and observe IMU readings - do they match expected values?
- Modify URDF: Change the mass of the torso and observe how it affects balance
- Gait experiment: Research a simple walking controller and attempt to implement it
Summary
Simulating humanoid robots in Gazebo provides a safe testbed for developing locomotion, balance, and manipulation algorithms. By modeling robots in URDF, spawning them in Gazebo, and interfacing via ROS 2 topics and services, developers can iterate rapidly before deploying to physical hardware.