Robot Everest
2026
Work
Sherpa is a AgiBot A3 trained for the terrain it will encounter on the South Col route. This is the validation harness built to find out whether that training actually holds up.
- 68/68
- 4.0 m/s
- 204.8M
The problem
A locomotion policy that works well in the simulator it was trained in doesn’t mean much on its own. PhysX can make a gait look great simply because the robot has learned to work around the quirks of the simulation. The reward goes up, the robot walks, and everything looks fine- until you take it somewhere the simulator didn’t expect. This helps us determine whether it actually learned to walk, or just learned to cheat the simulator.
Alpine terrain makes this even harder because its challenges don't hit the robot individually; instead, steep slopes, loose footing, uneven ground, and wind can all hit the robot at once. A policy might handle each of them on its own and still completely fail when they’re combined.
Approach
Choosing the Right Foundation
Before training anything, six potential training stacks were evaluated across ten weighted criteria. Disturbance robustness and rough-terrain performance each made up 20% of the score, followed by portability to the A3 at 15%, and sim-to-real design and pretrained weights at 10% each. Holosoma with FastSAC came out on top with a 4.35/5, largely because rough terrain, pushes, and heavy randomization are built into the training loop from the start.
Cross-embodiment policies were ruled out because there was no public code or pretrained weights to build on (as the AgiBot A3 has not been released to the public at the time of writing). Checkpoint reuse was also rejected because locomotion policies are often closely tied to the physical body they were trained on—the robot’s proportions, joint layout, mass distribution, and actuator limits. A policy trained for one robot may therefore not transfer cleanly to another with a different morphology.
Pin the robot down exactly
The A3 Ultra has 31 powered joints: 12 in the legs, 3 in the waist, 14 in the arms, and 2 in the head, with a total weight of 60.18 kg. For our locomotion system, the head is fixed, and the walking policy only controls the 12 leg joints using proprioceptive information from the robot itself. Most importantly, the A3 uses a joint naming scheme compatible with the Unitree G1, which makes it possible to adapt existing G1 configurations in Holosoma rather than building the control setup from scratch.
Every value lives in one manifest, with official values separated from our assumptions. This prevents an assumed value from quietly becoming “fact.” In the rollout above, the arm joints move less than two degrees, since the policy is focused on locomotion and treats arm movement as a disturbance. The lower body is responsible for maintaining stability when the arms move.
Verify the Robot Across Both Assets
Isaac Sim uses the URDF and MuJoCo uses the MJCF, so both models need to match. A parity test catches differences between them, and another test prevents us from assuming their joints are stored in the same order.
Both tests prevent a harder problem: getting different results between simulators and not knowing whether the cause is the policy or a mismatch between the robot models.
Train Against Real-World Variation
Isaac’s default G1 setup turns off most of the randomization we actually care about. There are no pushes, no meaningful changes to mass or center of mass, reset velocities are zero, and friction is basically fixed. The only real variation left is observation noise. We replace those defaults with our own randomization and then check what PhysX actually applied.
Three issues showed up. The USD has zero joint friction, so scaling it does nothing. Joint reset positions also have to use offsets instead of scaling because 17 joints start at exactly 0.0. Finally, our randomization has to be added after Isaac’s post-init setup; otherwise, the default setup wipes out the two most important settings.
Test in a Different Physics Engine
The validation gate runs in MuJoCo 3.11.0, a completely separate physics engine from the one used for training. It uses a different solver and integrator, so the policy has to work without relying on the quirks of its training simulator. The trained policy passed all 68 stability tests, compared with 26/68 for a basic PD-stand controller on the same tests, with no additional tuning.
The MuJoCo side uses the same 100-value observation vector, in the same order, at 50 Hz. This prevents observation mismatches from being mistaken for physics differences.
Learn From the Failures
The alpine scenario passes 0/3, even though each stressor passes on its own. That points to a problem with how the stressors interact, not with any single terrain condition. We also see 3–6°/s of yaw drift under a zero-yaw command. I added a head to the policy that corrects the yaw drift and improves true linear velocity tracking. Most importantly, masking the arm observations makes all 28 arm-motion tests pass without retraining. That means the policy itself can handle the arm motion; the failure comes from the arm data interfering with the walking controller.
The get-up policy plateaued at around 30%, roughly matching the 30% of poses in the dataset where the robot starts on its back. That showed us one policy wasn’t enough to handle all the different ways the robot could fall, so we split the problem into separate tracks instead of trying to tune one policy to do everything.
What I built
- Ran the weighted baseline study that selected the training stack and documented why each alternative was rejected.
- Rebuilt the domain randomization that the upstream setup had turned off, then added a validation gate to check what PhysX actually applied.
- Built the sim-to-sim harness in an entirely separate physics engine, without sharing code with the trainer.
- Found a reward bug that let the robot earn full turning reward by spinning in place. Fixed it by making the reward check all three movement commands, not just forward motion.
- Wrote the failure analysis, including the arm-motion issue, the yaw-drift fix and velocity-tracking head, and the get-up results that led us to split the training tracks.
- Ported the stack to the Unitree G1 after the A3 Ultra work was complete. All results shown here are from the A3 Ultra; the G1 has not been tested yet.
Results
- Sim2sim scenarios
- 68/68
- Push, standing
- 3.0 m/s
- Push, walking
- 4.0 m/s
- Slope
- 6/6
- Flat tracking error
- 0.126 m/s
- Training
- 204.8M samples
- Control rate
- 50 Hz
- Alpine
- 0/3
Stack
Lead Engineer at RobotEverest.