Skip to content

tracking_keybody_pos yaw-local frame: spurious keybody error at pitch ≈ 90° (Euler yaw artifact, not bad motion data) #52

Description

@gfyyly

Summary
We are training/evaluating on top of TWIST / TWIST2 (humanoid_mimic.py).
The default yaw-local keybody frame (quat(0,0,yaw) from euler_from_quaternion) can produce large spurious keybody tracking errors when reference root pitch is near ±90°, even when:

  • reference root_rot quaternions are smooth,
  • FK / world-frame keybody positions look correct,
  • the policy visually tracks reasonably well.

The same clip shows ~10× smaller keybody error when using the commented full-root-quaternion path (convert_to_local_root_body_pos(root_rot_full, ·)).

We would like to ask: Is this an accepted trade-off of the yaw-local design, or a known implementation limitation? Would you recommend root_local (full quat) for keybody reward/EA on bent / OMOMO-style clips?

Environment

  • Codebase: TWIST / TWIST2 lineage (legged_gym/envs/base/humanoid_mimic.py)

Default keybody reward (active lines):
base_yaw_quat = quat_from_euler_xyz(0self.yaw, 0self.yaw, self.yaw)
key_body_pos = convert_to_local_root_body_pos(base_yaw_quat, key_body_pos)
_, _, ref_yaw = euler_from_quaternion(self._ref_root_rot)
ref_yaw_quat = quat_from_euler_xyz(0ref_yaw, 0ref_yaw, ref_yaw)
tar_key_body_pos = convert_to_local_root_body_pos(ref_yaw_quat, tar_key_body_pos)

  • Alternative (commented in upstream):

key_body_pos = convert_to_local_root_body_pos(self.root_states[:, 3:7], key_body_pos)
tar_key_body_pos = convert_to_local_root_body_pos(self._ref_root_rot, tar_key_body_pos)

  • Note: _pose_termination in upstream already uses full quaternion (F_own), while reward/EA use yaw-only (Y).

Why we think this matters

  1. Reward bias: Clips with high pitch (common in OMOMO / bent manipulation) get inflated tracking_keybody_pos / error-aware sampling scores under Y, even when F_own error stays small.
  2. Inconsistent metrics: Rewarduse Y; _pose_termination uses F_own → play/debug can look fine (no reset) while reward think tracking is poor.
  3. Paper motivation vs implementation: TWIST correctly motivates local-frame tracking (vs world frame) for retarget/teleop drift . But yaw-only local via Euler extraction is not the same as full root-local (quat); the latter avoids gimbal lock at pitch ≈ 90°.

We did not find an existing TWIST/TWIST2 GitHub issue describing this specific yaw-local + Euler keybody artifact.

g1_sub10_smallbox_091.2026-08-12.16-21-17.webm

Thanks for the great open-source stack — wanted to check whether we should treat this as “by design” or worth upstream clarification/fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions