Files
ros_contorl/docs/INTERFACES.md
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

166 lines
7.1 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.
# 对外接口
三层:操作员脚本、ROS 话题/服务、可 import 的 Python。业务代码不要直接调 `rizon_arm_controller`。
---
## 1. 操作员脚本(推荐)
所有脚本在 `scripts/`。先 `source scripts/env.sh`。
| 脚本 | 输入 | 输出 / 行为 |
|------|------|-------------|
| `env.sh` | — | conda + Humble + `install/setup.bash` + `SITE_*` |
| `build_all.sh` | 源码 | colcon 编 `arm_*` + `flexiv_*` |
| `run_real.sh [--sn SN]` | `site.yaml` robot | 实机 stack,`backend:=real` |
| `run_camera_d405.sh [--preview]` | `camera.*` | 发布图像;可选 Qt 四宫格 |
| `run_visual_servo_rt.sh [--control]` | `paths` `yolo` `servo` | perception + servo + 手眼 TF |
| `go_home.sh` | `go_home.*` | 杀伺服后 `/set_named_pose` |
| `run_handeye.sh teach\|merge\|calibrate\|show` | `handeye.*` | 示教 / 写入 poses / 解 T |
| `run_gripper.sh --arm 89\|91 --cli …` | `robots[].gripper` + `gripper.*` | PGEA / RGI Modbus |
| `run_dual_gripper.sh` | 两侧 `robots[].gripper` | 双爪 ROS 节点 |
| `run_hole_detect.sh --arm …` | `hole_detect.*` `camera` | 入孔像素 |
| `run_tactile.sh [--cli]` | `tactile.*` | Orisys 左右指 |
| `run_gauge_assembly.sh --arm 89\|91 [--dry-run] [--holes N] [--backend auto\|contract\|legacy]` | `gauge_assembly.*` | **通止规装配主流程**(S00–S11);`--dry-run` 只验编排不动臂。流程见 [GAUGE_ASSEMBLY.md](GAUGE_ASSEMBLY.md) |
| `weights.sh list\|labels\|convert\|doctor\|show` | 权重模块 | 管理权重与标签,见 `models/README.md` |
| `export_yolo_trt.sh [onnx] [imgsz]` | 权重 | **旧命令**,转发壳 → `weights.sh convert --to engine` |
| `show_site_config.sh` | `site.yaml` | 打印解析结果 |
| `rdk_switch_tool.sh --list` | SN | Studio 工具列表 |
| `run_sim.sh` | — | mock stack |
| `convert_traj.sh FILE.traj` | Flexiv 轨迹 | `*_trajectory.yaml` |
环境变量契约由 `scripts/lib/export_site_env.py` 定义:`flatten()`、`perception_overrides()`、`servo_overrides()`、`gripper_overrides()`。
---
## 2. ROS 接口(稳定)
### 机械臂(`run_real.sh`)
| 名称 | 类型 | 方向 | 说明 |
|------|------|------|------|
| `/set_named_pose` | `arm_msgs/srv/SetNamedPose` | 应用 → 控制 | `home` `ready` `inspect` `pos_left` |
| `/get_arm_state` | `arm_msgs/srv/GetArmState` | 查询 | 关节 + EE 位姿 |
| `/arm_status` | `arm_msgs/msg/ArmStatus` | 状态 | 模式 / 是否在动 |
| `/follow_joint_trajectory` | `arm_msgs/action/FollowJointTrajectory` | 应用 → 适配器 | 应用只走这个 |
| `/rizon_arm_controller/joint_trajectory` | `trajectory_msgs/JointTrajectory` | 伺服 → 驱动 | **仅 servo_node 写** |
| `/joint_states` | `sensor_msgs/JointState` | 驱动 → 全局 | |
| `/tf` `/tf_static` | TF | | 基座 / 连杆 / 法兰 / 手眼 |
命名位姿表:`src/arm_control/config/named_poses.yaml`。
```bash
ros2 service call /set_named_pose arm_msgs/srv/SetNamedPose \
"{pose_name: 'home', velocity_scale: 0.25, acceleration_scale: 0.25}"
```
### 相机(`realsense_color_pub`)
| 话题 | 类型 | 说明 |
|------|------|------|
| `/d405/color/image_raw` | `sensor_msgs/Image` bgr8 | 彩图 |
| `/d405/color/camera_info` | `sensor_msgs/CameraInfo` | 内参 |
| `/d405/aligned_depth_to_color/image_raw` | `sensor_msgs/Image` 16UC1 | 对齐深度,毫米 |
`d405` 来自 `camera.name`。QoS:SensorData(BEST_EFFORT)。
### 感知 / 伺服
| 名称 | 类型 | 说明 |
|------|------|------|
| `/visual_servo/filtered_point` | `geometry_msgs/PointStamped` | 相机系工件点,perception → servo |
| `/workpiece/detection` | `std_msgs/Float32MultiArray` | `[x1,y1,x2,y2,conf,cls,cx,cy,z]`,空=清绿框 |
| `/cmd_vel` | `geometry_msgs/Twist` | 伺服调试用,真机动臂走轨迹 |
`PointStamped.header.frame_id` = `d405_color_optical_frame`。
### 夹爪(IPC Modbus,`arm_msgs`)
PGEA 单爪节点(`--arm 89` 无 `--cli`):
| 服务 | 类型 |
|------|------|
| `/gripper/open` | `std_srvs/srv/Trigger` |
| `/gripper/close` | `std_srvs/srv/Trigger` |
双爪 / 右爪 RGI:
| 名称 | 类型 |
|------|------|
| `/dual_gripper_driver/{left,right}/command` | `arm_msgs/msg/GripperCommand` |
| `/dual_gripper_driver/{left,right}/status` | `arm_msgs/msg/GripperStatus` |
| `/dual_gripper_driver/{left,right}/execute` | `arm_msgs/srv/GripperExecute` |
开合力/速在 `site.yaml` → `gripper` 与 `robots[].gripper`。
### 入孔检测(`hole_detect`)
| 话题 | 类型 |
|------|------|
| `/hole_detect/result` | `arm_msgs/msg/HoleDetections` |
| `/hole_detect/holes` | `std_msgs/Float32MultiArray` |
| `/hole_detect/overlay` | `sensor_msgs/Image` |
### 视触觉(`tactile` 节点)
| 话题 | 类型 |
|------|------|
| `/tactile/left/status` | `arm_msgs/msg/TactileStatus` |
| `/tactile/right/status` | `arm_msgs/msg/TactileStatus` |
### 通止规装配(`gauge_assembly` 节点)
| 话题 | 类型 | 方向 | 说明 |
|------|------|------|------|
| `/gauge/state` | `std_msgs/msg/String` | 出 | 每次状态转移一条:`#序号 状态 --事件--> 状态` |
| `/gauge/progress` | `std_msgs/msg/String` | 出 | 进度(第几孔 / 第几轮棘轮) |
| `/gauge/result` | `std_msgs/msg/String` | 出 | 结束结论(成功 / 失败原因) |
| `/gauge/reload_ok` | `std_msgs/msg/Bool` | 入 | **E1 掉件**:把规塞回爪里后发 `true`,流程继续(超时 = 中止) |
E1 人工确认:`ros2 topic pub --once /gauge/reload_ok std_msgs/msg/Bool "{data: true}"`
夹爪走 `/gripper/open` `/gripper/close`,类型按后端自动识别(`arm_msgs/srv/GripperExecute`
或真机驱动的 `std_srvs/srv/Trigger`),见 [GRIPPER.md](GRIPPER.md)。
---
## 3. `site.yaml` 契约
字段说明见 [SITE_CONFIG.md](SITE_CONFIG.md)。Launch 覆盖键:
- 感知:`perception_overrides()` → `weights` `conf` `imgsz` `backend` …
- 伺服:`servo_overrides()` → `ee_z_m` `xy_track` `v_max_xy` `kp_xy` …
改 yaml **不会**热加载权重 / 分辨率 / 锁高(`overlay_hold_sec` 相机会跟)。重启对应脚本。
---
## 4. Python(二次开发)
```python
from arm_application.yolo_detector import YoloDetector, resolve_weights, pick_best
from arm_application.dh_pgea import DhPgeaGripper
from arm_application.dual_gripper import DualArmGripperManager, load_from_site
from arm_application.hole_detector import HoleDetector
from arm_application.orisys_tactile import make_tactile, load_orisys_from_site
from arm_application.geom_ik import load_handeye_T, geometric_jacobian, dls_twist
from arm_application.handeye_lib import calibrate_hand_eye
from arm_application.plane_feature import geometric_center_on_plane
```
模块职责写在 `src/arm_application/arm_application/__init__.py`。
不要从业务节点里 `import flexivrdk`(ABI 在 `rdk_py310`)。夹爪走 Modbus;示教拖拽走 `scripts/rdk_drag_bridge.py` 子进程。
---
## 5. 坐标系
| 帧 | 谁发布 | 含义 |
|----|--------|------|
| `{SN}_base_link` | robot_state_publisher | 基座 |
| `{SN}_flange` | robot_state_publisher | 法兰 |
| `d405_color_optical_frame` | 手眼 static TF | 相机光心,Z 朝外 |
`hover`:基座 XY 上法兰对齐工件。`ee_z_m`:法兰在基座 Z。