← reports index
实机试跑 · 2026-09-08

右臂抓取:一天 16 次全败,问题出在哪

今天在四个 checkpoint 上跑了 16 次实机抓取,0 成功。最后八次样本量够大,把「这个模型在当前设置下抓不到」变成有统计支撑的结论(95%CI 0–36.9%)。这一页记录:操作者观察到的四个现象里哪些是真的、量出来的两个真实缺陷、以及被证伪的那些路 —— 后者同样重要,能省下再走一遍的时间。

一、操作者的四个观察,三个是错觉

现场观察:①左右转不够 ②张开太晚撞到杯子 ③往杯子伸出不够 ④闭爪有点早。把每一条对着示范集量出来:

观察示范中位实机中位实机/示范判定
① 左右转的幅度23.5°26.2°1.12×转得更多,不成立
② 张开时已伸出多少35.9%36.1%1.01×几乎一模一样,不成立
③ 最远伸出多少58.5°77.8°1.33×伸得更远,不成立
④ 闭爪时已伸出多少99.8%52.1%0.52×真的
示范里爪子在伸出行程的 99.8% 处闭合 —— 几乎伸到最远才夹。40 集的 p10~p90 是 98.2%~100%,方差近乎为零。实机是 52%,刚过一半。

另外三条是这一条造成的错觉。操作者是在闭爪那一刻观察的,而闭爪发生在整条轨迹的一半 —— 那时手臂当然还没转到位、也没伸到位。它后来都走到了。
「张开太晚」也是同一件事:张开的时刻其实很准(36.1% vs 35.9%),但闭合从 100% 提前到 52%,张开→闭合的窗口从 64% 行程压缩到 16% —— 爪子刚张开就合上,看起来像来不及张开。

二、第二个真实缺陷:横向只做到六成

最后八次每次记录了杯位档号,回归「杯位 → 闭爪时的 pan」:

闭爪时的 pan     斜率 +6.72 度/档   r=+0.857   增益 0.59
轨迹最终的 pan   斜率 +7.15 度/档   r=+0.686   增益 0.63
(示范里相邻档位杯位相差约 11.4 度,「跟得住」应该是 1.0)
原本以为「转不够」只是「闭爪太早」的副产品 —— 如果是,让它走完就该跟得上。实测走完也只有 0.63。所以这是独立的第二个缺陷,两个毛病互不解释。

而离线测量显示模型有这个能力:从够取过程中段起手、看整条 50 步计划,斜率是 1.02(r=0.98)。但从 home 位起手时是 −0.03 —— 完全不瞄。真机每次都从 home 开始,走不到会瞄的那一段。

起手位置计划终点与杯位的斜率r
phase 0.00(home)−0.03−0.10
phase 0.35(中段)+0.90+0.89
phase 0.70(接近)+1.02+0.98

三、被证伪的路(省下再走一遍的时间)

猜测怎么排除的
安全层把动作削掉了六条 trace 逐帧比对 raw 与 safe,pan 维被钳帧数 0/95、0/241、0/254… 全是 0。策略自己只发到那儿。
爪面朝向(wrist_roll)没转示范里 wrist_roll 与杯位完全无关(r=+0.032,斜率 0.006,40 集只在 ±5° 内晃)。爪面朝向本来就跟着整条臂转,模型输出常数是学对了。
相机角度偏了head_1 −3.69° / head_2 +49.83°,与训练集(−3.692 / +49.846)吻合到 0.02 度。三个数据集的头部角度也彼此一致。
加「手臂稳了才许夹」的闸实机闭爪前 0.5s 的 pan 角速度 0.04~3.34 度/秒,六次全部低于示范 p95(6.16)。这个闸一帧都拦不到。
加「多少秒内不许夹」的时间闸做了并上机跑过。闸在 7.4 秒放行、只拦下 9 帧,而真正的闭爪发生在 27.7 秒 —— 判据选错了维度。(它还有个 bug:对象没按次重置,第 2 次起就失效,已修。)
缩短执行视野 --exec-horizon「执行 1–5 步优于 20 步」的前提是模型有视觉增益、只是被开环时长浪费。这里增益本身就不在起手段,每 0.3 秒重看一次也只修正需要量的 4%。开关已加好,但不是主线。
给一个固定的横向补偿(观察到偏右约 2 cm)偏置随阶段变:中段 +3.12°(≈1.3 cm 偏右),接近段 −0.98°(≈0)。固定补偿会在接近段把它推过头。

四、唯一一个已修的真 bug

state 通道被放大 1e8 倍
训练集 16,487 帧的左臂六维全是 0,于是统计量 mean=0, std=0;而 lerobot 的归一化是 (x−mean)/(std+1e-8),对 std==0 没有任何保护。真机上左臂是连着的、报真实角度。
实测:同一张图、同一右臂状态,左臂偏 0.1° 就让右臂输出变 64°;而 0.1°/5°/几十度结果几乎一样 —— token 已经饱和。
修法:install_state_guard() 从 checkpoint 自己的统计量推出所有 std==0 的维度,喂给策略前钉回训练均值。不硬编码哪条臂;只改喂给策略的那一份,安全层继续看真实 17 维。
效果:同一 checkpoint 重跑,夹爪开合 10/18 → 5/10,CLIPPED 10 → 3。但仍然 0/2 —— 它治的是动作连续性,不是抓不到。

五、怎么解决

两个缺陷都不能在推理端打补丁:闭爪时机要知道「总行程」,而那是跑完才知道的;横向增益是模型本身的性质。都要靠数据和重训。

1
补录:换杯位 + 打散节奏
杯位覆盖现在差 16 倍(最密一档 16 集、最疏一档 1 集),而最疏那端正是操作者标的 hard zone —— 它不是本身难,是几乎没录过。
节奏:示范里「跑到全程 63.2% 闭爪」的标准差只有 4.6%,模型数拍子就能压低 loss、完全不用看杯子;而真机回路只有 4 Hz(示范 30 Hz),节拍一变全错。
约 15 集即可。做法与验收标准见 Recording guide(英文,可直接发给队友)。
2
重训:state dropout
state ↔ 下一帧 action 逐维相关 0.98–0.995,「照抄当前关节角」的误差中位只有 0.66° —— 捷径几乎白送。做法、退火档位与验收见 右臂重训手册 与 补丁机制。
3
验收换指标 —— 别再用视觉斜率
pan 斜率(今天一直在用)闭爪@行程(建议改用)
参考值方差±0.05 噪声底98.2~100%,近乎为零
区分度八个模型全落在噪声里现役 52%,差距近 2 倍
重跑稳定性同模型三次给 +0.086 / +0.041 / −0.006—
物理含义间接直接对应「夹的时候到没到位」
trace_timing.py 每次跑测自动输出这一列。

六、这一天在测量上翻的车

  1. 只用每集起始帧测视觉敏感度 —— 起手位本来就不瞄,任何模型都接近 0。要沿够取过程分阶段测才有分辨力。
  2. 每集用自己的 state —— state 的集间差异污染结果,测出的 32.8%「敏感度」里大半不是视觉。
  3. 以为加了 torch.manual_seed 就是配对比较 —— 实际没控制住流匹配的采样,同一模型同一喂法三次给三个数。±0.05 是噪声底,小于它的差异不能读。
  4. 只取动作块的第一步 —— SmolVLA 一次规划 50 步,而 predict_action 只返回第一步。这条是操作者指出来的,也是最要害的一条。
  5. 用 argmin 找「闭爪时刻」 —— 实机第 0 帧夹爪就是闭着的(示范教的就是闭着爪伸出去),argmin 落在开跑那段,算出「闭爪比到位早 19~47 秒」这种不成立的数。
  6. 两处各写一份「开合次数」 —— 脚本用双阈值迟滞只数开→合,我用固定阈值双向都数,同一批 trace 给出 2 vs 10。现在统一 import 脚本那一个。
六条里五条是自查发现的,第 4 条是操作者指出的 —— 而它恰好影响最大。把测量本身当成要验证的对象,和把模型当成要验证的对象同样重要。
16 次实机试跑于 2026-09-08,四个 checkpoint(state6 / sd-12k / sd-20k / sd-20k+闸)· 最后一批 8 次记录了杯位档号,结果文件 trials-20260908-172208.json(0/8,95%CI 0–36.9%)
工具:trace_timing.py(闭爪时机与行程)· chunk_sweep.py(整块 + 分阶段视觉斜率)· state_regime_sweep.py(四种 state 喂法)· camera_ablation.py(逐路相机遮盖)