TL;DR
- Install MuJoCo 3.2.0 via
pip install mujocoand verify withpython -c "import mujoco; print(mujoco.__version__)"→3.2.0. - Model robots in MJCF (XML) with
<world>,<body>,<joint>, and<actuator>tags. Example: minimal humanoid XML. - Tune physics with
<contact>(friction, stiffness) and<solver>(iterations, tolerance) tags. Default friction:mu=0.5,mu2=0.0. - Run GPU-parallel simulations with MJX (requires CUDA). Example:
python -m mujoco.mjx_simulate --gpu. - Load Gymnasium environments via
gymnasium.make("Humanoid-v4")and train with Stable Baselines3. - Sim-to-real transfer: Use system identification (e.g.,
scipy.optimizefor parameter tuning) and log data withmjDatastructs.
1. Installation and MJCF Basics
MuJoCo’s Python bindings (mujoco) are the fastest way to start. The MJCF (MuJoCo XML Format) is the core modeling language—think of it as a physics-aware CAD file.
Install MuJoCo 3.2.0
# Linux (Ubuntu/Debian)
sudo apt-get install -y libgl1-mesa-dev libxinerama-dev libxcursor-dev
pip install mujoco==3.2.0 # Pin to stable version
# Verify installation
python -c "import mujoco; print(f'MuJoCo {mujoco.__version__} installed successfully')"
Expected Output:
MuJoCo 3.2.0 installed successfully
MJCF: The XML Backbone
MuJoCo models are defined in XML files (.xml). Here’s a minimal example for a 2D pendulum:
<mujoco model="pendulum">
<worldbody>
<light name="light" pos="0 0 3"/>
<camera name="camera" pos="0 0 1.5" xyaxes="1 0 0 0 1 0"/>
<body name="pendulum" pos="0 0 0">
<joint name="hinge" type="hinge" axis="0 0 1"/>
<geom name="bob" type="sphere" size="0.1" rgba="0.8 0.6 0.4 1"/>
</body>
<actuator name="motor">
<motor joint="hinge"/>
</actuator>
</worldbody>
</mujoco>
Key Tags:
<worldbody>: Root container for all physics objects.<body>: Rigid bodies (e.g., robot links).<joint>: Defines degrees of freedom (hinge,slide,ball).<geom>: Collision geometry (box,sphere,mesh).<actuator>: Motors, forces, or torques.
Gotcha: Forgetting to close tags (e.g., <body> without </body>) will crash the simulator. Use a validator like XMLLint.
2. Modeling a Robot: Bodies, Joints, and Actuators
Let’s build a 7-DOF robotic arm with MJCF. Focus on:
- Bodies: Links with mass/inertia.
- Joints: Connect bodies with constraints.
- Actuators: Apply forces/torques.
Example: 7-DOF Arm in MJCF
<mujoco model="arm7dof">
<asset>
<mesh file="arm.mesh" scale="0.1"/>
</asset>
<worldbody>
<!-- Base -->
<body name="base" pos="0 0 0.5">
<freejoint/>
<geom type="box" size="0.2 0.2 0.1" rgba="0.5 0.5 0.5 1"/>
</body>
<!-- Arm links (joints between them) -->
<body name="link1" pos="0 0 0.3">
<joint name="joint1" type="hinge" axis="0 1 0" damping="0.1"/>
<geom type="box" size="0.1 0.1 0.3" rgba="0.8 0.6 0.4 1"/>
</body>
<!-- Repeat for links 2-7... -->
<!-- Actuators (one per joint) -->
<actuator name="motor1">
<motor joint="joint1" gear="100"/>
</actuator>
</worldbody>
</mujoco>
Critical Settings:
damping: Reduces joint oscillations (default:0.0).gear: Simulates gear ratios (e.g.,gear="100"= 100:1 reduction).size: Geometry dimensions (must match CAD if using<mesh>).
Gotcha: MuJoCo uses SI units (meters, kilograms, seconds). A size="0.1" box is 10cm wide.
3. Contacts, Friction, and Solver Settings
MuJoCo’s physics accuracy hinges on contact modeling and solver tuning.
Contact Properties
Edit <contact> tags to control friction, restitution (bounciness), and stiffness:
<contact>
<geom1>body1</geom1>
<geom2>body2</geom2>
<friction>0.3 0.01 0.001</friction> <!-- mu, mu2, mu3 -->
<restitution>0.5</restitution> <!-- Bounciness (0-1) -->
<solref>0.01 1.0</solref> <!-- Solver reference (penetration, stiffness) -->
</contact>
Default Values:
- Friction:
mu=0.5,mu2=0.0(static/dynamic). - Restitution:
0.0(no bounce).
Solver Tuning
Adjust the solver for stability:
<solver>
<iterations>100</iterations> <!-- Default: 100 -->
<tolerance>1e-8</tolerance> <!-- Default: 1e-8 -->
<constraint>LRP</constraint> <!-- "LRP" or "NCP" -->
</solver>
When to Tune:
- High iterations (200+): For complex contacts (e.g., dexterous hands).
- Lower tolerance (1e-6): Faster but less accurate.
Gotcha: If your simulation explodes, increase solref or reduce iterations. If it’s stiff, lower restitution.
4. MJX for GPU-Parallel Simulation
MJX (MuJoCo eXtended) enables GPU-accelerated parallel simulation, critical for RL training.
Install MJX
pip install mujoco==3.2.0 mjx # MJX is bundled with mujoco>=3.2.0
Verify CUDA Support:
python -c "import mjx; print(mjx.cuda.is_available())" # Should return True
Run a GPU-Simulated Pendulum
import mjx
import numpy as np
# Load model
model = mjx.make("pendulum.xml")
sim = mjx.Sim(model)
# Run for 100 steps
for _ in range(100):
sim.step()
Expected Output: The pendulum swings smoothly (visualized via sim.render()).
Gotcha: MJX requires CUDA 11.8+. Check compatibility with:
nvcc --version
5. Running RL with Gymnasium Environments
MuJoCo powers Gymnasium’s robotics benchmarks (e.g., Humanoid-v4). Here’s how to train an RL agent.
Install Gymnasium with MuJoCo
pip install gymnasium[mujoco] # Includes MuJoCo 3.2.0
Load and Train an Agent
import gymnasium as gym
from stable_baselines3 import PPO
# Initialize environment
env = gym.make("Humanoid-v4", render_mode="human")
obs, _ = env.reset()
# Train with PPO
model = PPO("MlpPolicy", env, verbose=1)
model.learn(total_timesteps=10000)
# Test
obs, _ = env.reset()
for _ in range(1000):
action, _ = model.predict(obs)
obs, _, terminated, truncated, _ = env.step(action)
if terminated or truncated:
obs, _ = env.reset()
Key Environments:
Humanoid-v4: 3D humanoid locomotion.Ant-v4: Quadrupedal walking.Reacher-v4: 2D arm reaching.
Gotcha: Gymnasium’s MuJoCo environments default to GPU. If you get CUDA errors, set:
env = gym.make("Humanoid-v4", render_mode=None, use_gpu=False)
6. Sim-to-Real Gotchas and System Identification
MuJoCo’s physics are not perfect. Bridge the sim-to-real gap with:
- System Identification: Tune MuJoCo parameters to match real hardware.
- Domain Randomization: Train on varied MuJoCo parameters.
System Identification Example
Use scipy.optimize to fit MuJoCo’s mass/inertia to real data:
import mujoco
import numpy as np
from scipy.optimize import minimize
# Load model and data
model = mujoco.MjModel.from_xml_path("robot.xml")
data = mujoco.MjData(model)
# Define cost function (e.g., error between sim and real torque)
def cost_function(params):
# Update model parameters (e.g., mass)
model.body_mass[0] = params[0]
# Simulate and compute error
error = simulate_and_compare(data)
return error
# Optimize
result = minimize(cost_function, x0=[1.0], method="L-BFGS-B")
print(f"Optimal mass: {result.x[0]} kg")
Domain Randomization
Randomize MuJoCo parameters during training:
def randomize_model(model):
# Randomize friction
model.contact.mu = np.random.uniform(0.3, 0.7)
model.contact.mu2 = np.random.uniform(0.0, 0.1)
# Randomize mass
model.body_mass = model.body_mass * np.random.uniform(0.9, 1.1)
return model
Gotcha: Sim-to-real transfer often fails due to unmodeled dynamics (e.g., cable friction). Start with identical mass/inertia and gradually randomize.
7. Visualization and Logging
MuJoCo’s built-in viewer is lightweight but effective.
Launch the Viewer
import mujoco
import mujoco.viewer
model = mujoco.MjModel.from_xml_path("arm7dof.xml")
data = mujoco.MjData(model)
# Create viewer
with mujoco.viewer.launch_passive(model, data) as viewer:
while viewer.is_running():
step = not viewer.cam_move
mujoco.mj_step(model, data)
Controls:
- Left-click + drag: Rotate camera.
- Right-click + drag: Pan.
- Scroll: Zoom.
Log Data for Analysis
Save simulation data to a .mat file:
import scipy.io
# Simulate and log
data = mujoco.MjData(model)
for _ in range(1000):
mujoco.mj_step(model, data)
# Save joint positions
joint_positions = data.qpos.copy()
# Save to MATLAB file
scipy.io.savemat("simulation_data.mat", {"qpos": joint_positions})
Gotcha: The viewer blocks Python execution. Use launch_passive for background rendering.
What’s Next?
- Build a Custom Robot: Start with a 7-DOF arm (Section 2) and export its MJCF to a CAD tool like Blender.
- Train an RL Agent: Use Stable Baselines3 (Section 5) to teach your robot a skill (e.g., reaching).
- Deploy to Hardware: Use system identification (Section 6) to tune MuJoCo for your real robot.
For Physical AI infrastructure—from simulator tuning to edge deployment—Hyperion Consulting’s tools and expertise can accelerate your pipeline. [Contact us](https://hyperion-consulting.io
