队友提的:「电机在往下推但角度不变,显然是撞到桌子了」。这一页记录把它做成可用判据的全过程 —— 包括第一版判据在真机上失败的原因,以及改完之后从第 13 步提前到第 3 步。
放杯子的位姿现在是写死的关节角(place_pose.json,从 10 集示范算的中位数)。桌面高度一变就不准,而且压过头会挤坏杯子或顶伤手臂。队友的建议是让手臂自己知道「碰到了」。
第一次采集(手臂端着杯子、杯底已触桌,继续往下压):
步 目标° 实际° Load Vel
1 32.03 32.00 36 0
2 31.53 32.00 60 0 ← 目标一直降,实际位置纹丝不动
3 31.03 32.00 84 0
4 30.53 32.00 104 0
5 30.03 32.00 128 0 ← Load 单调爬升
换一个完全不同的姿态再测一次(起点 52° 而不是 32°),曲线几乎重合:
| 步 | 第一次(32° 起点) | 第二次(52° 起点,杯子在桌上) |
|---|---|---|
| 1 | Load 36 | Load 36 |
| 2 | 60 | 60 |
| 3 | 84 | 84 |
| 4 | 104 | 104 |
| 5 | 128 | 124 |
两次在不同姿态下 Load 的爬升几乎一致 —— 信号稳定,不是偶然。
真机数据(先抬 6° 再下压):
步3-4: Vel=0 堵转 1/4 → 2/4
步5: Vel=-50 → 计数清零 ← 手臂又挪了一格
步7-8: Vel=0 堵转 1/4 → 2/4
步9: Vel=-50 → 计数清零 ← 又挪了
步10-13: Vel=0 堵转 1/4 → 4/4 ← 到第 13 步才判出
原因:手臂不是一次卡死,而是走走停停地下降(52→55→54→53)。舵机每次积累够力矩就挪一格,然后又停住。「连续 N 帧速度为零」被这个间歇运动反复打断,结果多压了 3.0°。
| 状态 | 帧数 | Velocity = 0 的比例 |
|---|---|---|
| 抬升(自由运动) | 24 | 67% |
| 下压(受阻) | 16 | 62% |
判据改成看窗口内实际走了多少,而不是瞬时速度:
跟随率 = 最近 4 步的实际位移 / 命令位移
判定撞到东西: 跟随率 < 35% 且 |Load| ≥ 40
连续满足 2 次
走走停停照样算「跟不上」,因为总位移远小于命令位移。
步 目标 实际 Load Vel 跟随率 判定
1 55.50 55 23 -50 -
2 55.00 55 35 -50 -
3 54.50 55 64 0 -
4 54.00 55 84 0 0% 堵转1
5 53.50 55 87 -50 0% 堵转2 ★判定★
注意第 5 步:Vel=-50(手臂在动), 旧判据会清零,新判据照样判出 —— 因为窗口内实际位移是 0,而命令走了 2 度。
步 目标 实际 Load Vel 跟随率 判定
1 56.55 56 -21 -50 0% 堵转0
2 56.05 56 40 0 0% 堵转1
3 55.55 56 64 0 0% 堵转2 ★判定★
| 判出的步数 | 多压了多少 | |
|---|---|---|
| 旧判据(连续 4 帧 Vel≈0) | 第 13 步 | 3.00° |
| 新判据(跟随率) | 第 3 步 | 1.05° |
| 状态 | Load 范围 | 中位 | 符号一致性 |
|---|---|---|---|
| 抬升(对抗重力向上) | -148 ~ -19 | -85 | 24/24 为负 |
| 下压(受桌面阻挡) | -21 ~ 196 | +86 | 15/16 为正 |
Present_Load 是符号-幅值编码的,符号直接指示受力方向。这比预期干净,可以用来区分「在往上顶」和「在往下压」。
shoulder_lift。要测重量或接触,必须读它,不是读夹爪。
place_cup.py:放杯改成「压到碰桌为止」,不再依赖写死的关节角,桌面高度变了也能自适应03-software/scripts/table_contact_probe.py(采集与判据)·
place_cup.py --no-release(走到放置位不松爪,给采样用)