跳转至

ROS 2 + Docker + Gazebo Harmonic 仿真环境配置

本教程介绍如何在 macOS/Linux 上通过 Docker 配置完整的 ROS 2 Jazzy + Gazebo Harmonic 仿真环境, 包括可视化界面(X11 转发)和 RViz,并在此基础上运行我们开发的 4 个机器人项目。

学习目标

  • 在 macOS 上安装并配置 XQuartz(X11 转发)
  • 构建 Docker 镜像(ROS 2 Jazzy + Gazebo Harmonic + 仿真包)
  • 启动容器并验证 RViz 可视化
  • 启动 Gazebo 仿真 + 机器人模型
  • 掌握统一启动命令:robot_bringup

1. 系统架构

┌─────────────────────────────────────────────────────────────┐
│  macOS 宿主机                                                │
│                                                              │
│  XQuartz (X11 服务器) ────── X11 socket ───→ Docker 容器   │
│  浏览器/终端                                                 │
│       │                                                      │
│  docker compose ───────────→ ros2-jazzy-gazebo:latest        │
│       │                                     │                │
│  Homebrew                          ┌────────────────────────┤
│  (X11 + Docker)                   │  ROS 2 Jazzy           │
│                                    │    ├── Gazebo Harmonic (gz sim)  │
│                                    │    ├── robot_bringup           │
│                                    │    ├── robot_description       │
│                                    │    ├── robot_gazebo           │
│                                    │    ├── robot_navigation        │
│                                    │    └── robot_vslam             │
│                                    │                          │
│                                    │  RViz2 ── GUI via X11 ──┘
│                                    │  Gazebo ── GUI via X11 ──┘
└─────────────────────────────────────────────────────────────┘

为什么要用 Docker?

优势 说明
零污染 不污染主机系统,ROS/Gazebo 依赖复杂
一致性 团队成员同一镜像,避免"在我机器上能跑"问题
可重复 docker compose build 保证每次环境相同
GPU 支持 Apple Silicon M 系列 GPU 可直接穿透

2. 安装 XQuartz(仅 macOS)

Docker 里的 RViz 和 Gazebo 需要 X11 显示服务。macOS 需要安装 XQuartz。

# Step 1: 通过 Homebrew 安装 XQuartz
brew install --cask xquartz

# Step 2: 重启 macOS(XQuartz 需要注册 X11 服务)
#    点击 Apple Logo → 重启

# Step 3: 允许本地 X11 连接
xhost + 127.0.0.1

# Step 4: 验证 XQuartz
open -a XQuartz
# 检查 XQuartz → Preferences → Output → "Enable connection from network clients" 勾选

必须重启 macOS

XQuartz 安装后必须重启系统,否则 /tmp/.X11-unix socket 不会创建, Docker 容器无法挂载 X11 socket,导致 RViz 无法显示。


3. 构建 Docker 镜像

cd ~/ros2_ws

# 构建包含所有仿真包的镜像(首次约需 20-30 分钟)
docker compose build ros2-dev

# 如果构建报错,检查 Docker Desktop 内存设置 ≥ 8GB
# Docker Desktop → Settings → Resources → Memory: 8GB+

镜像内包含的关键包

包名 说明
ros:jazzy ROS 2 Jazzy 基础镜像
gz-harmonic Gazebo Harmonic 仿真引擎
ros-jazzy-ros-gzsim ROS 2 ↔ Gazebo 桥接
ros-jazzy-moveit 机械臂运动规划
ros-jazzy-slam-toolbox 激光 SLAM 建图
ros-jazzy-rviz2 3D 可视化
ros-jazzy-nav2-* 导航2 全栈

4. 启动容器

# 方式 A: 后台启动开发容器
docker compose up -d ros2-dev     # 后台运行
docker compose exec ros2-dev bash # 进入容器

# 方式 B: 一行命令启动并进入
docker compose run --rm ros2-dev bash

验证 ROS 2 安装

# 在容器内执行
source /opt/ros/jazzy/setup.bash

ros2 pkg list | grep -E "gazebo|rviz|nav2|slam"
# 应该看到 ros_gz_sim, rviz2, nav2_bringup, slam_toolbox 等

5. 构建仿真包

# 在容器内
cd /root/ros2_ws

# 首次需要安装依赖
rosdep install --from-paths src --ignore-src -r -y

# 构建所有包(--symlink-install: 修改源码后无需重新构建整个包)
colcon build --symlink-install

# 激活 workspace
source install/setup.bash

预期输出:

Summary: X packages succeeded
  - robot_description
  - robot_gazebo
  - robot_bringup
  - robot_navigation
  - robot_vslam


6. 一键启动仿真

# 移动机器人(差速驱动 + 激光雷达)
ros2 launch robot_bringup robot.launch.py robot_type:=mobile

# 机械臂(7-DOF + 夹爪)
ros2 launch robot_bringup robot.launch.py robot_type:=manipulator

# 无人机(四旋翼 + 深度相机)
ros2 launch robot_bringup robot.launch.py robot_type:=drone world:=aerial_world

启动流程:

1. gz sim (Gazebo Harmonic) 启动,加载 world 文件
2. robot_state_publisher 解析 URDF 并发布 robot_description
3. 机器人模型被 spawn 到 Gazebo 场景中
4. ROS 2 ↔ Gazebo 桥接激活(时钟、里程计、激光、IMU)
5. RViz2 自动启动并显示机器人3D模型
6. teleop_twist_keyboard 键盘控制节点运行


7. 键盘遥控

在另一个终端(容器内)运行键盘控制:

# 终端 1: 启动仿真
docker compose exec ros2-dev bash
ros2 launch robot_bringup robot.launch.py robot_type:=mobile

# 终端 2: 键盘控制
docker compose exec ros2-dev bash
source /opt/ros/jazzy/setup.bash
source /root/ros2_ws/install/setup.bash
ros2 run teleop_twist_keyboard teleop_twist_keyboard

键盘控制说明

按键 动作
i 前进
, 后退
j 左转
l 右转
k 停止
q 加速
z 减速

8. RViz 可视化

RViz 已集成在 robot.launch.py 中自动启动。如需单独启动:

# 加载预配置的 RViz 界面(推荐)
rviz2 -d $(find robot_description)/config/robot.rviz

# 或者手动配置:
# 1. Add → RobotModel → Description Topic: /robot_description
# 2. Add → LaserScan → Topic: /scan
# 3. Add → TF display
# 4. Add → Image (depth camera): /depth_camera/color/image_raw

RViz 面板说明

面板 用途
RobotModel 显示 URDF 机器人3D模型
TF 坐标变换树(base_link → lidar_link → imu_link...)
LaserScan 激光雷达扫描点(红色)
Image 深度相机 RGB 画面
Path 导航路径
Pose 机器人当前位置估计

9. 各项目启动命令

项目一:移动机器人导航

# SLAM 建图模式
ros2 launch robot_navigation navigation.launch.py

# 2D 地图出现在 /map topic
# 在 RViz 中: Add → Map → Topic: /map
# 用键盘控制机器人在房间走动,地图逐渐构建

# 保存地图
ros2 run nav2_map_server map_saver_cli -f ~/map

项目二:机械臂(MoveIt2)

# 启动 MoveIt2 运动规划
ros2 launch moveit2_scripts demo.launch.py

# RViz 中: 使用 MotionPlanning 插件
# 拖动机械臂末端 → 自动规划无碰撞轨迹

项目三:无人机

# 无人机仿真
ros2 launch robot_bringup robot.launch.py robot_type:=drone world:=aerial_world

# 键盘控制(高度)
ros2 run teleop_twist_keyboard teleop_twist_keyboard /cmd_vel:=drone/cmd_vel

项目四:视觉导航

# 深度相机 + VSLAM
ros2 launch robot_vslam vslam.launch.py camera:=depth_camera

# 启动视觉导航
ros2 launch robot_bringup robot.launch.py robot_type:=mobile vslam:=true

10. 常见问题排查

X11 转发不工作

# 症状: RViz 窗口不出现

# 检查 1: XQuartz 是否运行
ps aux | grep Xquartz

# 检查 2: DISPLAY 环境变量
echo $DISPLAY
# 期望输出: host.docker.internal:0  或  :0

# 检查 3: X11 socket 是否存在
ls -la /tmp/.X11-unix/
# 期望: srwxrwxrwt ... X0

# 手动修复: 设置 DISPLAY
export DISPLAY=host.docker.internal:0
ros2 run rviz2 rviz2

Docker GPU 访问(Apple Silicon)

# 检查 Docker 是否识别 GPU
docker run --rm --device /dev/dri --privileged \
  ros:jazzy ros2 run demo_nodes_py talker

# Apple Silicon: 无需额外驱动,Docker Desktop 自动处理
# Intel/NVIDIA: 添加 --gpus all 参数

Gazebo 启动崩溃

# 降低仿真精度
gz sim -r --physics-engine ode basic_world.sdf

# 或使用无 GUI 模式(headless)
gz sim -s basic_world.sdf

找不到包(Package Not Found)

# 修改源码后重新构建
colcon build --symlink-install
source install/setup.bash

# 或加到 ~/.bashrc(自动生效)
echo "source /root/ros2_ws/install/setup.bash" >> ~/.bashrc

11. Docker 工作流总结

# ============================================================
# 日常工作流程
# ============================================================

# 1. 启动 Docker Desktop (macOS)

# 2. 启动开发容器
cd ~/ros2_ws
docker compose up -d ros2-dev
docker compose exec ros2-dev bash

# 3. 编写代码(在容器内或宿主机 ~/ros2_ws/src/)
#    源码修改后:
cd /root/ros2_ws
colcon build --symlink-install && source install/setup.bash

# 4. 运行仿真
ros2 launch robot_bringup robot.launch.py robot_type:=mobile

# 5. 停止
exit
docker compose down

12. 项目代码结构

~/ros2_ws/
├── Dockerfile              # 完整的仿真环境定义
├── docker-compose.yml      # 容器编排(GPU + X11)
├── src/
│   ├── my_first_pkg/       # ROS2 入门示例
│   ├── robot_description/  # URDF/xacro 模型(核心)
│   │   ├── urdf/
│   │   │   ├── common.xacro      # 共享宏(gazebo插件、惯性、材质)
│   │   │   ├── sensors.xacro     # 传感器(lidar、imu、realsense)
│   │   │   ├── mobile_robot.urdf.xacro
│   │   │   ├── manipulator.urdf.xacro
│   │   │   └── aerial_drone.urdf.xacro
│   │   └── config/
│   │       ├── robot.rviz        # RViz 可视化配置
│   │       └── controllers.yaml  # ROS2 Control 参数
│   ├── robot_gazebo/       # Gazebo 仿真世界 + 桥接
│   │   ├── worlds/
│   │   │   ├── basic_world.sdf   # 仓库环境(导航测试)
│   │   │   └── aerial_world.sdf  # 空中飞行环境
│   │   └── launch/
│   │       └── gazebo.launch.py
│   ├── robot_bringup/       # 统一启动器(核心入口)
│   │   └── launch/
│   │       └── robot.launch.py
│   ├── robot_navigation/   # SLAM + Nav2 导航栈
│   │   ├── config/
│   │   │   ├── slam_params.yaml  # SLAM Toolbox 配置
│   │   │   └── nav2_params.yaml  # Nav2 参数
│   │   └── launch/
│   │       └── navigation.launch.py
│   └── robot_vslam/         # 视觉 SLAM
│       └── launch/
│           └── vslam.launch.py

参考资料