上一篇理论篇主要聊了 GMR 的方法逻辑关键体匹配、默认姿态对齐、非均匀局部缩放以及两阶段 IK。理论上看起来比较清楚但真正接入自己的机器人时重点并不是“能不能跑通脚本”而是如何配置出一套稳定、可复用、质量还不错的smplx_to_robot映射表。本文主要记录一次将自定义机器人接入 GMR 的实践流程和调试经验不深扒代码细节重点放在工程配置和一些实际踩坑点上。理论篇参考上一篇文章传送门GMR 项目主页https://jaraujo98.github.io/retargeting_matters/代码仓库https://github.com/YanjieZe/GMR一、第一次接入自定义机器人的基本流程第一次给自己的机器人做重定向大致流程如下1. 放入自己的机器人 URDF 2. 补齐需要参考的连杆点例如手、头、脚趾等 3. 将 URDF 转为 XML / MJCF 格式 4. 创建对应机器人的 ik_configs 配置文件 5. 在脚本加载项中注册机器人名称和模型路径 6. 根据机器人结构修改 ik_configs配置映射部位和比例 7. 在两张 IK match 表中配置映射关系、权重、位置偏移和旋转偏移 8. 选择几段代表性动作进行重定向 9. 观察动作质量和匹配误差 10. 根据结果调整权重、offset 和 scale这里最麻烦的是第一次配置。只要机器人配置稳定下来后续换新的动作数据时流程会简单很多基本就是放入动作、运行重定向、检查结果。整体上这也和论文中的流程是一致的1. 找到人体和机器人的对应部位 2. 调整默认姿态和方向 3. 调整缩放比例 4. 配置两阶段 IK 权重 5. 计算得到机器人动作二、URDF 不一定够需要补参考连杆GMR 的匹配对象是人体骨架 body 和机器人 link。所以有些机器人虽然模型能正常仿真但未必有足够适合重定向的参考 link。比较常见需要补的点包括head left_hand / right_hand left_toe / right_toe torso reference point这些点不一定需要自由度可以用 fixed joint 加到 URDF 里。它们的作用不是改变机器人运动能力而是提供更明确的空间参考。比如脚部如果只有 ankle没有 toe 或 foot 参考点那么脚掌方向的约束会比较弱。对于步行、转身、跑步这类动作脚掌方向其实非常关键。一个G1的参考点示意图三、核心配置smplx_to_robot映射表GMR 配置里最重要的是人体骨架到机器人 link 的映射表。以 G1 的一段配置为例left_knee_link:[left_knee,0,10,[0.0,0.0,0.0],[0.5,-0.5,-0.5,-0.5]],这一项从上到下分别是机器人连杆 人体骨架部位 位置权重 旋转权重 xyz 位置偏移 wxyz 四元数旋转偏移也就是字段含义left_knee_link机器人参与 IK 匹配的 linkleft_knee人体骨架中对应的 body0位置跟踪权重10旋转跟踪权重[0.0, 0.0, 0.0]位置偏移[0.5, -0.5, -0.5, -0.5]旋转偏移格式为 wxyz这个表基本决定了机器人最终会“相信”人体骨架中的哪些点以及相信到什么程度。四、权重为 0就是不跟踪在 IK match 表中权重非常直接。如果某个部位的位置权重和旋转权重都设为 0那么这个部位实际上就不会参与跟踪。比如把左手肘和左手腕权重都设为 0可以看到机器人左臂基本保持 URDF 默认姿态不会主动追踪人体动作。左手肘和左手腕权重设为 0 后的重定向效果这点在调试时很有用。不是所有人体关节都应该强行对齐尤其是机器人没有对应自由度或者 link 定义和人体差异较大时高权重反而容易制造问题。一个典型例子是 G1 的torso_link - spine3。即便两者空间位置相差比较大只要位置权重设为 0就不会对重定向结果产生强约束。所以配置映射表时不要只看有没有对应关系更要看权重是否合理。五、人体关节很多但不需要全都对齐可用的人体关节很多例如body_joint_names[Pelvis,Left_Hip,Right_Hip,Spine1,Left_Knee,Right_Knee,Spine2,Left_Ankle,Right_Ankle,Spine3,Left_Foot,Right_Foot,Neck,Left_Collar,Right_Collar,Head,Left_Shoulder,Right_Shoulder,Left_Elbow,Right_Elbow,Left_Wrist,Right_Wrist,Left_Hand,Right_Hand]但实际配置时不建议一股脑全部高权重对齐。约束太多容易过拟合表现出来可能是动作抖动 局部关节异常扭动 腿部或手臂姿态不自然 为了满足某个点导致整体姿态变形我的理解是映射选择应该优先考虑三个问题1. 机器人是否真的有这个部位 2. 这个部位对动作质量是否关键 3. 机器人是否有能力合理实现这个约束比如机器人没有头部自由度却高权重跟踪Head的方向可能会导致机器人通过扭腰或扭 torso 去代偿头部旋转结果反而很怪。脚部则相反通常值得重点关注。因为脚部不仅影响动作像不像还直接影响接触、落地和稳定性。例如实践中使用foot作为脚部主要参考点效果通常比只用ankle更好一些。原因大概是ankle更像一个点而foot更能表达脚掌方向。虽然 ankle 到 foot 之间可能没有额外自由度但 foot 的方向信息对步态很有帮助尤其是转身、跑步、落脚这类动作。也可以 foot 和 ankle 都用但权重不要太激进。脚部约束过强时腿部姿态也可能变僵。只使用 ankle、只使用 foot的效果对比六、四元数偏移本质是坐标系对齐四元数 offset 是调试中最容易困惑的部分。比如常见的[0.5,-0.5,-0.5,-0.5]它并不是经验玄学而是在做坐标系对齐。GMR 中四元数格式是wxyz这一点要特别注意。原始动作骨架的默认状态中关节四元数基本都是[1,0,0,0]但这只说明它在骨架自己的坐标系下没有旋转并不代表它和机器人 link 的局部坐标系一致。观察原始骨架可以看到它可能是面朝上躺平的大字形态且轴系大致表现为z 轴朝身体前方 y 轴垂直身体 x 轴朝身体侧方[1, 0, 0, 0]应用[0.5, -0.5, -0.5, -0.5]后可以看到原本朝前的 z 轴被旋到 x 轴方向原本朝左的 x 轴被旋到 y 轴方向这样更接近常见机器人模型的 link 坐标定义。这里最重要的原则是四元数 offset 不是为了让某一帧动作看起来顺眼而是为了在默认姿态下对齐机器人 link 的局部坐标系。虽然[0.5, -0.5, -0.5, -0.5]在很多位置上有效但不是所有 link 都适用。比如 G1 的 hip 部位使用的是right_hip_roll_link它的局部轴系并不和 torso 保持一致所以需要单独配置right_hip_roll_link:[right_hip,0,10,[0.0,0.0,0.0],[0.4267755048530407,-0.5637931078484661,-0.5637931078484661,-0.4267755048530407]],hip 使用特殊offset 后的效果:可以发现这套偏移是更符合机器人的坐标系设定的这说明 offset 要看机器人 link 自己的坐标系而不是无脑都套用同一套偏移。手臂也类似。人体骨架通常是大字型姿态而机器人默认一般是垂手姿态G1 的手肘还带有一定弯曲。因此肩部配置会使用类似left_shoulder_yaw_link:[left_shoulder,0,10,[0.0,0.0,0.0],[0.70710678,0.0,-0.70710678,0.0]],在这个配置下如果把机器人 shoulder roll 调到 90°让手臂打直会发现这个偏移量和机器人坐标系是匹配的包括后续的小臂和手部也同理。不过这里还有一个我暂时没有完全确认的问题目前这种“手动旋转机器人后再观察匹配”的方式更像是一个工程辅助验证方法而不一定是严格的代码设计逻辑。仓库中并没有明确说明需要先旋转机器人再匹配因此这里还需要继续研究坐标变换的真实顺序。七、xyz offset 和 scale直观但最费时间相比四元数xyz offset 和 scale 更直观但更依赖具体机器人和动作数据。影响因素包括人体骨架身高和比例 机器人腿长、臂长、躯干比例 机器人 link 原点定义 foot / ankle / toe 的选择 不同动作库的骨架差异 root 缩放比例目前比较有效的方法还是构建可视化脚本反复观察原始人体骨架 偏移后的目标骨架 机器人 FK 后的实际 link 关键点位置误差 关键点旋转误差对于一些怎么都对不齐的点不建议死磕。可以降低位置权重保留旋转约束或者干脆弱化这个部位。本质上GMR 不是要让每个点都完美贴合而是要让关键部位合理贴合。原始动作骨架、未偏移结果、偏移后结果但骨架保留原始效果以便表达区别三图对比八、两阶段 IK表一粗对齐表二细对齐GMR 中通常会有两张 IK match 表对应两阶段 IK。第一阶段主要是粗对齐。重点是root / pelvis 方向位置合理 torso 方向合理 双足位置合理 主要 end-effector 大致到位 其他关节旋转方向不要太离谱第一阶段的目标不是精修动作而是得到一个比较稳定的初始姿态。如果第一阶段已经跑偏第二阶段很容易在错误姿态附近继续优化。第二阶段是细对齐。一般会加入更多 key body并适当提高部分旋转或位置约束让动作更贴近源动作。可以简单理解为表一先把机器人摆对 表二再把动作修细所以两张表不要配置成完全一样。表一应该抓重点表二可以更细但也不能过度激进。否则动作细节可能更像了但抖动、自碰撞和关节突变也更容易出现。其他补充不同数据格式骨架左边是smplx右边是bvh数据细节来看不经映射的位置要调整并且坐标轴也是需要彻底重新调整。个人调试经验整理一些目前比较有用的经验1. foot 通常比 ankle 更适合作为脚部主约束foot 对脚掌方向更敏感步行和转身效果会更好。ankle 可以辅助但单独用 ankle 时脚掌方向约束偏弱。2. 没有自由度的部位权重要低比如没有头部自由度就不要高权重跟踪Head的方向。否则机器人可能通过 torso 或腰部去代偿动作会变得很奇怪。3. 不同动作库可能需要不同 scale 或 offset不同动作库的骨架定义、身高比例、坐标系和帧率都可能不同。不要默认一套参数可以适配所有来源的数据。4. 不要只用一个动作验证配置一个动作调得很好不代表配置稳定。建议在同一个动作库/作者下至少准备几类动作普通步行 转身 跑步 上肢动作 大幅度动态动作多动作都能接受配置才比较可信。十、几个待研究问题目前还有一些问题没有完全搞清楚后续值得继续看。1. 权重和 scale 的影响能否量化现在调参主要依赖观察和枚举成本比较高。后面可以考虑引入一些自动指标key body position error rotation error foot sliding ground penetration self-intersection joint velocity spike如果这些指标能自动统计调参效率会高很多。2. 其他动作格式效果如何目前主要关注现有仓库主力支持的smplx格式数据。对于遥操数据、视频恢复动作、其他 mocap 格式还需要单独测试。3. 动作频率对训练效果有什么影响GMR 脚本里写死了 30 fps而宇树官方动作数据可能是 50 Hzbymimic仓库里则是区分了高频低频的训练环境。这里需要继续确认retarget 后是否需要插值 频率变化如何影响 tracking 效果这个问题对后续训练很关键。4. 是否需要为每个动作库单独配置 scale不同动作库录制者体型、骨架标准可能不同。理论上可能需要不同 scale但也可能动作数据内部已经做了统一标准化。这个需要更多动作源验证。5. table2 里的rot_offset是否真的生效代码分析时发现第二阶段表里的rot_offset似乎没有被实际套用。这里还不能确定是论文设计如此还是代码实现遗漏。十一、SMPL-X 到机器人动作重定向工程流程最后我们再快速过一下重定向过程中都干了什么。输入数据输入是一个 SMPL-X 动作.npz文件通常来自 AMASS/OMOMO 等数据集。脚本主要使用其中的pose_body: 每帧身体关节轴角姿态形状通常为(N, 63)。root_orient: 每帧根节点全局朝向形状为(N, 3)。trans: 每帧根节点全局平移形状为(N, 3)。betas: 人体形状参数。gender: SMPL-X body model 性别选择。mocap_frame_rate: 原始动作帧率。这些参数本身还不是“骨架点位序列”而是 SMPL-X 参数化人体模型的输入。SMPL-X 前向计算load_smplx_file()会根据输入文件中的gender和betas创建 SMPL-X body model并把root_orient、pose_body、trans输入模型得到每一帧的人体关节位置和完整姿态。之后get_smplx_data_offline_fast()将 SMPL-X 输出整理成重定向系统使用的格式{pelvis:(position,quaternion),left_hip:(position,quaternion),left_knee:(position,quaternion),...}其中四元数格式为[w, x, y, z]。这个阶段也会根据目标帧率进行时间对齐或重采样并返回实际使用的aligned_fps。逐帧重定向脚本逐帧取出 SMPL-X 处理后的人体数据smplx_datasmplx_data_frames[i]qposretarget.retarget(smplx_data)retarget()内部主要做几件事将人体骨架按目标机器人尺度进行缩放。对人体匹配点应用位置偏移和旋转偏移。将处理后的人体点位和朝向设置为 IK 任务目标。使用mink.solve_ik()求解机器人当前帧的qpos。返回的qpos是 MuJoCo 机器人状态通常包含qpos[:3]: 机器人根节点位置。qpos[3:7]: 机器人根节点四元数格式为[w, x, y, z]。qpos[7:]: 机器人各关节角度。输出数据最后脚本会把所有帧的机器人动作保存为.pkl。输出结构如下{fps:aligned_fps,root_pos:root_pos,root_rot:root_rot,dof_pos:dof_pos,local_body_pos:None,link_body_list:None,}其中root_pos:(T, 3)机器人根节点位置。root_rot:(T, 4)机器人根节点四元数。保存时会从 MuJoCo 的[w, x, y, z]转为[x, y, z, w]。dof_pos:(T, robot_dof)机器人关节位置序列。fps: 动作播放帧率。这里的dof_pos是关节角单位为 rad。以 G1 29DoF 为例dof_pos的形状是(T, 29)每一帧包含 29 个关节角列顺序由机器人 XML 中的 joint 顺序决定。这个.pkl就是后续播放、训练或进一步转换的机器人动作数据。技术要点SMPL-X 负责从参数化人体动作恢复人体关节位置和朝向。MuJoCo 提供目标机器人运动学模型。mink将人体目标点和机器人 link 之间的匹配关系转化为 IK 优化问题。IK 配置负责定义人体部位到机器人 link 的映射、权重、缩放和坐标系校准。输出结果不是力控或轨迹控制命令而是逐帧机器人运动学状态。整体流程可以概括为SMPL-X .npz - SMPL-X body model 前向计算 - 人体关节位置/姿态序列 - 缩放与坐标系校准 - 机器人 IK 求解 - 机器人 root joint motion - .pkl 动作文件总结把自己的机器人接入 GMR核心工作不是跑脚本而是配置好smplx_to_robot映射表。这张表里最重要的是映射哪个机器人 link 参考哪个人体 body 位置权重是多少 旋转权重是多少 xyz offset 如何设置 quaternion offset 如何设置其中映射关系决定机器人“看哪里”权重决定机器人“有多在意”offset 和 scale 决定人体动作目标是否真的适合当前机器人。我的整体感受是GMR 的工程配置本质上是在做一次折中既不能让机器人完全无视人体动作也不能让它死追所有人体关节。比较好的结果通常来自合理取舍关键部位强约束非关键部位弱约束可实现的部位认真跟踪不可实现的部位适当放过。当这套配置稳定之后GMR 就会变成一个比较实用的动作数据生产工具。对于后续 motion tracking、模仿学习或者遥操作数据处理来说前面这一步调得越稳后面的训练就越省心。