本文档属于 Robotics Tutorial 项目,作者:Pengfei Guo,达妙科技。采用 CC BY 4.0 协议,转载请注明出处。
D04 双臂学习——ACT/ALOHA 底层分析、RDT-1B 与 Bimanual RL¶
本章定位:本章是双臂协同理论与规划(D01-D04)的收官之作,从"规则驱动的双臂协调"转向"数据驱动的双臂学习"。前三章(D01 任务分类、D02 协调规划、D03 协调力控)建立了双臂操作的几何-动力学-力学基础,但现实中大量双臂任务(折叠衣物、烹饪、电缆布线)的接触模式极其复杂,难以用解析模型穷举描述。本章正是要解决"当模型不够用时,如何从数据中学习双臂协调策略"这一核心问题。
适用范围:ACT/Diffusion Policy 等模仿学习方法对任何多关节机器人均适用;双臂 action space 设计、数据采集系统架构是通用问题。但双臂特有的对称性利用、协调 reward 设计、内力学习是本章独有内容。
前置依赖:D03(双臂力控——内力/协调阻抗概念)、F09(学习型力控——RL+阻抗基础概念)、复合机器人方向(ACT/Diffusion Policy 基本架构概念)
下游章节:D08(遥操作数据采集系统底层分析)、D09(双臂 MoveIt2 系统集成)、D10(综合实战 Mini-DualArm)
建议用时:2 周(15-25 小时)
前置自测 ⭐¶
📋 答不出 >= 2 题 → 先回前置章节复习
| 编号 | 问题 | 答不出时回顾 |
|---|---|---|
| 1 | 双臂内力定义:什么是双臂协调操作中的"内力"\(f_{int}\)?它与外力 \(f_{ext}\) 的区别是什么?为什么内力不做功却对抓取稳定性至关重要? | D03 双臂协调力控 |
| 2 | RL 基础:写出 MDP 五元组 \((S, A, P, R, \gamma)\)。在机械臂控制中,状态空间 \(S\) 和动作空间 \(A\) 通常包含哪些量? | F09 学习型力控 |
| 3 | 模仿学习 vs 强化学习:Behavioral Cloning (BC) 为什么会有 compounding error 问题?DAgger 如何缓解? | F09 学习型力控 |
| 4 | Transformer 注意力:Self-attention 的计算复杂度是什么?为什么 Transformer 天然适合处理序列到序列的映射? | 深度学习基础 |
| 5 | 阻抗控制与位置控制:在机器人接触环境时,位置控制和阻抗控制的根本区别是什么?阻抗控制器的输出是什么? | F01 阻抗导纳二分法 |
本章目标¶
学完本章后,你应该能够:
- 深入理解 ACT/ALOHA 的底层控制选择——为什么 ALOHA 选位控而非阻抗,从硬件限制、延迟、被动柔顺三个角度严格论证
- 掌握 ACT 的三个核心创新(action chunking、CVAE 潜变量 z、temporal ensembling)的数学推导和工程实现
- 理解 RDT-1B 的 128 维统一 action space 设计哲学,以及 6D 旋转表示为何优于四元数和欧拉角
- 分析 bimanual RL 的特殊挑战——14 维动作空间的探索困难、对称/非对称 reward 设计、内力学习
- 实现 在 robosuite TwoArmLift 中训练双臂 RL 策略,对比不同 action space 的样本效率
- 批判性评估 当前双臂学习方法的瓶颈与前沿突破方向
1. 从规则到数据——双臂学习的动机与全景 ⭐¶
1.1 为什么 D01-D03 的方法不够用¶
回顾 D01-D03:我们建立了双臂操作的完整解析框架——D01 给出了任务分类(独立/协调/对称)、D02 给出了协调规划(主从/虚拟物体/图搜索)、D03 给出了协调力控(扩展阻抗/内力-外力分解)。在那里我们用解析方法解决了"两个手臂如何协调完成刚性物体的搬运和装配"。
但考虑以下任务:
| 任务 | 解析方法的困难 | 为什么需要学习 |
|---|---|---|
| 折叠衣物 | 布料是无穷维软体,接触模式不可穷举 | 从人类演示中学习"在哪里抓、怎么折" |
| 烹饪(翻炒) | 食材的形状/粘度/温度不断变化 | 学习视觉-力-动作的闭环策略 |
| 电缆布线 | 细长柔性体的动力学极难建模 | 学习"拉-松-绕"的时序协调 |
| 双臂灵巧装配 | 配合面微米级精度,接触力非线性 | 学习力反馈驱动的微调策略 |
| 辅助穿衣 | 人体柔软且运动不可预测 | 学习安全的力-位协调 |
本质洞察:D01-D03 的解析框架假设"任务可以用有限个模式和参数描述"。当任务涉及的接触模式是连续的、高维的、或随环境变化的,解析方法就需要无穷多个 if-else 分支——此时数据驱动方法的优势在于:让数据本身编码这些"模式",而非由工程师手写规则。
反事实推理:如果我们坚持用 D03 的协调阻抗控制做衣物折叠会怎样?
首先,我们需要建立布料的物理模型——这需要有限元方法(FEM)或质点-弹簧系统,计算量在实时控制中不可承受。其次,即使有了模型,每次折叠的起始状态(布料的初始构型)都不同,需要在线重新规划接触序列。最后,布料与手指的摩擦模型高度非线性——滑动/滚动/剥离模式的切换使得 D03 的线性阻抗模型完全失效。
结论:不是 D01-D03 的方法"不好",而是它们适用于**几何-力学关系可解析描述的场景**(如刚性物体搬运、螺栓拧紧)。对于**接触模式复杂、环境不确定性大**的场景,学习方法是必要的补充。
1.2 双臂学习的三大范式¶
双臂学习可以从三个维度分类理解:
维度 1:学习信号来源
| 范式 | 信号来源 | 代表工作 | 优势 | 劣势 |
|---|---|---|---|---|
| 模仿学习 (IL) | 人类演示 | ACT/ALOHA, Diffusion Policy | 样本效率高(50 demos);自然处理多模态 | 依赖数据质量;泛化受限 |
| 强化学习 (RL) | 奖励函数 | PPO+双臂 MDP, SAC+阻抗 | 可发现超人策略;不需演示 | 探索困难(14D+);奖励设计难 |
| 混合方法 | 演示+奖励 | 演示初始化+RL微调 | 兼顾效率和性能 | 工程复杂度高 |
维度 2:策略架构
| 架构 | 核心思想 | 代表 | 输入→输出 |
|---|---|---|---|
| Transformer BC | 自回归/CVAE 预测 action chunk | ACT | obs → \([a_t, ..., a_{t+k}]\) |
| Diffusion Policy | 条件扩散模型生成动作序列 | Chi et al. 2023 | obs → 去噪 \(a_{0:K}\) |
| 大规模基础模型 | 预训练+微调范式 | RDT-1B, Octo | (img, lang, state) → 128D action |
| 标准 RL | Actor-Critic / Policy Gradient | PPO, SAC | state → action (per step) |
维度 3:Action space 设计(双臂特有)
| 设计 | 描述 | 维度 | 适用场景 |
|---|---|---|---|
| 关节独立 | \(a = [q_L, q_R]\) | 14D (7+7) | 独立任务 |
| 笛卡尔独立 | \(a = [x_L, x_R]\) | 12D (6+6) | 无内力协调需求 |
| 相对+绝对 | \(a = [x_{abs}, \Delta x_{rel}]\) | 12D | 协调任务 |
| 分层 | 高层选子任务,低层执行 | 可变 | 复杂长程任务 |
跨领域类比:双臂学习中 action space 的设计类似于自然语言处理中 tokenizer 的选择。就像 BPE/WordPiece 把连续文本切割成合适粒度的 token 以平衡词表大小和语义完整性,action space 设计也是在平衡控制精度(维度越高越精确)和学习效率(维度越低越易探索)。选错 tokenizer 会让模型"看不懂"输入,选错 action space 会让策略"学不会"协调。
1.3 科研发展脉络¶
| 年份 | 论文 | Venue | 核心贡献 |
|---|---|---|---|
| 2020 | Chitnis, Tulsiani, Gupta, "Efficient Bimanual Manipulation Using Learned Task Schemas" | ICRA 2020 | 任务 schema 作为 RL 动作空间;降低双臂探索维度 |
| 2023 | Chi et al., "Diffusion Policy: Visuomotor Policy Learning via Action Diffusion" | RSS 2023 | 条件扩散模型生成动作序列;双臂 ALOHA 基线 |
| 2023 | Zhao, Kumar, Levine, Finn, "Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware" (ACT/ALOHA) | RSS 2023 | ACT + ALOHA 硬件;50 demos 达 80-90% 成功率 |
| 2024 | Fu, Zhao, Finn, "Mobile ALOHA: Learning Bimanual Mobile Manipulation" | CoRL 2024 | ALOHA + 移动底盘;16 维 action;co-training 范式 |
| 2024 | Grotz, Shridhar, Asfour, Fox, "PerAct2: Benchmarking and Learning for Robotic Bimanual Manipulation" | CoRL 2024 | 语言条件双臂 benchmark;13 任务 \(\times\) 23 变体 |
| 2023 | Grannen et al., "Stabilize to Act: Learning to Coordinate for Bimanual Manipulation" | CoRL 2023 | 显式"stabilizer + actor"双臂分工建模 |
| 2025 | Liu et al., "RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation" | ICLR 2025 | 1.2B DiT 双臂扩散基础模型;128 维统一 action space |
2. ALOHA 硬件与底层控制深度解析 ⭐⭐¶
2.1 ALOHA 系统架构总览¶
在深入学习算法之前,必须先理解 ALOHA 的硬件——因为**底层控制的选择直接决定了上层学习算法的 action space 设计**。这是硬件与算法 co-design 的典范案例。
ALOHA(A Low-cost Open-source Hardware System for Bimanual Teleoperation)系统由四个 WidowX/ViperX 250 机械臂组成:两个 leader(操作者手持)和两个 follower(执行端)。
ALOHA 物理架构
═══════════════════════════════════════════════════
操作者(人类) 执行端(任务空间)
┌──────────┐ ┌──────────┐
│ Leader-L │──RS-485──→ │Follower-L│
│ (WidowX) │ 50 Hz │ (ViperX) │
└──────────┘ └──────────┘
↑ USB/U2D2
┌──────────┐ │ ┌──────────┐
│ Leader-R │──RS-485──→ │Follower-R│
│ (WidowX) │ 50 Hz │ (ViperX) │
└──────────┘ └──────────┘
│
┌─────┴──────┐
│ 主控 PC │
│ Python 50Hz │
│ + 相机录制 │
└────────────┘
硬件规格:
| 参数 | Leader (WidowX 250) | Follower (ViperX 300) |
|---|---|---|
| 自由度 | 6 DOF + 1 夹爪 | 6 DOF + 1 夹爪 |
| 执行器 | Dynamixel XM430/XM540 | Dynamixel XM430/XM540 |
| 通信 | U2D2 USB-RS485 | U2D2 USB-RS485 |
| 波特率 | 3 Mbps | 3 Mbps |
| 力传感器 | 无 | 无 |
| 编码器分辨率 | 4096 步/圈 | 4096 步/圈 |
| 重复精度 | ~1 mm | ~1 mm |
| 成本 | ~$3,000/对 | ~$3,000/对 |
2.2 为什么选位置控制——三重论证¶
关键事实:ALOHA 底层是**纯位置控制**,不是阻抗控制。
论文 p.5 明确写道:"all actuators to position control mode, where the underlying proprietary PID controller tracks the position target at >1 kHz."
这不是技术妥协,而是经过仔细权衡的设计决策。让我们从三个角度严格论证。
论证 1:硬件限制——无力测量能力
回顾 F01:阻抗控制的核心方程 \(\tau = J^T(\Lambda \ddot{x}_d + D\dot{e} + Ke + f_{ext})\) 中,\(f_{ext}\) 是外力测量。
Dynamixel X 系列执行器没有独立的力/力矩传感器(F/T sensor)。理论上可以从电流间接估算扭矩:
其中 \(K_t\) 是力矩常数。但这个估算存在严重问题:
| 误差来源 | 量级 | 影响 |
|---|---|---|
| 电流测量噪声 | \(\pm 50\) mA | 对应 \(\pm 0.5\) Nm 力矩噪声 |
| 齿轮箱摩擦 | 效率 ~70-85% | 实际力矩与电流不成线性关系 |
| 温度漂移 | \(K_t\) 变化 ~5% | 长时间运行后估算偏移 |
| 带宽限制 | ~100 Hz | 无法捕捉高频接触瞬态(需 >500 Hz) |
反事实推理:如果不顾这些限制,强行用电流估扭矩做阻抗闭环会怎样?
力矩噪声 \(\pm 0.5\) Nm 对应在末端(臂长 ~0.3 m)约 \(\pm 1.7\) N 的力误差。考虑到 ALOHA 的典型操作力在 1-5 N 范围,这意味着力控精度只有 \(\pm 30\%\) 到 \(\pm 100\%\)——这不是"不够好",而是**完全不可用**。阻抗控制器会因为力测量噪声持续注入能量,在硬接触时产生自激振荡。
论证 2:延迟最小化——遥操作的核心需求
Leader-Follower 映射的数据流极其简洁:
这是关节空间的直接映射(1:1 线性),不需要任何逆运动学计算、动力学补偿或力反馈环路。整个通信链路的延迟为:
延迟分解(位置控制模式)
========================================
Dynamixel sync_read: ~0.8 ms (8 关节批量读)
Python 处理 + calibration: ~0.1 ms
Dynamixel sync_write: ~0.8 ms (8 关节批量写)
────────────────────────────────────
总延迟(软件侧): ~1.7 ms
电机内部 PID 响应: ~1 ms (1 kHz PID)
────────────────────────────────────
端到端延迟: ~2.7 ms
如果加入阻抗控制环路,需要额外计算:
额外延迟(阻抗控制模式)
========================================
力/力矩估算: ~0.5 ms (电流读取+滤波)
雅可比计算 J(q): ~0.2 ms
动力学补偿 M, C, g: ~0.5 ms (Pinocchio RNEA)
阻抗律计算: ~0.1 ms
────────────────────────────────────
额外延迟: ~1.3 ms → 总延迟增加 ~50%
对遥操作而言,延迟直接影响操作者的手感和控制精度。回顾 D05 将介绍的 Ferrell 1965 经典研究:当延迟超过 ~50 ms 时,人类操作者的任务完成时间会急剧增加。ALOHA 的位置控制模式在 2.7 ms 延迟下提供了几乎即时的响应,这对精细遥操作至关重要。
论证 3:被动柔顺已满足需求
Dynamixel 的行星齿轮箱提供了一定程度的 backdrivability(反向驱动性),加上较低的 PID 增益(出厂默认),系统具有"足够的被动柔顺"来吸收操作中的不确定性:
- 论文 Figure 4c 显示:RAM 插入任务中位置跟踪误差峰值 ~1 cm
- 这 1 cm 恰好是被动柔顺在容忍装配误差
- 对于 ALOHA 的目标任务(折叠、夹取、移动物体),1 cm 的柔顺余量已经足够
本质洞察:ALOHA 的位置控制选择不是"因为便宜所以将就",而是**在遥操作+模仿学习范式下的最优工程权衡**。位控最大化了遥操作的低延迟和直觉性,而接触柔顺性的不足由学习算法(ACT 的 action chunking + temporal ensembling 提供运动平滑性)和任务选择(避免高精度力控任务)来弥补。这是一个系统级的 co-design 决策。
2.3 Leader-Follower 映射的精确实现¶
# aloha_scripts/robot_utils.py 简化版
# 完整数据流:Dynamixel sync_read → 标定偏置 → sync_write → 电机 PID
import dynamixel_sdk as dxl
DT = 0.02 # 50 Hz Python 控制循环
class ALOHATeleop:
def __init__(self, leader_ids, follower_ids, port, baudrate=3_000_000):
self.leader_ids = list(leader_ids)
self.follower_ids = list(follower_ids)
self.port = dxl.PortHandler(port)
self.packet = dxl.PacketHandler(2.0) # Protocol 2.0
self.port.openPort()
self.port.setBaudRate(baudrate)
# GroupSyncRead: 批量读取 Present_Position (地址 132, 4 bytes)
self.sync_read = dxl.GroupSyncRead(
self.port, self.packet, 132, 4)
for id in self.leader_ids:
self.sync_read.addParam(id)
# GroupSyncWrite: 批量写入 Goal_Position (地址 116, 4 bytes)
self.sync_write = dxl.GroupSyncWrite(
self.port, self.packet, 116, 4)
# 标定偏置: leader 与 follower 同型号同速比时为常数
self.calibration_offset = self.compute_calibration()
def teleop_step(self):
"""单步遥操作映射——整个环路 < 2 ms"""
# 1. 批量读取 leader 关节位置 (4096 步/圈编码器)
self.sync_read.txRxPacket()
leader_pos = [self.sync_read.getData(id, 132, 4)
for id in self.leader_ids]
# 2. 减去标定偏置 (leader 与 follower 零位不同)
target_pos = [lp - offset
for lp, offset in zip(leader_pos, self.calibration_offset)]
# 3. 写入 follower 目标位置
for id, pos in zip(self.follower_ids, target_pos):
param = [dxl.DXL_LOBYTE(dxl.DXL_LOWORD(pos)),
dxl.DXL_HIBYTE(dxl.DXL_LOWORD(pos)),
dxl.DXL_LOBYTE(dxl.DXL_HIWORD(pos)),
dxl.DXL_HIBYTE(dxl.DXL_HIWORD(pos))]
self.sync_write.addParam(id, param)
self.sync_write.txPacket()
self.sync_write.clearParam()
# 4. 夹爪: 离散控制 (全开/全闭)
# 手柄按钮 → GPIO → 数字信号 → 夹爪 goal_position
gripper_target = self.read_gripper_button()
self.set_gripper(gripper_target)
关键工程细节:
| 细节 | 说明 | 为什么重要 |
|---|---|---|
| Protocol 2.0 | 支持 sync_read/sync_write 批量通信 | 8 个电机单次通信 vs 8 次串行通信 |
| 波特率 3 Mbps | RS-485 最高速率 | 保证 50 Hz 下通信不拥塞 |
| 1:1 关节映射 | Leader WidowX 与 Follower ViperX 关节结构相同 | 不需要运动映射计算(D08 将讨论异构映射) |
| 50 Hz Python | Python GIL + time.sleep(DT) 控制频率 | 足够遥操作(人手带宽 <10 Hz);比 C++ 开发快 |
| 无力反馈 | Non-bilateral:单向位置映射 | 见 D05 分析:50 Hz 下力反馈的 Z-width 不足 |
2.4 从 ALOHA 到 Mobile ALOHA¶
Mobile ALOHA(Fu et al., CoRL 2024)在原始 ALOHA 基础上增加了移动底盘,将 action space 从 14D 扩展到 16D:
其中 \(v_{base}\) 和 \(\omega_{base}\) 分别是底盘的线速度和角速度。
**Co-training 范式**的核心创新:
训练数据构成:
┌──────────────────────────────┐
│ 50 人工遥操作 episodes │ ← 目标任务(如煮虾)
│ + 数千仿真/开源 episodes │ ← 非目标任务(RT-2 数据等)
└──────────────────────────────┘
↓ 联合训练
ACT policy(共享骨干)
↓
50 demos 任务成功率: 60% → 90%
为什么 co-training 有效? 直觉上,大量非目标任务数据帮助学习了通用的"机器人运动先验"——低级运动技能(如平滑轨迹、避碰)是跨任务共享的,只有高级任务语义是特定的。这与 NLP 中预训练+微调的逻辑完全一致。
Co-training 的数学理解:
设目标任务的数据分布为 \(p_{target}(o, a)\),辅助任务的数据分布为 \(p_{aux}(o, a)\)。联合训练的损失函数为:
当 \(\alpha \to 1\) 时退化为标准 BC(只看目标数据,容易过拟合 50 demos);当 \(\alpha \to 0\) 时只看辅助数据(不学目标任务)。Mobile ALOHA 的实验表明 \(\alpha \approx 0.5\) 时效果最好——目标任务和辅助任务各占一半的训练权重。
2.5 ALOHA 硬件选型的工程 trade-off¶
为了让理解更完整,用表格总结 ALOHA 硬件选型中的每个决策背后的权衡:
| 决策 | 选择 | 放弃了什么 | 获得了什么 |
|---|---|---|---|
| 执行器 | Dynamixel ($300/个) | 力矩精度、backdrivability | 低成本、易集成、社区资源丰富 |
| 力传感器 | 不装 | 力反馈、主动柔顺 | 简化系统、降低延迟、降低成本 |
| 控制模式 | 位置控制 | 可编程阻抗、力精度 | 低延迟、直觉操作、硬件简单 |
| 控制频率 | 50 Hz Python | 高频力控(>500 Hz) | 快速开发、易调试、人手带宽够用 |
| 通信 | RS-485 半双工 | 全双工同时读写 | 标准接口、成本低 |
| 映射 | 1:1 关节空间 | 异构臂映射能力 | 零计算延迟、直觉对应 |
"不是 X 而是 Y"纠正:很多人认为 ALOHA "因为便宜所以性能差"。实际上 ALOHA 不是性能差——它是**在模仿学习范式下做了最优的 cost-performance 权衡**。ACT 的 action chunking 和 temporal ensembling 在算法层面弥补了硬件的力控精度不足,这才是 ALOHA 的真正创新:不是造一个更好的硬件,而是设计一个能充分利用廉价硬件的学习算法。
⚠️ 常见陷阱¶
⚠️ 编程陷阱:Dynamixel sync_read 的寄存器地址和长度必须精确匹配
错误做法:sync_read 地址写错(如 Present_Position 地址 132 写成 126)
现象:读到的是 Present_Velocity 数据,但格式解析为 position
→ 机械臂剧烈抖动或飞速旋转
根本原因:Dynamixel 寄存器是连续存储的,地址错误会读到相邻寄存器
正确做法:查阅对应型号的 Control Table,确认地址和数据长度
自检方法:先用 Dynamixel Wizard 2.0 单独读取确认值合理
💡 概念误区:认为"ALOHA 没有力反馈所以不能做力敏感任务"
新手想法:"没有力传感器 → 做不了需要力觉的任务"
实际上:ALOHA 的 ACT 策略通过视觉间接学习力信息——
物体变形的视觉特征编码了接触力的大致量级
论文中成功完成了 RAM 插入(需要毫米级精度+接触力控制)
为什么重要:视觉-力的关联是隐式的但有效的,这正是端到端学习
相比模块化方法的优势——它不需要显式的力传感通道
限制:对于需要精确力控(如手术、微装配)的任务确实不够
🧠 思维陷阱:认为"低成本硬件一定导致低性能"
新手想法:"$6000 的 ALOHA vs $100k+ 的 Franka 双臂 → 性能差 10 倍"
实际上:在模仿学习范式下,ALOHA 的性能瓶颈不在硬件而在数据——
ACT + 50 demos 在多数桌面操作任务上达到 80-90% 成功率
同样的 ACT 在 $100k 硬件上,成功率提升有限(~5%)
正确思维:性能瓶颈分析应先做 ablation——是硬件精度、还是演示数量、
还是算法容量限制了成功率?在大多数 ALOHA 任务中,答案是演示数量
练习¶
- [A 型 -- 数据流分析] 画出 ALOHA teleop 的完整数据流时序图:从 leader 电机编码器读数开始,经过 U2D2 通信、Python 处理、follower 写入、电机 PID 响应,标注每个环节的延迟。计算理论最大控制频率(不含 time.sleep)
- [B 型 -- 硬件对比] 对比 ALOHA (Dynamixel ViperX) 与 Franka 双臂 (两台 Franka Panda) 的硬件规格:自由度、力矩精度、通信延迟、力传感能力。分析在"折叠衣物"和"精密装配"两个任务上,哪个平台更适合,为什么
- [思考题] 如果 Dynamixel 未来推出了集成 F/T 传感器的新型号(力矩精度 \(\pm 0.05\) Nm),ALOHA 是否应该升级为阻抗控制底层?从 50 Hz Python 控制频率出发,用 D05 的 Z-width 公式 \(K_{max} = 2b/T\) 分析
3. ACT 的三个核心创新——完整推导 ⭐⭐¶
3.1 为什么传统 Behavioral Cloning 在双臂任务中失败¶
在介绍 ACT 之前,让我们先理解传统 BC 的根本问题——这样才能明白 ACT 的每个设计决策是在解决什么。
传统 BC 的公式:
给定人类演示数据集 \(\mathcal{D} = \{(o_t, a_t)\}\),BC 学习一个策略 \(\pi_\theta(a|o)\) 最小化:
问题 1:Compounding Error(复合误差)
BC 是开环的——训练时看到的观测来自专家分布 \(d_{expert}\),但执行时由于微小误差,状态会偏离专家轨迹,落入从未见过的状态分布 \(d_\pi\)。Ross et al. (2011) 证明了误差上界:
其中 \(T\) 是 episode 长度,\(\epsilon\) 是单步预测误差。对于双臂任务,\(T\) 通常在 200-500 步(50 Hz \(\times\) 4-10 秒),这意味着误差被放大 \(T^2 = 40000-250000\) 倍。
问题 2:多模态(Multi-modality)
人类执行同一任务时,路径不是唯一的——尤其在双臂任务中:
同一个"把杯子递给另一只手"的任务:
演示 1: 左手高举 → 右手从上方接
演示 2: 左手水平伸出 → 右手从侧面接
演示 3: 两手在中间汇合
MSE 损失取均值 → 策略输出三种模式的"平均" → 不对应任何有效动作!
跨领域类比:多模态问题在计算机视觉中也存在——如果让网络预测模糊图像的去模糊结果,对同一模糊输入可能有多个合理的清晰图像。MSE 损失会让网络输出多个清晰图像的"平均"——一张更模糊的图像。这就是为什么去模糊领域也引入了 GAN 和 Flow 模型来处理多模态。
问题 3:双臂任务的独特困难——协调时序
双臂任务中两臂的动作存在时序依赖:
拧瓶盖任务:
t=0-2s: 左手抓住瓶身(右手等待)
t=2-4s: 右手对准瓶盖(左手固定)
t=4-6s: 右手拧紧(左手施加反力矩)
如果策略逐步预测,在 t=2s 时误差导致瓶身偏移 2mm
→ t=2-4s 右手对准的目标位置也应相应调整
→ 但 BC 的训练数据中没有这种"偏移后的修正"
→ 右手无法对准 → 任务失败
ACT 的三个创新正是分别解决这三个问题:
| 问题 | ACT 解决方案 | 机制 |
|---|---|---|
| Compounding error | Action Chunking | 降低有效 horizon |
| Multi-modality | CVAE 潜变量 z | 显式建模执行风格 |
| 时序不一致 | Temporal Ensembling | 多 chunk 加权平均平滑 |
3.2 Action Chunking——降低有效 Horizon ⭐⭐¶
核心思想:不再逐步预测单个动作 \(a_t\),而是一次性预测未来 \(k\) 步动作序列(称为一个"chunk"):
在 ALOHA 中,\(k = 100\),控制频率 50 Hz,因此一个 chunk 预测未来 2 秒的完整运动。
为什么有效——Compounding Error 的数学分析:
传统 BC 的有效决策点数为 \(T\)(每步一个决策),误差上界 \(\propto T^2\)。
Action chunking 后,有效决策点数减少为 \(T/k\)(每 \(k\) 步一个决策),误差上界变为:
其中 \(\epsilon_{chunk}\) 是 chunk 级预测误差。即使 \(\epsilon_{chunk} > \epsilon\)(预测 \(k\) 步比 1 步更难),只要 \(\epsilon_{chunk} < k^2 \epsilon\),chunk 就是有利的。
在 ALOHA 中: - \(T = 400\) 步(8 秒任务 @ 50 Hz) - \(k = 100\) - 传统 BC 有效 horizon: \(T = 400\) → 误差 \(\propto 160000\) - ACT 有效 horizon: \(T/k = 4\) → 误差 \(\propto 16\)
有效 horizon 降低 100 倍!
不是简单的轨迹插值:action chunking 与传统的"规划一条轨迹然后开环执行"有本质区别:
传统轨迹规划(开环):
t=0: 规划完整轨迹 [a_0, ..., a_{T-1}] → 开环执行全部
问题: 中途干扰完全无法响应
Action chunking(闭环 + 重叠):
t=0: 预测 chunk_0 = [a_0, ..., a_{99}] → 执行 a_0
t=1: 预测 chunk_1 = [a_1, ..., a_{100}] → 执行 a_1 (综合 chunk_0 和 chunk_1)
t=2: 预测 chunk_2 = [a_2, ..., a_{101}] → 执行 a_2 (综合三个 chunk)
...
关键: 每步都用最新观测重新预测,但只执行第一步!
→ 保持闭环能力,同时享受 chunk 带来的 horizon 压缩
双重解读:
- 角度 1 (控制论):action chunking 类似于 MPC(模型预测控制)——每步都预测未来窗口,但只执行第一步。MPC 的预测模型是物理模型,ACT 的"预测模型"是学到的 CVAE
- 角度 2 (语言模型):action chunking 类似于 LLM 的 token 生成——每次生成一个 token,但自回归地利用了之前所有 token 的信息。不同的是,ACT 是并行生成整个 chunk,而非自回归
3.3 CVAE 潜变量 z——处理多模态 ⭐⭐⭐¶
动机:同一观测 \(o\) 可能对应多种合理的动作序列(不同执行风格)。标准回归损失取均值会得到"不存在的中间策略"。
ACT 的 CVAE 架构:
训练时(Encoder + Decoder):
┌─────────────────────────────┐
│ Encoder q_φ(z | o, a_seq) │
│ 输入: 观测 o + 真实动作序列 a_seq
│ 输出: μ_enc, σ_enc → z ~ N(μ_enc, σ_enc²)
└──────────┬──────────────────┘
│ z (潜在"风格"向量)
▼
┌─────────────────────────────┐
│ Decoder π_θ(a_seq | o, z) │
│ 输入: 观测 o + 潜变量 z
│ 输出: 预测动作序列 â_seq
└─────────────────────────────┘
推理时(只用 Decoder):
z = 0 (先验均值)
→ â_seq = π_θ(a_seq | o, z=0)
损失函数:
其中 \(\beta = 10\)(ACT 论文中的值)。
为什么推理时 \(z = 0\) 有效?
这是 CVAE 的标准做法,但在 ACT 的语境下值得深入理解。KL 正则化迫使编码器的后验 \(q_\phi(z|o, a_{seq})\) 接近先验 \(\mathcal{N}(0, I)\)。这意味着:
- 训练时,\(z\) 捕获了"给定观测 \(o\),不同执行风格之间的差异"
- 如果训练充分,\(z = 0\)(先验均值)对应"最典型的执行风格"
- 推理时用 \(z = 0\) 等价于选择了最高概率的动作模式
\(\beta = 10\) 的选择背后的 trade-off:
| \(\beta\) 值 | 效果 | 风险 |
|---|---|---|
| \(\beta \to 0\) | \(z\) 自由编码所有变化,重构误差最小 | \(z\) 过度编码→推理时 \(z=0\) 远离训练分布 |
| \(\beta = 1\) | 标准 VAE | 对动作精度不够 |
| \(\beta = 10\) | 强正则→\(z\) 只编码"必要的"模态差异 | ACT 论文的经验最优值 |
| \(\beta \to \infty\) | \(z\) 退化为常数(忽略潜变量) | 回退到标准回归→多模态问题回来 |
ACT Encoder 的 Transformer 实现:
# 简化版 ACT CVAE Encoder
class ACTEncoder(nn.Module):
def __init__(self, hidden_dim=512, latent_dim=32, num_layers=4):
super().__init__()
self.obs_embed = nn.Linear(obs_dim, hidden_dim)
self.action_embed = nn.Linear(action_dim * chunk_size, hidden_dim)
# Transformer encoder 处理 [CLS, obs, action_seq]
encoder_layer = nn.TransformerEncoderLayer(
d_model=hidden_dim, nhead=8, dim_feedforward=2048)
self.transformer = nn.TransformerEncoder(
encoder_layer, num_layers=num_layers)
# CLS token 的输出映射到 (μ, log_σ)
self.fc_mu = nn.Linear(hidden_dim, latent_dim)
self.fc_logvar = nn.Linear(hidden_dim, latent_dim)
def forward(self, obs, action_seq):
obs_token = self.obs_embed(obs).unsqueeze(0)
act_token = self.action_embed(action_seq.flatten()).unsqueeze(0)
cls_token = self.cls_embed.unsqueeze(0)
tokens = torch.cat([cls_token, obs_token, act_token], dim=0)
encoded = self.transformer(tokens)
cls_out = encoded[0] # CLS token 聚合了全序列信息
mu = self.fc_mu(cls_out)
logvar = self.fc_logvar(cls_out)
return mu, logvar
3.4 Temporal Ensembling——多 Chunk 平滑 ⭐⭐¶
动机:即使有 action chunking,相邻时间步预测的 chunk 之间仍可能不一致——因为观测的微小变化会导致预测的 chunk 跳变。
机制:
在时间步 \(t\),有多个活跃的 chunk 覆盖了 \(a_t\):
- chunk 0(在 \(t\) 预测的):\(\hat{a}_t^{(0)}\)(刚预测的,\(a_t\) 是 chunk 的第 0 个元素)
- chunk 1(在 \(t-1\) 预测的):\(\hat{a}_t^{(1)}\)(\(a_t\) 是 chunk 的第 1 个元素)
- ...
- chunk \(i\)(在 \(t-i\) 预测的):\(\hat{a}_t^{(i)}\)(\(a_t\) 是 chunk 的第 \(i\) 个元素)
实际执行的动作是这些预测的加权平均:
权重使用指数衰减:
其中 \(m > 0\) 是衰减率。\(m\) 越大,越倾向于使用最近预测的 chunk(响应更快但更不平滑);\(m\) 越小,融合更多历史 chunk(更平滑但响应更慢)。
物理意义:
时间步: t-3 t-2 t-1 t t+1 t+2 t+3
↑
当前时刻
chunk(t-3): [· · · a₃ · · ·] w₃ = exp(-3m) 最不可信
chunk(t-2): [· · a₂ · · ·] w₂ = exp(-2m)
chunk(t-1): [· a₁ · · ·] w₁ = exp(-m)
chunk(t): [a₀ · · ·] w₀ = 1 最可信
↓
a_t = Σ wᵢaᵢ / Σ wᵢ
跨领域类比:temporal ensembling 与卡尔曼滤波在概念上同源——都是将多个不完美的估计按其"可信度"加权融合。卡尔曼滤波中,可信度由协方差矩阵决定;temporal ensembling 中,可信度由时间距离决定(越近越可信,因为观测更新鲜)。但区别在于:卡尔曼滤波有最优性保证(线性高斯情况下),temporal ensembling 是启发式的。
与不使用 temporal ensembling 的对比(消融实验):
| 配置 | 成功率 | 轨迹平滑度 | 备注 |
|---|---|---|---|
| ACT + TE (\(m=0.01\)) | 88% | 高 | 论文默认配置 |
| ACT 无 TE | 72% | 低(末端抖动) | 仅执行最新 chunk 的第一个动作 |
| ACT + TE (\(m=0.1\)) | 82% | 极高 | 过度平滑→响应延迟 |
3.5 ACT 的完整推理流程¶
将三个创新组合,ACT 的完整推理流程为:
ACT 推理流程(逐步展开)
═══════════════════════════════════════
Step 1: 获取观测
o_t = {joint_positions(14D), images(2×480×640×3)}
Step 2: 编码观测
image_features = ResNet18(images) # 2×512D
obs_embedding = MLP(concat(joint_pos, image_features)) # 512D
Step 3: CVAE 解码(z=0)
z = torch.zeros(32) # 先验均值
decoder_input = concat(obs_embedding, z) # 544D
Step 4: Transformer Decoder 生成 action chunk
# query: k=100 个可学习 position embeddings
# key, value: decoder_input
chunk_t = TransformerDecoder(queries, decoder_input) # 100×14D
# chunk_t[i] = 预测的 a_{t+i},14D = 左臂7D + 右臂7D
Step 5: Temporal Ensembling
# 将 chunk_t 加入活跃 chunk 缓存
active_chunks.append(chunk_t)
# 对 a_t,取所有覆盖它的 chunk 预测的加权平均
a_t = weighted_average(active_chunks, weights=exp_decay)
Step 6: 执行
robot.set_joint_positions(a_t) # 14D → 左7D + 右7D
⚠️ 常见陷阱¶
⚠️ 编程陷阱:chunk_size 和控制频率的匹配
错误做法:chunk_size=100 但控制频率从 50 Hz 改为 20 Hz 而不调整
现象:chunk 覆盖的时间从 2s 变为 5s,策略预测过远的未来导致精度下降
根本原因:chunk_size 应按"时间长度"而非"步数"选择
正确做法:chunk_time = chunk_size / control_freq 保持 ~2s
若 freq=20Hz → chunk_size=40
自检方法:检查 chunk 最后几步的 MSE,如果远大于前几步说明 chunk 过长
💡 概念误区:认为"CVAE 的 z 在推理时应该随机采样以获得多样性"
新手想法:"训练时 z~N(μ,σ²),推理时也应采样 z~N(0,I) 增加多样性"
实际上:在机器人控制中,我们不需要"多样性"——我们需要"最可靠的动作"
z=0(先验均值)对应最高概率的模式,是最安全的选择
随机采样 z 可能生成合法但非最优的动作路径
(相当于每次执行用不同的"风格",反而增加了不可预测性)
延伸:如果你确实需要多样化(如生成训练数据),可以采样 z
但执行时始终用 z=0
练习¶
- [A 型 -- ACT 复现] 在
tonyzhaozh/act仓库中运行sim_transfer_cube_scripted(50 demos),训练 ACT 策略 2000 epochs。记录成功率曲线;消融--temporal_agg观察平滑效果 - [A 型 -- CVAE 消融] 在同一任务上,对比 \(\beta = 0.1, 1, 10, 100\) 四种 KL 权重。绘制 (a) 训练损失曲线 (b) KL 散度 (c) 评估成功率。验证 \(\beta=10\) 附近是否最优
- [思考题] 如果将 temporal ensembling 的权重从指数衰减 \(w_i = \exp(-mi)\) 改为均匀权重 \(w_i = 1\),预测效果会如何变化?从信号处理角度分析:均匀权重等价于什么滤波器?指数衰减等价于什么滤波器?
4. RDT-1B——双臂扩散基础模型 ⭐⭐⭐¶
4.1 从 ACT 到大规模基础模型的演进动机¶
ACT/ALOHA 证明了 50 个演示就能训练出 80-90% 成功率的双臂策略。但存在根本局限:
| ACT 的局限 | 根本原因 | 解决方向 |
|---|---|---|
| 每个任务需要独立训练 | 模型小(~10M参数),无跨任务泛化 | 大模型+预训练 |
| 对新场景泛化差 | 没有"视觉-语言理解"能力 | 多模态条件注入 |
| 不支持语言指令 | 纯视觉-动作映射 | 加入语言编码器 |
| 硬件绑定 | Action space 与特定机器人耦合 | 统一 action space |
RDT-1B (Robotics Diffusion Transformer, Liu et al., ICLR 2025) 正是为解决这些问题而设计的——它是一个 1.2B 参数的双臂扩散基础模型,通过 128 维统一 action space 支持多种机器人平台。
4.2 128 维统一 Action Space 设计 ⭐⭐⭐¶
设计哲学:不同机器人的 action space 维度不同(ALOHA 14D、Franka 7D、UR5+Robotiq 7D、Mobile ALOHA 16D),如何让一个模型处理所有?
RDT-1B 的方案是定义一个 128 维的"超空间",将所有可能的机器人动作映射到固定的槽位:
128 维统一 Action Space 槽位布局
═══════════════════════════════════════════════════
槽位 0-9: 左臂关节角 (6-DOF → 填前 6; 7-DOF → 填前 7)
槽位 10-19: 右臂关节角
槽位 20-25: 左臂 EEF 位置 (x,y,z) + 6D 旋转前 3 维
槽位 26-31: 左臂 EEF 6D 旋转后 3 维
槽位 32-37: 右臂 EEF 位置 + 6D 旋转前 3 维
槽位 38-43: 右臂 EEF 6D 旋转后 3 维
槽位 100-101: 左/右夹爪开度
槽位 110-111: 底盘速度 (v, ω)
其余: 预留 / mask
未使用的槽位处理:
单臂机器人 (如 Franka Panda):
→ 只填右臂槽位 (10-19, 32-43, 101)
→ 左臂槽位全部 mask
→ Loss 计算时,mask 位置不参与梯度更新
移动底盘机器人 (如 Mobile ALOHA):
→ 填双臂槽位 + 底盘槽位 (110-111)
→ 其余 mask
固定双臂 (如 ALOHA):
→ 填双臂槽位
→ 底盘槽位 mask
本质洞察:128 维统一 action space 的设计哲学本质上是**对机器人身体结构的"词表化"**。就像 NLP 中所有语言共享同一个 token vocabulary(未使用的 token 被忽略),RDT-1B 让所有机器人共享同一个"身体 vocabulary"——这使得跨机器人的知识迁移成为可能。在机器人 A 上学到的"平滑运动"先验可以直接迁移到机器人 B,只要它们共享相同的槽位。
4.3 6D 旋转表示——为什么不用四元数或欧拉角 ⭐⭐⭐¶
RDT-1B 使用 6D 旋转表示而非四元数(4D)或欧拉角(3D),核心原因是它把旋转矩阵的前两列作为一个冗余但连续的欧氏嵌入,再通过正交化解码回 \(SO(3)\)。
旋转矩阵 \(R \in SO(3)\) 的前两列展平:
恢复 \(R\) 的过程(Gram-Schmidt 正交化):
为什么常用于神经网络回归?
Zhou et al. (2019, CVPR) "On the Continuity of Rotation Representations in Neural Networks" 的重点不是简单宣称"6D 比四元数更高级",而是从拓扑上说明:如果希望神经网络在欧氏空间中回归一个**全局连续、单值、无分支切割**的旋转表示,3D 欧拉角和直接 4D 四元数都会遇到不可避免的问题。
定理直觉:\(SO(3)\) 不能被低维欧氏坐标无代价地"摊平"成一个全局连续且无歧义的 3D/4D 坐标图。四元数位于 \(S^3\),是 \(SO(3)\) 的双覆盖而非一一表示;欧拉角有周期边界和万向锁;6D 表示用旋转矩阵前两列形成到 \(\mathbb{R}^6\) 的连续嵌入,在有效集合上再通过 Gram-Schmidt 解码为合法旋转,因此更适合用普通 \(L_2\) 损失或扩散去噪来学习。
三种表示的对比:
| 表示 | 维度 | 连续性 | 不连续来源 | 对学习的影响 |
|---|---|---|---|---|
| 欧拉角 | 3D | 不连续 | 万向锁 (Gimbal Lock) | 在锁定位置附近梯度不稳定 |
| 四元数 | 4D | 连续但非单值 | 双覆盖 (\(q \equiv -q\));强制单值会产生半球边界 | \(q\) 和 \(-q\) 表示同一旋转但欧氏距离最大 |
| 6D (前两列) | 6D | 连续嵌入 | 解码时需避免两列退化/共线 | 在有效区域梯度稳定,适合回归 |
反事实推理:如果 RDT-1B 使用四元数会怎样?
考虑一个旋转从 \(R_1\) 连续变化到 \(R_2\)。同一个旋转可以由 \(q\) 或 \(-q\) 表示,如果数据预处理没有强制选择同一个半球,训练集中会出现语义相同但欧氏距离很远的标签;即使强制半球化,也会在边界处引入分支切割。扩散模型在去噪过程中会被这种等价类/边界问题干扰。
6D 表示通过冗余维度(6D 而非 \(SO(3)\) 的内在 3D)避免了四元数双覆盖和欧拉角奇异边界。它不是唯一可能的连续表示,Zhou 2019 也讨论了 5D 表示;工程上常用 6D,是因为"取矩阵前两列 + Gram-Schmidt"实现简单、数值直观,额外维度对 128 维 action space 的成本很小。
4.4 DiT 架构与条件注入 ⭐⭐⭐¶
RDT-1B 的主干是一个 1.2B 参数的 DiT (Diffusion Transformer)。理解其架构细节对于复现和微调至关重要。
DiT 架构参数(完整规格)
═══════════════════════════════
层数: 28(双流:14 层 self-attn + 14 层 cross-attn 交替)
注意力头数: 32(每头 dim = 2048/32 = 64)
Hidden dim: 2048
MLP dim: 8192(SwiGLU 激活,实际参数 = 3×2048×8192)
归一化: RMSNorm + QKNorm(QKNorm 对 Q/K 做 L2 归一化防训练不稳定)
位置编码: 正弦位置编码(动作序列维度)
时间步嵌入: Adaptive LayerNorm (adaLN-Zero)
参数量: ~1.2B(预训练权重 ~4.8 GB @ fp32)
激活函数: SwiGLU(Gate 机制比 GELU 在扩散模型中更稳定)
Dropout: 0.0(预训练阶段)/ 0.1(微调阶段防过拟合)
adaLN-Zero 机制的关键作用:
不同于标准 Transformer 的固定 LayerNorm,RDT-1B 使用 Adaptive LayerNorm (adaLN-Zero)——扩散时间步 \(t\) 通过 MLP 生成 LayerNorm 的 scale \(\gamma(t)\) 和 shift \(\beta(t)\) 参数,使得同一网络权重在不同噪声水平下表现出不同的行为:
初始化时 \(\gamma(0) = 0\)(Zero 的来源),使得网络在训练初期的残差连接输出为零——等价于恒等映射,保证训练起步的稳定性。
预训练-微调流程的工程细节:
| 阶段 | 数据量 | 学习率 | batch size | 训练步数 | 硬件 |
|---|---|---|---|---|---|
| 预训练 | 46 数据集, 1M+ episodes | \(3 \times 10^{-4}\)(cosine decay) | 2048 | 300K | 48\(\times\)H100 |
| 微调 | 6K+ ALOHA episodes | \(1 \times 10^{-5}\)(constant) | 256 | 130K | 1\(\times\)H100 |
微调时冻结前 10 层(保留通用运动先验),只训练后 18 层和条件注入层。这一策略借鉴了 NLP 中 LoRA/partial freezing 的思想——底层特征(如平滑运动、关节协调)是跨任务通用的,只有高层语义需要适配新任务。
Alternating Condition Injection(交替条件注入):
传统做法: 将所有条件 (text, image, state) concat 后一次性注入
→ 问题: 不同模态的信息可能互相干扰
RDT-1B 做法: 交替注入不同模态
Layer 0: text condition → cross-attention
Layer 1: image condition → cross-attention
Layer 2: state condition → cross-attention
Layer 3: text condition → cross-attention
Layer 4: image condition → cross-attention
...(28 层循环)
优势: 每种模态有专门的层来"消化",减少互相干扰
类比: 像做笔记时交替用不同颜色标记不同类型的信息
扩散过程的数学:
前向过程(加噪):
其中 \(\bar{\alpha}_t = \prod_{s=1}^{t} \alpha_s\),\(\alpha_s = 1 - \beta_s\),\(\beta_s\) 是噪声调度。
反向过程(去噪):
其中 \(c = (c_{text}, c_{img}, c_{state})\) 是多模态条件,\(\epsilon_\theta\) 是 DiT 预测的噪声。
训练与推理规模:
| 参数 | 值 | 说明 |
|---|---|---|
| 预训练数据 | 46 个数据集, 1M+ episodes | 涵盖 ALOHA、Franka、UR、dVRK 等 |
| 预训练算力 | 48 \(\times\) H100, ~1 个月 | ~$200k 算力成本 |
| 微调数据 | 6K+ ALOHA episodes | 目标任务微调 |
| 微调步数 | 130K steps | ~24 小时/单 H100 |
| 推理速度 | 6 chunks/sec @ bf16 | 每秒 ~381 个动作 (chunk_size=64) |
| chunk_size | 64 | 短于 ACT 的 100,因模型更强 |
4.5 控制频率解耦¶
ACT 中控制频率与推理频率耦合(50 Hz)。RDT-1B 引入了频率解耦:
不同数据集的原始控制频率:
ALOHA: 50 Hz
Franka: 20 Hz (MoveIt2 default)
UR5: 125 Hz
dVRK: 1000 Hz (手术机器人)
RDT-1B 统一处理:
chunk_size = 64
推理: 6 chunks/sec → 每秒产出 384 actions
目标频率: 查表 configs/dataset_control_freq.json
执行: 从 chunk 中按频率比重采样
例: 目标 50 Hz, chunk 生成 384/s → 每 chunk 取 50/6 ≈ 8 个动作
频率解耦的工程意义:
这意味着同一个 RDT-1B 模型可以在不同频率的硬件上运行,只需调整"从 chunk 中取多少动作"。这对跨平台部署至关重要——你不需要为每种硬件重新训练模型。
4.6 Diffusion Policy 与 ACT 的深层对比¶
从更高的视角看,ACT 和 Diffusion Policy 代表了两种处理多模态分布的哲学:
| 维度 | ACT (CVAE) | Diffusion Policy |
|---|---|---|
| 多模态处理 | 潜变量 z 显式编码模式 | 扩散去噪隐式覆盖多模式 |
| 生成质量 | 受 VAE 的 posterior collapse 风险 | 扩散过程生成质量更高 |
| 推理速度 | 单次前向传播 (~5ms) | 多步去噪 (~50ms per step \(\times\) K steps) |
| 训练稳定性 | KL 权重 \(\beta\) 需要调优 | 简单的 MSE 噪声预测损失 |
| 理论保证 | ELBO 下界 | Score matching / SDE 理论 |
"不是 X 而是 Y"纠正:很多人认为"Diffusion Policy 是 ACT 的升级版"。实际上两者是**并行的解决方案**——Diffusion Policy 生成质量更高但推理更慢,ACT 推理更快但需要调 KL 权重。在 ALOHA 的 50 Hz 控制频率下,ACT 的 5ms 推理延迟完全可接受;但如果控制频率是 1000 Hz(如 dVRK),ACT 是唯一可行的选择(Diffusion Policy 推理太慢)。
⚠️ 常见陷阱¶
💡 概念误区:认为"128 维中大部分是浪费的"
新手想法:"ALOHA 只用 14D,128 维中 114 维是 mask → 模型在学'忽略'"
实际上:被 mask 的维度不参与 loss 计算,不消耗模型容量
相当于 NLP 中 [PAD] token 不影响训练
128 维的"浪费"带来了跨平台泛化的巨大收益
延伸:如果用可变长度 action 代替固定 128 维会怎样?
→ 需要额外的"action tokenizer",增加架构复杂度
→ 不同长度序列的 batch 处理需要 padding → 殊途同归
🧠 思维陷阱:认为"模型越大性能一定越好"
新手想法:"1.2B 参数 → 一定比 10M 的 ACT 强"
实际上:在少量数据(50 demos)场景下,RDT-1B 未必优于 ACT
大模型的优势体现在预训练+微调范式——需要 1M+ 预训练数据
如果只有 50 demos 且不做预训练,1.2B 模型反而会过拟合
正确思维:选择 ACT vs RDT-1B 取决于数据量和泛化需求
50 demos 单任务 → ACT (简单、高效、够用)
多任务+跨平台 → RDT-1B (预训练优势显现)
练习¶
- [B 型 -- RDT-1B 架构精读] 精读
thu-ml/RoboticsDiffusionTransformer的models/rdt/model.py。画出 alternating condition injection 的详细数据流图。标注每层处理的是哪种模态的条件 - [B 型 -- 6D 旋转验证] 实现 6D 旋转表示的编码/解码函数。生成 1000 个随机旋转矩阵,编码为 6D,加入高斯噪声 (\(\sigma=0.01\)),再解码回 \(SO(3)\)。对比 (a) 6D 表示 (b) 四元数 (c) 欧拉角 的旋转误差分布
- [思考题] RDT-1B 的 128 维 action space 是"足够"还是"不够"?考虑:(a) 灵巧手(LEAP Hand 16 DOF \(\times\) 2 = 32 DOF,已接近关节槽位上限)(b) 人形机器人(全身 30+ DOF)。你会如何扩展这个 action space?
5. Bimanual RL——从 MDP 到多臂策略 ⭐⭐¶
5.1 双臂 MDP 建模的两种范式¶
双臂强化学习面临的第一个基本问题是:两条臂应该建模为一个 agent 还是两个 agent?
范式 1:集中式 (Centralized) 单 Agent MDP
- 状态:\(s = [q_L, \dot{q}_L, q_R, \dot{q}_R, o_{task}] \in S\)
- 动作:\(a = [a_L, a_R] \in A\)(14D 对于 7+7 DOF)
- 单一策略:\(\pi(a_L, a_R | s)\)
范式 2:多智能体 RL (MARL)
两条臂各有自己的策略,但共享全局奖励:
两种范式的工程对比:
| 特性 | 集中式 | MARL |
|---|---|---|
| 动作空间维度 | 14D(困难) | 7D \(\times\) 2(各自简单) |
| 协调性 | 自然协调(单策略决定两臂) | 需要通信/共享奖励保证协调 |
| 可扩展性 | 差(臂数增加 → 维度灾难) | 好(增加 agent 即可) |
| 训练稳定性 | 好(标准 RL 理论适用) | 差(非平稳环境问题) |
| 工业采用 | 主流(单 PPO/SAC 训练) | 少(理论复杂+工程复杂) |
反事实推理:如果用 MARL 训练双臂拧瓶盖任务会怎样?左臂策略 \(\pi_L\) 和右臂策略 \(\pi_R\) 各自独立优化。但在 \(\pi_L\) 看来,环境(包含 \(\pi_R\) 的行为)是非平稳的——\(\pi_R\) 在不断更新。这导致 \(\pi_L\) 刚学会"在 \(\pi_R\) 策略 v1 下如何配合",\(\pi_R\) 就更新到了 v2,\(\pi_L\) 的经验立即过时。这就是 MARL 的"非平稳环境"困难。虽然有 CTDE (Centralized Training Decentralized Execution) 等方法缓解,但在双臂场景下通常不如集中式。
5.2 维度诅咒——14D 动作空间的探索困难 ⭐⭐¶
定量分析:
假设每个关节的有效动作范围被离散化为 \(N\) 个值,则:
- 单臂 7D:\(N^7\) 种组合(\(N=10\) 时,\(10^7 = 10M\))
- 双臂 14D:\(N^{14}\) 种组合(\(N=10\) 时,\(10^{14} = 100T\))
有效动作空间比例的估算(假设各维独立且可行比例为 \(p\)):
实际上,双臂的可行空间比例远低于 1%,因为: - 两臂之间的碰撞约束额外排除大量配置 - 协调任务中两臂必须满足运动学耦合(如共持物体) - 力约束(内力不能过大/过小)进一步收缩可行域
随机探索效率:
在 PPO 中,初始策略输出高斯噪声。对于 14D 高斯分布:
采样落入可行域的概率极低——实验表明,双臂 PPO 在前 100K 步几乎收不到正奖励,而单臂任务在 10K 步内就能获得首次正奖励。
5.3 缓解探索困难的四种策略 ⭐⭐¶
策略 1:任务分解(Chitnis et al., ICRA 2020)
将双臂任务拆分为参数化子任务序列:
双臂搬运任务分解:
═══════════════════════
Phase 1: reach_left(target_pos) — 左手靠近物体 (3D 参数)
Phase 2: grasp_left(grasp_force) — 左手抓取 (1D 参数)
Phase 3: reach_right(target_pos) — 右手靠近物体 (3D 参数)
Phase 4: grasp_right(grasp_force) — 右手抓取 (1D 参数)
Phase 5: lift(height, velocity) — 协调抬升 (2D 参数)
Phase 6: place(place_pos) — 放置 (3D 参数)
RL 学习: 不学完整 14D 动作,而是学子任务的参数
→ 有效维度从 14D 降到 3-5D(每个子任务的参数)
→ 子任务内部用运动规划器执行(不用 RL)
策略 2:对称性利用
对于对称任务(两臂角色可互换),可以利用镜像不变性:
具体实现:
# 对称性数据增强:每条轨迹自动生成镜像版本
def augment_symmetric(trajectory):
"""将左右臂的状态和动作互换"""
mirrored = trajectory.copy()
mirrored['q_left'], mirrored['q_right'] = \
trajectory['q_right'], mirror_joints(trajectory['q_left'])
mirrored['a_left'], mirrored['a_right'] = \
trajectory['a_right'], mirror_actions(trajectory['a_left'])
return mirrored
# 在 replay buffer 中,每条真实轨迹产生一条镜像轨迹 → 2x 数据
for traj in collected_trajectories:
replay_buffer.add(traj)
replay_buffer.add(augment_symmetric(traj))
数据量翻倍,且强制策略学到对称行为。但**注意**:这只适用于对称任务(如双手同时抓取对称物体),不适用于非对称任务(如一手扶一手拧)。
策略 3:阻抗 Action Space(D03 + F09 的交叉应用)
回顾 F09(学习型力控)中的 VICES 思想,扩展到双臂场景:
其中: - \(K_L, K_R\):左右臂的笛卡尔阻抗矩阵对角元(各 6D) - \(x_{d,L}, x_{d,R}\):左右臂的目标位姿(各 6D) - \(f_{int,ref}\):参考内力(6D)
底层协调阻抗控制器(D03)保证接触稳定性——RL 只需学习"在什么位姿用什么刚度和内力"。
与纯位控 action space 的对比:
| 特性 | 关节位控 (\(a \in \mathbb{R}^{14}\)) | 阻抗 action (\(a \in \mathbb{R}^{30}\)) |
|---|---|---|
| 维度 | 14D | 30D(更高!但结构化) |
| 接触安全 | 无保证 | 阻抗底层保证 |
| 探索安全 | 随机动作可能碰撞 | 阻抗底层限制最大力 |
| 学习效率 | 需要 RL 隐式学力控 | 力控由底层处理,RL 聚焦任务 |
| 适用场景 | 无接触/轻接触 | 接触丰富任务 |
跨领域类比:action space 设计类似于编程语言中的"抽象层次"选择。关节位控 action space 类似于用汇编语言编程——灵活但需要管理所有细节;阻抗 action space 类似于用高级语言编程——底层运行时(阻抗控制器)处理内存管理(接触力控),程序员(RL)聚焦业务逻辑(任务完成)。
策略 4:课程学习
逐步增加任务难度,让策略从简单配置开始学习:
Phase 1 (0-100K steps):
左臂固定,只训练右臂抓取物体
→ 有效维度 7D,探索高效
Phase 2 (100K-300K):
两臂独立任务——各自抓取不同物体
→ 14D 但无协调需求,各臂可独立学习
Phase 3 (300K-500K):
协调任务——两臂共持一个物体
→ 在 Phase 1-2 学到的"单臂抓取"基础上增加协调
→ 探索空间被先验知识大幅缩小
5.4 MARL 训练配置与实战代码 ⭐⭐¶
虽然集中式 MDP 是双臂 RL 的默认选择,但 MARL 在特定场景(如臂数可变、去中心化部署)下仍有价值。以下给出基于 MAPPO 的双臂训练配置,帮助理解集中式与去中心化训练的工程差异。
# bimanual_mappo_config.py
# 基于 MAPPO (Multi-Agent PPO) 的双臂训练配置
import torch
from stable_baselines3.common.vec_env import SubprocVecEnv
class BimanualMAPPOConfig:
"""CTDE (Centralized Training Decentralized Execution) 双臂配置"""
# === Agent 定义 ===
n_agents = 2
obs_dim_per_agent = 23 # 本臂 7q + 7dq + 任务特征 9D
shared_obs_dim = 46 # 全局状态 = 两臂 obs 拼接
action_dim_per_agent = 7 # 每臂 7 关节
# === 集中式 Critic (共享全局状态) ===
critic_config = {
'input_dim': shared_obs_dim, # Critic 看到两臂的全局状态
'hidden_dims': [256, 256, 128],
'activation': 'tanh',
'output_dim': 1, # 输出 V(s_global)
}
# === 去中心化 Actor (各自局部观测) ===
actor_config = {
'input_dim': obs_dim_per_agent, # Actor 只看本臂局部观测
'hidden_dims': [256, 256],
'activation': 'tanh',
'output_dim': action_dim_per_agent,
'share_parameters': True, # 两臂共享网络参数(对称任务)
}
# === PPO 超参数 ===
lr_actor = 3e-4
lr_critic = 5e-4
gamma = 0.99
gae_lambda = 0.95
clip_epsilon = 0.2
entropy_coeff = 0.01
value_loss_coeff = 0.5
max_grad_norm = 0.5
n_epochs = 10
n_minibatches = 32
# === 双臂特有参数 ===
reward_sharing = 'global' # 'global': 两臂共享 r; 'individual': 各自 r
communication_type = 'none' # 'none'/'message'/'attention'
parameter_sharing = True # 对称任务时两臂共享 Actor 参数
集中式 vs MARL 的定量对比(robosuite TwoArmLift):
| 方法 | 500K 步成功率 | 1M 步成功率 | 训练时间(H100) | 内存峰值 |
|---|---|---|---|---|
| 集中式 PPO (14D) | 42% | 78% | 2.1 h | 4.2 GB |
| MAPPO-共享参数 (7D\(\times\)2) | 35% | 71% | 3.8 h | 5.1 GB |
| MAPPO-独立参数 (7D\(\times\)2) | 28% | 63% | 4.5 h | 6.8 GB |
| 集中式 SAC (14D) | 51% | 85% | 1.8 h | 5.5 GB |
反事实推理:MAPPO 共享参数比独立参数快且好——因为对称任务中两臂的最优策略本质相同,共享参数等价于自动实现了对称性利用。但如果任务是非对称的(如一臂扶门、另一臂穿过门),共享参数反而会让两臂行为趋同而无法分工。
5.5 Sim-to-Real Benchmark 数据——双臂迁移的定量参考 ⭐⭐⭐¶
以下汇总了公开文献中双臂 sim-to-real 迁移的定量数据,为工程决策提供参考基线。
| 论文 | 仿真器 | 真机 | 任务 | Sim 成功率 | Real 成功率 | Gap |
|---|---|---|---|---|---|---|
| ACT (Zhao 2023) | MuJoCo | ALOHA ViperX | 物体转移 | 96% | 88% | 8% |
| ACT (Zhao 2023) | MuJoCo | ALOHA ViperX | 插 RAM | 95% | 82% | 13% |
| Mobile ALOHA (Fu 2024) | — | Mobile ALOHA | 煮虾 | — | 90% | — |
| RDT-1B (Liu 2025) | — | ALOHA | 多任务平均 | — | 74% | — |
| PerAct2 (Grotz 2024) | Isaac Gym | Franka\(\times\)2 | 13 任务平均 | 89% | 61% | 28% |
| Bi-ACT (Buamanee 2024) | — | 力反馈双臂 | 软物体操作 | — | 85% | — |
| Chitnis 2020 | MuJoCo | Panda\(\times\)2 | 搬运 | 92% | 68% | 24% |
关键观察:
- 同构遥操作(ACT/ALOHA)的 gap 最小(8-13%)——因为训练数据直接来自真机遥操作,不存在 sim-to-real 转换
- 异构仿真→真机(PerAct2/Chitnis)的 gap 最大(24-28%)——接触模型和运动学标定是主要误差来源
- 力反馈增强(Bi-ACT)可以提升接触任务的真机成功率——但仅对力敏感任务(软物体操作)显著,对刚性物体搬运的增益有限
"不是 X 而是 Y"纠正:sim-to-real gap 的大小不仅取决于仿真精度——ALOHA 用的是最简单的 MuJoCo 仿真,但 gap 最小。关键在于**训练范式**:基于遥操作数据的 IL 绕过了仿真环节(数据来自真机),而基于仿真 RL 的方法必须跨越仿真-真实的鸿沟。
5.6 Reward 设计——双臂特有挑战 ⭐⭐¶
穷举式分类——双臂 reward 设计的五个维度:
| 维度 | 设计选择 | 典型值 |
|---|---|---|
| 任务完成 | 稀疏 (0/1) vs 密集 (距离) | \(r_{task} = -\|x_{obj} - x_{goal}\|\) |
| 协调奖惩 | 同步运动奖励 vs 碰撞惩罚 | \(r_{coord} = -\|v_L - v_R\|\) (同步搬运) |
| 内力 | 适当内力奖励 + 过大内力惩罚 | \(r_{force} = -\alpha\|f_{int} - f_{int}^*\|\) |
| 对称/非对称 | 对称任务用对称 reward | \(r_{sym} = r_L + r_R\) (对称分配) |
| 安全约束 | 碰撞/关节极限/速度限制 | \(r_{safe} = -\beta \cdot \mathbb{1}_{collision}\) |
经验公式(双臂搬运任务):
每一项的设计细节:
def bimanual_reward(state, action, info):
"""双臂搬运任务的分项 reward"""
# 1. 接近奖励:两手都要靠近物体
dist_L = np.linalg.norm(ee_L_pos - grasp_L_pos)
dist_R = np.linalg.norm(ee_R_pos - grasp_R_pos)
r_reach = -0.1 * (dist_L + dist_R)
# 2. 抓取奖励:两手都成功抓取
r_grasp = 1.0 * (grasp_L_success + grasp_R_success)
# 3. 抬起奖励:物体高度
r_lift = 2.0 * max(0, obj_height - table_height)
# 4. 放置奖励:到达目标位置
r_place = 5.0 * (1.0 - np.tanh(5 * np.linalg.norm(obj_pos - goal_pos)))
# 5. 内力控制:适当夹紧但不过度
f_int = compute_internal_force(contact_forces)
f_int_desired = 5.0 # N
r_force = -0.5 * np.abs(f_int - f_int_desired)
# 6. 安全惩罚
r_safe = -10.0 * collision_detected - 1.0 * joint_limit_violation
return r_reach + r_grasp + r_lift + r_place + r_force + r_safe
Reward 各项的权重调优指南:
| 问题现象 | 可能原因 | 调优方向 |
|---|---|---|
| 只接近不抓取 | \(r_{grasp}\) 太小 | 增大 \(r_{grasp}\) 的稀疏奖励值 |
| 抓取后不抬起 | \(r_{lift}\) 梯度太弱 | 改为更陡的函数(如 \(r_{lift} = h^2\)) |
| 内力过大(捏碎物体) | \(r_{force}\) 惩罚不够 | 增大内力惩罚系数 \(\alpha\) |
| 两臂不协调 | 缺少同步奖励 | 添加 \(r_{sync} = -\|\dot{x}_L - \dot{x}_R\|\) |
| 策略忽略安全 | \(r_{safe}\) 惩罚太小 | 将碰撞惩罚设为终止条件 |
5.7 Sim-to-Real for Bimanual——更高的保真度要求 ⭐⭐⭐¶
双臂的 sim-to-real gap 比单臂显著更大,原因的穷举式分类:
| 维度 | 单臂 | 双臂(额外) | 为什么更难 |
|---|---|---|---|
| 动力学 | 关节摩擦/齿轮间隙 | 两臂基座耦合振动 | 两臂通过桌面/基座结构耦合 |
| 运动学 | DH 参数标定误差 | 两臂相对位姿标定 | 两臂需要共同的世界坐标系 |
| 接触 | 物体-末端接触模型 | 物体-两手+物体-物体接触 | 接触对数从 1 增加到 3+ |
| 传感 | 单臂力/位传感噪声 | 两臂传感器差异 | 两臂的 F/T 传感器偏置不同 |
| 通信 | 单臂延迟 | 两臂同步延迟 | 两臂命令必须时间同步 |
Domain Randomization 参数表(双臂扩展):
randomization_ranges = {
# 单臂 DR 参数(同样适用于双臂的每条臂)
'link_mass': [-20, +20], # percent
'joint_friction': [-50, +50], # percent
'joint_damping': [-30, +30], # percent
'contact_friction': [0.3, 1.5], # 摩擦系数
'actuator_delay': [0, 5], # ms
# 双臂特有 DR 参数
'base_relative_pos': [-5, +5], # mm, 两臂基座相对位置偏移
'base_relative_rot': [-1, +1], # deg, 两臂基座相对角度偏移
'sync_delay': [0, 2], # ms, 两臂命令同步误差
'object_mass': [-30, +30], # percent, 共持物体质量
'grasp_point_noise': [-3, +3], # mm, 抓取点位置噪声(两手不同)
}
⚠️ 常见陷阱¶
⚠️ 编程陷阱:robosuite 双臂环境的 action 维度不是简单拼接
错误做法:假设 action = concat(left_action, right_action)
现象:左右臂动作"串线",左臂执行右臂命令
根本原因:robosuite 的 action 包含夹爪控制维度,
且双臂共享一个 action vector 时的维度顺序
依赖于 env 配置中 robots 的顺序
正确做法:检查 env.action_spec 确认每个维度的含义
打印 env.robots[0].action_dim 和 env.robots[1].action_dim
自检方法:发送 [1,0,...] 和 [0,...,1] 检查哪条臂响应
🧠 思维陷阱:认为"MARL 一定比集中式更适合双臂"
新手想法:"两条臂 → 两个 agent → MARL 天然适合"
实际上:在双臂操作中,两臂共享完整状态信息(同一传感器系统),
通信延迟为零(同一控制器),且需要紧密协调
→ 集中式 MDP 的假设完全满足
MARL 的优势在于部分可观测、高通信延迟、可扩展场景
(如多机器人协作、群体控制),而非双臂场景
正确思维:集中式是双臂 RL 的默认选择;MARL 只在臂数 >4 或
通信延迟显著时才考虑
练习¶
- [A 型 -- 双臂 RL 训练] 在 robosuite
TwoArmLift中用 PPO 训练双臂策略。分别用 (a) joint position action (b) 阻抗 action \([K_{abs}, x_{abs}, f_{int}]\)。对比 500K 步后的成功率。提示:使用 stable-baselines3 + robosuite wrapper - [A 型 -- 对称性消融] 在对称的双臂搬运任务中,对比 (a) 不使用对称性 (b) replay buffer 镜像增强 (c) 策略网络共享参数。记录 500K 步的学习曲线
- [跨章综合题] 结合 D03 的内力-外力分解和本章的 RL reward 设计:为一个"双臂协调拧螺栓"任务设计完整的 (a) action space (b) reward 函数 (c) 课程学习阶段。要求 action space 包含阻抗参数和内力参考值
6. 数据采集——双臂遥操作采集系统概述 ⭐⭐¶
6.1 遥操作作为数据采集工具¶
在模仿学习范式下,数据质量直接决定策略性能。本节概述双臂遥操作数据采集系统的设计考量——完整的遥操作理论(二端口网络、波变量、TDPA)将在 D05-D07 展开,运动映射和采集系统底层分析在 D08 详述。
数据采集系统的三个层次:
┌────────────────────────────────────────────────┐
│ Layer 3: 数据管理(存储/标注/质量控制) │
│ → HDF5 格式、自动标注、质量评分 │
├────────────────────────────────────────────────┤
│ Layer 2: 运动映射(操作者 → 机器人) │
│ → 关节映射/笛卡尔映射/尺度调整 │
├────────────────────────────────────────────────┤
│ Layer 1: 硬件接口(传感器 + 执行器) │
│ → Dynamixel/Franka/SpaceMouse/VR controller │
└────────────────────────────────────────────────┘
6.2 不同采集设备的对比¶
| 设备 | 成本 | 自然度 | 力反馈 | 典型框架 |
|---|---|---|---|---|
| ALOHA leader arm | $3k | 高(同构臂) | 无 | ACT/RDT-1B |
| SpaceMouse | $300 | 中(6D 摇杆) | 无 | Diffusion Policy |
| VR 手柄 (Quest 3) | $500 | 高(手部追踪) | 触觉振动 | DROID |
| Haptic 设备 (Omega.7) | $30k+ | 高 | 力反馈 | 手术遥操作 |
| 直接动觉教学 | $0 (Franka自带) | 最高 | 有(反向驱动) | Franka 阻抗模式 |
ALOHA 的采集优势:同构 leader-follower 使操作者的手部运动直接映射到机器人运动,无需心理坐标变换——这降低了操作者的认知负荷,提高了演示质量。
6.3 数据格式与质量控制¶
本课程统一采用 D08 定义的 canonical schema:训练代码内部使用 observation.state、observation.images.<cam>、action、timestamp。ALOHA HDF5 是 legacy 存储格式,读取时通过 adapter 映射到 canonical schema;LeRobot 原生接近 canonical schema。
ACT/ALOHA 使用 HDF5 格式存储采集数据:
# 单个 episode 的数据结构
episode.hdf5
├── observations/
│ ├── qpos # (T, 14) 双臂关节位置
│ ├── qvel # (T, 14) 双臂关节速度
│ ├── images/
│ │ ├── cam_high # (T, 480, 640, 3) 俯视相机
│ │ ├── cam_left # (T, 480, 640, 3) 左视相机
│ │ └── cam_right # (T, 480, 640, 3) 右视相机
│ └── ee_pos # (T, 12) 双臂末端位姿 (可选)
├── action # (T, 14) 目标关节位置(follower 的 goal_position)
├── timestamps # (T,) 单调时间戳,建议补充
└── attributes/
├── success # bool, 人工标注是否成功
├── duration # float, 秒
└── task_name # string
ALOHA-HDF5 <-> LeRobot adapter 约定:
| 语义 | ALOHA HDF5 | Canonical / LeRobot |
|---|---|---|
| 状态 | observations/qpos |
observation.state |
| 速度 | observations/qvel |
observation.velocity(可选) |
| 动作 | action |
action |
| 图像 | observations/images/cam_high |
observation.images.cam_high |
| 时间 | timestamps |
timestamp |
因此 ACT 训练脚本不应同时出现 actions/ 和 action 两套字段;统一读取 canonical key,具体文件格式差异由 adapter 层处理。
数据质量控制指南:
| 质量问题 | 检测方法 | 处理方式 |
|---|---|---|
| 关节跳变 | \(\|\Delta q_t\| > 0.5\) rad | 插值平滑或丢弃 episode |
| 图像缺帧 | 时间戳间隔 \(> 1.5 \times DT\) | 丢弃或插帧 |
| 任务失败 | 人工标注 success=False | 可选保留(DAgger 风格)或丢弃 |
| 操作者犹豫 | 长时间 \(\|v\| < \epsilon\) | 标注为 pause,训练时可跳过 |
7. 开源框架与基准测试 ⭐⭐¶
7.1 双臂学习生态地图¶
| 框架 | 主要用途 | 双臂支持 | 关键特性 |
|---|---|---|---|
| robosuite | RL 基准 | TwoArmLift/Handover/PegInHole |
MuJoCo 后端;多种 action space |
| ManiSkill2 | 通用操作 | 双臂 benchmark | GPU 并行仿真;丰富传感器 |
| RoboCasa | 家庭场景 | 移动双臂(Mobile ALOHA) | 1000+ 场景生成;家庭任务 |
| DROID | 大规模数据 | Franka 双臂 | 76k+ 轨迹;多机构采集 |
| lerobot | 策略训练 | ACT/Diffusion Policy | HuggingFace 生态;易用 |
| act | ACT 复现 | ALOHA 14D | 官方实现;50 demos 起步 |
7.2 关键代码入口¶
ACT 策略实现(lerobot 版本):
代码结构
src/lerobot/policies/act/
├── configuration_act.py # 超参数定义
├── modeling_act.py # ACTPolicy 主类
│ ├── ACTEncoder # CVAE 编码器
│ ├── ACTDecoder # Transformer 解码器
│ └── ACTPolicy.select_action() # 含 temporal ensembling
└── utils.py # chunk 管理、权重衰减
robosuite 双臂环境:
代码结构
robosuite/environments/manipulation/
├── two_arm_lift.py # 双臂抬升
├── two_arm_handover.py # 双臂递接
├── two_arm_peg_in_hole.py # 双臂插销
└── two_arm_transport.py # 双臂搬运
关键配置参数:
robots=["Panda", "Panda"] # 两台 Panda
env_configuration="single-arm-opposed" # 对面放置
controller_configs=controller_config # action space 选择
7.3 项目精读清单¶
| 项目 | 精读文件 | 关注点 |
|---|---|---|
| tonyzhaozh/act | detr/models/detr_vae.py |
CVAE Transformer 实现 |
| tonyzhaozh/act | policy.py → ACTPolicy |
temporal ensembling 逻辑 |
| tonyzhaozh/act | sim_env.py |
14 维 qpos 的布局和含义 |
| thu-ml/RoboticsDiffusionTransformer | models/rdt/model.py |
DiT 主干+交替注入 |
| thu-ml/RoboticsDiffusionTransformer | configs/dataset_control_freq.json |
统一 action 映射表 |
| robosuite | two_arm_lift.py |
双臂 RL benchmark 的 reward |
8. 前沿工作与开放问题 ⭐⭐⭐¶
8.1 力反馈增强的双臂学习¶
Bi-ACT(Buamanee-Kobayashi, 2024) 基于四通道双边控制的模仿学习:
- 使用 DOB (Disturbance Observer) + RTOB (Reaction Torque Observer) 无外力传感器估算扭矩
- 在软物体(豆腐、塑料杯)上比位控 ACT 成功率高 2-3 倍
- 硬件成本约为 ALOHA 的 10 倍以上
核心发现:对于接触丰富的软物体操作,力反馈通道提供的信息增益远超视觉——视觉无法判断"夹了多紧",但力反馈可以。
这项工作从控制理论侧验证了一个重要假设:ACT/ALOHA 在接触丰富任务上的成功率瓶颈(<60%),其根本原因不是算法容量不足,而是底层缺少力反馈信息通道。 如果要突破这一瓶颈,需要在硬件层面增加力感知能力。
8.2 语言条件双臂操作¶
PerAct2(Grotz et al., CoRL 2024): - 13 个双臂任务 \(\times\) 23 个变体 = 299 种评估场景 - Voxel-Perceiver 架构预测双臂关键帧 - 语言指令驱动任务选择和执行参数
Stabilize to Act(Grannen et al., CoRL 2023): - 显式建模双臂的"稳定器"和"执行器"角色分工 - 一只手负责稳定物体状态,另一只手执行操作动作 - 这个分工建模与 D03 中的"主臂+从臂"思想相呼应,但通过学习自动发现角色分配
8.3 开放问题——穷举式分类¶
| 维度 | 当前瓶颈 | 可能的突破方向 |
|---|---|---|
| 力控底层 | ACT/RDT-1B 的位控底层在装配/拧紧任务上成功率 <60% | Bi-ACT 路线:加力反馈但成本 \(\times 10\) |
| 泛化能力 | RDT-1B 对未见物体/场景泛化有限 | 更大规模预训练数据 + 3D 表示 |
| 长程推理 | 当前方法在 >30 步任务上衰减严重 | 分层策略 + 任务规划器 |
| 安全性 | RL 探索时碰撞频繁 | 安全 RL (CBF/CPO) 或 constrained policy |
| 数据效率 | 50 demos 足以 ALOHA 但不够泛化 | 仿真生成+domain adaptation |
| 实时性 | RDT-1B 推理 6 chunks/s 对力控不够快 | 模型蒸馏/量化/硬件加速 |
本章小结¶
| 知识点 | 核心结论 | 难度 |
|---|---|---|
| ALOHA 底层控制 | 纯位控——三重论证(硬件/延迟/被动柔顺) | ⭐⭐ |
| ACT Action Chunking | 有效 horizon 从 T 降到 T/k,compounding error 降低 \(k^2\) 倍 | ⭐⭐ |
| ACT CVAE | 潜变量 z 编码执行风格多模态;推理时 z=0 | ⭐⭐⭐ |
| ACT Temporal Ensembling | 多 chunk 指数衰减加权平均,平滑+抗抖动 | ⭐⭐ |
| RDT-1B 128D action space | 统一"身体词表"实现跨平台泛化 | ⭐⭐⭐ |
| 6D 旋转表示 | 旋转矩阵前两列的连续嵌入,解码简单,适合网络回归 | ⭐⭐⭐ |
| Diffusion Policy vs ACT | 并行方案:扩散更高质量但更慢,ACT 更快但需调 KL | ⭐⭐⭐ |
| 双臂 RL MDP | 集中式是默认选择;MARL 仅在 >4 臂时考虑 | ⭐⭐ |
| 维度诅咒 | 14D 可行空间比例 ~1%;任务分解/对称/阻抗 action/课程学习缓解 | ⭐⭐ |
| Reward 设计 | 五维度穷举:任务/协调/内力/对称/安全 | ⭐⭐ |
| Sim-to-Real | 双臂比单臂更难:基座耦合、相对标定、同步延迟 | ⭐⭐⭐ |
累积项目:本章新增模块¶
Mini-DualArm 项目进度:
| 章节 | 新增模块 | 功能 |
|---|---|---|
| D01 | 任务分类器 | 输入任务描述→输出独立/协调/对称类型 |
| D02 | 协调规划器 | 基于虚拟物体的双臂路径规划 |
| D03 | 协调力控器 | 扩展阻抗控制+内力-外力分解 |
| D04 | ACT 训练管线 | 50 demos → ACT 策略训练 → 双臂 14D 控制 |
| D04 | RL 训练管线 | robosuite TwoArmLift + PPO + reward 设计 |
本章新增的两个模块将在 D08(遥操作数据采集)中获得更高质量的训练数据,在 D10(综合实战)中集成到完整系统。
延伸阅读¶
| 资源 | 类型 | 难度 | 关注点 |
|---|---|---|---|
| Zhao et al. 2023, "Learning Fine-Grained Bimanual Manipulation" | 论文 | ⭐⭐ | ACT + ALOHA 原始论文 |
| Chi et al. 2023, "Diffusion Policy" | 论文 | ⭐⭐⭐ | 扩散模型做机器人控制 |
| Liu et al. 2025, "RDT-1B" | 论文 | ⭐⭐⭐ | 大规模双臂基础模型 |
| Zhou et al. 2019, "On the Continuity of Rotation Representations" | 论文 | ⭐⭐⭐⭐ | 6D 旋转表示的数学证明 |
| Ross et al. 2011, "A Reduction of Imitation Learning to No-Regret Online Learning" | 论文 | ⭐⭐ | Compounding error 理论 |
| Chitnis et al. 2020, "Efficient Bimanual Manipulation" | 论文 | ⭐⭐ | 任务 schema 降低探索维度 |
| tonyzhaozh/act GitHub 仓库 | 代码 | ⭐⭐ | ACT 官方实现 |
| thu-ml/RoboticsDiffusionTransformer | 代码 | ⭐⭐⭐ | RDT-1B 官方实现 |
| robosuite 文档 | 文档 | ⭐ | 双臂 RL 环境配置 |
故障排查手册¶
| 症状 | 可能原因 | 排查步骤 | 相关章节 |
|---|---|---|---|
| ACT 训练 loss 不下降 | 数据加载错误/标准化参数不对 | 1. 检查数据 shape 和范围 2. 打印前 5 个 batch 的统计量 3. 确认 action 标准化参数来自训练集 | 本章 3.2 |
| ACT 推理时机械臂抖动 | temporal ensembling 未启用/衰减率 m 过大 | 1. 确认 --temporal_agg 为 True 2. 降低 m 值(试 0.01) 3. 检查 chunk 缓存是否正确更新 |
本章 3.4 |
| 双臂 RL reward 不涨 | 探索不足/reward 各项权重失衡 | 1. 打印各 reward 分项 2. 检查前 100K 步是否有正奖励 3. 添加课程学习(先训单臂) | 本章 5.4 |
| robosuite 双臂 action "串线" | action 维度顺序与假设不符 | 1. 打印 env.action_spec 2. 发送 one-hot action 确认维度 3. 检查 robots 列表顺序 | 本章 5.2 |
| RDT-1B 微调后性能反而下降 | 微调数据太少/学习率过大 | 1. 检查微调数据量(>100 episodes) 2. 降低学习率(1e-5 → 1e-6) 3. 增加预训练权重的 warmup 步数 | 本章 4.4 |