在基于 AMP(Adversarial Motion Prior)的模仿学习管线中,高质量的运动数据集是决定策略自然度的关键前提。本章聚焦从原始运动捕获数据到训练就绪数据集的完整链路,系统阐述 GMR 格式到 Lab 格式的重定向原理、批量处理工具链、以及数据集在 Isaac Lab 环境中的加载与采样机制。阅读本章前,建议先掌握 ATOM01 机器人模型配置 中的关节命名与 URDF/MJCF 结构;本章内容为后续深入 AMP 对抗运动先验算法 和 AMP Runner 与模仿学习训练 提供数据层面的基础。
数据格式与坐标系约定
项目涉及三种运动数据表示:外部输入的 GMR 格式、中间处理用的 CSV/NPZ 格式,以及训练系统消费的标准 Lab 格式。三者在坐标约定与数据维度上存在显著差异,理解这些差异是避免重定向错误的先决条件。
| 格式 | 来源 | 根旋转四元数 | DOF 顺序 | 关键体位置 | 速度信息 |
|---|---|---|---|---|---|
| GMR | MuJoCo 生态 / MimicKit | (x, y, z, w) |
MuJoCo 模型定义 | 无 | 无 |
| CSV/NPZ | BeyondMimic 等手动示教 | (x, y, z, w),需手动转 (w, x, y, z) |
与 SDK 一致 | 仿真后计算 | 数值微分 |
| Lab | 项目内部标准 | (w, x, y, z) |
Isaac Lab 模型定义 | 仿真正向运动学计算 | 加载时前向差分 |
GMR 格式的原始数据为 Python pickle 文件,包含 fps、root_pos、root_rot、dof_pos 四个核心字段。Lab 格式在此基础上增加了 loop_mode(循环模式,0 为 clamp,1 为 wrap)以及 key_body_pos(关键体在世界坐标系中的位置),后者直接服务于 AMP 判别器对运动风格的度量。四元数从 GMR 的 (x, y, z, w) 转换为 Lab 的 (w, x, y, z) 通过 math_utils.convert_quat 完成,同时执行唯一化与归一化以确保插值稳定性。
Sources: gmr_to_lab.py, gmr_to_lab.py
重定向架构与数据流
整个重定向系统采用分层设计:配置层定义关节映射,核心层执行格式转换与坐标计算,应用层将结果注入 AMP 训练环境。下图展示了从原始运动文件到训练采样的完整数据流。
flowchart TD
A[原始运动数据<br/>GMR .pkl / CSV] --> B{格式类型}
B -->|GMR| C[gmr_to_lab.py<br/>核心转换引擎]
B -->|CSV| D[csv_to_npz.py<br/>BeyondMimic 管线]
C --> E[config/atom01.yaml<br/>关节映射配置]
E --> C
C --> F[Isaac Sim 仿真<br/>正向运动学计算关键体位置]
F --> G[Lab 格式 .pkl<br/>fps / root_pos / root_rot / dof_pos / key_body_pos / loop_mode]
D --> H[NPZ 格式<br/>关节与刚体状态]
G --> I[MotionDataManager<br/>加载 / 插值 / 采样]
I --> J[AnimationManager<br/>时间步提取与缓冲]
J --> K[AMP Discriminator<br/>演示数据供给]
配置层通过 YAML 文件显式声明 GMR 与 Lab 之间的 DOF 名称映射,避免了硬编码索引导致的维护灾难。核心层在提取 DOF 数据时,依据名称列表动态构建索引映射 gmr_to_lab_indices,实现 O(n) 的重排序。对于关键体位置,系统不会在离线阶段通过刚体运动学解析计算,而是启动轻量化的 Isaac Sim 上下文,将单条或多条运动逐帧写入机器人状态,利用 PhysX 的正向运动学缓存直接读取 body_pos_w,从而确保与训练环境完全一致的几何定义。
Sources: gmr_to_lab.py, gmr_to_lab.py, dataset_retarget.py
关节映射与关键体配置
robolab/scripts/tools/retarget/config/atom01.yaml 是 ATOM01 机器人所有重定向任务的中央配置。其包含三个逻辑段:GMR 关节名称列表、Lab 关节名称列表、以及关键体名称列表。两个关节列表的长度必须相等,且 Lab 列表中的每个名称必须在 GMR 列表中存在,通过名称匹配完成重排序。
关键体(key bodies)的选择直接决定了 AMP 判别器对运动风格的敏感度。在 ATOM01 的配置中,关键体包含左右脚踝滚转连杆、左右肘偏航连杆、以及左右手臂滚转连杆,共六个刚体。这些刚体覆盖了四肢末端与躯干连接点,能够在不使用完整刚体集的情况下有效区分行走、奔跑、转向等不同步态模式。关键体的顺序必须与 AMP 环境观测构造中的 preserve_order=True 保持一致,否则会导致判别器输入错位。
Sources: atom01.yaml, atom01_amp_env_cfg.py
批量重定向工作流
项目提供单文件验证与批量转换两种模式。单文件模式(single_retarget.py)适用于调试新运动或截取特定帧范围;批量模式(dataset_retarget.py)则用于将整个目录的 GMR 文件一次性转换为 Lab 格式,是数据集准备的标准路径。
flowchart LR
A[准备 GMR 文件目录] --> B[检查 atom01.yaml<br/>关节映射]
B --> C[运行 dataset_retarget.py]
C --> D[启动 Isaac Sim<br/>多环境并行仿真]
D --> E[逐帧写入关节状态]
E --> F[读取 body_pos_w<br/>记录关键体轨迹]
F --> G[输出 Lab .pkl 到目标目录]
批量转换脚本的核心设计是将所有待转换运动加载为独立的仿真环境(num_envs = number of motions),利用 GPU 并行能力一次性完成所有关键体位置的计算。该脚本要求所有运动的帧率一致,若检测到不同 fps 会发出警告并以首个运动的帧率作为仿真步长。转换完成后,每个输出文件保留原始文件名,内容扩展了 key_body_pos 与 loop_mode 字段。命令行调用时只需指定输入目录、输出目录与循环模式,无需为每个文件单独配置。
Sources: dataset_retarget.py, dataset_retarget.py
从 CSV/NPZ 构建数据集
除 GMR 生态外,部分运动数据以 CSV 文本格式存在,例如通过 BeyondMimic 或其他离线规划工具生成的轨迹。csv_to_npz.py 专门处理此类数据,其内部实现了完整的运动学管线:CSV 加载 → 帧率重采样(线性插值与球面插值)→ 数值微分求速度 → 仿真验证 → NPZ 输出。
CSV 的列顺序约定为:根位置 3 维、根旋转四元数 4 维、关节位置 n 维。脚本首先将输入帧率通过 MotionLoader 插值到目标帧率(默认 50 Hz),使用 quat_slerp 保证旋转插值的测地线性。随后通过前向差分计算根线速度、关节速度与根角速度(基于 SO3 导数)。与 GMR 管线不同,CSV 管线在仿真循环中不仅记录关节状态,还记录全部刚体的位置、姿态、线速度与角速度,输出为 NPZ 格式供直接回放或后续分析。
Sources: csv_to_npz.py, csv_to_npz.py
数据集在 AMP 环境中的加载机制
转换后的 Lab 格式数据并非被直接读取为原始帧序列,而是通过 MotionDataManager 与 AnimationManager 两级管理器接入训练循环。理解这一加载机制对于调试运动闪烁、错位或判别器收敛异常至关重要。
MotionDataTerm 是数据加载的物理单元。它在环境初始化时读取指定目录下所有 .pkl 文件,依据配置中的 motion_data_weights 为每条运动分配采样概率,并进行归一化。所有运动的根位置、根旋转、DOF 位置、关键体位置被拼接为长张量,同时建立 motion_start_indices 索引表以支持 O(1) 的跨运动随机访问。速度与角速度不在离线阶段预计算,而是在加载时通过前向差分实时生成,公式为 vel_forward_diff(pos, dt) 与 ang_vel_from_quat_diff(quat, dt),确保时间导数与仿真步长严格一致。
AnimationTerm 负责将离散的运动数据转化为与策略频率对齐的连续演示信号。它维护 motion_fetch_time 缓冲,支持两种时间推进模式:当 random_fetch=True 时,每步从有效时间范围内均匀重采样,适用于需要强泛化的判别器训练;当 random_fetch=False 时,时间线性递增并在运动末尾根据 loop_mode 截断或回绕。num_steps_to_use 参数控制提取的时间步长度,正值表示提取当前与未来步,负值表示提取当前与历史步,直接对应判别器观测中的时序堆叠维度。
Sources: motion_data_manager.py, motion_data_manager.py, animation_manager.py
运动状态插值与坐标变换
训练过程中,策略步长(通常 20–50 Hz)与运动数据的原始帧率(通常 30–60 Hz)并不严格对齐,因此必须在查询时刻进行插值。MotionDataTerm.get_motion_state() 实现了完整的插值管线:首先通过 calc_motion_phase 将时间映射到运动的归一化相位,再映射为帧索引与混合系数,最后对各物理量分别执行插值。
根位置、速度、角速度、关节位置与关键体位置采用线性插值;根旋转四元数采用球面插值(quat_slerp)以避免万向节锁与范数漂移。插值完成后,系统立即执行坐标系转换:将世界坐标系下的速度与角速度通过 quat_apply_inverse 旋转到根坐标系(body frame),将关键体世界坐标转换为相对于根位置的局部坐标。这些 body-frame 量直接构成了 AMP 判别器的观测输入,确保判别器对全局位置平移具有不变性,仅关注运动学风格。
Sources: motion_data_manager.py
配置实战:运动权重与环境集成
在 atom01_amp_env_cfg.py 中,motion_data 与 animation 两个配置段将数据集与训练逻辑耦合。motion_data.motion_dataset 指定数据目录与每条运动的采样权重;animation.animation 指定提取哪些分量、时间窗长度以及采样策略。
以 ATOM01 的配置为例,运动库融合了 CMU 动作捕捉数据(行走转奔跑、奔跑)、ACCAD 数据(站立、转向、变向)以及 GVHMR 视频估计数据(平移、旋转)。所有运动的权重均设为 1,意味着判别器将均衡地接触不同风格来源。实际调优时,若发现某一类运动难以被策略复现,可提高其权重以增加采样概率;反之,若某运动噪声较大,可降低权重或从 motion_data_weights 中移除。
AMP_NUM_STEPS 定义为 3,意味着判别器观测同时包含当前步与未来两步的运动状态,形成 (num_envs, 3, obs_dim) 的张量。AnimationTerm 通过 num_steps_to_use=3 与 random_fetch=True 的配合,确保每一步都从运动中随机抽取起始时间,从而最大化数据多样性并降低过拟合风险。
Sources: atom01_amp_env_cfg.py, amp_env_cfg.py
常见陷阱与调试策略
| 现象 | 根因 | 排查方法 |
|---|---|---|
| 重定向后机器人姿态扭曲 | GMR 与 Lab 的 DOF 名称映射错误,或四元数格式未转换 | 在 single_retarget.py 中启用可视化,逐帧对比关节角 |
| 关键体位置全部为 0 | lab_key_body_names 与机器人模型中的刚体名称不匹配 |
检查 find_joints / body_names 输出与 yaml 配置 |
| AMP 判别器 loss 不下降 | 运动数据 fps 与仿真 dt 不匹配,导致速度与观测错位 |
核对 motion_data_dict['fps'] 与 sim.cfg.dt 的倒数 |
| 运动在结尾处抖动 | loop_mode 设置错误,wrap 模式用于非周期运动 |
行走类用 wrap,起卧类用 clamp |
| 批量转换时部分运动缺失 | 文件名不在 motion_data_weights 键中,或扩展名非 .pkl |
检查目录文件列表与配置键的一致性 |
在单文件调试阶段,建议始终使用 single_retarget.py 配合 GUI 观察重定向结果。该脚本会在仿真结束后保存转换数据,并在控制台输出帧数、循环模式与文件路径等元数据,是验证新运动数据的第一道关卡。
Sources: single_retarget.py, motion_data_term_cfg.py
延伸阅读与后续步骤
完成数据集准备后,运动数据将通过 AMP 对抗运动先验算法 中的判别器网络影响策略学习。若需调整运动观测在策略网络中的表示方式,可参考 Actor-Critic 网络架构详解 中关于观测编码器的设计。对于已经准备好的 Lab 数据集,下一步即是配置 AMP Runner 与模仿学习训练 启动完整的模仿学习管线。