Files
ROS2_learn/AGENTS.md
T
2026-08-03 18:09:35 +08:00

207 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ROS2 子项目 Agent 铁律
## 铁律 (Hard Rules)
**违反任何一条,所有变更立刻回滚。**
1. **只允许在本目录 `D:\xs\ros2` 下创建/修改/删除文件。**
- 任何系统临时目录(`%TEMP%``/tmp` 等) 一律禁止落盘。
- 在 Windows 下临时目录会残留垃圾文件且不清理,绝对禁止。
- 创建临时数据用 PowerShell 内存对象或 stdout,不写盘。
2. **禁止用 shell(PowerShell / cmd)编辑文件。**
- 改 / 写 / 读文件一律用内置工具:Read / Edit / Write / Glob / Grep。
- shell(本会话的 `bash` 工具)只允许运行可执行命令,例如 `docker ...``colcon ...`,**不允许用 `Set-Content``Out-File``>``>>` 写文件**。
- 禁止 `cd` / `Set-Location` 切换工作目录;需要别的目录时,在 `bash` 工具里用绝对路径,或者在 GUI / 编辑器里用内置工具定位。
3. **禁止到处创建文件/目录。**
- 不擅自创建 `.cache/``.tmp/``.bak/` 等隐藏目录。
- 不擅自创建 `test/xxx` 临时目录、"out/`、`日志/。
- 所有产出(镜像 `ros2-humble-dev:latest`、容器 `ros2_dev`、构建目录 `install/``build/``log/`)放在本项目内或其默认位置,不放别处。
4. **禁止问与思考循环。**
- 用户拒绝连续"要不要 / 要不要这样"。给出明确方案,直接开干。
- 必须问时,一次问清,不要反问。
5. **测试必须 100% 通过才能停手。**
- `docker compose build` + `colcon build` + `colcon test` + 节点启动 + `ros2 topic echo` 全绿才能汇报"完成"。
- 任何环节失败 → 自动修 → 再跑,直到全过。
## 子项目结构
```
D:\xs\ros2\
├── AGENTS.md # 本文件
├── README.md # 项目入口 + 架构 + 启动命令
├── pyproject.toml # PEP 621 workspace metadata(IDE 入口)
├── requirements.txt # venv runtime 依赖
├── requirements-dev.txt # venv 开发工具(ruff/black/mypy/pytest)
├── .flake8 / pyrightconfig.json # lint / 类型检查配置
├── .gitignore # 包含 .venv/ build/ install/ log/
├── docker/
│ ├── Dockerfile # ROS2 Humble 镜像
│ ├── docker-compose.yml # 容器编排
│ ├── bringup_e2e.log # 4 节点跨语言端到端验证日志(31KB)
│ ├── srv_e2e.log # Service 端到端(12+30=42,664B)
│ ├── robot_e2e.log # URDF + TF 端到端(11KB)
│ ├── vision_e2e.log # sensor_msgs/Image 端到端(49KB)
│ └── full_demo_e2e.log # 11 节点全开端到端(46KB)
├── tools/
│ ├── setup_venv.sh # Linux/WSL/Docker 一键 venv
│ └── setup_venv.ps1 # Windows 一键 venv(不污染系统 Python)
├── build.sh # 容器内 colcon build 一键脚本
├── start.sh / start.ps1 # 一键启动 + 构建 + 进开发终端
├── src/
│ ├── py_pubsub/ # ament_python — Topic pub/sub (Python)
│ │ ├── package.xml
│ │ ├── setup.py / setup.cfg
│ │ ├── py_pubsub/publisher_member_function.py
│ │ ├── py_pubsub/subscriber_member_function.py
│ │ ├── launch/pubsub_launch.py
│ │ ├── resource/py_pubsub
│ │ └── test/test_pubsub_launch.py # 4 pytest 用例
│ ├── cpp_pubsub/ # ament_cmake — Topic pub/sub (C++) + gtest
│ │ ├── package.xml
│ │ ├── CMakeLists.txt
│ │ ├── src/publisher_member_function.cpp
│ │ ├── src/subscriber_member_function.cpp
│ │ ├── launch/pubsub_launch.py
│ │ └── test/test_pub_sub.cpp # 2 gtest 用例
│ ├── py_srv/ # ament_python — Service demo
│ │ ├── package.xml
│ │ ├── setup.py / setup.cfg
│ │ ├── py_srv/add_two_ints_server.py
│ │ ├── py_srv/add_two_ints_client.py
│ │ ├── launch/srv_launch.py
│ │ └── test/test_srv.py # 1 pytest 用例
│ ├── py_action_demo/ # ament_python — Action 三件套 demo
│ │ ├── package.xml
│ │ ├── setup.py / setup.cfg
│ │ ├── py_action_demo/fibonacci_server.py
│ │ ├── py_action_demo/fibonacci_client.py
│ │ ├── launch/action_launch.py
│ │ └── test/test_action.py # 1 pytest 用例
│ ├── cpp_robot_tf2/ # ament_cmake — URDF + TF2 + JointState (C++)
│ │ ├── package.xml
│ │ ├── CMakeLists.txt
│ │ ├── urdf/simple_arm.urdf # 3 关节机械臂
│ │ ├── src/joint_state_publisher.cpp
│ │ ├── src/tf2_listener.cpp
│ │ ├── launch/robot_tf2_launch.py
│ │ └── test/test_tf2_lookup.cpp # 2 gtest 用例
│ ├── py_vision_demo/ # ament_python — sensor_msgs/Image (Python)
│ │ ├── package.xml
│ │ ├── setup.py / setup.cfg
│ │ ├── py_vision_demo/fake_camera.py
│ │ ├── py_vision_demo/image_processor.py
│ │ ├── launch/vision_launch.py
│ │ └── test/test_vision.py # 2 pytest 用例
│ └── bringup/ # ament_python — 顶层 launch 聚合
│ ├── package.xml
│ ├── setup.py / setup.cfg
│ ├── launch/
│ │ ├── pubsub_launch.py # 4 节点 Topic(pubsub)
│ │ ├── service_launch.py # AddTwoInts server
│ │ ├── action_launch.py # Fibonacci server
│ │ ├── robot_launch.py # URDF TF2(嵌套 cpp_robot_tf2)
│ │ ├── vision_launch.py # 嵌套 py_vision_demo
│ │ └── full_demo_launch.py # 11 节点一起
│ └── resource/bringup
└── doc/ # 14 篇深度文档
├── 00-overview.md # 架构 + 设计取舍
├── 01-quickstart.md # 5 分钟上手
├── 02-virtualenv.md # venv 工作流(本机不污染)
├── 10-concepts.md # Node/Topic/Service/Action/Parameter/TF
├── 20-topics.md # Topic pub/sub 深度
├── 30-services.md # Service 深度
├── 40-actions.md # Action 三件套深度
├── 50-tf2.md # TF2 坐标变换
├── 60-urdf.md # URDF 机器人模型
├── 70-launch.md # launch 文件系统
├── 80-package-build.md # colcon / ament 包构建
├── 85-docker.md # Docker 容器化开发
├── 90-testing.md # 测试金字塔策略
├── 99-embodied-ai.md # VLA / 机器人 / 具身智能路径
└── 100-embedded-deployment.md # 三机嵌入式部署(PC + RDK X5 + RK3506)
```
## 子项目工作流
| 步骤 | 命令 |
|---|---|
| 构建镜像(首次 5-10min) | `docker compose -f docker/docker-compose.yml build` |
| 启动容器 | `docker compose -f docker/docker-compose.yml up -d` |
| 容器内构建所有 7 个包 | `docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && cd /root/ros2_ws && colcon build --symlink-install --packages-select py_pubsub cpp_pubsub py_srv py_action_demo cpp_robot_tf2 py_vision_demo bringup"` |
| 跑所有单元/集成测试 | `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"` |
| 启动 4 节点 Topic | `docker exec ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && ros2 launch bringup pubsub_launch.py"` |
| 启动 Service 端到端 | `docker exec ros2_dev bash -lc "source install/setup.bash && ros2 launch bringup service_launch.py"` + `ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts '{a: 12, b: 30}'` |
| 启动 Action 端到端 | `ros2 launch bringup action_launch.py` + `ros2 action send_goal /fibonacci example_interfaces/action/Fibonacci '{order: 6}' --feedback` |
| 启动 TF2 演示 | `ros2 launch bringup robot_launch.py` |
| 启动 Vision 演示 | `ros2 launch bringup vision_launch.py` |
| 启动 11 节点 Full demo | `ros2 launch bringup full_demo_launch.py` |
| 进入开发终端 | `docker exec -it ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && exec bash"` |
| 本机 venv 初始化(不污染系统 Python) | `powershell .\tools\setup_venv.ps1` |
| 本机 venv 激活 | `.\.venv\Scripts\Activate.ps1` |
## 测试覆盖 (100% 通过)
| 包 | 测试类型 | 用例数 | 结果 |
|---|---|---|---|
| py_pubsub | pytest + in-process spin | 4/4 | PASSED |
| cpp_pubsub | gtest | 2/2 | PASSED |
| py_srv | pytest + Service in-process | 1/1 | PASSED |
| py_action_demo | pytest + Action in-process | 1/1 | PASSED |
| cpp_robot_tf2 | gtest | 2/2 | PASSED |
| py_vision_demo | pytest + Image in-process | 2/2 | PASSED |
| bringup | launch 6 文件就绪 | OK | PASSED |
**总计: 10/10 单元/集成测试 + 5 个端到端 demo 全部通过 100%。**
### 端到端日志(固化在 `docker/`)
- `bringup_e2e.log`:4 节点 Topic 跨语言互通(listener_cpp 同时收到 PY + CPP 消息)
- `srv_e2e.log`:Service 12+30=42
- `robot_e2e.log`:3 关节机械臂 + TF 实时打印(gripper 在 base_link 下位置)
- `vision_e2e.log`:fake_camera → image_processor 图像流(cv_bridge 解码 + 平均亮度)
- `full_demo_e2e.log`:11 节点同时运行(Topic + Service + Action + Robot + Vision)
## 子项目约定
### Python 包用 `ament_python`(`py_pubsub` / `py_srv` / `py_action_demo` / `py_vision_demo` / `bringup`)。
### C++ 包用 `ament_cmake`(`cpp_pubsub` / `cpp_robot_tf2`)。
### 跨包 launch 收纳到 `bringup` 包,包名**不能**叫 `launch`(与 ROS2 自带包同名,ament 索引冲突)。
### 所有 ROS2 节点默认参数 `period_ms=500`、`topic=chatter`,可在 launch 文件里覆盖。
### 源码注释一律中文,顶部 docstring 先写"用途 / 关键概念 / 运行方式",关键 API 旁写 inline。
### 跨语言互通演示:talker_py / talker_cpp 都用 `std_msgs/String`,见 `ros2 topic info chatter -v`。
## 嵌入式部署硬件清单(典型)
| 设备 | 角色 | ROS2 适配 |
|---|---|---|
| PC (x86) | 主控 | ✅ 完整 ROS2 + MoveIt2 + Nav2 + RViz |
| RDK X5 (ARM + 5 TOPS NPU) | 边缘 AI | ✅ 完整 ROS2 (视觉 / 语音 / SLAM) |
| RK3506 × 2 (ARM 3核 + 512MB RAM + 8GB eMMC) | 实时控制 | ✅ **精简 ROS2** (`ros-humble-ros-base`,不要 desktop) |
**关键提示**:
- RK3506 是 Linux 应用处理器(不是 MCU),**直接 apt 装 `ros-humble-ros-base`**,不用 micro-ROS
- 三机同 LAN 同 `ROS_DOMAIN_ID`,通过 FastDDS multicast 自动发现(或 `ROS_STATIC_PEERS` 单播)
- RK3506 用精简包 + 关 daemon + 关 GUI,可省 ~300MB RAM
- 详细步骤 + 故障排查见 `doc/100-embedded-deployment.md`
## RMW / 网络注意事项
- Docker Desktop on Windows + host network 模式下,默认 `rmw_fastrtps_cpp` 工作良好。
- **不要在 docker-compose.yml 里设 `RMW_IMPLEMENTATION=rmw_cyclonedds_cpp`**:镜像没装 cyclone dds,
CMake 配置阶段会失败。切换 RMW 时务必 `rm -rf build/ install/ log/` 再 build。
- `ros2 launch``IncludeLaunchDescription` 时,被包含的子 launch 文件必须在被包含包的 `share/<pkg>/launch/` 下被 colcon 实际安装 — 检查 `data_files``glob('launch/*.py')` 是否覆盖到。
## 调试速查
| 症状 | 排查 |
|---|---|
| `rcl_xxx not found` | `source /opt/ros/humble/setup.bash` |
| `Command ['cat', path]` 空格丢了 | launch 里别用 cat,改用 `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 飘红 | 正常,rclpy 没 Windows wheels,在容器里跑 |