Download Latest Version mujoco-4.0.1-windows-x86_64.zip (22.7 MB)
Home / 3.17.0
Name Modified Size InfoDownloads / Week
Parent folder
mujoco-3.17.0-macos-universal2.dmg.sha256 2026-10-22 101 Bytes
mujoco-3.17.0-macos-universal2.dmg 2026-10-22 55.2 MB
mujoco-3.17.0-windows-x86_64.zip.sha256 2026-10-22 99 Bytes
mujoco-3.17.0-linux-aarch64.tar.gz.sha256 2026-10-22 101 Bytes
mujoco-3.17.0-windows-x86_64.zip 2026-10-22 22.5 MB
mujoco-3.17.0-linux-aarch64.tar.gz 2026-10-22 34.6 MB
mujoco-3.17.0-linux-x86_64.tar.gz.sha256 2026-10-22 100 Bytes
mujoco-3.17.0-linux-x86_64.tar.gz 2026-10-22 35.1 MB
3.17.0 source code.tar.gz 2026-10-22 77.0 MB
3.17.0 source code.zip 2026-10-22 78.3 MB
README.md 2026-10-22 20.5 kB
Totals: 11 Items   302.7 MB 2

Version 3.17.0 (October 22, 2026)

Significant new features

  1. c00ed8153 Added a batch API in mujoco/mjbatch.h (in Python as mujoco.batch (mujoco.readthedocs.io)): many simulations of one model stepped on a thread pool of its own, each held as its integration state and loaded into an mjData for each call, so memory scales with threads and results are bit-identical to a plain loop at any thread count. It supports per-simulation model and option fields or models of the caller's, observations of the state after a step, recorded trajectories, persistent simulations (required for sleep), and arbitrary per-simulation functions. Follows the design of mjbatch by @kevinzakka.

Engine

  1. Flex improvements:

  2. 94483e166 Added bending elasticity for 1D flexes, using a twist-free isotropic discrete elastic rod model. The cross-section is selected with the new section attribute: a circle of the flex radius, or a box with half-sizes sectionsize that uses the stiffness of its weak axis. It is enabled by a positive young modulus, requires a straight reference configuration (curved initial poses can be set with qpos or keyframes), is compatible with edge equality constraints, and is integrated implicitly by the discrete integrator. Previously young was ignored for 1D flexes: existing models that set it now bend, and fail to compile if the cross-section is degenerate (zero radius with the default circle section), if a vertex joins a zero-length edge, or if the rod is not straight.

  3. 36d0df9a5, 897e3fcb1 Interpolated flexes (trilinear or quadratic dofs) now support self-collision, excluding elements in the same or neighboring cells.

  4. 39dd10f2d The default arena memory for flex models is now much smaller, sized from the flex mesh topology instead of nv^2. If the Newton solver runs out of arena memory it falls back to CG with a warning.

  5. mj_setConst now computes only quantities derived from other fields of mjModel, while the compiler alone resolves spec-level conventions:

  6. 55c1b585a, d6d41f324 The damping of position actuators from dampratio, the spring length of tendons from (-1, -1), and model statistics are now resolved only at compile time, not by mj_setConst. Set the model fields directly when editing a compiled model (mj_copyBack now copies tendon spring lengths back to the spec).

  7. c8362756d Constraint solvers now scale their termination criteria by the trace of the current inertia matrix (of the model or island) instead of mjModel.stat.meaninertia. Models solved with PGS, noslip or islands disabled can stop at slightly different iterations. The meaninertia attribute is deprecated and now emits a compile warning; remove it to migrate.

  8. abddec5b9 For body-based weld constraints without a specified relpose, the relative pose in qpos0 is now recomputed by mj_setConst when the model is modified after compilation (matching the second body's anchor in body-based connect constraints). The compiler marks such welds with a nonzero eq_data[11], and mjNEQDATA increased from 11 to 12.

[!WARNING] Breaking ABI changes

body-based welds that had no relpose at compile time. Zero eq_data[11] before calling mj_setConst to set the relative pose of such a weld directly.

Compiler

[!WARNING] Breaking API changes

  1. aad2e2982 mjs_fuseStatic and mjs_discardVisual now return the number of bodies fused or elements discarded, and -1 on error. Previously they returned 0 on success, so a caller could not tell whether the spec changed. In Python, MjSpec.fuse_static and MjSpec.discard_visual return the same number instead of None.

Migration: Test for an error with < 0 rather than != 0.

  1. 084828896 mjs_addTexture now takes a default class, like mjs_addMesh and mjs_addMaterial.

Migration: mjs_addTexture(spec) → mjs_addTexture(spec, NULL). MjSpec.add_texture is unchanged.

  1. 3576818f5, b0f206d04 Textures can be left by reference instead of being decoded into mjModel. With compiler/passthrough set to "textures", or texture/embed set to "false", a single-file texture is not read at compile time; the model holds its path instead of its pixels, so a scene that attaches many textured sub-models loads in a fraction of the memory and time. In addition, a compiled mjSpec no longer keeps the decoded pixels of its textures between compilations.

  2. 3576818f5 What the model holds: tex_adr is -1, tex_width and tex_height are 0, ntexdata excludes the texture, the resolved path is at tex_pathadr, and any authored content_type is at the new tex_contenttypeadr. Flipped, composite, six-file, procedural, buffer and in-memory textures stay embedded, as does any texture with embed "true".

  3. 1be762d0c Getting the pixels: mj_loadTexture decodes a texture of either kind, and mj_embedAssets returns a copy of the model with every by-reference texture loaded (which followed by mj_saveModel gives a hermetic MJB). Both are in Python as mujoco.mj_loadTexture and mujoco.mj_embedAssets.

  4. fd92ba1db Rendering: the built-in and Filament renderers load by-reference textures on demand, and Filament uploads each file once for all textures that share it. A file that fails to resolve produces a warning and an untextured material.

  5. 084828896 Textures can have default classes: mjsDefault has a texture member and texture takes a class.

  6. 4e9a2de2d Added mjs_dedupAssets (MjSpec.dedup_assets), which merges the textures and meshes of an mjSpec that would compile to the same asset, as those of a sub-model attached several times do: the first of each group is kept and every reference to the others is rewritten to it. Like mjs_fuseStatic, it returns the number of assets merged.

  7. 027cb3dd8 The asset paths in mjModel (paths at mesh_pathadr, hfield_pathadr, skin_pathadr and tex_pathadr) now store the resolved path or URI from which the compiler read the asset (combining the model file's directory and meshdir or texturedir with file, unless file is an absolute path or URI), so mju_openResource can open them directly even after attaching models with different asset directories. Code that prefixed these paths with its own directory should pass them to mju_openResource as is.

  8. 9f035384d Mesh polygon normals (mjModel.mesh_polynormal) are now computed from the whole polygon outline using Newell's method rather than the first three vertices (#3691).

Python bindings

  1. 08330629b Added a mujoco.batch (mujoco.readthedocs.io) module over the batch API: Batch(model, nsim) with live (nsim, ...) arrays from bind() and named views such as joint(name), per-simulation model fields from expand(), step, forward, reset, set_const and rollout with the GIL released, and jac and ray queries.

  2. 1313ef78e Added support for building the Python bindings with Bazel (initially covers the core bindings, without rendering or the viewer).

  3. 39b7193e8 Fixed several bugs in named access (data.actuator('a'), model.joint('j'), data.bind(...)), and the corresponding generated accessors in the JavaScript bindings:

    • Multi-control or multi-output actuators (such as orientation) now follow actuator_ctrladr and actuator_outadr with leading dimension ctrlnum or outnum, instead of reading a single row at the actuator index.

    • data.actuator('a').moment is now a read-only dense copy of the actuator's moment arm of shape (nv,) or (outnum, nv), instead of reading the sparse actuator_moment array as if it were dense.

    • Views of multi-column per-dof fields (cdof, cdof_dot, dof_dampingpoly) on joints after the first now index the right rows.

  4. 7cdc8857e Unallocated arena arrays of MjData (such as efm_* when the discrete integrator is not used, or island arrays when no islands are formed) are now filled with zeros, or -1 for index fields, instead of returning uninitialized memory.

Bug fixes

  1. Fixed several bugs in interpolated flexcomp elasticity:

    • 4bbc96957 Volume (solid) interpolated flexes whose first cell is empty (e.g. a trilinear flexcomp from a mesh that does not fill the corner of its bounding box) now retain their elasticity; previously elasticity was gated on the first cell's stiffness.

    • b0b20166d Editing a flex to remove a strain equality (e.g. from body.make_flex) and recompiling now recomputes stiffness instead of keeping the strain constraint eigenmodes.

    • 08bf94b18 Shell-mode interpolated flexes with elastic2d set to "stretch" or "both" now apply membrane stretch forces and implicit stiffness, and "bend" shells without strain constraints no longer allocate flex_stiffness.

  2. Fixed several bugs in the Filament renderer:

    • 5c7c1e3ae Textures now allocate mipmap levels (including sRGB textures), fixing minification aliasing.

    • e81c8aed4 Skins that share vertices across faces no longer fail with an index count mismatch (#3719).

    • 001aa3203 Material colors now apply only when an object has the default color, instead of overwriting custom object colors.

    • 6cfc76e32 Textures with an unsupported number of channels are now skipped with a warning, matching the classic renderer, instead of calling mju_error.

  3. Fixed several bugs on error paths which called mju_error while C++ objects or locks were held (an error handler that does not return, as in the Python bindings and the model compiler, skips C++ destructors):

    • 4cc38db84, 8c1e45559, 526583e5b Invalid configurations of the touch grid, cable and SDF plugins leaked more than 10 MB per failed compilation (they now fail plugin initialization with a warning); mju_getXMLDependencies and unknown material layer roles also leaked memory on invalid XML, and unsupported equality types in the XML writer are now reported as write errors instead of calling mju_error.

    • 4cc38db84 An error while compiling meshes or textures on the compiler's worker threads crashed the process, and a failed library load in mj_loadAllPluginLibraries left its mutex locked.

    • ae15ab978 mj_recompile freed the given mjData and called mju_error if a plugin failed to initialize, and did not delete the model and data on some other failures, contrary to its documentation.

Models

  1. 94483e166 The elastic mechanism example models now use 1D flex rods: the cantilever comparison of quadratic flexes adds a rod, and the elastic slider-crank and the tendon-loaded dipper arm are built from rods.
Source: README.md, updated 2026-10-22