Skip to main content

Chapter 1: Physics Simulation with Gazebo

Learning Objectives

  • Understand why simulation is essential for robotics development
  • Install and configure Gazebo Fortress
  • Create robot models using URDF and SDF
  • Spawn and control robots in simulated environments
  • Add physics properties and constraints

1.1 Why Simulation?

The Reality of Robot Development

Problem: Physical robots are:

  • Expensive: $50,000 - $1,000,000+ for humanoids
  • Dangerous: A malfunctioning humanoid can cause serious injury
  • Slow: Each test requires setup, deployment, and reset
  • Limited: Can't test extreme scenarios (falling, collisions

)

Solution: Validate algorithms in simulation first, then deploy to hardware.

Simulation Benefits

AspectSimulationPhysical Robot
CostFree$$$$
SafetyPerfectly safeCan damage robot/environment
Iteration SpeedSecondsMinutes to hours
ParallelizationRun 1000 instancesLimited by hardware
ScenariosAny imaginableLimited by lab
DebuggingFull state accessLimited sensors

The Sim-to-Real Gap

Simulation is not perfect:

  • Physics: Simplified contact models
  • Sensors: Noise models are approximations
  • Actuators: Ideal vs. real motor dynamics

Solution: Domain randomization and careful calibration minimize the gap.

1.2 Gazebo Architecture

Gazebo Classic vs. Gazebo (Ignition/Fortress)

We use Gazebo Fortress (also called Ignition Gazebo):

  • Modern architecture
  • Better performance
  • Improved rendering (Ogre 2)
  • Plugins for ROS 2 integration

Installation

# Install Gazebo Fortress
sudo apt-get update
sudo apt-get install ros-humble-ros-gz

# Verify installation
gz sim --version

Architecture

┌──────────────┐
│ Gazebo GUI │ ← Visualization
└──────┬───────┘

┌──────▼───────┐
│ Gazebo Server│ ← Physics engine
│ (gz sim) │
└──────┬───────┘

┌───▼───┐
│ PhysX │ ← Contact dynamics
└───────┘

1.3 Creating World Files

SDF (Simulation Description Format)

Gazebo uses SDF to describe worlds and models.

worlds/empty.sdf
<?xml version="1.0" ?>
<sdf version="1.8">
<world name="empty_world">

<!-- Physics engine settings -->
<physics name="1ms" type="dart">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>

<!-- Lighting -->
<light type="directional" name="sun">
<cast_shadows>true</cast_shadows>
<pose>0 0 10 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>1000</range>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>

<!-- Ground plane -->
<model name="ground_plane">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
</collision>
<visual name="visual">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
</material>
</visual>
</link>
</model>

</world>
</sdf>

Launching a World

gz sim worlds/empty.sdf

1.4 URDF to SDF Conversion

Why Two Formats?

  • URDF: ROS-specific, simpler, good for robot description
  • SDF: Gazebo-specific, more features, good for world description

Gazebo can import URDF but converts it to SDF internally.

Enhanced URDF with Gazebo Tags

urdf/humanoid_gazebo.urdf
<?xml version="1.0"?>
<robot name="humanoid_gazebo">

<link name="base_link">
<visual>
<geometry>
<box size="0.3 0.2 0.5"/>
</geometry>
<material name="blue">
<color rgba="0.2 0.4 0.8 1"/>
</material>
</visual>

<collision>
<geometry>
<box size="0.3 0.2 0.5"/>
</geometry>
</collision>

<inertial>
<mass value="10.0"/>
<inertia ixx="0.2" ixy="0" ixz="0"
iyy="0.3" iyz="0" izz="0.2"/>
</inertial>
</link>

<!-- Gazebo-specific material -->
<gazebo reference="base_link">
<material>Gazebo/Blue</material>
<mu1>0.8</mu1> <!-- Friction coefficient -->
<mu2>0.8</mu2>
</gazebo>

<link name="right_foot">
<visual>
<geometry>
<box size="0.2 0.1 0.05"/>
</geometry>
</visual>

<collision>
<geometry>
<box size="0.2 0.1 0.05"/>
</geometry>
</collision>

<inertial>
<mass value="1.0"/>
<inertia ixx="0.01" ixy="0" ixz="0"
iyy="0.01" iyz="0" izz="0.01"/>
</inertial>
</link>

<joint name="right_ankle" type="revolute">
<parent link="base_link"/>
<child link="right_foot"/>
<origin xyz="0.1 -0.15 -0.4" rpy="0 0 0"/>
<axis xyz="1 0 0"/>
<limit lower="-0.5" upper="0.5" effort="100" velocity="2"/>
</joint>

<!-- Gazebo plugin for joint control -->
<gazebo>
<plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
<robot_param>robot_description</robot_param>
<parameters>config/controllers.yaml</parameters>
</plugin>
</gazebo>

</robot>

1.5 Spawning Robots

Using ros2 launch

launch/spawn_humanoid.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os

def generate_launch_description():
pkg_path = get_package_share_directory('humanoid_gazebo')
urdf_file = os.path.join(pkg_path, 'urdf', 'humanoid_gazebo.urdf')

with open(urdf_file, 'r') as f:
robot_description = f.read()

spawn_entity = Node(
package='ros_gz_sim',
executable='create',
arguments=[
'-name', 'humanoid',
'-topic', 'robot_description',
'-x', '0',
'-y', '0',
'-z', '1.0'
],
output='screen'
)

robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_description}]
)

return LaunchDescription([
robot_state_publisher,
spawn_entity
])

Testing Basic Motion

# Start Gazebo
gz sim worlds/empty.sdf

# Spawn robot
ros2 launch humanoid_gazebo spawn_humanoid.launch.py

# Command a joint
gz topic -t /model/humanoid/joint/right_ankle/cmd_pos -m gz.msgs.Double -p "data: 0.3"

1.6 Physics Properties

Contact Parameters

Critical for walking:

<gazebo reference="right_foot">
<mu1>1.0</mu1> <!-- Friction in primary direction -->
<mu2>1.0</mu2> <!-- Friction in secondary direction -->
<kp>1000000.0</kp> <!-- Contact stiffness -->
<kd>1.0</kd> <!-- Contact damping -->
<minDepth>0.001</minDepth> <!-- Minimum penetration for contact -->
</gazebo>

Self-Collision

<gazebo>
<self_collide>true</self_collide>
</gazebo>

Summary

✅ Understand simulation advantages and limitations
✅ Install and use Gazebo Fortress
✅ Create world and robot descriptions
✅ Spawn robots and apply physics

Next: Chapter 2: Sensor Simulation