以下是gazebo-simulation技能的中文翻译内容:
name: gazebo-simulation description: 专家级技能,用于Gazebo Classic和Ignition/Gazebo仿真世界创建和插件开发。创建包含地形、照明、物理配置、传感器模型和自定义插件的SDF世界。 allowed-tools: Bash(*) 读写编辑Glob Grep WebFetch metadata: author: babysitter-sdk version: “1.0.0” category: simulation backlog-id: SK-002
gazebo-simulation
你是gazebo-simulation - 一个专为Gazebo仿真环境创建、配置和插件开发提供的专家级技能。
概览
这项技能使得AI驱动的Gazebo仿真成为可能,包括:
- 创建包含地形、照明和物理的SDF世界文件
- 配置物理引擎参数(ODE、Bullet、DART)
- 实现Gazebo插件(模型、世界、传感器、视觉)
- 生成传感器模型(相机、激光雷达、IMU、GPS、深度)
- 设置接触传感器和力-扭矩传感器
- 配置动态演员和动画模型
- 实施自定义物理材料和摩擦
- 创建程序化世界生成
- 优化仿真性能(LOD、碰撞简化)
- 设置多机器人仿真实例
前提条件
- Gazebo Sim(Harmonic、Ionic)或Gazebo Classic(11)
- 带有gazebo_ros_pkgs的ROS2
- SDF规范知识
- 自定义插件的C++开发工具
能力
1. 世界文件创建
生成SDF世界文件:
<?xml version="1.0" ?>
<sdf version="1.8">
<world name="robot_world">
<!-- 物理配置 -->
<physics name="default_physics" type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>1000</real_time_update_rate>
<ode>
<solver>
<type>quick</type>
<iters>50</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>
<!-- 照明 -->
<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>
<direction>-0.5 0.1 -0.9</direction>
</light>
<light type="point" name="point_light">
<pose>5 5 3 0 0 0</pose>
<diffuse>0.5 0.5 0.5 1</diffuse>
<specular>0.1 0.1 0.1 1</specular>
<attenuation>
<range>20</range>
<linear>0.05</linear>
<quadratic>0.001</quadratic>
</attenuation>
</light>
<!-- 地面平面 -->
<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>
<surface>
<friction>
<ode>
<mu>100</mu>
<mu2>50</mu2>
</ode>
</friction>
</surface>
</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>
<!-- 包含模型 -->
<include>
<uri>model://my_robot</uri>
<name>robot1</name>
<pose>0 0 0.1 0 0 0</pose>
</include>
<!-- 插件 -->
<plugin filename="gz-sim-physics-system" name="gz::sim::systems::Physics"/>
<plugin filename="gz-sim-user-commands-system" name="gz::sim::systems::UserCommands"/>
<plugin filename="gz-sim-scene-broadcaster-system" name="gz::sim::systems::SceneBroadcaster"/>
<plugin filename="gz-sim-sensors-system" name="gz::sim::systems::Sensors">
<render_engine>ogre2</render_engine>
</plugin>
</world>
</sdf>
2. 物理引擎配置
配置不同的物理引擎:
<!-- ODE(默认,快速) -->
<physics name="ode_physics" type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<ode>
<solver>
<type>quick</type>
<iters>50</iters>
</solver>
</ode>
</physics>
<!-- Bullet(更适合复杂碰撞) -->
<physics name="bullet_physics" type="bullet">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<bullet>
<solver>
<type>sequential_impulse</type>
<iters>50</iters>
<sor>1.3</sor>
</solver>
</bullet>
</physics>
<!-- DART(最适合机器人学,铰接体) -->
<physics name="dart_physics" type="dart">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<dart>
<collision_detector>fcl</collision_detector>
<solver>
<solver_type>pgs</solver_type>
</solver>
</dart>
</physics>
3. 传感器配置
向机器人添加各种传感器:
<!-- 相机传感器 -->
<sensor name="camera" type="camera">
<always_on>true</always_on>
<update_rate>30</update_rate>
<camera>
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>100</far>
</clip>
<noise>
<type>gaussian</type>
<mean>0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
<plugin filename="gz-sim-camera-system" name="gz::sim::systems::Camera"/>
</sensor>
<!-- 深度相机 -->
<sensor name="depth_camera" type="depth_camera">
<always_on>true</always_on>
<update_rate>15</update_rate>
<camera>
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R_FLOAT32</format>
</image>
<clip>
<near>0.1</near>
<far>10</far>
</clip>
</camera>
<plugin filename="gz-sim-depth-camera-system" name="gz::sim::systems::DepthCamera"/>
</sensor>
<!-- 激光雷达传感器 -->
<sensor name="lidar" type="gpu_lidar">
<always_on>true</always_on>
<update_rate>10</update_rate>
<lidar>
<scan>
<horizontal>
<samples>640</samples>
<resolution>1</resolution>
<min_angle>-3.14159</min_angle>
<max_angle>3.14159</max_angle>
</horizontal>
<vertical>
<samples>16</samples>
<resolution>1</resolution>
<min_angle>-0.26</min_angle>
<max_angle>0.26</max_angle>
</vertical>
</scan>
<range>
<min>0.3</min>
<max>100</max>
<resolution>0.01</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0</mean>
<stddev>0.01</stddev>
</noise>
</lidar>
<plugin filename="gz-sim-gpu-lidar-system" name="gz::sim::systems::GpuLidar"/>
</sensor>
<!-- IMU传感器 -->
<sensor name="imu" type="imu">
<always_on>true</always_on>
<update_rate>200</update_rate>
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.0002</stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.0002</stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.0002</stddev>
</noise>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>0.017</stddev>
</noise>
</x>
</linear_acceleration>
</imu>
<plugin filename="gz-sim-imu-system" name="gz::sim::systems::Imu"/>
</sensor>
<!-- GPS传感器 -->
<sensor name="gps" type="navsat">
<always_on>true</always_on>
<update_rate>5</update_rate>
<navsat>
<position_sensing>
<horizontal>
<noise type="gaussian">
<mean>0</mean>
<stddev>0.5</stddev>
</noise>
</horizontal>
<vertical>
<noise type="gaussian">
<mean>0</mean>
<stddev>1.0</stddev>
</noise>
</vertical>
</position_sensing>
</navsat>
<plugin filename="gz-sim-navsat-system" name="gz::sim::systems::NavSat"/>
</sensor>
4. ROS2-Gazebo桥接
配置ROS2桥接以发布话题:
<!-- 在世界文件中 -->
<plugin filename="gz-sim-ros-gz-bridge" name="ros_gz_bridge::RosGzBridge">
<ros>
<namespace>/robot</namespace>
</ros>
<!-- 相机 -->
<bridge topic="/camera/image_raw" ros_topic="/robot/camera/image_raw" type="sensor_msgs/msg/Image" direction="GZ_TO_ROS"/>
<bridge topic="/camera/camera_info" ros_topic="/robot/camera/camera_info" type="sensor_msgs/msg/CameraInfo" direction="GZ_TO_ROS"/>
<!-- 激光雷达 -->
<bridge topic="/lidar/points" ros_topic="/robot/scan" type="sensor_msgs/msg/PointCloud2" direction="GZ_TO_ROS"/>
<!-- IMU -->
<bridge topic="/imu" ros_topic="/robot/imu" type="sensor_msgs/msg/Imu" direction="GZ_TO_ROS"/>
<!-- 速度命令 -->
<bridge topic="/cmd_vel" ros_topic="/robot/cmd_vel" type="geometry_msgs/msg/Twist" direction="ROS_TO_GZ"/>
<!-- 里程计 -->
<bridge topic="/odom" ros_topic="/robot/odom" type="nav_msgs/msg/Odometry" direction="GZ_TO_ROS"/>
<!-- 关节状态 -->
<bridge topic="/joint_states" ros_topic="/robot/joint_states" type="sensor_msgs/msg/JointState" direction="GZ_TO_ROS"/>
<!-- TF -->
<bridge topic="/tf" ros_topic="/tf" type="tf2_msgs/msg/TFMessage" direction="GZ_TO_ROS"/>
</plugin>
5. 地形和环境
创建地形和环境模型:
<!-- 高度图地形 -->
<model name="terrain">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<heightmap>
<uri>file://terrain/heightmap.png</uri>
<size>100 100 10</size>
<pos>0 0 0</pos>
</heightmap>
</geometry>
</collision>
<visual name="visual">
<geometry>
<heightmap>
<uri>file://terrain/heightmap.png</uri>
<size>100 100 10</size>
<pos>0 0 0</pos>
<texture>
<diffuse>file://terrain/grass.png</diffuse>
<normal>file://terrain/grass_normal.png</normal>
<size>10</size>
</texture>
</heightmap>
</geometry>
</visual>
</link>
</model>
<!-- 障碍物 -->
<model name="obstacle_box">
<static>true</static>
<pose>5 3 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>0.5 0.5 0.5 1</ambient>
</material>
</visual>
</link>
</model>
6. 自定义插件开发
创建自定义Gazebo插件:
// WorldPlugin示例
#include <gz/sim/System.hh>
#include <gz/plugin/Register.hh>
namespace my_plugins {
class MyWorldPlugin : public gz::sim::System,
public gz::sim::ISystemConfigure,
public gz::sim::ISystemPreUpdate
{
public:
void Configure(const gz::sim::Entity &_entity,
const std::shared_ptr<const sdf::Element> &_sdf,
gz::sim::EntityComponentManager &_ecm,
gz::sim::EventManager &_eventMgr) override
{
// 加载时配置
gzmsg << "MyWorldPlugin configured" << std::endl;
}
void PreUpdate(const gz::sim::UpdateInfo &_info,
gz::sim::EntityComponentManager &_ecm) override
{
// 每次仿真步骤前调用
if (_info.paused)
return;
// 自定义逻辑
}
};
}
GZ_ADD_PLUGIN(my_plugins::MyWorldPlugin,
gz::sim::System,
my_plugins::MyWorldPlugin::ISystemConfigure,
my_plugins::MyWorldPlugin::ISystemPreUpdate)
7. 启动文件集成
启动Gazebo与ROS2:
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, DeclareLaunchArgument
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():
pkg_share = FindPackageShare('my_robot_gazebo')
# 世界文件
world_file = PathJoinSubstitution([pkg_share, 'worlds', 'robot_world.sdf'])
# Gazebo启动
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
FindPackageShare('ros_gz_sim'), '/launch/gz_sim.launch.py'
]),
launch_arguments={
'gz_args': ['-r ', world_file],
'on_exit_shutdown': 'true'
}.items()
)
# 机器人生成
spawn_robot = Node(
package='ros_gz_sim',
executable='create',
arguments=[
'-name', 'my_robot',
'-topic', '/robot_description',
'-x', '0', '-y', '0', '-z', '0.1'
],
output='screen'
)
# ROS-GZ桥接
bridge = Node(
package='ros_gz_bridge',
executable='parameter_bridge',
arguments=[
'/cmd_vel@geometry_msgs/msg/Twist@gz.msgs.Twist',
'/odom@nav_msgs/msg/Odometry@gz.msgs.Odometry',
'/scan@sensor_msgs/msg/LaserScan@gz.msgs.LaserScan'
],
output='screen'
)
return LaunchDescription([
gazebo,
spawn_robot,
bridge
])
MCP服务器集成
这项技能可以利用以下MCP服务器增强功能:
| 服务器 | 描述 | 安装 |
|---|---|---|
| Gazebo MCP服务器 | ROS2 MCP for Gazebo | lobehub.com |
| ros-mcp-server | ROS/ROS2桥接 | GitHub |
最佳实践
- 使用适当的物理引擎 - 根据需求选择物理引擎
- 传感器噪声 - 为传感器添加现实噪声模型
- 碰撞简化 - 使用简化的碰撞几何体
- 实时因子 - 根据仿真与实时需求进行调整
- 资源管理 - 禁用未使用的传感器以提高性能
- 模块化世界 - 使用包含可重用的世界组件
流程集成
这项技能与以下流程集成:
gazebo-simulation-setup.js- 主要仿真设置digital-twin-development.js- 数字孪生创建synthetic-data-pipeline.js- 训练数据生成simulation-performance-optimization.js- 性能调整hil-testing.js- 硬件在环测试
输出格式
执行操作时,提供结构化输出:
{
"operation": "create-world",
"worldName": "robot_world",
"status": "success",
"configuration": {
"physicsEngine": "ode",
"realTimeFactor": 1.0,
"sensors": ["camera", "lidar", "imu"]
},
"artifacts": [
"worlds/robot_world.sdf",
"launch/simulation.launch.py"
],
"launchCommand": "ros2 launch my_robot_gazebo simulation.launch.py"
}
约束
- 验证Gazebo版本兼容性(经典版与Sim)
- 检查SDF版本以获取功能可用性
- 测试传感器更新率对性能的影响
- 验证物理参数以确保稳定性
- 确保ROS-GZ桥接话题兼容性