This commit is contained in:
2026-08-04 18:14:49 +08:00
parent 74b3c89e1e
commit 61796dfa9f
8 changed files with 201 additions and 95 deletions
+11 -11
View File
@@ -12,7 +12,7 @@
4. **禁止问与思考循环**。给出明确方案,直接开干。 4. **禁止问与思考循环**。给出明确方案,直接开干。
5. **测试必须 100% 通过才能停手** 5. **测试必须 100% 通过才能停手**
- `make colcon-build` + `make colcon-test` 全绿才能汇报"完成" - `make colcon-build` + `make colcon-test` 全绿才能汇报"完成"
- 当前实测:**12 包 / 78 用例(64 pytest + 14 gtest) 100% 通过** - 当前实测:**12 包 / 82 用例(64 pytest + 14 gtest + 4 launch_test) 100% 通过**
6. **调试日志/临时输出统一放 `.logs/` 目录**。禁止在项目根目录散放 `*.log``*.xml` 等临时文件。 6. **调试日志/临时输出统一放 `.logs/` 目录**。禁止在项目根目录散放 `*.log``*.xml` 等临时文件。
- `.logs/` 已加入 `.gitignore`,不会进版本控制 - `.logs/` 已加入 `.gitignore`,不会进版本控制
- 用法: `docker exec ... > .logs/build.log 2>&1` - 用法: `docker exec ... > .logs/build.log 2>&1`
@@ -96,23 +96,23 @@ D:\xs\ros2\
| 查看日志 | `make logs` | | 查看日志 | `make logs` |
| 本机 venv 初始化 | `make venv-setup`(或 `powershell .\tools\setup_venv.ps1`) | | 本机 venv 初始化 | `make venv-setup`(或 `powershell .\tools\setup_venv.ps1`) |
## 测试覆盖(12 包 / 78 用例 / 100% 目标) ## 测试覆盖(12 包 / 82 用例 / 100% 目标)
| 包 | 类型 | 测试 | | 包 | 类型 | 测试 |
|---|---|---| |---|---|---|
| py_pubsub | pytest | 11/11 | | py_pubsub | pytest | 11/11 |
| cpp_pubsub | gtest | 3/3 | | cpp_pubsub | gtest + launch_test | 4/4 |
| py_srv | pytest | 6/6 | | py_srv | pytest | 7/7 |
| py_action_demo | pytest | 4/4 | | py_action_demo | pytest | 5/5 |
| cpp_robot_tf2 | gtest | 4/4 | | cpp_robot_tf2 | gtest + launch_test | 5/5 |
| py_vision_demo | pytest | 11/11 | | py_vision_demo | pytest | 13/13 |
| py_params | pytest | 16/16 | | py_params | pytest | 16/16 |
| cpp_custom_interface | gtest | 3/3 | | cpp_custom_interface | gtest + launch_test | 4/4 |
| py_lifecycle_composable | pytest | 6/6 | | py_lifecycle_composable | pytest | 6/6 |
| cpp_qos_demo | gtest | 4/4 | | cpp_qos_demo | gtest + launch_test | 5/5 |
| py_overlay_dds | pytest | 6/6 | | py_overlay_dds | pytest | 6/6 |
| bringup | launch | 6/6 | | bringup | pytest(0) | 0/0 |
| **总计** | | **80/80** | | **总计** | | **82/82** |
## 子项目约定 ## 子项目约定
+1 -1
View File
@@ -293,7 +293,7 @@ Failed <<< py_pubsub [1 min 30 s]
**核心特点**: **核心特点**:
- ✅ 12 个真实可运行的 ROS2 包,涵盖 ROS2 几乎所有核心机制 - ✅ 12 个真实可运行的 ROS2 包,涵盖 ROS2 几乎所有核心机制
-78 个测试用例 100% 通过(可运行、可验证、不踩坑) - ✅ 82 个测试用例 100% 通过(64 pytest + 14 gtest + 4 launch_test,可运行、可验证、不踩坑)
- ✅ 24 篇深度文档,从 Hello World 到三机部署 - ✅ 24 篇深度文档,从 Hello World 到三机部署
- ✅ 跨语言互通(py ↔ cpp),贴近工业真实场景 - ✅ 跨语言互通(py ↔ cpp),贴近工业真实场景
- ✅ Docker 容器化,Windows / Linux / Mac 都能跑 - ✅ Docker 容器化,Windows / Linux / Mac 都能跑
+20 -8
View File
@@ -20,8 +20,8 @@
## 1. 一句话定位 ## 1. 一句话定位
> **ROS2 Humble 7 包全栈实战** — Topic / Service / Action / TF2 / URDF / Vision 六大通信范式 + > **ROS2 Humble 12 包全栈实战** — Topic / Service / Action / TF2 / URDF / Vision 六大通信范式 +
> Python/C++ 双语言互通 + 端到端 launch + **10/10 测试 100% 通过** + 15 篇文档 — > Python/C++ 双语言互通 + 端到端 launch + **82/82 测试 100% 通过** + 24 篇文档 —
> 为 VLA / 具身智能开发铺平最后一段学习路径。 > 为 VLA / 具身智能开发铺平最后一段学习路径。
--- ---
@@ -53,7 +53,9 @@
│ │ colcon build / install / test │ │ │ │ colcon build / install / test │ │
│ │ src/py_pubsub src/cpp_pubsub src/py_srv │ │ │ │ src/py_pubsub src/cpp_pubsub src/py_srv │ │
│ │ src/py_action_demo src/cpp_robot_tf2 │ │ │ │ src/py_action_demo src/cpp_robot_tf2 │ │
│ │ src/py_vision_demo src/bringup │ │ │ │ src/py_vision_demo src/py_params │ │
│ │ src/cpp_custom_interface src/py_lifecycle_composable │ │
│ │ src/cpp_qos_demo src/py_overlay_dds src/bringup │ │
│ │ ↓ │ │ │ │ ↓ │ │
│ │ install/<pkg>/share/<pkg>/launch/*.py │ │ │ │ install/<pkg>/share/<pkg>/launch/*.py │ │
│ │ install/<pkg>/lib/<pkg>/<exec> │ │ │ │ install/<pkg>/lib/<pkg>/<exec> │ │
@@ -89,6 +91,11 @@
| **py_action_demo** | Action 三件套(Python) | ament_python | rclpy, example_interfaces | | **py_action_demo** | Action 三件套(Python) | ament_python | rclpy, example_interfaces |
| **cpp_robot_tf2** | URDF + TF2 + JointState(C++) | ament_cmake | rclcpp, tf2, geometry_msgs, sensor_msgs | | **cpp_robot_tf2** | URDF + TF2 + JointState(C++) | ament_cmake | rclcpp, tf2, geometry_msgs, sensor_msgs |
| **py_vision_demo** | sensor_msgs/Image(Python) | ament_python | rclpy, sensor_msgs, cv_bridge | | **py_vision_demo** | sensor_msgs/Image(Python) | ament_python | rclpy, sensor_msgs, cv_bridge |
| **py_params** | 参数系统 + 校验回调(Python) | ament_python | rclpy, rcl_interfaces |
| **cpp_custom_interface** | 自定义 .msg/.srv/.action(C++) | ament_cmake | rclcpp, rclcpp_action, rosidl_default_generators |
| **py_lifecycle_composable** | Lifecycle + Composable(Python) | ament_python | rclpy, lifecycle_msgs |
| **cpp_qos_demo** | QoS 9 种组合(C++) | ament_cmake | rclcpp, std_msgs |
| **py_overlay_dds** | DDS 配置 + colcon overlay(Python) | ament_python | rclpy, launch |
| **bringup** | 顶层 launch 聚合(Python) | ament_python | launch, launch_ros | | **bringup** | 顶层 launch 聚合(Python) | ament_python | launch, launch_ros |
**设计原则**: **设计原则**:
@@ -182,12 +189,16 @@ D:\xs\ros2\
| 知识点 | 状态 | | 知识点 | 状态 |
|---|---| |---|---|
| ROS2 通信(Topic / Service / Action / Parameter) | ✅ | | ROS2 通信(Topic / Service / Action / Parameter) | ✅ |
| 自定义 .msg/.srv/.action + rosidl 编译 | ✅ |
| QoS 9 种组合(RELIABLE / BEST_EFFORT / TRANSIENT_LOCAL ...) | ✅ |
| Lifecycle Node(unconfigured → active → finalized) | ✅ |
| TF2 坐标变换 + URDF | ✅ | | TF2 坐标变换 + URDF | ✅ |
| sensor_msgs/Image + cv_bridge | ✅ | | sensor_msgs/Image + cv_bridge | ✅ |
| JointState 发布 | ✅ | | JointState 发布 | ✅ |
| DDS 配置 + colcon overlay + 多机部署 | ✅ |
| Launch + 测试 + Docker + venv | ✅ | | Launch + 测试 + Docker + venv | ✅ |
| 跨语言互通 | ✅ | | 跨语言互通(py ↔ cpp) | ✅ |
| 文档齐全(15 篇) | ✅ | | 文档齐全(24 篇) | ✅ |
### 6.2 ❌ 没覆盖(下一步) ### 6.2 ❌ 没覆盖(下一步)
@@ -246,8 +257,9 @@ sudo apt install ros-humble-navigation2
- 节点名小写下划线 + 后缀(`talker_py`, `joint_state_publisher_cpp`) - 节点名小写下划线 + 后缀(`talker_py`, `joint_state_publisher_cpp`)
### 8.3 测试 ### 8.3 测试
- 每个 Python 包 4 个测试用例 - 12 包 / **82 用例**(64 pytest + 14 gtest + 4 launch_test),100% 通过
- 每个 C++ 包 2gtest - Python 包 6 ~ 16pytest 不等(深度按包而定)
- C++ 包 3 ~ 4 个 gtest + launch_test
- 集成测试用 in-process spin(避免 launch_testing 的 shutdown 二次调用问题) - 集成测试用 in-process spin(避免 launch_testing 的 shutdown 二次调用问题)
### 8.4 文档 ### 8.4 文档
@@ -275,7 +287,7 @@ sudo apt install ros-humble-navigation2
## 📖 阅读路径导航 ## 📖 阅读路径导航
> 💡 这是仓库 `doc/` 下所有文档的推荐阅读顺序。[返回 README 总导航](../README.md#-23-篇文档怎么读) > 💡 这是仓库 `doc/` 下所有文档的推荐阅读顺序。[返回 README 总导航](../README.md#-24-篇文档怎么读)
> >
> ⏱ **本文预计阅读时间**: 20 分钟 > ⏱ **本文预计阅读时间**: 20 分钟
> 📍 **当前位置**: 第 1 / 24 篇 > 📍 **当前位置**: 第 1 / 24 篇
+50 -18
View File
@@ -78,10 +78,10 @@ cd D:\xs\ros2
# Linux / macOS # Linux / macOS
cd /path/to/ros2 cd /path/to/ros2
``` ```
### 2.2 构建镜像(首次 5-10 分钟) ### 2.2 构建镜像(首次 5-10 分钟)
```bash ```bash
docker compose -f docker/docker-compose.yml build docker compose -p ros2 -f docker/docker-compose.yml build
``` ```
**这一步做了什么**: **这一步做了什么**:
@@ -116,13 +116,14 @@ docker images
## Step 3: 启动容器 ## Step 3: 启动容器
```bash ```bash
docker compose -f docker/docker-compose.yml up -d docker compose -p ros2 -f docker/docker-compose.yml up -d
``` ```
**参数说明**: **参数说明**:
- `-p ros2`:compose project 名,所有容器归在 `ros2` 项目下(脱离默认 `docker`)
- `up -d`:后台启动(`-d` = detached) - `up -d`:后台启动(`-d` = detached)
- `container_name: ros2_dev`:容器名叫这个 - `container_name: ros2_dev`:容器名叫这个
- `network_mode: host`:DDS multicast 必须 - `networks: ros2_net`:自定义 bridge(脱离 docker_default,IP 段 172.20.0.0/24)
**预期**: **预期**:
``` ```
@@ -140,15 +141,19 @@ docker ps
**进入开发终端**: **进入开发终端**:
```bash ```bash
docker exec -it ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && exec bash" docker exec -it ros2_dev bash -lc "source /opt/ros/humble/setup.bash && source /root/ros2_ws/install/setup.bash && exec bash"
``` ```
> ❗ **两个 `source` 都要有**:
> - `source /opt/ros/humble/setup.bash` — 加载 ROS2 环境变量(rclpy / colcon / ros2 CLI)
> - `source /root/ros2_ws/install/setup.bash` — 加载本项目 12 个编译产物(只有 build 后才有 `install/`,第 4 步前先注释掉这一行)
你应该看到类似: 你应该看到类似:
``` ```
root@docker-desktop:/root/ros2_ws# root@docker-desktop:/root/ros2_ws#
``` ```
> 💡 **小技巧**: `docker exec -it ros2_dev bash` 进入容器;**`exec` 前要保证容器在运行**(`docker ps` 看到 `Up` 状态)。 > 💡 **小技巧**: 用 `bash scripts/shell.sh` 一键进入(自动检查容器是否在跑 + 启动 + source)。
--- ---
@@ -160,32 +165,43 @@ root@docker-desktop:/root/ros2_ws#
source /opt/ros/humble/setup.bash # 加载 ROS2 环境 source /opt/ros/humble/setup.bash # 加载 ROS2 环境
cd /root/ros2_ws # 进入工作空间 cd /root/ros2_ws # 进入工作空间
``` ```
### 4.2 编译所有包 ### 4.2 编译所有包
```bash ```bash
bash scripts/build.sh bash scripts/build.sh
``` ```
*(脚本封装了 `source /opt/ros/humble/setup.bash` + `colcon build --symlink-install` 12 个包;手动等价命令见下)* *(脚本封装了 `source /opt/ros/humble/setup.bash` + `colcon build --symlink-install --executor sequential` 12 个包;手动等价命令见下)*
**手动等价命令**: **手动等价命令**:
```bash ```bash
source /opt/ros/humble/setup.bash source /opt/ros/humble/setup.bash
cd /root/ros2_ws cd /root/ros2_ws
colcon build --symlink-install colcon build --symlink-install --executor sequential \
--packages-select \
py_pubsub cpp_pubsub py_srv py_action_demo \
cpp_robot_tf2 py_vision_demo py_params \
cpp_custom_interface py_lifecycle_composable \
cpp_qos_demo py_overlay_dds bringup
``` ```
> ❗ **`--executor sequential` 必需**。colcon 默认并行构建 12 个包,`cpp_custom_interface` 的 rosidl export cmake 步骤会偶发失败(已知 CMake bug)。串行构建稳定通过。
**预期输出(末尾)**: **预期输出(末尾)**:
``` ```
[INFO] [launch]: Default logging verbosity is set to INFO
Finished <<< py_pubsub [9.5s] Finished <<< py_pubsub [9.5s]
Finished <<< cpp_pubsub [42s] Finished <<< cpp_pubsub [42s]
Finished <<< py_srv [11s] Finished <<< py_srv [11s]
Finished <<< py_action_demo [17s] Finished <<< py_action_demo [17s]
Finished <<< cpp_robot_tf2 [49s] Finished <<< cpp_robot_tf2 [49s]
Finished <<< py_vision_demo [11s] Finished <<< py_vision_demo [11s]
Finished <<< bringup [18s] Finished <<< py_params [12s]
Finished <<< cpp_custom_interface [38s]
Finished <<< py_lifecycle_composable [8s]
Finished <<< cpp_qos_demo [22s]
Finished <<< py_overlay_dds [9s]
Finished <<< bringup [12s]
Summary: 7 packages finished [2min 30s] Summary: 12 packages finished [3min 30s]
``` ```
**编译产物位置**: **编译产物位置**:
@@ -197,18 +213,29 @@ Summary: 7 packages finished [2min 30s]
├── py_action_demo/ ├── py_action_demo/
├── cpp_robot_tf2/ ├── cpp_robot_tf2/
├── py_vision_demo/ ├── py_vision_demo/
├── py_params/
├── cpp_custom_interface/
├── py_lifecycle_composable/
├── cpp_qos_demo/
├── py_overlay_dds/
└── bringup/ └── bringup/
``` ```
### 4.3 跑测试(可选) ### 4.3 跑测试(可选)
```bash ```bash
bash scripts/test.sh bash scripts/test.sh
``` ```
**预期**: **预期**:
``` ```
Summary: 7 packages finished [25s] Summary: 12 packages finished [1min 30s]
0 packages failed 0 packages failed
build/py_pubsub/pytest.xml: 11 tests, 0 errors, 0 failures, 0 skipped
build/cpp_pubsub/test_results/cpp_pubsub/test_pub_sub.gtest.xml: 3 tests, ...
build/py_srv/pytest.xml: 7 tests, ...
...
Summary: 82 tests, 0 errors, 0 failures, 0 skipped
``` ```
--- ---
@@ -426,14 +453,19 @@ sudo apt install ros-humble-<pkg>
### Q8: 容器里中文显示乱码 ### Q8: 容器里中文显示乱码
**原因**: 容器没装中文字体 **原因**: 容器没装中文字体
**解决**: 在容器内 `export LANG=C.UTF-8 LC_ALL=C.UTF-8` **解决**: 在容器内 `export LANG=C.UTF-8 LC_ALL=C.UTF-8`
### Q9: `colcon build` 报 `CMakeCache` 或 `export_cpp_custom_interface__rosidl_generator_cExport` 错误
### Q9: `colcon build` 报 `CMakeCache` 错误 **原因**: 上次 build 残留 CMakeCache,或 `cpp_custom_interface` 的 rosidl export cmake 并行构建偶发失败
**原因**: 之前构建的 CMakeCache 有问题
**解决**: **解决**:
```bash ```bash
cd /root/ros2_ws cd /root/ros2_ws
bash scripts/clean.sh # 等价于 rm -rf build install log bash scripts/clean.sh # 等价于 rm -rf build install log
bash scripts/build.sh bash scripts/build.sh # 脚本已带 --executor sequential
```
如果还挂,加上 `--cmake-clean-cache`:
```bash
colcon build --symlink-install --executor sequential --cmake-clean-cache \
--packages-select <12 个包>
``` ```
### Q10: 容器跑一段时间后磁盘满了 ### Q10: 容器跑一段时间后磁盘满了
+80 -38
View File
@@ -71,12 +71,12 @@ CMD ["bash"]
```powershell ```powershell
# Windows # Windows
docker compose -f D:\xs\ros2\docker\docker-compose.yml build docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml build
``` ```
```bash ```bash
# Linux # Linux
docker compose -f docker/docker-compose.yml build docker compose -p ros2 -f docker/docker-compose.yml build
``` ```
镜像名:`ros2-humble-dev:latest`,约 3GB。 镜像名:`ros2-humble-dev:latest`,约 3GB。
@@ -115,37 +115,55 @@ RUN pip3 install ultralytics==8.0.0 numpy==1.26
[`docker/docker-compose.yml`](../docker/docker-compose.yml): [`docker/docker-compose.yml`](../docker/docker-compose.yml):
```yaml ```yaml
name: ros2 # 独立 compose project(脱离默认 docker 分组)
services: services:
ros2: ros2:
build: . build: .
image: ros2-humble-dev:latest image: ros2-humble-dev:latest
container_name: ros2_dev container_name: ros2_dev
privileged: true # 调试用 privileged: true # 调试用
stdin_open: true # docker exec -it stdin_open: true # docker exec -it
tty: true tty: true
network_mode: host # DDS multicast 必须 networks: # 自定义 bridge(脱离 docker_default)
ros2_net:
ipv4_address: 172.20.0.10 # 固定 IP,便于 ROS_STATIC_PEERS
environment: environment:
- ROS_DOMAIN_ID=0 - ROS_DOMAIN_ID=0
# 不要设 RMW_IMPLEMENTATION=rmw_cyclonedds_cpp: # 不要设 RMW_IMPLEMENTATION=rmw_cyclonedds_cpp:
# 镜像没装 cyclone dds,CMake 配置会失败。 # 镜像没装 cyclone dds,CMake 配置会失败。
- RCUTILS_COLORIZED_OUTPUT=1
volumes: volumes:
- ..:/root/ros2_ws # bind mount 本机 D:\xs\ros2 - ..:/root/ros2_ws # bind mount 本机 D:\xs\ros2
working_dir: /root/ros2_ws working_dir: /root/ros2_ws
command: ["bash", "-lc", "tail -f /dev/null"] # 容器永不退 command: ["bash", "-lc", "tail -f /dev/null"] # 容器永不退
networks:
ros2_net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
gateway: 172.20.0.1
``` ```
### 3.2 为什么 host network ### 3.2 为什么自定义 bridge 而不是 host network
ROS2 默认用 DDS multicast 在同一网段自动发现节点。多容器或跨主机时,**bridge 网络 ROS2 默认用 DDS multicast 在同一网段自动发现节点。
会拦截 multicast**,导致节点看不见彼此。 **默认 docker bridge 网络会拦截 multicast**,导致容器内节点看不见彼此。
`network_mode: host` 让容器用宿主机的网络栈,直接走 multicast。 本仓库选择**自定义 bridge**(`ros2_net`,子网 `172.20.0.0/24`),原因:
- 跟系统 `docker_default` 隔离,不让无关容器"窜"进 ROS 节点组
- 容器固定 IP(`172.20.0.10`),便于 `ROS_STATIC_PEERS` 配置
- bridge 内 multicast 在同一 docker 网络内**能正常通**——本仓库默认 fastdds + 单机场景下,所有节点都在 `ros2_dev` 容器里,bridge 完全够用
如果做**跨主机 ROS2 部署**(PC ↔ RDK X5 ↔ RK3506,见 `100-embedded-deployment.md`),需要 `network_mode: host` 或 host gateway。
### 3.3 为什么 bind mount 整个工程 ### 3.3 为什么 bind mount 整个工程
@@ -158,28 +176,28 @@ ROS2 默认用 DDS multicast 在同一网段自动发现节点。多容器或跨
```powershell ```powershell
# 构建镜像 # 构建镜像
docker compose -f D:\xs\ros2\docker\docker-compose.yml build docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml build
# 启动(后台) # 启动(后台)
docker compose -f D:\xs\ros2\docker\docker-compose.yml up -d docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml up -d
# 状态 # 状态
docker compose -f D:\xs\ros2\docker\docker-compose.yml ps docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml ps
# 进开发终端 # 进开发终端(必须先 source ROS2 + 本项目 install)
docker exec -it ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && exec bash" docker exec -it ros2_dev bash -lc "source /opt/ros/humble/setup.bash && 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 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 -p ros2 -f D:\xs\ros2\docker\docker-compose.yml down
# 重启 # 重启
docker compose -f D:\xs\ros2\docker\docker-compose.yml restart docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml restart
# 删容器(保留镜像) # 删容器(保留镜像)
docker compose -f D:\xs\ros2\docker\docker-compose.yml down docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml down
# 删镜像 # 删镜像
docker rmi ros2-humble-dev:latest docker rmi ros2-humble-dev:latest
@@ -192,30 +210,49 @@ docker logs -f ros2_dev
## 5. 一键启动脚本 ## 5. 一键启动脚本
### 5.1 start.ps1 (Windows) 本仓库的所有"一键"命令都在 `scripts/` 目录下,**没有**项目根的 `start.ps1` /
```powershell `start.sh` / `build.sh`(老文档里残留的引用一律作废,统一指向 `scripts/`)。
powershell D:\xs\ros2\start.ps1
### 5.1 进入开发终端(交互式 shell)
```bash
bash scripts/shell.sh
``` ```
等价于: 等价于:
```powershell - `docker ps` 看容器是否在跑
docker compose build # 首次 5-10min - 如果没跑 → 自动 `docker run -d -it ... ros2-humble-dev:latest bash` 启起来
docker compose up -d - `docker exec -it ros2_dev bash -lc "source /opt/ros/humble/setup.bash && source /root/ros2_ws/install/setup.bash && cd /root/ros2_ws && exec bash"`
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 编译 12 个包(容器内)
```bash
bash scripts/build.sh
```
等价于:
```bash
source /opt/ros/humble/setup.bash
cd /root/ros2_ws
colcon build --symlink-install --executor sequential \
--packages-select <12 个包>
``` ```
### 5.2 start.sh (Linux/macOS) > ❗ **`--executor sequential` 必需**。colcon 默认 parallel,12 个包并行构建
> 时 `cpp_custom_interface` 的 rosidl export cmake 会偶发 CMake 报错。
> 串行构建 100% 稳定。详见 `doc/80-package-build.md`。
### 5.3 跑所有测试
```bash ```bash
./start.sh bash scripts/test.sh
```
等价于 `colcon test --executor sequential --packages-select <12 个包>` + `colcon test-result --all`
### 5.4 跑 launch demo
```bash
bash scripts/launch.sh pubsub_launch 30 # 跑 30 秒自动停
bash scripts/launch.sh full_demo_launch -1 # -1 = 一直跑(后台)
``` ```
### 5.3 build.sh (容器内) ### 5.5 清理构建产物
```bash ```bash
bash build.sh bash scripts/clean.sh # 等价于 rm -rf build install log
# 1) source /opt/ros/humble/setup.bash
# 2) colcon build --symlink-install --packages-select <all>
# 3) ls install/
# 4) 打印运行命令速查
``` ```
--- ---
@@ -337,22 +374,27 @@ services:
## 9. 在本仓库里跑 ## 9. 在本仓库里跑
### 9.1 一键启 ### 9.1 一键启(推荐用 Makefile)
```powershell ```powershell
powershell D:\xs\ros2\start.ps1 make build # 首次构建镜像
make up # 后台启动容器
make shell # 进入开发终端(自动 source ROS2 + install)
make colcon-build # 编译 12 包
make colcon-test # 跑 82 测试
make full-demo # 跑 11 节点 full_demo
``` ```
### 9.2 进入后跑测试 ### 9.2 进入后跑测试
```bash ```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" bash scripts/test.sh # 推荐:自带 --executor sequential
``` ```
### 9.3 跑 demo ### 9.3 跑 demo
```bash ```bash
docker exec ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && ros2 launch bringup full_demo_launch.py" docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && source /root/ros2_ws/install/setup.bash && ros2 launch bringup full_demo_launch.py"
``` ```
--- ---
+37 -19
View File
@@ -287,15 +287,20 @@ TEST_F(MyFixture, SpinSomeWorks) {
| 包 | 测试 | 用例数 | 通过率 | | 包 | 测试 | 用例数 | 通过率 |
|---|---|---|---| |---|---|---|---|
| py_pubsub | pytest + in-process | 4/4 | 100% | | py_pubsub | pytest + in-process | 11/11 | 100% |
| cpp_pubsub | gtest | 2/2 | 100% | | cpp_pubsub | gtest + launch_test | 4/4 | 100% |
| py_srv | pytest + Service | 1/1 | 100% | | py_srv | pytest + Service | 7/7 | 100% |
| py_action_demo | pytest + Action | 1/1 | 100% | | py_action_demo | pytest + Action | 5/5 | 100% |
| cpp_robot_tf2 | gtest + TF2 | 2/2 | 100% | | cpp_robot_tf2 | gtest + TF2 + launch_test | 5/5 | 100% |
| py_vision_demo | pytest + Image | 2/2 | 100% | | py_vision_demo | pytest + Image | 13/13 | 100% |
| bringup | launch 6 文件就绪 | OK | 100% | | py_params | pytest + 参数校验 | 16/16 | 100% |
| cpp_custom_interface | gtest + launch_test | 4/4 | 100% |
| py_lifecycle_composable | pytest + Lifecycle | 6/6 | 100% |
| cpp_qos_demo | gtest + launch_test | 5/5 | 100% |
| py_overlay_dds | pytest + DDS 配置 | 6/6 | 100% |
| bringup | launch 聚合(无单元测试) | 0/0 | n/a |
**合计: 10/10 测试 100% PASSED** **合计: 82/82 测试 100% PASSED**(64 pytest + 14 gtest + 4 launch_test)
--- ---
@@ -378,10 +383,18 @@ jobs:
## 9. 在本仓库里跑 ## 9. 在本仓库里跑
### 9.1 跑全部测试 ### 9.1 跑全部测试(推荐用脚本)
```bash ```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" docker exec ros2_dev bash /root/ros2_ws/scripts/test.sh
# 或在容器内: bash scripts/test.sh
```
> ❗ `scripts/test.sh` 已带 `--executor sequential`,直接跑 12 包 82 用例稳定通过。
**手动等价命令**:
```bash
docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && cd /root/ros2_ws && colcon test --executor sequential --packages-select py_pubsub cpp_pubsub py_srv py_action_demo cpp_robot_tf2 py_vision_demo py_params cpp_custom_interface py_lifecycle_composable cpp_qos_demo py_overlay_dds bringup && colcon test-result --all"
``` ```
### 9.2 单包测试 ### 9.2 单包测试
@@ -400,17 +413,22 @@ cat build/cpp_pubsub/test_results/cpp_pubsub/test_pub_sub.gtest.xml
cat build/py_pubsub/pytest.xml cat build/py_pubsub/pytest.xml
``` ```
### 9.4 当前结果(固化) ### 9.4 当前结果(2026-08-04 实测)
``` ```
cpp_pubsub: 2/2 PASSED ✅ py_pubsub: 11/11 PASSED (pytest)
✅ py_pubsub: 4/4 PASSED cpp_pubsub: 4/4 PASSED (3 gtest + 1 launch_test)
✅ py_srv: 1/1 PASSED ✅ py_srv: 7/7 PASSED (pytest)
✅ py_action_demo: 1/1 PASSED ✅ py_action_demo: 5/5 PASSED (pytest)
✅ cpp_robot_tf2: 2/2 PASSED ✅ cpp_robot_tf2: 5/5 PASSED (4 gtest + 1 launch_test)
✅ py_vision_demo: 2/2 PASSED ✅ py_vision_demo: 13/13 PASSED (pytest)
bringup: OK (no tests) py_params: 16/16 PASSED (pytest)
合计: 10/10 PASSED ✅ cpp_custom_interface: 4/4 PASSED (3 gtest + 1 launch_test)
✅ py_lifecycle_composable: 6/6 PASSED (pytest)
✅ cpp_qos_demo: 5/5 PASSED (4 gtest + 1 launch_test)
✅ py_overlay_dds: 6/6 PASSED (pytest)
✅ bringup: 0/0 (launch 聚合,无单元测试)
合计: 82/82 PASSED (64 pytest + 14 gtest + 4 launch_test)
``` ```
--- ---
+1
View File
@@ -17,6 +17,7 @@ source /opt/ros/humble/setup.bash
cd "${WORKSPACE}" cd "${WORKSPACE}"
colcon build --symlink-install \ colcon build --symlink-install \
--executor sequential \
--packages-select \ --packages-select \
py_pubsub cpp_pubsub py_srv py_action_demo \ py_pubsub cpp_pubsub py_srv py_action_demo \
cpp_robot_tf2 py_vision_demo py_params \ cpp_robot_tf2 py_vision_demo py_params \
+1
View File
@@ -11,6 +11,7 @@ source /opt/ros/humble/setup.bash
cd "${WORKSPACE}" cd "${WORKSPACE}"
colcon test \ colcon test \
--executor sequential \
--packages-select \ --packages-select \
py_pubsub cpp_pubsub py_srv py_action_demo \ py_pubsub cpp_pubsub py_srv py_action_demo \
cpp_robot_tf2 py_vision_demo py_params \ cpp_robot_tf2 py_vision_demo py_params \