Implementation:Google deepmind Dm control MJCF Physics
| Metadata | |
|---|---|
| Knowledge Sources | dm_control |
| Domains | Physics Simulation, Robotics, Simulation Runtime |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
Concrete tool for compiling MJCF model trees into executable MuJoCo physics simulations via mjcf.Physics.from_mjcf_model() and accessing element-level simulation data through physics.bind().
Description
mjcf.Physics is a subclass of mujoco.Physics that adds MJCF-aware features. Its primary entry points are:
Physics.from_mjcf_model(mjcf_model)
A class method that compiles an mjcf.RootElement into a live physics simulation:
- Calls
mjcf_model.to_xml_string()to serialize the model with a debug context for error reporting. - Calls
mjcf_model.get_assets()to collect all binary assets (meshes, textures, etc.) into a{filename: bytes}dictionary. - Delegates to
Physics.from_xml_string(xml_string, assets=assets), which invokes MuJoCo's C compiler. - If compilation fails, the debug context processes the exception to provide source-level error information pointing back to the Python code that created the offending element.
physics.reload_from_mjcf_model(mjcf_model)
Re-compiles the model in place, preserving the Python Physics object identity. This is useful when the MJCF model has been modified (e.g., adding or removing elements) and the physics needs to reflect those changes.
physics.bind(mjcf_elements)
Creates a Binding object that maps one or more MJCF elements to their data in the compiled physics. The binding:
- Determines the MuJoCo namespace (e.g.,
'geom','joint','body') from the element's spec. - Uses the element's
full_identifier(the scoped name) as the named index into MuJoCo's data arrays. - Returns a
Bindingobject whose attributes correspond to MuJoCo data fields with type-specific prefixes stripped (e.g.,geom_posbecomespos,jnt_rangebecomesrange). - Caches bindings for reuse; subsequent calls with the same element(s) return the cached binding.
Binding attribute access returns SynchronizingArrayWrapper objects for array-valued fields. These are NumPy array views that, when written to, automatically update the backing MuJoCo data and mark derived quantities as dirty. Reading a derived attribute from any binding triggers a lazy forward() call to bring the physics state up to date.
The Physics object tracks dirtiness via an is_dirty flag and a mark_as_dirty() method. The forward() override clears the dirty flag after recomputing.
Usage
Use from_mjcf_model to compile a model. Use bind to read and write simulation state for specific elements. Use reload_from_mjcf_model after structural changes.
Code Reference
| Property | Value |
|---|---|
| Source Location | dm_control/mjcf/physics.py:L434-665 (Physics class), dm_control/mjcf/physics.py:L242-401 (Binding class), dm_control/mjcf/physics.py:L155-240 (SynchronizingArrayWrapper)
|
| Signature (from_mjcf_model) | Physics.from_mjcf_model(cls, mjcf_model) -> Physics
|
| Signature (reload_from_mjcf_model) | reload_from_mjcf_model(self, mjcf_model) -> None
|
| Signature (bind) | bind(self, mjcf_elements) -> Binding
|
| Import | from dm_control import mjcf
|
I/O Contract
Inputs (from_mjcf_model):
| Parameter | Type | Description |
|---|---|---|
mjcf_model |
mjcf.RootElement |
The root of a fully assembled MJCF model tree. |
Inputs (bind):
| Parameter | Type | Description |
|---|---|---|
mjcf_elements |
mjcf.Element or iterable of mjcf.Element |
One or more elements of the same type (e.g., all joints, all geoms). Must not be None.
|
Outputs:
| Output | Type | Description |
|---|---|---|
| return value (from_mjcf_model) | mjcf.Physics |
A live physics simulation compiled from the model. |
| return value (bind) | Binding |
An object whose attributes provide read/write access to MuJoCo data fields for the bound element(s). Attribute names have type-specific prefixes stripped. |
Usage Examples
from dm_control import mjcf
# Build a simple model
model = mjcf.RootElement(model='pendulum')
body = model.worldbody.add('body', name='link', pos=[0, 0, 0.5])
body.add('geom', type='capsule', size=[0.04, 0.2])
joint = body.add('joint', name='hinge', type='hinge', axis=[0, 1, 0])
model.actuator.add('motor', name='torque', joint='hinge')
# Compile to physics
physics = mjcf.Physics.from_mjcf_model(model)
# Bind elements to read/write simulation data
joint_binding = physics.bind(joint)
# Read joint position
print(joint_binding.qpos) # e.g., array([0.])
# Set joint position and read derived body position
joint_binding.qpos = 1.57
body_binding = physics.bind(body)
print(body_binding.xpos) # Triggers forward() to recalculate
# Bind multiple elements at once
all_geoms = model.find_all('geom')
geom_binding = physics.bind(all_geoms)
print(geom_binding.pos) # Array of all geom positions
# Modify model and reload
body.add('geom', name='extra', type='sphere', size=[0.05], pos=[0, 0, 0.3])
physics.reload_from_mjcf_model(model)
# Step the simulation
physics.step()
print(physics.bind(joint).qpos)