Skip to content

feat: G1 backflip whole-body tracking task under FastSAC - #77

Open
wlgys8 wants to merge 9 commits into
mainfrom
feat/g1-wbt-backflip
Open

wlgys8 wants to merge 9 commits into
mainfrom
feat/g1-wbt-backflip

Conversation

@wlgys8

@wlgys8 wlgys8 commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add manager-based G1 backflip whole-body motion tracking task (g1-wbt-backflip) trained with Motrix FastSAC
  • Include task env/cfg registration, task recipe, flip motion converter script (scripts/private/g1_flip_converter.py), design notes (wiki/design/g1-backflip-flight-metrics.md), and dependency updates

Training evidence

  • 60k-iteration training run on RTX 5090 (2048 envs, ~30 min, ~33 it/s), final rollout mean return ≈ 95

Play recording (best policy, 16 envs)

backflip play

Reward vs walltime

reward curve

Adds the g1-wbt-backflip WBT task: Unitree G1 tracks a full backflip
reference clip (converted from the mjbatch flip motion with FK cross-check)
and learns the complete skill — takeoff, full rotation, landing, and stable
hold — under motrix.fastsac.

Validated recipe (each element from controlled comparisons):

- mixed reset sampling: 20% frame-0 starts + 80% uniform whole-clip RSI
  (teleports exact in velocity: root velocity reset noise zeroed for this
  task; centered reset noise everywhere else). Frame-0-only start starves
  the flight window of episode-start coverage; adaptive sampling is
  strictly harmful in BOTH regimes — the uniform_ratio sweep (0.1/0.5/0.8)
  lost to plain uniform from scratch at every value (40k rotation 0.08/
  0.15/0.06 rad vs 0.48) and fine-tuning the flipping 80k policy with
  adaptive sampling regressed the play-visible skill
- sim dt 0.005 required: dt=0.01 doubles collector throughput but the
  ~0.1 s launch impulse is lost to the coarse contact solve and rotation
  never forms
- motion_global_body_ang_vel at the UniLab sigma (3.14); earlier
  tightening to 1.0 saturated the kernel to ~0.02 across whole runs
- flight-window rewards projected onto the clip's flight axis: linear
  flight_rotation_progress (unsaturating, pays per radian) plus
  FlightTuckRewardCfg over all eight leg joints including hip roll/yaw
  abduction (sigma 1.0, weight 4.0 — open-leg flight inflated the moment
  of inertia and stalled rotation at ~3 rad; extended coverage reached a
  3.8 rad peak at 60k, 2.2x faster than the knee/hip-pitch-only variant)
  and a full-3D EE term (weight 3.0, replacing the z-only variant:
  ablating z-only alone stalls launch bootstrap ~20k iters because the 3D
  error is dominated by early xy drift — the raised 3D weight keeps the
  height emphasis); action_rate_l2 flat -0.01 (sweep: every heavier flat
  or gated variant failed to unlock rotation)
- phased terminations: anchor z loose outside the flight window / tight
  inside (0.5/0.25, closes the tiptoe exploit at the apex), phased 3D
  anchor position (0.8/1.0); holosoma-contract strict terms available as
  metrics-only thresholds for later fine-tuning

Clip-data and metric fixes (the breakthrough changes):

- g1_flip_converter: MotrixSim free-joint qvel takes world-frame LINEAR
  but BODY-frame ANGULAR velocity (MuJoCo convention); feeding
  world-frame omega corrupted every baked body_ang_vel_w as R @ omega
  while positions stayed correct (positions were the only cross-check).
  Fixed, plus a new FK velocity self-check guards the convention;
  backflip.npz re-baked (flight-window x-axis integral now ~ -2pi)
- flight_axis: the flip rotation axis is derived from the reference
  window angular-velocity integral (signed, world frame);
  flight_pitch_rotation and flight_rotation_progress project onto it
  instead of a hardcoded world-y index — the robot faces -/+y in this
  clip, so world y was measuring the roll component. A perfect flip now
  reads ~2pi on the metric

Honest-skill metrics in WbtMotionCommand (flight window derived from the
clip root-z profile): flight_max_pelvis_z, flight_pitch_rotation
(rotation about flight_axis), landed_upright. Known dilution caveats and
the conditional-metric redesign are recorded in
wiki/design/g1-backflip-flight-metrics.md.

Also: pytest-xdist in the dev group (25 WBT tests: 5-8 min -> 2 s warm).
…blation plan

A1 ablation (40k): rotation/height identical to phased baseline, landed_upright
0.65 vs 0.18. Details in wiki/plan/g1-backflip-ablation.md.
@wlgys8 wlgys8 self-assigned this Sep 25, 2026
A3 ablation (40k): flight_tuck showed no measurable effect on rotation or
height vs A1, play skill intact. Remove the term, its kernel, and the
unreliable fixed-frame landed_upright metric (see
wiki/design/g1-backflip-flight-metrics.md); record results in the
ablation plan.
40k ablation showed no measurable effect vs zeroed noise; restore default
holosoma reset noise and remove the task-specific __post_init__ hack.
Weight-0 leftover with no effect (A6a); delete the cfg, kernel, and stale
comments. Record A6a outcome (term kept, landing accuracy regression) in
the ablation plan.
Episode-mean rotation is not interpretable under mixed/RSI sampling and is
manipulated by start distribution (uniform vs adaptive gave the same policy
a 3.7x different mean). Keep flight_max_pelvis_z and the flight_axis needed
by the rotation-progress reward; see
wiki/design/g1-backflip-flight-metrics.md for the binary success-rate
replacement design.
…ation)

Re-ablated on the current recipe (no flight_tuck): removal showed no
regression in height, tracking error, episode length, or play behavior.
Delete the term, kernel, and now-unused flight_axis plumbing. Document the
flat ang-vel kernel finding (A9 candidate).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant