OpenTrack trains humanoid motion trackers in MuJoCo JAX
Official implementation of Any2Track.
At a glance
- What is it?
- OpenTrack is the official implementation of Any2Track, a humanoid motion tracking codebase from GALBOT and Tsinghua that simulates in MuJoCo JAX and supports multi-GPU parallel training. The interesting engineering is the teacher-student pipeline: specialist trackers are trained per motion cluster, then distilled with DAgger into a single generalist policy that follows any of 40 reference motions.
- Who is it for?
- Adopt OpenTrack if you are working on humanoid whole-body control and want a tracker that follows arbitrary reference motion rather than a fixed set of scripted behaviours, since the released LAFAN1 generalist v2 policy tracks all 40 motions in that set.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 141 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A tracking codebase built around a generalist student
OpenTrack is the official implementation of Any2Track, an open-source humanoid motion tracking codebase from GALBOT and Tsinghua. It uses MuJoCo JAX for simulation and supports multi-GPU parallel training.
The core idea is a teacher-student split, and the release history shows it being built in pieces. The tracking codebase and simple domain randomization came in September 2025. LAFAN1 generalist v1 arrived in November 2025, described as a single policy that can track cartwheel, kungfu, fall and getup and many other motions. DAgger training code came in April 2026, to distil teacher trackers into a generalist student tracker. AnyAdapter training code followed on 23 May 2026, letting you finetune the base tracker to endow it with dynamics adaptivity. Real-world deployment code was released on 28 May 2026.
The TODO checklist at the top of the documentation marks all six of those as done, which is a useful signal that the project intends to be a complete pipeline rather than a partial release.
The generalist result is the headline. Generalist v1 was daggered from four teachers and can track most motions, but it fails on some extremely challenging ones, mainly because some teachers fail to track those motions. Generalist v2 was daggered from eight more carefully designed teachers, where each teacher policy successfully tracks all motions in its motion cluster, and the student policy inherits the capabilities of the different teachers and tracked all 40 out of 40 motions in LAFAN1.
The last push was on 2026-06-04 and there are no GitHub releases, so the checkpoints and code are distributed through the repository and linked drives rather than through a release feed.
The setup is a virtualenv, a .env file and a populated storage tree
Preparation is five steps, and two of them are about layout rather than software.
First, clone the repository:
git clone [email protected]:GalaxyGeneralRobotics/OpenTrack.gitThen create a virtual environment and install the dependencies:
uv sync -i https://pypi.org/simple Third, create a `.env` file in the project directory with the environment variables the training runs need:
export GLI_PATH=<your_project_path>
export WANDB_PROJECT=<your_project_name>
export WANDB_ENTITY=<your_wandb_entity>
export WANDB_API_KEY=<your_wandb_api_key>The W&B variables are the important detail. Experiment tracking is part of the workflow, not an optional extra, and you need a project, an entity and an API key before training will run.
Fourth, download the mocap data and put it under `storage/data/mocap/`. The documentation credits the retargeted LAFAN1 motions to the LocoMuJoCo project. The expected directory layout is spelled out, with storage/ holding assets, data, logs, training_configs and more. Under data you get a hfield with terrain.npz and a mocap directory containing lafan1/UnitreeG1. Under logs there are two subdirectories, dagger for student checkpoints and track for tracking checkpoints. Under training_configs there is a dagger directory with a demo.json.
Fifth, initialize the assets, which requires activating the environment and sourcing the .env first:
# First, initialize the environment
source .venv/bin/activate; source .env;
# Then, initialize the assets
python track_mj/app/mj_playground_init.pyPlaying a pretrained checkpoint is the shortest path in
If you want to see the system work before training anything, the evaluation path is the one to take.
Download the pretrained checkpoints and configs from the linked checkpoints and configs drive folder and put them under `storage/logs/dagger/`. The same folder holds the visualization videos for LAFAN1 generalist v2.
Then run the evaluation script:
python -m track_mj.eval.dagger.mj_onnx_video --task G1TrackingGeneral --exp_name <your_exp_name> [--use_viewer] [--use_renderer] [--play_ref_motion]The task name G1TrackingGeneral tells you the robot is the Unitree G1, and the module path shows the export route: the evaluation runs an ONNX model, which is why the dependency list carries tf2onnx, tensorflow, onnxruntime, onnxruntime-gpu and onnxscript.
The optional flags are the interesting part for anyone wanting to understand the behaviour. `--use_viewer` opens the interactive viewer, `--use_renderer` turns on video rendering, and `--play_ref_motion` plays the reference motion alongside the tracked result so you can compare the policy against the target.
The checkpoints are trained with simple domain randomization, and the documentation says you may try deploying one on a Unitree G1 robot with the deployment code, which is the step the May 2026 release added.
One caveat worth stating: the checkpoints and configs live in a Google Drive folder rather than in the repository, so a version mismatch between the checkpoint and the code is a real possibility when the codebase moves. The `storage/logs/dagger/` path from the directory listing tells you where the code expects to find them.
Preprocessing rewrites your motion files, so keep a copy
If you want to train on your own motion data rather than LAFAN1, the documentation requires a preprocessing step first, and it comes with a warning: the preprocess script will overwrite the original motion files.
You put the `.npz` files under `storage/data/mocap/<your_dataset_name>/UnitreeG1` and then run the preprocess script, which does two things. It aligns the frequency of the original motion data to the desired control frequency, 50Hz by default, and then recalculates velocities, angular and linear and joint, and other state features based on the aligned frequency.
The script supports splitting work across GPUs:
# Use `num_batches` to split data into multiple batches for parallel processing on multiple GPUs. You should manually launch multiple processes on different GPUs for parallel processing.
python scripts/process_motion/preprocess_motion.py --task G1TrackingGeneral --num_batches XXX --smooth_start_end False
# Or run on a single GPU without parallelism
python scripts/process_motion/preprocess_motion.py --task G1TrackingGeneral --num_batches 1 --smooth_start_end FalseNote the second command, which is the single GPU path with `--num_batches 1`.
The `--smooth_start_end True` option generates a natural transition motion from the default pose before the original motion. The mechanism is an inverse-kinematics solver that produces a smooth stepping motion from the default pose to the first motion frame, using QP optimization with OSQP, with foot position and orientation constraints and CoM balance constraints. One or two foot steps are chosen automatically based on the foot-placement gap between the default pose and the pose of the first frame.
The comparison between the original and the smoothed motion is shown side by side in the documentation, which is worth looking at if you enable it, because a stepping transition that is badly timed will show up as a visible artefact at the start of every episode.
Training runs in two stages, teachers first and then the student
The training path mirrors the teacher-student structure of the method itself.
You start with the specialist teachers, one per motion cluster:
python -m track_mj.learning.train.train_ppo_track --task G1TrackingGeneralDR --exp_name <your_exp_name>The DR in the task name refers to domain randomization, and the task name points at a config file you are expected to edit if you want to change the training setup. The documentation gives the location: the `g1_tracking_general_dr_task_config` in the `OpenTrack/track_mj/envs/g1_tracking/train/g1_env_tracking_general_dr.py`.
The generalist student comes second, and it takes a config path pointing at the DAgger setup:
python -m track_mj.learning.train.train_dagger --task G1TrackingGeneralDR --exp_name <your_exp_name> --dagger-config-path <your_config_path>The DAgger config is what defines which teachers the student learns from, which is how the eight-teacher generalist v2 differs from the four-teacher v1.
The configuration system is Hydra, with hydra-core in the dependencies, and the file layout separates environments, learning and evaluation into distinct modules under track_mj/: track_mj/learning/train/, track_mj/eval/dagger/ and track_mj/envs/.
For anyone reading the paper alongside the code, the arXiv entry at 2509.13833 is linked at the top, along with the Any2Track project website.
The dependency set is where the real constraints live
The pyproject file pins the environment tightly enough to be worth reading before you start.
`requires-python` is `==3.12.9`, an exact pin rather than a lower bound, so a mismatched interpreter will not install. The package is `track_mj` at version 0.1.0, built with setuptools.
The simulation and training stack is JAX-based: jax at 0.4.38 with jax[cuda12] at the same version, plus jaxlie, jaxopt at 0.8.5 and flax at 0.10.4. On top of that sit brax at 0.12.3, playground at 0.0.4 and mujoco at 3.3.1, which is the MuJoCo JAX environment the project is built around.
Two parallel model runtimes are installed, and that is worth understanding. PyTorch at 2.9.0 with torchvision at 0.24.0 is there for the ONNX export path, and TensorFlow at 2.19.0 with tf2onnx converts the trained policies to ONNX for the evaluation script and the deployment code. onnxruntime and onnxruntime-gpu at 1.23.2 run the exported model.
The rest of the list covers the surrounding work: OSQP at 1.0.5 for the inverse-kinematics solver, hydra-core for configuration, wandb and swanlab for experiment tracking, evdev for input device access which matters for the real-world deployment, mediapy and imageio-ffmpeg for video output, gradio for an interface, and trimesh and huggingface-hub for assets.
The linting setup is minimal, with ruff at line length 120 targeting py312 and only the pyflakes rules selected, ignoring F401 so unused imports do not fail the check, and black at 25.9.0 also in the dependencies.
The last thing worth noting is the repository layout. There is a deploy/ directory for the real-world deployment code released in May 2026, scripts/ for the motion preprocessing, storage/ for the data and checkpoints, and uv.lock for the resolved environment.
Editorial conclusion
Adopt OpenTrack if you are working on humanoid whole-body control and want a tracker that follows arbitrary reference motion rather than a fixed set of scripted behaviours, since the released LAFAN1 generalist v2 policy tracks all 40 motions in that set. Skip it if you need a ready-to-run pipeline, because the environment pins Python to exactly 3.12.9 and expects a populated storage/ tree with mocap data, assets and a W&B project, which is a lot of setup before the first checkpoint runs. Verify first that your GPU and driver line up with the jax[cuda12] build, that you have the LAFAN1 mocap data in the expected layout, and which of the training paths you actually need, since only the checkpoints and the evaluation script are turnkey.
Frequently asked questions
What is OpenTrack and what is Any2Track?
OpenTrack is the official implementation of Any2Track, an open-source humanoid motion tracking codebase from GALBOT and Tsinghua. It uses MuJoCo JAX for simulation and supports multi-GPU parallel training.
How do I set up OpenTrack for the first time?
Clone the repository, run `uv sync -i https://pypi.org/simple` to create the environment, create a `.env` file with GLI_PATH and the WANDB project, entity and API key variables, put the mocap data under `storage/data/mocap/`, then activate the environment, source the .env file and run `python track_mj/app/mj_playground_init.py` to initialize the assets.
What is the difference between LAFAN1 generalist v1 and v2?
Generalist v1 was daggered from four teachers and can track most motions, failing on some extremely challenging ones because some teachers fail to track them. Generalist v2 was daggered from eight more carefully designed teachers, each of which tracks all motions in its cluster, and the resulting student policy tracked all 40 out of 40 LAFAN1 motions.
What does the preprocess_motion.py script do to my motion files?
It aligns the motion data frequency to the desired control frequency, 50Hz by default, and recalculates velocities and other state features from the aligned frequency. The documentation warns that it overwrites the original motion files. The `--smooth_start_end` option adds a stepping transition from the default pose, generated by an inverse-kinematics solver using OSQP.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/galaxygeneralrobotics-opentrack)Was this useful?