代码参考https://github.com/Roboparty/roboto_origin
部署代码的atom01.yaml存在以下配置:
bash
gmr_dof_names:
- left_thigh_yaw_joint
- left_thigh_roll_joint
- left_thigh_pitch_joint
- left_knee_joint
- left_ankle_pitch_joint
- left_ankle_roll_joint
- right_thigh_yaw_joint
- right_thigh_roll_joint
- right_thigh_pitch_joint
- right_knee_joint
- right_ankle_pitch_joint
- right_ankle_roll_joint
- torso_joint
- left_arm_pitch_joint
- left_arm_roll_joint
- left_arm_yaw_joint
- left_elbow_pitch_joint
- left_elbow_yaw_joint
- right_arm_pitch_joint
- right_arm_roll_joint
- right_arm_yaw_joint
- right_elbow_pitch_joint
- right_elbow_yaw_joint
lab_dof_names:
- left_thigh_yaw_joint
- right_thigh_yaw_joint
- torso_joint
- left_thigh_roll_joint
- right_thigh_roll_joint
- left_arm_pitch_joint
- right_arm_pitch_joint
- left_thigh_pitch_joint
- right_thigh_pitch_joint
- left_arm_roll_joint
- right_arm_roll_joint
- left_knee_joint
- right_knee_joint
- left_arm_yaw_joint
- right_arm_yaw_joint
- left_ankle_pitch_joint
- right_ankle_pitch_joint
- left_elbow_pitch_joint
- right_elbow_pitch_joint
- left_ankle_roll_joint
- right_ankle_roll_joint
- left_elbow_yaw_joint
- right_elbow_yaw_joint
# Names of the key bodies that will be used in further processing
# Must match the names in the lab robot model
# Order matters and should align with that used in observation
lab_key_body_names:
- left_ankle_roll_link
- right_ankle_roll_link
- left_elbow_yaw_link
- right_elbow_yaw_link
- left_arm_roll_link
- right_arm_roll_link
为什么存在
gmr_dof_names:原始数据关节顺序lab_dof_names:IsaacLab 内部顺序(训练实际使用)
结论是:
gmr_dof_names:数据集侧(GMR/MuJoCo)输出向量的原始列顺序lab_dof_names:Isaac Lab 侧机器人 articulation 的 DOF 顺序(训练实际消费的顺序)
两者不是谁对谁错,而是来自两个系统的"默认索引约定"不同。
gmr_to_lab.py 里明确按 lab_dof_names 去 gmr_dof_names 里查索引,然后重排 dof_pos:
python
# Get the mapping indices from GMR to Legged Lab
gmr_to_lab_indices = []
for lab_dof in lab_dof_names:
if lab_dof in gmr_dof_names:
gmr_index = gmr_dof_names.index(lab_dof)
gmr_to_lab_indices.append(gmr_index)
dof_pos_lab = dof_pos[:, gmr_to_lab_indices]
也就是:输出顺序永远对齐 lab_dof_names,输入顺序按 gmr_dof_names 解释。
这正是你 atom01.yaml 的作用:
为什么会不一样?和 DFS/BFS 有什么关系?
你提到"DFS/BFS 读取图纸"这个理解方向是对的,官方给的是 BFS:
- Isaac Lab 维护者在官方讨论里明确说:
关节/刚体顺序遵循 PhysX stage parser,对 articulation tree 做 breadth-first parsing(广度优先),不是按你自定义列表、也不是字母序。
官方说明链接:
再结合官方代码接口语义:
joint_names是 "parsed by the simulation view" 的顺序(即引擎解析顺序)Articulation.joint_names底层来自root_physx_view.shared_metatype.dof_names
所以可以理解为:
- GMR/MuJoCo:按它自己的关节构造顺序导出(常是模型作者定义顺序)
- Isaac Lab/PhysX:按 articulation tree 的解析顺序(官方说明是 BFS)
- 两边顺序不必一致,于是就需要
gmr_dof_names -> lab_dof_names映射重排
从 atom01.urdf 把关节的父子链接关系和出现顺序提出来,对照你这段 lab_dof_names,给你说明它为什么是这个顺序。
就是因为 lab_dof_names 不是按 URDF 文件"写出来的先后顺序",而是按 URDF 关节树在仿真器里的层级遍历顺序(BFS) 来的。
你看 atom01.urdf 的父子关系就能对上:
base_link的一层子关节有 3 个:
left_thigh_yaw_joint、right_thigh_yaw_joint、torso_joint- 再下一层分别是:
- 从左右大腿 yaw 往下:
left/right_thigh_roll_joint - 从 torso 往下:
left/right_arm_pitch_joint
- 从左右大腿 yaw 往下:
- 再下一层:
- 腿:
left/right_thigh_pitch_joint - 手臂:
left/right_arm_roll_joint
- 腿:
- 再下一层:
- 腿:
left/right_knee_joint - 手臂:
left/right_arm_yaw_joint
- 腿:
- 再下一层:
- 腿:
left/right_ankle_pitch_joint - 手臂:
left/right_elbow_pitch_joint
- 腿:
- 再下一层:
- 腿:
left/right_ankle_roll_joint - 手臂:
left/right_elbow_yaw_joint
- 腿:
这和你 atom01.yaml 里的 lab_dof_names(27-49 行)一一对应,顺序完全一致。
对比一下:
gmr_dof_names更像"按身体部位连续列出"(左腿一串 -> 右腿一串 -> 躯干 -> 左臂一串 -> 右臂一串)lab_dof_names是"按树的层级展开"(同一深度的关节先排完,再到下一层),所以会出现你看到的左右腿和双臂交替出现。