#mujoco #bevy #robotics #physics #physics-simulation


Use MuJoCo physics and MCJF / URDF scenes in bevy

6 releases (3 breaking)

0.13.0 Apr 2, 2024
0.12.0 Nov 5, 2023
0.11.0-beta Jul 17, 2023
0.0.5 May 31, 2023
0.0.2 Dec 26, 2022

#24 in Simulation

Download history 2/week @ 2024-02-14 7/week @ 2024-02-21 2/week @ 2024-02-28 1/week @ 2024-03-06 3/week @ 2024-03-13 75/week @ 2024-03-27 53/week @ 2024-04-03

132 downloads per month


498 lines

Bevy MuJoCo

Crates.io MIT/Apache 2.0 Crates.io Rust


Import MJCF files into Bevy and run simulations with MuJoCo.

Implementation Notes

MuJoCo has 2 modes with different coordinate systems for bodies

  1. paused mode where all translations and rotations are extracted from mj_Model in MuJoCo-Rust as body.pos, body.quat in parent's body coordinate system. To make them work nice with bevy the body structure from mujoco has to be transformed to a tree structure with body_tree() call. Then body_tree is spawned into the bevy world recursively — a nice contraption to do it in setup_mujoco.

  2. simulation mode where translations are extracted from sim.xpos() and sim.xquat() — and this time they are in global frame. Since bodies are spawned hierarchically translations and rotations need to be converted to a parent coordinate system — it happens in simulate_physics.

Getting Started

MuJoCo Dependency

  • MuJoCo 2.3.5 installed in ~/.local/mujoco for Linux or C:/Program Files/Mujoco for Windows
  • nightly Rust. Compile with cargo +nightly build


// 1. Import bevy_mujoco
use bevy_mujoco::*;
// 2. Setup bevy_mujoco Plugin. MuJoCo Plugin would spawn entities to the world
fn main() {
        .insert_resource(MuJoCoPluginSettings {
            model_xml_path: "assets/unitree_a1/scene.xml".to_string(),
            pause_simulation: false,
            target_fps: 600.0, // this is not actual fps (bug in bevy_mujoco),
                               // the bigger the value, the slower the simulation
        .add_systems(Startup, setup)
        .add_systems(Update, robot_control_loop)
// 3. You can control your robots here
fn robot_control_loop(mut mujoco_resources: ResMut<MuJoCoResources>) {
    // prepare simulation data for the NN
    let qpos = mujoco_resources.state.qpos.clone();
    let qvel = mujoco_resources.state.qvel.clone();
    let cfrc_ext = mujoco_resources.state.cfrc_ext.clone();

    // Compute input -> control values here and fill control
    // ...
    let mut control: Vec<f32> = Vec::new();

    mujoco_resources.control.data = input_vec;

copy build.rs to root of your project to use in with Windows environments. it will copy mujoco.dll to a build dir of your application

To run tests and example initialize mujoco_menagerie submobule with

cd bevy_mujoco
git submodule init
git submodule update

See example for simulating Unitree A1 robot.


~887K SLoC