把当前控制栈收成一份可克隆的源码:腕部看不见时用顶视一次定到基座,二阶段对孔和手外标定跟着进同一份树。
现场 site.yaml、权重和编译产物仍不入库;模板只留占位符。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+35
-33
@@ -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"这种最难查的错)。
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
]
|
||||
@@ -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]
|
||||
Reference in New Issue
Block a user