跳转至

本文档属于 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 阻抗导纳二分法

本章目标

学完本章后,你应该能够:

  1. 深入理解 ACT/ALOHA 的底层控制选择——为什么 ALOHA 选位控而非阻抗,从硬件限制、延迟、被动柔顺三个角度严格论证
  2. 掌握 ACT 的三个核心创新(action chunking、CVAE 潜变量 z、temporal ensembling)的数学推导和工程实现
  3. 理解 RDT-1B 的 128 维统一 action space 设计哲学,以及 6D 旋转表示为何优于四元数和欧拉角
  4. 分析 bimanual RL 的特殊挑战——14 维动作空间的探索困难、对称/非对称 reward 设计、内力学习
  5. 实现 在 robosuite TwoArmLift 中训练双臂 RL 策略,对比不同 action space 的样本效率
  6. 批判性评估 当前双臂学习方法的瓶颈与前沿突破方向

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)。理论上可以从电流间接估算扭矩:

\[\hat{\tau}_{motor} = K_t \cdot i_{measured}\]

其中 \(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 映射的数据流极其简洁:

leader.present_position  →  follower.goal_position

这是关节空间的直接映射(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:

\[a = [q_{L,1}, ..., q_{L,7}, q_{R,1}, ..., q_{R,7}, v_{base}, \omega_{base}] \in \mathbb{R}^{16}\]

其中 \(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)\)。联合训练的损失函数为:

\[\mathcal{L}_{co-train} = \alpha \cdot \mathbb{E}_{p_{target}} [\|a - \pi_\theta(o)\|^2] + (1-\alpha) \cdot \mathbb{E}_{p_{aux}} [\|a - \pi_\theta(o)\|^2]\]

\(\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 任务中,答案是演示数量

练习

  1. [A 型 -- 数据流分析] 画出 ALOHA teleop 的完整数据流时序图:从 leader 电机编码器读数开始,经过 U2D2 通信、Python 处理、follower 写入、电机 PID 响应,标注每个环节的延迟。计算理论最大控制频率(不含 time.sleep)
  2. [B 型 -- 硬件对比] 对比 ALOHA (Dynamixel ViperX) 与 Franka 双臂 (两台 Franka Panda) 的硬件规格:自由度、力矩精度、通信延迟、力传感能力。分析在"折叠衣物"和"精密装配"两个任务上,哪个平台更适合,为什么
  3. [思考题] 如果 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)\) 最小化:

\[\mathcal{L}_{BC} = \mathbb{E}_{(o,a) \sim \mathcal{D}} \left[ \|a - \pi_\theta(o)\|^2 \right]\]

问题 1:Compounding Error(复合误差)

BC 是开环的——训练时看到的观测来自专家分布 \(d_{expert}\),但执行时由于微小误差,状态会偏离专家轨迹,落入从未见过的状态分布 \(d_\pi\)。Ross et al. (2011) 证明了误差上界:

\[J(\pi) - J(\pi^*) \leq T^2 \epsilon\]

其中 \(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"):

\[\pi_\theta(o_t) = [a_t, a_{t+1}, ..., a_{t+k-1}]\]

在 ALOHA 中,\(k = 100\),控制频率 50 Hz,因此一个 chunk 预测未来 2 秒的完整运动。

为什么有效——Compounding Error 的数学分析

传统 BC 的有效决策点数为 \(T\)(每步一个决策),误差上界 \(\propto T^2\)

Action chunking 后,有效决策点数减少为 \(T/k\)(每 \(k\) 步一个决策),误差上界变为:

\[J(\pi) - J(\pi^*) \leq \left(\frac{T}{k}\right)^2 \epsilon_{chunk}\]

其中 \(\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)

损失函数

\[\mathcal{L} = \underbrace{\|a_{seq} - \hat{a}_{seq}\|^2}_{\text{重构损失}} + \beta \cdot \underbrace{D_{KL}(q_\phi(z|o, a_{seq}) \| \mathcal{N}(0, I))}_{\text{KL 散度正则}}\]

其中 \(\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\) 个元素)

实际执行的动作是这些预测的加权平均:

\[a_t = \frac{\sum_{i=0}^{k-1} w_i \cdot \hat{a}_t^{(i)}}{\sum_{i=0}^{k-1} w_i}\]

权重使用指数衰减:

\[w_i = \exp(-m \cdot 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

练习

  1. [A 型 -- ACT 复现]tonyzhaozh/act 仓库中运行 sim_transfer_cube_scripted(50 demos),训练 ACT 策略 2000 epochs。记录成功率曲线;消融 --temporal_agg 观察平滑效果
  2. [A 型 -- CVAE 消融] 在同一任务上,对比 \(\beta = 0.1, 1, 10, 100\) 四种 KL 权重。绘制 (a) 训练损失曲线 (b) KL 散度 (c) 评估成功率。验证 \(\beta=10\) 附近是否最优
  3. [思考题] 如果将 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 = [\mathbf{r}_1; \mathbf{r}_2] = [R_{11}, R_{21}, R_{31}, R_{12}, R_{22}, R_{32}] \in \mathbb{R}^6\]

恢复 \(R\) 的过程(Gram-Schmidt 正交化)

\[\mathbf{r}_1' = \text{normalize}(\mathbf{r}_1)$$ $$\mathbf{r}_2' = \text{normalize}(\mathbf{r}_2 - (\mathbf{r}_2 \cdot \mathbf{r}_1')\mathbf{r}_1')$$ $$\mathbf{r}_3' = \mathbf{r}_1' \times \mathbf{r}_2'$$ $$R = [\mathbf{r}_1', \mathbf{r}_2', \mathbf{r}_3']\]

为什么常用于神经网络回归?

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)\) 参数,使得同一网络权重在不同噪声水平下表现出不同的行为:

\[\text{adaLN}(x, t) = \gamma(t) \cdot \frac{x - \mu}{\sigma} + \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 层循环)

优势: 每种模态有专门的层来"消化",减少互相干扰
类比: 像做笔记时交替用不同颜色标记不同类型的信息

扩散过程的数学

前向过程(加噪):

\[a^{(t)} = \sqrt{\bar{\alpha}_t} a^{(0)} + \sqrt{1 - \bar{\alpha}_t} \epsilon, \quad \epsilon \sim \mathcal{N}(0, I)\]

其中 \(\bar{\alpha}_t = \prod_{s=1}^{t} \alpha_s\)\(\alpha_s = 1 - \beta_s\)\(\beta_s\) 是噪声调度。

反向过程(去噪):

\[a^{(t-1)} = \frac{1}{\sqrt{\alpha_t}}\left(a^{(t)} - \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\epsilon_\theta(a^{(t)}, t, c)\right) + \sigma_t z\]

其中 \(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 (预训练优势显现)

练习

  1. [B 型 -- RDT-1B 架构精读] 精读 thu-ml/RoboticsDiffusionTransformermodels/rdt/model.py。画出 alternating condition injection 的详细数据流图。标注每层处理的是哪种模态的条件
  2. [B 型 -- 6D 旋转验证] 实现 6D 旋转表示的编码/解码函数。生成 1000 个随机旋转矩阵,编码为 6D,加入高斯噪声 (\(\sigma=0.01\)),再解码回 \(SO(3)\)。对比 (a) 6D 表示 (b) 四元数 (c) 欧拉角 的旋转误差分布
  3. [思考题] 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

\[\mathcal{M} = (S, A, P, R, \gamma)\]
  • 状态:\(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)

两条臂各有自己的策略,但共享全局奖励:

\[\pi_L(a_L | o_L), \quad \pi_R(a_R | o_R)\]

两种范式的工程对比

特性 集中式 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\)):

\[P_{feasible,single} = p^7 \approx 10\% \quad (p \approx 0.73)$$ $$P_{feasible,dual} = p^{14} \approx 1\% \quad (\text{各维独立假设下})\]

实际上,双臂的可行空间比例远低于 1%,因为: - 两臂之间的碰撞约束额外排除大量配置 - 协调任务中两臂必须满足运动学耦合(如共持物体) - 力约束(内力不能过大/过小)进一步收缩可行域

随机探索效率

在 PPO 中,初始策略输出高斯噪声。对于 14D 高斯分布:

\[\pi_0(a) = \mathcal{N}(0, \sigma^2 I_{14})\]

采样落入可行域的概率极低——实验表明,双臂 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:对称性利用

对于对称任务(两臂角色可互换),可以利用镜像不变性:

\[\pi(s_L, s_R) = \text{mirror}(\pi(s_R, s_L))\]

具体实现:

# 对称性数据增强:每条轨迹自动生成镜像版本
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 思想,扩展到双臂场景:

\[a = [K_L, x_{d,L}, K_R, x_{d,R}, f_{int,ref}]\]

其中: - \(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%

关键观察

  1. 同构遥操作(ACT/ALOHA)的 gap 最小(8-13%)——因为训练数据直接来自真机遥操作,不存在 sim-to-real 转换
  2. 异构仿真→真机(PerAct2/Chitnis)的 gap 最大(24-28%)——接触模型和运动学标定是主要误差来源
  3. 力反馈增强(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}\)

经验公式(双臂搬运任务)

\[r(s, a) = \underbrace{r_{reach}}_{\text{接近物体}} + \underbrace{r_{grasp}}_{\text{抓取成功}} + \underbrace{r_{lift}}_{\text{抬起高度}} + \underbrace{r_{place}}_{\text{放置精度}} + \underbrace{r_{force}}_{\text{内力控制}} + \underbrace{r_{safe}}_{\text{安全惩罚}}\]

每一项的设计细节:

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 或
            通信延迟显著时才考虑

练习

  1. [A 型 -- 双臂 RL 训练] 在 robosuite TwoArmLift 中用 PPO 训练双臂策略。分别用 (a) joint position action (b) 阻抗 action \([K_{abs}, x_{abs}, f_{int}]\)。对比 500K 步后的成功率。提示:使用 stable-baselines3 + robosuite wrapper
  2. [A 型 -- 对称性消融] 在对称的双臂搬运任务中,对比 (a) 不使用对称性 (b) replay buffer 镜像增强 (c) 策略网络共享参数。记录 500K 步的学习曲线
  3. [跨章综合题] 结合 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.stateobservation.images.<cam>actiontimestamp。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.pyACTPolicy 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