3D-VLA 方法原理详解
方法想解决什么问题
传统视觉语言动作模型常见做法是:
输入当前图像和语言指令。
模型直接输出动作。
机器人按动作执行。
这种方式有一个核心缺陷:模型容易只在二维图像空间里“看起来懂了任务”,但并没有显式建立三维物理世界的状态变化。例如“把薯片袋拿出来”“关上抽屉”“把钱放进保险柜”这些任务,不只是识别物体,还需要理解:
物体在三维空间中的位置。
当前状态和目标状态有什么差别。
哪些物体会移动,哪些环境结构要保持。
动作执行后世界应该变成什么样。
3D-VLA 的核心思想是:不要让模型直接从当前观察跳到动作,而是先让模型具备“想象目标状态”的能力。也就是先回答:
如果这个指令完成了,世界应该长什么样?
这个“目标世界”可以是目标 RGB 图像、目标 RGB-D 图像,也可以是目标点云。然后再基于当前状态和目标状态生成机器人动作。
因此 3D-VLA 的方法可以概括为:
用 3D 场景表示作为语言模型的输入,让语言模型在文本 token、3D token、目标生成 token 和动作 token 之间推理;当它需要预测未来状态时,调用 embodied diffusion model 生成目标图像或目标点云;最终将当前状态、目标状态和任务意图转化为机器人动作 token。
- 整体框架
3D-VLA 由三类能力组成:
3D Vision-Language-Action Model
这是中枢模型。它基于 3D-LLM / BLIP2 / Flan-T5 的思想,把三维场景特征转成语言模型能读的 token embedding,并输出自然语言、目标生成请求或动作 token。
Embodied Diffusion Models
这是“目标想象器”。输入当前状态和语言指令,生成任务完成后的目标状态。仓库中包含两种:
Goal Image LDM:生成目标 RGB 或 RGB-D 图像。
Goal Point Cloud Diffusion Model:生成目标点云。
Robot Control Tokenization
这是“动作接口”。机器人动作被离散成语言模型能输出的特殊 token,例如位置 token、旋转 token、夹爪开合 token 和动作分隔 token。语言模型通过生成 token 序列来表示一串机器人控制命令。
整体数据流如下:
当前多视角/RGB-D观察
|
v
3D特征提取与点云/体素表示
|
v
Q-Former压缩为少量3D scene tokens
|
v
3D Vision-Language-Action LLM
|
±-> 输出目标生成请求 token
| |
| v
| Goal Image / Point Cloud Diffusion Model
| |
| v
| 生成目标图像或目标点云
|
±-> 输出动作 token
|
v
解码成机器人动作
为了避免这个流程过于抽象,下面用一个具体任务走一遍。
示例任务:
用户指令: close bottom drawer
当前观察: 机器人看到一个柜子,底层抽屉是打开的;系统已有当前场景点云 start_pc
目标结果: 底层抽屉应该被关上,生成对应目标点云 goal_pc,并进一步产生关抽屉动作
对应的数据流可以展开成:
-
传感器/数据集给出当前状态
RGB-D / 多视角图像 / 点云
start_pc = [N, 6]
每个点包含 [x, y, z, r, g, b]| v -
构建 3D 场景表示
从当前状态中采样固定数量的点,例如 2048 或 8192 个点。
坐标做归一化,颜色/语义特征保留。
如果走 3D-VLA LLM,则还会有 pc_feat = [N, 1408] 的点级特征。| v -
Q-Former 把大量 3D 点压缩成 scene tokens
输入:
pc_feat: [1, T, N, 1408]
pc: [1, T, N, 3]输出:
scene_tokens: [1, T, 32, hidden_dim]这些 scene tokens 会插入到文本里的 位置。
| v -
3D-VLA LLM 理解任务并产生中间意图
输入文本可以理解为:
“The initial scene is . close bottom drawer”插入 scene tokens 后,LLM 看到的不是纯文本,而是:
文本 token + 当前 3D 场景 embedding方法级输出可能是:
“I should close bottom drawer ”这表示模型决定先生成一个“抽屉关闭后”的目标点云。
| v -
Goal Point Cloud Diffusion 生成目标状态
输入:
start_pc: 当前点云 [1, 6, N]
instruction: “close bottom drawer”
x_T: 随机噪声目标点云 [1, 6, N]扩散模型每一步预测噪声:
model_input = concat(x_t, start_pc) # [1, 12, N]
noise_pred = transformer(model_input, timestep, text=“close bottom drawer”)
x_{t-1} = scheduler.step(noise_pred, x_t)输出:
goal_pc: 预测的关闭抽屉后点云 [1, 6, N]| v -
当前状态和目标状态一起形成控制上下文
这里不能理解成“只把 goal_pc 直接丢给 action head”。
action 预测至少需要三类信息:- 当前执行场景: 机器人现在面对的 3D 状态,也就是 current_scene / start_pc。
- 目标或意图上下文: goal_pc、goal_image,或由它们重新编码出的 goal_scene_tokens。
- 执行提示: 例如 “Execute now.”,告诉 LLM 当前要从理解/想象阶段切换到动作输出阶段。
在方法图里,Robot Control 阶段画的是:
User: [embed] Execute now.这个 [embed] 可以理解为用于控制的 3D 上下文 embedding。
它通常应表达“现在在哪里、要达到什么状态”这类信息,而不是裸目标状态本身。一种更清楚的控制输入写法是:
“Current scene: . Goal scene: . Execute now.”输出动作 token:
<aloc…><aloc…><aloc…><arot…><arot…><arot…><gripper…><ACT_SEP>…| v -
动作 token 解码成机器人控制量
<aloc*> -> 末端执行器位置
<arot*> -> 末端执行器姿态
<gripper*> -> 夹爪开合
<ACT_SEP> -> 动作步之间的分隔最终得到一段关上底层抽屉的控制轨迹。
如果走 goal image 分支,步骤 5 换成:
输入:
当前图像 image
指令 “close bottom drawer”
随机图像 latent x_T
扩散过程:
model_input = concat(noisy_goal_image_latent, current_image_latent)
noise_pred = UNet(model_input, timestep, text=“close bottom drawer”)
输出:
goal_image = 关闭底层抽屉后的目标图像
所以“整体数据流”真正表达的是:3D-VLA 先把当前世界编码成 LLM 能读的 scene tokens;LLM 决定任务需要什么目标状态;扩散模型生成这个目标状态;最后把当前执行场景、目标/意图上下文和 Execute now 这类执行提示一起作为控制输入,生成动作 token。它不是一条单纯的图像到动作流水线,而是一条带有“目标想象”中间环节的世界模型流水线。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)