init: ROS2 learning suite

This commit is contained in:
xs
2026-08-03 18:09:35 +08:00
commit 5ef38ab508
95 changed files with 13322 additions and 0 deletions
+405
View File
@@ -0,0 +1,405 @@
# 85 · Docker 容器化开发(完全指南)
> **目标**:吃透本仓库 Docker 配置,知道每行在做什么,能改能扩,能在 Win/macOS/Linux 一致跑 ROS2。
---
## 目录
- [1. 为什么用 Docker](#1-为什么用-docker)
- [2. 镜像构建](#2-镜像构建)
- [3. 容器编排](#3-容器编排)
- [4. 容器生命周期命令](#4-容器生命周期命令)
- [5. 一键启动脚本](#5-一键启动脚本)
- [6. 调试技巧](#6-调试技巧)
- [7. 常见坑](#7-常见坑)
- [8. 多机 / 多机器人扩展](#8-多机--多机器人扩展)
- [9. 在本仓库里跑](#9-在本仓库里跑)
- [10. 进阶:多阶段构建 + 镜像瘦身](#10-进阶多阶段构建--镜像瘦身)
---
## 1. 为什么用 Docker
| 痛点 | Docker 怎么解 |
|---|---|
| Linux/Windows/macOS 行为差异 | 镜像固定 Linux,行为一致 |
| ROS2 apt 装一堆,污染系统 | 容器内隔离 |
| 团队协作"在我机器能跑" | 镜像统一 |
| 升级 ROS 版本代价大 | 换镜像就行 |
| 跨语言/多版本测试 | 同一镜像多容器 |
本仓库基于 **`osrf/ros:humble-desktop`**(OSRF 官方维护):
- ROS2 Humble 完整运行时
- 默认 RMW: `rmw_fastrtps_cpp`
- 自带 RViz2 / rqt / colcon / rosdep
---
## 2. 镜像构建
### 2.1 Dockerfile
[`docker/Dockerfile`](../docker/Dockerfile) 在 `osrf/ros:humble-desktop` 之上加:
```dockerfile
FROM osrf/ros:humble-desktop
ENV DEBIAN_FRONTEND=noninteractive
ENV ROS_DISTRO=humble
ENV WORKSPACE=/root/ros2_ws
RUN apt-get update && apt-get install -y \
python3-colcon-common-extensions \
python3-pip \
nano \
curl \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install -U colcon-argcomplete colcon-common-extensions
RUN echo 'source /opt/ros/humble/setup.bash' >> /root/.bashrc && \
echo 'source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash' >> /root/.bashrc
WORKDIR ${WORKSPACE}
CMD ["bash"]
```
### 2.2 构建
```powershell
# Windows
docker compose -f D:\xs\ros2\docker\docker-compose.yml build
```
```bash
# Linux
docker compose -f docker/docker-compose.yml build
```
镜像名:`ros2-humble-dev:latest`,约 3GB。
### 2.3 镜像内已装
- ROS2 Humble Desktop
- `colcon-common-extensions` + `colcon-argcomplete`
- `cv_bridge` (openCV ↔ ROS Image)
- `ros-humble-tf2-tools` (`view_frames`)
- `ros-humble-robot-state-publisher` (URDF → TF)
**未装**(按需补):
- `ros-humble-rmw-cyclonedds-cpp`(默认 fastdds 够用)
- `ros-humble-ros2-control`
- `ros-humble-moveit`
- `ros-humble-navigation2`
### 2.4 修改镜像(自定义)
加包:在 `apt-get install` 加一行:
```dockerfile
RUN apt-get install -y ros-humble-ros2-control ros-humble-ros2-controllers
```
加 Python 包:
```dockerfile
RUN pip3 install ultralytics==8.0.0 numpy==1.26
```
---
## 3. 容器编排
### 3.1 docker-compose.yml
[`docker/docker-compose.yml`](../docker/docker-compose.yml):
```yaml
services:
ros2:
build: .
image: ros2-humble-dev:latest
container_name: ros2_dev
privileged: true # 调试用
stdin_open: true # docker exec -it
tty: true
network_mode: host # DDS multicast 必须
environment:
- ROS_DOMAIN_ID=0
# 不要设 RMW_IMPLEMENTATION=rmw_cyclonedds_cpp:
# 镜像没装 cyclone dds,CMake 配置会失败。
volumes:
- ..:/root/ros2_ws # bind mount 本机 D:\xs\ros2
working_dir: /root/ros2_ws
command: ["bash", "-lc", "tail -f /dev/null"] # 容器永不退
```
### 3.2 为什么 host network
ROS2 默认用 DDS multicast 在同一网段自动发现节点。多容器或跨主机时,**bridge 网络
会拦截 multicast**,导致节点看不见彼此。
`network_mode: host` 让容器用宿主机的网络栈,直接走 multicast。
### 3.3 为什么 bind mount 整个工程
`..` 是 docker-compose.yml 的上一级(`D:\xs\ros2`)。挂到容器内
`/root/ros2_ws`,**你在 Windows 改代码,容器内 colcon 立即看到**(`--symlink-install`)。
---
## 4. 容器生命周期命令
```powershell
# 构建镜像
docker compose -f D:\xs\ros2\docker\docker-compose.yml build
# 启动(后台)
docker compose -f D:\xs\ros2\docker\docker-compose.yml up -d
# 状态
docker compose -f D:\xs\ros2\docker\docker-compose.yml ps
# 进开发终端
docker exec -it ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && exec bash"
# 一次性跑命令
docker exec ros2_dev bash -lc "cd /root/ros2_ws && colcon build --packages-select py_pubsub"
# 关
docker compose -f D:\xs\ros2\docker\docker-compose.yml down
# 重启
docker compose -f D:\xs\ros2\docker\docker-compose.yml restart
# 删容器(保留镜像)
docker compose -f D:\xs\ros2\docker\docker-compose.yml down
# 删镜像
docker rmi ros2-humble-dev:latest
# 看日志
docker logs -f ros2_dev
```
---
## 5. 一键启动脚本
### 5.1 start.ps1 (Windows)
```powershell
powershell D:\xs\ros2\start.ps1
```
等价于:
```powershell
docker compose build # 首次 5-10min
docker compose up -d
docker exec ros2_dev bash -lc "cd /root/ros2_ws && bash build.sh"
docker exec -it ros2_dev bash -lc "source install/setup.bash && exec bash"
```
### 5.2 start.sh (Linux/macOS)
```bash
./start.sh
```
### 5.3 build.sh (容器内)
```bash
bash build.sh
# 1) source /opt/ros/humble/setup.bash
# 2) colcon build --symlink-install --packages-select <all>
# 3) ls install/
# 4) 打印运行命令速查
```
---
## 6. 调试技巧
### 6.1 看容器日志
```bash
docker logs ros2_dev
docker logs -f ros2_dev # 持续
```
### 6.2 进容器交互 shell
```bash
docker exec -it ros2_dev bash
# 进入后:
source /opt/ros/humble/setup.bash
cd /root/ros2_ws
source install/setup.bash
```
### 6.3 在容器内单次跑命令
```bash
docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && ros2 node list"
```
### 6.4 看 DDS 流量
```bash
docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && ros2 doctor --report"
```
### 6.5 看网络
```bash
docker exec ros2_dev bash -lc "ip addr; ip route"
```
### 6.6 容器与宿主机共享 GPU(可选)
```yaml
services:
ros2:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
```
---
## 7. 常见坑
### 7.1 容器启动后找不到 ros2 命令
容器里 `/opt/ros/humble/setup.bash` 没 source。每个 shell 都要 source,
或者写进 `~/.bashrc`(已加,新 bash 自动 source)。
### 7.2 改了源码但 colcon 看不到
确认 `--symlink-install`(默认配置里加上了)。否则需要重 build。
### 7.3 跨容器看不到节点
- 同一 ROS Domain(`ROS_DOMAIN_ID`)
- host network(本仓库用了)
- multicast 没被拦截
### 7.4 Windows bind mount 文件锁
有时 LSP / IDE 持文件锁,导致容器内 colcon 失败。关掉 IDE 或在容器内编辑。
### 7.5 容器启动很慢
- Docker Desktop 未运行
- WSL2 后端未启用
- 镜像太大(本仓库 ~3GB 正常)
### 7.6 容器 OOM
Docker Desktop → Settings → Resources → Memory 调到 ≥ 4GB。
---
## 8. 多机 / 多机器人扩展
```yaml
# docker-compose.yml 改成:
services:
robot1:
image: ros2-humble-dev:latest
container_name: ros2_robot1
network_mode: host
environment:
- ROS_DOMAIN_ID=42
- ROS_NAMESPACE=robot1
volumes:
- ./robot1_conf:/root/ros2_ws
robot2:
image: ros2-humble-dev:latest
container_name: ros2_robot2
network_mode: host
environment:
- ROS_DOMAIN_ID=42
- ROS_NAMESPACE=robot2
volumes:
- ./robot2_conf:/root/ros2_ws
central:
image: ros2-humble-dev:latest
container_name: ros2_central
network_mode: host
environment:
- ROS_DOMAIN_ID=42
command: ["bash", "-lc", "ros2 launch bringup multi_robot_launch.py"]
```
每个 container 各跑一组节点,`ROS_NAMESPACE` 隔离命名空间,
`ROS_DOMAIN_ID` 共享同一总线 → 跨容器通讯。
详见 [`doc/100-embedded-deployment.md`](100-embedded-deployment.md)。
---
## 9. 在本仓库里跑
### 9.1 一键启
```powershell
powershell D:\xs\ros2\start.ps1
```
### 9.2 进入后跑测试
```bash
docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && cd /root/ros2_ws && colcon test --packages-select py_pubsub cpp_pubsub py_srv py_action_demo cpp_robot_tf2 py_vision_demo bringup"
```
### 9.3 跑 demo
```bash
docker exec ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && ros2 launch bringup full_demo_launch.py"
```
---
## 10. 进阶:多阶段构建 + 镜像瘦身
### 10.1 当前镜像大小
```bash
docker images ros2-humble-dev
# SIZE: 3.4GB
```
来源:
- `osrf/ros:humble-desktop`: ~2.1GB(包含 RViz / rqt / Gazebo)
- 我们的 apt 包 + colcon: ~1.3GB
### 10.2 改用 `osrf/ros:humble-ros-base`
基础镜像改成 `humble-ros-base`(无 RViz / rqt):
```dockerfile
FROM osrf/ros:humble-ros-base
```
**SIZE 减少 ~1.5GB**。但少了 RViz / rqt / Gazebo,如果需要这些再加 apt。
### 10.3 多阶段构建(进一步瘦身)
```dockerfile
# Stage 1: build
FROM osrf/ros:humble-ros-base AS builder
# ... 装 build 工具,build 我们的包 ...
# Stage 2: runtime
FROM osrf/ros:humble-ros-base
COPY --from=builder /root/ros2_ws/install /root/ros2_ws/install
# 不带 build 工具,更小
```
适合 CI 流水线 + 生产环境。
---
## 接下来读
| 主题 | 文档 |
|---|---|
| venv 工作流 | [`02-virtualenv.md`](02-virtualenv.md) |
| 测试策略 | [`90-testing.md`](90-testing.md) |
| 三机部署 | [`100-embedded-deployment.md`](100-embedded-deployment.md) |
| 项目总览 | [`00-overview.md`](00-overview.md) |