# ROS2 子项目 Agent 铁律 + 工作流 ## 铁律 (Hard Rules) **违反任何一条,所有变更立刻回滚。** 1. **只允许在本目录 `D:\xs\ros2` 下创建/修改/删除文件。** 2. **禁止用 shell(PowerShell / cmd)编辑文件**。改/写/读文件一律用内置工具:Read / Edit / Write / Glob / Grep。 - shell 只允许运行可执行命令,例如 `docker ...`、`colcon ...` - **不允许**用 `Set-Content`、`Out-File`、`>`、`>>` 写文件 3. **禁止到处创建文件/目录**。所有产出放在本项目内或其默认位置。 4. **禁止问与思考循环**。给出明确方案,直接开干。 5. **测试必须 100% 通过才能停手**。 - `make colcon-build` + `make colcon-test` 全绿才能汇报"完成" - 当前实测:**12 包 / 82 用例(64 pytest + 14 gtest + 4 launch_test) 100% 通过** 6. **调试日志/临时输出统一放 `.logs/` 目录**。禁止在项目根目录散放 `*.log`、`*.xml` 等临时文件。 - `.logs/` 已加入 `.gitignore`,不会进版本控制 - 用法: `docker exec ... > .logs/build.log 2>&1` ## 编程规范(必读) **严格遵循 [`doc/CODING_STYLE.md`](doc/CODING_STYLE.md)**。 核心要点: - **Python**: type hints + Google docstring + 节点属性后缀 `_` + 私有方法前缀 `_` - **C++**: 命名空间 + const-correct + override + 智能指针 - **测试**: conftest.py + session-scope fixture + pytest/gtest - **包内必须有 README.md**(功能 + 关键概念 + 运行 + 测试 + 深度学习链接) - **提交不修改 git config**: 用 `git -c user.name=x -c user.email=y commit` 临时设 ## 项目结构(12 包 + 完全体) ``` D:\xs\ros2\ ├── AGENTS.md # 本文件(铁律 + 工作流) ├── README.md # 项目入口 + 架构 + 启动 ├── LICENSE # MIT ├── CHANGELOG.md # 变更日志 ├── CONTRIBUTING.md # 贡献指南 ├── pyproject.toml # PEP 621 workspace 元数据 ├── requirements*.txt # venv 依赖 ├── Makefile # 命令聚合(Linux/macOS) ├── .gitlab-ci.yml # GitLab CI 配置 │ ├── docker/ │ ├── Dockerfile │ ├── docker-compose.yml # name: ros2 + ros2_net 自定义网络 │ └── *_e2e.log # 端到端验证日志 │ ├── doc/ # 24 篇深度文档 │ ├── 00-overview.md / 00-levels.md │ ├── 01-quickstart.md / 02-virtualenv.md │ ├── 10-concepts.md / 20-topics.md / 30-services.md / 40-actions.md │ ├── 50-tf2.md / 60-urdf.md │ ├── 70-launch.md / 80-package-build.md / 85-docker.md │ ├── 90-testing.md / 99-embodied-ai.md / 100-embedded-deployment.md │ ├── CODING_STYLE.md # ⭐ 编程规范 │ ├── 15-params.md # ⭐ 参数系统深度 │ ├── 16-custom-interfaces.md ⭐ │ ├── 17-lifecycle.md # ⭐ │ ├── 18-composable.md # ⭐ │ ├── 19-qos.md # ⭐ │ ├── 20-bag.md # ⭐ │ └── 21-overlay-dds.md # ⭐ │ ├── tools/ # 本机开发工具 │ └── src/ # 12 个 ROS2 包 ├── py_pubsub/ # Topic (Python) ├── cpp_pubsub/ # Topic (C++) ├── py_srv/ # Service (Python) ├── py_action_demo/ # Action 三件套 (Python) ├── cpp_robot_tf2/ # URDF + TF2 (C++) ├── py_vision_demo/ # Image + cv_bridge (Python) ├── py_params/ # ⭐ 参数系统 (Python) ├── cpp_custom_interface/ # ⭐ 自定义 msg/srv/action (C++) ├── py_lifecycle_composable/ # ⭐ Lifecycle + Composable (Python) ├── cpp_qos_demo/ # ⭐ QoS 9 种组合 (C++) ├── py_overlay_dds/ # ⭐ DDS 配置 + colcon overlay (Python) ├── bringup/ # 跨包 launch 聚合 (Python) ├── gazebo_sim/ # ⚪ L2 占位(空目录,待 Gazebo 仿真包创建) ├── moveit2_demo/ # ⚪ L2 占位(空目录,待 MoveIt2 演示包创建) ├── nav2_demo/ # ⚪ L2 占位(空目录,待 Nav2 导航演示包创建) └── ros2_control_demo/ # ⚪ L2 占位(空目录,待 ros2_control 演示包创建) ``` ## 工作流命令(make / 直接 docker compose) | 步骤 | 命令 | |---|---| | 构建镜像 | `make build` 或 `docker compose -p ros2 -f docker/docker-compose.yml build` | | 启动容器 | `make up` 或 `docker compose -p ros2 -f docker/docker-compose.yml up -d` | | 容器内 build 12 包 | `make colcon-build` | | 跑所有测试 | `make colcon-test` | | 单包测试 | `make colcon-test-one PKG=py_pubsub` | | 启动 full_demo(11 节点) | `make full-demo` | | 启动单 demo | `make launch NAME=pubsub_launch` | | 进入开发终端 | `make shell` | | 查看日志 | `make logs` | | 本机 venv 初始化 | `make venv-setup`(或 `powershell .\tools\setup_venv.ps1`) | ## 测试覆盖(12 包 / 82 用例 / 100% 目标) | 包 | 类型 | 测试 | |---|---|---| | py_pubsub | pytest | 11/11 | | cpp_pubsub | gtest + launch_test | 4/4 | | py_srv | pytest | 7/7 | | py_action_demo | pytest | 5/5 | | cpp_robot_tf2 | gtest + launch_test | 5/5 | | py_vision_demo | pytest | 13/13 | | py_params | pytest | 16/16 | | cpp_custom_interface | gtest + launch_test | 4/4 | | py_lifecycle_composable | pytest | 6/6 | | cpp_qos_demo | gtest + launch_test | 5/5 | | py_overlay_dds | pytest | 6/6 | | bringup | pytest(0) | 0/0 | | **总计** | | **82/82** | ## 子项目约定 ### Python 包用 `ament_python`,C++ 包用 `ament_cmake` ### 跨包 launch 收纳到 `bringup` 包,**包名不能叫 `launch`** ### 默认参数 `publish_rate_hz=1.0`、`topic=chatter`、`queue_size=10` ### 节点命名 ``(`chatter_publisher`,`joint_state_publisher`) ### 跨语言互通:talker_py / talker_cpp 都用 `std_msgs/String` ## 嵌入式部署硬件清单 | 设备 | 角色 | ROS2 适配 | |---|---|---| | PC (x86) | 主控 | ✅ 完整 ROS2 + MoveIt2 + Nav2 + RViz | | RDK X5 (ARM + 5 TOPS NPU) | 边缘 AI | ✅ 完整 ROS2 (视觉 / 语音 / SLAM) | | RK3506 × 2 (ARM 3核 + 512MB) | 实时控制 | ✅ 精简 ROS2 (`ros-humble-ros-base`) | **关键**: RK3506 是 Linux 应用处理器,**直接 apt 装 `ros-humble-ros-base`**,不用 micro-ROS。 三机同 LAN 同 `ROS_DOMAIN_ID`,通过 FastDDS multicast 自动发现。 ## RMW / 网络注意事项 - Docker 默认用 **`rmw_fastrtps_cpp`**(不要在 compose 里设 Cyclone,镜像没装) - 切换 RMW 时务必 `rm -rf build/ install/ log/` 再 build - `ros2 launch` 的 `IncludeLaunchDescription` 复用其他包 launch 时,**被包含的 launch 必须被 colcon 实际安装** — 检查 `data_files` 里 `glob('launch/*.py')` 是否覆盖 - 本仓库用自定义网络 `ros2_net`(172.20.0.0/24,脱离 docker_default) ## 调试速查 | 症状 | 排查 | |---|---| | `rcl_xxx not found` | `source /opt/ros/humble/setup.bash` | | `Command ['cat', path]` 空格丢了 | launch 里改 `open().read()` | | `rcl_shutdown already called` | 测试 fixture 别在 callback 里 shutdown | | `frame not exist` | robot_state_publisher 还没算完,等 1-2s | | `Cannot connect to Docker daemon` | 启动 Docker Desktop | | Windows venv import rclpy 飘红 | 正常,容器内跑 | ## Git 提交 - **不修改全局 git config**,用 `git -c user.name=x -c user.email=y commit` 临时设 - 分支命名: `feat/` / `fix/` / `docs/` - commit message 格式: `(): ` + body + footer - 不主动 commit / push,除非用户明确要求