第93章:人形全身 RL——动捕重定向、Teacher-Student 与多模态命令¶
| 元信息 | 值 |
|---|---|
| 难度 | ⭐⭐⭐⭐(数据管线 + PPO + 模仿学习 + 蒸馏) |
| 预计时间 | 2 周(55-65 小时) |
| 核心平台 | Unitree H1 / G1、AMASS、SMPL-X、IsaacGym / IsaacLab、MuJoCo |
| 主线 | SMPL-X/AMASS → 重定向 → 物理过滤 → 全身策略训练 → 稀疏观测蒸馏 |
本章定位 本章面向已经学过腿足简化模型、WBC、复合机器人动力学和四足 RL 基础的读者。 上一章(92)用 ZMP/DCM/TSID 构建了可解释的人形行走控制器。本章探索另一条路线:用大规模仿真和人体动作数据学习全身控制策略。 读完后应能设计奖励函数、理解训练管线、诊断常见训练失败。
93.0 前置自测¶
| # | 问题 | 前置知识 | 合格答案关键词 |
|---|---|---|---|
| 1 | PPO 中 GAE 的作用是什么? | 足式/190 | 低方差与低偏差折中 |
| 2 | Domain Randomization 为什么必要? | 足式/190 | 覆盖真实参数不确定性 |
| 3 | Teacher-Student 与非对称 critic 的区别是什么? | 足式/190 | 两阶段蒸馏 vs 一阶段训练 |
| 4 | SE(3) 误差为什么不能用欧拉角相减? | 复合/30 | 流形误差、对数映射 |
| 5 | 人形为什么需要动捕重定向? | 本章 | 全身动作先验和探索效率 |
本章目标¶
- 理解人形 RL 相比四足 RL 的新增难点:上体表达、双足平衡、动捕约束和高维动作。
- 掌握 AMASS / SMPL-X 到人形 URDF 的 shape fitting、motion fitting 与物理过滤。
- 理解 ExBody、HumanPlus、H2O、OmniH2O、HOVER 等路线背后的策略接口。
- 能区分 Teacher-Student、行为克隆、DAgger、非对称 critic 与 motion prior。
- 能设计 G1/H1 的 observation、action、reward、command mask 和评估指标。
93.1 人形 RL 的动机:从显式约束到数据驱动全身行为 ⭐⭐¶
经典控制留下的问题¶
第92章已经说明,ZMP/DCM/TSID 可以构建可解释的双足行走控制器。 但当任务变成挥手、踢球、跳舞、遥操作、上体跟踪和下体行走同时发生时,手工设计任务栈会非常困难。 每个动作都要定义 CoM、摆脚、躯干、双臂、腰部和头部的优先级。 更困难的是,很多动作的"自然性"不是一个简单二次代价能写出来的。
类比:经典 WBC 就像手工编写棋谱——每种局面都需要人类专家定义最优走法。RL 则类似于让程序自己下百万局棋后涌现出棋力。WBC 在结构化、可预测的任务中表现优异,但面对高维、模糊、多目标的全身运动时,数据驱动方法的优势开始显现。
人形 RL 的价值在于从大规模仿真和人体动作数据中学习这些高维协调规律。
| 维度 | 四足速度 RL | 人形全身 RL | 新增挑战 |
|---|---|---|---|
| 动作维度 | 12-18 | 23-43+ | 双臂、腰、头、手 |
| 任务目标 | 速度跟踪 | 速度 + 上体/末端/动作模仿 | 多目标冲突 |
| 数据来源 | 程序化地形和命令 | AMASS、视频、VR、遥操作 | 重定向与过滤 |
| 稳定指标 | 基座姿态与足端接触 | DCM/ZMP 影子指标 + 上体表达 | 平衡与动作自然性冲突 |
| 部署风险 | 摔倒与打滑 | 摔倒、碰撞、手臂惯性扰动 | 全身耦合更强 |
本质洞察 人形 RL 不是抛弃经典控制,而是把经典控制中难以手调的优先级和动作先验转移到数据与奖励中。 好的奖励项通常仍然能追溯到第92章的 CoM、角动量、接触和力矩约束。 如果不理解这些物理量,训练曲线看起来上涨也可能学到危险行为。
人形 RL 的历史脉络¶
| 时间 | 里程碑 | 关键创新 |
|---|---|---|
| 2018 | DeepMimic(Peng et al.) | 动作模仿 + RL,单个动作跟踪 |
| 2021 | AMP(Peng et al.) | 对抗式动作先验,无需逐帧对齐 |
| 2023 | ExBody(Cheng et al.) | 上下体解耦,人形全身表达 |
| 2024 | ExBody2、HumanPlus、HOVER | 多模态命令、Transformer、统一接口 |
| 2024-25 | Unitree G1/H1 实机验证 | sim-to-real 在人形上的成功案例 |
陷阱警告 ⚠️ "端到端 RL 可以学会一切"是一个危险的思维陷阱。实际上,成功的人形 RL 系统都大量依赖领域知识——精心设计的奖励函数、合理的观测选择、物理一致的仿真环境和经过过滤的动作数据。纯粹的"随机探索"在 30+ 维动作空间中几乎不可能收敛到有用的行为。
练习 93.1.A:列出经典 WBC(第92章)中的 5 个任务权重/优先级,解释为什么这些权重难以手工调整。
练习 93.1.B:从四足 RL(足式/190)的奖励函数出发,列出人形 RL 需要新增的奖励项。每个新增项对应第92章的哪个物理量?
93.2 AMASS 与 SMPL-X:人体动作数据的参数化 ⭐⭐⭐¶
为什么不用关节角 CSV 直接训练¶
人体动作数据来自不同实验室、不同骨架、不同 marker 设置。 如果直接把每个数据集的关节角当作机器人参考,关节定义和骨长都无法统一。 SMPL-X 的价值是提供统一人体网格和关节参数化,把不同来源动捕映射到同一个人体模型。
SMPL-X 的数学基础:SMPL-X 用一个可微函数 \(M(\beta, \theta, \psi)\) 将体型参数 \(\beta\)、身体姿态 \(\theta\) 和表情参数 \(\psi\) 映射到一个 10475 顶点的三角网格。其中身体姿态 \(\theta\) 包含 55 个关节的局部旋转(每个用轴角表示,共 \(55 \times 3 = 165\) 维)。
AMASS(Archive of Motion Capture as Surface Shapes)是一个统一数据集,收集了超过 40 小时、11000 段来自 15 个不同来源的动捕数据,全部用 SMPL-X 参数化。这使得研究者可以直接使用 AMASS 的 \((\beta, \theta)\) 参数,而无需处理不同动捕系统的骨架差异。
| 量 | 含义 | 典型维度 | 用于机器人时的作用 |
|---|---|---|---|
| shape \(\beta\) | 人体体型参数 | 10+ | 匹配机器人骨长比例 |
| pose \(\theta\) | 各关节旋转 | 55 关节左右 | 生成关键点和末端方向 |
| root translation | 全局平移 | 3 | 给出根轨迹 |
| body keypoints | 肩肘腕髋膝踝等 | 按任务选择 | 重定向主要目标 |
| mesh vertices | 人体表面点 | 数千点 | 碰撞与视觉对齐 |
从人体到机器人的三个误差来源¶
| 误差 | 例子 | 后果 | 缓解 |
|---|---|---|---|
| 形态误差 | 人类手臂长于 G1 手臂 | 末端无法同时对齐 | shape fitting 和关键点权重 |
| 关节拓扑误差 | 人体肩关节与机器人肩关节轴不同 | IK 多解或无解 | 使用 SE(3) 和关键点混合目标 |
| 动力学误差 | 人体动作可能需要机器人无法输出的力矩 | 仿真中摔倒或脚滑 | 物理过滤和课程训练 |
形态误差的量化:以 Unitree G1 为例,其手臂长度约为人类手臂长度的 70%,腿长约为 85%。这意味着如果人体动作要求双手触碰前方 50 cm 处的物体,G1 的末端只能到达约 35 cm 处。盲目匹配所有关键点会导致 IK 失败或机器人过度前倾。因此需要在关键点权重中区分:下体关键点(影响平衡)的权重应高于上体关键点(影响表达)。
数据管线总览¶
AMASS 不是直接喂给 PPO 的数据。 典型管线是:AMASS 动作片段 → SMPL-X 关键点 → 机器人 IK → 仿真跟踪 → 过滤可行动作 → 训练策略。 每一步都可能丢失信息,因此需要可视化对比人体和机器人关键点。
AMASS (.npz) ──→ SMPL-X (β, θ) ──→ 关键点 (N×3)
│
▼
┌──── 机器人 FK ←── 可微 IK ←── 关键点匹配
│ │
│ ▼
│ 仿真 rollout ──→ 物理过滤 ──→ 可行动作库
│ │
│ ▼
└───────────────────────── PPO 训练 ←── 参考动作
陷阱警告 ⚠️ AMASS 数据中有大量"安静"动作(站立、坐着说话等),这些动作对机器人训练贡献很小。如果不做筛选,训练数据中 60-70% 可能是几乎静止的状态,导致策略偏向保守、不愿意移动。数据预处理时应按根速度、关键点运动幅度和接触相位对动作片段分类,保证训练集中包含足够比例的动态动作。
练习 93.2.A:从 AMASS 数据集中选择 10 段动作,用 SMPL-X 可视化并标注每段的动作类型、时长、平均根速度和接触相位。
练习 93.2.B:计算人体和 G1 机器人在肩、肘、腕、髋、膝、踝 6 个关键点上的骨长比例。讨论哪些关键点的形态差异最大,以及如何在 IK 中处理这些差异。
93.3 SMPL-X 到机器人关节的可微重定向 ⭐⭐⭐⭐¶
Shape fitting¶
第一步不是求每一帧姿态,而是先让人体模型的骨长比例接近机器人。 $$ \beta^*=\arg\min_\beta\sum_k w_k|J_k^{human}(\beta)-J_k^{robot}|^2. $$
这里 \(J_k\) 是肩、肘、腕、髋、膝、踝等关键点。 权重 \(w_k\) 体现哪些部位更重要;对全身模仿,髋膝踝通常比手指更影响稳定。
为什么先做 shape fitting? 如果跳过这步直接做 motion fitting,优化器需要同时处理骨长差异和姿态差异,容易陷入局部极小值。先固定一个与机器人形态匹配的 \(\beta^*\),再逐帧求解姿态,问题更容易收敛。这是一种经典的"分步优化"策略:先解决低频变量(体型不变),再解决高频变量(每帧姿态变化)。
Motion fitting¶
第一项追踪人体关键点。 第二项限制速度(一阶差分),\(\lambda_v\) 典型值为 \(10^{-3}\)。 第三项限制离散加速度(二阶差分),\(\lambda_a\) 典型值为 \(10^{-4}\)。
没有平滑项时,逐帧 IK 会产生机器人无法执行的高频抖动。这些抖动来自 IK 的非唯一性:同一个关键点位置可能对应多个关节角解,逐帧独立求解时优化器可能在不同解之间跳动。
额外约束项:除了关键点误差和平滑项,实践中通常还需要关节限位约束: $$ L_{limit} = \sum_j \text{ReLU}(q_j - q_j^{max})^2 + \text{ReLU}(q_j^{min} - q_j)^2 $$
这防止重定向结果超出机器人的物理关节范围。
可微 IK 的代码骨架¶
import torch
def retarget_loss(robot_keypoints, human_keypoints, q, q_prev, q_prev2, weights):
"""中文注释:重定向损失由关键点误差、速度平滑和加速度平滑组成。"""
key_error = robot_keypoints - human_keypoints
key_loss = (weights[:, None] * key_error.square()).sum()
# 中文注释:一阶差分惩罚关节速度,防止逐帧跳动。
vel_loss = 1e-3 * (q - q_prev).square().sum()
# 中文注释:二阶差分惩罚关节加速度,保证力矩平滑。
acc_loss = 1e-4 * (q - 2.0 * q_prev + q_prev2).square().sum()
# 中文注释:关节限位的软惩罚,超限时产生二次代价。
limit_loss = torch.relu(q.abs() - 1.0).square().sum() * 1e-2
return key_loss + vel_loss + acc_loss + limit_loss
# 中文注释:真实工程中 robot_keypoints 来自可微 FK,human_keypoints 来自 SMPL-X。
# 使用 torch.autograd 对 q 求梯度后做梯度下降即可。
陷阱警告 ⚠️ 不要只看平均关键点误差。 一个动作的平均误差很小,也可能在单脚支撑瞬间出现 5 cm 足底穿透。 重定向完成后必须检查以下指标: 1. 足底高度(是否穿透地面) 2. 关节速度峰值(是否超出执行器极限) 3. 关节角限位距离(是否贴近或超出关节极限) 4. CoM 投影(是否在支撑多边形内)
练习 93.3.A:实现一个简化的可微 IK,以 3D 位置误差为目标,优化 5 个关节角。使用 PyTorch 的自动微分进行梯度下降。
练习 93.3.B:在上述 IK 中去掉速度平滑项 \(\lambda_v = 0\),观察连续帧之间关节角的跳变。量化有无平滑项时的关节速度峰值差异。
93.4 物理可行性过滤:从几何动作到可执行动作 ⭐⭐⭐¶
为什么 IK 成功不等于机器人能做¶
IK 只关心几何位置。 机器人在仿真中执行该轨迹时,还要满足摩擦、力矩、接触相位和动态平衡。 很多人体动作几何上能重定向,但动力学上会让机器人摔倒。
如果不做物理过滤会怎样? 不可执行的参考动作会严重破坏 RL 训练。假设 10% 的参考动作在物理上不可行(例如需要超出力矩极限的快速转体),策略在跟踪这些动作时会获得负奖励,但又被迫在这些状态附近探索。这导致: 1. 策略学会"放弃"某些动作,变得过于保守 2. 值函数对这些状态的估计不准确,影响 GAE 计算 3. 训练样本效率下降——大量计算资源浪费在不可行的 rollout 上
| 过滤指标 | 含义 | 常见阈值方向 | 失败解释 |
|---|---|---|---|
| MPJPE | 关键点平均误差 | 越小越好(< 5 cm) | 动作跟踪失败 |
| 足底穿透 | 脚低于地面距离 | 接近 0(< 1 cm) | 接触相位错误 |
| 关节速度峰值 | 执行器速度需求 | 低于硬件上限的 80% | 动作过快 |
| 力矩峰值 | 逆动力学估计 | 低于上限并留 20% 裕度 | 动力学不可执行 |
| 摔倒比例 | 仿真 rollout 中终止比例 | < 10% | 策略或参考不可行 |
Privileged teacher 的角色¶
过滤阶段常使用拥有完整状态信息的教师策略。 它可以看到真实接触、未来参考、相位、地形或精确根状态。 这样的策略不一定能部署,但很适合判断某段动作是否物理可行。
过滤不是删得越多越好¶
过滤过严会让训练集只剩简单动作,策略缺少多样性。 过滤过松会把大量不可执行动作放进训练,导致策略在高误差状态中浪费样本。
ExBody2 的关键发现:在构建动作数据集时,需要平衡**可行性**(feasibility)和**多样性**(diversity)。ExBody2 提出了一个自动数据集筛选方法:先用宽松阈值保留尽可能多的动作类别,再按难度分级,用课程学习逐步引入更难的动作。这种方法比简单的阈值过滤能保留 30-50% 更多的动作类型。
实践中常用分层阈值:先保留动作类别多样性,再按难度课程逐步加入。
物理过滤的实现流程¶
import numpy as np
def evaluate_motion_feasibility(env, reference_trajectory, n_rollouts=5):
"""中文注释:通过仿真 rollout 评估参考动作的物理可行性。"""
metrics = {
'mpjpe': [], # 关键点平均误差
'penetration': [], # 足底穿透深度
'vel_peak': [], # 关节速度峰值
'torque_peak': [], # 力矩峰值
'survival_rate': 0 # 存活率
}
survived = 0
for _ in range(n_rollouts):
obs = env.reset()
episode_alive = True
for t, ref_frame in enumerate(reference_trajectory):
# 中文注释:用 PD 控制跟踪参考关节角。
action = ref_frame['joint_angles']
obs, _, done, info = env.step(action)
if done:
episode_alive = False
break
# 中文注释:记录每帧的物理指标。
metrics['mpjpe'].append(info['keypoint_error'])
metrics['penetration'].append(info['foot_penetration'])
metrics['vel_peak'].append(info['joint_vel_max'])
metrics['torque_peak'].append(info['torque_max'])
if episode_alive:
survived += 1
metrics['survival_rate'] = survived / n_rollouts
return metrics
def filter_motion_library(motions, thresholds):
"""中文注释:根据物理指标过滤动作库。"""
feasible = []
for motion in motions:
m = evaluate_motion_feasibility(env, motion)
if (np.mean(m['mpjpe']) < thresholds['mpjpe']
and np.max(m['penetration']) < thresholds['penetration']
and m['survival_rate'] > thresholds['survival_rate']):
feasible.append(motion)
return feasible
练习 93.4.A:对一段重定向动作(如走路 + 挥手),计算上述 5 个过滤指标。讨论哪些指标之间存在冲突(例如放宽速度阈值可能增加摔倒比例)。
练习 93.4.B:实现一个简单的课程过滤器。将动作按难度分为 3 级(简单步行、快走、含上体动作),在训练的不同阶段逐步引入更难的动作。
93.5 奖励工程详解:逐项分析人形 RL 的奖励设计 ⭐⭐⭐⭐¶
为什么奖励设计是人形 RL 的核心¶
在四足 RL 中,奖励函数通常比较简单:跟踪速度命令 + 正则化。在人形 RL 中,奖励函数的复杂度显著增加,因为需要同时平衡多个目标:下体稳定、上体表达、动作平滑、能耗、接触质量和步态合理性。
奖励工程的本质是把第92章中 WBC 的任务优先级从"数学约束"转化为"标量信号"。WBC 用硬约束保护高优先级任务,RL 用奖励权重做软优先级。这种转化既是人形 RL 的灵活性来源(可以学习难以手写的行为),也是其主要风险源(权重错误会导致学到危险行为)。
奖励分量逐项分析¶
以典型的人形全身 RL 奖励函数为例(综合 ExBody、ExBody2、HOVER 等方案):
各分量如下:
(1)速度跟踪 \(r_{vel}\)
| 参数 | 典型值 | 含义 | 调节效果 |
|---|---|---|---|
| \(w_{vel}\) | 1.0-2.0 | 速度奖励权重 | 过大导致激进加速 |
| \(\sigma_v\) | 0.25 m/s | 奖励带宽 | 过小使奖励过于尖锐 |
物理对应:速度跟踪对应第92章中 DCM 规划的根速度输入。RL 策略学到的速度跟踪行为,在 WBC 框架中等价于由落脚规划和 DCM 反馈共同实现的功能。
(2)姿态奖励 \(r_{orient}\)
| 参数 | 典型值 | 含义 | 调节效果 |
|---|---|---|---|
| \(w_{orient}\) | 0.5-1.0 | 姿态奖励权重 | 过大使机器人僵硬 |
| \(\sigma_o\) | 0.2 rad | 姿态误差带宽 | 过小限制躯干运动 |
姿态奖励保证躯干大致竖直。\(e_{rpy}\) 通常只取 roll 和 pitch(偏航由速度命令控制)。
(3)上体关键点跟踪 \(r_{upper}\)
| 参数 | 典型值 | 含义 | 调节效果 |
|---|---|---|---|
| \(w_{upper}\) | 0.5-1.5 | 上体总权重 | 过大牺牲平衡换表达 |
| \(\sigma_u\) | 0.1 m | 关键点误差带宽 | 过小要求不合理的精度 |
| \(w_k\)(肩) | 1.0 | 肩关键点权重 | 肩部影响全身动量 |
| \(w_k\)(腕) | 0.5 | 腕关键点权重 | 腕部细节可放松 |
关键设计选择 上体关键点奖励的权重必须低于下体稳定奖励。 否则策略会为了手腕精度牺牲脚底接触,表现为手很准但机器人倾斜或摔倒。 ExBody 的核心创新正是这种上下体解耦:上体追踪关键点,下体只追踪速度和稳定。
(4)能耗惩罚 \(r_{energy}\)
| 参数 | 典型值 | 含义 | 调节效果 |
|---|---|---|---|
| \(w_e\) | 0.001-0.01 | 能耗惩罚权重 | 过大使动作僵硬 |
能耗惩罚防止策略学到高力矩振荡行为。在四足中这个项相对不敏感,但在人形中手臂的快速运动可能产生大的力矩功率,因此需要更仔细的调节。
(5)动作平滑 \(r_{smooth}\)
| 参数 | 典型值 | 含义 | 调节效果 |
|---|---|---|---|
| \(w_s\) | 0.01-0.1 | 平滑惩罚权重 | 过大使动作迟钝 |
动作平滑惩罚是 sim-to-real 的关键因素。仿真中高频振荡的动作在实物上会激励结构共振,导致传感器噪声放大和关节磨损。
(6)接触奖励 \(r_{contact}\)
| 参数 | 典型值 | 含义 | 调节效果 |
|---|---|---|---|
| \(w_c\) | 0.1-0.5 | 接触滑移惩罚 | 过大限制脚部运动 |
接触奖励惩罚支撑脚的水平滑动。\(\mathbb{1}_{contact}\) 是接触指示函数。这个项在 WBC 中对应接触不滑约束 \(J_c \dot v + \dot J_c v = 0\),但 RL 中只能用软惩罚。
(7)步态先验 \(r_{gait}\)
步态先验包含关节速度限制和摆脚离地高度引导。\(w_{air}\) 鼓励摆脚抬到合适高度(典型 3-8 cm),防止拖地行走。
奖励权重的诊断方法¶
训练时应当**分别记录**每个奖励分项的均值和方差。健康的训练曲线应该表现为:
| 分项 | 期望行为 | 异常信号 |
|---|---|---|
| \(r_{vel}\) | 随训练上升并稳定在 0.7-0.9 | 始终很低(速度跟踪失败)或过高(总是静止) |
| \(r_{orient}\) | 快速上升到 0.9+ | 振荡或下降(躯干不稳) |
| \(r_{upper}\) | 缓慢上升到 0.5-0.8 | 与 \(r_{orient}\) 反相关(上体和稳定冲突) |
| \(r_{energy}\) | 先下降后稳定 | 持续下降(策略越来越激进) |
| \(r_{smooth}\) | 快速下降后稳定 | 下降后反弹(策略发现了高奖励但抖动的行为) |
| \(r_{contact}\) | 快速下降后接近零 | 始终很大(脚底持续滑动) |
陷阱警告 ⚠️ 最危险的情况是总奖励上升但某个关键分项在恶化。例如:\(r_{vel}\) 和 \(r_{upper}\) 持续上升,但 \(r_{contact}\) 从 -0.1 恶化到 -0.5。这意味着策略学会了通过"滑动"来同时满足速度和上体跟踪,这种策略在实物上会立即摔倒。必须分项监控,不能只看总奖励。
奖励工程的系统方法论¶
奖励设计不应该是"试错法"。以下是一个系统化的奖励工程流程:
Phase 1:最小奖励集 只用存活奖励 + 速度跟踪奖励。训练至机器人能站立并缓慢移动。
Phase 2:稳定性奖励 加入姿态奖励、接触惩罚和能耗惩罚。训练至机器人能稳定行走。
Phase 3:质量奖励 加入平滑惩罚、步态先验和上体跟踪。训练至动作自然且可部署。
Phase 4:微调 根据分项监控结果,针对性调整权重。
def compute_humanoid_reward(state, action, prev_action, command, config):
"""中文注释:完整的人形 RL 奖励函数实现。"""
rewards = {}
# 中文注释:(1) 速度跟踪——指数核函数保证有界。
vel_error = (command[:3] - state['base_lin_vel'][:2]).norm()
rewards['velocity'] = config.w_vel * torch.exp(-vel_error**2 / config.sigma_vel**2)
# 中文注释:(2) 姿态保持——只惩罚 roll 和 pitch,不惩罚 yaw。
rp_error = state['base_rpy'][:2].norm()
rewards['orientation'] = config.w_orient * torch.exp(-rp_error**2 / config.sigma_orient**2)
# 中文注释:(3) 上体关键点跟踪。
kp_error = (state['upper_keypoints'] - state['ref_keypoints']).norm(dim=-1)
rewards['upper_body'] = config.w_upper * torch.exp(-kp_error.mean()**2 / config.sigma_upper**2)
# 中文注释:(4) 能耗惩罚——力矩乘速度的绝对值。
power = (state['joint_torques'] * state['joint_velocities']).abs().sum()
rewards['energy'] = -config.w_energy * power
# 中文注释:(5) 动作平滑——惩罚相邻时刻动作差异。
action_diff = (action - prev_action).norm()
rewards['smoothness'] = -config.w_smooth * action_diff**2
# 中文注释:(6) 接触滑移——惩罚支撑脚的水平速度。
for foot in ['left', 'right']:
if state[f'{foot}_contact']:
foot_slip = state[f'{foot}_foot_vel_xy'].norm()
rewards['contact'] = rewards.get('contact', 0) - config.w_contact * foot_slip
total = sum(rewards.values())
return total, rewards # 中文注释:同时返回总奖励和分项,便于监控。
本质洞察 奖励函数的设计本质上是把 WBC 的任务优先级从"硬约束/软约束的数学形式"转化为"标量信号的加权和"。 WBC 用 HQP 保证高优先级任务的精确满足,RL 用权重做近似优先级。 这种转化的代价是失去了数学上的优先级保证——RL 策略可能找到"总奖励高但某个重要分项差"的解。 这就是为什么分项监控如此重要。
练习 93.5.A:设计一个 G1 行走的奖励函数。包含速度跟踪、姿态、能耗和接触四个分项,给出每个分项的具体公式和超参数。
练习 93.5.B:假设训练中 \(r_{vel}=0.8\), \(r_{orient}=0.9\), \(r_{contact}=-0.3\), \(r_{smooth}=-0.05\)。分析这些数值是否合理,提出改进建议。
练习 93.5.C(跨章综合题):将 93.5 节的奖励分项与第92章的 TSID 任务做逐项对应。讨论以下问题:WBC 的 CoM 任务权重 \(w_{com}=100\) 和 RL 的 \(w_{vel}=1.5\) 在概念上有什么异同?为什么不能简单地用 WBC 的权重比例来设置 RL 的奖励权重?
93.6 网络架构:MLP 维度、激活、归一化与初始化 ⭐⭐⭐¶
人形 RL 的网络设计不是即插即用¶
四足 RL 中通常使用 2-3 层 MLP(如 [256, 128, 64]),配合 ELU 激活函数,这在 12 维动作空间中工作良好。人形 RL 的动作空间扩大到 23-43 维,观测空间也相应增大。网络架构的选择对训练稳定性和最终性能有显著影响。
策略网络¶
| 设计选择 | 典型方案 | 替代方案 | 权衡 |
|---|---|---|---|
| 隐藏层维度 | [512, 256, 128] | [1024, 512, 256] | 更宽的网络表达力更强但过拟合风险增加 |
| 激活函数 | ELU | ReLU, GELU, Tanh | ELU 在负区域有非零梯度,训练更稳定 |
| 输出激活 | 无(线性) | Tanh(限幅) | Tanh 自然限制动作范围但梯度在边界处消失 |
| 初始化 | Orthogonal | Xavier, Kaiming | Orthogonal 保持梯度范数,PPO 中最常用 |
| 标准差 | 可学习(per-action) | 固定或共享 | per-action 允许不同关节有不同探索强度 |
初始化的重要性:网络初始化决定了策略的初始行为。如果初始动作输出过大,机器人在第一步就会摔倒,导致大量负奖励充斥 buffer。正交初始化(Orthogonal initialization)配合较小的权重缩放(如 \(\sigma=0.01\) 对最后一层)可以保证初始动作接近零,让机器人以默认姿态站立,然后逐步探索。
值函数网络¶
值函数网络(Critic)通常比策略网络更宽,因为它需要估计所有可能状态的回报值——这比在某个状态下选择动作更困难。
| 设计选择 | 典型方案 | 原因 |
|---|---|---|
| 隐藏层维度 | [512, 512, 256] | 值函数需要更大容量 |
| 输入 | privileged 观测 | 训练时可以看到更多信息(非对称 critic) |
| 输出 | 标量 | 状态值 \(V(s)\) |
| 归一化 | 输入层归一化 | 不同观测维度的量纲不同 |
观测归一化策略¶
人形 RL 的观测向量包含关节角(\(\sim\) [-3, 3] rad)、关节速度(\(\sim\) [-10, 10] rad/s)、基座角速度(\(\sim\) [-5, 5] rad/s)、指令速度(\(\sim\) [-1, 1] m/s)等量纲差异巨大的信号。不做归一化会导致网络对大数值的输入过敏,忽略小数值但重要的输入。
| 方法 | 实现 | 优点 | 缺点 |
|---|---|---|---|
| Running mean/std | \(\hat o = (o - \mu_{run}) / \sigma_{run}\) | 自适应、无需先验 | 训练初期统计不稳定 |
| Fixed normalization | \(\hat o = o / s_{fixed}\) | 稳定、可复现 | 需要手工设定缩放因子 |
| 分组归一化 | 不同观测类型分别归一化 | 细粒度控制 | 实现复杂 |
实践建议:Running mean/std 在训练中最常用,但需要注意以下问题: 1. 前 100 步的统计量不可靠,应使用较大的初始方差 2. 部署时必须固定统计量(不再更新),否则策略行为会随时间漂移 3. 某些观测(如接触指示函数 \(\{0, 1\}\))不应做均值归一化
class RunningMeanStd:
"""中文注释:在线计算观测的运行均值和标准差,用于归一化。"""
def __init__(self, shape, epsilon=1e-4):
self.mean = torch.zeros(shape)
self.var = torch.ones(shape)
self.count = epsilon
def update(self, x):
# 中文注释:使用 Welford 在线算法更新统计量。
batch_mean = x.mean(dim=0)
batch_var = x.var(dim=0)
batch_count = x.shape[0]
delta = batch_mean - self.mean
total_count = self.count + batch_count
self.mean += delta * batch_count / total_count
self.var = (self.var * self.count + batch_var * batch_count
+ delta**2 * self.count * batch_count / total_count) / total_count
self.count = total_count
def normalize(self, x):
return (x - self.mean) / (self.var.sqrt() + 1e-8)
陷阱警告 ⚠️ 在 sim-to-real 部署中,使用了 running mean/std 归一化的策略必须保存训练结束时的统计量,并在部署时使用完全相同的值。如果忘记保存或加载了错误版本的统计量,策略的行为会完全不可预测——这是一个非常常见但极难调试的 bug,因为策略"看起来正常加载了"但输出完全错误。
人形 RL 的观测空间设计¶
观测空间的选择直接影响策略能学到什么。以下是典型的人形 RL 观测组成:
| 观测类型 | 维度 | 内容 | 获取方式 |
|---|---|---|---|
| 关节角 | 23-43 | 各关节相对角度 | 编码器读数 |
| 关节速度 | 23-43 | 各关节角速度 | 编码器差分或速度传感器 |
| 基座角速度 | 3 | 躯干角速度 | IMU 陀螺仪 |
| 基座方向 | 3-4 | 重力在基座坐标系中的投影 | IMU 加速度计 |
| 上一步动作 | 23-43 | 反馈上一时刻的动作 | 缓存 |
| 速度命令 | 3 | \([v_x, v_y, \omega_z]\) | 外部命令 |
| 历史观测 | \(H \times n_{obs}\) | 最近 \(H\) 帧的本体观测 | 滑动窗口 |
基座线速度的缺失:注意典型观测中不包含基座线速度。这是因为大多数人形机器人没有直接测量线速度的传感器(GPS 在室内不可用,视觉里程计有延迟)。策略需要从历史观测中隐式推断线速度。这就是为什么历史观测(或 LSTM/Transformer 编码器)对人形 RL 如此重要。
**privileged 教师观测**额外包含:
| 观测类型 | 维度 | 部署时不可用的原因 |
|---|---|---|
| 基座线速度 | 3 | 无直接传感器 |
| 接触力 | 4-8 | 传感器昂贵或不准确 |
| 未来参考轨迹 | 可变 | 只能看到当前命令 |
| 地形高度图 | 可变 | 需要外部感知 |
| 摩擦系数 | 1 | 未知 |
练习 93.6.A:实现一个简单的 MLP 策略网络(3 层,ELU 激活),输入 60 维观测,输出 23 维动作。比较 Orthogonal 和 Xavier 初始化下的初始动作分布。
练习 93.6.B:设计一个 G1 机器人的完整观测空间。列出每个观测的维度、量纲和归一化方式。计算总观测维度。
93.7 ExBody:上体 keypoint 跟踪 + 下体 velocity 跟踪 ⭐⭐⭐¶
核心放松¶
如果要求下体所有关键点严格模仿人体,机器人会被迫复现人类腿部细节。 但人类和机器人腿长、脚掌、关节轴都不同,严格模仿容易破坏稳定。 ExBody(Cheng et al., 2024, "Expressive Whole-Body Control for Humanoid Robots")的关键选择是:上体追踪表达性关键点,下体只追踪根速度和稳定行走。
这个设计选择背后有深刻的物理直觉:人形机器人的"表达性"主要体现在上半身(手势、躯干方向、头部朝向),而"稳定性"主要取决于下半身(步态、接触、CoM 位置)。两者的控制目标往往是冲突的——追求上体精确跟踪可能需要牺牲下体的稳定裕度。ExBody 的解耦设计正是为了化解这个冲突。
| 部分 | 跟踪目标 | 原因 | 风险 |
|---|---|---|---|
| 上体 | 肩肘腕、手部、躯干方向 | 表达动作语义 | 手臂扰动基座 |
| 腰部 | 姿态与相位相关目标 | 连接上下体动量 | 过度扭腰导致失稳 |
| 下体 | 根速度、站姿和接触稳定 | 优先保证不摔倒 | 腿部动作不像人体 |
| 全身 | 动作平滑和能耗正则 | 部署安全 | 权重过大使动作僵硬 |
奖励结构¶
关键是不要让上体 keypoint 奖励压过下体稳定奖励。 否则策略会为了手腕误差牺牲脚底接触。
与经典 WBC 的关系¶
ExBody 的奖励结构可以看作软任务栈。
| ExBody 奖励项 | WBC 对应任务 | 优先级处理方式 |
|---|---|---|
| \(r_{contact}\) | 接触不滑约束 | RL: 惩罚权重; WBC: 硬约束 |
| \(r_{root-vel}\) | CoM 速度任务 | RL: 跟踪奖励; WBC: 高优先级软任务 |
| \(r_{orientation}\) | 躯干姿态任务 | RL: 姿态奖励; WBC: 高优先级 |
| \(r_{upper-keypoint}\) | 末端位姿任务 | RL: 关键点奖励; WBC: 低优先级 |
| \(r_{smooth}\) + \(r_{energy}\) | 力矩正则 | RL: 惩罚项; WBC: QP 正则化 |
区别是 RL 不显式求解 HQP,而是通过回报学习折中。
ExBody 的训练流程¶
ExBody 的训练不是一步到位的。典型流程如下:
Stage 1:下体稳定训练(无上体目标) - 只启用速度跟踪、姿态和接触奖励 - 学会稳定行走,存活率 > 95% - 时长:约 2000 万步
Stage 2:加入上体跟踪 - 在 Stage 1 的策略基础上继续训练 - 加入上体关键点奖励,初始权重较小 - 逐步增大上体权重,监控存活率不低于 85% - 时长:约 5000 万步
Stage 3:全身精调 - 同时优化所有分项 - 加入更多样的动作参考数据 - 时长:约 5000 万步
如果不分阶段会怎样? 直接从头同时训练所有分项,策略很可能陷入"上体努力跟踪关键点但下体失去平衡"的局部最优。因为上体关键点奖励通常比稳定奖励更容易获得(手臂运动不受接触约束),策略会优先优化上体,导致下体的探索不足。
练习 93.7.A:设计一个 ExBody 风格的奖励表。给出每个分项的公式、权重和 \(\sigma\) 值。训练一段视频可视化结果。
练习 93.7.B:实验分阶段训练和一步训练的差异。比较两种方案在 1 亿步后的存活率和上体跟踪精度。
93.8 AMP 与动作先验:判别器结构与训练平衡 ⭐⭐⭐⭐¶
从显式奖励到对抗式先验¶
逐帧关键点跟踪要求精确的时间对齐,这在实际中很困难——不同人完成同一个动作的时序差异很大。AMP(Adversarial Motion Priors, Peng et al. 2021)提出了一种替代方案:用判别器区分"策略生成的运动"和"参考数据集中的运动",策略获得判别器认为"像真人"的奖励。
与 GAN 的类比:AMP 的判别器类似于 GAN 的判别器——它学习区分"真实"(参考动作)和"虚假"(策略生成的动作)。策略扮演生成器的角色,试图"欺骗"判别器。关键区别在于:GAN 的生成器直接优化判别器损失,而 AMP 的策略通过 RL 优化判别器提供的奖励。这使得 AMP 可以同时优化任务奖励(如速度跟踪)和风格奖励(像人类运动)。
判别器结构¶
判别器输入是**状态转移对**而非单帧状态,因为单帧不包含速度信息。
| 设计选择 | 典型方案 | 原因 |
|---|---|---|
| 输入 | \((s_t, s_{t+1})\) 的状态对 | 捕获运动特征而非静态姿态 |
| 网络 | 3 层 MLP [1024, 512] | 判别器不需要太大 |
| 输出 | 单个标量 | 经 sigmoid 后表示"像真人"的概率 |
| 训练目标 | LSGAN 或 WGAN-GP | WGAN-GP 训练更稳定 |
| 梯度惩罚 | \(\lambda_{gp} = 5-10\) | 防止判别器梯度爆炸 |
AMP 奖励与任务奖励的平衡¶
权重平衡的难点:\(w_{amp}\) 过大会导致策略只学动作风格,忽略任务目标(如速度跟踪)。\(w_{amp}\) 过小会让策略学到不自然但高效的动作。典型做法是 \(w_{task} : w_{amp} = 1 : 0.5\),并在训练后期逐步降低 \(w_{amp}\)。
**选择性 AMP**的最新进展:2025 年的研究(Multi-Gait Learning with Selective AMP)发现,AMP 不适用于所有运动类型。对于周期性、稳定性关键的步态(如行走、爬楼梯),AMP 可以加速收敛;但对于高动态步态(如跑步、跳跃),AMP 的正则化效应会过度约束运动,导致性能下降。因此应根据动作类型选择性地使用 AMP。
陷阱警告 ⚠️ 判别器训练不稳定是 AMP 最常见的问题。典型表现是判别器快速收敛到 100% 准确率,然后策略完全停止学习(因为判别器给所有策略动作都打零分)。解决方法: 1. 使用梯度惩罚(WGAN-GP) 2. 降低判别器学习率(通常为策略学习率的 1/5) 3. 限制判别器每步只更新 1 次,而策略更新 5-10 次 4. 在判别器输入中加入噪声
AMP 与显式跟踪奖励的对比¶
| 维度 | 显式跟踪奖励 | AMP 风格奖励 | 混合方案 |
|---|---|---|---|
| 时间对齐 | 需要精确帧对齐 | 不需要时间对齐 | 部分对齐 |
| 数据需求 | 每段动作需要完整参考 | 只需要状态分布 | 两种都需要 |
| 风格多样性 | 跟踪固定参考 | 从分布中采样 | 风格可变 |
| 调参难度 | \(\sigma\) 参数敏感 | 判别器训练不稳定 | 两套参数 |
| 动作自然性 | 取决于参考质量 | 取决于数据集分布 | 较好 |
何时用 AMP? 当你有大量未标注的人体动作数据但不需要精确跟踪特定动作时。例如,要让机器人"像人类一样走路"但不需要走出和某段视频完全一样的步态。
何时用显式跟踪? 当你需要精确复现特定动作时。例如,手语、舞蹈或特定操作任务中,动作的每一帧都有明确含义。
练习 93.8.A:实现一个简化的 AMP 判别器。输入为 \((s_t, s_{t+1})\)(状态维度 30),输出标量。用一组真实轨迹和随机轨迹训练判别器,观察损失曲线。
练习 93.8.B:对比 AMP 奖励和显式关键点跟踪奖励在人形行走任务中的表现。哪种方法的动作更自然?哪种方法的速度跟踪更准确?
93.9 HumanPlus:HST 预训练与 HIT 模仿学习 ⭐⭐⭐¶
为什么引入 Transformer¶
单帧本体观测不足以理解长动作。 例如挥拳、转身、踢腿都依赖相位和过去动作。 Transformer 可以把动作历史编码为上下文,学习更长时间尺度的动作先验。
HumanPlus(Fu et al., 2024)使用了两阶段框架:首先用大量动捕数据预训练一个"人体运动 Transformer"(HST),然后在机器人上微调为"人类到人形映射"(HIT)。
两阶段理解¶
| 阶段 | 输入 | 学习目标 | 输出 |
|---|---|---|---|
| HST 预训练 | 大规模动捕片段和机器人状态 | 学习可跟踪的低层动作模式 | 具有动作先验的策略 |
| HIT 模仿 | 人类示教或视觉输入 | 把人类意图映射到机器人动作 | 可遥操作/模仿策略 |
HST 的设计:HST 接收最近 \(H\) 帧的状态作为上下文(典型 \(H=10-30\)),使用因果注意力机制预测下一帧的动作。上下文长度的选择需要权衡:过短则无法理解长动作的相位,过长则增加计算量且可能引入无关信息。
与 ACT 的关系¶
ACT(Action Chunking with Transformers)风格模型常输出一段未来动作块(\(k\) 步),而不是单步动作。 好处是动作更平滑,坏处是闭环反应可能变慢。 人形上通常需要底层稳定控制频率高(50 Hz),而高层动作块频率可以低一些(10-20 Hz)。
| 方案 | 动作输出 | 控制频率 | 平滑性 | 反应速度 |
|---|---|---|---|---|
| 单步 MLP | \(a_t\) | 50 Hz | 依赖平滑奖励 | 快 |
| ACT (k=5) | \([a_t, ..., a_{t+4}]\) | 10 Hz | 内在平滑 | 慢 (50ms) |
| Temporal Ensemble | 多次预测加权平均 | 50 Hz | 良好 | 中等 |
Temporal Ensemble 的做法:在每个时刻,策略输出 \(k\) 步动作块,但只执行第一步。下一时刻重新预测,新预测和旧预测的重叠部分做指数加权平均。这既保持了高频闭环(每步都重新规划),又获得了动作块的平滑性。
陷阱警告 ⚠️ 在人形上使用动作块时,必须确保块长度不超过关键事件的时间尺度。例如,如果单支撑到双支撑的切换发生在 50 ms 内,而动作块跨度是 100 ms,策略无法在块内对接触切换做出反应。实践中动作块不宜超过 5 步(100 ms at 50 Hz)。
练习 93.9.A:比较单步 MLP 和 ACT(k=5)在人形站立推扰恢复任务中的表现。哪种方案的恢复更快?哪种方案的动作更平滑?
93.10 H2O / OmniH2O:稀疏输入、蒸馏与 DAgger ⭐⭐⭐⭐¶
信息不对称¶
| 信息 | 训练中可用 | 部署时可用 | 处理方式 |
|---|---|---|---|
| 完整人体姿态 | 可用 | 通常不可用 | 教师使用,学生蒸馏 |
| 真实接触状态 | 可用 | 传感困难 | 历史观测推断 |
| 未来参考轨迹 | 可用 | 只知道短期命令 | 相位和历史编码 |
| VR 头手位姿 | 可用 | 可用 | 稀疏命令接口 |
| 视觉 RGB | 可用但噪声大 | 可用 | 感知模块或离线重建 |
Teacher-Student 损失¶
\(o_t\) 是教师可见的完整观测,\(o_s\) 是学生部署时可见的稀疏观测。
两个损失项的作用: - 均方误差 \(\|\pi_s - \pi_t\|^2\) 让学生模仿教师的**期望动作**。 - KL 散度 \(D_{KL}(\pi_s \| \pi_t)\) 让学生模仿教师的**动作分布**(包括不确定性)。
只用均方误差时,学生可能在教师不确定的状态下过于自信;加入 KL 散度可以保留教师的"犹豫",这在部署时更安全。
为什么需要 DAgger¶
直接行为克隆只在教师访问过的状态上训练。 学生部署时一旦动作有小偏差,就会进入教师数据中很少出现的状态。 这就是分布偏移(distribution shift)问题。
分布偏移的数学表述:设教师的状态分布为 \(d_t\),学生的状态分布为 \(d_s\)。行为克隆在 \(d_t\) 上训练,但在 \(d_s\) 上测试。如果每步的误差为 \(\epsilon\),\(T\) 步后的累积误差可以达到 \(O(\epsilon T^2)\)(误差的复合效应)。DAgger 的关键思想是用学生的 \(d_s\) 重新采样数据,并由教师标注正确动作,使训练分布逐步接近部署分布。
DAgger 的做法是让学生自己 rollout,再由教师给这些状态标注动作。
DAgger 的训练流程:
| 阶段 | 数据来源 | 数据比例 | 预期效果 |
|---|---|---|---|
| Round 0 | 教师 rollout | 100% 教师数据 | 学生学会模仿教师分布 |
| Round 1 | 教师 50% + 学生 50% | 混合 | 学生覆盖自己的偏移状态 |
| Round 2 | 教师 20% + 学生 80% | 以学生为主 | 训练分布接近部署分布 |
| Round 3+ | 学生 rollout + 教师标注 | 几乎全部学生 | 收敛 |
为什么不从头只用学生 rollout? 因为在训练初期,学生的策略几乎是随机的,产生的状态分布与教师的状态分布完全不同。如果只在这些随机状态上训练,学生可能学到"如何从随机状态恢复",但忽略了"如何正确执行任务"。混合数据保证了学生既学会任务执行,又能处理自己的偏移。
import torch
def distill_step(student, teacher, batch, optimizer):
"""中文注释:学生只看稀疏观测,教师看完整观测。"""
sparse_obs = batch['sparse_obs']
full_obs = batch['full_obs']
with torch.no_grad():
teacher_action = teacher(full_obs)
student_action = student(sparse_obs)
# 中文注释:均方误差损失让学生模仿教师的期望动作。
loss = (student_action - teacher_action).square().mean()
optimizer.zero_grad()
loss.backward()
optimizer.step()
return float(loss.detach())
def dagger_collect(student, teacher, env, n_steps):
"""中文注释:DAgger 采集——用学生 rollout,教师标注。"""
buffer = []
obs = env.reset()
for _ in range(n_steps):
# 中文注释:用学生策略决定动作(部署分布采样)。
with torch.no_grad():
student_action = student(obs['sparse'])
next_obs, _, done, _ = env.step(student_action)
# 中文注释:用教师对同一状态标注"正确"动作。
with torch.no_grad():
teacher_action = teacher(obs['full'])
buffer.append({
'sparse_obs': obs['sparse'],
'full_obs': obs['full'],
'teacher_action': teacher_action
})
obs = next_obs if not done else env.reset()
return buffer
陷阱警告 ⚠️ DAgger 的一个常见实现错误是在学生 rollout 时使用教师的动作而非学生的动作。这失去了 DAgger 的核心意义——采集学生分布下的数据。正确做法是:学生决定动作、环境用学生动作前进、教师只负责标注"如果是我会怎么做"。
蒸馏训练的超参数指南¶
| 参数 | 典型值 | 选择依据 |
|---|---|---|
| 学习率 | 1e-3 到 3e-4 | 比 RL 训练略高,因为监督学习更稳定 |
| Batch size | 256-1024 | 越大越稳定,但受 GPU 内存限制 |
| KL 权重 \(\lambda\) | 0.01-0.1 | 过大会让学生过于保守 |
| DAgger 轮数 | 3-5 轮 | 每轮采集 10-50 万步学生数据 |
| 混合比例 | 逐轮减少教师数据 | Round 0: 100%, Round 1: 50%, Round 2: 20% |
| 历史帧数 | 5-15 | 太少丢失速度信息,太多增加延迟 |
| 训练 epoch | 50-200 | 每轮 DAgger 训练至损失收敛 |
如何判断蒸馏是否成功?
| 指标 | 合格标准 | 失败信号 |
|---|---|---|
| 动作 MSE | 教师动作标准差的 30% 以内 | 超过 50% |
| 存活率 | 教师的 90% 以上 | 低于 70% |
| 速度跟踪误差 | 教师的 1.5 倍以内 | 超过 2 倍 |
| 动作平滑度 | 与教师相当 | 学生明显更抖 |
陷阱警告 ⚠️ 蒸馏后的学生策略可能在某些"边缘状态"上表现很差——这些状态在正常 rollout 中很少出现,但在扰动后可能进入。典型的例子是"被推倒后的恢复":教师在完整观测下可以快速恢复,但学生缺少关键信息(如精确的基座线速度)时可能无法恢复。解决方法是在 DAgger 采集阶段刻意加入推力扰动,让学生的 rollout 覆盖更多边缘状态。
练习 93.10.A:构造一个简化的 Teacher-Student 实验。教师看 10 维观测,学生只看 5 维。比较纯行为克隆和 DAgger 在 1000 步后的跟踪误差。
练习 93.10.B:在 DAgger 训练中加入推力扰动(每 5 秒施加一次 30 N 推力)。比较有无扰动下的学生策略在扰动恢复任务中的存活率。
93.11 ExBody2 与 HOVER:多模态命令空间统一 ⭐⭐⭐¶
为什么需要统一命令接口¶
一个人形平台不可能为每种控制模式单独训练和部署一套策略。 速度跟踪、关节角跟踪、末端位姿跟踪、动作模仿和遥操作需要共享底层能力。 统一命令空间的思想是把不同命令编码到同一观测向量中,再用 mask 指明哪些维度有效。
类比操作系统:统一命令接口就像操作系统的系统调用——不同应用(速度控制、动作模仿、遥操作)通过同一个接口请求底层服务(全身运动),底层不需要知道上层应用是什么。这种设计大幅简化了部署和维护。
Observation masking¶
\(c\) 是命令向量,\(m\) 是 mask。 策略既看到命令值,也看到哪些命令是当前任务真正启用的。
训练时的随机 mask:为了让策略学会处理任意 mask 组合,训练时对 mask 做随机采样。例如在一个 batch 中,50% 的环境只启用速度命令,30% 启用关键点跟踪,20% 启用全部命令。这种随机 mask 训练等价于一种特殊的 domain randomization——randomize 的不是物理参数,而是任务接口。
ExBody2 的改进¶
ExBody2(Ji et al., 2024, "ExBody2: Advanced Expressive Humanoid Whole-Body Control")在 ExBody 基础上做了以下改进:
| 改进点 | ExBody | ExBody2 | 效果 |
|---|---|---|---|
| 动作数据集 | 手工筛选 | 自动筛选(平衡可行性和多样性) | 动作种类增加 50%+ |
| 蒸馏方式 | 单阶段 | privileged teacher + student | 稀疏观测下性能更好 |
| 命令接口 | 速度 + 关键点 | 多模态 mask | 一个策略多种用途 |
| 泛化性 | 特定动作集 | 预训练 + 微调 | 新动作只需少量微调 |
优点与风险¶
| 方面 | 优点 | 风险 | 缓解 |
|---|---|---|---|
| 部署 | 单策略覆盖多模式 | 接口复杂 | 固定命令规范 |
| 训练 | 共享动作先验 | 任务互相干扰 | 分阶段课程和采样平衡 |
| 泛化 | 可切换命令 | mask 外推失败 | 随机 mask 训练 |
| 安全 | 减少模式切换代码 | 错误 mask 可能危险 | 命令校验和限幅 |
统一命令空间的具体设计¶
以 HOVER 风格的接口为例,命令向量 \(c\) 和 mask \(m\) 的具体结构:
| 命令类型 | 维度 | 内容 | mask 位 |
|---|---|---|---|
| 速度命令 | 3 | \([v_x, v_y, \omega_z]\) | \(m[0:3]\) |
| 关节角目标 | \(n_a\) | 上体或全身关节角 | \(m[3:3+n_a]\) |
| 末端位姿 | 6-12 | 左右手的 SE(3) 目标 | \(m[3+n_a:...]\) |
| 动作参考 | 可变 | 动捕关键点或动作 ID | \(m[...]\) |
import torch
import numpy as np
def build_observation_with_mask(proprio, command_dict, active_modes):
"""中文注释:根据活跃模式构建统一观测向量。"""
# 中文注释:初始化命令和 mask 为零。
cmd = torch.zeros(command_dict['total_dim'])
mask = torch.zeros(command_dict['total_dim'])
if 'velocity' in active_modes:
cmd[0:3] = command_dict['velocity']
mask[0:3] = 1.0
if 'joint_target' in active_modes:
start = 3
end = 3 + command_dict['n_joints']
cmd[start:end] = command_dict['joint_target']
mask[start:end] = 1.0
if 'end_effector' in active_modes:
start = 3 + command_dict['n_joints']
end = start + 12 # 左右手各 6D
cmd[start:end] = command_dict['ee_target']
mask[start:end] = 1.0
# 中文注释:拼接本体观测、masked 命令和 mask 本身。
obs = torch.cat([proprio, mask * cmd, mask])
return obs
def random_mask_sampling(batch_size, n_modes=3):
"""中文注释:训练时随机采样 mask 组合。"""
masks = []
for _ in range(batch_size):
# 中文注释:每个环境随机启用 1-3 种命令模式。
n_active = np.random.randint(1, n_modes + 1)
active = np.random.choice(n_modes, n_active, replace=False)
masks.append(active)
return masks
陷阱警告 ⚠️ 随机 mask 训练的一个常见问题是某些 mask 组合被采样的频率过低,导致策略在这些组合上表现很差。例如"速度 + 末端位姿"同时启用的场景可能只占 10% 的采样,但在部署时可能是最常用的模式。应根据部署场景的频率分布调整 mask 采样概率。
练习 93.11.A:设计速度、关节角、末端位姿三类命令的统一观测向量。定义 mask 的维度和含义。写出一个 batch 中随机 mask 的采样代码。
练习 93.11.B:比较统一命令策略和三个独立策略在"速度跟踪"、"关节角跟踪"和"末端位姿跟踪"三个任务上的性能。哪种方案在单任务上更好?哪种在任务切换时更平滑?
93.12 2024-2025 人形 RL 前沿 ⭐⭐⭐¶
Unitree G1/H1:sim-to-real 的成功案例¶
Unitree 的 G1(29 DoF)和 H1(19 DoF)在 2024-2025 年成为人形 RL 研究的主流平台。多个研究组在这些平台上验证了 sim-to-real 迁移:
| 工作 | 平台 | 方法 | 关键结果 |
|---|---|---|---|
| unitree_rl_gym | G1/H1 | PPO + IsaacLab | 开源训练框架 |
| ALMI (2025) | H1-2 | AMP + 运动模仿 | 真机稳健行走 |
| ExBody2 (2024) | H1 | Teacher-Student + 多模态 | 全身表达 |
| 自动奖励学习 (2024) | G1 | PPO + learned reward | 无手工奖励设计 |
Berkeley Humanoid 与学术平台¶
Berkeley Humanoid 是 UC Berkeley 设计的开源小型人形(约 70 cm 高),专为 RL 研究设计。其特点是低成本、轻量化、可快速迭代。与 G1/H1 不同,Berkeley Humanoid 更适合算法验证而非应用场景。
Figure、1X 等商业人形¶
| 公司 | 机器人 | 控制路线 | RL 的角色 |
|---|---|---|---|
| Figure AI | Figure 01/02 | 混合(WBC + RL) | 高层技能学习 |
| 1X Technologies | NEO | RL + 视觉 | 家庭服务导向 |
| Agility Robotics | Digit | MPC + WBC | RL 用于步态优化 |
| Apptronik | Apollo | WBC 为主 | RL 作为补充 |
趋势:2024-2025 年的一个明显趋势是**混合架构**——底层使用 WBC 或简化 MPC 保证物理安全性,上层使用 RL 学习高维技能。纯端到端 RL(从像素到力矩)仍然主要停留在仿真和学术验证阶段,商业部署中 WBC + RL 的混合方案更受青睐。
IsaacLab 训练 pipeline¶
IsaacLab(原 IsaacGym 的继承者)是 NVIDIA 推出的大规模并行仿真平台,已经成为人形 RL 训练的事实标准。其核心优势是 GPU 并行——单张 RTX 4090 可以同时运行 4096 个人形环境,每秒产生数百万步训练数据。
典型训练配置:
| 参数 | 典型值 | 说明 |
|---|---|---|
| 并行环境数 | 4096 | GPU 并行 |
| 仿真频率 | 200 Hz | 物理步进 |
| 控制频率 | 50 Hz | 策略输出(decimation=4) |
| PPO batch size | 4096 x 24 steps | 约 10 万步 |
| 总训练步数 | 1-5 亿步 | 1-8 小时 |
| learning rate | 1e-4 到 3e-4 | Adam |
| discount \(\gamma\) | 0.99 | 标准值 |
| GAE \(\lambda\) | 0.95 | 标准值 |
| clip ratio | 0.2 | PPO 标准 |
训练曲线解读:
| 阶段 | 步数 | 期望行为 | 异常信号 |
|---|---|---|---|
| 初始探索 | 0-500万 | 奖励从负到零,学会站立 | 奖励始终为大负数(初始化过大) |
| 快速学习 | 500万-5000万 | 奖励快速上升,学会行走 | 奖励波动大(学习率过高) |
| 精细调节 | 5000万-2亿 | 奖励缓慢上升,动作更自然 | 奖励震荡(奖励冲突) |
| 收敛 | 2亿+ | 奖励稳定,各分项平衡 | 奖励下降(过拟合或探索衰减) |
陷阱警告 ⚠️ IsaacLab 的 GPU 仿真速度很快,但这也意味着如果奖励设计有误,你会在 30 分钟内训练出一个"完美但危险"的策略——总奖励很高但某个关键分项(如接触质量)已经严重恶化。快速迭代的前提是自动化的分项奖励监控和早期停止机制。
Domain Randomization 在人形上的特殊考虑¶
四足 RL 的 domain randomization 主要覆盖质量、摩擦和电机参数。人形 RL 需要额外考虑:
| 随机化参数 | 范围 | 原因 |
|---|---|---|
| 躯干质量 | \(\pm 20\%\) | 人形重心高,质量变化对平衡影响更大 |
| 手臂末端负载 | 0-2 kg | 模拟抓取或搬运 |
| 足底摩擦 | [0.3, 1.5] | 不同地面材质 |
| 关节阻尼 | \(\pm 30\%\) | 减速器特性差异 |
| 控制延迟 | [0, 40] ms | 通信和计算延迟 |
| IMU 噪声 | \(\pm 0.05\) rad/s | 陀螺仪漂移 |
| 推力扰动 | [0, 50] N, 每 3-8 s | 模拟外部碰撞 |
| CoM 偏移 | \(\pm 3\) cm | 建模误差 |
关节阻尼的特殊性:人形的关节阻尼对双足平衡有显著影响。阻尼过大会使策略依赖被动稳定性(靠阻尼耗散能量),部署到低阻尼的实物上时会失去平衡。阻尼过小则训练困难(系统更不稳定)。因此阻尼的随机化范围比四足更关键。
Sim-to-Real 的人形特有挑战¶
| 挑战 | 四足 | 人形 | 原因 |
|---|---|---|---|
| 接触模型 | 4 点接触 | 面接触 + 足底扭矩 | 人形脚掌提供扭矩而非点力 |
| 状态估计 | 基座姿态 | 基座姿态 + 线速度 | 人形更依赖线速度估计 |
| 安全性 | 摔倒后翻身 | 摔倒可能损坏 | 人形重心高、摔倒冲击大 |
| 动作空间 | 12 关节 | 23+ 关节 | 更多自由度、更多可能的失败模式 |
陷阱警告 ⚠️ 人形仿真中最常见的 sim-to-real gap 来源之一是足底接触模型。仿真通常用点接触或简化的面接触,而真实脚掌的接触力分布是非均匀的、依赖于脚掌形状和地面柔度的。这导致仿真中"稳定"的策略在实物上可能因为脚掌边缘先接触地面而失去 CoP 控制。
练习 93.12.A:在 IsaacLab 中配置一个 G1 行走任务。列出所有需要设定的参数(环境数、仿真频率、控制频率、PPO 超参数)。训练 1 亿步后绘制学习曲线。
练习 93.12.B:设计一个消融实验(ablation study)。逐个关闭 domain randomization 的参数类别(质量、摩擦、延迟、扰动),比较每种情况下策略在 perturbed 环境中的存活率。确定哪些随机化参数对 sim-to-real 最关键。
IsaacLab 训练的完整配置示例¶
以下是一个 G1 行走任务的典型配置清单(基于 IsaacLab 的 DirectRLEnvCfg 格式):
# 中文注释:IsaacLab 人形训练配置的关键参数示例(非完整配置文件)。
class G1WalkingCfg:
# === 仿真参数 ===
sim_dt = 0.005 # 仿真步长 5 ms (200 Hz)
decimation = 4 # 每 4 个仿真步输出一次动作 (50 Hz 控制)
episode_length_s = 20 # 每个 episode 最长 20 秒
num_envs = 4096 # GPU 并行环境数
# === 观测空间 ===
num_observations = 60 # 关节角(29) + 关节速度(29) + 基座角速度(3) + 重力(3) + 命令(3) - 重叠
num_privileged_obs = 75 # 额外包含接触力(4) + 摩擦(1) + 质量(1) + 线速度(3) + ...
num_actions = 29 # G1 的驱动关节数
# === 奖励权重 ===
reward_scales = {
'velocity_tracking': 1.5,
'orientation': 0.8,
'contact_penalty': -0.3,
'energy': -0.005,
'smoothness': -0.05,
'joint_limits': -1.0,
'survival': 0.5,
}
# === Domain Randomization ===
mass_randomization = 0.15 # ±15%
friction_range = [0.4, 1.2]
delay_range_ms = [0, 30]
push_interval_s = 5
push_force_range = [0, 40] # N
陷阱警告 ⚠️
decimation参数的设置直接影响策略的时间分辨率。decimation=4配合sim_dt=0.005意味着策略每 20 ms 输出一次动作。如果任务需要快速反应(如推扰恢复),可能需要降低 decimation。但降低 decimation 会增加每秒的策略调用次数,要求更轻量的网络以满足实时约束。
93.13 DeepMind Soccer、Parkour 与接触技能涌现 ⭐⭐⭐¶
从跟踪到技能¶
模仿学习擅长复现已有动作。 足球、起身、对抗和跑酷需要策略在交互中发现新技能。 这类任务通常结合课程学习、技能分解和自博弈。
技能学习的奖励结构¶
| 技能 | 主奖励 | 必要正则 | 失败模式 |
|---|---|---|---|
| 起身 | 恢复站立姿态 | 关节速度与碰撞 | 用头或膝盖撞地 |
| 踢球 | 球速和方向 | 支撑脚稳定 | 踢空或摔倒 |
| 对抗行走 | 任务得分 | 姿态和能耗 | 过激碰撞 |
| 跑酷 | 越障成功 | 感知一致性 | 跳得过高或落脚不稳 |
与全身模仿的互补¶
模仿给策略提供动作先验,强化学习给策略提供任务改进能力。 实际系统常先用动捕或程序参考预训练,再用任务奖励微调。
这种"预训练 + 微调"的范式与自然语言处理中的思路一致:大规模数据预训练(对应动捕数据预训练)提供通用能力,任务微调(对应任务奖励 RL)提供特定技能。两者缺一不可——没有预训练的 RL 探索效率极低,没有微调的预训练缺乏任务适应性。
课程学习在技能训练中的作用¶
复杂技能(如起身、跑酷)不能一开始就让机器人从零学习,需要逐步增加难度:
| 阶段 | 任务难度 | 训练策略 |
|---|---|---|
| 阶段 1 | 站立不倒 | 只有姿态和存活奖励 |
| 阶段 2 | 缓慢行走 | 加入速度跟踪,低速命令 |
| 阶段 3 | 正常行走 | 速度范围扩大,加入平滑正则 |
| 阶段 4 | 快走/小跑 | 高速命令,加入能耗惩罚 |
| 阶段 5 | 扰动恢复 | 加入随机推力和地形变化 |
课程的关键是**难度指标**的选择。常用的做法是监控存活率:当当前阶段的存活率超过 90%,自动切换到下一阶段。如果存活率低于 70%,回退到上一阶段。
练习 93.13.A:设计一个"起身"技能的课程学习方案。定义初始状态的随机化范围(从接近站立到完全躺倒),以及难度升级的触发条件。
从复杂技能的涌现到实际应用,人形 RL 还需要解决数据获取问题。下一节讨论如何通过遥操作高效收集人形任务数据。
93.14 OpenTeleVision 与遥操作数据接口 ⭐⭐¶
VR 遥操作为什么重要¶
人形需要大量真实任务数据。 直接让人形自主探索厨房、仓库和办公室任务成本高且危险。 VR 遥操作把人类意图转成头、手和身体命令,是构建数据集的实用入口。
遥操作接口层级¶
| 接口 | 输入 | 机器人侧处理 | 优点 | 缺点 |
|---|---|---|---|---|
| 头手位姿 | VR 头显和手柄 | 上体 IK + 下体策略 | 硬件简单 | 缺少手指细节 |
| 同构外骨骼 | 人体关节角 | 关节映射 | 低延迟直观 | 硬件定制 |
| RGB shadow | 相机图像 | 人体姿态估计 + 策略 | 无需穿戴 | 遮挡和延迟 |
| 语言命令 | 文本或语音 | 高层规划 + 技能库 | 自然交互 | 底层可行性难保证 |
数据记录要求¶
记录遥操作数据时,不只存动作。 还应存机器人状态、命令、相机时间戳、接触状态、失败标记、策略版本和环境描述。 否则后续很难判断失败来自感知、延迟、动力学还是示教本身。
最小数据记录规范:
| 字段 | 频率 | 格式 | 用途 |
|---|---|---|---|
| 关节角 \(q\) | 50 Hz | float32 x nq | 行为克隆标签 |
| 关节速度 \(\dot q\) | 50 Hz | float32 x nv | 动力学分析 |
| 关节力矩 \(\tau\) | 50 Hz | float32 x na | 力矩可行性检查 |
| IMU 数据 | 200 Hz | float32 x 6 | 基座状态估计 |
| VR 头手位姿 | 90 Hz | SE(3) x 3 | 命令重建 |
| 相机图像 | 30 Hz | JPEG/PNG | 视觉策略训练 |
| 接触状态 | 50 Hz | bool x 4 | 步态相位标注 |
| 失败标记 | 事件 | enum | 数据质量过滤 |
| 配置哈希 | 一次 | string | 复现性 |
时间同步的重要性:不同传感器的时间戳必须对齐到同一个时钟。如果 IMU 的时间戳比关节编码器快了 20 ms,后续的动力学分析会得到错误结果。工程上常用 PTP(Precision Time Protocol)或硬件触发同步。
陷阱警告 ⚠️ 遥操作数据中最容易被忽略的是"失败标记"。如果操作员在演示中犯了错误(如撞到桌子、动作不协调),这些数据如果不标记就混入训练集,会教策略学到错误行为。宁可丢弃 30% 的数据,也不要让低质量数据污染训练。
练习 93.14.A:设计一个 VR 遥操作的数据记录系统。定义每个字段的维度、频率和存储格式。估算 1 小时遥操作产生的数据量。
常见故障与排查¶
| 现象 | 可能原因 | 排查步骤 | 修复方向 |
|---|---|---|---|
| 重定向可视化正常但仿真摔倒 | 几何 IK 没有动力学可行性 | 检查足底接触、速度峰值和 CoM 投影 | 加入物理过滤和难度课程 |
| 训练奖励上涨但动作抖动 | 平滑正则太弱或动作频率过低 | 画动作差分和关节加速度 | 增加 action rate 和加速度惩罚 |
| 上体很准但下体不稳 | keypoint 奖励权重过高 | 分别统计上体和稳定奖励 | 降低上体权重或分阶段训练 |
| 学生蒸馏后明显退化 | 部署观测不足或分布偏移 | 比较教师与学生动作误差 | 增加历史观测并使用 DAgger |
| VR 遥操作延迟导致晃动 | 网络和感知时间戳未对齐 | 记录端到端延迟直方图 | 时间同步、预测滤波、低通命令 |
| 多模式策略切换异常 | mask 或命令归一化错误 | 打印每个模式的有效命令维度 | 固定接口规范并做限幅 |
| 动作很像人但脚底滑 | 模仿奖励压过接触稳定 | 统计接触脚水平速度 | 提高 foot slip 惩罚和接触相位约束 |
| 总奖励高但实物摔倒 | sim-to-real gap 或归一化不一致 | 对比训练/部署的观测统计量 | 检查 running mean 是否正确加载 |
| AMP 判别器收敛太快 | 判别器容量过大或学习率过高 | 画判别器准确率和策略 AMP 奖励 | 降低判别器 lr,增加梯度惩罚 |
练习汇总¶
| 编号 | 题目 | 要求 |
|---|---|---|
| 93.1 | AMASS 片段筛选 | 选 10 段动作,标注动作类型、时长、根速度和接触相位。 |
| 93.2 | SMPL-X 到 G1 关键点拟合 | 实现关键点 loss,并可视化机器人与人体关键点误差。 |
| 93.3 | 物理过滤指标 | 对一段重定向动作计算速度峰值、足底穿透和关节限位距离。 |
| 93.4 | 奖励函数设计 | 设计 G1 行走的完整奖励函数并给出超参数。 |
| 93.5 | ExBody 奖励复现 | 设计上体 keypoint + 下体 velocity 的 reward 表。 |
| 93.6 | Teacher-Student 蒸馏 | 构造教师完整观测与学生稀疏观测的对照实验。 |
| 93.7 | DAgger 分布偏移分析 | 实现 DAgger 采集并对比纯行为克隆。 |
| 93.8 | HOVER mask 接口设计 | 设计速度、关节角、末端位姿三类命令的统一观测。 |
| 93.9 | AMP 判别器实现 | 实现判别器并观察训练稳定性。 |
| 93.10 | 综合项目 | 训练一个 G1 上体动作模仿 + 下体速度跟踪的简化策略。 |
93.1 AMASS 片段筛选¶
- 目标:选 10 段动作,标注动作类型、时长、根速度和接触相位。
- 步骤 1:加载 AMASS 数据,提取根轨迹和关节角。
- 步骤 2:按运动幅度和速度对片段分类。
- 步骤 3:可视化每段动作的关键点轨迹。
- 交付物:分类表、图表和 500 字分析。
93.2 SMPL-X 到 G1 关键点拟合¶
- 目标:实现关键点 loss,并可视化机器人与人体关键点误差。
- 步骤 1:定义 6 个关键点的权重。
- 步骤 2:实现 shape fitting 和 motion fitting。
- 步骤 3:可视化误差并讨论形态差异的影响。
- 交付物:代码、可视化和 500 字分析。
93.3 物理过滤指标¶
- 目标:对一段重定向动作计算速度峰值、足底穿透和关节限位距离。
- 步骤 1:在仿真中 rollout 重定向轨迹。
- 步骤 2:记录并可视化 5 个过滤指标。
- 步骤 3:讨论过滤阈值的选择。
- 交付物:指标统计表和 500 字分析。
93.4 奖励函数设计¶
- 目标:设计 G1 行走的完整奖励函数并给出超参数。
- 步骤 1:定义速度、姿态、能耗、接触、平滑 5 个分项。
- 步骤 2:给出每个分项的公式和超参数值。
- 步骤 3:讨论各分项之间的潜在冲突。
- 交付物:奖励表和 500 字分析。
93.5 ExBody 奖励复现¶
- 目标:设计上体 keypoint + 下体 velocity 的 reward 表。
- 步骤 1:定义上体和下体的奖励分项。
- 步骤 2:给出权重和超参数。
- 步骤 3:讨论上下体奖励冲突的处理。
- 交付物:奖励配置和 500 字分析。
93.6 Teacher-Student 蒸馏¶
- 目标:构造教师完整观测与学生稀疏观测的对照实验。
- 步骤 1:定义教师和学生的观测空间。
- 步骤 2:实现蒸馏损失和训练循环。
- 步骤 3:对比教师和学生的动作误差。
- 交付物:代码、训练曲线和 500 字分析。
93.7 DAgger 分布偏移分析¶
- 目标:实现 DAgger 采集并对比纯行为克隆。
- 步骤 1:实现纯行为克隆训练。
- 步骤 2:实现 DAgger 在线采集和标注。
- 步骤 3:对比两种方法在 1000 步部署中的累积误差。
- 交付物:代码、对比图和 500 字分析。
93.8 HOVER mask 接口设计¶
- 目标:设计速度、关节角、末端位姿三类命令的统一观测。
- 步骤 1:定义三种命令的维度和范围。
- 步骤 2:设计 mask 的编码方式和随机采样策略。
- 步骤 3:实现观测拼接和验证。
- 交付物:接口规范文档和 500 字分析。
93.9 AMP 判别器实现¶
- 目标:实现 AMP 判别器并观察训练稳定性。
- 步骤 1:实现 WGAN-GP 损失和梯度惩罚。
- 步骤 2:用真实轨迹和随机轨迹训练判别器。
- 步骤 3:观察判别器准确率和梯度范数的变化。
- 交付物:代码、损失曲线和 500 字分析。
93.10 综合项目¶
- 目标:训练一个 G1 上体动作模仿 + 下体速度跟踪的简化策略。
- 步骤 1:定义完整的观测、动作和奖励。
- 步骤 2:在 IsaacLab 或 MuJoCo 中训练。
- 步骤 3:报告存活率、跟踪误差和动作平滑度。
- 交付物:训练代码、曲线和验收报告。
公式速查¶
| 编号 | 公式 | 含义 | 使用位置 |
|---|---|---|---|
| E1 | \(\beta^*=\arg\min_\beta\sum_k\|J_k^{human}(\beta)-J_k^{robot}\|^2\) | 形态拟合 | SMPL-X 到机器人 |
| E2 | \(q_t^*=\arg\min_q\sum_k\|T_k(q)-T_k^{human}\|^2+\lambda\|\Delta q\|^2\) | 动作拟合 | 逐帧 IK |
| E3 | \(r=r_{upper}+r_{vel}+r_{contact}+r_{smooth}\) | ExBody 奖励骨架 | 全身策略训练 |
| E4 | \(L=\|\pi_s(o_s)-\pi_t(o_t)\|^2\) | 蒸馏损失 | Teacher-Student |
| E5 | \(o=[o_{prop},m\odot c,m]\) | 命令 mask 观测 | 多模式策略 |
| E6 | \(A_t=\sum_l(\gamma\lambda)^l\delta_{t+l}\) | GAE | PPO 训练 |
| E7 | \(r=\exp(-\|e\|^2/\sigma^2)\) | 有界跟踪奖励 | 动作模仿和速度跟踪 |
| E8 | \(r_{AMP} = \max(0, 1 - 0.25(D-1)^2)\) | AMP 风格奖励 | 对抗式动作先验 |
综合项目:G1/H1 全身模仿训练管线¶
- 阶段 1:从 AMASS 选择 20 段不同动作,按速度、转身、上体幅度和接触难度分类。
- 阶段 2:完成关键点重定向,并保存每帧关节角、根状态和关键点误差。
- 阶段 3:在仿真中执行参考动作,过滤穿透、关节限位和高误差片段。
- 阶段 4:训练一个上体 keypoint + 下体 velocity 策略。
- 阶段 5:用教师完整观测训练,再蒸馏到只含本体历史和稀疏命令的学生策略。
- 阶段 6:在 MuJoCo 中做 sim2sim,报告 MPJPE、存活率、接触滑移和动作平滑度。
🔧 故障排查手册¶
以下故障场景来自实际人形 RL 训练和部署中的高频问题:
| 症状 | 可能原因 | 排查步骤 | 相关章节 |
|---|---|---|---|
| 训练 1000 万步仍不会站立 | 初始化过大或奖励尺度错误 | 1.检查初始动作分布 2.打印各奖励分项 3.降低最后一层初始化 | 93.6 |
| 会走但动作像机器人不像人 | AMP 或模仿奖励太弱 | 1.增加 AMP 权重 2.检查参考数据质量 3.可视化判别器准确率 | 93.8 |
| 实物上晃动但仿真稳定 | 观测归一化未正确加载 | 1.打印训练和部署的 running mean 2.检查统计量版本 3.固定并验证 | 93.6 |
| 蒸馏后学生在转弯时摔倒 | 转弯需要角速度信息但学生缺乏 | 1.对比教师和学生在转弯时的动作 2.增加历史帧数 3.加入 DAgger 转弯数据 | 93.10 |
| 多模态策略在切换时抖动 | mask 切换导致命令突变 | 1.画 mask 切换前后的命令值 2.加命令平滑插值 3.检查归一化一致性 | 93.11 |
调试原则:人形 RL 问题的排查应遵循"分项排查"的原则——先确定是哪个奖励分项导致了问题(通过分别禁用各分项做消融),再深入分析该分项的内部逻辑。不要一上来就改全部权重,因为这会把一个已知的问题变成多个未知的问题。
本章小结¶
| 知识点 | 核心内容 | 所在章节 |
|---|---|---|
| 人形 RL 动机 | 把 WBC 的手工优先级转移到数据驱动学习 | 93.1 |
| AMASS/SMPL-X | 统一人体动作数据的参数化 | 93.2 |
| 可微重定向 | shape fitting + motion fitting + 平滑约束 | 93.3 |
| 物理过滤 | 从几何可行到动力学可执行 | 93.4 |
| 奖励工程 | 逐项分析奖励分量和超参数 | 93.5 |
| 网络架构 | MLP 维度、归一化、初始化 | 93.6 |
| ExBody | 上下体解耦的奖励设计 | 93.7 |
| AMP | 对抗式动作先验和判别器平衡 | 93.8 |
| HumanPlus | Transformer 预训练和模仿学习 | 93.9 |
| Teacher-Student/DAgger | 稀疏观测蒸馏和分布偏移 | 93.10 |
| 多模态命令 | 统一命令空间和 mask 设计 | 93.11 |
| 2024-25 前沿 | Unitree G1/H1、IsaacLab pipeline | 93.12 |
人形 RL 与经典 WBC 的融合——回顾与前瞻¶
本章和第92章构成了人形全身控制的两条互补路线。在实际工程中,这两条路线正在融合:
混合架构的三种模式¶
模式 A:RL 策略 + WBC 安全层 RL 策略输出关节角目标,WBC 作为安全层检查这些目标是否满足物理约束(力矩限幅、接触稳定性)。如果不满足,WBC 修正目标。这种模式的优点是 RL 策略可以自由探索,WBC 提供安全保障。
模式 B:RL 上层 + WBC 下层 RL 策略输出 CoM 目标、末端位姿或动量参考,WBC 将这些高层目标转化为关节力矩。这种模式保留了 WBC 的精确任务执行能力,同时让 RL 处理高层决策。
模式 C:RL 初始化 + WBC 微调 先用 RL 训练一个粗略策略,然后用 WBC 的分析工具(ZMP 裕度、力矩分布等)诊断策略的弱点,针对性地微调奖励函数或增加约束。
| 模式 | RL 负责 | WBC 负责 | 适用场景 |
|---|---|---|---|
| A | 全身动作规划 | 安全约束检查 | 高动态、多样化动作 |
| B | 高层目标生成 | 低层力矩计算 | 精确操作 + 移动 |
| C | 初始策略搜索 | 事后分析与修正 | 研究和原型开发 |
本质洞察 经典 WBC 和 RL 不是对立关系,而是同一个硬币的两面。 WBC 提供了物理约束的精确数学表达——这些约束不会因为使用 RL 就消失。 RL 提供了在约束满足前提下的最优行为搜索能力——这是手工调参无法企及的。 未来的人形控制系统会越来越多地把两者结合:RL 学习"做什么",WBC 保证"安全地做"。
延伸阅读¶
| 论文/资源 | 难度 | 内容 |
|---|---|---|
| Peng et al., "DeepMimic: Example-Guided Deep RL of Physics-Based Character Skills", SIGGRAPH 2018 | ⭐⭐⭐ | 动作模仿 + RL 的开创性工作 |
| Peng et al., "AMP: Adversarial Motion Priors for Stylized Physics-Based Character Animation", SIGGRAPH 2021 | ⭐⭐⭐⭐ | 对抗式动作先验 |
| Cheng et al., "Expressive Whole-Body Control for Humanoid Robots", 2024 | ⭐⭐⭐ | ExBody 上下体解耦 |
| Ji et al., "ExBody2: Advanced Expressive Humanoid Whole-Body Control", 2024 | ⭐⭐⭐⭐ | 多模态命令、自动数据集筛选 |
| Fu et al., "HumanPlus: Humanoid Shadowing and Imitation from Humans", 2024 | ⭐⭐⭐ | Transformer + 模仿学习 |
| He et al., "OmniH2O: Universal and Dexterous Human-to-Humanoid Whole-Body Teleoperation and Learning", 2024 | ⭐⭐⭐⭐ | 稀疏输入蒸馏 |
| IsaacLab 文档:isaac-sim.github.io/IsaacLab | ⭐⭐ | 训练 pipeline 参考 |
| unitree_rl_gym:github.com/unitreerobotics/unitree_rl_gym | ⭐⭐ | G1/H1 训练代码 |
| Radosavovic et al., "Real-World Humanoid Locomotion with RL", Science Robotics 2024 | ⭐⭐⭐ | 实物人形 RL 验证 |
| awesome-humanoid-robot-learning:github.com/YanjieZe/awesome-humanoid-robot-learning | ⭐ | 论文汇总列表 |
推荐学习路径¶
| 阶段 | 内容 | 时间 |
|---|---|---|
| 入门 | 93.1-93.4,理解数据管线(AMASS → 重定向 → 过滤) | 1 周 |
| 核心 | 93.5-93.8,掌握奖励工程、网络设计和 AMP | 1 周 |
| 进阶 | 93.9-93.12,理解蒸馏、多模态和训练 pipeline | 0.5 周 |
| 实践 | 综合项目,训练一个简化的全身策略 | 0.5 周 |
学习建议:人形 RL 的代码实验需要 GPU 资源。如果没有本地 GPU,可以使用 MuJoCo(CPU 仿真,速度较慢但免费)进行算法验证,再在有 GPU 的服务器上用 IsaacLab 进行大规模训练。奖励函数设计是本章最重要的技能——建议先手工设计一个基础奖励,训练后分析分项曲线,再迭代改进。
术语对照表¶
| 本章术语 | 英文 | 其他常见名称 | 出处 |
|---|---|---|---|
| 动捕重定向 | Motion Retargeting | Motion Mapping | |
| 形态拟合 | Shape Fitting | Body Calibration | SMPL |
| 物理过滤 | Physics Filtering | Feasibility Check | |
| 教师-学生 | Teacher-Student | Privileged-Deployment | |
| 行为克隆 | Behavioral Cloning (BC) | Imitation Learning (IL) | |
| 对抗式动作先验 | Adversarial Motion Prior (AMP) | Style Reward | Peng 2021 |
| 命令掩码 | Command Masking | Task Conditioning | HOVER |
| 分布偏移 | Distribution Shift | Covariate Shift | DAgger |
93 巩固卡片 01:AMASS¶
- 问题:为什么需要统一人体数据?
- 直觉:不同动捕骨架需要共同参数化。
- 数学抓手:SMPL-X pose 与 shape
- 工程接口:数据预处理
- 易错判断:不能直接把人体角度给机器人。
- 自测动作:可视化关键点。
93 巩固卡片 02:重定向¶
- 问题:IK 成功为何还不够?
- 直觉:几何可达不代表动力学可执行。
- 数学抓手:关键点 loss + 平滑项
- 工程接口:motion fitting
- 易错判断:忽略速度会抖动。
- 自测动作:检查关节速度。
93 巩固卡片 03:物理过滤¶
- 问题:为什么要删除片段?
- 直觉:不可执行参考会污染训练。
- 数学抓手:rollout error 阈值
- 工程接口:数据筛选
- 易错判断:删太多会降低多样性。
- 自测动作:统计动作类别覆盖。
93 巩固卡片 04:ExBody¶
- 问题:为什么下体不严格模仿?
- 直觉:稳定优先于腿部外观。
- 数学抓手:\(r_{upper}+r_{vel}\)
- 工程接口:reward design
- 易错判断:上体权重过高会摔。
- 自测动作:分项奖励监控。
93 巩固卡片 05:蒸馏¶
- 问题:学生为什么会退化?
- 直觉:观测少且分布会偏移。
- 数学抓手:\(\|\pi_s-\pi_t\|^2\)
- 工程接口:Teacher-Student
- 易错判断:只做离线克隆不够。
- 自测动作:执行 DAgger 采样。
93 巩固卡片 06:Mask¶
- 问题:如何一个策略多模式?
- 直觉:命令值和有效位一起输入。
- 数学抓手:\(m\odot c\)
- 工程接口:HOVER 风格接口
- 易错判断:mask 错会危险。
- 自测动作:单元测试命令维度。