← Back to project

X2 SONIC · embodiment audit: hardcode bugs, vendor-file conflicts, ruled-out hypotheses

4 torque typos fixed · 29/29 torque transcription certified · KP/KD = official SOP mimic profile · pelvis-mass resolved (MJCF artifact) - ALL closed · 2026-07-12
auditbugfixhumanoidsim2real

1 · TL;DR

Deep audit of our X2 stack vs official SONIC: after fixing 4 transcription bugs in x2.py torque limits, the codebase differs from official ONLY in the G1→X2-Ultra swap. No hidden physics or hyper-parameter deviations. All vendor-data questions RESOLVED: KP/KD = AgiBot official SOP mimic profile; the pelvis-mass conflict was a MuJoCo density-fallback artifact.

Trigger: policy videos showed laggy wrists and slow locomotion. We chased it through data (GMR), hardware limits, and configs — the trail ended at hand-transcribed constants and two AgiBot vendor-file inconsistencies, NOT at retargeting or embodiment ceilings as first assumed.

2 · Bugs found & fixed (x2.py hardcoded torque limits)

constantwasreal (URDF & MJCF agree)impact
EFF_WRIST_PR2.24.8wrist torque halved — the main wrist-lag culprit
EFF_HIP1181201.7%
EFF_KNEE1181201.7%
EFF_WAIST_YAW1181201.7%

x2.py's own comment says these were copied from the MJCF ctrlrange — they were mistyped. Both vendor files agree on the correct values, so the fixes are unambiguous. They take effect on the next training run (running arms loaded the old values at start).

3 · What was ruled OUT (each with hard evidence)

4 · Codebase diff vs official SONIC (exhaustive)

Recursive diff of gear_sonic/ and the full config tree:

layerresult
config/** (rewards, PPO, obs, terminations, events)byte-identical; only addition = sonic_x2.yaml
sonic_x2.yaml vs sonic_release.yamlrobot=x2, data paths, warm-start block, critic dims (= official default, no-op), removed upper_body_augment_prefixes (official-internal clip names)
14 changed shared .py filesX2 registration (4), dof_sign infra (no-op for G1), /dev/shm fix; the rest = upstream is newer than fork base (teleop tooling refactors, not on the training path)
rigid/articulation props vs g1.py12/12 identical (solver 8/4, self-collision, damping…)
action_scale formulasame as G1 (0.25·effort/stiffness)
Guarantee: with the fixes applied, our stack = official SONIC + (G1→X2 Ultra embodiment, X2-native corpus, warm-start source, encoder-routing choice). Nothing else.

5 · Open vendor questions (blocked on external ground truth)

#questionevidenceowner
1Pelvis mass — RESOLVED ✓The MJCF's 5.03 kg is NOT an authored value: pelvis is the only body in the vendor MJCF lacking an explicit inertial, so MuJoCo auto-computes it from collision-geom volume × default density. URDF's 3.52 kg is the only authored value (byte-identical in third-party ioai-tech/robot_description redistribution). Training uses URDF — correct all along; MJCF serves kinematics only.closed
2KP/KD provenance — RESOLVED ✓x2.py gains = AgiBot official SOP 'AgiBot X2 motion-control deployment SOP (vendor PDF)' §3.1 mimic profile verbatim (the profile AgiBot pre-tuned FOR motion-mimic deployment — exactly our use case). Cross-checked vs the AimDK SDK joint-control example: wrist 20/2 identical in both profiles (official choice, likely wrist-motor protection); legs stiffer in mimic (120/150) vs safe-demo (40/80) as expected. SDK example joint ranges match our Ultra URDF digit-for-digit → same robot variant confirmed.closed
3URDF velocity field (wrist 4.19 rad/s) inconsistent with torque; unused by trainingParked — zero impact on current runs.(later)

6 · Corrected understanding of the video observations

auto-generated · X2 SONIC · full evidence chain in fork docs/perm_alignment_verified.md + this audit