2026-08-23。起因:首批 14 次实机试验 0 成功,排除链把硬件全部还清白之后,
剩下的全是「数据教了什么、模型学了什么」的问题。
本文件回答三件事:数据怎么处理 · 怎么让它学得更好 · 实验流程长什么样。
配套失败分析:TRIALS-2026-08-23-miss-analysis.md
别再调超参了 —— 这批数据在最右边那个杯位只有 4 集,而且那 4 集抓得最浅最散。 模型忠实地复现了它的数据。补录 + 纪律,比任何训练技巧都值钱。
结果:硬件几何没变,问题在策略侧 —— 假设成立。
操作者重放了一集(面板「▶ 重放示范」):手臂到达了正确的低位,把杯子放进了 两个爪片之间,动作链完整。唯一的失败原因是夹爪摩擦力不足,杯子被推滑出去了。
由此确定:
新夹爪一旦装上:
GRIPPER-SWAP-CHECKLIST.md:不能混训)GRIPPER_LEN = 0.159 m 变了 —— 新爪更长 → 爪尖在更高的手腕位置就触桌 →
z_min 必须上调,不是下调。必须重跑 measure_table.py换爪后的正确顺序:装爪 → measure_table.py 重标 → gripper_range.py 验张口 → 整批重录(按 §3.2 纪律 + 杯位均衡)→ 重训。
把这次学到的东西全部用在新一批数据上,比抢救旧数据划算。
把 50 集示范按闭爪时刻的 pan 角聚类(= 杯子摆在哪),再看每一组的抓取质量:
| 杯位 (pan 均值) | 集数 | 闭爪高度 z | 组内 σ | 前伸 y |
|---|---|---|---|---|
| −30.5°(最左) | 22 | 0.028(最深) | 0.0063(最一致) | 0.160 |
| −10.2° | 7 | 0.034 | 0.0101 | 0.201 |
| +8.8° | 17 | 0.034 | 0.0118 | 0.142 |
| +22.9°(最右) | 4 | 0.038(最浅) | 0.0141(最散) | 0.157 |
集数 vs 抓取高度 r = −0.88 数据越多,抓得越深
集数 vs 组内散布 r = −0.75 数据越多,示范越一致
这正是操作者观察到的现象:「杯子放在右臂偏右边时,过高问题更明显」。 最右那个杯位只有 4 集训练数据,而那 4 集本身就是抓得最浅、最不一致的。 模型在那里表现最差,不是因为它笨,是因为你在那里教得最少、教得最乱。
(数据来源:data/.../file-000.parquet 全 50 集,闭爪时刻用夹爪开度峰值后跌破一半再回退 8 帧
判定,FK 用 arm_kinematics.forward()。这段分析可复现:见第五节工具。)
| 量 | 示范均值 ± σ | 含义 |
|---|---|---|
闭爪时高度 z | 0.032 ± 0.010 m | 肩坐标系;安全下限是 0.020 —— 示范就压在下限上方 1 cm |
全程最低 z | 0.022 ± 0.008 m | 有 4 帧甚至低于 0.02(安全层今天会拒) |
闭爪时前伸 y | 0.159 ± 0.043 m | |
闭爪时 pan | −10.0 ± 20.0° | σ 大是应该的:跨 4 个杯位 |
| 集长 | 389 ± 71 帧(7.1–19.2 s) |
关键认识:抓取动作的成败区间只有 ~1 cm 宽,而且贴着安全边界。 任何"保守一点"的倾向都会直接导致抓空 —— 这正是回归均值在这个任务上如此致命的原因。
录制时刻意做到这三条,每一集都做,不要看心情:
z ≈ 0.025–0.030(比示范均值再深一点,
给模型的回归均值留余量)。PY=~/miniconda3/envs/train310/bin/python
cd ~/Robotic_challenge
# 1) 准星接触表:每集闭爪瞬间的腕部画面拼成一张图
$PY 03-software/scripts/grasp_sight_check.py
# 看:杯子中偏右、爪片左下兜入、俯视进杯口。构图跑偏的集号记下来。
# 2) 分窗质量回报:clamp 事件的趋势(录制时也可 --watch 自动跑)
$PY 03-software/scripts/quality_gate.py
# 3) 杯位覆盖与一致性(本文件第一节那张表)
$PY 03-software/scripts/demo_coverage.py
淘汰标准:构图明显跑偏、或 z@close > 0.045 的集,宁可删掉重录 —— 它们不是"多一点数据",它们是在教错误的技巧。
| # | 动作 | 代价 | 预期 |
|---|---|---|---|
| 1 | 重放实验先做(第五节) | 5 min | 裁决"硬件变了 vs 策略不行",避免后面全白干 |
| 2 | 换 checkpoint:016000 / 018000 各 3 次 | 20 min | 零成本;不同步数对极端段的拟合可能差别很大 |
| 3 | 定向补录:右侧杯位补到 15 集,纪律按 §3.2 | 1–2 h | 最高性价比 —— 直击 r=−0.88 那条相关性 |
| 4 | v2 重训:80/20 分层 + 轻量增强 | 3 h+ | 堵死"走到大概那片区域"的捷径 |
| 5 | 超参调整 | — | 暂不做。数据分布问题没解决之前,调参只是换一种方式过拟合 |
模仿学习里没有渠道"告诉"模型什么重要 —— 示范数据的分布就是全部课程表。
四条推论:
┌ A. 开工前(不碰硬件,5 min)
│ $PY 03-software/scripts/policy_safety.py # 必须 RESULT: PASS
│ $PY 03-software/scripts/robot_profile.py # 两条配置路径一致
│ 面板 → 头部相机对准 → 叠参考图 → 套预设 → 拍快照核对
│
├ B. 裁决实验(只在怀疑硬件变了时做,5 min)
│ 杯子按参考图 1/5 摆回录制位
│ $PY .../run_policy_trials.py --replay-episode 0 --send --trials 1 \
│ --speed 1.0 --chunk-rate auto
│ 能夹到 → 几何没变,问题在策略 │ 同样偏 → 去查硬件,策略无罪
│
├ C. 空跑 1 次(面板「▶ 空跑」,手臂不动)
│ 看:device 是 cuda、总线认对、头部锁定值 ≈ (−4.3, 49.8)、HELD = 0
│
├ D. 实跑 10 次(面板「▶ 实跑」,速度 1.0 / 40 s / 动作块 auto)
│ 手放 12V 插头。10 次里至少 3 次把杯子挪开 2–3 cm。
│ 每次当场判 成功/失败/不计。
│
├ E. 事后分析(不再靠肉眼,2 min)
│ $PY 03-software/scripts/trace_vs_demo.py # 轨迹 vs 示范逐点比
│ 输出:"下沉不足 1.2 cm" 这种可量化结论,直接进下一轮的输入
│
└ F. 回填
结论写进 GOAL-NEXT.md(这个仓库的规矩:做完一件事就把边界条件回填)
一次只改一个变量。 速度、时长、chunk、checkpoint、数据 —— 一轮只动一个, 否则结果无法归因。这条在本次调试中被反复验证:先是速度,再是时序, 每次都是单独改、单独看。
修复(都在工作区,未提交)
| 文件 | 修了什么 |
|---|---|
run_policy_trials.py | 默认 SmolVLA;按舵机数认串口(ACM 编号会反);连接失败重试一次(丢包不该让整场作废);--chunk-rate 让动作块按真实时间播放;--replay-episode 重放模式;--trace 默认记录逐帧轨迹 |
robot_server.py | 面板作业改用 train310(此前用无 CUDA 的环境,2.4 s/帧 → 每帧都会被判陈旧);BUS_OWNERS/CAMERA_JOBS 加入试跑脚本(轮询和预览会抢总线/相机);密码文件进取值链(重启不再换密码);HTML 不缓存;命令描述双语;参考图接口 |
robot_server_dashboard.html | 左侧目录;手机适配;试跑进度小面板;log 自动滚动+报错高亮;速度/时长/动作块选择器;软件急停按钮+急停到底是什么的说明;数据集排序筛选;头部对齐参考图叠加;一个把「读取失败」显示成「没有数据」的 bug |
head_aim.py | 预设改原子写 + .bak(原来是截断写,崩一次全没) |
| 文档 | 更正了流传数日的「head_motor_2 = 99.649 悖论」—— 实为 49.846,在标定范围内 |
新增工具
grasp_sight_check.py —— 准星接触表(50 集闭爪瞬间拼图)trace_vs_demo.py —— 试验轨迹 vs 示范的逐点对比,输出 σ 距离demo_coverage.py —— 杯位覆盖与一致性统计(第一节那张表)分析结论
今天,按顺序:
--model .../checkpoints/016000/pretrained_model)录制时手上要记住的三句话:
轴线向左偏,让左爪贴杯子左缘 · 腕部沉到杯沿以下再推进 · 偏移做夸张,每集都做
别做的: