Skip to main content
Home/Guides/MuJoCo Tutorial 2026
💻 TutorialMuJoCo 3.x · June 2026Free & Open Source

MuJoCo Tutorial 2026 — Complete Robotics Simulation Guide

MuJoCo is the most widely used physics engine in robotics research — behind DeepMind's bipedal walking, OpenAI's Dactyl hand, and hundreds of robotics papers. Now free and open-source. This guide goes from pip install to training your first locomotion policy.

Why MuJoCo in 2026?

🍎
Apple Silicon support
Runs natively on M1/M2/M3 Macs. Crucial for researchers without NVIDIA GPUs.
📚
Research standard
If a paper benchmarks on Ant, HalfCheetah, or Humanoid, it uses MuJoCo. Every RL library supports it.
🆓
Free since 2022
DeepMind acquired and open-sourced it. No license key, no cost, Apache 2.0.

Getting Started — Step by Step

1Install MuJoCo
# MuJoCo 3.x is free, open-source, and pip-installable
pip install mujoco

# Verify installation
python -c "import mujoco; print(mujoco.__version__)"
# Expected: 3.x.x

# Install optional viewer (standalone window)
pip install mujoco[viewer]

# Also install dm_control for gym-style environments
pip install dm-control
💡 MuJoCo went free and open-source in October 2022 when DeepMind acquired it from Ercument Gören and donated it. No license key required. Works on Linux, macOS (including Apple Silicon), and Windows.
2Your First XML Model (MJCF)
<!-- simple_arm.xml — a 2-DOF arm -->
<mujoco>
  <worldbody>
    <light diffuse=".5 .5 .5" pos="0 0 3" dir="0 0 -1"/>
    <geom type="plane" size="1 1 0.1" rgba=".9 0 0 1"/>

    <body name="upper_arm" pos="0 0 0.5">
      <joint name="shoulder" type="hinge" axis="0 1 0"/>
      <geom type="capsule" size="0.04" fromto="0 0 0 0 0 0.3" rgba="0 .9 0 1"/>

      <body name="lower_arm" pos="0 0 0.3">
        <joint name="elbow" type="hinge" axis="0 1 0"/>
        <geom type="capsule" size="0.04" fromto="0 0 0 0 0 0.25" rgba="0 0 .9 1"/>
      </body>
    </body>
  </worldbody>

  <actuator>
    <motor name="shoulder_motor" joint="shoulder" gear="100"/>
    <motor name="elbow_motor" joint="elbow" gear="50"/>
  </actuator>
</mujoco>
💡 MJCF (MuJoCo XML format) is how you define robots. Bodies have joints, geoms (collision/visual shapes), and sensors. Actuators apply forces. Everything is hierarchical.
3Python API Basics
import mujoco
import mujoco.viewer
import numpy as np

# Load model from XML file
model = mujoco.MjModel.from_xml_path("simple_arm.xml")
data = mujoco.MjData(model)

# Single step
mujoco.mj_step(model, data)

# Access state
print("Time:", data.time)
print("Joint positions:", data.qpos)
print("Joint velocities:", data.qvel)
print("Actuator forces:", data.ctrl)

# Set control and simulate
data.ctrl[0] = 0.5   # shoulder motor
data.ctrl[1] = -0.3  # elbow motor

for _ in range(1000):
    mujoco.mj_step(model, data)
    print(f"t={data.time:.3f}  qpos={data.qpos}")

# Launch interactive viewer
with mujoco.viewer.launch_passive(model, data) as viewer:
    while viewer.is_running():
        mujoco.mj_step(model, data)
        viewer.sync()
💡 MjModel holds the static model structure. MjData holds the simulation state — positions, velocities, forces, contacts. Always separate the two — model is read-only during simulation.
4Load a Real Robot (MuJoCo Menagerie)
# Clone the Menagerie (20+ robots in MJCF format)
git clone https://github.com/google-deepmind/mujoco_menagerie.git

# Load Franka Panda
import mujoco

model = mujoco.MjModel.from_xml_path(
    "mujoco_menagerie/franka_emika_panda/panda_nohand.xml"
)
data = mujoco.MjData(model)

print("Model name:", model.body(0).name)
print("Number of joints:", model.njnt)
print("Number of actuators:", model.nu)
print("DOF:", model.nv)

# Other robots available:
# - unitree_a1 (quadruped)
# - unitree_go1 (quadruped)
# - anybotics_anymal_c (quadruped)
# - shadow_hand
# - robotis_op3 (humanoid)
# - boston_dynamics_spot (quadruped)
💡 MuJoCo Menagerie is the official robot model library — maintained by Google DeepMind. All robots are physics-validated and include accurate mass properties and actuator parameters.
5RL Training with Stable-Baselines3
import gymnasium as gym
import numpy as np
from stable_baselines3 import PPO
from stable_baselines3.common.env_util import make_vec_env

# MuJoCo environments via Gymnasium
# pip install gymnasium[mujoco]

# Classic benchmarks
env_id = "Ant-v4"          # 4-legged locomotion
# env_id = "HalfCheetah-v4" # 2D running
# env_id = "Humanoid-v4"    # Full humanoid walking

# Vectorize for parallel training
vec_env = make_vec_env(env_id, n_envs=4)

# Train with PPO
model = PPO(
    "MlpPolicy",
    vec_env,
    verbose=1,
    n_steps=2048,
    batch_size=64,
    n_epochs=10,
    learning_rate=3e-4,
    clip_range=0.2,
    ent_coef=0.0,
    vf_coef=0.5,
)

model.learn(total_timesteps=1_000_000)
model.save("ppo_ant")

# Evaluate
obs, _ = vec_env.reset()
for _ in range(1000):
    action, _ = model.predict(obs, deterministic=True)
    obs, reward, done, truncated, info = vec_env.step(action)
💡 Gymnasium's MuJoCo environments (Ant, HalfCheetah, Humanoid) are the benchmark standard. If a research paper claims 1M reward on Ant-v4, this is the environment.

MJCF (MuJoCo XML) Reference

Bodies & Joints
Bodies are rigid objects in the kinematic chain. Joints connect parent and child bodies. Joint types: hinge (1 DOF rotation), slide (1 DOF translation), ball (3 DOF rotation), free (6 DOF).
<body name="link1" pos="0 0 0.2">
  <joint name="j1" type="hinge" axis="0 1 0" range="-1.57 1.57"/>
  <geom type="capsule" size="0.05" fromto="0 0 0 0 0 0.2"/>
</body>
Geoms (Geometry)
Geoms define collision and visual shapes. Types: sphere, capsule, cylinder, box, mesh (for complex shapes from OBJ/STL). Geoms have rgba for color and material for contact properties.
<!-- Visual and collision geom -->
<geom type="sphere" size="0.05" rgba="0.8 0.2 0.2 1"/>
<geom type="mesh" mesh="my_mesh" rgba="0.3 0.3 0.3 1"/>

<!-- In <asset> section -->
<asset>
  <mesh name="my_mesh" file="mesh.obj"/>
</asset>
Actuators
Actuators apply forces/torques to joints. Position (servo-style), velocity (speed control), motor (torque control). Use gear to scale force. Specify ctrlrange to limit control input.
<actuator>
  <!-- Motor actuator (direct torque) -->
  <motor name="hip" joint="hip_joint" gear="50" ctrlrange="-2 2"/>

  <!-- Position actuator (PD control) -->
  <position name="knee_pos" joint="knee" kp="100" ctrlrange="-1.57 1.57"/>

  <!-- Velocity actuator -->
  <velocity name="wheel" joint="wheel_joint" kv="10"/>
</actuator>
Sensors
Sensors measure state during simulation. Types: jointpos, jointvel, actuatorfrc, force (6-axis), touch (contact), gyro (angular velocity), accelerometer, camera, rangefinder.
<sensor>
  <jointpos name="hip_pos" joint="hip_joint"/>
  <jointvel name="hip_vel" joint="hip_joint"/>
  <force name="foot_force" site="foot_site"/>
  <gyro name="imu_gyro" site="body_imu"/>
  <accelerometer name="imu_acc" site="body_imu"/>
</sensor>

<!-- Read in Python -->
# data.sensor("hip_pos").data[0]  # joint position value
Contacts & Friction
Contact properties control how surfaces interact. Friction pair (tangential, torsional, rolling). Condim controls friction cone dimensionality. Solref/solimp control solver parameters for penetration.
<default>
  <geom condim="4" friction="1 0.005 0.0001" solref="0.01 1" solimp="0.9 0.95 0.001"/>
</default>

<!-- Per-geom override -->
<geom type="box" size="0.1 0.1 0.01"
      friction="0.5 0.01 0.0001"  <!-- tangential torsional rolling -->
      solimp="0.95 0.99 0.001"/>

MuJoCo vs NVIDIA Isaac Lab

FeatureMuJoCoNVIDIA Isaac Lab
PlatformAll (Linux, macOS, Windows, Apple Silicon)Linux + NVIDIA GPU only
GPU ParallelismLimited (~500 envs)10,000+ envs on A100
Install Complexitypip install mujoco (seconds)Requires Isaac Sim (~30 min)
CostFree (Apache 2.0)Free (Isaac Sim free license)
Physics AccuracyIndustry standard — MJC physicsPhysX 5 — similar accuracy
Robot LibraryMuJoCo Menagerie — 20+ robotsOfficial assets — 15+ robots
RL EcosystemGymnasium — every RL framework supports itRSL-RL, skrl, RL-Games, SB3
Research PapersDeepMind, OpenAI, MIT, CMUETH, ANYbotics, legged labs
Best ForResearch, diversity, Apple Silicon devsLocomotion training at scale, enterprise

Rule of thumb: use MuJoCo if you're on macOS, need fast setup, or want ecosystem breadth. Use Isaac Lab if you have an NVIDIA GPU and need 10,000+ parallel environments for locomotion.

Frequently Asked Questions

Q: Does MuJoCo work on Apple Silicon (M1/M2/M3)?
Yes — natively. MuJoCo 3.x ships with arm64 binaries. pip install mujoco works immediately on M-series Macs. This is one of the biggest advantages over Isaac Lab, which requires NVIDIA GPUs.
Q: What's the difference between MuJoCo and PyBullet?
Both are physics simulators. MuJoCo has more accurate contact physics and is the current research standard. PyBullet is older, uses the Bullet physics engine, and has fallen behind in research adoption since MuJoCo went free in 2022. Start with MuJoCo.
Q: How do I convert a URDF robot to MJCF?
Use the mujoco.mjcf utility or the `obj2mjcf` tool. For ROS robots with URDFs: use the `urdf2mjcf` package (pip install urdf2mjcf). Alternatively, MuJoCo Menagerie already has many common robots converted to MJCF.
Q: What reinforcement learning framework should I use with MuJoCo?
For beginners: Stable-Baselines3 (SB3) — clean API, well-documented, all major algorithms (PPO, SAC, TD3). For research: CleanRL (minimal clean implementations) or TianShou. For scale: Isaac Lab's RSL-RL if you switch to GPU-accelerated training.
Q: What are the standard MuJoCo benchmark environments?
Gymnasium (formerly OpenAI Gym) provides the standard benchmarks: HalfCheetah-v4, Ant-v4, Humanoid-v4, Hopper-v4, Walker2d-v4, Swimmer-v4. These are the 'hello world' of continuous control RL. When comparing algorithms, always use these exact versions.