MuJoCo XML  ·  .xml

MJCF, MuJoCo's model format

MJCF is the XML that MuJoCo reads: a robot, the world around it and everything the solver needs, in one file. Here is how it is put together, which defaults change the answer, what MuJoCo's error messages mean — and what 67 models of the MuJoCo Menagerie actually write, counted rather than recalled.

What MJCF is

"MuJoCo XML" and "MJCF" are the same thing: the modelling language MuJoCo compiles before it simulates anything. Where a URDF describes one robot as a flat list of links and joints, an MJCF describes a world — the robot, the floor, the lights, the motors and the solver's settings — with bodies nested inside one another, so the shape of the file is the shape of the machine.

Most of what makes MJCF different follows from one decision: it is written to be simulated. Motors are elements of their own with their own limits. Contact is configurable per shape. Closed chains, tendons and coupled joints have a place to live. And almost every attribute has a default, which is what makes real files short — and what makes a wrong assumption silent.

The same arm, in MJCF

The two-link arm from the URDF walkthrough, written the way MuJoCo wants it. It compiles in MuJoCo 3.11 as it stands.

two-link-arm.xml Open it in the viewer
<mujoco model="two_link_arm">
  <!-- Without this line every angle below is read in degrees. -->
  <compiler angle="radian"/>
  <option timestep="0.002" integrator="implicitfast"/>

  <!-- Defaults: said once, inherited by every joint in the file. -->
  <default>
    <joint damping="0.1"/>
  </default>

  <worldbody>
    <!-- A body with no joint is welded to its parent: here, the world. -->
    <body name="base">
      <inertial pos="0 0 0" mass="2.0" diaginertia="0.00412 0.00412 0.0049"/>
      <geom type="cylinder" size="0.07 0.05"/>

      <!-- Bodies nest. The joint lives inside the child it moves. -->
      <body name="arm" pos="0 0 0.05">
        <joint name="shoulder" type="hinge" axis="0 0 1" range="-1.57 1.57"/>
        <inertial pos="0.15 0 0" mass="0.8" diaginertia="0.000213 0.00611 0.00611"/>
        <geom type="box" size="0.15 0.02 0.02" pos="0.15 0 0"/>
      </body>
    </body>
  </worldbody>

  <!-- The motor is separate from the joint, with its own limits. -->
  <actuator>
    <motor name="shoulder" joint="shoulder" ctrlrange="-12 12"/>
  </actuator>
</mujoco>
  • Bodies nest. There is no joint element naming a parent and a child: the arm is inside the base, and its joint is inside the arm. pos on the body is where the URDF put the joint's origin.
  • Sizes are halves. A box of 0.15 0.02 0.02 is 30 × 4 × 4 cm, and a cylinder's second number is half its length.
  • The motor is separate from the joint. The URDF's 12 N·m effort becomes the motor's ctrlrange. The URDF's top speed has nowhere to go: MJCF keeps no velocity limit on a joint.
  • Defaults do the repetition. The damping is said once and every joint inherits it. Real files lean on this far harder than the example.
  • The first line matters most. Without angle="radian", the range below it would be ±1.57 degrees.

Defaults that change the answer

Each of these is what MuJoCo assumes when the file says nothing, checked by compiling a model that leaves it out. None of them produces a warning.

SettingDefaultWhat it does to you
angle on <compiler>degreerange="-1.57 1.57" is ±1.57°, not ±90°. 62 of the 67 Menagerie models switch to radian; a URDF's numbers pasted into a file that does not are wrong by a factor of 57.
euler and eulerseqxyz, about the turning axesAn MJCF euler is not a URDF rpy. The same three numbers give a different orientation unless eulerseq="XYZ" is set, which turns about fixed axes the way URDF does.
quatw x y zScalar first. ROS messages and SciPy write x y z w, so a quaternion copied across is a different rotation.
inertiafromgeomautoA body with no <inertial> is weighed from its geoms at 1000 kg/m³ — water. A 20 cm cube comes out at 8 kg. 26 of the 67 models rely on this somewhere.
type on <geom>sphereA geom given a size and no type is a ball, which looks deliberate in a render and is not.
contype, conaffinity1, 1Every geom collides with every other. Shapes meant only to be seen need contype="0" conaffinity="0"; 62 of the 67 models set it.
autolimitstrueA range alone makes a joint limited. Switch it off and a range without limited="true" stops the model loading.
timestep, integrator0.002 s, Euler34 of the 67 models choose implicitfast, which stays stable with stiff joints and high damping where Euler does not.
type and axis on <joint>hinge, 0 0 1A bare <joint/> is a hinge about Z, placed at the origin of the body it sits in.

What the MuJoCo Menagerie actually writes

The specification lists everything MJCF can say. This is what 67 models of the MuJoCo Menagerie — the robots in the catalogue here — do say: each robot file read with its includes, and a model counted once however often it uses a feature.

FeatureModelsWhy it is there
Default classes, <default class>66 of 67Seven per model is typical. Real MJCF is written as defaults plus exceptions.
Mesh folder set with meshdir or assetdir63 of 67Mesh paths are relative to it, not to the file.
angle="radian"62 of 67The five that keep degrees: two drones, a depth camera, the Shadow hand and Cassie.
Display-only geoms, contype="0"62 of 67Detailed meshes to look at, simple shapes to collide.
Joint armature51 of 67Rotor inertia reflected through the gearbox — invisible in a URDF.
Keyframes, <keyframe>41 of 67Usually a standing pose to start from.
Position actuators, <position>39 of 67Against 11 with plain torque <motor> and 16 with <general>.
Contact exclusions, <exclude>35 of 67Neighbouring parts that would otherwise push each other apart.
A floating base, <freejoint>29 of 67Legged robots, hands on a free base, drones.
Bodies with no <inertial>26 of 67Mass taken from the geoms at the default density.
Equality constraints22 of 67Coupled joints in 21 of them, closed chains in 7. A URDF mimic joint covers the first; the second has no URDF form at all.
Ball joints, type="ball"1 of 67Cassie's leg linkage, the only one.

Two things stand out. Nearly every model overrides the angle unit and leans on default classes, so a file written without either looks nothing like the ones that simulate well. And a third of them weigh some of their bodies from the geometry, which is invisible in the file and only appears as a number after MuJoCo compiles it.

MuJoCo's error messages, and what they mean

MuJoCo refuses a model whole and says why in one line. These are the lines, exactly as MuJoCo 3.11 prints them, from models written to trigger each one.

mass and inertia of moving bodies must be larger than mjMINVAL
A body with a joint and nothing to weigh: no geom, no <inertial>, or an inertial of zero. The usual source is a URDF link that only exists to hold a frame. Give it a gram and a small inertia, or fuse it into its parent.
free joint can only be used on top level
A <freejoint> inside a nested body. A free joint floats a body in the world, so it belongs on a body directly under <worldbody>.
inertia must satisfy A + B >= C; use 'balanceinertia' to fix
The principal moments describe no rigid body that can exist. balanceinertia makes the error go away by changing the numbers; the honest fix is the tensor, which the viewer draws as an ellipsoid so the bad one stands out.
joint has `range` but not `limited`
autolimits was switched off and a joint states a range without limited="true". Turn autolimits back on, or say limited explicitly.
Schema violation: unrecognized element
An element MJCF does not have — often a URDF habit such as <link>. The message names the element and the line.
Schema violation: unrecognized attribute: 'mass'
Mass on a <body>. In MJCF it belongs to <inertial> or comes from the geoms.
repeated name 'a' in body
Names are unique per kind of element: two bodies cannot share one, although a body and a joint can.
Error opening file 'part.stl'
A mesh path that does not resolve. It is taken relative to meshdir, or assetdir, or the model file — in that order. The viewer lists every file it could not find before you get this far.

MJCF and URDF, both ways

The two formats describe the same robot with different vocabularies, and the converter says what changes in each direction rather than leaving you to find out in simulation:

  • URDF to MJCF adds what a description has no place for when you ask for a physics model — a floor, a light, a free base for a robot with legs — and moves each joint's effort onto a motor. Velocity limits have nowhere to go.
  • MJCF to URDF flattens the nesting into links and joints, turns coupled joints into mimic joints and reads the motor ratings back from the actuators. Capsules become cylinders; closed chains, tendons and solver settings are listed as lost.
  • MJCF to SDF and MJCF to USD take the same robot to Gazebo and to Isaac Sim.

Common questions

What is MJCF?

MuJoCo's native model format: an XML file, usually ending in .xml, that describes bodies, joints, geometry, actuators, sensors and the simulation settings around them. "MuJoCo XML" and "MJCF" are the same thing.

How is MJCF different from URDF?

A URDF is one robot as a flat list of links and joints; an MJCF is a world, with bodies nested inside each other and each joint written inside the body it moves. MJCF also holds what URDF has no place for: motors as separate elements, contact settings, closed chains, tendons and the solver's own options.

Can MuJoCo load a URDF directly?

Yes — MuJoCo compiles URDF, and by default merges links held by fixed joints and drops visual geometry. What it cannot do is add what a URDF never said: motors, contact settings, a floating base. Converting with the URDF to MJCF converter writes those choices into a file you can read and change.

How do I convert MJCF to URDF?

With the MJCF to URDF converter. Bodies become links, joints keep their limits, coupled joints become mimic joints, and the motor ratings are recovered from the actuators. What does not survive is said in the file: capsules become cylinders, and closed chains, tendons and solver settings have nowhere to go.

Which programs read MJCF besides MuJoCo?

Anything built on MuJoCo's compiler reads it unchanged — MJX on JAX and MuJoCo Warp among them. Isaac Sim has an MJCF importer, and Genesis loads MJCF as well as URDF. For the rest there is a converter to URDF, SDF and USD.

Where can I find MJCF robot models?

The MuJoCo Menagerie is the curated collection, and every one of its robots in the catalogue here opens in a tab: simulate it, look inside it, or download it as MJCF or URDF with its meshes.

Where to go next

  • The viewer — open an MJCF and read it: the body tree, joints, which geoms collide
  • MuJoCo in the browser — the same files, simulated, with nothing to install
  • MJCF models — the Menagerie robots, one click from a running simulation