Continuous control environments and MuJoCo Python bindings for physics-based simulation and Reinforcement Learning
—
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.
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
"""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)
"""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."""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
"""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}")# 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')# 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()# 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# 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# 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