Skip to main content

Week 6: Gazebo Simulation

Introduction

Now you can build and launch ROS 2 applications. This week introduces Gazebo, the industry-standard physics simulator for robotics. Gazebo allows you to test algorithms in a simulated environment before deploying to real hardware—critical for safety and cost savings. You'll learn to model robots using URDF (Unified Robot Description Format), configure physics engines, simulate sensors, and bridge the sim-to-real gap. Gazebo is essential infrastructure for any robotics team working on legged robots, manipulators, and autonomous vehicles.

Learning Objectives

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

  • Understand URDF (Unified Robot Description Format) and write robot descriptions with links, joints, and inertia
  • Use SDF (Simulation Description Format) for advanced physics and plugin configuration
  • Set up and launch Gazebo simulation environments with ROS 2 integration
  • Configure physics engines (ODE, Bullet, DART) for realistic dynamics
  • Simulate sensors (cameras, LiDAR, IMU, force-torque) with realistic noise and latency
  • Implement sim-to-real transfer techniques to bridge the gap between simulation and real hardware

Core Concepts

1. URDF: Robot Structure and Kinematics

URDF describes robot structure as a tree of rigid bodies (links) connected by joints:

<?xml version="1.0"?>
<robot name="optimus">

<!-- Base link -->
<link name="base_link">
<inertial>
<mass value="50.0"/>
<inertia ixx="2.0" ixy="0.0" ixz="0.0" iyy="2.0" iyz="0.0" izz="1.5"/>
</inertial>
<visual>
<geometry>
<box size="0.3 0.3 0.8"/>
</geometry>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.3 0.3 0.8"/>
</geometry>
</collision>
</link>

<!-- Right hip joint -->
<joint name="right_hip_pitch" type="revolute">
<parent link="base_link"/>
<child link="right_thigh"/>
<origin xyz="0 -0.15 0" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit lower="-1.57" upper="1.57" effort="200" velocity="2.0"/>
</joint>

<!-- Right thigh link -->
<link name="right_thigh">
<inertial>
<mass value="8.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.05" iyz="0" izz="0.12"/>
</inertial>
<visual>
<geometry>
<cylinder length="0.4" radius="0.05"/>
</geometry>
</visual>
<collision>
<geometry>
<cylinder length="0.4" radius="0.05"/>
</geometry>
</collision>
</link>

</robot>

Key Elements:

  • <link>: Rigid body with mass, inertia, visual shape, collision shape
  • <joint>: Connection between parent and child links (revolute, prismatic, fixed)
  • <inertial>: Mass and moment of inertia (critical for dynamics)
  • <visual>: 3D mesh or geometry for display
  • <collision>: Geometry for physics calculations (often simpler than visual)

2. SDF: Simulation-Specific Configuration

SDF (Simulation Description Format) extends URDF with physics plugins, sensors, and world properties:

<?xml version="1.0"?>
<sdf version="1.9">
<world name="warehouse">

<!-- Physics engine configuration -->
<physics type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>

<!-- Gravity -->
<gravity>0 0 -9.81</gravity>

<!-- Lighting -->
<light type="directional">
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<direction>-0.5 0.5 -1</direction>
</light>

<!-- Robot model with plugins -->
<model name="optimus">
<include uri="model://optimus/model.sdf"/>

<!-- ROS 2 plugin for joint control -->
<plugin name="gazebo_ros2_control" filename="libgazebo_ros2_control.so"/>

<!-- Camera sensor -->
<link name="camera_link">
<sensor type="camera" name="front_camera">
<camera>
<image>
<width>640</width>
<height>480</height>
</image>
<clip near="0.1" far="100"/>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<plugin name="camera_controller" filename="libgazebo_ros_camera.so"/>
</sensor>
</link>

</model>

<!-- Static ground plane -->
<model name="ground_plane">
<include uri="model://ground_plane"/>
</model>

</world>
</sdf>

3. Physics Engines and Configuration

Physics engines simulate dynamics. Key parameters:

ParameterImpactValue
max_step_sizeSimulation timestep (smaller = more accurate but slower)0.001s (1ms)
real_time_factorSim speed vs real time (1.0 = real time, 0.5 = half speed)0.5-1.0
gravityGravitational acceleration(0, 0, -9.81) m/s²
surface frictionContact friction coefficient0.5-1.0
contact dampingEnergy dissipation in contacts0.01-0.1

Engine Types:

  • ODE (Open Dynamics Engine): Fast, stable, used by most robots
  • Bullet: Good for rigid body dynamics, GPU acceleration available
  • DART: Advanced constraint solving, good for humanoids

4. Sensor Simulation

Simulated sensors add realism with noise and latency:

<!-- LiDAR sensor -->
<sensor type="ray" name="laser">
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</resolution>
<min_angle>0</min_angle>
<max_angle>6.28319</max_angle>
</horizontal>
</scan>
<range>
<min>0.08</min>
<max>10.0</max>
</range>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<plugin name="laser_controller" filename="libgazebo_ros_laser.so"/>
</sensor>

<!-- IMU sensor -->
<sensor type="imu" name="imu">
<always_on>true</always_on>
<update_rate>200</update_rate>
<noise type="gaussian">
<rate stddev="0.001"/>
<accel stddev="0.001"/>
</noise>
<plugin name="imu_controller" filename="libgazebo_ros_imu.so"/>
</sensor>

5. Sim-to-Real Transfer Challenges and Solutions

The Sim-to-Real Gap:

  • Physics Mismatch: Simulated friction, damping, contact don't match reality
  • Sensor Noise: Simulated noise is statistically clean; real sensors have correlated errors
  • Latency: Simulation has predictable delays; real systems have variable latency
  • Model Mismatch: CAD models never perfectly represent actual hardware

Solutions:

  • Domain Randomization: Vary physics parameters randomly during training
  • Noisy Simulation: Add realistic sensor noise and actuation delays
  • System ID: Calibrate simulator to match real robot through experiments
  • Transfer Learning: Train in sim, fine-tune on real hardware

Practical Explanation

Creating a Simple URDF Model

<?xml version="1.0"?>
<robot name="simple_arm">

<!-- Base -->
<link name="base_link">
<inertial>
<mass value="10.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.05"/>
</inertial>
<visual>
<geometry>
<box size="0.2 0.2 0.1"/>
</geometry>
</visual>
</link>

<!-- First joint (shoulder) -->
<joint name="shoulder_joint" type="revolute">
<parent link="base_link"/>
<child link="upper_arm"/>
<origin xyz="0 0 0.05" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit lower="0" upper="1.57" effort="100" velocity="1.0"/>
<dynamics damping="0.7" friction="0.1"/>
</joint>

<!-- Upper arm link -->
<link name="upper_arm">
<inertial>
<mass value="2.0"/>
<origin xyz="0 0 0.2"/>
<inertia ixx="0.01" ixy="0" ixz="0" iyy="0.01" iyz="0" izz="0.001"/>
</inertial>
<visual>
<geometry>
<cylinder length="0.4" radius="0.05"/>
</geometry>
<origin xyz="0 0 0.2"/>
</visual>
<collision>
<geometry>
<cylinder length="0.4" radius="0.05"/>
</geometry>
<origin xyz="0 0 0.2"/>
</collision>
</link>

</robot>

Launch Gazebo with ROS 2

# Install Gazebo and ROS 2 integration
sudo apt install gazebo ros-humble-gazebo-ros

# Create simple launch file
cat > launch/gazebo.launch.xml << 'EOF'
<?xml version="1.0"?>
<launch>
<arg name="world" default="warehouse.sdf"/>

<!-- Start Gazebo server -->
<executable cmd="gzserver --verbose $(find-pkg-share my_robot)/worlds/$(var world)" output="screen"/>

<!-- Start Gazebo client -->
<executable cmd="gzclient" output="screen"/>

<!-- Spawn robot -->
<node pkg="gazebo_ros" exec="spawn_entity.py" args="-file $(find-pkg-share my_robot)/urdf/robot.urdf -entity my_robot"/>

<!-- Controllers -->
<node pkg="controller_manager" exec="ros2_control_node" args="--ros-args -p robot_description:=$(command 'cat $(find-pkg-share my_robot)/urdf/robot.urdf')"/>
</launch>
EOF

# Launch Gazebo
ros2 launch my_robot gazebo.launch.xml

Visual Aids

URDF Robot Chain Structure

Physics Simulation Pipeline

Sim-to-Real Transfer Workflow

Real-World Applications

Boston Dynamics Atlas

Atlas is trained heavily in simulation:

  • URDF/SDF Models: Precise CAD-derived models of every joint, sensor, and actuator
  • Physics Calibration: Simulator tuned to match real robot dynamics through extensive testing
  • Domain Randomization: Training includes random variations in terrain, friction, sensor noise
  • Sensor Simulation: Realistic latency and noise on vision, IMU, force sensors
  • Result: Complex behaviors (parkour, dancing) learned in sim, transferred to real hardware

Tesla Optimus Training in Isaac Sim (Gazebo alternative)

  • Simulation Farm: Massive parallel simulations for RL training
  • Domain Randomization: Random object appearances, lighting, friction during training
  • Sim-to-Real: Policies trained in sim deployed directly to real Optimus robots
  • Continuous Improvement: Real-world telemetry feeds back to improve simulator

Summary

This week covered the fundamentals of robot simulation:

  • URDF provides a standard format for describing robot structure, kinematics, and inertia—essential for accurate dynamics simulation.

  • SDF extends URDF with simulation-specific features like physics engines, plugins, sensors, and world properties.

  • Physics engines (ODE, Bullet, DART) simulate rigid body dynamics. Choosing the right engine and tuning parameters impacts both accuracy and simulation speed.

  • Sensor simulation adds realism through noise, latency, and field-of-view limitations—critical for developing robust algorithms.

  • Sim-to-Real transfer remains challenging but techniques like domain randomization and system identification can significantly reduce the gap.

Key Takeaway: A well-tuned simulator is invaluable for robotics development, enabling safe testing of complex behaviors before real-world deployment. The best simulators are continuously calibrated against real-world data.