Skip to main content

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:

  1. Physics Engine: Handles collision detection, dynamics simulation, and constraints
  2. Rendering Engine: Provides 3D visualization and sensor simulation
  3. User Interface: Offers both GUI and command-line interfaces
  4. 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

  1. Create a new ROS 2 package called humanoid_simulation
  2. Create a world file with obstacles and terrain
  3. Create a launch file to start Gazebo with your world
  4. Add a humanoid robot model to the simulation
  5. Configure physics properties appropriately
  6. Add sensors to the robot model
  7. 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: b
Explanation: 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

  1. "Gazebo Tutorial" - Official Gazebo tutorials
  2. "Simulation for Robotics" - Principles of robot simulation
  3. "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.