A Rerun external data loader for MJCF (MuJoCo XML) files.
no-audio-rerun.mp4
Simulating fourier_n1 and boston_dynamics_spot from mujoco_menagerie:
uv run rerun-loader-mjcf --simulate mujoco_menagerie/fourier_n1/scene.xml
uv run rerun-loader-mjcf --simulate mujoco_menagerie/boston_dynamics_spot/scene.xmlno-audio-rerun_mjcf.mp4
Loading all robots from mujoco_menagerie
pip install rerun-loader-mjcfrerun-loader-mjcf robot.xmlTo run a real-time simulation loop:
rerun-loader-mjcf robot.xml --simulateOr run directly without installing:
uvx rerun-loader-mjcf robot.xmlimport mujoco
import rerun as rr
import rerun_loader_mjcf
model = mujoco.MjModel.from_xml_path("robot.xml")
data = mujoco.MjData(model)
rr.init("mjcf_viewer", spawn=True)
logger = rerun_loader_mjcf.MJCFLogger(model)
rr.set_time("frame", sequence=0)
logger.log_model()
data.qpos[0] += 0.5
mujoco.mj_forward(model, data)
rr.set_time("frame", sequence=1)
logger.log_data(data)logger = rerun_loader_mjcf.MJCFLogger(
model,
entity_path_prefix="robot", # Prefix for all entity paths
opacity=0.5, # Transparency (0.0 to 1.0)
log_collision=True, # Log collision geometries (default: False)
)When log_collision=True, collision geometries are logged to a separate entity path ({prefix}/collision_geometries/) which can be toggled in the Rerun viewer.
To log collision geometries but hide them by default:
import rerun.blueprint as rrb
logger = rerun_loader_mjcf.MJCFLogger(model, log_collision=True)
rr.set_time("sim_time", duration=0.0)
logger.log_model()
blueprint = rrb.Spatial3DView(
overrides={logger.paths.collision_root: rrb.EntityBehavior(visible=False)}
)
rr.send_blueprint(blueprint)You can change body colors during simulation (e.g., for highlighting):
# Set a body to red
logger.set_body_color(body_id=5, rgba=[1.0, 0.0, 0.0, 1.0])
# Reset to original color
logger.reset_body_color(body_id=5)
# Reset with custom opacity
logger.reset_body_color(body_id=5, opacity=0.5)For efficient batch recording of simulations, use MJCFRecorder:
import mujoco
import rerun as rr
import rerun_loader_mjcf
model = mujoco.MjModel.from_xml_path("robot.xml")
data = mujoco.MjData(model)
rr.init("simulation", spawn=True)
logger = rerun_loader_mjcf.MJCFLogger(model)
rr.set_time("sim_time", duration=0.0)
logger.log_model()
# With simulation time (default: uses duration=data.time)
with rerun_loader_mjcf.MJCFRecorder(logger) as recorder:
while data.time < 5.0:
mujoco.mj_step(model, data)
recorder.record(data)
# With explicit sequence index
with rerun_loader_mjcf.MJCFRecorder(logger, timeline_name="frame") as recorder:
for i in range(1000):
mujoco.mj_step(model, data)
recorder.record(data, sequence=i)
# With explicit timestamp
with rerun_loader_mjcf.MJCFRecorder(logger, timeline_name="sim_time") as recorder:
while data.time < 5.0:
mujoco.mj_step(model, data)
recorder.record(data, timestamp=data.time)uv run pre-commit run -aInspired by rerun-loader-python-example-urdf.
- Integrate mujoco-rs to implement a native Rust loader similar to loader_urdf.rs