跳转至

本文档属于 Robotics Tutorial 项目,作者:Pengfei Guo,达妙科技。采用 CC BY 4.0 协议,转载请注明出处。

第 90 章 UMI-on-Legs 精读——移动底盘上的 Diffusion Policy 操作

难度: ⭐⭐⭐⭐ | 建议时间: 1.5 周 (35-45 小时) | 前置: 复合/180 Deep-WBC, 足式/190 RL 基础, 复合/20 操作基础, 复合/30 MPC 基础

本章定位
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
复合/180 Deep-WBC ──→ [UMI-on-Legs 精读] ──→ 复合/220 移动操作前沿
复合/20 操作基础   ──→ [Diffusion Policy] ──→ 复合/210 RAMBO
足式/190 RL 基础   ──→ [RL WBC 策略]     ──→ 复合/230 VBC 对比
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

前置自测

📋 前置自测(答不出 ≥ 2 题 → 先回复合/180 和复合/20 复习)

  1. 什么是末端执行器(EE)轨迹接口?为什么它比关节角接口更适合跨平台复用?
  2. 扩散模型(Diffusion Model)的前向过程和反向过程分别做什么?训练目标是什么?
  3. 一个 RL 训练的全身控制器(WBC)的观测空间通常包含哪些量?奖励函数如何设计?
  4. 手眼标定(hand-eye calibration)要求解什么方程?AX=XB 的几何含义是什么?
  5. 在 Sim-to-Real 部署中,动作延迟(action delay)会导致什么问题?常见的缓解方法有哪些?

本章目标

学完本章,学员应能:

  1. 解释 UMI-on-Legs 的三层架构设计——感知、规划、执行各层的职责边界
  2. 从零推导 DDPM/DDIM 的去噪过程——理解条件扩散策略如何生成动作序列
  3. 设计 Action Chunking 的时序管线——包括插值、过期检查、延迟补偿
  4. 实现任务帧注册——从示教数据中提取任务坐标系并完成部署时的坐标变换
  5. 分析 14 物体评估的失败模式——将失败归因到系统的具体层次

90.1 动机:为什么要把 UMI 放在腿上? ⭐⭐

90.1.1 固定基座操作的局限

在传统机器人操作研究中,机械臂被安装在固定桌面上。这种设置有一个隐含假设:操作对象永远在臂的工作空间之内。这个假设在工厂产线上成立——零件被传送带精确地送到机器人面前。但在家庭、仓库、户外等非结构化环境中,这个假设彻底失败。

考虑一个具体场景:让机器人从厨房台面上拿起一个杯子,走到客厅放在茶几上。固定基座的臂只能覆盖约 0.8m 半径的工作空间。整个任务需要跨越 5-10m 的距离——这已经超出了任何单臂的物理极限。

传统的解决方案是"移动底盘 + 机械臂"的两阶段方案:先移动到目标附近,停稳,再执行操作。但这种方案有三个根本缺陷:

缺陷 具体表现 根本原因
移动和操作割裂 必须先停下来再操作 底盘控制器和臂控制器各自独立
定位精度要求高 停稳后臂的起始位姿必须精确 两个控制器之间没有闭环耦合
动态环境失效 目标移动时需要重新规划 移动-停止-操作的串行流程太慢

本质洞察:固定基座操作的核心限制不是工作空间大小,而是移动和操作无法同时发生。四足机器人 + 机械臂的组合天然解决了这个问题——腿可以提供移动性,同时臂可以持续操作。但代价是控制复杂度急剧上升:腿的运动会扰动臂的基座,臂的负载会改变身体的质心分布。

90.1.2 为什么选四足而不是轮式?

轮式底盘更简单、更稳定,为什么 UMI-on-Legs 选择四足?

这个选择不是学术上的炫技,而是工程上的必要。非结构化环境的地形——门槛、台阶、不平地面、柔软地毯——对轮式底盘是灾难性的障碍。四足机器人能跨越这些障碍,代价是引入了一个新问题:基座持续晃动。行走时机身的俯仰(pitch)和滚转(roll)波动可达 ±5°,上下颠簸幅度约 2-3cm。这些扰动会直接传递到安装在背上的机械臂末端。

如果不处理这个问题会怎样?假设操作策略输出的是世界坐标系下的末端目标位置 \(\mathbf{p}_{world}^{ee,des}\),而底层控制器只做简单的逆运动学:

\[\mathbf{q}_{arm} = \text{IK}(\mathbf{p}_{world}^{ee,des})\]

当机身向右倾斜 3° 时,如果逆运动学没有考虑基座姿态变化,末端实际位置会偏移约 \(L_{arm} \cdot \sin(3°) \approx 0.5 \text{m} \times 0.052 \approx 2.6 \text{cm}\)。对于精密操作(如插拔 USB),这个误差是不可接受的。

UMI-on-Legs 的解决方案是:让底层全身控制器(WBC)同时控制腿和臂,在行走的同时主动补偿基座扰动。这就是"manipulation-centric whole-body control"的含义——WBC 的首要目标是让末端稳定,行走只是手段。

90.1.3 UMI 的核心思想:示教数据的跨平台复用

UMI (Universal Manipulation Interface, Chi et al., RSS 2024) 的原始版本是一个手持夹爪数据采集工具。操作员手持 UMI 夹爪完成操作示教,GoPro 相机记录腕部视角,SLAM 系统记录夹爪的 6-DoF 轨迹。这些数据被用来训练 Diffusion Policy。

关键洞察在于:UMI 采集的数据完全不涉及机器人本体。数据记录的是"夹爪相对于任务物体应该怎么运动",而不是"某台机器人的关节应该怎么转"。这意味着同一份示教数据可以部署到任何拥有相似夹爪的机器人上——只要底层控制器能跟踪末端轨迹。

UMI 数据流:
┌──────────────┐    ┌───────────────────┐    ┌──────────────────┐
│ 手持示教      │───→│ 任务帧 EE 轨迹     │───→│ Diffusion Policy │
│ (GoPro+SLAM) │    │ {T_task^ee(t)}    │    │ (条件去噪生成)    │
└──────────────┘    └───────────────────┘    └──────────────────┘
                    ┌────────────────────────────────────┘
                    │ 部署时:任务帧 EE 轨迹
        ┌───────────────────────┐
        │  固定臂 / 四足臂 / ...│  ← 不同机器人,同一接口
        │  底层 IK 或 RL WBC    │
        └───────────────────────┘

UMI-on-Legs (Ha et al., CoRL 2024) 的贡献是:证明这个接口可以延伸到移动操作——把 UMI 数据训练的策略直接部署到四足机器人背上的臂上,由 RL 训练的全身控制器执行末端跟踪。

时间线:
2023.03 ─ Chi et al. ─ Diffusion Policy (Chi et al., RSS 2023)
2024.01 ─ Chi et al. ─ UMI: 手持夹爪通用示教接口 (RSS 2024)
2024.07 ─ Ha et al. ─ UMI-on-Legs: 移动底盘上的 UMI (CoRL 2024)
2025    ─ UMI-3D ─ 3D 空间感知扩展

90.1.4 论文核心贡献总结

贡献 具体内容 为什么重要
跨平台接口 任务帧 EE 轨迹作为操作策略和底层控制器的接口 解耦了上层策略和底层硬件
Manipulation-centric WBC RL 训练的 WBC 以末端跟踪为首要目标 行走扰动不影响操作精度
零样本迁移 预训练的 Diffusion Policy 无需微调直接用 证明接口设计的有效性
14 物体评估 系统性的真机实验 + 失败分析 暴露了哪些环节是瓶颈

⚠️ Pitfall: 初学者容易把 UMI-on-Legs 理解为"把臂装在狗上然后训练一个端到端策略"。实际上它的核心不是端到端,而是分层 + 接口设计——上层策略完全不知道下面是什么机器人,下层 WBC 完全不知道上面在执行什么任务。这种解耦是系统能工作的关键。

练习 90.1a (⭐): 计算一个 0.5m 臂长的机械臂,当基座俯仰角波动 ±5° 时,末端位置在垂直方向的偏移范围。如果任务要求精度为 5mm,WBC 需要在多长时间内完成补偿?(提示:考虑四足行走的步态频率约 2Hz。)

练习 90.1b (⭐⭐): 对比"移动-停止-操作"和"移动中操作"两种范式。列出各自的优势场景和失败场景。在哪些任务中"移动中操作"是不可替代的?


90.2 系统架构总览:感知→规划→执行的三层分工 ⭐⭐

90.2.1 整体架构

UMI-on-Legs 的系统分为三个层次,每层有明确的输入、输出和职责边界。理解这三层的分工是理解整个系统的基础。

┌─────────────────────────────────────────────────────────────┐
│                     Layer 1: 感知层                          │
│  输入: 腕部相机 RGB 图像, 机器人本体感知                      │
│  输出: 条件向量 c_t (视觉特征 + 位姿历史)                    │
│  频率: 10-15 Hz (受相机帧率和推理速度限制)                    │
├─────────────────────────────────────────────────────────────┤
│                     Layer 2: 规划层                          │
│  输入: 条件向量 c_t                                         │
│  输出: 未来 EE 轨迹 chunk {T_task^ee(t+k·Δt)}_{k=0}^{K-1}  │
│  频率: 2-5 Hz (DDIM 10步去噪约 50-100ms)                    │
│  核心: Diffusion Policy + Action Chunking                   │
├─────────────────────────────────────────────────────────────┤
│                     Layer 3: 执行层                          │
│  输入: body-frame EE 目标 + 本体感知                         │
│  输出: 12+N 个关节 PD 目标 (4腿×3关节 + N臂关节)             │
│  频率: 50-100 Hz (RL WBC 策略推理)                           │
│  核心: RL-trained Whole-Body Controller                     │
└─────────────────────────────────────────────────────────────┘

三层之间的频率差异是设计的核心难点。感知层以 10-15Hz 提供观测,规划层以 2-5Hz 输出动作片段,执行层以 50-100Hz 发送关节命令。这种频率金字塔要求精心设计的缓冲和插值机制来弥合速率差异。

如果三层以相同频率运行会怎样?假设全部以 50Hz 运行:Diffusion Policy 的单次推理需要约 100ms(DDIM 10 步),远超 20ms 的周期要求。降低执行层频率到 5Hz 以匹配规划层?关节控制在 5Hz 下完全无法抑制高频振动——四足行走的足底冲击频率约 20-30Hz,5Hz 的采样率连 Nyquist 条件都不满足。

本质洞察:三层频率不同不是设计缺陷,而是物理必然。视觉处理、生成式推理、关节伺服——三者的计算密度和物理时间尺度天然不同。UMI-on-Legs 的架构巧妙地利用了 Action Chunking 来桥接这些时间尺度:规划层一次性输出未来 0.5-1 秒的动作,执行层从缓存中逐帧取用。

90.2.2 接口设计:任务帧 EE 轨迹

三层之间的接口是理解系统的关键。上层(规划层)和下层(执行层)之间的接口是任务帧(task frame)下的末端执行器轨迹

\[\mathcal{C}_t = \{(T_{\text{task}}^{ee}(t + k \cdot \Delta t),\ g(t + k \cdot \Delta t))\}_{k=0}^{K-1}\]

其中 \(T_{\text{task}}^{ee} \in SE(3)\) 是末端在任务帧中的位姿,\(g \in [0,1]\) 是夹爪开合度,\(K\) 是 chunk 长度(通常 16-32 步),\(\Delta t\) 是规划层的时间步长。

为什么选择任务帧而不是世界帧或机身帧?

坐标系选择 优势 劣势
世界帧 全局一致 示教和部署的世界帧必须对齐
机身帧 不受移动影响 行走时机身晃动,目标相对于物体在抖
任务帧 与任务物体绑定 需要实时估计任务帧位姿

任务帧通常绑定在操作对象附近——例如门把手的坐标系、抽屉的坐标系、杯子的坐标系。Diffusion Policy 学习的是"相对于任务物体,夹爪应该怎么运动",这与在哪台机器人上执行、机器人站在什么位置完全无关。

从任务帧到执行层需要的机身帧(body frame)目标,需要一条坐标变换链:

\[T_{\text{body}}^{ee} = \left(T_{\text{world}}^{\text{body}}\right)^{-1} \cdot T_{\text{world}}^{\text{task}} \cdot T_{\text{task}}^{ee}\]

每一项的来源和失败模式:

变换 来源 更新频率 典型误差源
\(T_{\text{world}}^{\text{body}}\) IMU + 腿部里程计 100Hz+ 漂移、冲击跳变
\(T_{\text{world}}^{\text{task}}\) 视觉定位 / 初始注册 任务开始时一次 标定误差、遮挡
\(T_{\text{task}}^{ee}\) Diffusion Policy 输出 2-5Hz 模型泛化误差

90.2.3 与 VBC 的对比预览

UMI-on-Legs 使用的是末端轨迹接口——上层输出 \(T_{\text{task}}^{ee}\),下层跟踪。另一种方案是 VBC (Velocity-Based Control),上层输出末端速度指令 \(\mathbf{v}_{ee}^{des}\)

两者的设计差异深刻影响了整个系统的行为:

UMI-on-Legs 接口:               VBC 接口:
上层: "到这个位置"               上层: "以这个速度移动"
      ↓ 位置目标                       ↓ 速度指令
下层: 跟踪误差 → 关节命令         下层: 速度映射 → 关节命令
      ↓                               ↓
优势: 可预测、可回放              优势: 响应快、连续
劣势: 对延迟敏感                  劣势: 积分漂移

💡 Insight: 位置接口 vs 速度接口的选择,类似于 PD 控制中"位置环"vs"速度环"的经典争论。位置接口保证了终态正确性(最终会到达目标位置),但对延迟敏感(过时的位置目标会导致突然跳变)。速度接口响应更快但需要积分器,容易漂移。UMI-on-Legs 选择位置接口是因为 Diffusion Policy 天然输出位置序列,而且 Action Chunking 提供了面对延迟的缓冲。

⚠️ Pitfall: 初学者常认为"位置接口比速度接口简单"。实际上位置接口在移动操作场景中更难——因为机身在移动,世界帧下的 EE 位置目标在不断变化。如果坐标变换链有任何一环出错(例如里程计漂移了 5cm),末端就会偏离目标。

练习 90.2a (⭐): 画出从 Diffusion Policy 输出到关节 PD 目标的完整信号流图,标注每一步的数据格式、坐标系和频率。

练习 90.2b (⭐⭐): 如果 \(T_{\text{world}}^{\text{body}}\) 的估计存在 3cm 的恒定偏差,这个偏差会如何传递到末端?在什么条件下这个偏差不影响任务成功?


90.3 Diffusion Policy 深度解析 ⭐⭐⭐

90.3.1 从生成模型到机器人策略

Diffusion Policy (Chi et al., RSS 2023) 的核心思想是把机器人策略建模为一个条件生成模型:给定当前的观测,从噪声中"去噪"出一个动作序列。

为什么不直接用回归模型(如 MLP)预测动作?考虑一个简单例子:面前有一个杯子,你可以从左边抓或从右边抓。两种方式都是正确的。如果用回归模型(最小化 MSE),它会预测两种方式的平均值——从正上方抓。但正上方可能是一种糟糕的抓取姿态(例如手指无法合拢)。

这就是多模态性(multi-modality)问题。示教数据中同一个场景可能有多种正确的操作方式。回归模型只能给出平均解,而扩散模型可以采样不同模态。

回归模型 vs 扩散模型:

回归:    观测 ──→ [MLP] ──→ 单一动作 (均值)
                              ↕ 平均了多个模态
                              ↕ 可能是非法动作

扩散:    观测 + 噪声 ──→ [去噪网络 × T步] ──→ 一个模态的动作
                   ↕ 从噪声采样                ↕ 是某个真实模态
                   ↕ 不同噪声给出不同模态

跨领域类比:Diffusion Policy 之于机器人控制,类似 Stable Diffusion 之于图像生成。Stable Diffusion 从随机噪声生成图像,条件是文本描述;Diffusion Policy 从随机噪声生成动作序列,条件是视觉观测。两者用的是同一个数学框架,只是"生成什么"不同。

90.3.2 DDPM 前向过程:逐步加噪

前向过程(forward process)定义了如何从干净数据逐步添加噪声。设 \(\mathbf{a}_0\) 是一个干净的动作序列(从示教数据中采样),前向过程定义一个 Markov 链:

\[q(\mathbf{a}_t | \mathbf{a}_{t-1}) = \mathcal{N}(\mathbf{a}_t;\ \sqrt{1 - \beta_t}\, \mathbf{a}_{t-1},\ \beta_t \mathbf{I})\]

其中 \(\beta_t \in (0, 1)\) 是预定义的噪声调度表(noise schedule),\(t = 1, 2, \dots, T\)

直觉理解:每一步把上一步的结果乘以一个略小于 1 的系数(缩小信号),再加上一个小的高斯噪声。经过 \(T\) 步之后,原始信号被完全淹没在噪声中。

利用高斯分布的加法性质,可以推导出任意时刻的边缘分布(不需要逐步模拟):

推导过程

定义 \(\alpha_t = 1 - \beta_t\)\(\bar{\alpha}_t = \prod_{s=1}^{t} \alpha_s\)

Step 1: 写出一步转移: $\(\mathbf{a}_t = \sqrt{\alpha_t}\, \mathbf{a}_{t-1} + \sqrt{1 - \alpha_t}\, \boldsymbol{\epsilon}_{t-1}, \quad \boldsymbol{\epsilon}_{t-1} \sim \mathcal{N}(\mathbf{0}, \mathbf{I})\)$

Step 2: 递归展开两步: $\(\mathbf{a}_t = \sqrt{\alpha_t}\left(\sqrt{\alpha_{t-1}}\, \mathbf{a}_{t-2} + \sqrt{1-\alpha_{t-1}}\, \boldsymbol{\epsilon}_{t-2}\right) + \sqrt{1-\alpha_t}\, \boldsymbol{\epsilon}_{t-1}\)$

\[= \sqrt{\alpha_t \alpha_{t-1}}\, \mathbf{a}_{t-2} + \underbrace{\sqrt{\alpha_t(1-\alpha_{t-1})}\, \boldsymbol{\epsilon}_{t-2} + \sqrt{1-\alpha_t}\, \boldsymbol{\epsilon}_{t-1}}_{\text{两个独立高斯的和}}\]

Step 3: 两个独立高斯 \(\mathcal{N}(0, \sigma_1^2 I)\)\(\mathcal{N}(0, \sigma_2^2 I)\) 的和服从 \(\mathcal{N}(0, (\sigma_1^2 + \sigma_2^2) I)\)。验证方差:

\[\alpha_t(1-\alpha_{t-1}) + (1-\alpha_t) = \alpha_t - \alpha_t\alpha_{t-1} + 1 - \alpha_t = 1 - \alpha_t\alpha_{t-1} = 1 - \bar{\alpha}_t\]

Step 4: 归纳到任意 \(t\)

\[\boxed{q(\mathbf{a}_t | \mathbf{a}_0) = \mathcal{N}(\mathbf{a}_t;\ \sqrt{\bar{\alpha}_t}\, \mathbf{a}_0,\ (1 - \bar{\alpha}_t) \mathbf{I})}\]

等价地:\(\mathbf{a}_t = \sqrt{\bar{\alpha}_t}\, \mathbf{a}_0 + \sqrt{1 - \bar{\alpha}_t}\, \boldsymbol{\epsilon}, \quad \boldsymbol{\epsilon} \sim \mathcal{N}(\mathbf{0}, \mathbf{I})\)

为什么这个公式重要? 训练时不需要模拟 \(T\) 步 Markov 链,而是直接从 \(\mathbf{a}_0\) 跳到任意 \(t\) 时刻的噪声样本。这让训练效率提高了几个数量级。

\(t = T\)\(\bar{\alpha}_T \approx 0\) 时,\(q(\mathbf{a}_T | \mathbf{a}_0) \approx \mathcal{N}(\mathbf{0}, \mathbf{I})\)——原始信号几乎完全消失,只剩纯噪声。

90.3.3 DDPM 反向过程:逐步去噪

反向过程(reverse process)从纯噪声出发,逐步去噪恢复出干净的动作序列。真实的反向条件分布 \(q(\mathbf{a}_{t-1} | \mathbf{a}_t)\) 是难以计算的(需要知道全局数据分布),但当 \(\beta_t\) 足够小时,它近似为高斯分布。

我们用一个参数化的神经网络 \(p_\theta\) 来拟合反向过程:

\[p_\theta(\mathbf{a}_{t-1} | \mathbf{a}_t, \mathbf{c}) = \mathcal{N}(\mathbf{a}_{t-1};\ \boldsymbol{\mu}_\theta(\mathbf{a}_t, t, \mathbf{c}),\ \sigma_t^2 \mathbf{I})\]

其中 \(\mathbf{c}\) 是条件信息(视觉观测),\(\boldsymbol{\mu}_\theta\) 是网络预测的去噪均值。

关键的参数化技巧:与其让网络直接预测均值 \(\boldsymbol{\mu}_\theta\),不如让网络预测噪声 \(\boldsymbol{\epsilon}_\theta\)。利用前向过程的公式,可以从预测的噪声反推均值:

\[\boldsymbol{\mu}_\theta(\mathbf{a}_t, t, \mathbf{c}) = \frac{1}{\sqrt{\alpha_t}} \left(\mathbf{a}_t - \frac{\beta_t}{\sqrt{1 - \bar{\alpha}_t}} \boldsymbol{\epsilon}_\theta(\mathbf{a}_t, t, \mathbf{c})\right)\]

推导

已知 \(\mathbf{a}_t = \sqrt{\bar{\alpha}_t}\, \mathbf{a}_0 + \sqrt{1-\bar{\alpha}_t}\, \boldsymbol{\epsilon}\),反解 \(\mathbf{a}_0\)

\[\mathbf{a}_0 = \frac{\mathbf{a}_t - \sqrt{1-\bar{\alpha}_t}\, \boldsymbol{\epsilon}}{\sqrt{\bar{\alpha}_t}}\]

真实后验 \(q(\mathbf{a}_{t-1} | \mathbf{a}_t, \mathbf{a}_0)\)(注意这里条件包含 \(\mathbf{a}_0\),是可以精确计算的)的均值为:

\[\tilde{\boldsymbol{\mu}}_t = \frac{\sqrt{\bar{\alpha}_{t-1}} \beta_t}{1-\bar{\alpha}_t} \mathbf{a}_0 + \frac{\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_t} \mathbf{a}_t\]

\(\mathbf{a}_0\) 的表达式代入,经过整理得到上式。网络 \(\boldsymbol{\epsilon}_\theta\) 预测的是 \(\boldsymbol{\epsilon}\)(加入的噪声),从而间接给出均值。

训练损失非常简洁:

\[\boxed{\mathcal{L}_{\text{simple}} = \mathbb{E}_{t, \mathbf{a}_0, \boldsymbol{\epsilon}} \left[\|\boldsymbol{\epsilon} - \boldsymbol{\epsilon}_\theta(\underbrace{\sqrt{\bar{\alpha}_t}\,\mathbf{a}_0 + \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}}_{\mathbf{a}_t},\ t,\ \mathbf{c})\|^2\right]}\]

直觉:随机选一个时间步 \(t\),给数据加噪得到 \(\mathbf{a}_t\),让网络预测加入的噪声 \(\boldsymbol{\epsilon}\),MSE 越小越好。

90.3.4 DDIM 加速采样

DDPM 需要 \(T=100\text{-}1000\) 步去噪,每步一次网络推理。在机器人上以 100 步跑一个 U-Net 需要约 500ms——完全无法满足实时性要求。

DDIM (Song et al., ICLR 2021) 的关键发现:去噪过程不需要是 Markov 的。DDIM 构造了一个非 Markov 的反向过程,使得可以跳过中间步骤,用 10-25 步达到 DDPM 100 步的质量。

DDIM 的更新公式:

\[\mathbf{a}_{t-1} = \sqrt{\bar{\alpha}_{t-1}} \underbrace{\left(\frac{\mathbf{a}_t - \sqrt{1-\bar{\alpha}_t}\, \boldsymbol{\epsilon}_\theta(\mathbf{a}_t, t, \mathbf{c})}{\sqrt{\bar{\alpha}_t}}\right)}_{\text{"预测的" } \mathbf{a}_0} + \sqrt{1-\bar{\alpha}_{t-1} - \sigma_t^2}\, \boldsymbol{\epsilon}_\theta(\mathbf{a}_t, t, \mathbf{c}) + \sigma_t \boldsymbol{\epsilon}_t\]

\(\sigma_t = 0\) 时,过程变为完全确定性——给定相同的初始噪声和条件,总是生成相同的动作序列。这个性质对调试非常有用。

采样方法 步数 推理时间 (RTX 3090) 推理时间 (Jetson Orin) 质量
DDPM 100 ~500ms ~2s 最优
DDIM-25 25 ~125ms ~500ms 接近 DDPM
DDIM-10 10 ~50ms ~200ms 略降,实用
DDIM-5 5 ~25ms ~100ms 明显下降

反事实推理:如果 DDIM 没有被发明,Diffusion Policy 在机器人上根本不可行——500ms 的推理延迟意味着机器人每秒只能做 2 次决策,远不够精细操作。DDIM-10 把延迟压到 50ms,配合 Action Chunking(一次输出 16 步动作),有效控制频率达到 10Hz,这才进入实用区间。

90.3.5 条件扩散策略的网络架构

Diffusion Policy 使用 U-Net 或 Transformer 作为去噪网络。在机器人操作中,条件 \(\mathbf{c}\) 包括:

条件向量 c 的构成:
┌──────────────────────────────────────────┐
│ 视觉特征 (腕部相机)                       │
│   └─ ResNet-18 提取 → 512维向量          │
│ 本体感知历史                              │
│   └─ 最近 T_obs 步的 EE 位姿和夹爪状态   │
│ 时间步编码                                │
│   └─ sinusoidal embedding of t           │
└──────────────────────────────────────────┘

去噪网络的输入是噪声动作序列 \(\mathbf{a}_t \in \mathbb{R}^{K \times d_a}\)\(K\) 步,每步 \(d_a\) 维),输出是预测噪声 \(\boldsymbol{\epsilon}_\theta \in \mathbb{R}^{K \times d_a}\)

⚠️ Pitfall: Diffusion Policy 的去噪网络不是在单个动作上工作,而是在整个动作序列上工作。这意味着网络需要同时考虑序列内部的时序一致性。如果把 \(K\) 步动作当作独立样本分别去噪,生成的序列会不连续——相邻动作之间可能有大的跳变。

练习 90.3a (⭐⭐): 从 DDPM 的训练损失出发,推导当 \(t\) 很大(接近 \(T\))时,网络实际上在学习什么;当 \(t\) 很小(接近 0)时,网络在学习什么。提示:考虑 \(\bar{\alpha}_t\) 在两个极端的值。

练习 90.3b (⭐⭐⭐): 实现一个最小的 1D Diffusion Policy:状态是一个标量 \(x\),动作是一个标量 \(a\),示教数据是 \(a = \sin(x)\)\(a = -\sin(x)\) 两个模态的混合。验证扩散模型能采样出两个模态,而 MSE 回归只能给出 \(a = 0\)


90.4 Action Chunking:动作片段的时序设计 ⭐⭐⭐

90.4.1 为什么需要 Action Chunking?

回顾 90.2 中的频率金字塔:Diffusion Policy 以 2-5Hz 输出,执行层以 50-100Hz 运行。如果每次推理只输出下一步的动作,那么在推理的 50-200ms 期间,执行层没有新的目标可用——机器人要么停住等待,要么使用过时的目标。

Action Chunking 的解决方案是:每次推理输出未来 K 步的动作序列(一个"chunk")。执行层从 chunk 中按时间顺序取用动作,直到新的 chunk 到达。

时间轴:
t=0     t=1     t=2     t=3     t=4     t=5     t=6     t=7
│       │       │       │       │       │       │       │
│ 推理开始       │ 推理完成,chunk 到达
│       │       │ [a0, a1, a2, a3, a4, a5, a6, a7]
│       │       │ ←执行→  ←执行→  ←执行→  ←执行→ ...
│       │       │                 │ 新推理开始
│       │       │                 │       │ 新chunk到达
│       │       │                 │       │ [b0, b1, b2, ...]

90.4.2 Chunk 参数设计

Action Chunking 有三个关键参数:

参数 符号 典型值 影响
Chunk 长度 \(K\) 16-32 过短→频繁等待;过长→预测不准
执行步数 \(K_{exec}\) 8-16 过少→浪费计算;过多→使用过时预测
观测窗口 \(T_{obs}\) 2-4 过短→缺乏上下文;过长→特征模糊

执行步数 vs Chunk 长度:虽然每个 chunk 有 \(K\) 步动作,但通常只执行前 \(K_{exec} < K\) 步就丢弃,等待新 chunk。后面的动作预测精度随时间衰减——越远的未来越难准确预测。

跨领域类比:Action Chunking 与 MPC 的 receding horizon 思想异曲同工。MPC 也是每步规划未来 \(N\) 步,只执行第一步然后重新规划。区别在于 MPC 通过优化产生预测,Diffusion Policy 通过生成式推理产生预测。两者都遵循同一个原则:规划要看远处,执行只用近处

90.4.3 Chunk 重叠与时序插值

当新 chunk 到达时,旧 chunk 可能还没执行完。这创造了一个重叠区域——同一时刻有两个(甚至更多个)chunk 给出了不同的动作预测。

UMI-on-Legs 采用指数衰减混合来处理重叠:

\[\mathbf{a}_{exec}(t) = w \cdot \mathbf{a}_{new}(t) + (1-w) \cdot \mathbf{a}_{old}(t), \quad w = 1 - e^{-\lambda \cdot \Delta t_{new}}\]

其中 \(\Delta t_{new}\) 是新 chunk 到达后经过的时间,\(\lambda\) 控制过渡速度。

如果不做混合直接切换会怎样?新旧 chunk 的预测在同一时刻可能相差数厘米。直接切换会产生动作跳变,执行层会响应这个跳变并产生大的关节加速度,轻则导致操作不平滑,重则触发安全保护。

无混合切换:                    有混合过渡:
EE位置                         EE位置
  │    旧chunk                   │    旧chunk
  │   /                          │   /
  │  /                           │  / ─── 平滑过渡
  │ /   跳变!                    │ /  /
  │/    │                        │/ /
  │     │ 新chunk                │ /  新chunk
  │     │/                       │/
  └─────────── t                 └─────────── t

90.4.4 过期检查与安全降级

Action Chunk 有一个隐含的时间戳。当以下情况发生时,chunk 应被标记为"过期":

  1. 推理延迟:Diffusion Policy 推理时间超过预期,chunk 到达时已"迟到"
  2. 感知中断:相机帧丢失,当前 chunk 是基于过时观测生成的
  3. 大扰动:机器人被踢或绊倒,当前 chunk 的前提假设已不成立

过期检查机制:

def check_chunk_validity(chunk, current_state, config):
    """检查 action chunk 是否仍然有效"""
    # 1. 时间戳检查:chunk 是否太旧?
    age = current_time - chunk.timestamp
    if age > config.max_chunk_age:  # 典型值: 0.5s
        return EXPIRED, "chunk 超时"

    # 2. 状态偏差检查:当前状态是否偏离 chunk 的起始假设?
    ee_deviation = norm(current_ee_pose - chunk.expected_ee_pose_at(current_time))
    if ee_deviation > config.max_ee_deviation:  # 典型值: 5cm
        return DEVIATED, "末端偏离过大"

    # 3. 安全检查:chunk 中剩余动作是否会导致危险?
    for future_action in chunk.remaining_actions():
        if not is_within_workspace(future_action):
            return UNSAFE, "未来动作超出工作空间"

    return VALID, "chunk 有效"

当 chunk 被判定为无效时,安全降级策略有三种选择:

策略 行为 适用场景
冻结 保持当前 EE 位姿不变,等待新 chunk 短暂延迟
回缩 慢速将 EE 移向安全位姿(如身体上方) 感知中断
紧停 锁定所有关节,触发 E-stop 硬件故障

⚠️ Pitfall: Action Chunking 最隐蔽的 bug 是时间戳不对齐。如果 chunk 的时间戳用的是 GPU 的时钟,而执行层用的是 CPU 的时钟,两个时钟之间可能有毫秒级偏差。在 10Hz 的控制频率下,1ms 的偏差看起来不大;但如果 chunk 的时间步 \(\Delta t = 50\text{ms}\),1ms 偏差意味着在 50 个 chunk 后累积到 50ms——整整一个时间步的漂移。所有时钟必须同步到同一个时间源(通常是系统单调时钟 CLOCK_MONOTONIC)。

练习 90.4a (⭐⭐): 设计一个实验:比较 \(K_{exec} = K\)(执行完整 chunk)和 \(K_{exec} = K/2\)(只执行前半)的表现差异。预测哪种设置在以下场景中更好:(1) 静态环境中的精密操作;(2) 动态环境中的快速抓取。

练习 90.4b (⭐⭐⭐): 实现指数衰减混合的 chunk 融合算法。输入是旧 chunk 和新 chunk 的动作序列以及时间戳,输出是融合后的执行动作。考虑 SE(3) 空间中的插值(位置用线性插值,旋转用 SLERP)。


90.5 任务帧注册:从示教数据中提取任务坐标系 ⭐⭐⭐

90.5.1 什么是任务帧?

任务帧(task frame)是绑定在操作对象上的坐标系。它的原点通常选在操作的"焦点"——门把手的转轴、杯子的中心、抽屉的把手中心。它的朝向按照任务的自然方向定义——例如开门任务中,任务帧的 x 轴指向门的打开方向。

为什么不直接用世界帧?因为同一个任务(比如"打开门")在不同位置执行时,世界帧下的 EE 轨迹完全不同。但在任务帧下,无论门在房间的哪个位置,"推门把手"的运动模式是相同的。

反事实推理:如果 Diffusion Policy 在世界帧下训练,它需要记住"门在 (1.2, 3.5) 米处时右手从右边推,门在 (0.5, 2.1) 米处时左手从左边推"——这需要海量数据覆盖所有可能的空间位置。而在任务帧下,一个位置的示教就足以泛化到所有位置。

90.5.2 任务帧的注册流程

在部署时,系统需要知道任务帧在世界坐标系中的位置——这个过程叫做"任务帧注册(task frame registration)"。UMI-on-Legs 使用以下流程:

任务帧注册流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 1: 操作员手动指定任务帧
   └─ 方式 A: 让机器人的夹爪触碰操作对象的参考点
   └─ 方式 B: 视觉检测物体位姿 (ArUco/AprilTag)
   └─ 方式 C: 使用示教时记录的参考位姿

Step 2: 记录 T_world^task
   └─ 从 Step 1 的结果得到任务帧在世界中的位置

Step 3: 在任务执行期间保持 T_world^task 不变
   └─ 假设操作对象不移动 (静态任务帧)
   └─ 或实时更新 (动态任务帧, 需要持续的视觉追踪)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

静态 vs 动态任务帧

场景 任务帧类型 注册方式
打开固定的门 静态 开始时注册一次
从移动传送带上取物 动态 视觉持续追踪
在行走中抓桌上物体 准静态 定期重新注册

90.5.3 坐标变换链的数值稳定性

完整的坐标变换链中,每一步都可能引入误差。误差在链式乘法中累积而非抵消。

设各环节的位置误差为 \(\delta_1, \delta_2, \delta_3\),末端的总误差:

\[\|\delta_{total}\| \leq \|\delta_1\| + \|\delta_2\| + \|\delta_3\| + \text{交叉项}\]

旋转误差的情况更复杂。两个旋转矩阵各有小角度误差 \(\delta R_1, \delta R_2\) 时:

\[R_{total} = (R_1 \cdot \delta R_1)(R_2 \cdot \delta R_2) = R_1 R_2 \cdot R_2^{-1} \delta R_1 R_2 \cdot \delta R_2\]

交叉项 \(R_2^{-1} \delta R_1 R_2\) 表明:上游的旋转误差会被下游的旋转"放大"。如果 \(R_2\) 是一个大角度旋转,它会把 \(\delta R_1\) 的误差方向旋转到不同的轴上,可能从一个不敏感的方向变到一个敏感的方向。

⚠️ Pitfall: 坐标变换中最常见的 bug 是四元数未归一化。经过多次乘法后,浮点误差导致四元数的模不再是 1。模偏离 1 超过 \(10^{-6}\) 时,旋转矩阵不再正交,逆运动学会给出错误的关节角。正确做法是每次乘法后重新归一化:q = q / q.norm()

90.5.4 从 UMI 示教数据中提取任务帧

UMI 的示教数据由 GoPro 相机的 SLAM 系统提供 6-DoF 夹爪轨迹。但原始轨迹是在SLAM 坐标系下的——这个坐标系的原点和朝向取决于 SLAM 初始化时相机的位置和方向,是随机的。

任务帧提取的关键步骤:

  1. 选择参考时刻:通常是操作开始的时刻(如夹爪接触物体的瞬间)
  2. 定义任务帧原点:参考时刻的夹爪位置(或由操作员指定的物体上的点)
  3. 定义任务帧朝向:从操作轨迹的主方向提取
示例:开门任务
━━━━━━━━━━━━━━
原始 SLAM 轨迹: 手持夹爪从左到右画弧

参考时刻: 夹爪碰到门把手的瞬间
任务帧原点: 门把手的位置
任务帧 x 轴: 从门轴到门把手 (门的打开方向)
任务帧 z 轴: 垂直向上

转换后: 所有 EE 轨迹变成 "相对于门把手, 手怎么动"
        → 这个表示与门的世界坐标位置无关

90.5.5 任务帧的鲁棒性分析

任务帧注册的精度直接影响操作成功率。让我们量化分析不同误差源的影响。

设任务帧在世界坐标系中的真实位姿为 \(T_{world}^{task,true}\),估计的位姿为 \(T_{world}^{task,est}\),误差为 \(\delta T = T_{world}^{task,est} \cdot (T_{world}^{task,true})^{-1}\)

对于位置误差 \(\delta p\) 和旋转误差 \(\delta \theta\),末端轨迹的误差放大取决于操作的空间范围 \(L\)

误差类型 末端误差 量级估计 (L=0.3m)
位置 \(\delta p\) \(\delta p\) 直接传递
旋转 \(\delta \theta\) \(L \sin(\delta\theta) \approx L \cdot \delta\theta\) \(\delta\theta = 2° → 0.3 \times 0.035 = 1.05\)cm
位置+旋转耦合 \(\delta p + L\delta\theta\) 叠加

关键观察:旋转误差通过操作范围 \(L\) 被放大。对于大范围操作(如整臂伸展 L=0.5m),即使 2° 的任务帧旋转误差也会导致末端偏差 1.7cm——这已经是很多精细操作的容忍上限。

动态任务帧的更新策略

对于需要动态更新的任务帧(如目标物体可能被移动),更新策略有三种:

策略 A: 每帧更新 (最精确, 最不稳定)
  每次视觉检测 → 更新 T_world^task
  → 问题: 检测噪声直接传递到目标, 导致 EE 抖动

策略 B: 滤波更新 (折中)
  视觉检测 → Kalman 滤波 → 更新 T_world^task
  → 优势: 抑制噪声, 平滑变化
  → 参数: 过程噪声 Q 和观测噪声 R 需要调参

策略 C: 事件触发更新 (最稳定)
  仅当 ||T_new - T_old|| > threshold 时才更新
  → 优势: 避免小幅抖动
  → 问题: 对大的突变反应延迟

在 UMI-on-Legs 中,大部分任务使用静态任务帧(策略 C 的极端情况——只在任务开始时注册一次),因为操作对象通常不会自己移动。

练习 90.5a (⭐⭐): 给定两次不同位置的开门示教数据(SLAM 坐标系下),设计算法提取统一的任务帧。提示:利用示教轨迹中夹爪接触门把手的位置作为原点对齐。

练习 90.5b (⭐⭐⭐): 考虑一个"倒水"任务,任务帧应该绑定在杯子上还是水壶上?如果水壶是固定的(放在桌上),杯子是机器人拿着的,答案是否改变?分析两种选择各自的优劣。


90.6 腕部相机管线:视觉观测流水线 ⭐⭐⭐

90.6.1 为什么用腕部相机而不是头部相机?

UMI-on-Legs 使用安装在夹爪/机械臂腕部的相机作为主要视觉输入。这个选择背后有深刻的工程考量。

头部相机(或身体固定相机)的问题:四足行走时身体持续晃动,头部相机看到的图像也在晃动。更严重的是,操作物体可能被机械臂自身遮挡——当臂在身体前方操作时,头部相机可能根本看不到操作区域。

腕部相机的优势:它与夹爪刚性连接。无论机身怎么晃动,腕部相机看到的是夹爪"眼前"的场景——操作对象始终在视野中央。这和人类的视觉系统不同(人用头部的眼睛看手操作的物体),但对机器人而言更高效。

相机位置 与操作物体的相对运动 遮挡风险 标定复杂度
头部 大(身体+臂运动叠加) 高(臂可能遮挡) 需要全身运动学
肩部 中(臂运动) 需要臂运动学
腕部 小(只有手指运动) 低(始终朝向物体) 只需手眼标定
外部固定 无(但受环境限制) 需要世界帧标定

90.6.2 视觉特征提取

腕部相机输出 RGB 图像(通常 640×480 或 320×240),需要编码为策略可用的特征向量。UMI-on-Legs 使用 ResNet-18 的前几层作为视觉编码器,输出 512 维特征。

完整的视觉管线:

原始图像 (640×480×3)
    ├── 1. 预处理
    │   ├── 裁剪: 去除不相关区域
    │   ├── 缩放: → 224×224 (ResNet 输入尺寸)
    │   └── 归一化: ImageNet 均值/标准差
    ├── 2. 特征提取
    │   ├── ResNet-18 conv1-conv4
    │   ├── Global Average Pooling
    │   └── → 512维特征向量
    └── 3. 时间堆叠
        ├── 保留最近 T_obs 帧的特征
        └── → (T_obs × 512) 的条件矩阵

90.6.3 时间同步:视觉和本体感知的对齐

视觉管线的延迟约 30-50ms(相机曝光 + 图像传输 + 特征提取)。本体感知(关节编码器、IMU)的延迟约 1-2ms。如果不对齐,策略收到的条件向量中,视觉和本体感知描述的是不同时刻的状态。

在 10Hz 的操作频率下,50ms 的时间差意味着视觉和本体感知之间差了半个控制步。如果机器人正以 0.3m/s 移动,50ms 对应 1.5cm 的位移——这个量级已经足以影响精密操作。

同步策略:

方案 A: 延迟对齐 (推荐)
━━━━━━━━━━━━━━━━━━━━━
把本体感知数据延迟到与视觉对齐
    t_visual  ──→ 时间戳 t-Δ
    t_proprio ──→ 缓存, 取时间戳 t-Δ 的数据
    → 两者对齐, 但整体观测延迟了 Δ

方案 B: 预测补偿
━━━━━━━━━━━━━━━━━━━━━
用本体感知预测未来 Δ 时刻的状态
    t_visual  ──→ 时间戳 t-Δ
    t_proprio ──→ 当前 + 预测到 t-Δ 的差
    → 减少延迟, 但预测不准确引入新误差

⚠️ Pitfall: 视觉管线中最致命的 bug 不是特征提取不好,而是图像时间戳标错。如果系统用的是图像到达 CPU 的时间而非相机曝光的时间,所有基于时间戳的同步都是错的。USB 相机的传输延迟可以有 10-100ms 的抖动(取决于系统负载),必须使用相机硬件时间戳(V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)。

90.6.4 图像增广与视觉鲁棒性

训练 Diffusion Policy 时,视觉输入需要数据增广来提高鲁棒性。但机器人操作的增广策略与图像分类不同——不能随意翻转或大幅旋转图像,因为这些变换会改变操作的空间语义。

适合机器人操作的增广策略:

增广类型 参数范围 适用 不适用
颜色抖动 (brightness/contrast) ±15% 光照变化 暗环境操作
随机裁剪 (crop) ±10% 相机位置微移 大幅裁剪改变空间关系
高斯模糊 σ ∈ [0, 1.5] 焦距不准 过度模糊丢失关键特征
随机擦除 <10% 面积 遮挡鲁棒 擦除操作物体本身
水平翻转 禁止 改变左右方向
大角度旋转 禁止 改变重力方向的语义

⚠️ Pitfall: 初学者从计算机视觉(图像分类)迁移过来时,习惯使用激进的数据增广(如 RandAugment)。但在机器人操作中,图像的空间结构承载了关键信息——物体在画面上方还是下方对应了不同的物理位置。随机旋转 90° 会让"向上抓取"变成"向右抓取",完全破坏了动作标签的正确性。

90.6.5 相机内参与外参的标定

腕部相机的内参(焦距、畸变系数)和外参(相对于工具中心点的位姿)都需要标定。

内参标定:使用 OpenCV 的 calibrateCamera 函数,采集 15-30 张棋盘格图像。对于 GoPro 等广角相机,特别注意桶形畸变的校正——未校正的畸变会导致图像边缘的物体位置估计偏差达到 3-5%。

外参标定的在线验证方法:部署后在机器人末端安装一个已知尺寸的标记物(如 10cm 的 ArUco 标记),让机器人移动到已知位置,比较视觉估计的标记物位姿与运动学计算的位姿。如果重投影误差 > 5 pixel(在 640×480 图像上),外参需要重新标定。

# 简化的外参验证代码
def verify_hand_eye(T_cam_ee, camera_matrix, T_base_ee, T_base_marker_gt):
    """验证手眼标定的外参精度"""
    # 从相机检测标记物
    T_cam_marker = detect_aruco(image, camera_matrix)

    # 通过运动学 + 手眼外参计算标记物在基座下的位姿
    T_base_marker_est = T_base_ee @ T_cam_ee.inverse() @ T_cam_marker

    # 计算与真值的误差
    pos_error = np.linalg.norm(
        T_base_marker_est[:3, 3] - T_base_marker_gt[:3, 3]
    )
    rot_error = rotation_angle_error(
        T_base_marker_est[:3, :3], T_base_marker_gt[:3, :3]
    )

    print(f"位置误差: {pos_error*100:.1f} cm")
    print(f"旋转误差: {np.degrees(rot_error):.1f} deg")

    assert pos_error < 0.02, "位置误差 > 2cm, 需重新标定"
    assert rot_error < np.radians(3), "旋转误差 > 3°, 需重新标定"

练习 90.6a (⭐⭐): 设计一个实验来测量视觉管线的端到端延迟。提示:在相机视野中放一个快速闪烁的 LED(由已知时间戳的 GPIO 控制),通过比较 LED 闪烁时刻和图像帧中检测到闪烁的时刻来测量延迟。

练习 90.6b (⭐⭐⭐): 如果腕部相机的桶形畸变系数为 \(k_1 = -0.3\)(典型的 GoPro 值),计算图像边缘(距中心 200 pixel)处一个点的实际位置偏差。如果不校正,这个偏差在 30cm 操作距离下对应多少毫米的 3D 位置误差?


90.7 RL WBC 底层策略:观测与奖励设计 ⭐⭐⭐

90.7.1 WBC 的角色

UMI-on-Legs 的底层是一个 RL 训练的全身控制器(Whole-Body Controller)。它的唯一职责是:给定 body frame 下的 EE 目标位姿,输出所有关节的 PD 目标,使得腿稳定行走的同时臂精确跟踪。

这与传统的优化型 WBC (如 TSID) 有本质不同:

维度 优化型 WBC (TSID) RL WBC
计算方式 在线求解 QP 前向推理神经网络
模型需求 精确的 URDF + 接触力 不需要显式模型
鲁棒性 模型精度敏感 通过 domain randomization 鲁棒
可解释性 可分析约束和优先级 黑盒
计算耗时 1-5ms (CPU) 0.1-0.5ms (GPU)

回顾复合/180 Deep-WBC:在那一章我们讨论了 RL WBC 的基本框架——Privileged Learning + Domain Randomization。教师策略在完美信息下训练,学生策略从受限观测中学习。UMI-on-Legs 的 WBC 正是这个框架的一个实例,不同之处在于它的奖励函数以末端跟踪精度为最高优先级。

90.7.2 观测空间设计

WBC 策略的观测空间需要包含足够的信息来实现稳定行走 + 精确跟踪。典型设计:

观测向量 o_t ∈ R^{d_obs}:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[本体感知]
  关节角度     q_joint ∈ R^{12+N}     (12腿关节 + N臂关节)
  关节角速度   dq_joint ∈ R^{12+N}
  基座角速度   ω_body ∈ R^3           (来自 IMU)
  基座方向     R_body ∈ R^6           (重力方向的投影)

[目标信息]
  EE 目标位置   p_ee^des ∈ R^3        (body frame)
  EE 目标朝向   R_ee^des ∈ R^6        (6D rotation representation)
  夹爪目标      g^des ∈ R^1

[命令]
  速度命令     v_cmd ∈ R^3            (行走速度/转向)

[历史]
  上一步动作   a_{t-1} ∈ R^{12+N}

总维度: 约 60-80 维 (取决于臂的自由度 N)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

为什么用 6D 旋转表示而不是四元数? Zhou et al. (CVPR 2019) 证明了 4 维表示(如四元数)不能连续地映射整个 SO(3)——存在不可避免的不连续性。6D 表示(旋转矩阵的前两列)是连续的,神经网络更容易学习。

⚠️ Pitfall: 观测中的"上一步动作"容易被忽略,但它对平滑性至关重要。没有动作历史,策略可能在两个相似的状态下输出差别很大的动作(因为策略是无记忆的 MLP),导致关节抖动。包含上一步动作让策略能保持一定的时间连贯性。

90.7.3 奖励函数设计

UMI-on-Legs 的 WBC 是"manipulation-centric"的——末端跟踪精度是最高优先级。奖励函数反映了这个设计意图:

\[r_t = \underbrace{w_{ee} \cdot r_{ee}}_{\text{末端跟踪 (最重要)}} + \underbrace{w_{base} \cdot r_{base}}_{\text{基座稳定}} + \underbrace{w_{smooth} \cdot r_{smooth}}_{\text{动作平滑}} + \underbrace{w_{alive} \cdot r_{alive}}_{\text{存活奖励}}\]

各分项的详细设计:

奖励分项 公式 权重 含义
EE 位置跟踪 \(-\|p_{ee} - p_{ee}^{des}\|^2\) 高 (10.0) 末端位置误差越小越好
EE 朝向跟踪 \(-\|R_{ee}^T R_{ee}^{des} - I\|_F^2\) 高 (5.0) 末端旋转误差
基座高度 $- h_{base} - h_{nom} ^2$
基座倾斜 \(-\|\theta_{roll,pitch}\|^2\) 中 (1.0) 身体保持水平
动作变化率 \(-\|a_t - a_{t-1}\|^2\) 中 (1.0) 关节命令平滑
关节力矩 \(-\|\tau\|^2\) 低 (0.1) 能量效率
接触奖励 \(+1\) if 足底接触正常 中 (1.0) 鼓励正确步态

权重设计的直觉:末端跟踪的权重远高于其他项。这意味着策略在面临"跟踪末端 vs 保持身体水平"的 trade-off 时,会优先选择跟踪末端——即使这意味着身体稍微倾斜。这就是"manipulation-centric"的具体体现。

如果反过来,基座稳定的权重更高会怎样?策略会优先保持身体水平,当行走扰动来临时,它会牺牲末端跟踪精度来维持身体姿态。这在纯行走任务中是正确的,但在操作任务中会导致末端抖动——每次迈步都会影响操作精度。

90.7.4 Domain Randomization

WBC 在仿真中训练,需要 Domain Randomization 来缩小 Sim-to-Real Gap:

随机化参数 范围 作用
地面摩擦系数 [0.3, 1.5] 适应不同地面
负载质量 [0, 2.0] kg 适应不同操作对象
基座质量偏移 [-0.5, 0.5] kg 补偿建模误差
电机延迟 [0, 20] ms 适应通信延迟
PD 增益 ±20% 补偿执行器参数
地形坡度 [0, 15°] 适应不平地面
传感器噪声 ±5% 适应传感器精度

90.7.5 WBC 训练的 Sim-to-Real 关键因素

WBC 的 Sim-to-Real 迁移有几个特别需要注意的因素:

执行器模型:仿真中的理想电机(给力矩立刻产生运动)与真实电机差距很大。真实电机有:

  1. 力矩延迟:从命令发出到力矩实际产生,约 5-15ms
  2. 力矩带宽限制:高频力矩命令会被电机的电气时间常数衰减
  3. 反电动势:高速运动时实际可用力矩减少
  4. 摩擦和齿隙:减速器的非线性摩擦
理想电机 vs 真实电机:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
理想:  τ_cmd ──→ τ_actual = τ_cmd (瞬时)

真实:  τ_cmd ──→ [延迟 10ms] ──→ [低通滤波]
              ──→ [摩擦+齿隙] ──→ τ_actual ≠ τ_cmd

仿真中的简化模型:
  τ_actual(t) = τ_cmd(t - Δt) * (1 - friction_coeff * sign(dq))
  Δt ~ Uniform(5, 20) ms  ← Domain Randomization
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

地面接触模型:仿真器(MuJoCo, Isaac)的接触模型使用 penalty 方法或解析接触——真实世界的接触更复杂(弹性变形、接触面积随力变化)。Domain Randomization 通过随机化地面刚度和阻尼来缓解这个 gap。

90.7.6 从 Manipulation-Centric 到 Locomotion-Centric 的切换

UMI-on-Legs 的 WBC 是 manipulation-centric 的——末端跟踪优先。但有些场景(如爬楼梯时暂时不操作)需要切换到 locomotion-centric 模式。

一种实现方式是奖励权重的动态调节

\[w_{ee}(t) = \begin{cases} w_{ee}^{high} = 10.0 & \text{if 操作模式} \\ w_{ee}^{low} = 1.0 & \text{if 行走模式} \end{cases}\]

但在训练时不能使用两套固定权重(会导致策略在模式边界处行为不连续)。更好的做法是把模式权重作为观测的一部分,让策略学会根据权重信号调整行为。

⚠️ Pitfall: 模式切换时最常见的问题是末端位姿跳变。从行走模式切换到操作模式时,如果末端目标突然从"身体上方的默认位姿"变成"操作物体附近的位姿",跳变可能导致大的关节加速度。正确做法是在切换时用平滑的插值(如最小 jerk 轨迹)从当前位姿过渡到目标位姿,过渡时间约 0.5-1.0s。

练习 90.7a (⭐⭐): 在 Isaac Lab/Gym 中实现一个简化版的 WBC 训练环境。只需要 2D(sagittal plane)的四足模型 + 1-DoF 臂。设计奖励函数使得臂能在行走时保持末端高度恒定。

练习 90.7b (⭐⭐⭐): 设计一个消融实验:分别移除 EE 跟踪奖励和基座稳定奖励,观察策略行为的变化。预测结果并验证。


90.8 夹爪与工具标定 ⭐⭐

90.8.1 手眼标定的经典问题

腕部相机安装在机械臂末端,其相对于工具中心点(TCP)的变换是固定但未知的。这个变换称为手眼标定(hand-eye calibration)

经典手眼标定问题的数学形式化:

\[\mathbf{A}_i \mathbf{X} = \mathbf{X} \mathbf{B}_i, \quad i = 1, 2, \dots, n\]

其中 \(\mathbf{A}_i\) 是两次机器人运动之间的末端位姿变化(来自运动学),\(\mathbf{B}_i\) 是对应的相机观测变化(来自视觉),\(\mathbf{X}\) 是相机到末端的未知变换。

几何直觉:想象你在转头(末端运动 \(\mathbf{A}\)),同时看世界在旋转(相机观测变化 \(\mathbf{B}\))。\(\mathbf{X}\) 就是眼睛在头上的安装位置——知道了头怎么转、世界看起来怎么变,就能反推眼睛装在哪里。

90.8.2 UMI 特有的标定挑战

UMI 的手持夹爪使用 GoPro 相机,安装在 3D 打印的支架上。与工业级安装相比:

挑战 原因 影响
安装精度低 3D 打印公差 ±0.5mm 外参初始偏差大
重复性差 每次安装位置略有不同 每次都需要重新标定
运行中松动 操作时的冲击和振动 外参随时间漂移

标定流程:

UMI 标定流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. 打印标定靶 (ArUco 板)

2. 手持 UMI 夹爪, 从多个角度拍摄标定靶
   → 至少 15 个不同位姿
   → 确保位姿多样性 (不要只在一个平面上)

3. 用 SLAM 系统记录每个位姿的夹爪 6-DoF 位置

4. 用相机检测每帧中标定靶的位姿

5. 求解 AX=XB 得到手眼变换 X

6. 验证: 用独立的测试位姿检查重投影误差
   → 重投影误差 < 2 pixel 为合格
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠️ Pitfall: 手眼标定中最常见的错误是旋转和平移的量纲不一致\(\mathbf{A}\) 矩阵中旋转部分是弧度(无量纲),平移部分是米。如果在求解 \(\mathbf{AX} = \mathbf{XB}\) 时用 Frobenius 范数做误差度量,平移误差会被旋转误差淹没(旋转值通常 <1 rad,平移值通常 >0.01 m)。正确做法是对旋转和平移分别求解或使用加权范数。

90.8.3 Tsai 方法求解 AX=XB

经典的 AX=XB 求解方法由 Tsai & Lenz (1989) 提出。其核心思想是将旋转和平移分离求解。

Step 1: 求解旋转部分

\(\mathbf{A}_i \mathbf{X} = \mathbf{X} \mathbf{B}_i\) 中分离旋转:

\[\mathbf{R}_A^{(i)} \mathbf{R}_X = \mathbf{R}_X \mathbf{R}_B^{(i)}\]

利用旋转的轴-角表示。设 \(\mathbf{R}_A^{(i)}\) 的旋转轴为 \(\hat{\mathbf{n}}_A^{(i)}\)、角度为 \(\theta_A^{(i)}\)\(\mathbf{R}_B^{(i)}\) 的旋转轴为 \(\hat{\mathbf{n}}_B^{(i)}\)、角度为 \(\theta_B^{(i)}\)

Tsai 证明了一个关键性质:\(\theta_A^{(i)} = \theta_B^{(i)}\)(旋转角相同,因为是同一次运动在两个坐标系下的描述),且:

\[\hat{\mathbf{n}}_A^{(i)} = \mathbf{R}_X \hat{\mathbf{n}}_B^{(i)}\]

利用至少两组运动数据,可以建立旋转方程求解 \(\mathbf{R}_X\)

Step 2: 求解平移部分

已知 \(\mathbf{R}_X\) 后,从 \(\mathbf{A}_i \mathbf{X} = \mathbf{X} \mathbf{B}_i\) 中提取平移方程:

\[\mathbf{R}_A^{(i)} \mathbf{t}_X + \mathbf{t}_A^{(i)} = \mathbf{R}_X \mathbf{t}_B^{(i)} + \mathbf{t}_X\]

整理为:

\[(\mathbf{R}_A^{(i)} - \mathbf{I}) \mathbf{t}_X = \mathbf{R}_X \mathbf{t}_B^{(i)} - \mathbf{t}_A^{(i)}\]

这是关于 \(\mathbf{t}_X\) 的线性方程组。至少需要 2 组运动数据(实际使用 10+ 组以提高精度),用最小二乘求解。

⚠️ Pitfall: Tsai 方法要求运动对的旋转轴不平行——如果所有运动都围绕同一轴旋转,方程退化(奇异)。采集标定数据时应确保从多个不同方向观察标定靶,旋转轴至少覆盖 3 个线性无关的方向。

90.8.4 在线外参监控

在长时间部署中,外参可能因振动松动而漂移。一个实用的在线监控方法:

# 在线外参漂移检测
class HandEyeMonitor:
    def __init__(self, T_cam_ee_calib, threshold_pos=0.005, threshold_rot=0.05):
        self.T_calib = T_cam_ee_calib  # 标定时的外参
        self.threshold_pos = threshold_pos  # 5mm
        self.threshold_rot = threshold_rot  # ~3°
        self.check_history = []

    def check(self, T_base_ee_fk, T_base_marker_visual, T_marker_ee_known):
        """通过已知参考物体检测外参漂移"""
        # 从视觉+运动学反推当前外参
        T_cam_ee_current = (
            T_base_ee_fk.inverse() @ T_base_marker_visual @ T_marker_ee_known
        )

        # 与标定值比较
        delta = self.T_calib.inverse() @ T_cam_ee_current
        pos_drift = np.linalg.norm(delta[:3, 3])
        rot_drift = rotation_angle(delta[:3, :3])

        self.check_history.append((pos_drift, rot_drift))

        if pos_drift > self.threshold_pos or rot_drift > self.threshold_rot:
            return WARNING, f"外参漂移: pos={pos_drift*100:.1f}cm, rot={np.degrees(rot_drift):.1f}°"
        return OK, "外参稳定"

练习 90.8a (⭐⭐): 如果手眼标定的外参 \(\mathbf{X}\) 有 1cm 的平移偏差,计算在不同操作距离(10cm, 30cm, 50cm)下末端位置的相对误差。在哪个距离范围内这个偏差可以忽略?

练习 90.8b (⭐⭐⭐): 实现 Tsai 方法的简化版本:给定 5 组 (A, B) 矩阵对,求解 X。用合成数据(已知 X,生成 A 和 B)验证算法的正确性。添加不同水平的噪声(0.1°, 0.5°, 1° 旋转噪声 + 0.1mm, 0.5mm, 1mm 平移噪声),绘制估计误差随噪声的变化。


90.9 延迟处理:动作片段的延迟随机化 ⭐⭐⭐

90.9.1 延迟的来源与量级

在真机部署中,从观测到动作的整个管线有多个延迟源:

延迟分解:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
相机曝光        ~10ms
图像传输 (USB3) ~5-15ms
视觉编码        ~10-20ms  (GPU)
Diffusion推理   ~50-100ms (GPU, DDIM-10)
动作传输        ~1-5ms
关节控制延迟     ~5-10ms
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
总计:           ~80-160ms

80-160ms 的延迟意味着:当机器人执行动作时,这个动作是基于 80-160ms 之前的观测做出的。如果机器人正以 0.2m/s 移动,动作的执行位置与决策位置之间差了 1.6-3.2cm。

90.9.2 延迟随机化训练

UMI-on-Legs 在训练 Diffusion Policy 时引入延迟随机化(latency randomization):人为在观测和动作之间添加随机延迟,让策略学会在延迟不确定的情况下仍然输出合理的动作。

# 训练时的延迟随机化
def augment_with_latency(obs_buffer, action_buffer, config):
    """在训练数据中添加随机延迟"""
    latency_steps = np.random.randint(
        config.min_latency,    # 典型: 1 步 (50ms)
        config.max_latency + 1  # 典型: 4 步 (200ms)
    )

    # 观测使用 latency_steps 之前的帧
    obs_delayed = obs_buffer[:-latency_steps]
    # 动作保持原始时间
    action_aligned = action_buffer[latency_steps:]

    return obs_delayed, action_aligned

为什么延迟随机化有效? 当策略在不同延迟下训练时,它被迫学会输出"保守但安全"的动作——不依赖于精确的实时观测,而是基于观测的趋势做出平滑的预测。这与 Domain Randomization 的原理一致:用训练时的多样性换部署时的鲁棒性。

反事实推理:如果训练时不做延迟随机化,策略在仿真中(延迟几乎为零)表现完美。但部署到真机时,100ms 的延迟让策略看到的是"过去"的世界而执行"现在"的动作。对于精确操作(如插入销钉),100ms 意味着目标已经移走了几毫米,策略会反复"追赶"目标而无法收敛。延迟随机化让策略预先适应了这种"看过去做现在"的模式。

90.9.3 动作片段中的延迟补偿

Action Chunking 天然提供了一定程度的延迟容忍:因为 chunk 包含未来 \(K\) 步的动作,即使 chunk 迟到了几步,执行层仍然可以从 chunk 中取出"应该现在执行"的动作(跳过已过期的前几步)。

延迟补偿示意:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
chunk 应在 t=0 到达, 实际在 t=2 到达:

chunk 内容: [a_0, a_1, a_2, a_3, a_4, a_5, a_6, a_7]
                    跳过 a_0, a_1 (已过期)
                    从 a_2 开始执行

这要求 chunk 的每个动作带有绝对时间戳, 而不仅是序号
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

90.9.4 延迟分布的尾部效应

延迟不仅有平均值,更有尾部分布。平均延迟 100ms 的系统,可能 99% 的时间在 80-120ms,但 1% 的时间因 GPU 负载波动跳到 200-300ms。这些"延迟尾部"(tail latency) 是真机部署中最大的不确定性来源。

延迟分布示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
频率 ▲
     │ ████
     │ ██████
     │ ████████
     │ ██████████
     │ ████████████
     │ ██████████████ ░░     ← 尾部
     │ ██████████████ ░░░
     └─────────────────────→ 延迟(ms)
       50   100  150  200  300

主体: 80-120ms (正常)
尾部: 200-300ms (GPU context switch, GC, 系统中断)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

应对尾部延迟的策略:

策略 做法 效果
异步推理 推理在后台线程,不阻塞控制 消除推理延迟对控制的影响
多 chunk 缓存 缓存 2-3 个 chunk,新的到了再替换 即使一次推理迟到也有备用
降级模式 超时后切换到简单启发式 保证有动作输出

90.9.5 端到端延迟的精确测量

在调试延迟问题时,需要精确测量管线每一段的延迟:

import time

class LatencyProfiler:
    """精确测量每段延迟"""
    def __init__(self):
        self.timestamps = {}

    def mark(self, name):
        """在关键节点打时间戳"""
        self.timestamps[name] = time.clock_gettime(time.CLOCK_MONOTONIC)

    def report(self):
        """打印各段延迟"""
        keys = list(self.timestamps.keys())
        for i in range(1, len(keys)):
            dt = (self.timestamps[keys[i]] - self.timestamps[keys[i-1]]) * 1000
            print(f"  {keys[i-1]}{keys[i]}: {dt:.2f} ms")

# 使用示例
profiler = LatencyProfiler()
profiler.mark("camera_capture")
image = camera.read()
profiler.mark("image_preprocess")
obs = preprocess(image)
profiler.mark("feature_extract")
features = encoder(obs)
profiler.mark("diffusion_start")
chunk = diffusion_policy.inference(features)
profiler.mark("diffusion_end")
profiler.mark("action_execute")
send_to_wbc(chunk[0])
profiler.mark("wbc_complete")

profiler.report()
# 输出:
#   camera_capture → image_preprocess: 2.31 ms
#   image_preprocess → feature_extract: 8.45 ms
#   feature_extract → diffusion_start: 0.12 ms
#   diffusion_start → diffusion_end: 52.67 ms
#   diffusion_end → action_execute: 0.08 ms
#   action_execute → wbc_complete: 0.95 ms

练习 90.9a (⭐⭐): 实现一个延迟补偿的 chunk 执行器。输入是 chunk(带时间戳)和当前时间,输出是应该执行的动作。处理以下边界情况:(1) chunk 整体过期;(2) chunk 部分过期。

练习 90.9b (⭐⭐⭐): 设计一个延迟敏感度分析实验。在仿真中分别测试 0ms, 50ms, 100ms, 200ms 的恒定延迟对抓取成功率的影响。找到使成功率降至 50% 的临界延迟。


90.10 部署验证:14 物体评估的方法论与失败分析 ⭐⭐⭐

90.10.1 评估方法论

UMI-on-Legs 在 14 种不同物体上进行了系统性评估,包含抓取(prehensile)、非抓取(non-prehensile)和动态(dynamic)三类任务。评估方法论的设计值得仔细学习。

任务类别 示例物体 挑战
抓取 杯子、瓶子、工具 形状多样、质量差异
非抓取 推盘子、翻书页 需要精确力控
动态 抛接球 高速、时间窗口窄

每个物体每种配置重复 10 次试验。成功标准明确定义——不是主观判断。

90.10.2 失败模式分类

论文中报告的失败模式可以归类到系统的不同层次:

失败模式分层:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Layer 1 (感知): 视觉特征误匹配 → 错误的条件输入
  │ 症状: 策略输出与场景不匹配的动作
  │ 诊断: 检查视觉编码器的激活图
Layer 2 (规划): Diffusion Policy 生成不合理动作
  │ 症状: EE 轨迹不连续或超出工作空间
  │ 诊断: 回放 chunk 的 EE 轨迹, 检查平滑性
Layer 3 (执行): WBC 跟踪误差过大
  │ 症状: 末端实际轨迹偏离目标
  │ 诊断: 比较 EE 目标和实际位姿的误差曲线
Layer 4 (硬件): 夹爪打滑/电机过热
  │ 症状: 物体已到手但没抓住
  │ 诊断: 检查夹爪力传感器和电机温度
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

90.10.3 日志记录与回放

有效的失败分析依赖于全面的日志记录。UMI-on-Legs 的日志系统需要记录以下内容:

层次 记录内容 频率 格式
感知 原始图像 + 视觉特征 10Hz HDF5
规划 Chunk 内容 + 时间戳 2-5Hz JSON
执行 关节角/角速度/力矩 50Hz+ CSV/ROS2 bag
目标 EE 目标 + 实际位姿 50Hz+ CSV
安全 安全层状态/裁剪事件 每事件 Log

固定输入回放是最强大的调试工具:把日志中的观测重新输入策略,检查输出是否与原始一致。如果一致,问题在执行层或硬件;如果不一致,问题在策略(可能是随机种子或时间戳问题)。

90.10.4 零样本跨平台迁移

UMI-on-Legs 的一个亮点是:把在固定臂上训练的 Diffusion Policy checkpoint 零样本迁移到四足臂上。这证明了任务帧 EE 接口的有效性——只要接口语义一致,上层策略可以跨平台使用。

但零样本迁移有边界条件:

条件 要求 不满足时后果
EE 工作空间重叠 新平台的 EE 可达空间覆盖任务需要的区域 部分轨迹不可达
夹爪相似 夹爪的开合范围和力相近 抓取力度不匹配
视角一致 腕部相机的安装角度和视场角相近 视觉特征域偏移
动态能力 新平台的运动速度和加速度够快 跟不上高速操作

💡 Insight: 零样本迁移的成功说明,接口设计比算法本身更重要。即使用最普通的 Diffusion Policy(没有任何针对移动操作的特殊设计),只要接口正确,它就能在全新的平台上工作。这是一个强有力的工程教训:好的抽象层比好的算法更有持久价值。

90.10.5 关键评估指标

在评估移动操作系统时,单一的"成功率"指标远远不够。需要一组结构化的指标来全面评估系统性能:

指标类别 具体指标 计算方式 基线值 (UMI-on-Legs)
任务成功率 总体成功率 成功次数/总次数 >70%
末端精度 EE 位置 RMSE \(\sqrt{\frac{1}{T}\sum_t \|p_{ee} - p_{ee}^{des}\|^2}\) ~2-4cm
末端精度 EE 旋转误差 \(\frac{1}{T}\sum_t \angle(R_{ee}, R_{ee}^{des})\) ~5-10°
行走稳定 基座高度波动 std\((h_{base})\) <1.5cm
行走稳定 基座倾斜 max\((\theta_{roll,pitch})\) <8°
平滑性 关节加速度 \(\frac{1}{T}\sum_t \|\ddot{q}\|\)
延迟 策略推理时间 95th percentile <150ms
鲁棒性 扰动后恢复时间 从推扰到 EE 误差 <5cm 的时间 <0.5s

统计学注意事项:每种配置至少 10 次试验才有统计意义。报告均值 ± 标准差或中位数 + 四分位距。不要只报告"最好的一次"。

90.10.6 典型失败模式的具体案例

从 UMI-on-Legs 论文和后续工作中总结的典型失败:

案例 1:相机遮挡导致策略混乱

症状:机器人在抓取物体的过程中突然停止或做出无关动作。

根因:操作过程中手臂挡住了腕部相机的视野。Diffusion Policy 收到的图像中操作物体消失了,生成的动作序列不再朝向目标。

解决:(a) 调整相机安装角度减少自遮挡;(b) 在训练数据中包含部分遮挡的样本;(c) 添加遮挡检测逻辑——当图像中关键物体消失时,冻结当前 chunk 而非生成新的。

案例 2:里程计漂移导致任务帧偏移

症状:操作初期正常,但随时间推移末端逐渐偏离目标。

根因:\(T_{world}^{body}\) 由视觉-惯性里程计提供。行走过程中里程计累积漂移,导致计算的 \(T_{body}^{ee}\) 偏移。

解决:(a) 使用外部定位(如 AprilTag 或 Vicon)定期校正里程计;(b) 在任务帧下工作时减少对世界帧的依赖;(c) 任务时间控制在里程计漂移可接受的范围内。

案例 3:夹爪力度不匹配

症状:物体被成功抓到但在行走中掉落。

根因:UMI 的手持夹爪和机器人上的夹爪有不同的力特性。训练时示教数据反映的是手持夹爪的力度,但部署时机器人夹爪可能力度不同。

解决:(a) 在部署时增加夹爪力度的安全裕度;(b) 在训练数据预处理中增广夹爪开合度。

练习 90.10a (⭐⭐): 设计一个失败归因的决策树:给定一次失败的实验日志,通过哪些检查步骤可以确定失败发生在哪一层?

练习 90.10b (⭐⭐⭐): 在零样本迁移中,如果新平台的 EE 工作空间比原平台小 20%,有哪些方法可以缓解这个问题?(提示:考虑运行时的轨迹裁剪、任务帧重新注册、底层速度放大等。)


90.11 与 VBC 的对比:目标接口的设计差异 ⭐⭐

90.11.1 位置接口 vs 速度接口

UMI-on-Legs 使用位置目标接口(输出 \(T_{task}^{ee}\)),VBC (Velocity-Based Control) 使用速度指令接口(输出 \(\mathbf{v}_{ee}^{des}\))。两种接口方案导致了截然不同的系统行为。

维度 位置接口 (UMI-on-Legs) 速度接口 (VBC)
上层输出 "去这个位置" \(T^{ee}\) "以这个速度移动" \(\dot{T}^{ee}\)
下层行为 位置跟踪控制 速度跟踪控制
延迟影响 过时目标导致跳变 过时速度导致漂移
误差特性 有界(目标位置固定) 无界(速度积分漂移)
示教方式 记录位置序列 记录速度序列

本质洞察:位置接口和速度接口的根本差异是误差的性质。位置接口的误差是有界的——无论中间怎么偏,最终都会收敛到目标位置。速度接口的误差会积分——任何持续的偏差都会导致位置漂移,且永远不会自动修复。这就是为什么 UMI-on-Legs 选择位置接口:操作任务的终态精度是最重要的。

90.11.2 何时选择哪种接口?

两种接口各有适用场景:

选择决策树:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
任务需要精确终态?
  ├── 是 → 位置接口
  │   ├── 示教数据有完整轨迹? → UMI 方案
  │   └── 只有终态目标?       → 运动规划 + IK
  └── 否 → 速度接口
      ├── 需要连续交互(如擦桌子)? → VBC
      └── 需要力控(如打磨)?       → 阻抗控制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

练习 90.11 (⭐⭐): 分析以下三个任务各适合哪种接口:(1) 从架子上取书;(2) 用抹布擦桌面;(3) 打开水龙头。给出理由。

90.11.3 Diffusion Policy vs ACT 的架构对比

UMI-on-Legs 选择了 Diffusion Policy 作为操作策略。另一个强力竞争者是 ACT (Action Chunking with Transformers, Zhao et al., RSS 2023)。两者都生成动作 chunk,但生成机制不同:

维度 Diffusion Policy ACT
生成方式 迭代去噪 (DDPM/DDIM) 单次前向 (CVAE + Transformer)
多模态 天然支持(不同噪声→不同模态) 通过 CVAE 的 latent 采样
推理速度 慢(10-25 步去噪) 快(单次前向)
训练稳定性 简单(MSE on noise) 需要 KL 平衡
长时序质量 chunk 内部高质量 chunk 边界可能不连续

Diffusion Policy 的独特优势在于处理多模态性。在 UMI 的数据采集中,不同操作员完成同一个任务的方式不同(左手抓 vs 右手抓、快速完成 vs 慢速完成),数据天然是多模态的。Diffusion Policy 可以通过不同的初始噪声采样到不同模态,每次生成的动作序列都是某个模态的完整、一致的轨迹。ACT 依赖 CVAE 的 latent 变量来捕捉多模态,但 CVAE 的模态坍缩(mode collapse)问题更容易发生。

多模态处理对比:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Diffusion Policy:
  噪声 ε₁ ──→ [去噪 10步] ──→ 左手抓 轨迹
  噪声 ε₂ ──→ [去噪 10步] ──→ 右手抓 轨迹
  噪声 ε₃ ──→ [去噪 10步] ──→ 左手抓 轨迹 (不同随机种子但同模态)
  → 自然地在模态之间切换

ACT (CVAE):
  z₁ ∈ latent ──→ [Transformer] ──→ 左手抓 轨迹
  z₂ ∈ latent ──→ [Transformer] ──→ 左手抓 轨迹 (模态坍缩!)
  → KL 权重太大→只学到一个模态;太小→latent 无意义
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

反事实推理:如果 UMI-on-Legs 使用 ACT 替代 Diffusion Policy,在单模态任务(如拧螺丝——只有一种正确方式)上可能更好(推理更快),但在多模态任务(如抓取杯子——可以从多个角度抓)上可能更差(模态坍缩导致平均化)。这说明策略架构的选择应该根据任务的多模态性程度来决定。

90.11.4 Score Matching 与噪声预测的等价性

Diffusion Policy 训练网络预测噪声 \(\boldsymbol{\epsilon}_\theta\)。这与score matching(学习对数概率密度的梯度 \(\nabla_{\mathbf{a}} \log p(\mathbf{a})\))是等价的。

Score function 的定义:

\[\mathbf{s}(\mathbf{a}_t, t) = \nabla_{\mathbf{a}_t} \log q(\mathbf{a}_t)\]

由前向过程 \(q(\mathbf{a}_t | \mathbf{a}_0) = \mathcal{N}(\sqrt{\bar{\alpha}_t}\,\mathbf{a}_0,\ (1-\bar{\alpha}_t)\mathbf{I})\),可以计算精确的 score:

\[\nabla_{\mathbf{a}_t} \log q(\mathbf{a}_t | \mathbf{a}_0) = -\frac{\mathbf{a}_t - \sqrt{\bar{\alpha}_t}\,\mathbf{a}_0}{1-\bar{\alpha}_t} = -\frac{\boldsymbol{\epsilon}}{\sqrt{1-\bar{\alpha}_t}}\]

因此噪声预测 \(\boldsymbol{\epsilon}_\theta\) 和 score 预测 \(\mathbf{s}_\theta\) 之间的关系为:

\[\boxed{\mathbf{s}_\theta(\mathbf{a}_t, t) = -\frac{\boldsymbol{\epsilon}_\theta(\mathbf{a}_t, t)}{\sqrt{1-\bar{\alpha}_t}}}\]

这个等价性意味着:训练 Diffusion Policy 预测噪声,本质上是在学习数据分布的 score function。在采样时,沿着 score 的方向迭代(Langevin 动力学),就能从噪声分布逐步移动到数据分布。

为什么这个理论理解重要? 因为它解释了 Diffusion Policy 为什么能捕捉多模态:score function 在多模态分布的每个模态附近都有"吸引区域"——从不同初始噪声出发,Langevin 动力学会把样本引导到不同的模态。这不是 heuristic,而是有严格数学保证的。

⚠️ Pitfall: score matching 在低密度区域(模态之间)的 score 估计不准确——训练数据在那里很少。这意味着如果去噪步数太少(如 DDIM-3),样本可能停留在模态之间的"无人区",产生不合理的动作序列。DDIM-10 通常是实用的下限。

90.11.5 Noise Schedule 的设计

噪声调度表 \(\{\beta_t\}_{t=1}^T\) 的选择对 Diffusion Policy 的质量有显著影响:

调度类型 公式 特点
线性 (DDPM 原始) \(\beta_t = \beta_1 + \frac{t-1}{T-1}(\beta_T - \beta_1)\) 简单,后期噪声增长太快
余弦 (improved DDPM) \(\bar{\alpha}_t = \frac{f(t)}{f(0)}\), \(f(t)=\cos(\frac{t/T+s}{1+s}\cdot\frac{\pi}{2})^2\) 前期信号保留更多
Squaredcos_cap_v2 裁剪后的余弦平方 Diffusion Policy 默认

余弦调度的关键优势是在 \(t\) 较小时保留更多信号。对于机器人动作序列,细微的差异(如 1cm 的位移差异)在小 \(t\) 时需要被准确重建——线性调度在 \(t\) 小时加的噪声太多,模糊了这些细节。

练习 90.11c (⭐⭐⭐): 实现线性和余弦两种 noise schedule,绘制 \(\bar{\alpha}_t\)\(t\) 的变化曲线。在一个 1D 双模态分布 \(p(a) = 0.5\mathcal{N}(-1, 0.1) + 0.5\mathcal{N}(1, 0.1)\) 上训练 Diffusion Model,比较两种 schedule 的采样质量。

90.11.6 WBC 训练的 Privileged Learning 细节

UMI-on-Legs 的 WBC 使用 Privileged Learning 框架训练。这个框架分两个阶段:

Privileged Learning 两阶段训练:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
阶段 1: 教师策略 (Teacher)
  观测: 完整信息 (包括真实地面摩擦系数、精确质心位置、
        外部扰动力、接触法向量等)
  训练: PPO, ~2000 轮
  目标: 学到"如果我知道一切,最好怎么做"

阶段 2: 学生策略 (Student)
  观测: 受限信息 (只有关节编码器、IMU、EE 目标)
  训练: 行为克隆 (模仿教师的动作)
  目标: 从受限观测中推断出教师能看到的信息

关键: 学生不直接模仿教师的动作,而是学习
      从受限观测中重构教师的 "privileged context"
      然后用这个重构的 context 做决策
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

教师策略的观测中包含的"特权信息"(privileged information):

特权信息 维度 真机上不可用的原因
地面摩擦系数 \(\mu\) 1 无法直接测量
精确的外部力 \(F_{ext}\) 3 需要力传感器(通常没有)
精确的地形高度 若干 需要高精度深度传感器
精确的基座速度 3 IMU 积分有漂移
真实的质心位置 3 负载变化时不准确

学生策略通过一个编码器(estimator)从历史观测序列中隐式估计这些特权信息。这与 DreamWaQ 的 "implicit terrain imagination" 思想一致——不显式估计地形,而是学习一个隐式表征,其中编码了足以做出好决策的信息。

跨章回顾:回顾复合/180 Deep-WBC:我们讨论了 Privileged Learning 的理论基础——信息瓶颈(Information Bottleneck)。教师的特权观测是高维的(包含一切),学生的观测是低维的(只有传感器数据)。学生的编码器学到的是一个压缩表征——保留了与决策相关的信息,丢弃了无关的信息。这个压缩过程的最优解恰好是信息瓶颈的解。

90.11.7 UMI 数据采集的实操要点

虽然 UMI 的概念简单(手持夹爪采集数据),但实际操作中有很多细节决定数据质量:

要点 说明 常见错误
采集速度 慢速、自然、流畅 太快导致运动模糊、SLAM 失败
视角多样性 从不同角度重复同一任务 只从一个角度采集导致策略过拟合
失败示教 也要记录失败的尝试 只保留成功数据导致分布偏差
光照条件 在多种光照下采集 只在特定光照下采集导致部署失败
标定板可见性 确保参考标记物始终可见 SLAM 丢失导致轨迹断裂
夹爪状态一致 训练和部署的夹爪尺寸一致 不同夹爪的抓取策略不同

数据量的经验值

任务复杂度 所需示教次数 训练轮次
简单抓放 50-100 次 3000 epoch
工具使用 100-200 次 5000 epoch
多阶段操作 200-500 次 8000+ epoch

💡 Insight: UMI 的数据效率比传统的 teleoperation(遥操作)高得多。因为 UMI 用的是手持夹爪——人可以自然地完成操作,不需要学习复杂的遥操作界面(如 VR 手柄映射到机器人关节)。自然的示教速度约 5-10 分钟/任务,而遥操作可能需要 20-30 分钟来适应界面。

90.11.8 Diffusion Policy 的训练超参数

对于机器人操作任务,Diffusion Policy 的关键训练超参数:

超参数 推荐值 影响
去噪步数 \(T\) (训练) 100 增大→质量更好但训练慢
去噪步数 (DDIM推理) 10-16 增大→质量更好但推理慢
Chunk 长度 \(K\) 16 (观测2+预测16) 增大→更长的规划视野
观测窗口 \(T_{obs}\) 2 太大→特征模糊
学习率 1e-4 太大→不稳定
Batch size 256 太小→梯度噪声大
预测类型 epsilon (噪声预测) 比 sample 预测更稳定
网络架构 U-Net 或 Transformer U-Net 更快,Transformer 更灵活

U-Net vs Transformer 架构对比

U-Net 架构:
  优势: 推理快 (~30ms on RTX 3090)
        参数少 (~30M)
        适合固定维度的动作空间
  劣势: 难以处理可变长度的条件
        难以融合多种模态的条件

Transformer 架构:
  优势: 可以自然处理可变长度序列
        多模态条件融合更灵活
        支持 cross-attention
  劣势: 推理慢 (~100ms)
        参数多 (~100M)
        需要更多训练数据

UMI-on-Legs 使用 U-Net 架构——因为腕部相机只有一个,条件结构固定,推理速度更重要。

练习 90.11d (⭐⭐): 比较 DDIM-10 和 DDIM-16 在你的最小 1D Diffusion Model 上的采样质量差异。在什么条件下两者差异最大?


90.12 WBC 奖励工程的深层分析:manipulation-centric 设计哲学 ⭐⭐⭐⭐

90.12.1 为什么 WBC 奖励不能照搬纯足式设计

UMI-on-Legs 的 WBC 奖励设计与 Deep-WBC(复合/180)有一个根本性差异:操作精度是第一公民,行走稳定是服务于操作的手段。这一设计哲学被称为 manipulation-centric(以操作为中心),它颠倒了纯足式控制中的优先级关系。

在纯足式 RL 中,奖励的核心是速度跟踪和姿态稳定——机器人的全部目的是"走好"。末端跟踪(如果有的话)是次要的。但在 UMI-on-Legs 中,机器人行走的全部目的是"让末端稳定"——如果末端能保持精确,即使行走步态不那么优美也是可接受的。

这个优先级反转体现在奖励权重的量级关系上:

奖励类别 纯足式 RL 典型权重 UMI-on-Legs WBC 典型权重 差异倍数
速度跟踪 \(r_{vel}\) 1.5 0.3 \(\times 0.2\)
姿态惩罚 \(c_{rp}\) -5.0 -2.0 \(\times 0.4\)
末端跟踪 \(r_{ee}\) 0(不存在) 3.0 \(\infty\)
末端平滑 \(c_{ee\_smooth}\) 0(不存在) -1.0 \(\infty\)
动作平滑 \(c_{act}\) -0.01 -0.05 \(\times 5\)

类比:纯足式 RL 训练出的策略像一个"跑步运动员"——步态对称、速度精准、姿态稳健。UMI-on-Legs 训练出的策略像一个"端着满杯水走路的服务员"——他的步态可能不优美(步幅不等、频率不均),但全身都在为"不洒水"服务。两者的训练目标截然不同,虽然底层动作空间完全相同。这个类比的边界在于:真实的服务员有视觉反馈来持续调整手臂,而 WBC 只看到 EE 目标和本体感知,不看液面。

90.12.2 末端跟踪奖励的精细设计

末端跟踪奖励不是简单的 L2 距离惩罚。UMI-on-Legs 使用位置和姿态分别加权的高斯核奖励:

\[ r_{ee} = w_{pos} \cdot \exp\left(-\frac{\|\mathbf{p}_{ee} - \mathbf{p}_{ee}^{des}\|^2}{\sigma_{pos}^2}\right) + w_{rot} \cdot \exp\left(-\frac{\theta_{err}^2}{\sigma_{rot}^2}\right) \]

其中 \(\theta_{err} = \arccos\left(\frac{\text{tr}(\mathbf{R}_{ee}^T \mathbf{R}_{ee}^{des}) - 1}{2}\right)\) 是旋转误差的角度表示。

位置和旋转使用不同的 \(\sigma\) 有重要的物理原因。位置误差的可接受范围通常是 1-3 cm(\(\sigma_{pos} \approx 0.02\) m),而旋转误差的可接受范围通常是 5-15 度(\(\sigma_{rot} \approx 0.15\) rad)。如果用同一个 \(\sigma\),旋转项会被位置项淹没或反过来。

反事实推理:如果末端跟踪权重设得太高(例如 \(w_{ee} = 10\)),策略会学到一种"冻结下体"的行为——腿几乎不动,用臂的冗余度来补偿所有基座扰动。这在仿真中可能成功率很高,但到真机上基座持续漂移时,臂的工作空间很快耗尽,导致任务失败。正确的做法是让末端权重足够高以驱动学习,但不高到让策略完全忽视行走稳定。

90.12.3 行走扰动补偿奖励

UMI-on-Legs 引入了一个独特的奖励项——行走扰动补偿奖励。它的思想是:当腿部运动产生基座扰动时,臂部应该主动补偿以保持末端稳定。

\[ r_{comp} = w_{comp} \cdot \exp\left(-\frac{\|\Delta \mathbf{p}_{ee}^{walk}\|^2}{\sigma_{comp}^2}\right) \]

其中 \(\Delta \mathbf{p}_{ee}^{walk} = \mathbf{p}_{ee}^{actual} - \mathbf{p}_{ee}^{des\_in\_world}\) 是行走引起的末端世界坐标偏差。

这个奖励项和 \(r_{ee}\) 的区别在于:\(r_{ee}\) 衡量的是"末端相对于基座的跟踪精度",而 \(r_{comp}\) 衡量的是"行走过程中末端在世界坐标系的稳定性"。两者互补——前者鼓励臂追踪命令,后者鼓励臂抵消走路带来的晃动。

90.12.4 奖励课程策略

WBC 训练采用三阶段课程:

阶段 Epoch 范围 任务 末端权重 速度命令
Phase 1 0-500 站立 + EE 跟踪 1.0 \(v = 0\)
Phase 2 500-1500 慢速行走 + EE 跟踪 2.0 \(v \leq 0.3\) m/s
Phase 3 1500-3000 全速行走 + EE 跟踪 + DR 3.0 \(v \leq 1.0\) m/s

Phase 1 让策略先学会"稳定的手臂"——不走路时末端精度是容易的,策略可以专注于学习臂的逆运动学映射。Phase 2 引入慢速行走,策略开始学习用臂补偿基座扰动。Phase 3 增加速度和域随机化,策略在最具挑战性的条件下精细化行为。

本质洞察:manipulation-centric WBC 的核心思想可以用一句话总结——行走是操作的交通工具,不是目的。所有行走相关的奖励(速度跟踪、步态对称、能耗)都只是约束条件,真正的优化目标是末端精度。这种优先级翻转是 UMI-on-Legs 与纯足式 RL 的根本区别。

90.12.5 WBC 与 Diffusion Policy 的协调频率分析

WBC 和 Diffusion Policy 在频率上相差 10-50 倍(WBC 50-100 Hz vs Diffusion 2-5 Hz)。这种频率差异要求 WBC 具备目标内插和外推能力——在两个 Diffusion chunk 之间,WBC 必须自主推断末端应该在哪里。

WBC 的目标更新逻辑:

\[ \mathbf{p}_{ee}^{des}(t) = \begin{cases} \text{interpolate}(\mathbf{p}_{k}, \mathbf{p}_{k+1}, t) & \text{if chunk 有效} \\ \text{hold}(\mathbf{p}_{last}) & \text{if chunk 过期} \\ \text{retract}(\mathbf{p}_{safe}) & \text{if chunk 严重超时} \end{cases} \]

这里的 hold 和 retract 模式是 WBC 的安全后备——当上层策略长时间无响应时,WBC 不会盲目执行最后一个命令,而是切换到安全行为。

⚠️ 常见陷阱

⚠️ 末端跟踪奖励只用 L2 距离

错误做法:\(r_{ee} = -\|\mathbf{p}_{ee} - \mathbf{p}_{ee}^{des}\|^2\),不区分位置和旋转。

典型现象:位置跟踪好但旋转跟踪差,或反过来。

根本原因:位置和旋转的量纲和可接受范围不同。

正确做法:分别设计位置和旋转奖励,用不同 \(\sigma\) 和权重。

💡 概念误区:认为 WBC 只需要跟踪 Diffusion 输出的位置

实际上 WBC 还需要处理 chunk 过期、目标跳变、安全降级等状态。

WBC 是一个带状态机的控制器,不只是一个位置跟踪器。

🧠 思维陷阱:认为 manipulation-centric 意味着可以忽略行走质量

行走质量太差(如跌倒)会直接中断操作任务。

manipulation-centric 是优先级排序,不是忽略行走。

练习 90.12

  1. (⭐⭐) 设计一个 Phase 1 到 Phase 2 的平滑过渡策略:如何在不中断训练的情况下从站立过渡到行走?
  2. (⭐⭐⭐) 对比 \(w_{ee} = 1.0\)\(w_{ee} = 5.0\) 两组训练的行为差异。预测哪组在仿真中成功率更高,哪组在真机上更可靠。
  3. (⭐⭐⭐) 设计一个实验来测量"行走引起的末端扰动幅度":固定 EE 目标,让机器人以不同速度行走,记录 EE 位置的标准差。

90.13 跨具身迁移的理论边界与工程实践 ⭐⭐⭐⭐

90.13.1 什么决定了零样本迁移的成功

UMI-on-Legs 的零样本跨平台迁移之所以能工作,依赖于三个关键条件的同时满足。理解这些条件的数学本质,有助于判断新场景下迁移是否可行。

条件一:末端执行器几何一致性。源平台和目标平台的夹爪必须有相似的物理几何——开合范围、指尖形状、夹持面积。数学上,两个夹爪的抓取可达性集合(Grasp Reachability Set)必须有足够大的交集:

\[ |GRS_{source} \cap GRS_{target}| / |GRS_{source}| > \eta_{grasp} \]

\(\eta_{grasp}\) 通常需要大于 0.8。如果目标平台的夹爪比源平台小很多,很多示教中学到的抓取策略会因为"夹不住"而失败。

条件二:工作空间覆盖。目标平台的 EE 可达空间必须覆盖任务所需的操作区域。这不是要求两个平台的工作空间完全相同,而是要求任务所需的操作区域是目标平台可达空间的子集:

\[ \mathcal{W}_{task} \subseteq \mathcal{W}_{target} \]

如果不满足,需要通过调整任务帧位置(\(T_{world}^{task}\))来将操作区域"平移"到目标平台的可达范围内。

条件三:动态能力匹配。目标平台的末端速度和加速度能力必须足以执行示教中的动作。如果示教数据中包含高速动作(如快速抓取),但目标平台的臂较慢,WBC 会因为跟不上 EE 目标而产生持续跟踪误差。

类比:跨具身迁移类似于"用同一份菜谱在不同厨房做菜"。菜谱(Diffusion Policy)描述的是"把鸡蛋打入碗中"这样的任务级操作。只要新厨房有碗和鸡蛋(几何一致)、台面够大(工作空间覆盖)、厨师手速够快(动态能力),菜谱就能用。但如果新厨房是迷你厨房(工作空间不够),或者用的是鸵鸟蛋(几何不一致),菜谱就需要修改。这个类比的边界在于:真实的菜谱有容错性(多放点油也行),而 Diffusion Policy 对几何偏差更敏感。

90.13.2 迁移失败的诊断框架

当零样本迁移失败时,需要系统化地诊断问题来源:

def diagnose_transfer_failure(source_platform, target_platform, task_logs):
    """跨平台迁移失败的诊断框架"""
    checks = []

    # 检查 1:工作空间覆盖
    ws_overlap = compute_workspace_overlap(
        source_platform.ee_workspace, target_platform.ee_workspace
    )
    if ws_overlap < 0.8:
        checks.append("工作空间覆盖不足: {:.1%}".format(ws_overlap))

    # 检查 2:夹爪兼容性
    grasp_compat = compare_gripper_geometry(
        source_platform.gripper, target_platform.gripper
    )
    if grasp_compat < 0.8:
        checks.append("夹爪几何不兼容: {:.1%}".format(grasp_compat))

    # 检查 3:动态能力
    max_ee_vel_task = extract_max_ee_velocity(task_logs)
    max_ee_vel_target = target_platform.max_ee_velocity
    if max_ee_vel_task > 0.8 * max_ee_vel_target:
        checks.append("目标平台速度裕度不足")

    # 检查 4:视觉域差异
    visual_shift = compute_domain_shift(
        source_platform.camera_params, target_platform.camera_params
    )
    if visual_shift > 0.3:
        checks.append("视觉域偏移过大: {:.2f}".format(visual_shift))

    return checks

90.13.3 从 UMI-on-Legs 到多臂系统的扩展

UMI-on-Legs 验证了单臂的跨平台迁移。将这个框架扩展到双臂或多臂系统时,面临的新挑战包括:

挑战 单臂 UMI 双臂扩展
数据采集 单手持 UMI 需要双手持两个 UMI,或一个双夹爪 UMI
任务帧 单一物体坐标系 可能需要多个任务帧(左手目标、右手目标、共享物体)
碰撞避免 臂-腿碰撞 额外增加臂-臂碰撞
协调 不存在 双臂时序协调(如一只手扶住、另一只手操作)

双臂扩展中最核心的研究问题是:任务帧如何在双臂之间共享。如果两只手操作同一个物体(如双手端盘子),它们应该共享同一个任务帧。如果两只手操作不同物体(如左手拿杯子、右手拿水壶),它们需要各自独立的任务帧。这个决策需要在任务规划层做出,而不是在底层控制器中。

⚠️ 常见陷阱

⚠️ 直接在新平台上跑旧策略不做任何检查

错误做法:把 Diffusion Policy checkpoint 复制到新平台直接推理。

典型现象:策略输出看似合理但成功率极低。

根本原因:工作空间、夹爪和视角中的任何一个不匹配都会导致失败。

正确做法:先完成工作空间覆盖检查、夹爪兼容性测试和视觉域对比。

💡 概念误区:认为跨具身只需要 EE 接口一致

EE 接口一致是必要条件但不充分。

还需要视觉域一致(腕部相机安装角度和分辨率)和动态能力匹配。

练习 90.13

  1. (⭐⭐) 如果目标平台的 EE 工作空间比源平台向上偏移了 10cm,应该如何修改任务帧 \(T_{world}^{task}\) 来补偿?
  2. (⭐⭐⭐) 设计一个双臂 UMI 的数据采集方案:两个操作员分别控制一只手,还是一个操作员同时控制两只手?分析各自的优缺点。
  3. (⭐⭐⭐⭐) 提出一种"部分迁移"方案:当新平台的工作空间只覆盖 60% 的任务需求时,如何修改 Diffusion Policy 的推理过程来避免生成不可达的 EE 目标?

90.14 UMI-on-Legs 与 2024-2025 年移动操作前沿的关系 ⭐⭐⭐

90.14.1 技术演进时间线

UMI-on-Legs 发表于 CoRL 2024,它在移动操作领域的定位可以通过以下时间线理解:

时间 工作 关键贡献 与 UMI-on-Legs 的关系
2022.10 Deep-WBC (Fu et al.) 统一策略控制腿+臂 UMI-on-Legs WBC 的直接前驱
2023.03 Diffusion Policy (Chi et al.) 条件去噪生成动作 UMI-on-Legs 操作策略的基础
2024.01 UMI (Chi et al.) 手持夹爪通用示教 数据采集接口来源
2024.07 UMI-on-Legs (Ha et al.) 移动底盘上的 UMI 本章主题
2024.10 MLM (多任务 Loco-Mani) 多任务全身 RL 扩展到多任务场景
2025 Visual WBC 视觉闭环 WBC 在 WBC 中加入视觉反馈

90.14.2 与 Loco-Manipulation 前沿的差异化

2024-2025 年 Loco-Manipulation 领域呈现三条主要技术路线:

路线一:纯 RL 端到端。以 Deep-WBC 和 MLM 为代表,策略直接从观测到全身关节命令。UMI-on-Legs 属于这条路线的操作层解耦版本——底层仍是 RL,但操作目标由独立的 Diffusion Policy 提供。

路线二:RL + MPC 混合。以 RAMBO(复合/210)为代表,用 MPC 保证安全约束,RL 提供残差或高层决策。UMI-on-Legs 没有显式的 MPC 安全层,安全主要靠 WBC 奖励中的惩罚项实现。

路线三:VLA + 安全过滤。以 \(\pi_0\)、OpenVLA 等为代表,用大型视觉语言模型直接生成操作目标,底层安全过滤保证执行安全。UMI-on-Legs 使用的 Diffusion Policy 比 VLA 更专注但也更高效——它不理解开放语言指令,但推理速度更快且多模态处理更好。

不是 X 而是 Y:UMI-on-Legs 的核心贡献不是提出新的 WBC 算法或新的操作策略——Deep-WBC 和 Diffusion Policy 都是已有的工作。它的核心贡献是证明了 EE 轨迹接口的跨平台有效性——同一个操作策略可以从固定臂迁移到移动四足臂。这是一个系统集成层面的贡献,而非算法层面的贡献。

90.14.3 非抓取操作与动态操作的前沿挑战

UMI-on-Legs 在非抓取(non-prehensile)和动态操作上的表现暴露了当前技术的瓶颈:

非抓取操作(如推盘子)要求策略理解物体与地面之间的摩擦关系。Diffusion Policy 从示教数据中学到的是"用多大的力推多远",但这种映射高度依赖接触面的摩擦系数。真机上的桌面材质和仿真中不同时,推送力度会不匹配。

动态操作(如抛接球)要求极低的延迟和精确的时序。Diffusion Policy 的推理延迟(50-100 ms)意味着策略看到的是 100 ms 前的世界。对于需要在 50 ms 时间窗口内做出反应的动态任务(如接住一个下落的物体),这个延迟是致命的。

2025 年的前沿工作开始探索以下解决方案:

挑战 解决方向 代表工作
非抓取摩擦敏感 触觉反馈 + 力域随机化 力敏感 Loco-Manipulation 路线
动态操作延迟 异步推理 + 反射式底层策略 反射弧式架构
开放世界语义 VLA 替代 Diffusion Policy \(\pi_0\), OpenVLA
长时序任务 TAMP + Diffusion 结合 任务规划层 + 技能库

⚠️ 常见陷阱

⚠️ 混淆系统贡献和算法贡献

错误想法:UMI-on-Legs "只是把两个已有的东西接在一起"。

实际上:证明 EE 接口在移动操作中有效是一个重要的系统贡献。

在机器人领域,系统集成的可行性验证本身就是研究贡献。

🧠 思维陷阱:认为更大的模型(VLA)一定比 Diffusion Policy 好

VLA 擅长开放世界语义理解,但推理慢且多模态处理不如 Diffusion。

选择策略架构应根据任务的多模态性、延迟预算和数据量来决定。

练习 90.14

  1. (⭐⭐) 画出 UMI-on-Legs 在移动操作技术栈中的位置图,标注它使用了哪些已有技术,自己的贡献在哪里。
  2. (⭐⭐⭐) 如果要把 UMI-on-Legs 的 Diffusion Policy 替换为 VLA(如 \(\pi_0\)),接口层需要做哪些修改?WBC 需要做哪些修改?
  3. (⭐⭐⭐⭐) 设计一个"反射弧式"底层策略来处理动态操作:当 Diffusion Policy 来不及推理时,底层 WBC 如何自主做出快速反应?

90.15 常见误解汇总

误解 正确理解
UMI-on-Legs 提出了新的 Diffusion Policy 它复用了 Chi et al. 的 Diffusion Policy,贡献在系统集成
WBC 只是逆运动学 WBC 是带动力学补偿的全身控制器,处理行走扰动和接触
零样本迁移不需要任何调整 仍需检查工作空间覆盖、夹爪兼容性和视觉域
Action Chunking 的 chunk 越长越好 chunk 太长会降低对环境变化的响应速度
manipulation-centric 意味着行走不重要 行走是操作的前提,只是优先级低于末端精度
Diffusion Policy 比 ACT 严格更好 两者各有优势场景,取决于多模态性和延迟预算
手持 UMI 采集数据很简单 需要注意采集速度、视角多样性、光照和标定板可见性
延迟只影响精度 严重延迟可导致策略行为完全错误,不只是精度下降

本章小结

知识点 核心要点 难度
移动操作动机 四足+臂解决移动+操作同时进行的需求 ⭐⭐
三层架构 感知(10Hz) → 规划(2-5Hz) → 执行(50-100Hz) ⭐⭐
Diffusion Policy DDPM/DDIM 条件去噪生成动作序列 ⭐⭐⭐
Action Chunking 一次输出多步动作,桥接频率差 ⭐⭐⭐
任务帧注册 将示教数据绑定到物体坐标系实现跨平台复用 ⭐⭐⭐
腕部相机管线 视觉编码 + 时间同步 ⭐⭐⭐
RL WBC manipulation-centric 奖励设计 ⭐⭐⭐
延迟处理 延迟随机化训练 + chunk 时间戳补偿 ⭐⭐⭐
部署验证 分层失败分析 + 日志回放 ⭐⭐⭐

累积项目:本章新增模块

在累积的移动操作项目中,本章新增以下模块:

  • 模块 1: 最小 1D Diffusion Policy 实现(90.3 练习)
  • 模块 2: Action Chunk 执行器,含延迟补偿(90.4, 90.9 练习)
  • 模块 3: 坐标变换链,含任务帧注册(90.5 练习)
  • 模块 4: 失败归因决策树(90.10 练习)

UMI-on-Legs 的开源代码结构

UMI-on-Legs 的代码开源在 GitHub (real-stanford/umi-on-legs)。理解代码结构有助于复现和改进:

umi-on-legs/
├── diffusion_policy/          # Diffusion Policy 训练和推理
│   ├── config/                # 训练配置 (YAML)
│   ├── model/                 # 网络架构 (U-Net / Transformer)
│   ├── dataset/               # UMI 数据加载
│   └── workspace/             # 训练主循环
├── whole_body_controller/     # RL WBC
│   ├── envs/                  # Isaac Gym 环境定义
│   ├── algorithms/            # PPO 训练
│   ├── configs/               # 奖励/观测/DR 配置
│   └── deployment/            # 真机部署
├── calibration/               # 标定工具
│   ├── hand_eye.py            # AX=XB 求解
│   └── camera_intrinsics.py   # 内参标定
├── deployment/                # 部署管线
│   ├── action_executor.py     # Chunk 执行器
│   ├── safety_monitor.py      # 安全监控
│   └── logger.py              # 日志记录
└── evaluation/                # 评估工具
    ├── success_checker.py     # 成功判定
    └── analysis.py            # 失败分析

代码阅读建议

  1. diffusion_policy/model/ 开始,理解去噪网络的输入/输出维度
  2. 然后读 whole_body_controller/envs/,理解 WBC 的观测/动作/奖励定义
  3. 最后读 deployment/action_executor.py,理解 chunk 执行和延迟补偿的实现

⚠️ Pitfall: 开源代码中的超参数通常是针对特定硬件(如 Unitree Go2 + ARX5 臂)调优的。直接迁移到其他硬件时,至少需要重新调整以下参数:PD 增益、动作缩放(action scale)、奖励权重、Domain Randomization 范围。

延伸阅读

资源 难度 内容
Chi et al., "Diffusion Policy" (RSS 2023) ⭐⭐⭐ Diffusion Policy 原始论文
Ho et al., "DDPM" (NeurIPS 2020) ⭐⭐⭐⭐ DDPM 数学基础
Song et al., "DDIM" (ICLR 2021) ⭐⭐⭐⭐ DDIM 加速采样
Chi et al., "UMI" (RSS 2024) ⭐⭐⭐ UMI 手持夹爪数据采集
Ha et al., "UMI-on-Legs" (CoRL 2024) ⭐⭐⭐⭐ 本章主题论文
Zhou et al., "On the Continuity of Rotation Representations" (CVPR 2019) ⭐⭐⭐ 6D 旋转表示

符号表

符号 含义 首次出现
\(T_{world}^{body}\) 机体在世界坐标系下的位姿 90.1
\(T_{body}^{ee}\) 末端执行器在机体坐标系下的位姿 90.1
\(T_{task}^{ee}\) 末端执行器在任务坐标系下的位姿 90.5
\(\mathbf{a}_t\) 时刻 \(t\) 的动作(6D EE 目标) 90.3
\(\bar{\alpha}_t\) DDPM 的累积噪声调度参数 90.3
\(\boldsymbol{\epsilon}_\theta\) 噪声预测网络的输出 90.3
\(K\) Action Chunk 的长度(步数) 90.4
\(\mathbf{R}_X\), \(\mathbf{t}_X\) 手眼标定变换的旋转和平移 90.8
\(w_{ee}\) WBC 中末端跟踪奖励的权重 90.7
\(\sigma_{pos}\), \(\sigma_{rot}\) EE 跟踪奖励的位置和旋转高斯核宽度 90.12
\(GRS\) 抓取可达性集合(Grasp Reachability Set) 90.13

定理与核心公式速查表

公式 一句话说明 对应节
$q(\mathbf{a}_t \mathbf{a}_0) = \mathcal{N}(\sqrt{\bar{\alpha}_t}\mathbf{a}_0, (1-\bar{\alpha}_t)\mathbf{I})$ DDPM 前向过程:逐步加噪
\(\mathbf{a}_{t-1} = \frac{1}{\sqrt{\alpha_t}}(\mathbf{a}_t - \frac{\beta_t}{\sqrt{1-\bar{\alpha}_t}}\boldsymbol{\epsilon}_\theta)\) DDPM 反向过程:逐步去噪 90.3
\(\mathbf{s}_\theta = -\boldsymbol{\epsilon}_\theta / \sqrt{1-\bar{\alpha}_t}\) 噪声预测与 score matching 的等价性 90.11
\(\tau = K_p(q^{des} - q) - K_d \dot{q}\) WBC 的关节 PD 控制 90.7
\((\mathbf{R}_A - \mathbf{I})\mathbf{t}_X = \mathbf{R}_X\mathbf{t}_B - \mathbf{t}_A\) 手眼标定的平移方程 90.8
\(r_{ee} = w_{pos}\exp(-\|p\|^2/\sigma_{pos}^2) + w_{rot}\exp(-\theta^2/\sigma_{rot}^2)\) 末端跟踪高斯核奖励 90.12

版本信息速查

工具/框架 论文使用版本 当前推荐版本
Isaac Gym Preview 4 IsaacLab (建议迁移)
PyTorch 1.13+ 2.x
Diffusion Policy 代码 chi2023diffusion 最新 main 分支
UMI 硬件 v1 (GoPro + 3D 打印夹爪) v1
DDIM 推理步数 10-16 10(生产环境)/ 16(精度优先)
机器人平台 Go2 + ARX5 Go2 + ARX5 / Go2 + Z1

跨章综合题

综合练习 1 (⭐⭐⭐): 结合本章 (UMI-on-Legs) 和复合/210 (RAMBO) 的知识,设计一个系统:上层使用 Diffusion Policy 生成 EE 轨迹,底层使用 RAMBO 的 MPC+RL 混合控制器跟踪。画出完整的信号流图,标注每个模块的输入/输出维度、坐标系和频率。与 UMI-on-Legs 原始的纯 RL WBC 相比,这种混合方案有什么优势和劣势?

综合练习 1B (⭐⭐⭐): 如果要把 UMI-on-Legs 扩展到双臂操作(如一只手扶住门、另一只手转门把手),系统的哪些组件需要修改?列出 Diffusion Policy 的输入/输出变化、WBC 的动作空间变化、以及坐标变换链的新增部分。

综合练习 1C (⭐⭐⭐⭐): 分析 UMI-on-Legs 系统在以下三种失败场景中的行为:(a) Diffusion Policy 推理延迟从 100ms 突增到 500ms;(b) 腕部相机镜头被遮挡 2 秒;(c) 行走中一条腿的关节编码器故障。对于每种场景,当前系统会如何反应?理想系统应该如何反应?

综合练习 2 (⭐⭐⭐⭐): 设计一个从头到尾的四足操作实验流程:从 UMI 数据采集 → Diffusion Policy 训练 → WBC 训练 → 标定 → 部署 → 评估。列出每个步骤的输入/输出、预计时间、可能出错的环节和验证方法。估算整个流程从零到部署需要多少人-天。

90.16 研究实践建议

给新手的建议

  1. 先理解 Diffusion Policy 再理解 UMI-on-Legs。UMI-on-Legs 是 Diffusion Policy 在移动操作上的应用。如果你不理解 DDPM/DDIM 的数学原理,直接看 UMI-on-Legs 的系统设计会感到困惑。建议先完成 90.3 的最小 1D Diffusion Model 练习。
  2. 标定是被低估的关键步骤。在实验室里标定只需要 30 分钟,但标定误差会传播到整个系统——1mm 的外参偏差在 50cm 操作距离上可能导致 3-5mm 的末端误差。花时间做好标定,比花时间调策略更有效。
  3. 用日志回放代替反复部署。真机时间昂贵且有风险。每次部署都记录完整日志(图像、关节状态、EE 目标、chunk 内容),失败后先在日志上做分析,定位问题后再重新部署。
  4. 理解 EE 接口的解耦价值。UMI-on-Legs 最重要的工程洞察是:操作策略和运动控制通过 EE 轨迹接口解耦。理解这个解耦,比理解任何一个具体算法都更有持久价值。

给有经验者的建议

  1. 零样本迁移有条件。不要期望把一个平台上的 checkpoint 直接在另一个平台上工作。至少检查工作空间覆盖、夹爪兼容性和视觉域差异。
  2. DDIM 步数是速度-质量权衡的核心旋钮。生产部署用 DDIM-10,研究精度评测用 DDIM-16。不要在生产中用 DDIM-100——延迟增加 10 倍但质量提升微乎其微。
  3. WBC 的 manipulation-centric 设计不可忽视。如果你直接用纯足式 WBC 的奖励权重,末端精度会很差。必须显著提高 EE 跟踪权重,降低速度跟踪权重。
  4. 尾部延迟是真机部署的最大敌人。平均延迟 100ms 的系统,1% 的概率出现 300ms 延迟。这些"偶发长延迟"是导致真机失败的主要原因。必须设计异步推理和多 chunk 缓存来对抗尾部延迟。

故障排查手册

症状 可能原因 排查步骤 相关章节
末端持续偏移 3-5cm 手眼标定偏差 1. 重新标定 2. 检查标定板检测 3. 验证重投影误差 90.8
动作片段到达后末端跳变 chunk 融合参数不当 1. 打印新旧 chunk 差异 2. 增大混合衰减系数 3. 检查时间戳 90.4
行走时末端抖动 WBC 末端跟踪权重太低 1. 打印 EE 跟踪误差 2. 增大 \(w_{ee}\) 3. 检查基座扰动幅度 90.7
Diffusion 推理超时 GPU 负载过高或 DDIM 步数太多 1. 检查 GPU 占用 2. 减少 DDIM 步数到 10 3. 降低图像分辨率 90.3
零样本迁移成功率骤降 EE 工作空间不匹配 1. 可视化两个平台的工作空间 2. 检查夹爪尺寸差异 3. 调整任务帧位置 90.10
SLAM 漂移导致任务帧偏移 里程计累积误差 1. 检查行走距离与漂移的关系 2. 加入外部定位校正 3. 缩短任务时长 90.10
非抓取任务(推盘子)成功率低 摩擦敏感 + 力控精度不足 1. 检查接触力分布 2. 增加力相关的 DR 3. 考虑触觉反馈 90.14
不同操作员示教的策略行为不一致 多模态数据但 chunk 融合不当 1. 增加示教次数 2. 验证 Diffusion 的多模态覆盖 3. 调整 DDIM 步数 90.11
WBC 训练不收敛 EE 奖励权重不够高 1. 检查 EE 奖励在分项中的占比 2. 提高到 \(w_{ee} \geq 2.0\) 3. 先从站立 EE 跟踪开始 90.12
行走时抓取失败 WBC 未做 manipulation-centric 设计 1. 对比站立和行走时的 EE 误差 2. 加入行走补偿奖励 3. 降低速度追踪权重 90.12
视觉编码器输出不稳定 光照变化或运动模糊 1. 检查图像质量 2. 加入数据增强 3. 降低相机曝光时间 90.6
chunk 边界处动作不连续 chunk 融合策略缺失 1. 实现指数衰减融合 2. 调整融合窗口长度 3. 检查 chunk 重叠率 90.4
训练时 Diffusion loss 不降 学习率太高或数据量不足 1. 降低 lr 到 1e-4 2. 增加训练数据 3. 检查数据预处理 90.11
跨平台迁移 EE 偏移 任务帧注册误差 1. 重新检测参考标记物 2. 验证 \(T_{world}^{task}\) 3. 用已知目标做校准 90.5

90.17 本章与后续章节的关系

后续章节 与本章的关系 本章哪个知识点为其铺垫
复合/210 RAMBO RAMBO 的 MPC+RL 混合控制可替代 UMI-on-Legs 的纯 RL WBC 90.12 WBC 奖励设计
复合/220 移动操作前沿 UMI-on-Legs 是 2024 移动操作的代表性工作 90.14 前沿关系
复合/230 人形全身 RL UMI-on-Legs 的 EE 接口思想可扩展到人形 90.13 跨具身迁移
复合/250 力敏感 Loco-Mani UMI-on-Legs 的非抓取任务暴露了力控不足的问题 90.14 前沿挑战
复合/290 统一闭环 UMI-on-Legs 的三层架构是统一闭环的一个实例 90.1-90.2 架构设计

90.18 如果跳过本章会怎样

如果跳过本章,你会遇到以下问题:

  1. 读复合/210 RAMBO 时,不理解为什么需要 MPC 安全壳——因为不知道纯 RL WBC 的安全约束缺失问题。
  2. 读复合/220 移动操作前沿时,不理解 EE 轨迹接口的设计哲学——这是 UMI-on-Legs 最重要的工程贡献。
  3. 读复合/290 统一闭环时,缺乏具体系统实例——UMI-on-Legs 的三层架构是统一闭环的最直观案例。
  4. 尝试实现自己的移动操作系统时,不知道 Diffusion Policy 的推理延迟、Action Chunking 的融合策略和手眼标定的实操细节。

因此,即使你对 Diffusion Policy 的数学已经很熟悉,本章的系统工程细节(延迟处理、标定、失败分析、WBC 奖励设计)仍然值得仔细阅读。

90.19 预计阅读时间

阅读方式 时间 适合谁
精读(含练习) 30-45 小时 需要复现或搭建移动操作系统的读者
速读(跳过推导细节) 8-12 小时 有 RL 和操作背景的读者
速查(只看表格和速查卡) 1-2 小时 遇到具体部署问题时回来查

90.20 知识点总表

编号 知识点 核心要点 对应节 难度
1 移动操作动机 固定基座的局限:移动和操作无法同时发生 90.1 ⭐⭐
2 四足 vs 轮式选择 非结构化地形需要四足,代价是基座晃动 90.1 ⭐⭐
3 UMI 数据采集 手持夹爪示教,数据不涉及机器人本体 90.1 ⭐⭐
4 三层架构 感知-规划-执行的频率分离 90.2 ⭐⭐⭐
5 DDPM 前向过程 逐步加噪:$q(\mathbf{a}_t \mathbf{a}_0)$ 90.3
6 DDPM 反向去噪 噪声预测 → 逐步恢复信号 90.3 ⭐⭐⭐
7 DDIM 加速采样 确定性去噪,10-16 步即可 90.3 ⭐⭐⭐⭐
8 Action Chunking 一次输出多步动作,桥接频率差 90.4 ⭐⭐⭐
9 任务帧注册 把 EE 目标绑定到物体坐标系 90.5 ⭐⭐⭐
10 视觉编码 腕部相机 → ResNet → 条件向量 90.6 ⭐⭐⭐
11 RL WBC 奖励 manipulation-centric 优先级设计 90.7/90.12 ⭐⭐⭐
12 手眼标定 AX=XB 的 Tsai 方法 90.8 ⭐⭐⭐
13 延迟处理 延迟随机化 + chunk 时间戳补偿 90.9 ⭐⭐⭐
14 失败分析 四层分层归因:感知-规划-执行-硬件 90.10 ⭐⭐⭐
15 Score Matching 噪声预测等价于 score function 学习 90.11 ⭐⭐⭐⭐
16 跨具身迁移 三个条件:几何一致、空间覆盖、动态匹配 90.13 ⭐⭐⭐⭐
17 前沿定位 UMI-on-Legs 的系统集成贡献 90.14 ⭐⭐⭐
18 Manipulation-centric WBC 行走服务于操作,末端精度是第一公民 90.12 ⭐⭐⭐
19 行走补偿奖励 臂主动补偿行走引起的基座扰动 90.12 ⭐⭐⭐
20 WBC 奖励课程 站立→慢速行走→全速行走三阶段 90.12 ⭐⭐⭐
21 迁移诊断框架 工作空间、夹爪、动态能力、视觉域四维检查 90.13 ⭐⭐⭐⭐
22 非抓取操作挑战 摩擦依赖、力控精度要求 90.14 ⭐⭐⭐
23 动态操作延迟瓶颈 Diffusion 推理延迟限制了快速反应任务 90.14 ⭐⭐⭐⭐
24 EE 接口解耦 操作策略和运动控制通过末端轨迹解耦 90.1, 90.23 ⭐⭐⭐
25 Sim2Sim 验证 WBC 应在不同仿真器中交叉验证 90.7 ⭐⭐⭐
26 日志回放调试 从日志重放观测来定位策略问题 90.10 ⭐⭐⭐
27 安全层设计 chunk 过期/超时时的安全降级策略 90.12 ⭐⭐⭐
28 数据增强 光照/视角/遮挡增强提升策略鲁棒性 90.11 ⭐⭐⭐
29 首尾呼应 移动和操作同时发生的三层答案 90.23 ⭐⭐
30 职责划分原则 Diffusion 负责"做什么",WBC 负责"怎么做" 90.23 ⭐⭐

90.24 致读者

UMI-on-Legs 不是技术上最复杂的移动操作系统——它的 Diffusion Policy 和 WBC 都是已有工作的直接应用。但它是工程上最完整、可复现性最高的移动操作系统之一。完整阅读本章后,你应该能够:独立搭建一个从数据采集到真机部署的移动操作管线;理解每个工程决策背后的技术权衡;诊断部署中遇到的常见问题并定位根因。这些能力比理解任何一个算法的数学细节都更有持久的工程价值。

建议的复现路线:先完成 90.3 的最小 Diffusion Model 练习(理解生成机制),再完成 90.7 和 90.12 的 WBC 奖励设计分析(理解控制目标),最后尝试 90.10 的日志回放和失败归因(理解系统调试)。三个阶段各约 1-2 天,总计约一周即可建立对全系统的工程直觉。

90.21 如果跳过本章的补充说明

本章的独特价值不在于某个单一算法,而在于系统集成的完整性。它展示了从数据采集(UMI 手持夹爪)、到策略训练(Diffusion Policy + RL WBC)、到标定部署(手眼标定 + 延迟补偿)、到评估分析(14 物体系统性评估 + 分层失败归因)的全栈工程流程

在学术论文中,这些工程细节通常只在附录或补充材料中简要提及。但在实际复现和部署中,这些细节往往是成败的关键——标定误差 1mm 看起来微不足道,但在精细操作中它可能是成功和失败的分界线。

本质洞察:UMI-on-Legs 教给我们的最重要一课是:好的接口设计比好的算法更有持久价值。Diffusion Policy 可能在未来被更好的生成模型替代,RL WBC 可能被更安全的混合控制器替代,但"通过 EE 轨迹接口解耦操作和运动"这个架构原则不会过时——因为它是基于任务本质(操作关心末端,运动关心关节)的分层。

90.22 本章与前置章节的关系

前置知识桥接

本章的三个核心组件分别对应不同的前置章节:

Diffusion Policy 需要理解条件概率模型。如果你没有学过 DDPM 的数学基础(前向过程的马尔可夫链、反向过程的变分推断、噪声预测与 score matching 的等价性),90.3 节的推导会很困难。建议回顾概率论中的贝叶斯推断和变分方法。

RL WBC 需要理解 PPO 和 Privileged Learning。回顾复合/180 Deep-WBC:我们在那里学习了统一策略的设计动机、观测空间的本体感知与特权信息划分、以及 Teacher-Student 蒸馏。UMI-on-Legs 的 WBC 在此基础上增加了 manipulation-centric 的奖励优先级。

坐标变换链 需要理解刚体变换。回顾 SLAM 主线中的 \(SE(3)\) 变换和坐标系关系。UMI-on-Legs 的坐标变换链(世界→机体→臂基座→末端→相机→任务帧)有 5-6 层嵌套,每层都需要精确标定。

本章在课程中的定位

前置链路:
  SLAM 因子图 → SLAM 不确定性 → 统一闭环 (Ch.99)
  足式 RL    → Deep-WBC (Ch.88) → UMI-on-Legs (本章)
  操作基础   → Diffusion Policy → UMI 数据采集 → 本章

后续链路:
  本章 → RAMBO (Ch.91): MPC 安全壳替代纯 RL WBC
  本章 → 移动操作前沿 (Ch.92): UMI-on-Legs 的后续发展
  本章 → 统一闭环 (Ch.99): 三层架构的系统化分析

本章是"从单模块到系统集成"的关键转折点——之前的章节讨论的是各个模块(SLAM、MPC、WBC、RL、Diffusion Policy)的独立原理;本章展示了这些模块如何在一个真实系统中协同工作

90.23 本章的首尾呼应

本章开头提出的核心问题是:如何让移动和操作同时发生

通过 UMI-on-Legs 的系统设计,我们看到了答案的三个层次:

第一层(架构层次):通过 EE 轨迹接口解耦操作策略和运动控制器。操作策略只关心"末端应该去哪里",运动控制器只关心"如何在行走中保持末端稳定"。

第二层(数据层次):通过 UMI 手持夹爪采集任务级示教数据,数据完全不涉及机器人本体。这让同一份数据可以部署到任何拥有相似夹爪的平台上。

第三层(控制层次):通过 manipulation-centric WBC,让行走服务于操作。WBC 的首要目标是末端稳定,行走步态是实现这个目标的手段。

这三个层次共同回答了开头的问题:移动和操作之所以能同时发生,不是因为有一个"万能"的控制器,而是因为有一个清晰的职责划分——Diffusion Policy 负责"做什么",WBC 负责"怎么做",EE 接口负责连接两者。

反事实推理:如果没有 EE 接口解耦,而是让 Diffusion Policy 直接输出关节角度,会发生什么?首先,示教数据不再跨平台——Go2+ARX5 的关节定义和 Franka 完全不同。其次,策略需要同时学会操作技巧和行走控制——一个 Diffusion Policy 要负责 18 个关节的协调,学习难度指数级上升。最后,无法独立改进操作和运动——改善 WBC 的行走质量需要重新训练整个 Diffusion Policy。EE 接口解耦不仅是工程上的简化,更是概念上的必然——因为操作和运动确实是两个不同层次的问题。