minimal_mjx
Starter code for MJX-based reinforcement learning from the Dynamic Mobility Lab. It is built on MuJoCo Playground and Brax PPO, and keeps training, checkpointing, and evaluating policies simple:
- Swappable backend. Write an environment once and run it on JAX/MJX (
jnp) for fast parallel training, or on NumPy/C MuJoCo (np) for fast, debuggable rollouts. - Base environment class (
SwappableBase) with common reward terms and helpers. - Config-agnostic library. Library functions take plain arguments (
run_dir,ppo_params,network_params, ...).mm.utils.Configis the only code that knows the YAML layout, so you can use your own layout by subclassing it or skip it.
Install
pip install minimal_mjx # from PyPI
pip install -e ".[dev]" # from source, with pytest
Repository layout
src/minimal_mjx/
envs/generic/base.py SwappableBase: backend switching, reward helpers, history buffers
learning/training.py train(): runs Brax PPO into a run dir, checkpoints, resumes
learning/inference.py load_policy(run_dir), get_last_model(run_dir), get_step_reset()
eval/rollout.py rollout_policy(): roll out a policy, record data, render video
utils/config.py Config (the only YAML-aware code), read_config(), save_config()
utils/plotting.py reward/data plotters, save_video(), save_metrics()
utils/logging.py Weights & Biases helpers (init, upload/download checkpoints)
utils/state.py EnvState, the NumPy-backend counterpart of mjx_env.State
example/ a complete Cheetah task (see below)
tests/ pytest suite
Example: Cheetah
example/ shows the full workflow on DeepMind Control's Cheetah:
| File | Purpose |
|---|---|
cheetah.xml |
MuJoCo model |
cheetah.py |
Cheetah(SwappableBase): reset, step, observations, rewards, termination |
cheetah.yaml |
Run config: name, save dir, backend, env_config, learning_params |
create_environment.py |
Maps the config's env name to an environment class |
simulate.py |
Rolls out a zero-action policy to check the environment |
train.py |
Trains with PPO (logs to W&B; set USE_WANDB = False to turn this off) |
rollout.py |
Loads the latest checkpoint and renders a rollout |
cheetah_model_input.py |
Lean Cheetah that takes the mjx.Model as an argument, so many model variants can be vmapped (used by scripts/rollout_cheetah_models.py) |
Run each script from the repository root and pass the config as its argument:
python -m example.simulate example/cheetah.yaml # video + reward plot in example/videos, example/plots
python -m example.train example/cheetah.yaml # checkpoints in <save_dir>/<name>/
python -m example.rollout example/cheetah.yaml # roll out the latest checkpoint
Use backend: np for simulation and rollouts. Training always builds the jnp
version. Before training, simulate once with backend: jnp to check that your
environment is JAX-compatible.
To roll out an older policy, pass the config.yaml saved in that run's directory.
Its git_hash records the commit the run was trained at. Runs named test can be
overwritten and skip the git hash; any other name refuses to overwrite an existing run.
Writing your own environment
Subclass mm.envs.SwappableBase and implement reset, step, reward_function,
_get_obs, and action_size. To stay backend-agnostic, use the backend handles
instead of np/jnp directly: self._np, self._step_fn, self._data_init_fn,
self._set_val_fn, self._uniform, and so on. Rewards come back as a dict
{name: value}, and get_reward_and_metrics weights them by
env_config.reward.weights. Use state.info to carry values from one step to
the next.
Using the API directly
import minimal_mjx as mm
cfg = mm.utils.Config('example/cheetah.yaml') # cfg.env_name, cfg.env_params, cfg.run_dir, ...
env = Cheetah(env_params=cfg.env_params, backend=cfg.backend)
policy = mm.learning.inference.load_policy(cfg.run_dir)
frames, traj, rewards, data, info = mm.eval.rollout_policy(policy, env, n_steps=500)
mm.utils.plotting.save_video(frames, env.dt, 'videos/rollout.mp4')
Training follows the same pattern (see example/train.py):
run_dir = mm.learning.create_training_directory(cfg.run_dir, overwrite=cfg.is_test)
cfg.save(run_dir / 'config.yaml', make_dir=False) # records the git hash
mm.learning.train(env, env, run_dir, cfg.ppo_params, cfg.network_params,
algorithm=cfg.algorithm, overwrite=cfg.is_test)
For a different YAML layout, subclass Config and override its properties (as
moplayground's MOConfig does), or pass the arguments yourself.
Tests
pytest # fast suite (~15 s, CPU)
pytest -m slow # rendering, video, and a tiny end-to-end PPO run
Metadata
Release files for minimal-mjx 0.1.16
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| minimal_mjx-0.1.16.tar.gz | 35.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| minimal_mjx-0.1.16-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 65.4 kB
Release files / minimal_mjx-0.1.16.tar.gz
| Download URL | minimal_mjx-0.1.16.tar.gz |
|---|---|
| Size | 35.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ca92fe756f726252cf4e0bb026be71080f0fd190dbc4fadd20dde991daf7201e
|
|
BLAKE2b-256 checksum How to use checksums |
461b06fada6718cb5c83c4963589c8f99ac9a6683ca8aff8d9ab105271e3c215
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / minimal_mjx-0.1.16-py3-none-any.whl
| Download URL | minimal_mjx-0.1.16-py3-none-any.whl |
|---|---|
| Size | 29.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bd87bbc6f1e999889a107a824b1809feec1541c4bda5195fe4ddfc5498f07ffe
|
|
BLAKE2b-256 checksum How to use checksums |
df8a44b0d95c70faaf6f1f9a0b7628278c92c659715e12f14aeff6a2238df604
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency log