Chapter 2.1: Gazebo Simulation Environment
Learning Objectives
By the end of this chapter, students will be able to:
- Understand the architecture and capabilities of Gazebo simulation
- Install and configure Gazebo for robotics development
- Create basic simulation worlds with objects and environments
- Integrate Gazebo with ROS 2 for robot simulation
- Configure physics properties and sensors in Gazebo
Introduction
Simulation is a critical component of robotics development, allowing engineers to test algorithms, validate designs, and train AI systems in a safe, cost-effective environment before deploying to real hardware. Gazebo has emerged as one of the most popular simulation environments in robotics, offering realistic physics simulation, sensor simulation, and visualization capabilities.
In the context of physical AI and humanoid robotics, simulation becomes even more important due to the complexity and cost of real humanoid robots. Gazebo enables researchers and developers to experiment with complex behaviors, test control algorithms, and develop AI systems without the risk of damaging expensive hardware or causing safety issues.
This chapter introduces the Gazebo simulation environment, covering its architecture, installation, basic usage, and integration with ROS 2.
Gazebo Architecture and Components
Overview of Gazebo Architecture
Gazebo is built on a modular architecture that separates the physics engine, rendering engine, and user interface:
- Physics Engine: Handles collision detection, dynamics simulation, and constraints
- Rendering Engine: Provides 3D visualization and sensor simulation
- User Interface: Offers both GUI and command-line interfaces
- Transport Layer: Manages communication between components and external systems
Key Components
Physics Engine
Gazebo supports multiple physics engines:
- ODE (Open Dynamics Engine): Default engine, good for general-purpose simulation
- Bullet: Offers more advanced contact modeling
- DART: Provides better kinematic modeling
- SimBody: Specialized for biomechanical simulation
Sensor Simulation
Gazebo provides realistic simulation of various sensors:
- Camera Sensors: RGB, depth, and stereo cameras
- LIDAR: 2D and 3D laser range finders
- IMU: Inertial measurement units
- Force/Torque Sensors: For measuring forces and torques
- GPS: Global positioning system simulation
- Contact Sensors: For detecting physical contact
Installing and Setting Up Gazebo
Installation for ROS 2 Humble
Gazebo Fortress is the recommended version for ROS 2 Humble Hawksbill:
# Update package lists
sudo apt update
# Install Gazebo Fortress
sudo apt install gazebo/gz-fortress
# Install ROS 2 Gazebo packages
sudo apt install ros-humble-gazebo-ros-pkgs ros-humble-gazebo-ros-control
# Install additional dependencies
sudo apt install ros-humble-joint-state-publisher-gui ros-humble-robot-state-publisher
Verification
Test the installation:
# Launch Gazebo GUI
gz sim
# Or with ROS 2 integration
ros2 launch gazebo_ros gazebo.launch.py
Creating Basic Simulation Worlds
World File Structure
Gazebo worlds are defined using SDF (Simulation Description Format):
<?xml version="1.0" ?>
<sdf version="1.7">
<world name="default">
<!-- Include models from Fuel (Gazebo's online model database) -->
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://ground_plane</uri>
</include>
<!-- Define a simple box -->
<model name="box">
<pose>0 0 0.5 0 0 0</pose>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<material>
<ambient>1 0 0 1</ambient>
<diffuse>1 0 0 1</diffuse>
</material>
</visual>
<inertial>
<mass>1.0</mass>
<inertia>
<ixx>0.166667</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.166667</iyy>
<iyz>0</iyz>
<izz>0.166667</izz>
</inertia>
</inertial>
</link>
</model>
</world>
</sdf>
Creating a Simple World File
Let's create a world file for a humanoid robot testing environment:
<?xml version="1.0" ?>
<sdf version="1.7">
<world name="humanoid_test_world">
<!-- Lighting -->
<include>
<uri>model://sun</uri>
</include>
<!-- Ground plane -->
<include>
<uri>model://ground_plane</uri>
</include>
<!-- Simple room with obstacles -->
<model name="wall_1">
<pose>-5 0 1 0 0 0</pose>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.1 10 2</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.1 10 2</size>
</box>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
</material>
</visual>
<inertial>
<mass>100.0</mass>
<inertia>
<ixx>100</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>100</iyy>
<iyz>0</iyz>
<izz>100</izz>
</inertia>
</inertial>
</link>
</model>
<!-- Add a table for humanoid to interact with -->
<model name="table">
<pose>2 0 0.4 0 0 0</pose>
<link name="table_top">
<collision name="collision">
<geometry>
<box>
<size>1.5 0.8 0.05</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>1.5 0.8 0.05</size>
</box>
</geometry>
<material>
<ambient>0.6 0.4 0.2 1</ambient>
<diffuse>0.6 0.4 0.2 1</diffuse>
</material>
</visual>
<inertial>
<mass>10.0</mass>
<inertia>
<ixx>1.0</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>1.0</iyy>
<iyz>0</iyz>
<izz>1.0</izz>
</inertia>
</inertial>
</link>
<!-- Table legs -->
<model name="leg_1">
<pose>0.7 0.35 0.2 0 0 0</pose>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.05 0.05 0.4</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.05 0.05 0.4</size>
</box>
</geometry>
</visual>
<inertial>
<mass>1.0</mass>
<inertia>
<ixx>0.01</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.01</iyy>
<iyz>0</iyz>
<izz>0.01</izz>
</inertia>
</inertial>
</link>
</model>
<model name="leg_2">
<pose>-0.7 0.35 0.2 0 0 0</pose>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.05 0.05 0.4</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.05 0.05 0.4</size>
</box>
</geometry>
</visual>
<inertial>
<mass>1.0</mass>
<inertia>
<ixx>0.01</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.01</iyy>
<iyz>0</iyz>
<izz>0.01</izz>
</inertia>
</inertial>
</link>
</model>
</model>
</world>
</sdf>
Integrating Gazebo with ROS 2
Launching Gazebo with ROS 2
Create a launch file to start Gazebo with ROS 2 integration:
# launch/gazebo_humanoid.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
def generate_launch_description():
# Launch configuration
world = LaunchConfiguration('world')
# Launch arguments
world_arg = DeclareLaunchArgument(
'world',
default_value='humanoid_test_world.sdf',
description='Choose one of the world files from `/my_simulation/worlds`'
)
# Launch Gazebo with ROS 2 integration
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
PathJoinSubstitution([
FindPackageShare('gazebo_ros'),
'launch',
'gazebo.launch.py'
])
]),
launch_arguments={
'world': PathJoinSubstitution([
FindPackageShare('my_simulation'),
'worlds',
world
])
}.items()
)
return LaunchDescription([
world_arg,
gazebo
])
Spawning Robots in Gazebo
To spawn a robot model in Gazebo, use the spawn_entity script:
# launch/spawn_robot.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, ExecuteProcess
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
def generate_launch_description():
# Launch configuration
robot_name = LaunchConfiguration('robot_name')
robot_urdf = LaunchConfiguration('robot_urdf')
# Launch arguments
robot_name_arg = DeclareLaunchArgument(
'robot_name',
default_value='humanoid_robot',
description='Name of the robot to spawn'
)
robot_urdf_arg = DeclareLaunchArgument(
'robot_urdf',
default_value=PathJoinSubstitution([
FindPackageShare('my_robot_description'),
'urdf',
'humanoid.urdf'
]),
description='URDF file to spawn'
)
# Spawn robot in Gazebo
spawn_entity = Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=[
'-topic', 'robot_description',
'-entity', robot_name,
'-x', '0', '-y', '0', '-z', '1.0' # Position where to spawn
],
output='screen'
)
# Robot state publisher to broadcast TF
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': PathJoinSubstitution([
FindPackageShare('my_robot_description'),
'urdf',
'humanoid.urdf'
])}]
)
return LaunchDescription([
robot_name_arg,
robot_urdf_arg,
spawn_entity,
robot_state_publisher
])
Configuring Physics Properties
Physics Engine Configuration
Physics properties can be configured in the world file:
<world name="humanoid_test_world">
<!-- Physics engine configuration -->
<physics type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>1000.0</real_time_update_rate>
<gravity>0 0 -9.8</gravity>
<!-- ODE-specific parameters -->
<ode>
<solver>
<type>quick</type>
<iters>10</iters>
<sor>1.3</sor>
</solver>
<constraints>
<cfm>0.0</cfm>
<erp>0.2</erp>
<contact_max_correcting_vel>100.0</contact_max_correcting_vel>
<contact_surface_layer>0.001</contact_surface_layer>
</constraints>
</ode>
</physics>
<!-- Rest of the world definition -->
</world>
Material Properties
Material properties affect how objects interact:
<model name="friction_test">
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<surface>
<friction>
<ode>
<mu>1.0</mu> <!-- Coefficient of friction -->
<mu2>1.0</mu2>
<fdir1>0 0 0</fdir1>
<slip1>0</slip1>
<slip2>0</slip2>
</ode>
</friction>
<bounce>
<restitution_coefficient>0.5</restitution_coefficient>
<threshold>100000</threshold>
</bounce>
</surface>
</collision>
</link>
</model>
Sensor Simulation in Gazebo
Camera Sensor Configuration
<sensor name="camera" type="camera">
<pose>0.1 0 0 0 0 0</pose>
<camera name="head_camera">
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>100</far>
</clip>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
LIDAR Sensor Configuration
<sensor name="lidar" type="ray">
<pose>0.1 0 0.1 0 0 0</pose>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1.0</resolution>
<min_angle>-3.14159</min_angle>
<max_angle>3.14159</max_angle>
</horizontal>
</scan>
<range>
<min>0.1</min>
<max>10.0</max>
<resolution>0.01</resolution>
</range>
</ray>
<always_on>true</always_on>
<update_rate>10</update_rate>
<visualize>true</visualize>
</sensor>
Best Practices for Gazebo Simulation
1. Realistic Physics Parameters
Use physics parameters that match real-world conditions:
<physics type="ode">
<max_step_size>0.001</max_step_size> <!-- Small time steps for stability -->
<real_time_factor>1.0</real_time_factor> <!-- Real-time simulation -->
<gravity>0 0 -9.8</gravity> <!-- Standard gravity -->
</physics>
2. Proper Inertial Properties
Ensure your robot models have realistic inertial properties:
<link name="link">
<!-- ... visual and collision properties ... -->
<inertial>
<mass>1.0</mass>
<!-- Properly calculated moments of inertia -->
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0" izz="0.02"/>
</inertial>
</link>
3. Sensor Noise Modeling
Add realistic noise to sensors to better match real hardware:
<sensor name="imu_sensor" type="imu">
<always_on>true</always_on>
<update_rate>100</update_rate>
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-3</stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-3</stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-3</stddev>
</noise>
</z>
</angular_velocity>
</imu>
</sensor>
Hands-On Exercise: Gazebo Simulation Setup
Objective
Set up a complete Gazebo simulation environment with a humanoid robot.
Prerequisites
- ROS 2 Humble installed
- Gazebo Fortress installed
- Basic understanding of URDF
Steps
- Create a new ROS 2 package called
humanoid_simulation - Create a world file with obstacles and terrain
- Create a launch file to start Gazebo with your world
- Add a humanoid robot model to the simulation
- Configure physics properties appropriately
- Add sensors to the robot model
- Test the simulation with basic movement
Expected Result
Students will have a working Gazebo simulation with a humanoid robot that can move and interact with the environment.
Assessment Questions
Multiple Choice
Q1: Which physics engine is the default in Gazebo?
- a) Bullet
- b) ODE (Open Dynamics Engine)
- c) DART
- d) SimBody
Details
Click to reveal answer
Answer: bExplanation: ODE (Open Dynamics Engine) is the default physics engine in Gazebo, though others like Bullet, DART, and SimBody are also supported.
Short Answer
Q2: Explain the importance of using realistic sensor noise models in Gazebo simulations for humanoid robotics.
Practical Exercise
Q3: Create a Gazebo world file with a humanoid robot, a table, and a few obstacles. Configure the robot with camera and LIDAR sensors, and set up appropriate physics parameters. Create a launch file to start the simulation.
Further Reading
- "Gazebo Tutorial" - Official Gazebo tutorials
- "Simulation for Robotics" - Principles of robot simulation
- "ROS 2 with Gazebo" - Integration guide
Summary
In this chapter, we've introduced the Gazebo simulation environment, covering its architecture, installation, basic usage, and integration with ROS 2. We've learned how to create simulation worlds, configure physics properties, and add sensors to robot models.
Simulation is crucial for humanoid robotics development as it allows for safe, cost-effective testing of complex behaviors and algorithms. Properly configured simulations with realistic physics and sensor models help bridge the gap between simulation and reality, making the transition to real hardware more successful.
In the next chapter, we'll explore how to describe robots using both URDF and SDF formats, and how these formats work together in simulation environments.