Physics and Sensor Simulation
This chapter focuses on creating realistic physics simulation and sensor models for humanoid robots in Gazebo. Proper physics and sensor simulation are critical for developing and testing humanoid robot behaviors before deployment on real hardware.
Learning Objectives
By the end of this chapter, you will be able to:
- Configure realistic physics parameters for humanoid robots
- Model and simulate various types of sensors (cameras, IMUs, force/torque)
- Create custom sensor noise models for realistic behavior
- Tune physics parameters for stable humanoid simulation
- Validate sensor simulation against real hardware characteristics
- Implement advanced sensor fusion techniques in simulation
Physics Simulation Fundamentals
Understanding the Physics Pipeline
Physics simulation in Gazebo follows this pipeline:
- Force Application: Joint torques, gravity, external forces
- Integration: Computing motion from forces using numerical integration
- Collision Detection: Identifying contacting bodies
- Contact Resolution: Computing contact forces and responses
- State Update: Updating positions and velocities
Physics Engine Configuration
<physics type="ode" name="default_physics">
<max_step_size>0.001</max_step_size> <!-- Simulation time step -->
<real_time_factor>1.0</real_time_factor> <!-- Simulation speed -->
<real_time_update_rate>1000</real_time_update_rate> <!-- Hz -->
<gravity>0 0 -9.8</gravity>
<ode>
<solver>
<type>quick</type> <!-- Fast iterative solver -->
<iters>1000</iters> <!-- More iterations = more stable -->
<sor>1.3</sor> <!-- Successive Over-Relaxation parameter -->
</solver>
<constraints>
<cfm>0.0</cfm> <!-- Constraint Force Mixing -->
<erp>0.2</erp> <!-- Error Reduction Parameter -->
<contact_max_correcting_vel>100.0</contact_max_correcting_vel>
<contact_surface_layer>0.001</contact_surface_layer>
</constraints>
</ode>
</physics>
Physics Parameters for Humanoid Robots
Humanoid robots require special attention to physics parameters due to their complex kinematics and balance requirements:
<physics type="ode" name="humanoid_physics">
<max_step_size>0.0005</max_step_size> <!-- Smaller for stability -->
<real_time_factor>0.5</real_time_factor> <!-- May need slower simulation -->
<real_time_update_rate>2000</real_time_update_rate>
<gravity>0 0 -9.8</gravity>
<ode>
<solver>
<type>quick</type>
<iters>2000</iters> <!-- More iterations for complex joints -->
<sor>1.2</sor>
</solver>
<constraints>
<cfm>0.0001</cfm> <!-- Small CFM for tight constraints -->
<erp>0.1</erp> <!-- Moderate ERP for stability -->
<contact_max_correcting_vel>10.0</contact_max_correcting_vel>
<contact_surface_layer>0.0005</contact_surface_layer>
</constraints>
</ode>
</physics>
Collision Properties and Contact Modeling
Contact Parameters for Different Body Parts
Different parts of a humanoid robot need different contact properties:
<!-- Feet - need high friction for stable walking -->
<link name="left_foot">
<collision name="foot_collision">
<geometry>
<box>
<size>0.18 0.08 0.02</size>
</box>
</geometry>
<surface>
<friction>
<ode>
<mu>1.0</mu> <!-- High friction for grip -->
<mu2>1.0</mu2>
</ode>
</friction>
<contact>
<ode>
<kp>1e7</kp> <!-- High stiffness for solid contact -->
<kd>100</kd> <!-- Damping to prevent oscillation -->
<max_vel>100.0</max_vel>
<min_depth>0.001</min_depth> <!-- Penetration depth -->
</ode>
</contact>
</surface>
</collision>
</link>
<!-- Hands - need moderate friction for grasping -->
<link name="left_hand">
<collision name="hand_collision">
<geometry>
<box>
<size>0.08 0.06 0.04</size>
</box>
</geometry>
<surface>
<friction>
<ode>
<mu>0.8</mu> <!-- Good for grasping objects -->
<mu2>0.8</mu2>
</ode>
</friction>
<contact>
<ode>
<kp>1e6</kp> <!-- Medium stiffness -->
<kd>50</kd>
</ode>
</contact>
</surface>
</collision>
</link>
<!-- Torso - less critical for friction -->
<link name="torso">
<collision name="torso_collision">
<geometry>
<box>
<size>0.2 0.15 0.4</size>
</box>
</geometry>
<surface>
<friction>
<ode>
<mu>0.5</mu>
<mu2>0.5</mu2>
</ode>
</friction>
<contact>
<ode>
<kp>1e5</kp> <!-- Lower stiffness -->
<kd>20</kd>
</ode>
</contact>
</surface>
</collision>
</link>
Sensor Simulation
Camera Sensors
<link name="head">
<sensor name="rgb_camera" type="camera">
<pose>0.05 0 0.05 0 0 0</pose> <!-- Position in head -->
<camera name="head_camera">
<horizontal_fov>1.047</horizontal_fov> <!-- 60 degrees -->
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>10.0</far>
</clip>
<distortion>
<k1>0.0</k1>
<k2>0.0</k2>
<k3>0.0</k3>
<p1>0.0</p1>
<p2>0.0</p2>
<center>0.5 0.5</center>
</distortion>
</camera>
<always_on>1</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
<!-- Depth camera -->
<sensor name="depth_camera" type="depth">
<pose>0.07 0 0.05 0 0 0</pose> <!-- Slightly offset -->
<camera name="head_depth_camera">
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>320</width>
<height>240</height>
<format>L8</format>
</image>
<clip>
<near>0.1</near>
<far>5.0</far>
</clip>
</camera>
<always_on>1</always_on>
<update_rate>30</update_rate>
<visualize>false</visualize>
</sensor>
</link>
IMU Sensors
<link name="imu_link"> <!-- Usually in torso or pelvis -->
<sensor name="imu_sensor" type="imu">
<pose>0 0 0 0 0 0</pose>
<always_on>1</always_on>
<update_rate>100</update_rate>
<imu>
<!-- Angular velocity noise -->
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev> <!-- ~0.01 deg/s RMS -->
<bias_mean>0.001</bias_mean>
<bias_stddev>0.0001</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.0001</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.0001</bias_stddev>
</noise>
</z>
</angular_velocity>
<!-- Linear acceleration noise -->
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev> <!-- ~0.0017g RMS -->
<bias_mean>0.01</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.01</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.01</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</z>
</linear_acceleration>
</imu>
</sensor>
</link>
Force/Torque Sensors
<link name="left_foot">
<sensor name="ft_sensor" type="force_torque">
<pose>0 0 -0.01 0 0 0</pose> <!-- At foot contact point -->
<always_on>1</always_on>
<update_rate>100</update_rate>
<force_torque>
<frame>child</frame> <!-- Measurements in child link frame -->
<measure_direction>child_to_parent</measure_direction>
<!-- Noise parameters -->
<force>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.5</stddev> <!-- 0.5N RMS -->
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.5</stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.0</stddev> <!-- 1.0N RMS (higher for Z axis) -->
</noise>
</z>
</force>
<torque>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.01</stddev> <!-- 0.01Nm RMS -->
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</z>
</torque>
</force_torque>
</sensor>
</link>
LIDAR Sensors
<link name="head">
<sensor name="lidar" type="ray">
<pose>0.05 0 0.1 0 0 0</pose> <!-- On top of head -->
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</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>1</always_on>
<update_rate>10</update_rate>
<visualize>false</visualize>
</sensor>
</link>
Advanced Physics Tuning for Humanoid Robots
Balance and Stability Considerations
Humanoid robots require special attention to physics parameters for stable simulation:
<!-- In the world file -->
<physics type="ode" name="humanoid_simulation">
<max_step_size>0.0005</max_step_size>
<real_time_factor>0.8</real_time_factor>
<real_time_update_rate>2000</real_time_update_rate>
<gravity>0 0 -9.8</gravity>
<ode>
<solver>
<type>quick</type>
<iters>1500</iters> <!-- High for stability -->
<sor>1.2</sor>
</solver>
<constraints>
<cfm>1e-5</cfm> <!-- Very low CFM for tight constraints -->
<erp>0.05</erp> <!-- Low ERP for accuracy -->
<contact_max_correcting_vel>5.0</contact_max_correcting_vel>
<contact_surface_layer>0.0001</contact_surface_layer>
</constraints>
</ode>
</physics>
Joint-Level Physics Parameters
<!-- In the robot URDF/SDF -->
<joint name="left_knee" type="revolute">
<parent>left_thigh</parent>
<child>left_lower_leg</child>
<axis>
<xyz>0 1 0</xyz>
<limit lower="-0.1" upper="2.5" effort="200" velocity="5"/>
<dynamics damping="1.0" friction="0.1"/> <!-- Joint-specific damping -->
</axis>
<safety_controller k_position="10" k_velocity="1"
soft_lower_limit="-0.05" soft_upper_limit="2.45"/>
</joint>
Sensor Noise Modeling
Realistic Noise Characteristics
Real sensors have various types of noise that should be modeled:
<!-- Gyroscope with realistic noise -->
<sensor name="gyro" type="imu">
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<!-- Angle Random Walk: 0.3 deg/sqrt(hr) = 0.0015 deg/s/sqrt(Hz) -->
<stddev>2.6e-5</stddev>
<!-- Rate Random Walk: 3.8 deg/s/sqrt(hr) = 0.02 deg/s^2/sqrt(Hz) -->
<bias_stddev>3.5e-4</bias_stddev>
</noise>
</x>
<!-- Similar for y and z axes -->
</angular_velocity>
</imu>
</sensor>
<!-- Accelerometer with realistic noise -->
<sensor name="accel" type="imu">
<imu>
<linear_acceleration>
<x>
<noise type="gaussian">
<!-- Bias instability: 50 ug -->
<bias_stddev>4.9e-4</bias_stddev>
<!-- Noise density: 100 ug/sqrt(Hz) -->
<stddev>9.8e-4</stddev>
</noise>
</x>
<!-- Similar for y and z axes -->
</linear_acceleration>
</imu>
</sensor>
Validation and Calibration
Comparing Simulation to Reality
To validate your sensor models:
- Collect real data: Record sensor readings from real robot
- Simulate same scenario: Run identical motions in simulation
- Compare statistics: Analyze noise characteristics, biases
- Adjust parameters: Tune simulation to match real behavior
Calibration Workflows
# Example Python code for sensor validation
import numpy as np
from scipy import stats
def validate_imu_simulation(real_data, sim_data):
"""Compare real and simulated IMU data"""
# Compare noise characteristics
real_std = np.std(real_data)
sim_std = np.std(sim_data)
print(f"Real data std: {real_std}")
print(f"Sim data std: {sim_std}")
print(f"Ratio: {sim_std/real_std}")
# Perform statistical tests
ks_stat, p_value = stats.ks_2samp(real_data, sim_data)
print(f"Kolmogorov-Smirnov test p-value: {p_value}")
# If p > 0.05, distributions are statistically similar
return p_value > 0.05
Advanced Sensor Fusion in Simulation
Creating Multi-Sensor Nodes
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Imu, Image, PointCloud2
from nav_msgs.msg import Odometry
from geometry_msgs.msg import PoseWithCovarianceStamped
class SensorFusionNode(Node):
def __init__(self):
super().__init__('sensor_fusion_node')
# Subscribe to various sensors
self.imu_sub = self.create_subscription(
Imu, '/imu/data', self.imu_callback, 10)
self.camera_sub = self.create_subscription(
Image, '/camera/image_raw', self.camera_callback, 10)
self.odom_sub = self.create_subscription(
Odometry, '/odom', self.odom_callback, 10)
# Publish fused data
self.pose_pub = self.create_publisher(
PoseWithCovarianceStamped, '/fused_pose', 10)
self.get_logger().info('Sensor fusion node initialized')
def imu_callback(self, msg):
"""Process IMU data for attitude estimation"""
# Implement attitude estimation
pass
def camera_callback(self, msg):
"""Process camera data for visual odometry"""
# Implement visual processing
pass
def odom_callback(self, msg):
"""Process odometry data"""
# Implement odometry fusion
pass
Performance Optimization
Reducing Computational Load
For complex humanoid simulations:
<!-- Optimize sensor update rates -->
<sensor name="low_freq_camera" type="camera">
<update_rate>10</update_rate> <!-- Lower for background tasks -->
</sensor>
<sensor name="high_freq_imu" type="imu">
<update_rate>200</update_rate> <!-- Higher for control -->
</sensor>
<!-- Simplify collision geometries for performance -->
<link name="torso">
<collision name="simplified_collision">
<geometry>
<box>
<size>0.25 0.2 0.5</size> <!-- Simplified from complex mesh -->
</box>
</geometry>
</collision>
</link>
Multi-Threading Considerations
<!-- In Gazebo launch file -->
<node name="gazebo" pkg="gazebo_ros" exec="gzserver">
<param name="enable_multithread_physics" value="true"/>
<param name="max_threads" value="4"/>
</node>
Debugging Physics and Sensor Issues
Common Problems and Solutions
Problem: Robot falls through floor
Solution: Check collision properties, mass, and inertia values
Problem: Unstable joint oscillation
Solution: Increase damping, adjust ERP/CFM, reduce step size
Problem: Sensor data looks unrealistic
Solution: Verify noise parameters, update rates, and coordinate frames
Problem: Simulation runs too slowly
Solution: Simplify collision geometries, reduce update rates, optimize physics
Diagnostic Tools
# Monitor physics performance
gz topic -e /gazebo/performance_metrics
# Check sensor topics
ros2 topic echo /camera/image_raw --field header.stamp
# Monitor TF tree
ros2 run tf2_tools view_frames
Integration with ROS 2 Control
Sensor and Joint State Integration
<!-- In robot URDF -->
<gazebo>
<plugin name="ros_control" filename="libgazebo_ros_control.so">
<robot_namespace>/humanoid_robot</robot_namespace>
<robot_param>robot_description</robot_param>
<period>0.001</period>
</plugin>
</gazebo>
<gazebo>
<plugin name="joint_state_publisher" filename="libgazebo_ros_joint_state_publisher.so">
<robot_namespace>/humanoid_robot</robot_namespace>
<joint_name>left_hip_joint</joint_name>
<joint_name>left_knee_joint</joint_name>
<!-- Add all joints -->
<update_rate>100</update_rate>
</plugin>
</gazebo>
Best Practices for Humanoid Simulation
1. Gradual Complexity
- Start with simple models and basic physics
- Add complexity incrementally
- Test each addition thoroughly
2. Realistic Parameters
- Use real robot specifications for masses and dimensions
- Model sensor noise based on actual hardware
- Validate physics parameters against real robot behavior
3. Performance vs Realism Balance
- Use high-fidelity models for final validation
- Use simplified models for rapid testing
- Adjust parameters based on simulation purpose
4. Comprehensive Testing
- Test extreme scenarios safely in simulation
- Validate across different environments
- Compare simulation and real robot performance
Summary
Physics and sensor simulation are crucial for creating effective digital twins of humanoid robots. Properly configured physics parameters ensure stable simulation, while realistic sensor models enable robust algorithm development. The key is balancing computational efficiency with simulation accuracy to create a useful training and testing environment.
Next Steps
In the next chapter, we'll explore Unity integration for robot visualization and advanced simulation capabilities, complementing the physics-based simulation with high-quality graphics.
Estimated Reading Time: 30 minutes