Implementation:Google deepmind Dm control Viewer Launch For Locomotion
| Metadata | |
|---|---|
| Knowledge Sources | dm_control |
| Domains | Reinforcement Learning, Robotics, Visualization |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
Concrete tool for launching an interactive viewer to visualize dm_control locomotion environments, supporting real-time rendering, optional policy execution, and camera manipulation.
Description
The Template:Code function opens an interactive GUI window that renders a dm_control environment in real time using MuJoCo's built-in renderer. It accepts either a pre-built environment instance or an environment loader (factory function) and optionally a policy callable. The viewer provides controls for stepping through the simulation, pausing, resetting episodes, manipulating the camera, and toggling rendering modes (wireframe, contact visualization, etc.).
For locomotion tasks, the viewer is the primary tool for visually verifying that:
- The walker spawns in the correct pose within the arena.
- The terrain geometry (corridors, gaps, walls, mazes, bowls) generates correctly.
- Target spheres and props appear at expected positions.
- A trained policy produces natural-looking locomotion behavior.
- Contact dynamics and termination conditions work as intended.
The viewer runs the simulation in a loop: at each control step, it either queries the provided policy for an action or uses zero/user-supplied actions, steps the environment, and renders the resulting physics state. The rendering runs at the display refresh rate, independent of the simulation rate.
Usage
Use Template:Code during development and evaluation of locomotion tasks. Pass an environment loader function for maximum flexibility (the viewer can recreate the environment on demand), or pass a pre-built environment instance for quick inspection.
Code Reference
Source Location
| Function | File | Lines |
|---|---|---|
| launch | Template:Code | L22-40 |
| (example) explore.py | Template:Code | L17-28 |
Signature
def launch(environment_loader, policy=None, title='Explorer',
width=1024, height=768):
"""Launches an environment viewer.
Args:
environment_loader: An environment loader (a callable that returns
an instance of dm_control.rl.control.Environment), or an
instance of dm_control.rl.control.Environment.
policy: An optional callable corresponding to a policy to execute
within the environment. It should accept a TimeStep and return
a numpy array of actions conforming to the output of
environment.action_spec().
title: Application title to be displayed in the title bar.
width: Window width, in pixels.
height: Window height, in pixels.
Raises:
ValueError: When 'environment_loader' argument is set to None.
"""
Import
from dm_control import viewer
I/O Contract
Inputs
| Parameter | Type | Description |
|---|---|---|
| environment_loader | callable or Environment | A factory function that returns a dm_control Environment instance, or a pre-built Environment instance. |
| policy | callable or None | Optional policy function: accepts a Template:Code and returns a numpy action array matching Template:Code. Default None. |
| title | str | Window title text. Default Template:Code. |
| width | int | Window width in pixels. Default 1024. |
| height | int | Window height in pixels. Default 768. |
Outputs
| Output | Type | Description |
|---|---|---|
| (none) | None | The function opens an interactive window and blocks until the window is closed. It does not return a value. |
Usage Examples
Launching the built-in CMU humanoid gaps corridor example:
from dm_control.locomotion.examples import basic_cmu_2019
from dm_control import viewer
viewer.launch(environment_loader=basic_cmu_2019.cmu_humanoid_run_gaps)
Launching a custom locomotion environment:
from dm_control import composer
from dm_control import viewer
from dm_control.locomotion.walkers import cmu_humanoid
from dm_control.locomotion.arenas import floors
from dm_control.locomotion.tasks import go_to_target
def my_environment_loader():
walker = cmu_humanoid.CMUHumanoidPositionControlled()
arena = floors.Floor(size=(8, 8))
task = go_to_target.GoToTarget(
walker=walker, arena=arena,
moving_target=True,
physics_timestep=0.005,
control_timestep=0.03)
return composer.Environment(
task=task, time_limit=30,
strip_singleton_obs_buffer_dim=True)
viewer.launch(environment_loader=my_environment_loader,
title='Go To Target', width=1280, height=960)
Launching with a trained policy for evaluation:
import numpy as np
from dm_control import composer
from dm_control import viewer
from dm_control.locomotion.examples import basic_cmu_2019
def trained_policy(timestep):
"""A placeholder for a trained policy.
In practice, this would load a neural network and compute actions
from timestep.observation.
"""
# Replace with actual policy inference
obs = timestep.observation
action = np.zeros(56) # CMU humanoid has 56 actuators
return action
viewer.launch(
environment_loader=basic_cmu_2019.cmu_humanoid_run_walls,
policy=trained_policy,
title='Trained Policy Evaluation')
Running the viewer from the command line (using the explore example):
# From the command line:
# python -m dm_control.locomotion.examples.explore
#
# This launches the viewer with the CMU humanoid gaps corridor task.
# The explore.py script contains:
from absl import app
from dm_control.locomotion.examples import basic_cmu_2019
from dm_control import viewer
def main(unused_argv):
viewer.launch(environment_loader=basic_cmu_2019.cmu_humanoid_run_gaps)
if __name__ == '__main__':
app.run(main)
Launching a maze navigation environment in the viewer:
import functools
from dm_control import composer
from dm_control import viewer
from dm_control.locomotion.walkers import cmu_humanoid
from dm_control.locomotion.arenas import mazes, labmaze_textures
from dm_control.locomotion.tasks import random_goal_maze
from dm_control.locomotion.props import target_sphere
def maze_env_loader():
walker = cmu_humanoid.CMUHumanoidPositionControlled(
observable_options={'egocentric_camera': dict(enabled=True)})
arena = mazes.RandomMazeWithTargets(
x_cells=11, y_cells=11, xy_scale=3,
max_rooms=4, room_min_size=4, room_max_size=5,
spawns_per_room=1, targets_per_room=3,
skybox_texture=labmaze_textures.SkyBox(style='sky_03'),
wall_textures=labmaze_textures.WallTextures(style='style_01'),
floor_textures=labmaze_textures.FloorTextures(style='style_01'))
task = random_goal_maze.ManyGoalsMaze(
walker=walker, maze_arena=arena,
target_builder=functools.partial(
target_sphere.TargetSphere,
radius=0.4, rgb1=(0, 0, 0.4), rgb2=(0, 0, 0.7)),
target_reward_scale=50.0,
physics_timestep=0.005, control_timestep=0.03)
return composer.Environment(task=task, time_limit=30,
strip_singleton_obs_buffer_dim=True)
viewer.launch(environment_loader=maze_env_loader,
title='Maze Foraging')