| name | gazebo-simulation-env |
| description | Gazebo 仿真环境创建技能 - 世界文件、地形、障碍物、气象条件、多机器人场景配置 |
| argument-hint | Gazebo仿真环境 OR 创建仿真世界 OR 地形建模 OR gazebo环境配置 |
| user-invocable | true |
Gazebo 仿真环境创建技能
用于在 Gazebo Harmonic 中创建高质量仿真环境,包括地形、障碍物、多机器人场景和气象条件
何时使用
当需要以下帮助时使用此技能:
- 创建 Gazebo 世界文件(.world)
- 构建地形和障碍物
- 配置多机器人仿真场景
- 设置气象条件(光照、雨雪)
- 导入真实环境扫描地图
世界文件结构
最小 Gazebo Harmonic 世界
<?xml version="1.0"?>
<sdf version="1.9">
<world name="empty_world">
<physics name="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>
</physics>
<scene>
<ambient>0.5 0.5 0.5 1</ambient>
<shadows>true</shadows>
<grid>false</grid>
</scene>
<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.1 0.1 0.1 1</specular>
<attenuation><range>1000</range><constant>0.9</constant><linear>0.01</linear><quadratic>0.001</quadratic></attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>
<平面>
<geometry>
<plane>
<size>100 100</size>
<normal>0 0 1</normal>
</plane>
</geometry>
<material>
<ambient>0.5 0.5 0.5 1</ambient>
<diffuse>0.7 0.7 0.7 1</diffuse>
<specular>0.01 0.01 0.01 1</specular>
</material>
</平面>
<include>
<uri>model://my_robot</uri>
<name>robot1</name>
<pose>0 0 0 0 0 0</pose>
</include>
</world>
</sdf>
地形创建
高度图地形
<model name="heightmap_terrain">
<static>true</static>
<link name="terrain_link">
<collision name="collision">
<geometry>
<heightmap>
<use_terrain_paging>false</use_terrain_paging>
<sdf_filename>terrain.dem</sdf_filename>
<texture>
<size>10</size>
<diffuse>file://media/materials/textures/terrain/dirt_diffuse.png</diffuse>
<normal>file://media/materials/textures/terrain/dirt_normal.png</normal>
</texture>
<blur>1.5</blur>
<primitives>3</primitives>
<view_primitives>false</view_primitives>
<>0.5
terrain.dem
file://media/materials/textures/terrain/dirt_diffuse.png
file://media/materials/textures/terrain/dirt_normal.png
程序化不平整地面
import numpy as np
def generate_rough_terrain(size=20, amplitude=0.1):
"""生成粗糙地面高度数据"""
x = np.linspace(-size/2, size/2, 100)
y = np.linspace(-size/2, size/2, 100)
X, Y = np.meshgrid(x, y)
Z = amplitude * np.sin(X * 0.5) * np.cos(Y * 0.5)
Z += 0.05 * np.random.randn(100, 100)
return Z
障碍物配置
静态障碍物
<model name="wall_1">
<static>true</static>
<link name="wall_link">
<pose>5 0 1.25 0 0 0</pose>
<collision name="wall_collision">
<geometry>
<box><size>0.2 5 2.5</size></box>
</geometry>
</collision>
<visual name="wall_visual">
<geometry>
<box><size>0.2 5 2.5</size></box>
</geometry>
<material>
<diffuse>0.6 0.6 0.6 1</diffuse>
</material>
</visual>
</link>
true
3 3 0.5 0 0 0
0.3
1.0
0.3
1.0
0.8 0.2 0.2 1
动态障碍物
<model name="walking_person">
<static>false</static>
<link name="body">
<pose>0 0 0.9 0 0 0</pose>
<collision name="collision">
<geometry>
<cylinder><radius>0.3</radius><length>1.8</length></cylinder>
</geometry>
</collision>
<plugin name="actor_plugin" filename="libActorPlugin.so">
<model>
<walking>
<pose>-5 0 0 0 0 0</pose>
<keyframe>
<time>0</time>
<pose>-5 0 0 0 0 0
2
5 0 0 0 0 0
4
-5 0 0 0 0 0
传感器仿真
激光雷达
<plugin name="gazebo::ros::Rayscan" name="gazebo_ros_laser">
<ros>
<namespace>/robot1</namespace>
<remapping>~/out:=scan</remapping>
</ros>
<frame_name>laser_link</frame_name>
<publish_intensities>false</publish_intensities>
<publish_channels>true</publish_channels>
<update_rate>10</update_rate>
<ray>
<scan>
<horizontal>
<samples>720</samples>
<resolution>1</resolution>
<min_angle>-3.14159</min_angle>
<max_angle>3.14159</max_angle>
</horizontal>
</scan>
<>
0.08
30.0
0.01
gaussian
0.0
0.01
RGB-D 相机
<sensor name="depth_camera" type="depth">
<camera name="depth">
<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>
<plugin name="gazebo_ros_camera" filename="libgazebo_ros_camera.so">
<ros>
<namespace>/robot1</namespace>
<remapping>image_raw:=camera/image_raw</remapping>
<remapping>camera_info:=camera/camera_info
depth
camera_link
气象条件
<scene>
<fog>
<type>exponential</type>
<color>0.9 0.9 0.9 1</color>
<density>0.01</density>
</fog>
<sky>
<clouds>
<speed>10</speed>
<direction>1 0 -1</direction>
<humidity>30</humidity>
</clouds>
</sky>
</scene>
<model name="rain">
<static>true</static>
<link name="rain_link">
<plugin name="ParticleEffect" name="rain">
<filename>particle/rain.dae</>
0
-1
30
-1
多机器人场景
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument
import math
def generate_robot_pose(i, total):
angle = 2 * math.pi * i / total
r = 2.0
x = r * math.cos(angle)
y = r * math.sin(angle)
return f"{x} {y} 0 0 0 {angle}"
def generate_multi_robot_launch(num_robots=3):
robots = []
for i in range(num_robots):
ns = f"robot{i+1}"
robots.append(
DeclareLaunchArgument(f'{ns}_pose', default_value=generate_robot_pose(i, num_robots)),
Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=[
'-entity', f'robot_{i+1}',
'-topic', f'robot_description_{i+1}',
'-namespace', ns,
'-x', str(2 * math.cos(2 * math.pi * i / num_robots)),
'-y', str( * math.sin( * math.pi * i / num_robots)),
],
output=,
),
)
LaunchDescription(robots)
ROS2 launch 整合
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
def generate_launch_description():
pkg_share = get_package_share_directory('my_robot_description')
world_file = os.path.join(pkg_share, 'worlds', 'warehouse.world')
return LaunchDescription([
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')
),
launch_arguments={'world': world_file}.items(),
),
Node(
package='robot_state_publisher',
executable='robot_state_publisher',
name='robot_state_publisher',
parameters=[{'robot_description': open(os.path.join(pkg_share, 'urdf', 'robot.urdf')).read()}],
),
])
故障排查
| 问题 | 原因 | 解决方案 |
|---|
| Gazebo 启动黑屏 | GPU 驱动问题 | export LIBGL_ALWAYS_SOFTWARE=1 |
| 模型加载失败 | URI 路径错误 | 确认 GAZEBO_MODEL_PATH 包含模型目录 |
| 激光雷达无数据 | 插件未加载 | 检查 gz topic -l 确认插件已启动 |
| 物理不稳定 | dt 太大 | 减小 max_step_size |
| 纹理缺失 | 材质路径错误 | 设置 GAZEBO_RESOURCE_PATH |
调试命令
gz topic -l
gz model -l
gz model -m robot1 -x 1 -y 2 -z 0
gz topic -e /robot1/lidar/scan
gz world -w empty_world -r
相关技能
simulator/gazebo-harmonic/robot-modeling — Gazebo 机器人建模
simulator/gazebo-harmonic/sensor-integration — Gazebo 传感器集成
simulator/gazebo-harmonic/plugin-development — Gazebo 插件开发
navigation/nav2-integration — Nav2 导航集成