← 报告首页 / reports index
2026-09-05 · 演示路线与迭代规划 · 代码端逐段查过

读懂客人需求的机器人:抓取只是最后一环

我们要做的不是一只机械臂,是一个能读懂客人情绪和需求的机器人。 看见人、判断状态、开口对话、听懂他要什么、把那个东西拿给他——抓取是这条链路的最后一段。 这一页把整条链路摊开(第 0 节),然后回答:为了这个目标,现在该做什么、下一轮再做什么、各自多少钱。 时间有限,所以要分清演示的底线和加分项:左右手抓取的数据已经有了, 单纯用 SmolVLA 能把杯子抓起来,本身就已经撑得起一场演示。 深度定位和物体检测都是泛化用的,不是抓起来的前提,因此归入 Turn 2。

一句话:Turn 1 零新成本——不用新数据、不用新代码、不用任何标定, 只要现场把两个输入框填对再跑一次。Turn 2 才是花钱的部分,两条泛化路线各自解决一半问题, 成本和风险在第 3 节逐项列出。而「用户说我要高脚杯」这种交互, 答案是不要指望 SmolVLA 提供——见第 6 节。

0. 北极星:一次完整的客人交互

下面每一格都可以点开。注意最后两格才是这一页后面在讨论的东西—— 前面五格是这个机器人真正的主体,而且大部分已经在跑了。

已在跑 部分可用 / 要补 本页讨论的部分

← 左右滑动看完整条交互 →

为什么这个框架重要:单看抓取,0/3 是个坏消息。 放回整条链路看,人脸、语音、表情、转头迎宾这几段已经能跑, 抓取只要在固定位置稳定成功,整条演示就闭环了。 Turn 2 的两条泛化路线,真正的价值不是「抓得更准」,而是让第 ④ 格(听懂他要什么)能真正连到第 ⑥ 格——见第 6 节。

1. 两个 Turn 的分工

Turn 1 · 把杯子抓起来Turn 2 · 泛化
目标固定位置、固定那只杯子,稳定抓起换位置也行 / 换杯子也行
需要什么已经全部就位:202 集数据、已训好的 checkpoint、安全层、试跑流程新代码 + 标定 + 可能要重录数据 + 重训
还差什么只差跑对一次——09-04 那 0/3 的指令串和 speed 都填错了见第 3 节
现场时间约 30 分钟(10 次试跑)数小时到一天
钱0训练 $1–2,加上录制的人力
演示价值这就是演示的底线,必须成加分项
把这条说清楚很重要:一个能在固定位置稳定抓起杯子的真实机器人, 配上已经在跑的人脸、语音、表情屏,已经是一个完整的演示。 泛化是让它更像产品,但不是让它成立的条件。

2. Turn 1:现在就该做的事

09-04 试跑 0/3,但在归因到「模型不行」之前,两个填错的输入框还没排除:

当时填的应该是为什么要紧
任务指令串...with the left arm....with the right arm. 现役模型训练集里只有右臂那一句。SmolVLA 是语言条件模型,换一句 = 换一个它没学过的任务
speed0.31.0 把安全层步长上限乘了 0.3,轨迹实测削掉 shoulder_lift 的 11–20%——正是「放下去够杯子」那个关节

指令串这一项现在有硬拦截了(robot_server_dashboard.html:4841):不一致时直接阻止实跑启动。 但正确条件下的 10 次还没跑——截至 2026-09-04 23:28,最新记录仍是 09-04 18:33 那 4 次错误数据。

Turn 1 的唯一待办就是这一次重跑。它同时也是 Turn 2 的前提: 如果最有利条件下仍然抓不起来,那先要修的是模型/数据,而不是加泛化。

3. Turn 2:两条泛化路线,各解决一半

它们互补,不冲突,也不互为前提——可以只做一条:

换杯子(外观变,位置不变)换位置(同一只杯子挪走)
2A 深度 + 编码移动深度对不透明杯都行✅ 正是它解决的
2B 物体 token(B0)✅ 正是它解决的❌ 架构解决不了

成本对照(这是决定做不做的依据)

成本项2A · 深度 + 编码移动2B · 物体 token
要写的代码一个新脚本 guided_grasp.py。七步里五步是现成的(第 4 节),
要写的只有坐标变换、退让距离、交棒时机
object_proj + embed_prefix 的 append 分支,
约 15 行,另加 pad/att mask
标定① 相机系→臂基座系:可用已录的 202 集离线拟合,0 现场时间(第 5 节)
② 深度相机内参:要现场拍棋盘,约 30 分钟
不需要任何标定
要不要重录数据可能要——取决于第 7 节那个五分钟测试。
要的话:新建数据集,每集 3–5 秒,预计几十集,约 1–2 小时录制
不用。物体 token 从已录的 RGB 离线算
重训要(新数据集)· 约 1.3 小时 / $1要(object_proj 是随机初始化的)· 约 1.3 小时 / $1
算力(Jetson 每周期余量 337 ms)深度反投影几乎免费;在线不需要跑大检测器FT-DINOSAUR small@224 实测 52.4 ms ✅
2026-09-05 本机实测,中位 52.4 / p95 53.8 / 显存 152 MB
新增的失败模式标定漂、深度对透明杯失效、检测锁错目标——
这些原来都不存在,端到端是把它们一起学掉的
slot 质量不佳时给出错误先验;
比没有先验更糟
最大的未知SmolVLA 能不能从预抓取位姿接上(第 7 节,未测)7 个 slot 有没有真的把杯子分出来(未过人工看图)
如果只能做一条:看演示要展示什么。 要展示「放哪都能抓」→ 做 2A;要展示「换个杯子照样抓」→ 做 2B。 2B 不用重录数据,所以它的下限成本更低;2A 的上限价值更高,因为它直接绕开了那 35.1° 的数据覆盖限制。

3.5 ★ 三条路线:怎么实现、吃多少内存、现在能不能做 ★

Jetson Orin Nano 是 7.4 GB 统一内存(显存和系统内存是同一块)。 下面全部是 2026-09-05 在本机实测,不是估算。

内存与耗时(实测)

加载什么进程 RSStorch 显存单次耗时系统仍可用
起点(只 import torch)490 MB0—3505 MB
+ 几何路线(深度反投影 + IK)+84 MB03.56 ms3475 MB
+ FT-DINOSAUR small@224+705 MB138 MB52.4 ms3091 MB
+ SmolVLA(450M 参数)+1911 MB1023 MB1329 ms—
三者同时驻留3190 MB1023 MB—1844 MB
★ 检测器和 SmolVLA 可以同时驻留,还剩 1.8 GB ★ 这原本是 GOAL-T1 里的头号未测项,现在关掉了。

而几何路线几乎不占资源:+84 MB、零显存、3.56 ms。 所以「这块板子内存不够,所以不能靠硬编码」这个担心正好反了—— 硬编码是这块板子上最负担得起的那一半;吃内存的是学习式的感知模型。

三条路线逐项对照

路线 1 · 纯 SmolVLA
Turn 1
路线 2A · 几何硬编码 + SmolVLA 收尾路线 2B · 物体 token
怎么实现 已有:run_policy_trials.py 直接跑 checkpoint 新脚本 guided_grasp.py:深度→3D→坐标变换→IK→安全层→send_action→交棒。七步里五步现成 模型内改动:object_proj + embed_prefix 的 append 分支,约 15 行 + mask
额外内存0(本来就要加载)+84 MB,零显存+705 MB / 138 MB 显存(FT-DINOSAUR)
额外耗时/周期0+3.56 ms+52.4 ms(预算 337 ms)
现在能不能做 ✅ 能,而且零成本 ⚠️ 一半能:算出「杯子在相机系的 3D 坐标」现在就能跑;但还不能让手臂去那里——缺相机→臂基座的变换 ⚠️ 输入端已验证(耗时 52 ms、7 个固定 slot、接近阶段纯度 2.7×),但接口代码还没写
还缺什么 只差跑对一次 ① 相机→臂基座变换(可离线拟合,纯远程,见第 5 节)
② 深度相机内参(要现场拍棋盘约 30 分钟)
③ 第 7 节那个五分钟测试
① 写 object_proj(远程)
② 重训一次
要什么数据 不要,202 集已有 标定不要新数据(用已录的 202 集拟合)。
但如果第 7 节测出「接不上」,要重录:新建数据集,每集 3–5 秒,预计几十集
完全不要。物体 token 从已录 RGB 离线算
成本 现场 30 分钟,¥0 远程:拟合标定几小时(含 OWLv2 跑几百帧,离线慢无所谓)
现场:内参 30 分钟 + 测试 5 分钟
若要重录:录制 1–2 小时 + 训练 1.3 小时 / $1
远程:写代码 + 训练 1.3 小时 / $1
无现场时间、无录制
新增失败模式无标定漂、深度对透明杯失效、检测锁错目标slot 不干净时给出错误先验
买到什么固定位置稳定抓起换位置 + 听懂点单(第 6 节)换外观
回答「硬编码现在能不能做」: 几何计算本身现在就能跑——深度反投影和 IK 都在仓库里,实测 3.56 ms、+84 MB。 缺的只有那一个坐标变换,而拟合它不需要新数据、不需要现场、可以立刻开始(第 5 节)。 所以 2A 的远程部分今天就可以动手;需要现场的只有深度内参(30 分钟)和那个五分钟测试。
但顺序不能错:先做第 7 节那个五分钟测试。 它决定了 2A 要不要重录数据——那是这三条路线里唯一一笔大成本。

4. 2A 的运行时流程(点开每一格)

已有,直接用 要写 / 要补 被挡住 未测,先验证

← 左右滑动看完整条链路 →

5. 那唯一被挡住的一步,有个不用棋盘格的解法

缺的是相机系 → 臂基座系的变换。09-04 试过棋盘格手眼,失败了——棋盘没夹在爪子上(远程给错了指示)。 但还有一条路,而且不需要再拍一张照片:

用已经录好的 202 集自己解出这个变换。 依据在我们自己的数据里:夹爪合拢的那一刻,夹爪就在杯子上——这一条 09-04 已经用来量过数据覆盖。 所以每一集都天然给出一对对应关系:
这一端该集开头的头部帧里,杯子的像素位置 (u, v) + 深度 Z 那一端合拢那一帧的臂关节 → arm_kinematics.forward() → 臂基座系的 (y, z)
202 集 = 202 对对应关系,拟合出相机相对臂基座的位姿。留一验证直接给出误差。
两条限制要说清楚: ① 这些对应只覆盖已录过的杯位范围(右臂横向 35.1°)。必须拟合几何模型(参数少、有物理含义)才能外推,查表或回归不行。 ② 要先在那些帧上检出杯子。OWLv2 在我们数据上是 19/36 帧、100% 精度,所以能用上的集数会少于 202——但这是离线的,慢无所谓。

6. ★ 用户说「我想要高脚杯」,能不能做到 ★

不要指望 SmolVLA 提供这个能力。 它确实是语言条件的——我们自己的合并集里两条指令就是用一句话切换左右臂的:
Pick up the cup with the right arm.   task_index 0
Pick up the cup with the left arm.    task_index 1
但它一共只见过这两句。喂它 Pick up the wine glass 就是分布外—— 和 09-04 那个 left arm 错误是同一类问题,不是同一个程度的问题:它没有任何理由把新词映射到新行为。

那为什么它的 VLM 主干「认识」高脚杯却不管用? 因为主干是冻结的(freeze_vision_encoder: True、train_expert_only: True), 训练时只有 action expert 在学,而它只在那两句指令上学过。语义知识在模型里,但没有通向动作的路径。

要让 SmolVLA 自己做到,需要什么

需要代价
场景里同时放多只不同的杯子,用指令指定拿哪一只重新设计录制场景
每种指令都要有足够的示范数据量成倍增长(N 种杯子 × M 个位置)
指令措辞要有多样性,否则只会背下固定几句还要做指令改写/增广

这条路对我们的时间预算来说不现实。

★ 正确的做法:把语义放到策略外面 ★

让开放词表检测器提供语义泛化,策略只管闭合。
用户说「我想要高脚杯」
  ↓ 对话层(已在跑:人脸 / 语音 / 表情屏)解析出物体名
  ↓  OWLv2 用这个词当提示去找 ← 语义泛化在这里发生
  ↓ 深度 → 3D 坐标 → 编码移动到预抓取位姿
  ↓ SmolVLA 只做最后的合爪与提起(它不需要知道那是高脚杯)
关键在于:OWLv2 是开放词表的——换一个物体名不用改代码、不用重训、不用新数据。 而 SmolVLA 那一段对所有杯子是同一个动作,本来就不需要区分。
但要诚实标注三条:
① OWLv2 在我们数据上只测过「cup」这一个词(19/36 帧、100% 精度)。 换成 wine glass / red cup 没测过,必须重新过逐框人工看图。
② 高脚杯要抓杯身、不抓杯脚;透明+反光的杯子深度会失效,那时要贴 ArUco 兜底(depth-grasp.html 已有决策树)。
③ 这条链路依赖 2A 全部做完——所以「用户点单」这个演示效果,是 2A 的副产品,不是独立的一项。

结论:「用户说要什么就拿什么」是可以做到的,但它的能力来源是开放词表检测器,不是 SmolVLA。 这也反过来说明 2A 的价值——它不只是「换位置也能抓」, 它是让机器人能听懂点单的那条链路。

7. ★ 2A 动手之前必须先验的那一件事 ★

现役模型没见过「从预抓取位姿开始」这个起点。 它是从归位姿态开始的整段示范训练出来的。编码移动把手臂送到杯子跟前再交棒, 那个起始状态可能是分布外的。

验证方法,五分钟,零标定、零代码:把手臂手动摆到预抓取位姿(相当于编码移动已跑完), 指令串用右臂那句、speed 1.0,启动策略,看它接不接得上。

结果结论
能接上并抓住2A 成立,且不用重录数据——成本立刻少一大块
动作不连贯 / 原地试探起点确实分布外 → 必须按第 8 节重录(架构不变,数据要换)
完全不动 / 乱动先排查别的问题(指令串、speed、模型选择)
排序上的关键:不要先做标定。09-04 已经在手眼上花掉过半天且没成功。 这五分钟测试不需要任何标定,而它才是 2A 的真正前提。

8. 2A 的数据要怎么采(只有第 7 节测出「接不上」才需要)

现在的录制2A 的录制
每集怎么开始手臂在归位姿态,从头遥操作先由程序编码移到预抓取位姿,再开始遥操作
操作者做什么整段:接近 → 对准 → 合爪 → 提起只做最后一小段:微调 → 合爪 → 提起
每集时长15–25 秒约 3–5 秒
杯位要变(靠它撑覆盖范围)要变,而且更宽——但目的从「教泛化」变成「验证编码移动到处都准」
指令串右臂那一句要换一句新的,单独建 tasks.parquet
能不能和现有数据合并—❌ 不能,起始分布完全不同,必须新建数据集
相机头 424×240 + 双腕 640×480不变,但腕部相机重要性上升——定位交给深度后,策略主要看细节
好处:数据量需求大幅下降。策略要学的从「找杯子 + 规划整条轨迹」缩成「爪子已经对准时把它合上」。 参照 Depth Helps 的量级(每任务约 20 条真机轨迹), 这类窄任务通常几十集就够。但这是类比推断,不是我们实测。
★ 数据分界 ★2026-08-26 换过夹爪硬件(读数区间前 −13.6~65.0、后 0.3~59.2)。 新数据天然在换代后,但任何和旧数据的对照都要先确认是否跨 0826。

9. 训练链路的变化

10. 代码骨架(2A)

# 03-software/scripts/guided_grasp.py   (新文件,还不存在)
import arm_kinematics, policy_safety
from cup_locate_demo import locate_nearest          # 已有:深度 → 相机系 3D
from v4l2_depth import DepthCamera                  # 已有:裸 V4L2 读 Z16

# ── ① 看:深度帧 → 杯子在相机系的 (X, Y, Z),毫米
with DepthCamera(DEPTH_NODE) as cam:
    hit = locate_nearest(cam.read())
if hit is None:
    return "没找到杯子"                              # ← 必须有这个分支,不许瞎猜

# ── ② 换坐标系:相机系 → 臂基座系   ★ 唯一缺的一环,见第 5 节
y_base, z_base = camera_to_base(hit.X, hit.Y, hit.Z)

# ── ③ 退一点:不要直接怼到杯子上,留出预抓取距离
y_pre = y_base - PREGRASP_BACKOFF_M                 # 需要实测确定

# ── ④ IK:(y, z) → 关节角      已有,且已绕开上游 FK/IK 不自洽的坑
lift, elbow = arm_kinematics.inverse(y_pre, z_base)
pan = pan_from_lateral(hit.X)

# ── ⑤ 安全层:和试跑用的是同一套      已有
target = policy_safety.clamp({... lift, elbow, pan ...})

# ── ⑥ 送到手臂:和 run_policy_trials 同一个原语      已有
robot.send_action(target)

# ── ⑦ 交棒:策略接管,只做最后的闭合与提起   ★ 未测,见第 7 节
run_policy(...)
七步里五步是现成的。要写的只有 ②(第 5 节给了方案)、③ 的退让距离(要实测)、⑦ 的交棒时机。

11. 每条结论的证据等级

结论等级来源
IK 已有,且已绕开上游 FK/IK 不自洽(差 32.35°,过一遍偏 196 mm)读过源码arm_kinematics.py
发关节目标的原语已有读过源码XLerobot.send_action
安全层已接 arm_kinematics读过源码policy_safety.py
深度反投影已有,深度有效像素 0.88实测cup_locate_demo.py / 09-03 评估
OWLv2 对「cup」19/36 帧、100% 精度、1623 ms实测36 帧逐框人工看图
FT-DINOSAUR small@224 = 52.4 ms,出 7 个固定 slot(256 维)实测2026-09-05 本机 train310,N=50
合并集含 left / right 两条指令实测meta/tasks.parquet
右臂横向覆盖 35.1°实测合并集 202 集
SmolVLA 能否从预抓取位姿接上未测第 7 节,2A 的前提
几何路线 +84 MB / 零显存 / 3.56 ms本机实测2026-09-05,50 次平均
FT-DINOSAUR + SmolVLA 可同时驻留,剩 1844 MB本机实测2026-09-05,逐步加载测 RSS/显存
FT-DINOSAUR 接近阶段纯度 2.7× 基线、覆盖率中位 94%实测 + 人工看图印证9 帧,操作者判读与测量吻合
深度相机内参未标09-04 标的是彩色相机,不适用
OWLv2 对「wine glass」等新词的效果未测只测过「cup」
FT-DINOSAUR 的 slot 有没有分出杯子未过人工看图掩码图已生成,待核对
「几十集就够」类比推断Depth Helps 的量级,非我们实测

12. 一句话

Turn 1 零成本,只差跑对一次,那是演示的底线。 Turn 2 的两条路各解决一半泛化:2A 换位置、2B 换外观,都不是抓起来的前提。 而「用户说要高脚杯」这种交互,能力来源是开放词表检测器而不是 SmolVLA—— 它是 2A 的副产品。动 2A 之前,先花五分钟把手臂手动摆到预抓取位姿跑一次策略。