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

physics.mddocs/

Physics Simulation

Low-level MuJoCo physics simulation interface providing direct access to the physics engine, rendering capabilities, and comprehensive state management. Enables fine-grained control over simulation parameters, dynamics, and visualization.

Capabilities

Physics Class

Main interface to MuJoCo simulation with model loading, stepping, and state access.

class Physics:
    """
    Encapsulates a MuJoCo model and simulation state.
    
    A MuJoCo model is typically defined by an MJCF XML file. Provides 
    stepping, control, rendering, and state access functionality.
    """
    
    @classmethod
    def from_xml_path(cls, xml_path: str) -> 'Physics':
        """
        Create Physics instance from XML file path.
        
        Parameters:
        - xml_path: Path to MJCF XML file
        
        Returns:
        Physics instance with loaded model
        """
    
    @classmethod  
    def from_xml_string(cls, xml_string: str) -> 'Physics':
        """
        Create Physics instance from XML string.
        
        Parameters:
        - xml_string: MJCF XML content as string
        
        Returns:
        Physics instance with loaded model
        """
        
    @classmethod
    def from_binary_path(cls, mjb_path: str) -> 'Physics':
        """
        Create Physics instance from MJB binary file.
        
        Parameters:
        - mjb_path: Path to compiled MuJoCo binary file
        
        Returns:
        Physics instance with loaded model
        """
    
    def step(self, nstep: int = 1) -> None:
        """
        Advance simulation by specified number of timesteps.
        
        Parameters:
        - nstep: Number of simulation steps to advance (default: 1)
        """
    
    def forward(self) -> None:
        """Compute forward dynamics without advancing time."""
        
    def set_control(self, control: np.ndarray) -> None:
        """
        Set control signals for actuators.
        
        Parameters:
        - control: Array of control values matching actuator count
        """
        
    def reset(self) -> None:
        """Reset simulation to initial state."""
        
    def copy(self, share_model: bool = False) -> 'Physics':
        """
        Create copy of Physics instance.
        
        Parameters:
        - share_model: Whether to share model data (default: False)
        
        Returns:
        New Physics instance
        """

Rendering and Cameras

Camera system for generating images and querying scene information.

class Camera:
    """Camera for rendering views and scene queries."""
    
    def render(self, depth: bool = False, segmentation: bool = False) -> np.ndarray:
        """
        Render camera view to numpy array.
        
        Parameters:
        - depth: Return depth buffer instead of RGB (default: False)  
        - segmentation: Return segmentation mask (default: False)
        
        Returns:
        Rendered image as numpy array
        """
        
    def select(self, cursor_position: tuple) -> 'Selected':
        """
        Query objects at screen position.
        
        Parameters:
        - cursor_position: (x, y) screen coordinates
        
        Returns:
        Selected object information
        """

class MovableCamera(Camera):
    """Camera with adjustable pose and parameters."""
    
    def move(self, azimuth: float = None, elevation: float = None, 
             distance: float = None, lookat: np.ndarray = None) -> None:
        """
        Adjust camera pose.
        
        Parameters:
        - azimuth: Horizontal rotation in degrees
        - elevation: Vertical rotation in degrees  
        - distance: Distance from target
        - lookat: 3D target position
        """

# Physics rendering method
def render(self, height: int, width: int, camera_id: int = 0, 
           depth: bool = False, segmentation: bool = False, 
           scene_option: object = None) -> np.ndarray:
    """
    Render view from specified camera.
    
    Parameters:
    - height, width: Image dimensions in pixels
    - camera_id: Camera index or name (default: 0)
    - depth: Return depth buffer (default: False)
    - segmentation: Return segmentation mask (default: False)
    - scene_option: Optional rendering options
    
    Returns:
    Rendered image as numpy array with shape (height, width, channels)
    """

State Access

Named access to model and simulation data structures.

class NamedView:
    """Named access to MuJoCo data arrays."""
    
    model: object  # Named model data (e.g., body_mass, geom_size)
    data: object   # Named simulation data (e.g., qpos, qvel, ctrl)

# Physics named data access
@property  
def named(self) -> NamedView:
    """
    Named access to model and data arrays.
    
    Returns:
    NamedView with model and data attributes for named element access
    
    Example:
    >>> physics.named.data.qpos['joint_name'] = 0.5
    >>> mass = physics.named.model.body_mass['body_name']
    """

@property
def model(self) -> object:
    """Access to MuJoCo model structure."""
    
@property  
def data(self) -> object:
    """Access to MuJoCo simulation data."""
    
def timestep(self) -> float:
    """Get simulation timestep duration."""
    
@property
def time(self) -> float:
    """Current simulation time."""

Contextual Operations

Context managers for safe state manipulation.

def reset_context(self) -> object:
    """
    Context manager for safe state modification.
    
    Returns:
    Context manager that restores state on exit
    
    Example:
    >>> with physics.reset_context():
    ...     physics.named.data.qpos[:] = 0  # Modify state
    ...     physics.forward()  # Update derived quantities
    # State automatically restored on exit
    """

Usage Examples

Basic Simulation

from dm_control.mujoco import Physics
import numpy as np

# Load model
physics = Physics.from_xml_path('/path/to/model.xml')

# Simulation loop
for _ in range(1000):
    # Set random controls
    control = np.random.randn(physics.model.nu)
    physics.set_control(control)
    
    # Step simulation
    physics.step()
    
    # Access state
    positions = physics.named.data.qpos
    velocities = physics.named.data.qvel
    
    print(f"Time: {physics.time:.3f}")

Rendering

# Basic rendering
rgb_array = physics.render(height=240, width=320, camera_id=0)

# Depth rendering  
depth_array = physics.render(height=240, width=320, depth=True)

# Multiple camera views
front_view = physics.render(240, 320, camera_id='front_camera')
side_view = physics.render(240, 320, camera_id='side_camera')

Camera Control

# Create movable camera
camera = physics.render_camera(width=320, height=240)
if hasattr(camera, 'move'):
    # Adjust camera pose
    camera.move(azimuth=45, elevation=30, distance=2.0)
    
# Render from adjusted pose
image = camera.render()

State Manipulation

# Safe state modification
with physics.reset_context():
    # Set joint positions
    physics.named.data.qpos['hip_joint'] = 0.5
    physics.named.data.qpos['knee_joint'] = -1.0
    
    # Update derived quantities
    physics.forward()
    
    # Access derived data
    com_position = physics.named.data.subtree_com['torso']
# State automatically restored after context

Named Data Access

# Access joint data by name
joint_names = physics.named.model.joint_names
for name in joint_names:
    position = physics.named.data.qpos[name]
    velocity = physics.named.data.qvel[name]
    print(f"{name}: pos={position:.3f}, vel={velocity:.3f}")

# Access body properties
body_masses = physics.named.model.body_mass
torso_mass = body_masses['torso']

# Access sensor readings
if hasattr(physics.named.data, 'sensordata'):
    sensor_values = physics.named.data.sensordata

Types

# Selection result from camera queries
Selected = namedtuple('Selected', ['body', 'geom', 'flex', 'skin', 'world_position'])

# Camera pose specification
Pose = namedtuple('Pose', ['lookat', 'distance', 'azimuth', 'elevation'])

# Context containers
Contexts = namedtuple('Contexts', ['gl', 'mujoco'])

# Named index structures  
NamedIndexStructs = namedtuple('NamedIndexStructs', ['model', 'data'])

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