Workflow:Google deepmind Dm control MJCF Model Composition
| Knowledge Sources | |
|---|---|
| Domains | Model_Building, Physics_Simulation, Robotics |
| Last Updated | 2026-02-15 12:00 GMT |
Overview
End-to-end process for programmatically creating, parsing, modifying, and composing MuJoCo MJCF physics models using the PyMJCF Python object model.
Description
This workflow covers the standard procedure for building MuJoCo physics models programmatically using the PyMJCF library. PyMJCF provides a DOM-like Python object model for the MJCF XML modeling language, enabling users to create models from scratch, parse existing XML files, modify model attributes, and compose multiple models into a single simulation. Key features include automatic name scoping (disambiguation of duplicated names from multiple models), schema-driven validation, asset management, debug mode with source tracing, and export to XML or zip archives. The output is a compiled MuJoCo Physics object ready for simulation.
Usage
Execute this workflow when you need to programmatically construct or modify MuJoCo physics models, compose multiple MJCF models into a larger one, or create parametric model generators. This is the foundation for the Composer framework's Entity and Arena systems.
Execution Steps
Step 1: Create or Parse an MJCF Model
Begin by creating a new empty model via RootElement() or parsing an existing MJCF XML file via from_path(), from_xml_string(), or from_file(). The RootElement represents the root mujoco element and provides access to all top-level sections (worldbody, actuator, sensor, asset, default, etc.). Parsing creates a complete Python object tree mirroring the XML structure.
Key considerations:
- RootElement() creates an empty model with a model name parameter
- from_path() parses an XML file and resolves relative asset paths
- from_xml_string() parses XML from a string (useful for testing)
- from_file() parses from an open file handle
- All parsed elements become fully editable Python objects
- Schema validation is performed automatically during construction
Step 2: Build the Model Structure
Add elements to the model tree using the add() method on parent elements. Elements include bodies (rigid bodies with position/orientation), geoms (visual/collision shapes), joints (degrees of freedom), sites (reference frames), actuators, sensors, and assets (meshes, textures, materials). Each element's attributes are passed as keyword arguments matching the MJCF schema.
Key considerations:
- worldbody is the root body element; add child bodies to create kinematic chains
- Geom types include box, sphere, capsule, cylinder, ellipsoid, mesh, plane
- Joint types include hinge, slide, ball, free
- Sites serve as attachment points and reference frames
- Default classes provide attribute inheritance for reducing repetition
- All attributes are strongly typed and validated against the MJCF schema
Step 3: Compose Multiple Models
Attach child models to parent models using the attach() method on site elements. PyMJCF automatically handles name scoping by prefixing child element names with the parent's namespace, preventing name collisions when multiple instances of the same model are used. The attachment creates a physical connection between the parent site and the child model's root body.
Key considerations:
- attach() takes a child RootElement and creates a namescoped subtree
- Names are automatically prefixed to prevent collisions (e.g., left_arm/shoulder)
- Multiple instances of the same model can be attached without manual renaming
- Attachment frames provide the physical connection point between models
- include_copy() copies elements between models without attachment semantics
- References (e.g., material names, default classes) are resolved across model boundaries
Step 4: Modify and Parameterize
Modify model attributes programmatically by setting Python properties on elements. This enables parametric model generation where dimensions, masses, colors, joint ranges, and actuator gains can be computed from parameters. Elements can be found by traversal, queried by type, or accessed via stored references.
Key considerations:
- Element attributes are directly settable as Python properties
- Array attributes accept Python lists or numpy arrays
- Reference attributes accept element objects (not just name strings)
- find() and find_all() search the element tree by type and name
- The all_children() method iterates over child elements
- Removing elements is done via remove() or setting attributes to None
Step 5: Compile to Physics Simulation
Compile the MJCF model into a MuJoCo Physics object using mjcf.Physics.from_mjcf_model(). The compilation serializes the Python object tree to XML, loads it into MuJoCo, and creates the Physics wrapper. The Physics object provides named indexing for reading and writing simulation state using MJCF element references rather than raw array indices.
Key considerations:
- Physics.from_mjcf_model() handles XML generation and MuJoCo compilation
- The Physics.bind() method connects MJCF elements to their simulation data
- Named indexing allows accessing data like physics.bind(joint).qpos
- Recompilation is needed if the model structure changes (not just attribute values)
- Debug mode records Python source locations to help trace compilation errors
- Assets (meshes, textures) are automatically bundled during compilation
Step 6: Export the Model
Optionally export the MJCF model to XML files for sharing, inspection, or use with other MuJoCo tools. Export options include writing the XML string directly, exporting with assets to a directory, or packaging as a zip archive. The export preserves all asset references and can flatten the model hierarchy for standalone use.
Key considerations:
- to_xml_string() returns the complete XML as a string
- export_with_assets() writes XML and binary assets to a directory
- export_with_assets_as_zip() packages everything into a single zip file
- Asset paths are adjusted to be relative to the export directory
- The exported model can be loaded by standard MuJoCo tools and viewers