动作表示与策略头¶
VLA 最难的桥梁是:语言和图像是离散/语义的,机器人控制却是连续、实时、受约束的。动作表示决定了模型能不能把“理解”变成稳定动作。
1. 机器人动作到底是什么?¶
在不同系统中,“动作”可能表示不同控制接口:
| 动作接口 | 例子 | 特点 |
|---|---|---|
| 末端位姿增量 | \(\Delta x,\Delta y,\Delta z,\Delta r,\Delta p,\Delta y\) | 操作任务常用,跨机器人相对容易 |
| 关节位置 | \(q_1,\ldots,q_n\) | 和具体机器人强绑定 |
| 关节速度 | \(\dot{q}_1,\ldots,\dot{q}_n\) | 适合连续控制,但要注意积分漂移 |
| 力矩/力控制 | \(\tau_1,\ldots,\tau_n\) | 最底层,学习难度和安全风险高 |
| 夹爪命令 | open/close 或连续开合度 | 常作为独立维度 |
VLA 论文里常见的是“末端位姿增量 + 夹爪 + 终止信号”。例如每一步输出:
其中 \(g\) 是夹爪命令,\(e\) 是是否结束当前动作段。
1.1 先确定控制层级¶
设计动作空间前,先问:模型输出给谁?
或:
一般建议:
| 阶段 | 推荐动作空间 | 原因 |
|---|---|---|
| 新手桌面抓取 | 末端位姿增量 + 夹爪 | 最直观,跨机械臂较容易 |
| 固定机械臂项目 | 关节位置/速度 | 与底层控制接口一致 |
| 灵巧手 | 手指关节目标或低维手势 latent | 自由度高,直接末端表示不够 |
| 移动机器人 | 线速度/角速度 | 与底盘控制天然一致 |
| 人形机器人 | 分层动作:高层任务 + 局部控制器 | 全身自由度太高,端到端难度大 |
不要一开始就让 VLA 输出力矩
力矩控制最接近物理底层,但对模型、数据、安全要求都高。新手更适合从位置或速度接口开始。
1.2 姿态怎么表示?¶
机械臂末端动作常包含姿态变化。常见表示:
| 表示 | 维度 | 优点 | 缺点 |
|---|---|---|---|
| Euler 角 | 3 | 直观 | 有万向节锁,角度跳变 |
| 轴角 | 3 | 紧凑,适合小旋转增量 | 大角度时不直观 |
| 四元数 | 4 | 平滑,无万向节锁 | 需要单位化,双覆盖 |
| 6D rotation | 6 | 神经网络训练稳定 | 需要转换回旋转矩阵 |
桌面操作里经常使用“小姿态增量”:
如果任务需要大范围旋转或连续姿态插值,四元数或 6D rotation 会更稳。
2. 坐标系选择¶
同一个动作可以放在不同坐标系中表达:
| 坐标系 | 含义 | 适用场景 |
|---|---|---|
| 世界坐标系 | 相对桌面/房间不动 | 固定工作站、相机外参稳定 |
| 机器人基座坐标系 | 相对 base_link | 机械臂操作常用 |
| 末端坐标系 | 相对当前手爪方向 | 精细接近、插入、擦拭 |
| 相机坐标系 | 相对视觉观测 | 视觉伺服、多相机任务 |
坐标系不一致会直接毁掉训练
数据集中动作如果有的在世界系,有的在末端系,模型会看到同样画面对应完全不同的动作。训练前必须统一坐标系、单位、方向和动作尺度。
3. 离散动作 Tokenization¶
RT-2、OpenVLA 这类模型把连续动作变成 token,让模型像生成文字一样生成动作。
3.1 Binning¶
假设某个动作维度 \(x \in [-1,1]\),把它均匀切成 256 个 bin:
其中 \(N=256\)。模型输出 bin id 后,再反量化回连续值:
直觉上就是:
3.2 数值例子¶
假设某一维末端增量 \(\Delta x\) 的范围是 \([-0.05, 0.05]\) 米,也就是每步最多移动 5cm。现在专家动作是:
用 256 个 bin:
模型输出 token 153 后,反量化:
这说明动作 token 不是“文字”,而是“被离散化后的控制数值”。
3.3 多维动作如何变成 Token 序列?¶
如果动作是 7 维:
每一维都可以单独量化成一个 token:
如果一次预测未来 4 步 action chunk,序列会变成:
也就是 28 个动作 token。自由度越高、chunk 越长,自回归输出越慢,这也是连续动作头和 FAST 这类方法重要的原因。
3.4 优点¶
- 可以复用 LLM 的自回归训练方式。
- 动作 token 能和文本 token 放在同一个序列里。
- 实现简单,便于大模型微调。
3.5 缺点¶
- 量化会损失精度。
- 高频动作会产生很长 token 序列,推理慢。
- 每个维度独立分箱,可能忽略动作维度之间的相关性。
- 对灵巧手、双臂、全身控制这类高自由度系统不够优雅。
4. Action Chunking¶
逐步输出动作会遇到延迟问题。Action chunking 的做法是一次预测未来 \(H\) 步:
执行时可以滚动预测:
优点:
- 减少高层模型调用频率。
- 动作更平滑。
- 适合较慢的大模型推理。
风险:
- 如果中途环境变化,后面几步可能过期。
- chunk 太长会降低反应速度。
- chunk 太短则无法解决延迟问题。
5. 连续动作头:Diffusion 与 Flow¶
现代 VLA 越来越常用连续动作头,尤其是需要高频、平滑、灵巧控制的任务。
这里的“连续动作头”可以先理解成:视觉语言模型负责理解图像和指令,动作头负责把这种理解变成一段实数动作。
其中动作块通常不是一个动作,而是未来一小段轨迹:
\(H\) 是 chunk 长度,\(D\) 是每一步动作维度。例如末端位姿增量加夹爪可能是 \(D=7\),如果一次预测 8 步,就是一个 \(8 \times 7\) 的连续矩阵。
为什么不直接用一个 MLP 回归这个矩阵?
普通回归通常学的是“平均动作”。如果同一个状态下有多种合理做法,例如从杯子左侧绕过去或从右侧绕过去,MSE 会倾向于预测两条轨迹的平均值。这个平均值在数学上可能 loss 很低,但在物理上可能正好撞到杯子。
Diffusion 和 Flow 的核心动机就是:不要只预测一个平均答案,而是学习一个动作分布。
Robot Policy
│
Observation → Action Chunk
│
┌───────────┼───────────┐
│ │ │
Diffusion Flow Matching Autoregressive
│ │ │
去噪生成 速度场生成 Token生成
│ │ │
Continuous Continuous FAST
Action Action │
│
Action Tokenizer
5.1 Diffusion Policy¶
扩散策略把动作序列看成要生成的数据。它和图像生成里的 diffusion 很像,只不过生成对象不是图片像素,而是机器人未来几步动作。
假设专家数据里有真实动作块 \(a^0\)。训练时,我们随机选一个噪声等级 \(k\),往真实动作上加噪声:
其中:
- \(a^0\) 是干净的专家动作块。
- \(a^k\) 是被污染后的动作块。
- \(\epsilon\) 是高斯噪声。
- \(k\) 表示扩散步数,\(k\) 越大,动作越接近纯噪声。
- \(o,l\) 分别表示视觉观测和语言指令。
模型学习的问题是:给你一个带噪声的动作块、当前观测、语言指令和噪声等级,请你把噪声找出来。
训练 loss 常写成:
直觉上,它不是直接问模型“正确动作是什么”,而是问:
推理时没有专家动作,所以从一个纯噪声动作块开始:
每一步都用当前图像和语言指令作为条件。最后得到的不是 token 序列,而是一整段连续控制轨迹。
5.1.1 一个抓取例子¶
假设任务是“拿起桌上的红色积木”,真实动作块可能长这样:
Diffusion 训练时会把这 5 步动作整体加噪声,让模型学习如何把“乱七八糟的 5 步动作”恢复成“接近、下降、夹取、抬起”的轨迹。
这点很重要:它生成的是动作序列的整体形状,而不是每一步孤立预测。
5.1.2 为什么 Diffusion 适合机器人?¶
机器人动作经常有多峰性:
这些都可能是合理专家动作。普通 MSE 回归容易把它们平均掉;diffusion 更像是在条件分布中采样一条完整轨迹,所以更适合表示“多种都对”的情况。
优点:
- 适合多峰动作分布,例如同一个目标可以从左边或右边抓。
- 输出连续轨迹,动作平滑。
- 在机器人模仿学习中效果很好。
- 可以和 action chunking 自然结合,一次生成未来多步。
缺点:
- 多步去噪会增加推理成本。
- 实时控制时要优化采样步数。
- 采样步数太少时动作质量可能下降。
- 模型还需要低层控制器处理限幅、碰撞和安全问题。
5.2 Flow Matching¶
Flow matching 学习从简单分布到动作分布的连续变换。\(\pi_0\)、SmolVLA 等模型使用这类思路来生成连续动作。
如果说 diffusion 像是“从噪声里一步步擦出动作”,flow matching 更像是“学习一条把噪声搬运成动作的速度场”。
先定义两个点:
- \(x_0\):从简单分布采样的噪声动作块。
- \(x_1\):数据里的真实专家动作块。
然后在它们之间取一个中间时刻 \(\tau \in [0,1]\):
当 \(\tau=0\) 时,\(x_\tau\) 是噪声;当 \(\tau=1\) 时,\(x_\tau\) 是真实动作。模型要学的是在中间任意位置,应该朝哪个方向流动:
也就是:
推理时,从随机噪声动作块 \(x_0\) 出发,沿着模型预测的速度场积分:
最后到 \(\tau=1\) 附近,就得到一个可执行的连续动作块。
5.2.1 Diffusion 和 Flow 的关系¶
两者都在做“从简单分布到动作分布”的生成,只是学习目标不同:
| 方法 | 学什么 | 推理直觉 |
|---|---|---|
| Diffusion | 学怎么去掉噪声 | 从纯噪声开始反复去噪 |
| Flow Matching | 学速度场/流方向 | 从噪声沿着路径流到动作 |
Flow matching 常被认为采样路径更直接,工程上可能用更少的步数生成动作。但它仍然需要多步积分,所以并不是完全没有推理成本。
5.2.2 为什么 VLA 喜欢 Flow?¶
VLA 的 backbone 往往已经很大,如果动作头也需要很多自回归 token 或很多 diffusion steps,实时性会很吃紧。Flow 类方法的吸引力在于:
- 输出是连续动作,不需要逐维离散化。
- 能生成一整段 action chunk。
- 比普通 MLP 更能表达复杂动作分布。
- 采样过程通常比长 token 序列更适合高频控制。
可以把它理解成介于“简单连续回归”和“复杂扩散采样”之间的一类生成式动作头。
5.3 FAST¶
FAST(Frequency-space Action Sequence Tokenization)严格说不是 diffusion/flow 这种连续动作头,而是“更聪明的动作 tokenization”。它放在这里,是因为它解决的也是高频动作序列难生成的问题。
控制频率越高,平滑信号相邻 timestep 的变化越小,相邻 action token 的相关性越强,next-token objective 中新增信息量下降;模型甚至可能落入“复制最近动作”的差局部最优。
普通动作 tokenization 是逐时间步、逐维度离散化:
问题是动作序列很长,而且相邻时间步高度相关。比如一段平滑接近动作:
逐点 tokenization 会把每个数都单独编码,但其实这段轨迹主要表达的是“缓慢向前移动”。
FAST 的思路是:先把时间序列从时域变到频域。频域里不直接描述“每一帧动作是多少”,而是描述:
常用工具是离散余弦变换(DCT)。对一个动作 chunk 做 DCT 后,会得到一组频率系数:
低频系数控制整体形状,例如向前、下降、抬起;高频系数控制快速变化,例如手指细微调整、灵巧手接触瞬间的动作变化。
然后再对这些频率系数做 tokenization。这样模型不必一个时间点一个时间点地拼动作,而是在更压缩的频域里生成整段动作。
总结:先把整个动作序列压缩成“运动频率结构”,再 Token 化。
5.3.1 一个直觉例子¶
假设某一维动作是“夹爪逐渐闭合”:
它的主要信息是一个平滑上升趋势。频域表示可以用少量低频系数表达这个趋势。
如果动作是“接触物体时快速抖了一下”:
那就需要更多高频系数来描述这个突然变化。
这就是为什么 FAST 对灵巧动作有意义:灵巧手和双臂协作里经常既有整体运动,又有局部高频细节。
5.3.2 FAST 和普通动作 token 的区别¶
| 方法 | 编码对象 | 优点 | 代价 |
|---|---|---|---|
| 普通 tokenization | 每个时间步的每个动作维度 | 简单直观 | 序列长,重建高频动作困难 |
| FAST | 动作 chunk 的频率系数 | 更压缩,更适合长 chunk | 需要频域变换和反变换 |
推理时,模型生成的不是直接动作值,而是频域 token。系统需要先把 token 还原成频率系数,再通过逆 DCT 还原成时域动作序列。
所以 FAST 的关键不是“动作变连续了”,而是“用更适合序列压缩的方式离散化动作”。
怎么选动作头?
如果你主要读 OpenVLA/RT-2,先学离散 token;如果你要做平滑操作、双臂或灵巧手,尽早学习 diffusion/flow;如果你关心大模型自回归和高频动作的结合,就看 FAST。
可以用一个简单判断:
| 需求 | 更适合的动作头 |
|---|---|
| 复用 LLM 生成范式,方便微调 | 离散动作 token |
| 动作维度低,任务简单 | 连续 MLP 回归 |
| 同一状态有多种合理动作 | Diffusion / Flow |
| 需要平滑、高频、长 chunk 控制 | Diffusion / Flow / FAST |
| 想在自回归模型里更高效地产生长动作序列 | FAST |
6. 动作头的训练损失¶
不同动作表示对应不同 loss:
| 动作头 | 输出 | 常用 loss | 直觉 |
|---|---|---|---|
| 离散 token | 每一维的 bin/token | Cross Entropy | 预测正确 token |
| 连续回归 | 实数动作 | MSE / L1 | 让动作数值接近专家 |
| Gaussian policy | 均值和方差 | Negative Log Likelihood | 学动作分布和不确定性 |
| Diffusion Policy | 去噪动作序列 | diffusion denoising loss | 从噪声恢复专家轨迹 |
| Flow Matching | 速度场/流 | flow matching loss | 学从噪声到动作的连续变换 |
低 loss 不等于能执行
离线 loss 低,只说明模型在数据分布上像专家。真正执行时,模型自己的动作会改变下一帧观测,状态分布可能偏离专家轨迹,这就是行为克隆的复合误差。
7. 低层控制器仍然重要¶
VLA 输出的动作通常不是直接打到电机力矩上,而是送到低层控制器:
graph LR
A[VLA 输出末端增量] --> B[运动学/限幅/滤波]
B --> C[IK 或轨迹生成]
C --> D[关节位置/速度控制器]
D --> E[电机驱动]
必须处理:
- 关节限位
- 速度和加速度限幅
- 碰撞检测
- 奇异位形
- 夹爪力限制
- 急停和人工接管
端到端学习不等于把安全交给神经网络。真正上机器人时,传统控制层是最后一道边界。
8. 实践检查清单¶
训练或调试 VLA 前,先确认:
- 动作单位统一:米、弧度、秒。
- 坐标系统一:base、world、eef、camera 不混用。
- 动作范围合理:不要让极端值主导归一化。
- 夹爪命令清晰:开/合/保持是否可区分。
- 控制频率匹配:模型频率、数据频率、底层控制频率一致或可重采样。
- 有限幅和安全层:模型输出异常时不会撞机。
- 姿态表示连续:避免 Euler 角在边界附近跳变。
- 反归一化正确:模型输出 token/归一化动作后能还原到底层控制单位。