Skip to content

Releases: mujocolab/mjlab

mjlab v1.3.0

14 Apr 22:05
Immutable release. Only release title and notes can be modified.
19d6c06

Choose a tag to compare

TLDR: A packed release with a viewer rebuilt on mjviser, a preset-based terrain system, simplified actuator configuration, and new MDP primitives like RecorderManager and termination_curriculum.

Physics engine bump

mjlab 1.3.0 uses mujoco-warp 3.7.0.1 and mujoco 3.7.0.

Viewer: Rebuilt on mjviser

The Viser viewer internals have been replaced with the standalone mjviser package. Scene creation, mesh conversion, and overlay rendering (contacts, forces, inertia, tendons, joints, frames) now live in mjviser, while mjlab keeps debug visualization and warp tensor conversion in its MjlabViserScene subclass. The viewer exposes a new Visualization tab for overlay controls and a Groups tab for geom and site visibility.

mjviser_teaser.mp4

New panels and tabs:

  • Reward bar panel showing horizontal bars for each reward term with a running mean over ~1 second
  • W&B run tab for browsing recent runs and pulling checkpoints
  • Checkpoints tab in play for hot-swapping checkpoints without restarting, with support for local directories and W&B runs
  • Motion reference scrubber for tracking tasks
  • Per-pixel segmentation camera data type for geom ID output alongside RGB and depth, with a new Mjlab-Multi-Cube-Seg-Yam task that uses it

Terrain System, Revamped

Terrain configuration moves to a preset-based system with a new @terrain_preset decorator for composing reusable configurations. Curriculum mode now assigns exactly one column per terrain type, with proportion controlling robot spawning distribution rather than column counts. A new STAIRS_TERRAINS_CFG preset provides a progressive stair curriculum out of the box.

mjlab_go1_stair_terrain.mp4

A Go1 velocity policy trained on the new stair terrain

TerrainHeightSensor, a RayCastSensor subclass, computes per-frame vertical clearance above terrain. The velocity task configs now use it for feet_clearance, feet_swing_height, and foot_height, replacing the previous world-Z proxy that was incorrect on rough terrain. A new terrain-aware upright reward penalizes body pitch and roll relative to the local terrain normal.

RayCastSensor itself was generalized: pass a tuple of ObjRef to frame for multi-frame, per-site raycasting, and use the new RingPatternCfg for concentric ring sampling around each frame.

Actuator Configuration, Simplified

Actuator delay is now configured inline on any ActuatorCfg subclass:

# Before
DelayedActuatorCfg(BuiltinPositionActuatorCfg(...), delay_min_lag=2, delay_max_lag=5)

# After
BuiltinPositionActuatorCfg(..., delay_min_lag=2, delay_max_lag=5)

DelayedActuator, DelayedActuatorCfg, and DelayedBuiltinActuatorGroup are removed. Delay always applies to the actuator's command_field automatically, so delay_target is no longer needed.

The four XML actuator config classes (XmlPositionActuatorCfg, XmlVelocityActuatorCfg, XmlMotorActuatorCfg, XmlMuscleActuatorCfg) collapse into a single XmlActuatorCfg that auto detects the actuator type from XML. Pass command_field=... to override.

Two new behaviors on ActuatorCfg:

  • viscous_damping for passive velocity proportional damping (f = -b·v), distinct from the PD derivative gain damping used by position and velocity actuators. Maps to <joint damping> for JOINT transmission and <tendon damping> for TENDON transmission.
  • armature and frictionloss now default to None instead of 0.0, preserving the XML values instead of silently overwriting them. Pass armature=0.0 or frictionloss=0.0 explicitly to restore the old behavior.

New MDP Primitives

Several additions to the manager and MDP APIs:

  • RecorderManager for logging observations, actions, or arbitrary environment data during rollouts. Implement a RecorderTerm subclass and register it in the recorders dict on ManagerBasedRlEnvCfg. The manager provides record_pre_reset, record_post_reset, and record_post_step lifecycle hooks with no opinion on how data is stored.
  • termination_curriculum for scheduling changes to termination term parameters during training, matching the existing reward_curriculum pattern. Both now share a single internal engine with init-time validation of stage ordering, field existence, and param keys.
  • MetricsTermCfg.reduce field with a "last" option that reports the final step of the episode rather than the episode mean. Useful for binary success metrics.
  • RelativeJointPositionAction for joint position control relative to the current configuration. The target is current_pos + action * scale, so a zero action holds the current configuration rather than commanding the default pose.
  • dr.pair_friction for randomizing geom-pair friction overrides, with an isotropic=True option that mirrors the symmetric tangent and roll axes so single-axis randomization does not leave the paired axis stale.
  • ActionTermCfg.clip for clamping processed actions after scale and offset.
  • qfrc_actuator and qfrc_external generalized force accessors on EntityData. qfrc_actuator gives actuator forces in joint space (projected through the transmission); qfrc_external recovers the generalized force from body external wrenches (xfrc_applied).

Cartpole Tutorial

A new cartpole tutorial walks through building an environment from scratch, using the Mjlab-Cartpole-Balance and Mjlab-Cartpole-Swingup tasks as running examples. It covers scene setup, action and observation terms, rewards, terminations, and training.

Also In This Release

  • Mujoco 3.7.0 and mujoco-warp 3.7.0.1 are now the minimum supported versions
  • Motion imitation documentation with preprocessing instructions, replacing the BeyondMimic link that produced incompatible NPZ files
  • margin, gap, solmix fields on CollisionCfg for per geom contact parameter configuration
  • ManagerBasedRlEnvCfg.auto_reset flag for custom training loops that need access to the true terminal state
  • Top-level --help for train and play that points users at list-envs and <TASK> --help
  • list_envs renamed to list-envs for consistency with other hyphenated entry points
  • RNN model support in RslRlModelCfg
  • NaN guard now captures mocap body poses, enabling full state reconstruction in the dump viewer for fixed-base entities
  • Per-substep metric evaluation via MetricsTermCfg.per_substep for metrics evaluated inside the decimation loop
  • dr.pseudo_inertia no longer loads cuSOLVER, eliminating ~4 GB of persistent GPU memory overhead
  • CUDA graph capture no longer triggers GC, avoiding capture failures on long runs
  • Onnxruntime roundtrip tests for ONNX policy export

Breaking Changes

  • DelayedActuator, DelayedActuatorCfg, DelayedBuiltinActuatorGroup are removed. Configure delay inline on any ActuatorCfg subclass.
  • delay_target is removed. Delay always applies to the actuator's command_field.
  • XmlPositionActuatorCfg, XmlVelocityActuatorCfg, XmlMotorActuatorCfg, XmlMuscleActuatorCfg are replaced by a single XmlActuatorCfg.
  • TerrainImporter and TerrainImporterCfg aliases are removed. Use TerrainEntity and TerrainEntityCfg.
  • EntityData.generalized_force is removed. Use qfrc_actuator or qfrc_external.
  • ActuatorCfg.armature and .frictionloss default to None instead of 0.0.
  • Entity.clear_state() is deprecated. Use Entity.reset().
  • out_of_terrain_bounds is replaced with terrain_edge_reached.

Bug Fixes

  • SceneEntityCfg names and IDs ordering mismatch with preserve_order=False (#876)
  • ONNX export path resolution when a parent directory name contains "model" (#867)
  • export-scene writing assets to the wrong location and allowing path traversal in asset keys (#858)
  • electrical_power_cost now uses joint space forces, correct for actuators with non-unit gear ratios (#776)
  • create_velocity_actuator no longer sets ctrllimited=True with inheritrange=1.0, which crashed on continuous joints such as wheels (#787)
  • write_root_com_velocity_to_sim with tensor env_ids on floating base entities (#793)
  • dr.pseudo_inertia 4 GB GPU memory overhead (#753)
  • Contact force visualization for non-builtin actuators (#786)
  • BoxSteppingStonesTerrainCfg large gap around the platform (#785)
  • TerrainHeightSensor reporting box thickness during penetration and max_distance during ground contact (#835, #841)
  • Sensor name prefix duplicated on deepcopy (#851)
  • get_wandb_checkpoint_path stale cache on repeated calls (#869)
  • Ghost geom filtering now uses visual alpha instead of collision flags (#888)
  • Native viewer syncs qpos0 when domain randomized, fixing incorrect body positions after dr.joint_default_pos (#760)
  • command_manager.compute() is now called during reset() so derived command state is populated before the first observation (#761)
  • RayCastSensor frame offset alignment for sites and geoms with a local offset from their parent body (#775)

New Contributors

Thank you to @cjyyx, @omarrayyann, @gokulp01, @cmjang, @jsw7460, and @lzyang2000 for their first contributions to mjlab!

Full Changelog: v1.2.0...v1.3.0

mjlab v1.2.0

06 Mar 22:22
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

Our biggest release yet. 60+ pull requests from 12 contributors. A ground up redesign of domain randomization, major viewer improvements, cloud training support, and many bug fixes.

pip install mjlab
dr_hero.mp4

Domain randomization on the yam lift cube task: cube color, cube size, cube mass, link orientations, link inertias, camera FOV, and lighting all randomized per environment on every reset.

Domain Randomization, Redesigned

Domain randomization is a key technique for sim-to-real transfer. The new dr module replaces the previous randomize_field interface with typed, per-field randomization functions. These functions automatically recompute dependent physical quantities when a parameter is modified. For example, if body mass is randomized, the corresponding inertia values are updated to remain physically consistent. Similarly, when geom size parameters change, the broadphase collision bounds are recomputed. This design removes the need for manual set_const calls and reduces the risk of introducing inconsistent physics states.

import mjlab.envs.mdp.dr as dr

dr.geom_friction(env, cfg, operation=dr.scale, distribution=dr.uniform, ranges=(0.8, 1.2))
dr.pseudo_inertia(env, cfg, alpha_range=(-0.3, 0.3), d_range=(-0.3, 0.3))
dr.mat_rgba(env, cfg, operation=dr.add, distribution=dr.gaussian, ranges=(-0.1, 0.1))

The full lineup covers geometry, bodies, visuals, cameras, and lights. Custom operations and distributions are first class: define your own and pass them anywhere a string is accepted. The native viewer syncs all randomized fields from the GPU model on every reset, so DR changes are immediately visible.

Viewer Overhaul

viewer.mp4

The viewer timing model was rewritten. A single sim budget accumulator with a wall time deadline keeps physics and rendering in sync at any speed multiplier (1/32x to 8x). When physics cannot keep up, the deadline caps the burst so the renderer always gets a turn.

New in both viewers:

  • Single step mode to advance exactly one physics step while paused
  • Error recovery that pauses and logs the traceback instead of crashing
  • Force arrows that visualize apply_body_impulse events in real time
  • Realtime factor displayed alongside FPS

New in Viser:

  • Velocity joystick for manual command override
  • Revamped term plotter with per term filtering
  • Reorganized controls with a cleaner folder hierarchy

Step Events and Body Impulses

The new "step" event mode fires every environment step, not just on reset. Combine it with apply_body_impulse to throw external forces at your robot during training, with configurable duration, magnitude, and application point.

impulse.mp4

Cloud Training

Train on cloud GPUs with a single command. We added SkyPilot integration for Lambda Cloud with docs covering setup, monitoring, and cost management. W&B sweep scripts distribute one agent per GPU across multi GPU instances.

Documentation

The docs have been completely rewritten with improved guides, API reference, and multi versioned support. Check them out at mujocolab.github.io/mjlab.

Also In This Release

  • export-scene CLI to dump any task scene or asset zoo entity to a directory or zip for inspection and debugging
  • rsl-rl-lib upgraded to 5.0.1 with automatic checkpoint migration for the new distribution config format
  • Contact sensor history across decimation substeps for more reliable self collision and illegal contact detection
  • Docker images published on every push to main
  • joint_torques_l2 now accepts actuator_ids for penalizing a subset of actuators

Breaking Changes

  • randomize_field is removed. Use typed functions from the dr module (e.g. dr.geom_friction, dr.body_mass).
  • EventTermCfg no longer accepts domain_randomization.
  • RslRlModelCfg uses distribution_cfg dict instead of stochastic/init_noise_std/noise_std_type. Existing checkpoints are migrated automatically on load.

Bug Fixes

  • Viewer FPS drops from physics starving the renderer (#694, #705)
  • height_scan returning ~0 for missed rays (#646)
  • Ghost mesh rendering for fixed base entities (#645)
  • Actuator target resolution for entities with internal attach prefixes (#714)
  • Offscreen rendering artifacts in large vectorized scenes (#682)
  • Viser viewer crashing on scenes with no mocap bodies (#662)
  • Bundled ffmpeg via imageio-ffmpeg, no more system install required (#650)

New Contributors

Thank you to @Msornerrrr, @rdeits-bd, @jonzamora, @jgueldenstein, @saikishor, @ax-anoop, @chengruiz, @ManuelActisCassa, and @etaoxing!

Full Changelog: v1.1.1...v1.2.0

mjlab v1.1.1

15 Feb 01:55
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

Minor patch release with bug fixes and small improvements. Highlights include a new differential IK action space, reward visualization in the native viewer, and a switch from moviepy to mediapy for video recording.

What's Changed

New Contributors

Full Changelog: v1.1.0...v1.1.1

mjlab v1.1.0

13 Feb 05:41
Immutable release. Only release title and notes can be modified.
9954a18

Choose a tag to compare

mjlab and all its dependencies (including mujoco-warp) are now available directly from PyPI. Installation no longer requires pinning a specific mujoco-warp revision or custom indices and is now just:

pip install mjlab

or try it instantly with:

uvx --from mjlab demo

What's new

  • RGB and depth camera sensors with BVH-accelerated raycasting
  • MetricsManager for logging custom metrics during training
  • Terrain visualizer and many new terrain types
  • Site group visualization in the Viser viewer
  • Upgraded rsl-rl-lib to 4.0.0 with native ONNX export
  • Various bug fixes

See the full changelog for details.

mjlab v1.0.0

29 Jan 05:38
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

mjlab is now stable. Thank you to everyone who contributed code, reported issues, and provided feedback along the way. This release wouldn't have happened without you.

Some highlights:

  • RayCastSensor: Terrain and obstacle detection for navigation tasks
  • ContactSensor improvements: History tracking for better contact dynamics
  • Muscle actuator support: Biomechanical simulation capabilities
  • Sensor caching: Performance optimizations for large-scale training
  • Better NaN handling: Easier debugging with detection in observations and sensor data

v1.1 will follow shortly after mjwarp exits beta (imminent), adding RGB-D camera support (experimental #511).

Cheers!

v0.1.0 - Beta Release

29 Sep 10:00

Choose a tag to compare

v0.1.0 - Beta Release Pre-release
Pre-release

mjlab is public and on PyPI! 🎉

We're excited to announce the release of mjlab. It is available here on GitHub and on PyPI.

Quick Demo

See mjlab in action with a pre-trained motion imitation policy on the Unitree G1 humanoid:

uvx --from mjlab --with "mujoco-warp @ git+https://github.com/google-deepmind/mujoco_warp" demo

Beta Release

This is an early beta release - we're actively implementing missing features and would love your feedback on what to prioritize! The API may evolve as we incorporate community input, add new features and squash bugs.

Thanks!