Files
arm_dev bda2fa7129 通止规装配:配置段进 site.yaml + 中文手册 + 成败判定「不看 $?」
配置(site.yaml → gauge_assembly:,38 键全部带中文注释)
------------------------------------------------------
- 键名/单位/类型/交叉矛盾由 gauge_config.py 校验:拼错键名报错并给最相近的候选,
  单位后缀(_deg/_mm/_m/_s/_pct/_delta)逐条对表,`contact_safe_delta ≤
  contact_tangential_delta` 这类矛盾启动就拦(R1.2:没接线的键不许静默存在)。
- 借机清掉 4 个**没接线**的键(require_preview / track_*_s / hover_m:前两个是
  stage1 那层的、后两个是 servo 那层的,放在这里等于第二份真相),
  并把 contact_speed_m_s / coarse_timeout_s / 夹爪力速 真的接上。
- site.example.yaml 由 site.yaml 生成(gen_site_example.py --check 通过)。

成败判定:`ros2 launch` 的退出码**恒为 0**
------------------------------------------
实测(Humble):子进程 exit 3,`ros2 launch` 仍返回 0。用 `$?` 判成败的脚本会把
"装配失败"记成"成功"——没人会去查一个说成功的脚本。改成:

- 节点把结论**落盘**(--result-file,默认 /tmp/gauge_assembly_result.json,原子写、
  先落盘再发话题),任何"没跑到收尾"的退出也会补一份 ok=false;
- 脚本读结论文件判成败:0=成功、1=失败、**文件不存在也算失败**并说清;
- 新增 test_gauge_result_gate.py:把脚本里那段判成败的 Python 抽出来,
  对成功/失败/干跑/缺文件/坏 JSON 五种输入断言退出码 —— 判据本身也有测试。

顺带修掉两个"看着像玄学"的现象
------------------------------
- **流程打完了终端不回提示符**:launch 里的静态 TF 发布者是常驻的,主节点退出
  带不走它 —— 挂 OnProcessExit → Shutdown。
- **"已装 1/2 孔"**:结果里 hole_index 是 0 基当前孔号,不是"装完几个",
  新增 holes_done 给人和脚本看。

文档(全部中文,含"怎么调参/还没做")
------------------------------------
- 新增 docs/GAUGE_ASSEMBLY.md:状态机全图、每步判据表、E1 掉件处理(**按实现**:
  掉件后该孔作废、换下一个孔;最后一个孔掉件则序号被夹住=重试本孔)、
  话题契约、调参顺序、验收命令、踩过的坑。
- FRAMEWORK_RULES 新增 R5.8(同一份数学只许一份 + 守卫测试)、R5.9(自检的
  期望类型与调用处同源)、R5.10(缺依赖 skip,别留常年红)、R6.9(硬退出前打
  traceback)、R6.10(ros2 launch 退出码恒 0)+ R5.7 补真机/仿真"生效方式不同"
  (真机软链即改即生效,仿真拷贝必须重编)+ 5 条症状反例、.cursor/rules 同步。
- WORKSPACE / INTERFACES / SITE_CONFIG / HANDBOOK / 两份 README 索引与决策表补齐。

验证(本机真跑)
----------------
  pytest(仿真环境)  436 passed, 14 skipped(缺 onnx 跳过)
  干跑 --sim --dry-run  → 脚本退出码 0,结论 ok=true  已装 2/2 孔
  不干跑 --sim          → 脚本退出码 1,S00 拦住,未发任何运动指令

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 10:30:11 +08:00

83 lines
4.2 KiB
Markdown
Raw Permalink 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.
# site.yaml
路径:`~/ros2/config/site.yaml`(从 `config/site.example.yaml` 复制,**不进 git**)。
目录总表:[WORKSPACE.md](WORKSPACE.md)。查看解析:`bash ~/ros2/scripts/show_site_config.sh`
改完后重启对应进程才会进节点(夹爪 CLI 每次重读)。
## 三台相机
| 相机 | 序列号 | 位置 | 脚本 |
|------|--------|------|------|
| 左腕 D405 | `352122274408` | 89 平行夹爪 | `run_camera_d405.sh --arm 89` |
| 右腕 D405 | `260522274442` | 91 旋转夹爪(新,易过曝) | `run_camera_d405.sh --arm 91` |
| 中间 D435 | `262522073161` | 双臂之间手外 | `run_camera_d435.sh --preview` |
列出:`bash ~/ros2/scripts/list_realsense.sh`
右腕过曝:`robots[]` 里 `ae_limit_us: 1500` 且关投射器。仍亮则把该臂 `auto_exposure: false` 并设 `exposure_us: 800`。
## 双臂(89 / 91)
89 和 91 **各有一份** 手眼、腕部相机序列号、夹爪串口、named poses。
`robot.robots[]` 里写该臂覆盖项;`run_*.sh --arm 89|91` 会合并进去。
| 臂 | SN | IP | 手眼 | 夹爪 |
|----|----|----|------|------|
| 左 89 | Rizon4-063989 | 192.168.2.101 | `handeye/results/89_eye_in_hand.yaml` | PGEA `/dev/ttyUSB0` |
| 右 91 | Rizon4-063991 | 192.168.2.100 | `handeye/results/91_eye_in_hand.yaml` | RGI `/dev/ttyUSB1` |
```bash
bash ~/ros2/scripts/run_real.sh --arm 89
bash ~/ros2/scripts/run_camera_d405.sh --arm 89 --preview
bash ~/ros2/scripts/run_visual_servo_rt.sh --arm 89 --control
bash ~/ros2/scripts/run_handeye.sh --arm 91 teach # 91 必须单独标定
```
每个终端都要带同一 `--arm`,或改 `robot.sn`。不要把 89 的 `T_4x4` 拷到 91。
棋盘尺寸仍是全局 `handeye.board_*`(两臂共用同一块板)。
## 谁读哪些段
| 段 | 读者 |
|----|------|
| `robot` `network` | `run_real.sh`、RDK 工具切换 |
| `camera` | `run_camera_d405.sh`;`overlay_hold_sec` 运行中会跟文件 |
| `paths` `yolo` `servo` | `visual_servo.launch.py` |
| `handeye` `paths.handeye_*` | `run_handeye.sh` |
| `gripper` | `run_gripper.sh` / `dh_pgea` / `dual_gripper` |
| `hole_detect` | `run_hole_detect.sh`(算法参数也在这一段) |
| `tactile` | `run_tactile.sh` |
| `go_home` | `go_home.sh` |
| `gauge_assembly` | `run_gauge_assembly.sh`(通止规装配 S00–S11;`gauge_config.py` 校验键名/单位) |
## 常改项
| 键 | 含义 |
|----|------|
| `robot.sn` / `--arm` | 当前臂。可被 `run_real.sh --arm 91` 覆盖 |
| `robot.robots[].camera.serial` | 该臂腕部 D405。91 必须单独填写 |
| `robot.robots[].paths.handeye_file` | 该臂手眼结果(`handeye/results/<臂号>_<模式>.yaml`),禁止混用 |
| `paths.yolo_weights` | 写 `.onnx` 或 `.pt`;`backend: tensorrt` 时须有同名 `.engine`(见 `models/README.md`) |
| `yolo.imgsz` | 必须等于模型输入边长 |
| `yolo.backend` | `tensorrt` / `onnx` / `auto` |
| `camera.serial` `width` `height` `fps` | D405 流。改分辨率要重启相机 |
| `servo.ee_z_m` | 法兰锁高 [m];**写在 `robots[].servo`,89/91 分开** |
| `servo.xy_track` | `hover`(法兰/爪心正对工件)或 `lookat` |
| `camera.name` | `d405_left` / `d405_right`,话题与预览按臂分开 |
| `servo.v_max_xy` `kp_xy` `a_max` | 跟踪快慢 |
| `gripper.force_pct` `open_position` `close_position` | 左臂 PGEA 力与开度 |
| `robots[].gripper.port` `model` | 该臂串口与型号(91 为 RGI) |
| `hole_detect.backend` `hough_*` `conf` | 入孔检测 |
| `tactile.left_video` `right_video` `config` | Orisys 左右指设备与 dd03 |
| `gauge_assembly.extreme_angle_deg` `_direction` | S01 预绕多少度、往哪边转(逆时针=+1) |
| `gauge_assembly.contact_*_delta` `screw_*_delta` | 通止规装配的**力判据**(任意单位增量),必须现场标定,见 [TACTILE.md](TACTILE.md) |
| `gauge_assembly.holes_total` `reload_timeout_s` | 这次任务的孔数、掉件后等人工确认的时限 |
路径写成**绝对路径**。换机器改 `USER` 和 SN,不要改 Python。
`gauge_assembly:` 段**每个键都有中文注释与取值建议**,直接读
`config/site.yaml` 那一段即可;流程与判据见 [GAUGE_ASSEMBLY.md](GAUGE_ASSEMBLY.md)。
键名拼错会**直接报错并给出最相近的候选名**,不会静默退回默认值(R1.2)。