Browse by type

Code will be released in stages:
[x] Pretrained checkpoints + sim-to-sim / sim-to-real deployment
→ deploy branch
[x] Minimal inference code + tutorial
→ minimal_inference branch
[x] Full training and evaluation pipelines
[x] A distributed training in MJLab (6 hours training) + Teleoperation
→ UFO implementation
[ ] Minimal training code (RTX 4090 support)
Humanoidverse training for BFM-Zero with Isaac Sim or MuJoCo.
This repo uses Git LFS for motion data and model. After cloning, install LFS and pull the large files:
git clone https://github.com/LeCAR-Lab/BFM-Zero.git
cd BFM-Zero
git lfs install
git lfs pull
Note: If the repository exceeded its LFS budget, you can access the data here: https://huggingface.co/LeCAR-Lab/BFM-Zero/tree/main/data
curl -LsSf https://astral.sh/uv/install.sh | sh
Or with pip: pip install uv
From this directory (BFM-Zero):
uv sync
humanoidverse/data/ after git lfs pull. lafan_29dof.pkl is for evaluation; lafan_29dof_10s-clipped.pkl is for training.uv run python -m humanoidverse.train
Note: change buffer_device to "cuda:0" if you have larger vRAM.
Training is driven by humanoidverse.train (see train_bfm_zero() in train.py). Key options:
| Area | Parameters |
|---|---|
| Scale | num_env_steps, online_parallel_envs, buffer_size, checkpoint_every_steps |
| Paths | work_dir, env’s lafan_tail_path (expert motion data) |
| Run | seed, use_wandb, wandb_pname / wandb_gname / wandb_ename |
| Policy / optim | update_agent_every, num_agent_updates, num_seed_steps; agent config (e.g. batch_size, lr_actor, lr_critic, discount) |
| Robot / env | Overridden via hydra_overrides (e.g. robot=..., robot.control.action_scale=..., env.config.lie_down_init=...) |
Override from code by passing a custom TrainConfig, or extend the CLI to accept Hydra/tyro overrides.
Tips: After 50-100 M steps training, eval/emd should lower than 0.75.

After training, three scripts handle inference and export:
| Script | Purpose |
|---|---|
humanoidverse.tracking_inference |
Motion tracking → extract latent (z), export ONNX |
humanoidverse.goal_inference |
Goal-reaching → compute (z) for different goals |
humanoidverse.reward_inference |
Reward-based tasks → compute (z) and evaluate performance |
Videos from BFM-Zero/model after running each inference script with --save_mp4:
1. Tracking inference — expert (left) vs policy (right):
![]()
2. Goal inference — goal-reaching rollout:

3. Reward inference — example task (e.g. move-ego):

All scripts use tyro for the CLI. General usage:
uv run python -m humanoidverse.tracking_inference --help
uv run python -m humanoidverse.goal_inference --help
uv run python -m humanoidverse.reward_inference --help
Common arguments:
--model_folder: Path to the trained model directory (must contain checkpoint/ and config.json).--data_path (optional): Override the default LaFan data path.--simulator: isaacsim (default) or mujoco. Use --simulator mujoco to run without Isaac Lab (MuJoCo only; output is directly usable for sim2sim visualization).--headless (default: True): Run without GUI; use --no-headless to show the viewer.--save_mp4: Save rendered videos.Output: All inference scripts export the policy to ONNX ({model_name}.onnx) in their respective output subdirectories under exported/.
Runs motion tracking, exports ONNX, and optionally saves a comparison video (expert vs policy).
uv run python -m humanoidverse.tracking_inference \
--model_folder /path/to/model \
--data_path humanoidverse/data/lafan_29dof.pkl \
--no-headless \
--save_mp4
--model_folder should point to the outer model directory (the one that contains checkpoint/).Outputs (under model_folder/tracking_inference/):
zs_{MOTION_ID}.pkl: Latent (z) for each motion.tracking.mp4: Expert vs policy comparison (when --save_mp4 is set).Computes (z) for predefined goals and optionally renders goal-reaching videos.
uv run python -m humanoidverse.goal_inference \
--model_folder /path/to/model \
--data_path humanoidverse/data/lafan_29dof.pkl \
--save_mp4
goal_frames_lafan29dof.json (the script searches for it in several locations).Outputs (under model_folder/goal_inference/):
goal_reaching.pkl: Dictionary {goal_name -> z}.videos/*.mp4: Per-goal videos (if --save_mp4 True).Runs reward-based task inference: computes (z) and optionally runs rollouts for evaluation.
uv run python -m humanoidverse.reward_inference \
--model_folder /path/to/model \
--save_mp4
Key arguments:
| Argument | Description |
|---|---|
--num_samples |
Number of samples in the buffer per inference run. |
--n_inferences |
Number of inference latents per reward task. |
--episode_length |
Steps per rollout. |
--skip_rollouts |
If True, only compute (z); do not run visualization rollouts. |
Outputs (under model_folder/reward_inference/):
reward_locomotion.pkl: Dictionary {task_name -> z}.videos/*.mp4: Per-task videos (when --save_mp4 is set).BFM-Zero is licensed under the CC BY-NC 4.0 license. See LICENSE for details.
If you find this project useful in your research, please consider citing:
@misc{li2025bfmzeropromptablebehavioralfoundation,
title={BFM-Zero: A Promptable Behavioral Foundation Model for Humanoid Control Using Unsupervised Reinforcement Learning},
author={Yitang Li and Zhengyi Luo and Tonghe Zhang and Cunxi Dai and Anssi Kanervisto and Andrea Tirinzoni and Haoyang Weng and Kris Kitani and Mateusz Guzek and Ahmed Touati and Alessandro Lazaric and Matteo Pirotta and Guanya Shi},
year={2025},
eprint={2511.04131},
archivePrefix={arXiv},
primaryClass={cs.RO},
url={https://arxiv.org/abs/2511.04131},
}
If you have any problems, please contact liyitang475@gmail.com.
$ claude mcp add BFM-Zero \
-- python -m otcore.mcp_server <graph>