把当前控制栈收成一份可克隆的源码:腕部看不见时用顶视一次定到基座,二阶段对孔和手外标定跟着进同一份树。

现场 site.yaml、权重和编译产物仍不入库;模板只留占位符。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
arm_dev
2026-10-09 14:51:03 +08:00
parent 16d2912a9a
commit 7d22f777c8
67 changed files with 8597 additions and 409 deletions
+35 -33
View File
@@ -16,7 +16,7 @@
| 模式 | 相机装在哪 | 解出的 X 是什么 | 本项目的用法 |
|------|-----------|----------------|-------------|
| `eye_in_hand` | **相机装在机械臂末端(法兰/手腕)上** | 相机 → 法兰 | **D405 腕部相机(当前使用)** |
| `eye_to_hand` | **相机固定在旁边不动** | 相机 → 机械臂基座 | D435 顶置相机(预留) |
| `eye_to_hand` | **相机固定在旁边不动** | 相机 → 机械臂基座 | D435 顶置相机 |
**怎么选**:看相机是不是跟着机械臂动。
- 跟着动 → `eye_in_hand`
@@ -50,40 +50,36 @@ handeye/
`handeye_workdir`。两条臂若共用一个工作目录,先标定的那份采点会被后
标定的覆盖,而症状是"标定结果突然变得很差",不容易联想到是目录冲突。
**命名约定**:`<臂号>_<模式>.yaml`
- 臂号 = Flexiv 序列号后两位(`Rizon4-063989` → `89`,`Rizon4-063991` → `91`)
- 模式 = `eye_in_hand` | `eye_to_hand`
运行时谁读结果:`config/site.yaml` 里 `robots[89].paths.handeye_file` 指向
`handeye/results/89_eye_in_hand.yaml`,再由各 launch 文件发布成静态 TF。
**换模式 = 把 site.yaml 里那个路径改成 `_eye_to_hand` 那份**,不需要改代码。
**命名约定**:
- 眼在手上:`<臂号>_eye_in_hand.yaml`(`paths.handeye_file` 指向它)
- 眼在手外:`<臂号>_<相机>_eye_to_hand.yaml`(S03 按这个名字自己找,
不要改 `paths.handeye_file`)
- 臂号 = Flexiv 序列号后两位(`Rizon4-063989` → `89`)
- 示教点:`<臂号>_<模式>.yaml`(两种模式的关节角完全不同,分开存)
---
## 3. 标定板(最容易出错的地方)
当前使用的板:
两种装法用**两块不同的物理板**,尺寸按模式分开写,不能共用一组键:
```
内角点 8 列 × 11 行 (注意是"内角点",不是方格数!)
方格边长 15 mm (0.015 m)
```
| 模式 | 物理板 | 内角点(列 × 行) | 方格边长 | `site.yaml` 里的位置 |
|------|--------|-------------------|----------|----------------------|
| `eye_in_hand` | A5(腕部相机看台面) | 8 × 11 | 15 mm (`0.015`) | `handeye.boards.eye_in_hand` |
| `eye_to_hand` | A4(板装在法兰上) | 11 × 8 | 20 mm (`0.020`) | `handeye.boards.eye_to_hand` |
**这个尺寸必须三处一致**,否则标定结果会系统性偏错:
| 位置 | 内容 |
|------|------|
| `config/site.yaml` → `handeye.board_cols/rows/square_size_m` | 8 / 11 / 0.015 |
| `handeye/calibrate.yaml` | `board_cols/rows/square_size_m` |
| `src/.../handeye_calibrate.py` 的参数默认值 | 代码兜底 |
> ⚠️ **历史上这里出过问题**:曾经三处分别写着 `9×6/0.025`、`11×16/0.011`、
> `8×11/0.015`,谁生效取决于覆盖顺序。症状是"标定流程跑得很顺、不报错,
> 但结果明显不对",非常难查。现已统一为 `8×11/0.015`。
> **换板子时,请把上面三处一起改。**
权威只有 `config/site.yaml` 的 `handeye.boards.<模式>`。`run_handeye.sh` 按
`--mode` 取对应那一组,用 `-p` 传给节点。`handeye/calibrate.yaml` 和节点默认值
只是兜底(眼在手上那块板),**没配过的模式会被脚本当场拦下**,不会静默用兜底
尺寸去标(那会让结果系统性偏,还不报错)。
怎么看内角点:把棋盘当成一张网格,**数内部的黑白交叉点**,
是「方格数 − 1」。比如 A5 板上画了 9×12 个格子 → 内角点是 8×11。
是「方格数 − 1」。A5 板上画了 9×12 个格子 → 内角点 8×11;
A4 板上画了 12×9 个格子 → 内角点 11×8。列/行顺序不用纠结,检测端两种顺序都会试。
> ⚠️ **历史上这里出过问题**:曾经三处分别写着 `9×6/0.025`、`11×16/0.011`、
> `8×11/0.015`,谁生效取决于覆盖顺序。后来又把两块板合成一组键,于是标眼在手外
> 时静默用了 A5 的 15 mm。症状都是"标定流程跑得很顺、不报错,但结果明显不对"。
---
@@ -97,7 +93,8 @@ handeye/
bash ~/ros2/scripts/run_handeye.sh teach --arm 89
```
会弹出实时预览窗口,里面能看到标定板有没有被识别到。操作:
会弹出实时预览窗口(**只显示画面,不做棋盘检测**——真正的角点稳定判定在
`calibrate` 那一步)。操作:
| 按键 | 作用 |
|------|------|
@@ -190,20 +187,25 @@ bash ~/ros2/scripts/run_handeye.sh teach --ros --auto-solve --arm 89
### 切换 eye-in-hand / eye-to-hand
```bash
# 用腕部相机(默认)
# 用腕部相机 + A5 板(默认,板放台面不动)
bash ~/ros2/scripts/run_handeye.sh --arm 89 teach
# 用固定相机
bash ~/ros2/scripts/run_handeye.sh --arm 89 teach --mode eye_to_hand
# 用固定相机 + A4 板(板必须装到法兰上,相机不动)
# 前置:另开终端 bash ~/ros2/scripts/run_camera_d435.sh --preview
bash ~/ros2/scripts/run_handeye.sh --arm 89 teach --mode eye_to_hand --points 12
bash ~/ros2/scripts/run_handeye.sh --arm 89 merge --mode eye_to_hand
bash ~/ros2/scripts/run_handeye.sh --arm 89 calibrate --mode eye_to_hand
```
`--mode` 会把读写的文件切到 `<臂号>_<模式>.yaml`,所以:
`--mode` 会同时切:标定板、相机、示教点文件、结果文件。所以:
- 两种模式**互不覆盖**,可以分别标定、共存
- 跑完想切换使用,改 `config/site.yaml` 里 `robots[89].paths.handeye_file`
指向对应那份即可,代码不用动
- 眼在手上结果:`handeye/results/<臂号>_eye_in_hand.yaml`(`T` = 相机 → 法兰)
- 眼在手外结果:`handeye/results/<臂号>_<相机>_eye_to_hand.yaml`
(`T` = 相机 → 这条臂的基座;双臂共用一台 D435 时必须按臂分开)
- **不要**把 `paths.handeye_file` 改成眼在手外那份 —— 那条路径是腕部相机
(S05 精拍定位)用的。手外那份由 `gauge_assembly.launch` 按名字自己找,
并以 **基座 ← 相机** 发布 TF(不是法兰 ← 相机)
传了非法模式会立刻报错并退出(不会悄悄退回默认值 —— 那会导致"以为标的是
eye-to-hand、其实算的是 eye-in-hand"这种最难查的错)。
+4 -4
View File
@@ -48,10 +48,10 @@ handeye_calibrate:
camera_cy: 0.0
camera_dist: [0.0, 0.0, 0.0, 0.0, 0.0]
# 真实使用的标定板:内角点 8x11,方格 15mm。
# 依据是 handeye/results/*.yaml 头部记录的实测板子,以及 site.yaml 的 handeye.board_*。
# 这里原先写的是 11x16 / 0.011(另一张早期用过的板)—— 三处配置曾互相矛盾,
# 谁生效取决于覆盖顺序,因此存在"标定跑完但结果不对"的风险。
# 板尺寸的权威在 site.yaml → handeye.boards.<模式>。
# 这里只写眼在手上那块板的兜底(A5 / 8×11 / 15mm);run_handeye.sh 会按
# --mode 用 -p 覆盖成对应模式的值。没配过的模式会被脚本当场拦下,
# 不会静默用这份兜底去标另一块板。
board_cols: 8
board_rows: 11
square_size_m: 0.015
+50
View File
@@ -0,0 +1,50 @@
# 眼在手外示教关节(7 关节 × N)。板装在法兰上,顶置 D435 看它。
#
# 由 teach → merge 写入,不要手抄眼在手上那份(两种模式的姿态完全不同)。
#
# bash ~/ros2/scripts/run_handeye.sh --arm 89 teach --mode eye_to_hand --points 12
# bash ~/ros2/scripts/run_handeye.sh --arm 89 merge --mode eye_to_hand
/**:
ros__parameters:
num_poses: 19
waypoint_positions: [
# pose 0
-1.045969, -0.575935, 0.132913, 2.251024, -0.297265, 1.274437, -0.219817,
# pose 1
-1.221272, -0.582225, 0.269777, 2.060852, -0.180051, 1.157081, -0.070498,
# pose 2
-1.222672, -0.605722, 0.273858, 2.111021, -0.181634, 1.193047, -0.059758,
# pose 3
-1.219127, -0.576923, 0.281368, 2.310613, -0.162188, 1.339573, -0.026065,
# pose 4
-1.100853, -0.552692, 0.291246, 2.473326, -0.116403, 1.504852, 0.051283,
# pose 5
-1.022050, -0.394038, 0.375788, 2.311711, -0.503617, 1.217768, 1.268088,
# pose 6
-1.180556, -0.574370, 0.471095, 2.055400, -0.490664, 1.086456, 1.216527,
# pose 7
-2.039707, -0.492556, 1.462952, 2.222064, -0.329990, 0.209789, 0.523258,
# pose 8
-1.959748, -0.554596, 1.469405, 2.293419, -0.165008, 0.422761, 0.844081,
# pose 9
-1.666347, -0.747468, 1.236192, 2.176000, -0.303646, 0.773895, 1.279040,
# pose 10
-1.689100, -0.879982, 1.168013, 2.057620, -0.424417, 0.752234, 1.241290,
# pose 11
-1.691875, -0.889908, 1.154014, 2.062930, -0.549154, 0.850985, 1.257704,
# pose 12
-1.715420, -0.986765, 1.125361, 1.948461, -0.638012, 0.809355, 1.173290,
# pose 13
-1.729057, -1.004106, 1.126932, 1.961482, -0.727920, 0.900058, 1.188069,
# pose 14
-2.034166, -0.748356, 1.234076, 2.252718, -1.542249, 0.093972, 0.640260,
# pose 15
-2.155450, -0.769613, 1.249491, 2.275528, -1.648348, 0.073256, 0.495109,
# pose 16
-1.959788, -0.979802, 1.271261, 2.222882, -1.560991, 0.057204, 0.296625,
# pose 17
-1.933247, -0.398944, 1.211885, 2.312756, -0.424981, 0.358678, 0.347203,
# pose 18
-1.944530, -0.399220, 1.244635, 2.293245, -0.423596, 0.317991, 0.358565,
]
+13
View File
@@ -0,0 +1,13 @@
# 手眼标定结果
# mode: eye_to_hand
# camera_source: d435
# views: 18
# utc: 2026-10-09T02:56:24.621687+00:00
# board: 11x8 square_m=0.02
# T_cam_to_base (eye_to_hand)
translation_m: [0.37495201, -0.52156937, 0.72589194]
T_4x4:
- [-0.04575158, 0.99819969, -0.03878355, 0.37495201]
- [0.99893621, 0.04594039, 0.00399073, -0.52156937]
- [0.00576527, -0.03855971, -0.99923967, 0.72589194]
- [0.00000000, 0.00000000, 0.00000000, 1.00000000]