0
# Physics Simulation
1
2
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.
3
4
## Capabilities
5
6
### Physics Class
7
8
Main interface to MuJoCo simulation with model loading, stepping, and state access.
9
10
```python { .api }
11
class Physics:
12
"""
13
Encapsulates a MuJoCo model and simulation state.
14
15
A MuJoCo model is typically defined by an MJCF XML file. Provides
16
stepping, control, rendering, and state access functionality.
17
"""
18
19
@classmethod
20
def from_xml_path(cls, xml_path: str) -> 'Physics':
21
"""
22
Create Physics instance from XML file path.
23
24
Parameters:
25
- xml_path: Path to MJCF XML file
26
27
Returns:
28
Physics instance with loaded model
29
"""
30
31
@classmethod
32
def from_xml_string(cls, xml_string: str) -> 'Physics':
33
"""
34
Create Physics instance from XML string.
35
36
Parameters:
37
- xml_string: MJCF XML content as string
38
39
Returns:
40
Physics instance with loaded model
41
"""
42
43
@classmethod
44
def from_binary_path(cls, mjb_path: str) -> 'Physics':
45
"""
46
Create Physics instance from MJB binary file.
47
48
Parameters:
49
- mjb_path: Path to compiled MuJoCo binary file
50
51
Returns:
52
Physics instance with loaded model
53
"""
54
55
def step(self, nstep: int = 1) -> None:
56
"""
57
Advance simulation by specified number of timesteps.
58
59
Parameters:
60
- nstep: Number of simulation steps to advance (default: 1)
61
"""
62
63
def forward(self) -> None:
64
"""Compute forward dynamics without advancing time."""
65
66
def set_control(self, control: np.ndarray) -> None:
67
"""
68
Set control signals for actuators.
69
70
Parameters:
71
- control: Array of control values matching actuator count
72
"""
73
74
def reset(self) -> None:
75
"""Reset simulation to initial state."""
76
77
def copy(self, share_model: bool = False) -> 'Physics':
78
"""
79
Create copy of Physics instance.
80
81
Parameters:
82
- share_model: Whether to share model data (default: False)
83
84
Returns:
85
New Physics instance
86
"""
87
```
88
89
### Rendering and Cameras
90
91
Camera system for generating images and querying scene information.
92
93
```python { .api }
94
class Camera:
95
"""Camera for rendering views and scene queries."""
96
97
def render(self, depth: bool = False, segmentation: bool = False) -> np.ndarray:
98
"""
99
Render camera view to numpy array.
100
101
Parameters:
102
- depth: Return depth buffer instead of RGB (default: False)
103
- segmentation: Return segmentation mask (default: False)
104
105
Returns:
106
Rendered image as numpy array
107
"""
108
109
def select(self, cursor_position: tuple) -> 'Selected':
110
"""
111
Query objects at screen position.
112
113
Parameters:
114
- cursor_position: (x, y) screen coordinates
115
116
Returns:
117
Selected object information
118
"""
119
120
class MovableCamera(Camera):
121
"""Camera with adjustable pose and parameters."""
122
123
def move(self, azimuth: float = None, elevation: float = None,
124
distance: float = None, lookat: np.ndarray = None) -> None:
125
"""
126
Adjust camera pose.
127
128
Parameters:
129
- azimuth: Horizontal rotation in degrees
130
- elevation: Vertical rotation in degrees
131
- distance: Distance from target
132
- lookat: 3D target position
133
"""
134
135
# Physics rendering method
136
def render(self, height: int, width: int, camera_id: int = 0,
137
depth: bool = False, segmentation: bool = False,
138
scene_option: object = None) -> np.ndarray:
139
"""
140
Render view from specified camera.
141
142
Parameters:
143
- height, width: Image dimensions in pixels
144
- camera_id: Camera index or name (default: 0)
145
- depth: Return depth buffer (default: False)
146
- segmentation: Return segmentation mask (default: False)
147
- scene_option: Optional rendering options
148
149
Returns:
150
Rendered image as numpy array with shape (height, width, channels)
151
"""
152
```
153
154
### State Access
155
156
Named access to model and simulation data structures.
157
158
```python { .api }
159
class NamedView:
160
"""Named access to MuJoCo data arrays."""
161
162
model: object # Named model data (e.g., body_mass, geom_size)
163
data: object # Named simulation data (e.g., qpos, qvel, ctrl)
164
165
# Physics named data access
166
@property
167
def named(self) -> NamedView:
168
"""
169
Named access to model and data arrays.
170
171
Returns:
172
NamedView with model and data attributes for named element access
173
174
Example:
175
>>> physics.named.data.qpos['joint_name'] = 0.5
176
>>> mass = physics.named.model.body_mass['body_name']
177
"""
178
179
@property
180
def model(self) -> object:
181
"""Access to MuJoCo model structure."""
182
183
@property
184
def data(self) -> object:
185
"""Access to MuJoCo simulation data."""
186
187
def timestep(self) -> float:
188
"""Get simulation timestep duration."""
189
190
@property
191
def time(self) -> float:
192
"""Current simulation time."""
193
```
194
195
### Contextual Operations
196
197
Context managers for safe state manipulation.
198
199
```python { .api }
200
def reset_context(self) -> object:
201
"""
202
Context manager for safe state modification.
203
204
Returns:
205
Context manager that restores state on exit
206
207
Example:
208
>>> with physics.reset_context():
209
... physics.named.data.qpos[:] = 0 # Modify state
210
... physics.forward() # Update derived quantities
211
# State automatically restored on exit
212
"""
213
```
214
215
## Usage Examples
216
217
### Basic Simulation
218
219
```python
220
from dm_control.mujoco import Physics
221
import numpy as np
222
223
# Load model
224
physics = Physics.from_xml_path('/path/to/model.xml')
225
226
# Simulation loop
227
for _ in range(1000):
228
# Set random controls
229
control = np.random.randn(physics.model.nu)
230
physics.set_control(control)
231
232
# Step simulation
233
physics.step()
234
235
# Access state
236
positions = physics.named.data.qpos
237
velocities = physics.named.data.qvel
238
239
print(f"Time: {physics.time:.3f}")
240
```
241
242
### Rendering
243
244
```python
245
# Basic rendering
246
rgb_array = physics.render(height=240, width=320, camera_id=0)
247
248
# Depth rendering
249
depth_array = physics.render(height=240, width=320, depth=True)
250
251
# Multiple camera views
252
front_view = physics.render(240, 320, camera_id='front_camera')
253
side_view = physics.render(240, 320, camera_id='side_camera')
254
```
255
256
### Camera Control
257
258
```python
259
# Create movable camera
260
camera = physics.render_camera(width=320, height=240)
261
if hasattr(camera, 'move'):
262
# Adjust camera pose
263
camera.move(azimuth=45, elevation=30, distance=2.0)
264
265
# Render from adjusted pose
266
image = camera.render()
267
```
268
269
### State Manipulation
270
271
```python
272
# Safe state modification
273
with physics.reset_context():
274
# Set joint positions
275
physics.named.data.qpos['hip_joint'] = 0.5
276
physics.named.data.qpos['knee_joint'] = -1.0
277
278
# Update derived quantities
279
physics.forward()
280
281
# Access derived data
282
com_position = physics.named.data.subtree_com['torso']
283
# State automatically restored after context
284
```
285
286
### Named Data Access
287
288
```python
289
# Access joint data by name
290
joint_names = physics.named.model.joint_names
291
for name in joint_names:
292
position = physics.named.data.qpos[name]
293
velocity = physics.named.data.qvel[name]
294
print(f"{name}: pos={position:.3f}, vel={velocity:.3f}")
295
296
# Access body properties
297
body_masses = physics.named.model.body_mass
298
torso_mass = body_masses['torso']
299
300
# Access sensor readings
301
if hasattr(physics.named.data, 'sensordata'):
302
sensor_values = physics.named.data.sensordata
303
```
304
305
## Types
306
307
```python { .api }
308
# Selection result from camera queries
309
Selected = namedtuple('Selected', ['body', 'geom', 'flex', 'skin', 'world_position'])
310
311
# Camera pose specification
312
Pose = namedtuple('Pose', ['lookat', 'distance', 'azimuth', 'elevation'])
313
314
# Context containers
315
Contexts = namedtuple('Contexts', ['gl', 'mujoco'])
316
317
# Named index structures
318
NamedIndexStructs = namedtuple('NamedIndexStructs', ['model', 'data'])
319
```