一、安装 Gazebo
1. 安装 Gazebo Harmonic 和 ROS 2 接口
bash
# 更新软件源
sudo apt update
# 安装 Gazebo Harmonic 和 ROS 2 集成包(推荐)
sudo apt install ros-jazzy-ros-gz
# 或分开安装
sudo apt install gz-harmonic # Gazebo 本体
sudo apt install ros-jazzy-ros-gz-sim # ROS 2 接口
2. 安装常用插件和工具
bash
# 机器人控制插件
sudo apt install ros-jazzy-gz-ros2-control
# 传感器插件
sudo apt install ros-jazzy-ros-gz-sim-demos
# 桥接工具(ROS 2 与 Gazebo 通信)
sudo apt install ros-jazzy-ros-gz-bridge
二、启动 Gazebo
基本启动方式
bash
# 方法1:通过 ROS 2 启动(推荐)
ros2 launch ros_gz_sim gz_sim.launch.py
# 方法2:直接启动 Gazebo
gz sim
# 方法3:启动并加载特定世界
gz sim /usr/share/gz/gz-sim8/worlds/shapes.sdf
常用启动参数
bash
# 启动空世界
ros2 launch ros_gz_sim gz_sim.launch.py
# 启动示例世界
ros2 launch ros_gz_sim gz_sim.launch.py world:=shapes.sdf
# 启动时暂停(方便添加模型)
ros2 launch ros_gz_sim gz_sim.launch.py pause:=true
# 指定自定义世界文件
ros2 launch ros_gz_sim gz_sim.launch.py world:=/path/to/your/world.sdf
三、加载机器人模型
1. 使用 launch 文件加载 URDF/SDF
创建 spawn_robot.launch.py:
python
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
import os
def generate_launch_description():
# 启动 Gazebo
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
PathJoinSubstitution([
FindPackageShare('ros_gz_sim'),
'launch',
'gz_sim.launch.py'
])
]),
launch_arguments={'world': 'empty.sdf'}.items()
)
# 发布机器人状态
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
name='robot_state_publisher',
output='screen',
parameters=[{'robot_description': open('/path/to/robot.urdf', 'r').read()}]
)
# 在 Gazebo 中生成机器人
spawn_entity = Node(
package='ros_gz_sim',
executable='create',
arguments=[
'-name', 'my_robot',
'-topic', 'robot_description',
'-x', '0.0',
'-y', '0.0',
'-z', '0.5'
],
output='screen'
)
return LaunchDescription([
gazebo,
robot_state_publisher,
spawn_entity,
])
2. 命令行生成模型
bash
# 生成 URDF 模型
ros2 run ros_gz_sim create -file /path/to/robot.urdf -name my_robot -x 0 -y 0 -z 1
# 生成 SDF 模型
ros2 run ros_gz_sim create -file /path/to/robot.sdf -name my_robot
四、ROS 2 与 Gazebo 通信(桥接)
1. 使用 ros_gz_bridge
命令行方式:
bash
# 桥接特定话题
ros2 run ros_gz_bridge parameter_bridge /clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock
# 桥接多个话题
ros2 run ros_gz_bridge parameter_bridge \
/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
Launch 文件方式:
python
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
bridge = Node(
package='ros_gz_bridge',
executable='parameter_bridge',
arguments=[
'/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock',
'/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',
'/camera/image@sensor_msgs/msg/Image[gz.msgs.Image',
'/camera/camera_info@sensor_msgs/msg/CameraInfo[gz.msgs.CameraInfo',
],
output='screen'
)
return LaunchDescription([bridge])
2. 话题映射规则
| ROS 2 话题 | Gazebo 话题 | 方向 | 说明 |
|---|---|---|---|
/cmd_vel |
/model/robot/cmd_vel |
ROS→Gz | 速度指令 |
/odom |
/model/robot/odometry |
Gz→ROS | 里程计 |
/scan |
/model/robot/scan |
Gz→ROS | 激光雷达 |
/imu |
/model/robot/imu |
Gz→ROS | IMU 数据 |
/camera/image |
/model/robot/camera/image |
Gz→ROS | 相机图像 |
五、完整示例:差速小车仿真
目录结构
my_robot_sim/
├── launch/
│ └── robot_sim.launch.py
├── urdf/
│ └── robot.urdf
├── world/
│ └── my_world.sdf
└── config/
└── bridge.yaml
Launch 文件(完整版)
python
import os
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
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
pkg_share = get_package_share_directory('my_robot_sim')
# 参数
world_file = LaunchConfiguration('world', default='empty.sdf')
# 启动 Gazebo
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
PathJoinSubstitution([
FindPackageShare('ros_gz_sim'),
'launch',
'gz_sim.launch.py'
])
]),
launch_arguments={'world': world_file}.items()
)
# 加载 URDF
urdf_file = os.path.join(pkg_share, 'urdf', 'robot.urdf')
with open(urdf_file, 'r') as f:
robot_description = f.read()
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_description}],
output='screen'
)
# 生成机器人
spawn_robot = Node(
package='ros_gz_sim',
executable='create',
arguments=[
'-name', 'diff_drive_robot',
'-topic', 'robot_description',
'-x', '0.0',
'-y', '0.0',
'-z', '0.1'
],
output='screen'
)
# 桥接
bridge = Node(
package='ros_gz_bridge',
executable='parameter_bridge',
arguments=[
# 时钟
'/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock',
# 速度控制
'/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',
# 相机
'/camera/image@sensor_msgs/msg/Image[gz.msgs.Image',
'/camera/camera_info@sensor_msgs/msg/CameraInfo[gz.msgs.CameraInfo',
# 深度相机(如有)
'/camera/depth@sensor_msgs/msg/Image[gz.msgs.Image',
'/camera/points@sensor_msgs/msg/PointCloud2[gz.msgs.PointCloudPacked',
],
output='screen'
)
# RViz2
rviz = Node(
package='rviz2',
executable='rviz2',
arguments=['-d', os.path.join(pkg_share, 'config', 'robot.rviz')],
output='screen'
)
return LaunchDescription([
DeclareLaunchArgument(
'world',
default_value='empty.sdf',
description='World file to load'
),
gazebo,
robot_state_publisher,
spawn_robot,
bridge,
rviz,
])
六、常用命令速查
bash
# 查看 Gazebo 版本
gz sim --version
# 查看可用世界文件
ls /usr/share/gz/gz-sim8/worlds/
# 查看话题列表(Gazebo 侧)
gz topic -l
# 查看话题信息
gz topic -i /topic/name
# 查看 ROS 2 侧话题
ros2 topic list
# 键盘控制测试
ros2 run teleop_twist_keyboard teleop_twist_keyboard
七、与 Humble 的主要区别
| 功能 | Humble | Jazzy |
|---|---|---|
| Gazebo 版本 | Gazebo 11 (Ignition Fortress) | Gazebo Harmonic |
| 包名 | gazebo_ros |
ros_gz_sim |
| Launch 文件 | gazebo.launch.py |
gz_sim.launch.py |
| 生成模型 | spawn_entity.py |
create |
| 世界格式 | .world |
.sdf |
| 命令行工具 | ign |
gz |
八、常见问题
1. 黑屏或渲染问题
bash
# 尝试软件渲染
export LIBGL_ALWAYS_SOFTWARE=1
ros2 launch ros_gz_sim gz_sim.launch.py
2. 模型无法加载
- 检查
GAZEBO_MODEL_PATH或GZ_SIM_RESOURCE_PATH
bash
export GZ_SIM_RESOURCE_PATH=$HOME/.gz/models:$GZ_SIM_RESOURCE_PATH
3. 找不到包
bash
# 确保 source 了 setup.bash
source /opt/ros/jazzy/setup.bash
source ~/ros2_ws/install/setup.bash