Chapter 2.4: Sensor Simulation
Learning Objectives
By the end of this chapter, students will be able to:
- Configure various sensor types in Gazebo simulation
- Understand sensor noise modeling and realistic simulation
- Integrate simulated sensors with ROS 2 topics
- Optimize sensor performance and accuracy
- Troubleshoot common sensor simulation issues
Introduction
Sensors are the eyes, ears, and sensory organs of robots, providing the critical data needed for perception, navigation, and interaction with the environment. In simulation, accurately modeling sensors is crucial for developing and testing perception algorithms that will eventually run on real robots. For humanoid robots operating in human environments, realistic sensor simulation is particularly important as these robots must perceive and understand the same world that humans do.
In this chapter, we'll explore how to configure and use various sensor types in Gazebo simulation, focusing on creating realistic sensor models that closely match their real-world counterparts. We'll cover cameras, LIDAR, IMUs, force/torque sensors, and other sensor types commonly used in humanoid robotics.
Camera Simulation
Basic Camera Configuration
Cameras are essential for visual perception in humanoid robots:
<sensor name="head_camera" type="camera">
<pose>0.1 0 0 0 0 0</pose>
<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>100</far>
</clip>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
Advanced Camera Features
For more realistic camera simulation, add noise and distortion models:
<sensor name="head_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>
<!-- Add noise to simulate real camera sensor -->
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.007</stddev>
</noise>
<!-- Add distortion to simulate lens effects -->
<distortion>
<k1>-0.172933</k1>
<k2>0.205327</k2>
<k3>-0.043047</k3>
<p1>-0.001798</p1>
<p2>-0.000959</p2>
<center>0.5 0.5</center>
</distortion>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
Depth Camera Configuration
Depth cameras provide 3D perception capabilities:
<sensor name="depth_camera" type="depth">
<pose>0.1 0 0.05 0 0 0</pose>
<camera name="depth_camera">
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>10</far>
</clip>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
Stereo Camera Setup
Stereo cameras provide depth perception through triangulation:
<!-- Left camera -->
<sensor name="stereo_left" type="camera">
<pose>0.05 0.06 0 0 0 0</pose>
<camera name="stereo_left">
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>10</far>
</clip>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
<!-- Right camera -->
<sensor name="stereo_right" type="camera">
<pose>0.05 -0.06 0 0 0 0</pose>
<camera name="stereo_right">
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>10</far>
</clip>
</camera>
<always_on>true</always_on>
<update_rate>30</update_rate>
<visualize>true</visualize>
</sensor>
LIDAR Simulation
2D LIDAR Configuration
2D LIDAR is commonly used for navigation and obstacle detection:
<sensor name="laser_2d" 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>
3D LIDAR Configuration
3D LIDAR provides full 3D environment mapping:
<sensor name="laser_3d" type="ray">
<pose>0.1 0 0.2 0 0 0</pose>
<ray>
<scan>
<horizontal>
<samples>640</samples>
<resolution>1</resolution>
<min_angle>-3.14159</min_angle>
<max_angle>3.14159</max_angle>
</horizontal>
<vertical>
<samples>64</samples>
<resolution>1</resolution>
<min_angle>-0.2618</min_angle> <!-- -15 degrees -->
<max_angle>0.2618</max_angle> <!-- 15 degrees -->
</vertical>
</scan>
<range>
<min>0.1</min>
<max>20.0</max>
<resolution>0.01</resolution>
</range>
</ray>
<always_on>true</always_on>
<update_rate>10</update_rate>
<visualize>true</visualize>
</sensor>
Adding Noise to LIDAR
Real LIDAR sensors have measurement noise:
<sensor name="laser_2d" 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>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev> <!-- 1cm standard deviation -->
</noise>
</ray>
<always_on>true</always_on>
<update_rate>10</update_rate>
<visualize>true</visualize>
</sensor>
IMU Simulation
Basic IMU Configuration
IMUs provide orientation and acceleration data:
<sensor name="imu_sensor" type="imu">
<pose>0 0 0 0 0 0</pose>
<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>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.0001</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-3</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-3</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.0001</bias_stddev>
</noise>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<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>
</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>
IMU Placement for Humanoid Balance
For humanoid robots, IMU placement is critical for balance:
<!-- Place IMU at the center of mass for best balance information -->
<joint name="imu_joint" type="fixed">
<parent link="torso"/>
<child link="imu_link"/>
<origin xyz="0 0 0" rpy="0 0 0"/>
</joint>
<link name="imu_link">
<inertial>
<mass value="0.001"/>
<inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.0001" iyz="0" izz="0.0001"/>
</inertial>
</link>
<gazebo reference="imu_link">
<sensor name="imu_sensor" type="imu">
<always_on>true</always_on>
<update_rate>200</update_rate> <!-- Higher rate for balance control -->
<imu>
<!-- Include orientation data -->
<orientation>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1e-3</stddev>
</noise>
</orientation>
<!-- Angular velocity and linear acceleration as before -->
<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>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
</noise>
</z>
</linear_acceleration>
</imu>
</sensor>
</gazebo>
Force/Torque Sensor Simulation
Joint Force/Torque Sensors
Force/torque sensors are essential for manipulation tasks:
<gazebo reference="left_wrist">
<sensor name="left_wrist_ft" type="force_torque">
<always_on>true</always_on>
<update_rate>100</update_rate>
<force_torque>
<frame>child</frame> <!-- Measurement frame -->
<measure_direction>child_to_parent</measure_direction>
</force_torque>
</sensor>
</gazebo>
Custom Force/Torque Sensor
For more complex force sensing:
<gazebo reference="end_effector">
<sensor name="end_effector_force" type="force_torque">
<always_on>true</always_on>
<update_rate>500</update_rate> <!-- High rate for manipulation -->
<force_torque>
<frame>sensor</frame>
<measure_direction>child_to_parent</measure_direction>
</force_torque>
</sensor>
</gazebo>
GPS Simulation
GPS Sensor Configuration
GPS is useful for outdoor humanoid applications:
<sensor name="gps_sensor" type="gps">
<pose>0 0 1.0 0 0 0</pose> <!-- Position on top of robot -->
<always_on>true</always_on>
<update_rate>1</update_rate>
<gps>
<position_sensing>
<horizontal>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2.0</stddev> <!-- 2m standard deviation -->
</noise>
</horizontal>
<vertical>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>4.0</stddev> <!-- 4m standard deviation -->
</noise>
</vertical>
</position_sensing>
</gps>
</sensor>
Sensor Integration with ROS 2
Camera Sensor Integration
Cameras publish to ROS 2 topics automatically when properly configured:
<!-- Camera with ROS 2 interface -->
<sensor name="rgb_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>
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
<frame_name>head_camera_frame</frame_name>
<topic_name>image_raw</topic_name>
<hack_baseline>0.07</hack_baseline>
</plugin>
</sensor>
LIDAR Integration
LIDAR sensors also publish to ROS 2 topics:
<sensor name="laser_scan" 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>
<plugin name="laser_controller" filename="libgazebo_ros_ray.so">
<ros>
<namespace>/humanoid_robot</namespace>
<remapping>~/out:=scan</remapping>
</ros>
<output_type>sensor_msgs/LaserScan</output_type>
<frame_name>laser_frame</frame_name>
</plugin>
</sensor>
IMU Integration
IMU sensors publish orientation, angular velocity, and linear acceleration:
<gazebo reference="imu_link">
<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>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
</noise>
</z>
</linear_acceleration>
</imu>
<plugin name="imu_plugin" filename="libgazebo_ros_imu.so">
<ros>
<namespace>/humanoid_robot</namespace>
<remapping>~/out:=imu</remapping>
</ros>
<frame_name>imu_link</frame_name>
<body_name>imu_link</body_name>
<update_rate>100</update_rate>
<gaussian_noise>0.01</gaussian_noise>
</plugin>
</sensor>
</gazebo>
Sensor Performance Optimization
Reducing Computational Load
For better simulation performance, optimize sensor settings:
<!-- Lower resolution for faster simulation -->
<sensor name="low_res_camera" type="camera">
<pose>0.1 0 0 0 0 0</pose>
<camera name="low_res_camera">
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>320</width> <!-- Lower resolution -->
<height>240</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>10</far> <!-- Shorter range -->
</clip>
</camera>
<always_on>true</always_on>
<update_rate>15</update_rate> <!-- Lower update rate -->
<visualize>false</visualize> <!-- Disable visualization for headless sim -->
</sensor>
Multi-threading Sensor Processing
Gazebo can process sensors in separate threads:
<!-- Configure Gazebo to use multiple threads -->
<gazebo>
<plugin name="sensor_thread_manager" filename="libgazebo_ros_sensor_thread_manager.so">
<threads>4</threads>
</plugin>
</gazebo>
Sensor Fusion and Coordination
Synchronizing Multiple Sensors
For effective perception, sensors need to be properly coordinated:
<!-- Example: Synchronized sensor configuration -->
<sdf version="1.7">
<model name="humanoid_with_sensors">
<!-- ... robot definition ... -->
<!-- Camera with specific timing -->
<sensor name="camera" type="camera">
<update_rate>30</update_rate>
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
<frame_name>camera_frame</frame_name>
<topic_name>camera/image_raw</topic_name>
<camera_info_topic_name>camera/camera_info</camera_info_topic_name>
</plugin>
</sensor>
<!-- IMU with higher frequency for fusion -->
<sensor name="imu" type="imu">
<update_rate>200</update_rate>
<plugin name="imu_controller" filename="libgazebo_ros_imu.so">
<frame_name>imu_frame</frame_name>
<topic_name>imu/data</topic_name>
</plugin>
</sensor>
<!-- LIDAR with appropriate frequency -->
<sensor name="lidar" type="ray">
<update_rate>10</update_rate>
<plugin name="lidar_controller" filename="libgazebo_ros_ray.so">
<frame_name>lidar_frame</frame_name>
<topic_name>scan</topic_name>
</plugin>
</sensor>
</model>
</sdf>
Troubleshooting Sensor Simulation
Common Issues and Solutions
Sensor Not Publishing Data
<!-- Solution: Ensure proper plugin configuration -->
<sensor name="camera" type="camera">
<!-- ... camera definition ... -->
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
<frame_name>camera_frame</frame_name>
<topic_name>camera/image_raw</topic_name>
<!-- Make sure namespace is correct -->
<robot_namespace>/my_robot</robot_namespace>
</plugin>
</sensor>
High CPU Usage from Sensors
<!-- Solution: Reduce update rates and resolution -->
<sensor name="camera" type="camera">
<update_rate>10</update_rate> <!-- Lower update rate -->
<camera name="camera">
<image>
<width>320</width> <!-- Lower resolution -->
<height>240</height>
</image>
</camera>
<visualize>false</visualize> <!-- Disable visualization -->
</sensor>
Sensor Noise Too High/Low
<!-- Solution: Adjust noise parameters to match real sensors -->
<sensor name="depth_camera" type="depth">
<camera name="depth_camera">
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev> <!-- Adjust to match real sensor -->
</noise>
</camera>
</sensor>
Best Practices for Sensor Simulation
1. Match Real Sensor Characteristics
Configure simulated sensors to match real hardware:
<!-- Example: Matching RealSense D435 camera -->
<sensor name="realsense_camera" type="depth">
<camera name="realsense_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</far>
</clip>
<!-- Noise parameters matching real sensor -->
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
</sensor>
2. Proper Sensor Placement
Place sensors where they would be on the real robot:
<!-- Camera in the head for humanoid-like vision -->
<joint name="head_camera_joint" type="fixed">
<parent link="head"/>
<child link="head_camera_frame"/>
<origin xyz="0.05 0 0.05" rpy="0 0 0"/> <!-- Forward and slightly up -->
</joint>
<link name="head_camera_frame">
<inertial>
<mass value="0.001"/>
<inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.0001" iyz="0" izz="0.0001"/>
</inertial>
</link>
<gazebo reference="head_camera_frame">
<sensor name="head_camera" type="camera">
<!-- Camera configuration -->
</sensor>
</gazebo>
3. Realistic Noise Modeling
Include appropriate noise models for realistic simulation:
<!-- IMU with realistic noise parameters -->
<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>0.02</stddev> <!-- 0.02 rad/s = ~1.1 deg/s -->
<bias_mean>0.01</bias_mean> <!-- 0.01 rad/s = ~0.6 deg/s bias -->
<bias_stddev>0.005</bias_stddev>
</noise>
</x>
<!-- Similar for y and z axes -->
</angular_velocity>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.017</stddev> <!-- 0.017 * 9.81 m/s² = ~0.17 m/s² -->
<bias_mean>0.05</bias_mean> <!-- 0.05 * 9.81 m/s² = ~0.49 m/s² -->
<bias_stddev>0.01</bias_stddev>
</noise>
</x>
<!-- Similar for y and z axes -->
</linear_acceleration>
</imu>
</sensor>
Hands-On Exercise: Sensor Integration
Objective
Integrate multiple sensors into a humanoid robot model and verify proper data publication.
Prerequisites
- Completed previous chapters
- Working humanoid robot model
- Gazebo simulation environment
Steps
- Add a camera, IMU, and 2D LIDAR to your humanoid robot
- Configure realistic noise models for each sensor
- Set up ROS 2 plugins to publish sensor data
- Launch the simulation and verify that sensor topics are publishing
- Use ROS 2 tools to inspect the sensor data quality
- Optimize sensor parameters for performance while maintaining quality
Expected Result
Students will have a humanoid robot with properly configured sensors publishing realistic data to ROS 2 topics.
Assessment Questions
Multiple Choice
Q1: What is the primary purpose of adding noise models to simulated sensors?
- a) To make the simulation run faster
- b) To make the simulation more realistic by matching real sensor characteristics
- c) To reduce the accuracy of the simulation
- d) To increase the number of sensor topics
Details
Click to reveal answer
Answer: bExplanation: Adding noise models to simulated sensors makes the simulation more realistic by matching the characteristics of real sensors, which have inherent noise and inaccuracies.
Short Answer
Q2: Explain the importance of proper sensor placement on a humanoid robot for effective perception.
Practical Exercise
Q3: Create a robot model with a camera, IMU, and LIDAR. Configure each sensor with realistic parameters and noise models. Verify that each sensor publishes data to the appropriate ROS 2 topics with the correct frame IDs and data quality.
Further Reading
- "Gazebo Sensor Tutorial" - Official Gazebo sensor documentation
- "Robot Sensors and Perception" - Comprehensive guide to robot sensing
- "Simulation-Based Sensor Development" - Best practices for sensor simulation
Summary
In this chapter, we've explored sensor simulation in Gazebo, covering the configuration and use of various sensor types including cameras, LIDAR, IMUs, and force/torque sensors. We've learned how to add realistic noise models, integrate sensors with ROS 2, and optimize sensor performance.
Accurate sensor simulation is crucial for humanoid robotics as it enables the development and testing of perception algorithms that will eventually run on real robots. By properly configuring simulated sensors to match their real-world counterparts, we can bridge the gap between simulation and reality, making the transition to physical robots more successful.
In the next chapter, we'll explore Unity for high-fidelity rendering and how it can complement Gazebo simulation for humanoid robotics applications.