0
# Environment Viewer
1
2
Interactive GUI application for visualizing dm-control environments, executing policies, and exploring simulation dynamics. Provides real-time rendering, camera controls, policy execution capabilities, and comprehensive environment interaction tools.
3
4
## Capabilities
5
6
### Viewer Launch
7
8
Launch interactive viewer for any dm-control environment.
9
10
```python { .api }
11
def launch(environment_loader, policy=None, title='Explorer', width=1024, height=768) -> None:
12
"""
13
Launch interactive environment viewer.
14
15
Parameters:
16
- environment_loader: Callable that returns Environment instance, or Environment instance directly
17
- policy: Optional callable for automatic policy execution
18
- title: Window title string (default: 'Explorer')
19
- width: Window width in pixels (default: 1024)
20
- height: Window height in pixels (default: 768)
21
22
Raises:
23
- ValueError: When environment_loader is None
24
25
The viewer provides:
26
- Real-time environment rendering
27
- Interactive camera controls
28
- Manual action input via GUI controls
29
- Policy execution and visualization
30
- Episode reset and control
31
- Physics parameter inspection
32
33
Example:
34
>>> from dm_control import suite, viewer
35
>>> env = suite.load('cartpole', 'balance')
36
>>> viewer.launch(env)
37
38
With policy:
39
>>> def random_policy(time_step):
40
... return env.action_spec().generate_value()
41
>>> viewer.launch(env, policy=random_policy)
42
43
With environment loader:
44
>>> def env_loader():
45
... return suite.load('walker', 'walk')
46
>>> viewer.launch(env_loader, title='Walker Environment')
47
"""
48
```
49
50
### Application Class
51
52
Core application class for advanced viewer customization.
53
54
```python { .api }
55
class Application:
56
"""
57
Core viewer application with GUI and rendering capabilities.
58
59
Provides lower-level access to viewer functionality for custom
60
applications and advanced use cases.
61
"""
62
63
def __init__(self, title: str = 'Explorer', width: int = 1024, height: int = 768):
64
"""
65
Initialize viewer application.
66
67
Parameters:
68
- title: Application window title
69
- width: Window width in pixels
70
- height: Window height in pixels
71
"""
72
73
def launch(self, environment_loader, policy=None) -> None:
74
"""
75
Launch viewer with environment and optional policy.
76
77
Parameters:
78
- environment_loader: Environment or environment factory function
79
- policy: Optional policy function for automatic control
80
"""
81
```
82
83
## Usage Examples
84
85
### Basic Environment Viewing
86
87
```python
88
from dm_control import suite, viewer
89
90
# View suite environment
91
env = suite.load('humanoid', 'walk')
92
viewer.launch(env)
93
94
# View with custom window settings
95
viewer.launch(env, title='Humanoid Walker', width=1280, height=720)
96
```
97
98
### Policy Visualization
99
100
```python
101
from dm_control import suite, viewer
102
import numpy as np
103
104
# Load environment
105
env = suite.load('cheetah', 'run')
106
107
# Define policy function
108
def random_policy(time_step):
109
"""Random policy for demonstration."""
110
return env.action_spec().generate_value()
111
112
def simple_controller(time_step):
113
"""Simple PD controller example."""
114
# Extract joint positions and velocities
115
obs = time_step.observation
116
positions = obs.get('position', np.zeros(6))
117
velocities = obs.get('velocity', np.zeros(6))
118
119
# Simple PD control toward zero position
120
kp, kd = 1.0, 0.1
121
control = -kp * positions - kd * velocities
122
123
# Clip to action bounds
124
spec = env.action_spec()
125
return np.clip(control, spec.minimum, spec.maximum)
126
127
# Launch with policy
128
viewer.launch(env, policy=simple_controller, title='Cheetah with Controller')
129
```
130
131
### Environment Factory Pattern
132
133
```python
134
from dm_control import suite, composer, viewer
135
136
def create_environment():
137
"""Factory function for creating environments."""
138
# Create fresh environment instance each time
139
return suite.load('walker', 'walk',
140
task_kwargs={'random': np.random.randint(1000)})
141
142
def create_composer_environment():
143
"""Factory for composer environments."""
144
# Custom composer environment creation
145
task = MyCustomTask()
146
arena = MyCustomArena()
147
return composer.Environment(task, arena, time_limit=20.0)
148
149
# Launch with factory functions
150
viewer.launch(create_environment, title='Random Walker')
151
viewer.launch(create_composer_environment, title='Custom Environment')
152
```
153
154
### Policy Development and Testing
155
156
```python
157
from dm_control import suite, viewer
158
import numpy as np
159
160
# Load environment for policy development
161
env = suite.load('cartpole', 'balance')
162
163
class PDController:
164
"""PD controller for cartpole balancing."""
165
166
def __init__(self, kp=10.0, kd=1.0):
167
self.kp = kp
168
self.kd = kd
169
170
def __call__(self, time_step):
171
obs = time_step.observation
172
angle = obs['orientation'][0] # Pole angle
173
angular_vel = obs['velocity'][1] # Angular velocity
174
175
# PD control
176
control = -self.kp * angle - self.kd * angular_vel
177
return np.array([control])
178
179
# Test different controller parameters
180
controllers = [
181
PDController(kp=5.0, kd=0.5),
182
PDController(kp=10.0, kd=1.0),
183
PDController(kp=20.0, kd=2.0)
184
]
185
186
for i, controller in enumerate(controllers):
187
print(f"Testing controller {i+1}")
188
viewer.launch(env, policy=controller,
189
title=f'Controller {i+1} (kp={controller.kp}, kd={controller.kd})')
190
```
191
192
### Advanced Viewer Usage
193
194
```python
195
from dm_control import viewer
196
197
# Create custom application
198
app = viewer.application.Application(
199
title='Custom Physics Viewer',
200
width=1600,
201
height=900
202
)
203
204
def environment_with_variations():
205
"""Create environment with random variations."""
206
domains = ['walker', 'humanoid', 'cheetah']
207
tasks = ['walk', 'run', 'stand']
208
209
domain = np.random.choice(domains)
210
if domain == 'walker':
211
task = np.random.choice(['walk', 'run', 'stand'])
212
elif domain == 'humanoid':
213
task = np.random.choice(['walk', 'run', 'stand'])
214
else: # cheetah
215
task = 'run'
216
217
return suite.load(domain, task)
218
219
def adaptive_policy(time_step):
220
"""Policy that adapts to different environments."""
221
obs = time_step.observation
222
223
# Simple heuristic based on observation structure
224
if 'orientations' in obs: # Humanoid-like
225
return np.random.uniform(-0.5, 0.5, size=21)
226
elif 'position' in obs: # Walker-like
227
return np.random.uniform(-1, 1, size=6)
228
else: # Default fallback
229
return np.random.uniform(-1, 1, size=12)
230
231
# Launch with custom application
232
app.launch(environment_with_variations, policy=adaptive_policy)
233
```
234
235
### Debugging and Analysis
236
237
```python
238
from dm_control import suite, viewer
239
240
# Environment for debugging
241
env = suite.load('manipulator', 'bring_ball')
242
243
def debug_policy(time_step):
244
"""Policy with debugging output."""
245
obs = time_step.observation
246
247
# Print observation info for debugging
248
print(f"Step type: {time_step.step_type}")
249
print(f"Reward: {time_step.reward}")
250
print(f"Observation keys: {list(obs.keys())}")
251
252
# Simple random action
253
action = env.action_spec().generate_value()
254
print(f"Action: {action}")
255
256
return action
257
258
# Launch with debug output
259
viewer.launch(env, policy=debug_policy, title='Debug Mode')
260
```
261
262
## Viewer Controls
263
264
The interactive viewer provides these controls:
265
266
### Camera Controls
267
- **Mouse drag**: Rotate camera view
268
- **Mouse wheel**: Zoom in/out
269
- **Shift + mouse drag**: Pan camera
270
- **R key**: Reset camera to default position
271
272
### Simulation Controls
273
- **Space bar**: Pause/resume simulation
274
- **R key**: Reset episode
275
- **S key**: Single step when paused
276
- **Arrow keys**: Manual action input (environment-dependent)
277
278
### Display Options
279
- **F key**: Toggle fullscreen
280
- **H key**: Show/hide help overlay
281
- **I key**: Show/hide info panel
282
- **C key**: Cycle through available cameras
283
284
### Policy Controls
285
- **P key**: Toggle policy execution on/off
286
- **T key**: Toggle time display
287
- **Number keys**: Adjust simulation speed
288
289
## Integration with Other Modules
290
291
```python
292
# Viewer with physics inspection
293
from dm_control import suite, viewer, mujoco
294
295
env = suite.load('quadruped', 'walk')
296
297
def physics_inspector(time_step):
298
"""Policy that inspects physics state."""
299
physics = env.physics
300
301
# Access physics data during viewer session
302
print(f"Time: {physics.time():.3f}")
303
print(f"Energy: {physics.named.data.energy}")
304
305
return env.action_spec().generate_value()
306
307
viewer.launch(env, policy=physics_inspector)
308
```
309
310
## Types
311
312
```python { .api }
313
# Policy function signature
314
PolicyFunction = Callable[[TimeStep], np.ndarray]
315
"""
316
Policy function that takes a TimeStep and returns actions.
317
318
Parameters:
319
- time_step: Current environment timestep
320
321
Returns:
322
Action array conforming to environment's action_spec()
323
"""
324
325
# Environment loader signature
326
EnvironmentLoader = Callable[[], Environment]
327
"""
328
Function that creates and returns an Environment instance.
329
330
Returns:
331
Fresh Environment instance ready for interaction
332
"""
333
```