← 报告首页 / reports index
2026-09-05 · 录制 / 训练 / 跑测 全流程 · 命令全部来自仓库实际代码
录制到验收:要补哪些动作、录前查什么、怎么判成没成
这一页是操作手册,不是概述。回答六件事:
哪些动作还没录、三条路线各自要不要重录、录之前必须查什么、
录完在数据上怎么判合格、去远端 GPU 训练要改什么、现场跑测看哪几个数。
所有命令和判据都对应仓库里真实存在的脚本与接口。
1. 现在有什么,还缺什么
把本机 35 个数据集的 tasks.parquet 全部读出来,去重后只有 5 种任务串:
| 任务串 | 出现在几个数据集 | 能用吗 |
Pick up the cup with the left arm. | 12 | ✅ 训练在用 |
Pick up the cup with the right arm. | 9 | ✅ 现役模型就是这句 |
Pick up the cup and place it down | 11 | ⚠️ 多数是 0826 换夹爪之前的旧数据 |
soak test / Test recording. Not for training. | 5 | ❌ 不是训练数据 |
结论:我们只录过「把杯子拿起来」这一个动作。
pitch 里描述的完整服务链需要的其余动作一个都没有。
还没录的动作清单
| 动作 | 为什么需要 | 难度 | 备注 |
| 倾倒(把液体倒进杯子) | 调酒的核心动作 | 高 | 涉及液体,示范一致性要求高;建议先用固体/空瓶验证流程 |
| 放下 / 摆位 | 拿起来之后总要放下 | 低 | 旧数据里有 place it down,但跨 0826 夹爪换代,不能直接混用 |
| 旋转展示 | pitch 的差异化卖点之一 | 中 | 纯手臂动作,不涉及抓取精度,可能是最容易补的一条 |
| 朝人递出 | 服务链的最后一环 | 高 | 被手眼标定挡着——要知道人在机器人坐标系哪里。且需要人身安全策略 |
| 从预抓取位姿接手 | 路线 2A 的收尾段 | 低 | 可能不用录——先做第 5 节那个五分钟测试 |
2. 三条路线,各自要不要重录
| 路线 | 要重录吗 | 录什么 | 成本 |
| Turn 1 · 纯 SmolVLA | 不要 | — | 0。202 集已经在手,只差跑对一次 |
| 2B · 物体 token | 不要 | — | 物体 token 从已录的 RGB 离线算,只需重训一次 |
| 2A · 深度 + 编码移动 | 可能要 | 从预抓取位姿开始的短集,每集 3–5 秒,预计几十集 | 录制 1–2 小时 + 训练 1.3 小时 / $1。先做第 5 节测试再决定 |
| 新动作(倾倒 / 展示 / 递出) | 要 | 每个动作一个独立数据集 + 独立任务串 | 每个动作约 30–50 集 |
3. ★ 录制前必须查的四类东西 ★
为什么这一节最重要:09-02 那晚录了 102 集,
其中 88 集的深度数据是坏的,当晚没有任何提示。
录制期间没人会告诉你哪里不对——所有检查都必须在按下开始之前做完。
3.1 总线与关节
| 查什么 | 命令 | 合格标准 |
| 整机就绪 | python preflight.py | 无红项。它不碰硬件,只报告环境 |
| 舵机在不在 | python check_arms.py | LEFT 总线 8 颗(左臂+头),RIGHT 总线 9 颗(右臂+轮)。数目不对就是插反了 |
| 端口没插反 | python check_record_ports.py --port1 ... --port2 ... | 在 lerobot.record 通电之前验。2026-08-14 和后来各反过一次,反过来的那一半是静默通过的 |
| 夹爪读数区间 | python gripper_range.py --arm right | 换代后应在 0.3–59.2 区间。若出现 −13.6 / 65.0 那是旧夹爪的数 |
★ 一条总线同一时刻只能有一个程序打开 ★
跑这些检查时,8770 的录制/试跑必须是停的,否则会出现幻影硬件故障——
不是硬件坏了,是两个程序在抢同一个 /dev/ttyACM*。
3.2 三路相机
| 查什么 | 怎么查 | 合格标准 |
| 哪个 /dev/videoN 是哪个相机 | python identify_cameras.py | 两个腕部是同型号 Sonix、USB 序列号相同,只能靠动一个关节看哪路画面在动来区分 |
| 分辨率对不对 | 看录制面板 / 数据集 meta/info.json | 头部 424×240,双腕各 640×480。三路都开 640×480 会撑爆 USB 2.0 集线器、头部超时 |
| 三路都在 | 录制开始后看面板的相机瓦片 | 三块都有画面。缺一路会静默少一个特征,训练时才发现 |
| 头部视角 | 对照 configs/head_reference_cup_grasp.jpg | 和标准视角一致。视角变了模型就是分布外——09-02 那批头抬高约 6°,只能单独成一个变体 |
3.3 深度(只有要用深度时才需要)
| 查什么 | 命令 | 合格标准 |
| 深度录制体检 | python lf_depth_doctor.py(LF 服务开着时随时跑) | 四项全绿。这个脚本是 09-03 那次事故的直接产物 |
| 有没有孤儿录制器 | ps 看有没有常驻 ~30% CPU 的进程 | 无。Start 按两次会孤儿掉上一个录制器,它会一直写盘直到把根分区写满 |
| 磁盘余量 | df -h / | 留足空间。满盘会让整个开发环境失效,不只是录制失败 |
3.4 物体检测(只有走 2A / 2B 时才需要)
| 查什么 | 怎么查 | 合格标准 |
| 杯子在画面里检得出吗 | 用 OWLv2 @0.30 跑一批帧 | 实测基线:36 帧里 19 帧检出,100% 是杯子,零误检。低于这个要查场景 |
| 有没有锁错目标 | 逐框裁开人工看图 | 这一步不能省。假阳性历史:VR 手柄、桌面走线孔被当成杯子,已经发生三次 |
| 物体分组质量 | 看 slot 掩码图 | 接近阶段应有一个 slot 明显专注在杯子上(实测 2.7× 基线) |
4. 录完立刻要做的三件事
- 确认数据集传上去了。查
meta/upload.json。
上传只在录制结束当场发生一次——事后不会自动补传。漏了要走 /api/dataset/publish 手动补。
- 数一下集数和帧数对不对。面板会报每集深度帧数、0 帧标红。集数少了说明中途掉了。
- 跑数据健康检查:
GET /api/data/health 与 GET /api/dataset/verify?repo_id=...。
5. ★ 数据侧怎么判「这批数据合格」★
下面每一条都是可以机器算出来的,不靠感觉:
| 指标 | 合格标准 | 怎么算 | 不合格意味着 |
| 夹爪开合次数 | 每集恰好 1 次 | 取夹爪序列,以 min+0.25*range / min+0.75*range 双阈值做迟滞计数 | 示范里 40 集100% 都是 1 次。多次开合 = 示范本身不连贯,会教坏模型 |
| 任务串 | 全数据集只有一句,且和推理端下发的完全一致 | 读 meta/tasks.parquet | SmolVLA 是语言条件模型,多一句就是多一个任务 |
| 三路相机 | head 424×240 + 双腕各 640×480 | meta/info.json 的 features shape | 缺一路 = 推理端喂的和训练的对不上,静默失配 |
| 杯位覆盖 | 越宽越好;现状右臂只有 35.1°(std 5.15) | 找每集夹爪首次降到 (max+min)/2 以下的帧,取当时五个臂关节的 shoulder_pan | 覆盖窄 = 换位置就不行,这一条架构解决不了 |
| 每集时长 | 同一批内应当接近;离群的要看 | 帧数 ÷ fps | 特别短 = 中途中止;特别长 = 反复试探 |
| 开头突跳 | 前 5 帧的关节变化不应远高于常态 | 比较前 5 帧最大 |Δjoint| 与全集中位 | 实测现状 12–20 倍,主因是腕部对齐。录制时先静止 3–5 帧可消除 |
| 静止帧占比 | 越低越好;现状 26–35% 在中间 | 逐帧最大 |Δjoint| < 0.05° 即算静止 | 三分之一训练信号在教「不动」,与试跑时的原地试探吻合 |
| 深度帧数 | 非 0,且和 RGB 帧数量级一致 | 面板每集显示 | 0 帧 = 那一集深度作废(09-02 有 88 集是这样) |
| 跨硬件变更 | 不许跨 2026-08-26 | 看 meta/merge_sources.json 的来源日期 | 换代前夹爪读数 −13.6~65.0、换代后 0.3~59.2,同一个动作是不同的数字 |
5.1 ★ 2026-09-05 新查出来的两条,都要进验收 ★
① 每一集第 0 帧手臂就已经在动 —— 没有静止的开场。
实测:开头静止占比中位 0.0%(0826 与 sep3 都是)。
而开头几帧的关节变化是 3–5.5°/帧,常态只有 0.26°/帧——高 12–20 倍。
动的是哪个关节高度一致:sep3 有 41/42 集全在 wrist_roll,
0826 主要在 wrist_flex。这不是噪声,是遥操作接管那一瞬间的腕部姿态对齐。
后果:模型学到的「第一帧该做什么」就是那个突跳。
录新数据时的改法:按下录制后先静止 3–5 帧再开始动,
让模型有一个干净的起始状态。这几乎不花成本,但改变的是每一集。
② 每集有 26–35% 的帧手臂完全不动,而且集中在中间。
实测(MOVE 阈值 0.05°/帧):
| 0826 右臂 | sep3 左臂 |
| 开头静止 | 0.0% | 0.0% |
| 结尾静止 | 12.0% | 9.6% |
| 中间夹杂的静止 | 25.8% | 35.2% |
模仿学习是在每一帧上学的:三分之一的训练信号在教「原地不动」。
这和试跑时看到的
原地试探 / 停滞高度吻合——模型学到「停着」是一个合法动作。
裁首尾只能省 10–12%,解决不了。中间那些停顿是操作者在对准和犹豫,
机械裁掉会破坏时序连续性(动作 chunk 是连续 50 步)。
只能在录制方式上改:动作要连贯,宁可这一集作废重来,也不要中途长时间停下来想。
最省事的做法:这些指标里前四条已经有实现(
run_policy_trials.py 里的 _gripper_cycles、覆盖分析脚本),
下一步是把它们抽成 dataset_audit.py,对任意数据集一条命令跑完。
6. ★ 去远端 GPU 训练:代码改动与指令差异 ★
本机训练不了。lerobot 环境里的 torch 是 CPU-only
(实测 torch.cuda.is_available() 为 False)。
本机只负责合并数据集 + 推 Hub;训练一律在租的 GPU 上跑。
6.1 本机做的两步
# ① 合并数据集 —— 必须在训练【之前】做完
# lerobot 0.6.2 不支持 --dataset.repo_id 传列表(datasets/factory.py:128 直接 raise)
python 03-software/scripts/aggregate_datasets.py ... # 要传 roots,多任务必须显式 --task
# ② 推到 Hub —— 远端只认 repo_id,不认本地路径
6.2 远端 GPU 上的差异(逐条)
| 项 | 本机 / 直觉做法 | 远端实际要怎么做 | 为什么 |
| 怎么起 | ./train.sh 直接跑 | 必须在 tmux 里跑 | 家里网一断,Pod 不停、计费也不停,但你的进程会死 |
| 数据来源 | 本地路径 | 只能传 --dataset.repo_id,且只能一个 | 不支持列表,合并要提前做 |
| 相机名映射 | 想加 rename_map 把相机改成 camera1/2/3 | 绝对不要传 rename_map | 现役模型的输入特征就叫 observation.images.head / right_arm_wrist / left_arm_wrist,推理端也按这套名字喂。改了名新 checkpoint 就和机器人对不上 |
| 输出目录 | 随便放 | --output_dir=/workspace/... | Pod 的持久盘,重启不丢 |
| 存档频率 | 默认 | save_freq = steps / 10 | 断了能从最近的 checkpoint 接着来 |
| 推 Hub | push_to_hub=true | push_to_hub=false,训练完手动 hf upload | 训练中途推会拖慢并占带宽;手动传能挑 checkpoint |
| 视频后端 | 默认 | --dataset.video_backend=torchcodec | 2026-08-27 在 4090 上验证过的 AV1 后端 |
| batch | 一个 batch_size | B_eff = MICRO_BATCH × ACCUM,两者分开传 | 显存不够时靠梯度累积凑有效批大小 |
| 模型归属 | — | 模型在 Suyang99 个人名下,数据集在 xlerobot-team 组织名下 | 两者不一样,别搞混 |
| 先烟测 | 直接开跑 | BENCH=1 ./train_smolvla_lr.sh(40 步、不存档) | 省得跑一小时才发现配置错了 |
| 只看命令 | — | DRY=1 ./train_smolvla_lr.sh | 打印不执行 |
6.3 实际命令
# 在租的 GPU 上,tmux 里:
tmux new -s train
./train_smolvla_lr.sh # 默认 sameview 变体,4090 上一小时出头
VARIANT=all ./train_smolvla_lr.sh # 对照实验(202 集全量)
BENCH=1 ./train_smolvla_lr.sh # 40 步烟测,先跑这个
DRY=1 ./train_smolvla_lr.sh # 只打印命令
# 配方(= 现役模型 b16-3cam-u20k,改了就要写实验记录)
# B_eff 16 / lr 1e-4 / updates 20000 / warmup 1000 / aug on(含 affine)
# scheduler_decay_steps = updates ← 让学习率曲线走完
改配方前先想清楚这次要测的变量是什么。
train_smolvla_lr.sh 刻意把配方对齐现役模型,
就是为了让「换数据」成为唯一的变量。同时改两个东西,结果无法归因。
7. 现场跑测怎么看
7.1 开跑前(两个输入框)
| 项 | 必须是 | 错了会怎样 |
| 任务指令串 | 和模型训练集里那句逐字一致 | SmolVLA 是语言条件模型,换一句 = 它没学过的任务。面板现在会硬拦截,不一致直接不许启动实跑(空跑和重放不拦) |
| speed | 1.0 | 0.3 会把安全层步长上限乘 0.3,实测削掉够杯子那个关节的 11–20% |
7.2 跑的时候(当场诊断会自己打印)
诊断 · [right 臂] 够下去的动作被安全层削掉 20%(策略想动 154°,实际 124°) ← 偏高,考虑把 speed 调到 1.0
诊断 · 夹爪开合 3 次 ← 示范里恒为 1 次,多次开合说明动作不连贯
它在你判成功/失败之前就打印,诊断出异常永远不打断试验。
| 看什么 | 好 | 不好 | 说明什么 |
| 安全层削减 | 接近 0% | > 10% | 削减大 = 策略想做的没被执行,不能归因给模型 |
| 夹爪开合次数 | 1 次 | 2 次以上 | 示范里 100% 是 1 次。多次 = 策略在反复试探,动作不连贯 |
| 哪只臂在动 | 和任务串一致 | 不一致 | 诊断按运动量判,不认任务串措辞——因为措辞可能填错 |
| 控制频率 | 稳定 | 忽高忽低 | 09-04 只有 1.8–4.7 Hz,原因之一是浏览器失控轮询(已修) |
7.3 一批跑完怎么判
预注册:开跑前先写下判据、计划次数、初始条件。
跑完再定标准,那不是测量,是讲故事。
一批建议 10 次,杯子位置固定、顺序固定,这样和上一批可以直接比。
说「从没成功过」「唯一一次」这类话之前,先去 05-training/trials/trials-*.json 数一遍。
| 结果 | 该得出的结论 |
| 削减降了 + 开合回到 1 + 成功率上去 | 之前的失败是输入框,不是模型 |
| 开合回到 1 但还是抓不到 | 指令串确实错过,但模型能力也确实不够 → 补数据 / 上泛化路线 |
| 开合还是 2、3 次 | 指令串不是原因,另找(视角?训练不足?) |
| 全都正常但成功率仍为 0 | 这才轮到「模型不行」——而且是在最有利条件下都不行 |
8. 一页速查
| 阶段 | 关键命令 / 接口 | 一票否决项 |
| 录前 | preflight.py · check_arms.py · check_record_ports.py · identify_cameras.py · lf_depth_doctor.py | 总线颗数不对 / 相机缺一路 / 磁盘将满 |
| 录中 | LF 面板(8781):动左臂,右臂跟随并录制 | Start 不要按两次 · 不要重绑 RIGHT B(那是头部跟随/锁定开关) |
| 录后 | meta/upload.json · /api/data/health · /api/dataset/verify | 没上传 / 深度 0 帧 / 跨 0826 |
| 训练 | 本机 aggregate_datasets.py → 推 Hub → 远端 tmux 里 train_smolvla_lr.sh | 传了 rename_map / 没在 tmux 里 / 同时改多个变量 |
| 跑测 | 面板试跑卡(指令串硬拦截 + speed 1.0) | 指令串不一致 / speed 0.3 / 跑完才定判据 |
9. 证据等级
| 结论 | 等级 | 来源 |
| 全部数据集只有 5 种任务串,训练用的只有 pick left/right | 本机实测 | 2026-09-05 读全部 tasks.parquet |
| 示范里夹爪开合 100% 恰好 1 次 | 实测 | 40 集,双阈值迟滞计数 |
| 右臂横向覆盖 35.1°,std 5.15 | 实测 | 合并集 202 集 |
| 安全层削掉 11–20% | 实测 | 09-04 四条轨迹 raw vs safe |
| 09-02 那 102 集里 88 集丢深度 | 实测 | 09-03 事故排查 |
| OWLv2 @0.30:19/36 帧、100% 精度 | 实测 + 逐框人工看图 | 36 帧 |
| 训练配方与远端差异 | 读过脚本 | 05-training/train_smolvla_lr.sh |
| 开头静止 0.0%、突跳 3–5.5°/帧 vs 常态 0.26° | 本机实测 | 2026-09-05,100 集逐集算 |
sep3 里 41/42 集突跳在 wrist_roll | 本机实测 | 同上,按关节归因 |
| 中间静止 25.8% / 35.2% | 本机实测 | 同上,MOVE 阈值 0.05°/帧 |
| 新动作各需要多少集 | 未测 | 「30–50 集」是按现有经验类比,不是实测 |
这一页的每条命令都对应仓库里真实存在的脚本。找不到的、跑不通的,直接说,我改。