CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dm-control

Continuous control environments and MuJoCo Python bindings for physics-based simulation and Reinforcement Learning

Pending
Overview
Eval results
Files

mjcf.mddocs/

MJCF Model Building

Object-oriented library for creating, manipulating, and composing MuJoCo MJCF (MuJoCo XML Configuration Format) models programmatically. Provides high-level abstractions for model elements while maintaining full compatibility with MuJoCo's XML format and enabling complex model composition.

Capabilities

Model Loading and Parsing

Load MJCF models from various sources with full element hierarchy support.

def from_xml_string(xml_string: str) -> 'RootElement':
    """
    Parse MJCF model from XML string.
    
    Parameters:  
    - xml_string: Complete MJCF XML content as string
    
    Returns:
    RootElement representing the parsed model
    
    Example:
    >>> xml = '<mujoco><worldbody><body name="box"/></worldbody></mujoco>'
    >>> model = mjcf.from_xml_string(xml)
    """

def from_path(path: str) -> 'RootElement':
    """
    Parse MJCF model from file path.
    
    Parameters:
    - path: Path to MJCF XML file
    
    Returns:
    RootElement representing the loaded model
    
    Example:
    >>> model = mjcf.from_path('/path/to/model.xml')
    """

def from_file(file_object) -> 'RootElement':
    """
    Parse MJCF model from file object.
    
    Parameters:
    - file_object: Open file object containing MJCF XML
    
    Returns:  
    RootElement representing the parsed model
    """

Model Elements

Core classes for representing MJCF model structure and hierarchy.

class RootElement:
    """
    Root element of an MJCF model representing the complete model hierarchy.
    
    Provides access to all model components and enables model-level operations
    like compilation, attachment, and asset management.
    """
    
    @property
    def worldbody(self) -> 'Element':
        """Access to the worldbody element."""
        
    @property  
    def asset(self) -> 'Element':
        """Access to the asset element."""
        
    @property
    def actuator(self) -> 'Element':
        """Access to actuator definitions."""
        
    @property
    def sensor(self) -> 'Element':  
        """Access to sensor definitions."""
        
    def find_all(self, tag: str) -> list:
        """
        Find all elements with specified tag.
        
        Parameters:
        - tag: Element tag name to search for
        
        Returns:
        List of matching Element instances
        """
        
    def compile_model(self) -> 'Physics':
        """
        Compile MJCF model to Physics instance.
        
        Returns:
        Physics instance ready for simulation
        """

class Element:
    """
    Base class for MJCF elements supporting attribute access and hierarchy.
    
    Represents individual MJCF elements with dynamic attribute access,
    parent-child relationships, and element-specific operations.
    """
    
    @property
    def tag(self) -> str:
        """Element tag name."""
        
    @property
    def parent(self) -> 'Element':
        """Parent element in hierarchy."""
        
    def add(self, tag: str, **attributes) -> 'Element':
        """
        Add child element with specified tag and attributes.
        
        Parameters:
        - tag: Child element tag name
        - **attributes: Element attributes as keyword arguments
        
        Returns:
        Newly created child Element
        
        Example:
        >>> body = worldbody.add('body', name='box', pos=[0, 0, 1])
        >>> geom = body.add('geom', type='box', size=[0.1, 0.1, 0.1])
        """
        
    def remove(self) -> None:
        """Remove this element from parent."""
        
    def find(self, tag: str, name: str = None) -> 'Element':
        """
        Find first child element matching criteria.
        
        Parameters:
        - tag: Element tag to search for
        - name: Optional name attribute to match
        
        Returns:
        First matching Element or None
        """
        
    def find_all(self, tag: str) -> list:
        """
        Find all child elements with specified tag.
        
        Parameters:
        - tag: Element tag to search for
        
        Returns:
        List of matching child Elements
        """

Asset Management

Handle external assets like meshes, textures, and materials.

class Asset:
    """
    Represents MJCF asset with file path and metadata.
    
    Handles asset file paths, automatic copying, and asset referencing
    within MJCF models.
    """
    
    @property
    def path(self) -> str:
        """Asset file path."""
        
    @property
    def prefix(self) -> str:
        """Asset name prefix for namespacing."""

def export_with_assets(model: 'RootElement', out_dir: str, 
                      model_filename: str = 'model.xml') -> None:
    """
    Export model with all referenced assets to directory.
    
    Parameters:
    - model: RootElement to export
    - out_dir: Output directory path
    - model_filename: Name for main model file (default: 'model.xml')
    
    Creates directory containing model XML and all asset files with
    correct relative paths preserved.
    """

def export_with_assets_as_zip(model: 'RootElement', zip_path: str,
                             model_filename: str = 'model.xml') -> None:
    """
    Export model with assets as ZIP archive.
    
    Parameters:
    - model: RootElement to export  
    - zip_path: Output ZIP file path
    - model_filename: Name for main model file (default: 'model.xml')
    
    Creates ZIP archive containing model and all assets.
    """

Model Composition and Attachment

Tools for combining and modifying MJCF models.

def get_attachment_frame(element: 'Element') -> 'Element':
    """
    Get attachment frame for element composition.
    
    Parameters: 
    - element: Element to get attachment frame for
    
    Returns:
    Element representing the attachment frame
    """

def get_frame_freejoint(frame: 'Element') -> 'Element':
    """
    Get free joint associated with frame.
    
    Parameters:
    - frame: Frame element
    
    Returns:
    Associated free joint Element or None
    """

def get_frame_joints(frame: 'Element') -> list:
    """
    Get all joints associated with frame.
    
    Parameters:
    - frame: Frame element
    
    Returns:
    List of joint Elements
    """

def get_freejoint(body: 'Element') -> 'Element':
    """
    Get free joint for body element.
    
    Parameters:
    - body: Body element
    
    Returns:
    Associated free joint Element or None
    """

def commit_defaults(root: 'RootElement') -> None:
    """
    Commit default values throughout model hierarchy.
    
    Parameters:
    - root: Root element to process
    
    Applies default values to all elements recursively.
    """

Constants and Utilities

PREFIX_SEPARATOR: str
    """Separator used in element name prefixing for model composition."""

class Physics:
    """MJCF-specific physics instance with enhanced model access."""
    
    def bind(self, element: 'Element') -> object:
        """
        Bind MJCF element to physics data.
        
        Parameters:
        - element: MJCF element to bind
        
        Returns:
        Bound physics data object
        """

Usage Examples

Creating Models Programmatically

from dm_control import mjcf

# Create new model
model = mjcf.RootElement()

# Add basic structure  
worldbody = model.worldbody

# Create a simple pendulum
pendulum_body = worldbody.add('body', name='pendulum', pos=[0, 0, 1])
pendulum_body.add('joint', name='hinge', type='hinge', axis=[0, 1, 0])
pendulum_body.add('geom', name='bob', type='sphere', size=[0.05], 
                  rgba=[1, 0, 0, 1])

# Add actuator
model.actuator.add('motor', name='motor', joint='hinge', gear=[1])

# Compile to physics
physics = model.compile_model()

Loading and Modifying Models

# Load existing model
model = mjcf.from_path('/path/to/robot.xml')

# Find and modify elements
arm = model.find('body', name='arm')
if arm:
    # Add new sensor
    arm.add('site', name='wrist_site', pos=[0, 0, 0.1])
    model.sensor.add('touch', name='wrist_sensor', site='wrist_site')

# Add new actuator
model.actuator.add('position', name='new_actuator', 
                   joint='elbow_joint', kp=100)

Model Composition

# Load base robot
robot = mjcf.from_path('/path/to/base_robot.xml')

# Load tool model
tool = mjcf.from_path('/path/to/tool.xml')

# Get attachment point
attachment_frame = robot.find('site', name='end_effector')

# Attach tool to robot (conceptual - actual attachment may require 
# more complex operations depending on model structure)
if attachment_frame:
    # This would typically involve more complex attachment logic
    pass

Asset Handling

# Create model with assets
model = mjcf.RootElement()

# Add mesh asset
model.asset.add('mesh', name='custom_mesh', file='path/to/mesh.stl')

# Use asset in geometry
body = model.worldbody.add('body', name='custom_body')
body.add('geom', name='mesh_geom', type='mesh', mesh='custom_mesh')

# Export with assets
mjcf.export_with_assets(model, '/output/directory/')

# Or export as ZIP
mjcf.export_with_assets_as_zip(model, '/output/model.zip')

Advanced Element Operations

# Create complex hierarchy
model = mjcf.from_path('/path/to/base.xml')

# Find all bodies
bodies = model.find_all('body')
for body in bodies:
    print(f"Body: {body.name}, Mass: {body.get('mass', 'default')}")

# Add sensors to all bodies
for i, body in enumerate(bodies):
    if body.name:  # Only named bodies
        site_name = f"{body.name}_site"
        sensor_name = f"{body.name}_sensor"
        
        body.add('site', name=site_name, pos=[0, 0, 0])
        model.sensor.add('accelerometer', name=sensor_name, site=site_name)

# Commit defaults to finalize
mjcf.commit_defaults(model)

Physics Integration

# Create model and compile
model = mjcf.from_path('/path/to/model.xml')
physics = model.compile_model()

# Bind MJCF elements to physics data
hinge_joint = model.find('joint', name='hinge')
if hinge_joint:
    joint_data = physics.bind(hinge_joint)
    # Use bound data for direct physics access

Install with Tessl CLI

npx tessl i tessl/pypi-dm-control

docs

composer.md

index.md

mjcf.md

physics.md

suite.md

viewer.md

tile.json