### Run an example environment with random actions
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/locomotion/README.md
Builds an example environment and steps through it using random actions. Requires importing `composer`, `basic_cmu_2019`, and `numpy`.
```python
from dm_control import composer
from dm_control.locomotion.examples import basic_cmu_2019
import numpy as np
# Build an example environment.
env = basic_cmu_2019.cmu_humanoid_run_walls()
# Get the `action_spec` describing the control inputs.
action_spec = env.action_spec()
# Step through the environment for one episode with random actions.
time_step = env.reset()
while not time_step.last():
action = np.random.uniform(action_spec.minimum, action_spec.maximum,
size=action_spec.shape)
time_step = env.step(action)
print("reward = {}, discount = {}, observations = {}.".format(
time_step.reward, time_step.discount, time_step.observation))
```
--------------------------------
### Install dm_control from repository
Source: https://github.com/google-deepmind/dm_control/blob/main/README.md
Install an unreleased version of dm_control directly from its GitHub repository.
```sh
pip install git+https://github.com/google-deepmind/dm_control.git
```
--------------------------------
### Install dm_control
Source: https://github.com/google-deepmind/dm_control/blob/main/README.md
Install dm_control from PyPI. Do not use editable mode.
```sh
pip install dm_control
```
--------------------------------
### Install MuJoCo and dm_control on Colab
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb
Installs MuJoCo and dm_control, configures the EGL rendering backend for GPU acceleration, and verifies the installation by loading a simple environment.
```python
#@title Run to install MuJoCo and `dm_control`
import distutils.util
import os
import subprocess
if subprocess.run('nvidia-smi').returncode:
raise RuntimeError(
'Cannot communicate with GPU. '
'Make sure you are using a GPU Colab runtime. '
'Go to the Runtime menu and select Choose runtime type.')
# Add an ICD config so that glvnd can pick up the Nvidia EGL driver.
# This is usually installed as part of an Nvidia driver package, but the Colab
# kernel doesn't install its driver via APT, and as a result the ICD is missing.
# (https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md)
NVIDIA_ICD_CONFIG_PATH = '/usr/share/glvnd/egl_vendor.d/10_nvidia.json'
if not os.path.exists(NVIDIA_ICD_CONFIG_PATH):
with open(NVIDIA_ICD_CONFIG_PATH, 'w') as f:
f.write("""{
"file_format_version" : "1.0.0",
"ICD" : {
"library_path" : "libEGL_nvidia.so.0"
}
}
""")
print('Installing dm_control...')
!pip install -q dm_control>=1.0.42
# Configure dm_control to use the EGL rendering backend (requires GPU)
%env MUJOCO_GL=egl
print('Checking that the dm_control installation succeeded...')
try:
from dm_control import suite
env = suite.load('cartpole', 'swingup')
pixels = env.physics.render()
except Exception as e:
raise e from RuntimeError(
'Something went wrong during installation. Check the shell output above '
'for more information.\n'
'If using a hosted Colab runtime, make sure you enable GPU acceleration ' 'by going to the Runtime menu and selecting "Choose runtime type".')
else:
del suite, pixels
print('dm_control installation succeeded.')
```
--------------------------------
### Launch Viewer with Environment
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/viewer/README.md
Launches the viewer with a specified environment from the Control Suite. Ensure dm_control is installed.
```python
from dm_control import suite
from dm_control import viewer
# Load an environment from the Control Suite.
env = suite.load(domain_name="humanoid", task_name="stand")
# Launch the viewer application.
viewer.launch(env)
```
--------------------------------
### Load and Interact with Control Suite Environments
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/suite/README.md
Demonstrates how to load a specific task, iterate over all benchmarking tasks, and step through an episode using random actions. Ensure dm_control and numpy are installed.
```python
from dm_control import suite
import numpy as np
# Load one task:
env = suite.load(domain_name="cartpole", task_name="swingup")
# Iterate over a task set:
for domain_name, task_name in suite.BENCHMARKING:
env = suite.load(domain_name, task_name)
# Step through an episode and print out reward, discount and observation.
action_spec = env.action_spec()
time_step = env.reset()
while not time_step.last():
action = np.random.uniform(action_spec.minimum,
action_spec.maximum,
size=action_spec.shape)
time_step = env.step(action)
print(time_step.reward, time_step.discount, time_step.observation)
```
--------------------------------
### Instantiate and Run a Soccer Environment
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/locomotion/soccer/README.md
Instantiates a 2-vs-2 BOXHEAD soccer environment and steps through it with random actions. Ensure dm_control and numpy are installed.
```python
import numpy as np
from dm_control.locomotion import soccer as dm_soccer
# Instantiates a 2-vs-2 BOXHEAD soccer environment with episodes of 10 seconds
# each. Upon scoring, the environment reset player positions and the episode
# continues. In this example, players can physically block each other and the
# ball is trapped within an invisible box encapsulating the field.
env = dm_soccer.load(team_size=2,
time_limit=10.0,
disable_walker_contacts=False,
enable_field_box=True,
terminate_on_goal=False,
walker_type=dm_soccer.WalkerType.BOXHEAD)
# Retrieves action_specs for all 4 players.
action_specs = env.action_spec()
# Step through the environment for one episode with random actions.
timestep = env.reset()
while not timestep.last():
actions = []
for action_spec in action_specs:
action = np.random.uniform(
action_spec.minimum, action_spec.maximum, size=action_spec.shape)
actions.append(action)
timestep = env.step(actions)
for i in range(len(action_specs)):
print(
"Player {}: reward = {}, discount = {}, observations = {} ".format(
i, timestep.reward[i], timestep.discount, timestep.observation[i]))
```
--------------------------------
### Install MuJoCo and dm_control
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Installs the dm_control package and its dependencies, including MuJoCo. Requires a GPU-enabled Colab runtime and configures dm_control to use the EGL rendering backend.
```python
#@title Run to install MuJoCo and `dm_control`
import distutils.util
import os
import subprocess
if subprocess.run('nvidia-smi').returncode:
raise RuntimeError(
'Cannot communicate with GPU. '
'Make sure you are using a GPU Colab runtime. '
'Go to the Runtime menu and select Choose runtime type.')
# Add an ICD config so that glvnd can pick up the Nvidia EGL driver.
# This is usually installed as part of an Nvidia driver package, but the Colab
# kernel doesn't install its driver via APT, and as a result the ICD is missing.
# (https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md)
NVIDIA_ICD_CONFIG_PATH = '/usr/share/glvnd/egl_vendor.d/10_nvidia.json'
if not os.path.exists(NVIDIA_ICD_CONFIG_PATH):
with open(NVIDIA_ICD_CONFIG_PATH, 'w') as f:
f.write("""
{
"file_format_version" : "1.0.0",
"ICD" : {
"library_path" : "libEGL_nvidia.so.0"
}
}
""")
print('Installing dm_control...')
!pip install -q dm_control>=1.0.42
# Configure dm_control to use the EGL rendering backend (requires GPU)
%env MUJOCO_GL=egl
print('Checking that the dm_control installation succeeded...')
try:
from dm_control import suite
env = suite.load('cartpole', 'swingup')
pixels = env.physics.render()
except Exception as e:
raise e from RuntimeError(
'Something went wrong during installation. Check the shell output above '
'for more information.\n'
'If using a hosted Colab runtime, make sure you enable GPU acceleration ' 'by going to the Runtime menu and selecting "Choose runtime type".')
else:
del pixels, suite
!echo Installed dm_control $(pip show dm_control | grep -Po "(?<=Version: ).+")
```
--------------------------------
### Create Plugin Installer Zip
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/blender/mujoco_exporter/README.md
This command creates a zip archive of the MuJoCo model exporter addon for installation in Blender.
```shell
cd ./addons && zip -r mujoco_model_exporter.zip mujoco_model_exporter/*
```
--------------------------------
### Instantiate and Reset Environment
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Instantiates a dm_control environment with a custom task and resets it. This is the initial step before starting a simulation or training loop.
```python
#@title Instantiating an environment{vertical-output: true}
creature = Creature(num_legs=4)
task = PressWithSpecificForce(creature)
env = composer.Environment(task, random_state=np.random.RandomState(42))
env.reset()
PIL.Image.fromarray(env.physics.render())
```
--------------------------------
### Conflicting Global Options Error (Python)
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mjcf/README.md
Example demonstrating how attempting to attach models with conflicting global compiler options (e.g., angle units) raises an error.
```python
model_1 = mjcf.RootElement()
model_1.compiler.angle = 'radian'
model_2 = mjcf.RootElement()
model_2.compiler.angle = 'degree'
model_1.attach(model_2) # Error!
```
--------------------------------
### Render Initial State of Mujoco Model
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb
This snippet loads a complex Mujoco model defined in MJCF format, which includes a bat, a piñata (represented by a box and sphere), and a wire tendon connecting them. It then renders a single image of the initial state of the simulation. Use this to quickly inspect the setup of a Mujoco model.
```python
#@title bat and piñata: {vertical-output: true}
MJCF = """
"
physics = mujoco.Physics.from_xml_string(MJCF)
PIL.Image.fromarray(physics.render(480, 480, "fixed") )
```
--------------------------------
### dm_control Core Imports
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Imports essential components from dm_control for mujoco, PyMJCF, and Composer functionalities. Includes specific imports for locomotion and manipulation examples.
```python
#@title All `dm_control` imports required for this tutorial
# The basic mujoco wrapper.
from dm_control import mujoco
# Access to enums and MuJoCo library functions.
from dm_control.mujoco.wrapper.mjbindings import enums
from dm_control.mujoco.wrapper.mjbindings import mjlib
# PyMJCF
from dm_control import mjcf
# Composer high level imports
from dm_control import composer
from dm_control.composer.observation import observable
from dm_control.composer import variation
# Imports for Composer tutorial example
from dm_control.composer.variation import distributions
from dm_control.composer.variation import noises
from dm_control.locomotion.arenas import floors
# Control Suite
from dm_control import suite
# Run through corridor example
from dm_control.locomotion.walkers import cmu_humanoid
from dm_control.locomotion.arenas import corridors as corridor_arenas
from dm_control.locomotion.tasks import corridors as corridor_tasks
# Soccer
from dm_control.locomotion import soccer
# Manipulation
from dm_control import manipulation
```
--------------------------------
### Define a Custom Task: PressWithSpecificForce
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Defines a custom task for the dm_control environment, including arena setup, entity attachment, observable configuration, and reward calculation. This is useful for creating specialized control problems.
```python
#@title The `PressWithSpecificForce` task
class PressWithSpecificForce(composer.Task):
def __init__(self, creature):
self._creature = creature
self._arena = floors.Floor()
self._arena.add_free_entity(self._creature)
self._arena.mjcf_model.worldbody.add('light', pos=(0, 0, 4))
self._button = Button()
self._arena.attach(self._button)
# Configure initial poses
self._creature_initial_pose = (0, 0, 0.15)
button_distance = distributions.Uniform(0.5, .75)
self._button_initial_pose = UniformCircle(button_distance)
# Configure variators
self._mjcf_variator = variation.MJCFVariator()
self._physics_variator = variation.PhysicsVariator()
# Configure and enable observables
pos_corrptor = noises.Additive(distributions.Normal(scale=0.01))
self._creature.observables.joint_positions.corruptor = pos_corrptor
self._creature.observables.joint_positions.enabled = True
vel_corruptor = noises.Multiplicative(distributions.LogNormal(sigma=0.01))
self._creature.observables.joint_velocities.corruptor = vel_corruptor
self._creature.observables.joint_velocities.enabled = True
self._button.observables.touch_force.enabled = True
def to_button(physics):
button_pos, _ = self._button.get_pose(physics)
return self._creature.global_vector_to_local_frame(physics, button_pos)
self._task_observables = {}
self._task_observables['button_position'] = observable.Generic(to_button)
for obs in self._task_observables.values():
obs.enabled = True
self.control_timestep = NUM_SUBSTEPS * self.physics_timestep
@property
def root_entity(self):
return self._arena
@property
def task_observables(self):
return self._task_observables
def initialize_episode_mjcf(self, random_state):
self._mjcf_variator.apply_variations(random_state)
def initialize_episode(self, physics, random_state):
self._physics_variator.apply_variations(physics, random_state)
creature_pose, button_pose = variation.evaluate(
(self._creature_initial_pose, self._button_initial_pose),
random_state=random_state)
self._creature.set_pose(physics, position=creature_pose)
self._button.set_pose(physics, position=button_pose)
def get_reward(self, physics):
return self._button.num_activated_steps / NUM_SUBSTEPS
```
--------------------------------
### Launch Viewer with Policy
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/viewer/README.md
Launches the viewer with an environment and a custom policy for action generation. The policy must accept a TimeStep and return actions.
```python
from dm_control import suite
from dm_control import viewer
import numpy as np
env = suite.load(domain_name="humanoid", task_name="stand")
action_spec = env.action_spec()
# Define a uniform random policy.
def random_policy(time_step):
del time_step # Unused.
return np.random.uniform(low=action_spec.minimum,
high=action_spec.maximum,
size=action_spec.shape)
# Launch the viewer application.
viewer.launch(env, policy=random_policy)
```
--------------------------------
### Parent and Child MJCF Models
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mjcf/README.md
Example XML structure for a parent and a child model before attachment.
```xml
```
--------------------------------
### Launch the environment viewer
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/locomotion/README.md
Launches the `dm_control.viewer` to visualize and interact with the environment. Requires importing `viewer` and specifying an `environment_loader`.
```python
from dm_control import viewer
viewer.launch(environment_loader=basic_cmu_2019.cmu_humanoid_run_walls)
```
--------------------------------
### Accessing Cartesian Positions of Geoms
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Get the world frame Cartesian positions of geoms using `physics.data.geom_xpos`.
```python
print(physics.data.geom_xpos)
```
--------------------------------
### Visualize Initial Task States
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Loads and visualizes the initial state of one task per domain in the Control Suite. Requires numpy and matplotlib for visualization.
```python
#@title Visualizing an initial state of one task per domain in the Control Suite
#@test {"timeout": 180}
domains_tasks = {domain: task for domain, task in suite.ALL_TASKS}
random_state = np.random.RandomState(42)
num_domains = len(domains_tasks)
n_col = num_domains // int(np.sqrt(num_domains))
n_row = num_domains // n_col + int(0 < num_domains % n_col)
_, ax = plt.subplots(n_row, n_col, figsize=(12, 12))
for a in ax.flat:
a.axis('off')
a.grid(False)
print(f'Iterating over all {num_domains} domains in the Suite:')
for j, [domain, task] in enumerate(domains_tasks.items()):
print(domain, task)
env = suite.load(domain, task, task_kwargs={'random': random_state})
timestep = env.reset()
pixels = env.physics.render(height=200, width=200, camera_id=0)
ax.flat[j].imshow(pixels)
ax.flat[j].set_title(domain + ': ' + task)
clear_output()
```
--------------------------------
### Simulate and Render MuJoCo Model to Video
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Simulates a dynamic MuJoCo model over a specified duration and collects frames to create a video. Requires a model with DOFs.
```python
#@title Making a video {vertical-output: true}
duration = 2 # (seconds)
framerate = 30 # (Hz)
# Visualize the joint axis
scene_option = mujoco.wrapper.core.MjvOption()
scene_option.flags[enums.mjtVisFlag.mjVIS_JOINT] = True
# Simulate and display video.
frames = []
physics.reset() # Reset state and time
while physics.data.time < duration:
physics.step()
if len(frames) < physics.data.time * framerate:
pixels = physics.render(scene_option=scene_option)
frames.append(pixels)
display_video(frames, framerate)
```
--------------------------------
### Animate tippe-top simulation
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Simulates the tippe-top model for a specified duration and framerate, rendering and collecting frames to display as a video.
```python
#@title Video of the tippe-top {vertical-output: true}
duration = 7 # (seconds)
framerate = 60 # (Hz)
# Simulate and display video.
frames = []
physics.reset(0) # Reset to keyframe 0 (load a saved state).
while physics.data.time < duration:
physics.step()
if len(frames) < (physics.data.time) * framerate:
pixels = physics.render(camera_id='closeup')
frames.append(pixels)
display_video(frames, framerate)
```
--------------------------------
### Load and Simulate a Control Suite Task
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Loads a specific task from the Control Suite and simulates it with random actions for a given duration. This snippet demonstrates environment loading, stepping, rendering, and data collection.
```python
#@title Loading and simulating a `suite` task{vertical-output: true}
# Load the environment
random_state = np.random.RandomState(42)
env = suite.load('hopper', 'stand', task_kwargs={'random': random_state})
# Simulate episode with random actions
duration = 4 # Seconds
frames = []
ticks = []
rewards = []
observations = []
spec = env.action_spec()
time_step = env.reset()
while env.physics.data.time < duration:
action = random_state.uniform(spec.minimum, spec.maximum, spec.shape)
time_step = env.step(action)
camera0 = env.physics.render(camera_id=0, height=200, width=200)
camera1 = env.physics.render(camera_id=1, height=200, width=200)
frames.append(np.hstack((camera0, camera1)))
rewards.append(time_step.reward)
observations.append(copy.deepcopy(time_step.observation))
ticks.append(env.physics.data.time)
html_video = display_video(frames, framerate=1./env.control_timestep())
# Show video and plot reward and observations
num_sensors = len(time_step.observation)
_, ax = plt.subplots(1 + num_sensors, 1, sharex=True, figsize=(4, 8))
ax[0].plot(ticks, rewards)
ax[0].set_ylabel('reward')
ax[-1].set_xlabel('time')
for i, key in enumerate(time_step.observation):
data = np.asarray([observations[j][key] for j in range(len(observations))])
ax[i+1].plot(ticks, data, label=key)
ax[i+1].set_ylabel(key)
html_video
```
--------------------------------
### Load and Simulate Manipulation Task
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Loads a specified manipulation environment, defines a function to sample random actions, and simulates a full episode, recording camera observations.
```python
#@title Loading and simulating a `manipulation` task{vertical-output: true}
env = manipulation.load('stack_2_of_3_bricks_random_order_vision', seed=42)
action_spec = env.action_spec()
def sample_random_action():
return env.random_state.uniform(
low=action_spec.minimum,
high=action_spec.maximum,
).astype(action_spec.dtype, copy=False)
# Step the environment through a full episode using random actions and record
# the camera observations.
frames = []
timestep = env.reset()
frames.append(timestep.observation['front_close'])
while not timestep.last():
timestep = env.step(sample_random_action())
frames.append(timestep.observation['front_close'])
all_frames = np.concatenate(frames, axis=0)
display_video(all_frames, 30)
```
--------------------------------
### List All Manipulation Tasks
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Prints the names of all available environments within the dm_control manipulation suite.
```python
#@title Listing all `manipulation` tasks{vertical-output: true}
# `ALL` is a tuple containing the names of all of the environments in the suite.
print('\n'.join(manipulation.ALL))
```
--------------------------------
### Load Model, Simulate, and Render with MuJoCo
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/README.md
Loads a model from an XML string, renders the default camera view, resets the simulation with joint modifications, prints geom positions, and advances the simulation.
```python
from dm_control import mujoco
# Load a model from an MJCF XML string.
xml_string = """
"
physics = mujoco.Physics.from_xml_string(xml_string)
# Render the default camera view as a numpy array of pixels.
pixels = physics.render()
# Reset the simulation, move the slide joint upwards and recompute derived
# quantities (e.g. the positions of the body and geoms).
with physics.reset_context():
physics.named.data.qpos['up_down'] = 0.5
# Print the positions of the geoms.
print(physics.named.data.geom_xpos)
# FieldIndexer(geom_xpos):
# x y z
# 0 floor [ 0 0 0 ]
# 1 box [ 0 0 0.8 ]
# 2 sphere [ 0.2 0.2 1 ]
# Advance the simulation for 1 second.
while physics.time() < 1.:
physics.step()
# Print the new z-positions of the 'box' and 'sphere' geoms.
print(physics.named.data.geom_xpos[['box', 'sphere'], 'z'])
# [ 0.19996362 0.39996362]
```
--------------------------------
### Define and simulate the tippe-top model
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Defines a tippe-top model with a free joint, custom assets, and a low center of mass for flipping behavior. Renders an initial state using a defined camera.
```python
#@title The "tippe-top" model{vertical-output: true}
tippe_top = """
"
physics = mujoco.Physics.from_xml_string(tippe_top)
PIL.Image.fromarray(physics.render(camera_id='closeup'))
```
--------------------------------
### Initialize MjvOption with Default Values (Before)
Source: https://github.com/google-deepmind/dm_control/blob/main/migration_guide_1.0.md
Before version 1.0, initializing MjvOption required explicit calls to default functions. This pattern is no longer necessary.
```python
from dm_control.mujoco import wrapper
from dm_control.mujoco.wrapper import mjbindings
mjlib = mjbindings.mjlib
scene_option = wrapper.core.MjvOption()
mjlib.mjv_defaultOption(scene_option.ptr)
```
--------------------------------
### Measure and Plot Tippe-Top Dynamics
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb
Simulates the tippe-top and collects data on time, angular velocity, and stem height. This data is then plotted to visualize the simulation's dynamics.
```python
#@title Measuring values {vertical-output: true}
timevals = []
angular_velocity = []
stem_height = []
# Simulate and save data
physics.reset(0)
while physics.data.time < duration:
physics.step()
timevals.append(physics.data.time)
angular_velocity.append(physics.data.qvel[3:6].copy())
stem_height.append(physics.named.data.geom_xpos['stem', 'z'])
dpi = 100
width = 480
height = 640
figsize = (width / dpi, height / dpi)
_, ax = plt.subplots(2, 1, figsize=figsize, dpi=dpi, sharex=True)
ax[0].plot(timevals, angular_velocity)
ax[0].set_title('angular velocity')
ax[0].set_ylabel('radians / second')
ax[1].plot(timevals, stem_height)
ax[1].set_xlabel('time (seconds)')
ax[1].set_ylabel('meters')
_ = ax[1].set_title('stem height')
```
--------------------------------
### Inspect tippe-top model state
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Prints the joint positions (including quaternion orientation) and velocities of the tippe-top model after initialization.
```python
print('positions', physics.data.qpos)
print('velocities', physics.data.qvel)
```
--------------------------------
### Iterate Over Control Suite Benchmark Tasks
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Iterates through the predefined benchmark tasks in the Control Suite, printing the domain and task names. Useful for understanding the available benchmarks.
```python
#@title Iterating over tasks{vertical-output: true}
max_len = max(len(d) for d, _ in suite.BENCHMARKING)
for domain, task in suite.BENCHMARKING:
print(f'{domain:<{max_len}} {task}')
```
--------------------------------
### RunThroughCorridor Environment Simulation
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Instantiates and resets the RunThroughCorridor environment, renders camera observations, and displays them as a horizontally stacked image.
```python
#@title The `RunThroughCorridor` environment
env = composer.Environment(
task=task,
time_limit=10,
random_state=np.random.RandomState(42),
strip_singleton_obs_buffer_dim=True,
)
env.reset()
pixels = []
for camera_id in range(3):
pixels.append(env.physics.render(camera_id=camera_id, width=240))
PIL.Image.fromarray(np.hstack(pixels))
```
--------------------------------
### Virtual Spring-Damper Simulation with Kinematic Jacobians
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb
Creates a virtual spring-damper system using the kinematic Jacobian of an end effector to reach a random target position. Renders the simulation from two camera perspectives.
```python
#@ title virtual spring-damper: {vertical-output: true}
MJCF = """
"
physics = mujoco.Physics.from_xml_string(MJCF)
# virtual spring coefficient
KP = 3
# prepare simulation
jac_pos = np.zeros((3, physics.model.nv))
jac_rot = np.zeros((3, physics.model.nv))
n_frames = 50
height = 320
width = 320
video = np.zeros((n_frames, height, 2*width, 3), dtype=np.uint8)
# place target in random location
with physics.reset_context():
target_pos = np.random.rand(3)*.5
target_pos[:2] -= .25
physics.named.model.geom_pos["target"][:] = target_pos
physics.named.model.geom_sameframe["target"] = 0
# simulate and render
for i in range(n_frames):
while physics.data.time < i/15.0:
# get Jacobian of fingertip position
mjlib.mj_jacGeom(physics.model.ptr,
physics.data.ptr,
jac_pos,
jac_rot,
physics.model.name2id('fingertip', 'geom'))
# multiply the jacobian by error to get vector in joint space
err = (physics.named.data.geom_xpos["target"] -
physics.named.data.geom_xpos["fingertip"])
jnt_err = np.dot(err, jac_pos)
# set virutal spring force
physics.data.qfrc_applied[:] = KP * jnt_err
# step
physics.step()
video[i] = np.hstack((physics.render(height, width, "y"),
physics.render(height, width, "x")))
display_video(video, framerate=24)
```
--------------------------------
### Analyze Contact Forces and Kinematics
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb
This snippet simulates a Mujoco environment, collects data on contact forces, accelerations, velocities, and number of contacts over time, and then visualizes this data. It iterates through active contacts to extract force and penetration depth. Use this to understand the dynamics of contact interactions in a simulation.
```python
#@title contact-related quantities: {vertical-output: true}
n_steps = 499
# allocate
sim_time = np.zeros(n_steps)
ncon = np.zeros(n_steps)
force = np.zeros((n_steps,3))
velocity = np.zeros((n_steps, physics.model.nv))
penetration = np.zeros(n_steps)
acceleration = np.zeros((n_steps, physics.model.nv))
forcetorque = np.zeros(6)
# random initial rotational velocity:
with physics.reset_context():
physics.data.qvel[3:6] = 2*np.random.randn(3)
# simulate and save data
for i in range(n_steps):
physics.step()
sim_time[i] = physics.data.time
ncon[i] = physics.data.ncon
velocity[i] = physics.data.qvel[:]
acceleration[i] = physics.data.qacc[:]
# iterate over active contacts, save force and distance
for j,c in enumerate(physics.data.contact):
mjlib.mj_contactForce(physics.model.ptr, physics.data.ptr,
j, forcetorque)
force[i] += forcetorque[0:3]
penetration[i] = min(penetration[i], c.dist)
# we could also do
# force[i] += physics.data.qfrc_constraint[0:3]
# do you see why?
# plot
_, ax = plt.subplots(3, 2, sharex=True, figsize=(7, 10))
lines = ax[0,0].plot(sim_time, force)
ax[0,0].set_title('contact force')
ax[0,0].set_ylabel('Newton')
ax[0,0].legend(iter(lines), ('normal z', 'friction x', 'friction y'));
ax[1,0].plot(sim_time, acceleration)
ax[1,0].set_title('acceleration')
ax[1,0].set_ylabel('(meter,radian)/s/s')
ax[2,0].plot(sim_time, velocity)
ax[2,0].set_title('velocity')
ax[2,0].set_ylabel('(meter,radian)/s')
ax[2,0].set_xlabel('second')
ax[0,1].plot(sim_time, ncon)
ax[0,1].set_title('number of contacts')
ax[0,1].set_yticks(range(6))
ax[1,1].plot(sim_time, force[:,0])
ax[1,1].set_yscale('log')
ax[1,1].set_title('normal (z) force - log scale')
ax[1,1].set_ylabel('Newton')
z_gravity = -physics.model.opt.gravity[2]
mg = physics.named.model.body_mass["box_and_sphere"] * z_gravity
mg_line = ax[1,1].plot(sim_time, np.ones(n_steps)*mg, label='m*g', linewidth=1)
ax[1,1].legend()
ax[2,1].plot(sim_time, 1000*penetration)
ax[2,1].set_title('penetration depth')
ax[2,1].set_ylabel('millimeter')
ax[2,1].set_xlabel('second')
plt.tight_layout()
```
--------------------------------
### Use mujoco module directly instead of mjbindings.mjlib
Source: https://github.com/google-deepmind/dm_control/blob/main/migration_guide_1.0.md
Replace imports and calls from dm_control.mujoco.wrapper.mjbindings.mjlib to the direct mujoco module.
```python
import dm_control.mujoco.wrapper.mjbindings
jlib = mjbindings.mjlib
jlib.mj_objectVelocity(
physics.model.ptr, physics.data.ptr,
enums.mjtObj.mjOBJ_SITE,
site_id, vel, 0)
```
```python
import mujoco
jmujoco.mj_objectVelocity(
physics.model.ptr, physics.data.ptr,
mujoco.mjtObj.mjOBJ_SITE,
site_id, vel, 0)
```
--------------------------------
### dm_control Core and Composer Imports
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mujoco/tutorial.ipynb
Imports the basic mujoco wrapper, bindings for MuJoCo library functions, and high-level composer modules. Also includes specific imports for composer variations and the floors arena.
```python
#@title All `dm_control` imports required for this tutorial
# The basic mujoco wrapper.
from dm_control import mujoco
# Access to enums and MuJoCo library functions.
from dm_control.mujoco.wrapper.mjbindings import enums
from dm_control.mujoco.wrapper.mjbindings import mjlib
# Composer high level imports
from dm_control import composer
from dm_control.composer.observation import observable
from dm_control.composer import variation
# Imports for Composer tutorial example
from dm_control.composer.variation import distributions
from dm_control.composer.variation import noises
from dm_control.locomotion.arenas import floors
# Control Suite
from dm_control import suite
# Run through corridor example
from dm_control.locomotion.walkers import cmu_humanoid
from dm_control.locomotion.arenas import corridors as corridor_arenas
from dm_control.locomotion.tasks import corridors as corridor_tasks
# Soccer
from dm_control.locomotion import soccer
# Manipulation
from dm_control import manipulation
```
--------------------------------
### Button Class Implementation
Source: https://github.com/google-deepmind/dm_control/blob/main/tutorial.ipynb
Defines a Button Entity that changes color when pressed with a specific force. It implements `_build`, `_build_observables`, `initialize_episode`, and `after_substep` methods. Use this class to create interactive elements in your simulation.
```python
#@title The `Button` class
NUM_SUBSTEPS = 25 # The number of physics substeps per control timestep.
class Button(composer.Entity):
"""A button Entity which changes colour when pressed with certain force."""
def _build(self, target_force_range=(5, 10)):
self._min_force, self._max_force = target_force_range
self._mjcf_model = mjcf.RootElement()
self._geom = self._mjcf_model.worldbody.add(
'geom', type='cylinder', size=[0.25, 0.02], rgba=[1, 0, 0, 1])
self._site = self._mjcf_model.worldbody.add(
'site', type='cylinder', size=self._geom.size*1.01, rgba=[1, 0, 0, 0])
self._sensor = self._mjcf_model.sensor.add('touch', site=self._site)
self._num_activated_steps = 0
def _build_observables(self):
return ButtonObservables(self)
@property
def mjcf_model(self):
return self._mjcf_model
# Update the activation (and colour) if the desired force is applied.
def _update_activation(self, physics):
current_force = physics.bind(self.touch_sensor).sensordata[0]
self._is_activated = (current_force >= self._min_force and
current_force <= self._max_force)
physics.bind(self._geom).rgba = (
[0, 1, 0, 1] if self._is_activated else [1, 0, 0, 1])
self._num_activated_steps += int(self._is_activated)
def initialize_episode(self, physics, random_state):
self._reward = 0.0
self._num_activated_steps = 0
self._update_activation(physics)
def after_substep(self, physics, random_state):
self._update_activation(physics)
@property
def touch_sensor(self):
return self._sensor
@property
def num_activated_steps(self):
return self._num_activated_steps
```
```python
class ButtonObservables(composer.Observables):
"""A touch sensor which averages contact force over physics substeps."""
@composer.observable
def touch_force(self):
return observable.MJCFFeature('sensordata', self._entity.touch_sensor,
buffer_size=NUM_SUBSTEPS, aggregator='mean')
```
--------------------------------
### Compose MJCF Models with PyMJCF
Source: https://github.com/google-deepmind/dm_control/blob/main/dm_control/mjcf/README.md
Demonstrates composing MJCF models by instantiating reusable components like 'Arm' within a parent 'UpperBody' class. Automatically handles name prefixing to avoid collisions.
```python
from dm_control import mjcf
class Arm:
def __init__(self, name):
self.mjcf_model = mjcf.RootElement(model=name)
self.upper_arm = self.mjcf_model.worldbody.add('body', name='upper_arm')
self.shoulder = self.upper_arm.add('joint', name='shoulder', type='ball')
self.upper_arm.add('geom', name='upper_arm', type='capsule',
pos=[0, 0, -0.15], size=[0.045, 0.15])
self.forearm = self.upper_arm.add('body', name='forearm', pos=[0, 0, -0.3])
self.elbow = self.forearm.add('joint', name='elbow',
type='hinge', axis=[0, 1, 0])
self.forearm.add('geom', name='forearm', type='capsule',
pos=[0, 0, -0.15], size=[0.045, 0.15])
class UpperBody:
def __init__(self):
self.mjcf_model = mjcf.RootElement()
self.mjcf_model.worldbody.add(
'geom', name='torso', type='box', size=[0.15, 0.045, 0.25])
left_shoulder_site = self.mjcf_model.worldbody.add(
'site', size=[1e-6]*3, pos=[-0.15, 0, 0.25])
right_shoulder_site = self.mjcf_model.worldbody.add(
'site', size=[1e-6]*3, pos=[0.15, 0, 0.25])
self.left_arm = Arm(name='left_arm')
left_shoulder_site.attach(self.left_arm.mjcf_model)
self.right_arm = Arm(name='right_arm')
right_shoulder_site.attach(self.right_arm.mjcf_model)
body = UpperBody()
physics = mjcf.Physics.from_mjcf_model(body.mjcf_model)
```