dm_control

GitHub

Google DeepMind's software stack for physics-based simulation and Reinforcement Learning environments, using MuJoCo.

RAW Doc

README (README.md)

dm_control: Google DeepMind Infrastructure for Physics-Based Simulation.

Google DeepMind's software stack for physics-based simulation and Reinforcement
Learning environments, using MuJoCo physics.

An introductory tutorial for this package is available as a Colaboratory
notebook:
[](https://colab.research.google.com/github/google-deepmind/dm_control/blob/main/tutorial.ipynb)

Overview

This package consists of the following "core" components:

- [dm_control.mujoco]: Libraries that provide Python bindings to the MuJoCo
physics engine.

- [dm_control.suite]: A set of Python Reinforcement Learning environments
powered by the MuJoCo physics engine.

- [dm_control.viewer]: An interactive environment viewer.

Additionally, the following components are available for the creation of more
complex control tasks:

- [dm_control.mjcf]: A library for composing and modifying MuJoCo MJCF
models in Python.

- dm_control.composer: A library for defining rich RL environments from
reusable, self-contained components.

- [dm_control.locomotion]: Additional libraries for custom tasks.

- [dm_control.locomotion.soccer]: Multi-agent soccer tasks.

If you use this package, please cite our accompanying [publication]:

text
@article{tunyasuvunakool2020,
title = {dm_control: Software and tasks for continuous control},
journal = {Software Impacts},
volume = {6},
pages = {100022},
year = {2020},
issn = {2665-9638},
doi = {https://doi.org/10.1016/j.simpa.2020.100022},
url = {https://www.sciencedirect.com/science/article/pii/S2665963820300099},
author = {Saran Tunyasuvunakool and Alistair Muldal and Yotam Doron and
Siqi Liu and Steven Bohez and Josh Merel and Tom Erez and
Timothy Lillicrap and Nicolas Heess and Yuval Tassa},
}

Installation

Install dm_control from PyPI by running

sh
pip install dm_control

Note: dm_control cannot be installed in "editable" mode (i.e. pip

install -e).

> While dm_control has been largely updated to use the pybind11-based bindings

provided via the mujoco package, at this time it still relies on some legacy

components that are automatically generated from MuJoCo header files in a way

that is incompatible with editable mode. Attempting to install dm_control in

editable mode will result in import errors like:

> ``

ImportError: cannot import name 'constants' from partially initialized module 'dm_control.mujoco.wrapper.mjbindings' ...

`

> The solution is to pip uninstall dm_control and then reinstall it without

the -e flag.

Versioning

Starting from version 1.0.0, we adopt semantic versioning.

Prior to version 1.0.0, the dm_control Python package was versioned 0.0.N,
where
N was an internal revision number that increased by an arbitrary amount
at every single Git commit.

If you want to install an unreleased version of dm_control directly from our
repository, you can do so by running
pip install
git+https://github.com/google-deepmind/dm_control.git.

Rendering

The MuJoCo Python bindings support three different OpenGL rendering backends:
EGL (headless, hardware-accelerated), GLFW (windowed, hardware-accelerated), and
OSMesa (purely software-based). At least one of these three backends must be
available in order render through
dm_control.

* Hardware rendering with a windowing system is supported via GLFW and GLEW.
On Linux these can be installed using your distribution's package manager.
For example, on Debian and Ubuntu, this can be done by running
sudo apt-get
install libglfw3 libglew2.0. Please note that:

- [dm_control.viewer] can only be used with GLFW.
- GLFW will not work on headless machines.

* "Headless" hardware rendering (i.e. without a windowing system such as X11)
requires [EXT_platform_device] support in the EGL driver. Recent Nvidia
drivers support this. You will also need GLEW. On Debian and Ubuntu, this
can be installed via
sudo apt-get install libglew2.0.

* Software rendering requires GLX and OSMesa. On Debian and Ubuntu these can
be installed using
sudo apt-get install libgl1-mesa-glx libosmesa6.

By default, dm_control will attempt to use GLFW first, then EGL, then OSMesa.
You can also specify a particular backend to use by setting the
MUJOCO_GL=
environment variable to
"glfw", "egl", or "osmesa", respectively. When
rendering with EGL, you can also specify which GPU to use for rendering by
setting the environment variable
MUJOCO_EGL_DEVICE_ID= to the target GPU ID.

Additional instructions for Homebrew users on macOS

1. The above instructions using pip should work, provided that you use a
Python interpreter that is installed by Homebrew (rather than the
system-default one).

2. Before running, the DYLD_LIBRARY_PATH environment variable needs to be
updated with the path to the GLFW library. This can be done by running
export DYLD_LIBRARY_PATH=$(brew --prefix)/lib:$DYLD_LIBRARY_PATH.

[EXT_platform_device]: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_platform_device.txt
[Releases page on the MuJoCo GitHub repository]: https://github.com/google-deepmind/mujoco/releases
[MuJoCo website]: https://mujoco.org/
[publication]: https://doi.org/10.1016/j.simpa.2020.100022
[
ctypes]: https://docs.python.org/3/library/ctypes.html
[
dm_control.mjcf]: dm_control/mjcf/README.md
[
dm_control.mujoco]: dm_control/mujoco/README.md
[
dm_control.suite]: dm_control/suite/README.md
[
dm_control.viewer]: dm_control/viewer/README.md
[
dm_control.locomotion]: dm_control/locomotion/README.md
[
dm_control.locomotion.soccer]: dm_control/locomotion/soccer/README.md

---

CONTRIBUTING (CONTRIBUTING.md)

How to Contribute

We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.

Contributor License Agreement

Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution,
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.

You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.

Code reviews

All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
GitHub Help for more
information on using pull requests.

---

Migration Guide 1.0 (migration_guide_1.0.md)

dm_control: 1.0.0 update guide

With 1.0.0, we changed the way dm_control uses the MuJoCo physics simulator, and
migrated to new python bindings. For most users, this will require no code
changes. However, some more advanced users will need to change their code
slightly. Below is a list of known changes that need to be made. Please contact
us if you've had to make any further changes that are not listed below.

Required changes

dm_control.mujoco.wrapper.mjbindings.types should not be used This module was
specific to the previous implementation of the dm_control python bindings. For
example,
types.MJRRECT should be replaced with mujoco.MjrRect.

MjData.contact has changed

MjData.contact (often accessed as Physics.data.contact) used to offer an
interface similar to a numpy structured array. For example,
data.contact.geom1
used to be a numpy array of geom IDs.

With the recent update, MjData.contact will appear as a list of MjContact
structs. Code that used to operate on the structured array will have to change.
For example, the following code would get an array containing the contact
distance for all contacts that involve geom_id:

text
contact = physics.data.contact
involves_geom = (contact.geom1 == geom_id) | (contact.geom2 == geom_id)
dists = contact[involves_geom].dist

After the upgrade:

text
contacts = physics.data.contact
dists = [
c.dist for c in contacts if c.geom1 == geom_id or c.geom2 == geom_id
]

.ptr.contents will not work

Code that accesses .ptr.contents on objects such as MjvScene will need to be
updated. In most cases, simply using
scene instead of scene.ptr.contents
will work.

Different exceptions will be thrown from MuJoCo

Code (mostly in tests) that expects dm_control.mujoco.wrapper.core.Error
exceptions, will receive different exceptions, thrown by the
mujoco library.
These will often be
ValueError (for errors caused by input parameters), or
mujoco.FatalError (for low level errors in MuJoCo).

Better error handling

The Python interpreter no longer crashes out when
mju_error
is called. Instead,
mju_error calls are translated into mujoco.FatalError
exceptions in Python.

When Python callables are used as user-defined MuJoCo callbacks, they are now
permitted to raise exceptions, which will be correctly propagated back down the
Python call stack.

Change of signature for mj_saveModel

mj_saveModel
now expects a numpy
uint8 array rather than a ctypes string buffer, and
doesn't require a "size" parameter (it's inferred from the numpy array size).

Before:

text
model_size = mjlib.mj_sizeModel(model.ptr)
buf = ctypes.create_string_buffer(model_size)
mjlib.mj_saveModel(model.ptr, None, buf, model_size)

After:

text
model_size = mujoco.mj_sizeModel(model)
buf = np.empty(model_size, np.uint8)
mjlib.mj_saveModel(model.ptr, None, buf)

Optional changes

The following are some changes that can make your code more concise, but are not
required for it to continue working.

Use the mujoco module directly, instead of mjlib

Existing code that uses dm_control.mujoco.wrapper.mjbindings.mjlib can
directly replace these modules with mujoco. Code that uses
enums or
constants from dm_control.mujoco.wrapper.mjbindings can also use mujoco,
with slight type changes. All mujoco functions will accept the old enum values
or the new ones.

Before:

text
import dm_control.mujoco.wrapper.mjbindings
mjlib = mjbindings.mjlib

mjlib.mj_objectVelocity(
physics.model.ptr, physics.data.ptr,
enums.mjtObj.mjOBJ_SITE,
site_id, vel, 0)

After:

text
import mujoco

mujoco.mj_objectVelocity(
physics.model.ptr, physics.data.ptr,
mujoco.mjtObj.mjOBJ_SITE,
site_id, vel, 0)

Assume structs are correctly initialized and memory is managed

The MuJoCo C API includes functions that manage the memory for certain structs.
Those include functions that allocate memory (e.g.
mj_makeModel,
mj_makeData, mjv_makeScene), functions that free memory (e.g.
mj_deleteModel, mj_deleteData, mjv_freeScene), and functions that reset a
struct to its default value (e.g.
mjv_defaultOption, mj_defaultVisual).

The new Python bindings take care of this. Wrapper classes like
mujoco.MjvScene will automatically allocate memory when they're created, and
release it when they're deleted, and be created with default values set.

As such, allocating and freeing functions are not available through the mujoco
Python bindings. The "default" functions are still available, but in most cases
the calls can simply be removed.

Before:

text
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)

After:

text
from dm_control.mujoco import wrapper

scene_option = wrapper.core.MjvOption()

---

Requirements (requirements.txt)

absl-py==2.3.1
dm-env==1.6
dm-tree==0.1.9
glfw==2.9.0
h5py==3.14.0
labmaze==1.0.6
lxml==6.0.1
mock==5.2.0
mujoco==3.11.0
numpy==2.3.2; python_version >= '3.11'
numpy==2.2.6; python_version == '3.10'
numpy==2.0.2; python_version == '3.9'
pillow==11.3.0
protobuf==3.19.4
pyopengl==3.1.10
pyparsing==3.2.3
pytest==8.4.1
pytest-xdist==3.8.0
pytest-timeout==2.4.0
requests==2.32.5
scipy==1.16.1; python_version >= '3.11'
scipy==1.15.3; python_version == '3.10'
scipy==1.13.1; python_version == '3.9'
setuptools==80.9.0
tqdm==4.67.1

---

Dm Control/Blender/Mujoco Exporter/README (dm_control/blender/mujoco_exporter/README.md)

Export Mujoco models from Blender

Prerequisites

The MuJoCo exporter works as Blender addon, tested with ver 3.4.1. You can
download Blender from https://www.blender.org.

Installation

Preparing a plugin installer

The install.sh command will deploy the installable version of the plugin to
./addons/mujoco_model_exporter. This folder should be zipped:

shell
$ cd ./addons && zip -r mujoco_model_exporter.zip mujoco_model_exporter/*

Installing the plugin in Blender

Open Blender and select Edit/Preferences menu option.

{style="display:block;margin:auto"}

Clicking the Install button will open a file selection dialog that will allow
you to select the .zip archive with the plugin.

The next window will follow, listing the installed plugin and allowing you to
enable it.

{style="display:block;margin:auto"}

Check the checkbox next to its name to enable it.

Modelling for Mujoco.

The plugin was designed to allow the artists to keep using core Blender features
when building models for Mujoco.

feature | Mujoco | Blender
-------------- | ------------------------- | -----------------------------------
kinematic tree | hierarchy of Bodies | Armatures or hierarchies of Objects
geometry | Geoms | Meshes
materials | Material + Texture assets | Material + Texture definitions
lighting | Lights | Lights

Node naming

The exporter will copy the names of the bones, meshes and lights. Mujoco joints
will be named after the bone that owns the respective constraint, with a postfix
denoting the degree of freedom they enable.

Modelling kinematic trees using Armatures and IK

Blender Armatures allow to model kinematic capabilities of a Blender model. They
comprise a tree of bones, each of which can be further extended with IK
Constraints.

Only the bones affected by an IK chain will receive appropriate degrees of
freedom. This means that if you export a model without any IK chains, it will be
exported as a static model.

#### IK Constraints and bone limits

IK constraints offer the easiest way to verify how a kinematic chain would
behave in a physical environment. For that reason we chose to use them, along
with IK bone limits, to model Mujoco joints.

* Select the bone at the end of a kinematic chain,

* Add an IK Bone Constraint to it.
This webpage
contains detailed instructions.

* Add a target bone to the scene and use it as the IK constraint's target.

* Adjust the Chain Length value to reflect the number of parent bones that
should become a part of this IK chain.

* For each of the bones in the chain, visit the Bone/Inverse Kinematics tab
and adjust the locks and bone limits.

NOTE: you can take advantage of a helpful limit visualization gizmo.

Armature free joints.

Armatures form the kinematic trees, so it makes sense to give their roots all 6
degrees of freedom.

This behavior can be changed by disabling the Armature freejoint export
option.

Modelling the geometry

Mujoco uses parametric geometry comprised of primitive shapes such
as cubes, spheres and capsules. It does support triangle based mesh geometry
however.

Blender on the other hand deals exclusively in meshes, and even though it
contains a palette of such primitive shapes, these are not parametric.

#### MSH files

The exporter therefore exports the geometry as meshes. All meshes referenced by
the scene are exported into Mujoco's native .msh format.

When this plugin was created, the native .msh format was the only format to
support texture mapping. Since MuJoCo 2.1.2,
.obj files are supported. The
.msh format is expected to be deprecated and removed soon. Until this plugin
is updated to output
.obj files we recommend all user to convert their .msh
files to
.obj files using this utility.

#### Phong lighting model and lack of support for Cycles nodes

Mujoco implements a forward rendering model with Phong lightning and support for
reflective surfaces.

Mujoco material definition
is fixed and limited to:

* base color (diffuse color)
* specularity coefficient
* smoothness coefficient
* reflectiveness coefficient

These parameters translate well to Blender's default material definition, which
should be used to model the materials exported to Mujoco.

Due to the diversity and open-ended nature of Cycle's material nodes, the choice
was made not to support materials defined using them.

#### Division of meshes that employ multiple materials

Mujoco renderer supports a single material per mesh, in contrast to Blender's
multi material model. In order to support meshes with multiple materials, the
exporter divides them into submeshes, each of which uses a single material.

Since Blender materials are applied to faces, and a single face may only have a
single material assigned, there is no risk that the subdivided mesh will exhibit
any overlapping artifacts.

#### Effect of mesh division on inertia and mass.

The exported submeshes will have different geometry and volume than the
original. This will affect the mass and inertia of the geom that uses the
exported mesh.

Please note that Mujoco derives these quantities not from the mesh itself, but
rather from the convex hull calculated for it. The sum of hulls of subdivided
meshes are not guaranteed to be equal to the hull of the original mesh.

This phenomenon is illustrated on the image below.

Blender | Mujoco renderer | Mujoco convex hulls
----------------------------- | ------------------------------- | -------------------
| |

A different material was assigned to 2 out of 6 rectangular faces of the right
cube, causing that mesh to be split into two submeshes.

While they render well in Mujoco, the Moiré effect visible on the convex hull
comes from two overlapping hulls, each with a different volume.

#### Double-sided materials

Double sided materials cause the meshes (or faces) that use them to be exported
with the faces duplicated with the reverse face winding order. This is because
Mujoco renderer does not support any other face culling modes than back face
culling.

CAUTION: Because this operation affects the exported geometry, it may
indirectly affect the physical properties of a geom that references that mesh,
such as its mass and inertia. Please use this feature with caution.

#### Scaling

CAUTION: If you are using the scaling transform, the exporter will modify your
scene!

The exporter will by default reset the scaling transform on all bones and meshes
to ensure affine reference frame transformations.

This operation can be undo'ed after the exporter is completed, but the exporter
doesn't undo it automatically!

Textures

NOTE: This feature will be added in the next version of the exporter.

#### One texture channel

Mujoco renderer supports a single texture channel. It's therefore advised to use
a single UV map for meshes that are to be exported to Mujoco.

#### Choice between atlases and individual textures

Mujoco's fixed rendering pipeline is quite fast, and handles both variants well.
Therefore we leave it up to the artist to decide which it prefers using.

Please keep in mind that the exporter doesn't export the texture assets. Those
should be copied into the folder with the exported model manually.

---

Dm Control/Locomotion/README (dm_control/locomotion/README.md)

Locomotion task library

This package contains reusable components for defining control tasks that are
related to locomotion. New users are encouraged to start by browsing the
examples/ subdirectory, which contains preconfigured RL environments
associated with various research papers. These examples can serve as starting
points or be customized to design new environments using the components
available from this library.

<p float="left">
<img src="walls.png" height="200">
<img src="gaps.png" height="200">
</p>

Terminology

This library facilitates the creation of environments that require walkers
to perform a task in an arena.

- walkers refer to detached bodies that can move around in the
environment.

- arenas refer to the surroundings in which the walkers and possibly other
objects exist.

- tasks refer to the specification of observations and rewards that are
passed from the "environment" to the "agent", along with runtime details
such as initialization and termination logic.

Installation and requirements

See [the documentation for dm_control][installation-and-requirements].

Quickstart

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))

[dm_control.viewer] can also be used to visualize and interact with the
environment, e.g.:

python
from dm_control import viewer

viewer.launch(environment_loader=basic_cmu_2019.cmu_humanoid_run_walls)

Publications

This library contains environments that were adapted from several research
papers. Relevant references include:

- [Emergence of Locomotion Behaviours in Rich Environments (2017)][heess2017].

- [Learning human behaviors from motion capture by adversarial imitation
(2017)][merel2017].

- [Hierarchical visuomotor control of humanoids (2019)][merel2019a].

- [Neural probabilistic motor primitives for humanoid control (2019)][merel2019b].

- [Deep neuroethology of a virtual rodent (2020)][merel2020].

- [CoMic: Complementary Task Learning & Mimicry for Reusable Skills (2020)][hasenclever2020]

[installation-and-requirements]: ../../README.md#installation-and-requirements
[
dm_control.viewer]: ../viewer/README.md
[heess2017]: https://arxiv.org/abs/1707.02286
[merel2017]: https://arxiv.org/abs/1707.02201
[merel2019a]: https://arxiv.org/abs/1811.09656
[merel2019b]: https://arxiv.org/abs/1811.11711
[merel2020]: https://openreview.net/pdf?id=SyxrxR4KPS
[hasenclever2020]: http://proceedings.mlr.press/v119/hasenclever20a.html

---

Dm Control/Locomotion/Soccer/README (dm_control/locomotion/soccer/README.md)

DeepMind MuJoCo Multi-Agent Soccer Environment.

This submodule contains the components and environment used in the following
works.

* [Emergent Coordination through Competition][boxhead]
(dynamic team play,
defensive team play).

* [From Motor Control to Team Play in Simulated Humanoid Football][humanoid].

Quickstart

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]))

Rewards

The environment provides a reward of +1 to each player when their team scores a
goal, -1 when their team concedes a goal, or 0 if neither team scored on the
current timestep.

In addition to the sparse reward returned the environment, the player
observations also contain various environment statistics that may be used to
derive custom per-player shaping rewards. See
environment.observation_spec()
for the additional statistics available to the agents.

Episode terminations

If terminate_on_goal is set to True, episodes will terminate immediately
with a discount factor of 0 when either side scores a goal or if the
time_limit elapsed. If neither team scores within this time then the episode
will terminate with a discount factor of
1.0.

If terminate_on_goal is set to False, players and ball positions are
randomly initialized if either team scores a goal. Episodes always terminate
after
time_limit with a discount factor of 1.0.

Environment Viewer

To visualize an example environment instance using the dm_control interactive
viewer, execute
dm_control/locomotion/soccer/explore.py.

[boxhead]: http://arxiv.org/abs/1902.07151
[humanoid]: https://arxiv.org/abs/2105.12196

---

Dm Control/Locomotion/Tasks/Reference Pose/README (dm_control/locomotion/tasks/reference_pose/README.md)

Reference pose tasks

This directory contains components to define tasks based on reference poses (e.g
motion capture data) as well as a motion capture tracking tasks. The tasks and
associated utils were developed as part of
[CoMic: Complementary Task Learning & Mimicry for Reusable Skills (2020)][hasenclever2020].

The reference data is stored in HDF5 files, which can be loaded using the
HDF5TrajectoryLoader class in dm_control/locomotion/mocap/loader.py. To
download the data used in the CoMic project, please use
dm_control/locomotion/mocap/cmu_mocap_data.py. In the reference pose tasks,
reference trajectories are represented as
Trajectory objects (see
dm_control/locomotion/mocap/trajectory.py). For an example of how to construct
a task, see
dm_control/locomotion/examples/cmu_2020_tracking.py.

[hasenclever2020]: https://proceedings.icml.cc/static/paper_files/icml/2020/5013-Paper.pdf

---

Dm Control/Mjcf/README (dm_control/mjcf/README.md)

PyMJCF

IMPORTANT: If you find yourself stuck while using PyMJCF, check out the various
IMPORTANT boxes on this page and the Common gotchas section
at the bottom to see if any of them is relevant.

This library provides a Python object model for MuJoCo's XML-based
MJCF physics modeling language. The
goal of the library is to allow users to easily interact with and modify MJCF
models in Python, similarly to what the JavaScript DOM does for HTML.

A key feature of this library is the ability to easily compose multiple separate
MJCF models into a larger one. Disambiguation of duplicated names from different
models, or multiple instances of the same model, is handled automatically.

The following snippet provides a quick example of this library's typical use
case. Here, the
UpperBody class can simply instantiate two copies of Arm,
thus reducing code duplication. The names of bodies, joints, or geoms of each
Arm are automatically prefixed by their parent's names, and so no name
collision occurs.

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)

Basic operations

Creating an MJCF model

In PyMJCF, the basic building block of a model is an mjcf.Element. This
corresponds to an element in the generated XML. However, user code _cannot_
instantiate a generic
mjcf.Element object directly.

A valid model always consists of a single root <mujoco> element. This is
represented as the special
mjcf.RootElement type in PyMJCF, which _can_ be
instantiated in user code to create an empty model.

python
from dm_control import mjcf

mjcf_model = mjcf.RootElement()
print(mjcf_model) # MJCF Element: <mujoco/>

Adding new elements

Attributes of the new element can be passed as kwargs:

python
my_box = mjcf_model.worldbody.add('geom', name='my_box',
type='box', pos=[0, .1, 0])
print(my_box) # MJCF Element: <geom name="my_box" type="box" pos="0. 0.1 0."/>

Parsing an existing XML document

Alternatively, if an existing XML file already exists, PyMJCF can parse it to
create a Python object:

python
from dm_control import mjcf

Parse from path


mjcf_model = mjcf.from_path(filename)

Parse from file


with open(filename) as f:
mjcf_model = mjcf.from_file(f)

Parse from string


with open(filename) as f:
xml_string = f.read()
mjcf_model = mjcf.from_xml_string(xml_string)

print(type(mjcf_model)) # <type 'mjcf.RootElement'>

Traversing through a model

Consider the following MJCF model:

xml
<mujoco model="test">
<default>
<default class="brick">
<geom rgba="1 0 0 1"/>
</default>
</default>
<worldbody>
<body name="foo">
<freejoint/>
<inertial pos="0 0 0" mass="1"/>
<body name="bar">
<joint name="my_hinge" type="hinge"/>
<geom name="my_geom" pos="0 1 2" class="brick"/>
</body>
</body>
</worldbody>
</mujoco>

The child elements and XML attributes of an Element object are exposed as
Python attributes. These attributes all have the same names as their XML
counterparts, with one exception: the
class XML attribute is named dclass in
order to avoid a clash with the Python
class keyword:

python
my_geom = mjcf_model.worldbody.body['foo'].body['bar'].geom['my_geom']
print(isinstance(mjcf_model, mjcf.Element)) # True
print(my_geom.name) # 'my_geom'
print(my_geom.pos) # np.array([0., 1., 2.], dtype=float)
print(my_geom.class) # SyntaxError
print(my_geom.dclass) # 'brick'

Note that attribute values in the object model are not affected by defaults:

python
print(mjcf_model.default.default['brick'].geom.rgba)  # [1, 0, 0, 1]
print(my_geom.rgba) # None

Finding elements without traversing

We can also find elements directly without having to traverse through the object
hierarchy:

python
found_geom = mjcf_model.find('geom', 'my_geom')
print(found_geom == my_geom) # True

Find all elements of a given type:

python

Note that <freejoint> is also considered a joint


joints = mjcf_model.find_all('joint')
print(len(joints)) # 2
print(joints[0] == mjcf_model.worldbody.body['foo'].freejoint) # True
print(joints[1] == mjcf_model.worldbody.body['foo'].body['bar'].joint[0]) # True

Note that the order of elements returned by find_all is the same as the order
in which they are declared in the model.

Modifying XML attributes

Attributes can be modified, added, or removed:

python
my_geom.pos = [1, 2, 3]
print(my_geom.pos) # np.array([1., 2., 3.], dtype=float)
my_geom.quat = [0, 1, 0, 0]
print(my_geom.quat) # np.array([0., 1., 0., 0.], dtype=float)
del my_geom.quat
print(my_geom.quat) # None

Schema violations result in errors:

python
print(my_geom.poss)  # raise AttributeError (no child or attribute called poss)
my_geom.pos = 'invalid' # raise ValueError (assigning string to array)
my_geom.pos = [1, 2, 3, 4, 5, 6] # raise ValueError (array length is too long)

raise ValueError (mass is a required attribute of <inertial>)


del mjcf_model.find('body', 'foo').inertial.mass

Uniqueness of identifiers

PyMJCF enforces the uniqueness of "identifier" attributes within a model.
Identifiers consist of the
class attribute of a <default>, and all name
attributes. Their uniqueness is only enforced within a particular namespace. For
example, a
<body> is allowed to have the same name as a <geom>, whereas
<position> and <velocity> actuators cannot have the same name.

python
mjcf_model.worldbody.add('geom', name='my_geom')
foo = mjcf_model.worldbody.find('body', 'foo')
foo.add('my_geom') # Error, duplicated geom name
foo.add('foo') # OK, a geom can have the same name as a body
mjcf_model.find('geom', 'foo').name = 'my_geom' # Error, duplicated geom name

Reference attributes

Some attributes are references to other elements. For example, the joint
attribute of an actuator refers to a
<joint> element in the model.

An mjcf.Element can be directly assigned to these reference attributes:

python
my_hinge = mjcf_model.find('joint', 'my_hinge')
my_actuator = mjcf_model.actuator.add('velocity', joint=my_hinge)

This is the recommended way to assign reference attributes, since it guarantees
that the reference is not invalidated if the referenced element is renamed.
Alternatively, a string can also be assigned to reference attributes. In this
case, PyMJCF does not attempt to verify that the named element actually
exists in the model.

IMPORTANT: If the element being referenced is in a different model to the
reference attribute (e.g. in an attached model), the reference must be
created by directly assigning an
mjcf.Element object to the attribute rather
than a string. Strings assigned to reference attributes cannot contain '/',
since they are automatically scoped by PyMJCF upon attachment.

Attaching models

In this section we will refer to an mjcf.RootElement simply as a "model".
Models can be _attached_ to other models in order to create compositional
scenes.

python
arena = mjcf.RootElement()
arena.worldbody.add('geom', name='ground', type='plane', size=[10, 10, 1])

robot = mjcf.from_xml_file('robot.xml')
arena.attach(robot)

We refer to arena as the _parent model_, and robot as the _child model_ (or
the _attached model_).

Attachment frames

When a model is attached to a site, an empty body is created in the parent
model. This empty body is called an _attachment frame_.

The attachment frame is created as a child of the body that contains the
attachment site, and it has the same position and orientation as the site. When
the XML is generated, the attachment frame's contents shadow the contents of the
attached model's
<worldbody>. The attachment frame's name in the generated XML
is the child's
fully/qualified/prefix/. The trailing slash ensures that the
attachment frame's name never collides with a user-defined body.

More concretely, if we have the following parent and child models:

xml
<mujoco model="parent">
<worldbody>
<body>
<geom name="foo" type="box" pos="-0.2 0 0.3" size="0.5 0.3 0.1"/>
<site name="attachment_site" pos="1. 2. 3." quat="1. 0. 0. 1."/>
</body>
</worldbody>
</mujoco>

<mujoco model="child">
<worldbody>
<geom name="bar" type="box" pos="0.5 0.25 1." size="0.1 0.2 0.3"/>
</worldbody>
</mujoco>

Then the final generated XML will be:

xml
<mujoco model="parent">
<worldbody>
<body>
<geom name="foo" type="box" pos="-0.2 0 0.3" size="0.5 0.3 0.1"/>
<site name="attachment_site" pos="1. 2. 3." quat="1. 0. 0. 1."/>
<body name="child/" pos="1. 2. 3." quat="1. 0. 0. 1.">
<geom name="child/my_box" type="box" pos="0.5 0.25 1." size="0.1 0.2 0.3"/>
</body>
</body>
</worldbody>
</mujoco>

IMPORTANT: The attachment frame is created _transparently_ to the user. In
particular, it is NOT treated as a regular
body by PyMJCF. Its name in the
generated XML should be considered implementation detail and should NOT be
relied on.

Having said that, it is sometimes necessary to access the attachment frame, for
example to add a joint between the parent and the child model. The easiest way
to do this is to hold a reference to the object returned by a call to
attach:

python
attachment_frame = parent_model.attach('child')
attachment_frame.add('freejoint')

Alternatively, if a model has already been attached, the find function can be
used with the
attachment_frame namespace in order to retrieve the attachment
frame. The
get_attachment_frame convenience function in mjcf.traversal_utils
can find the child model's attachment frame without needing access to the parent
model.

python
frame_1 = parent_model.find('attachment_frame', 'child')

Convenience function: get the attachment frame directly from a child model


frame_2 = mjcf.traversal_utils.get_attachment_frame(child_model)
print(frame_1 == frame_2) # True

IMPORTANT: To encourage good modeling practices, the only allowed direct
children of an attachment frame are
<joint> and <inertial>. Other types of
elements should instead add be added to the
<worldbody> of the attached model.

Element ownership

IMPORTANT: Elements of child models do not appear when traversing through
the parent model.

Default classes

PyMJCF ensures that default classes of a parent model _never_ affect any of its
child models. This minimises the possibility that two models become subtly
"incompatible", as a model always behaves in the same way regardless of what it
is attached to.

The way that PyMJCF achieves this in practice is to move everything in a model's
global
<default> context into a default class named /. In other words, a
PyMJCF-generated model never has anything in the global default context.
Instead, the generated model always looks like:

xml
<mujoco>
<default>
<default class="/">

<geom rgba="1. 0. 0. 1."/>
</default>
</default>
</mujoco>

IMPORTANT: This transformation is _transparent_ to the user. Within Python, the
above geom rgba setting is accessed as if it were a global default, i.e.
mjcf_model.default.geom.rgba. Generally speaking, users should never have to
worry about PyMJCF's internal handling of defaults.

When a model is attached, its / default class turns into
fully/qualified/prefix/. The trailing slash ensures that this transformation
never conflicts with a user-named default class. More specifically, if we have
the following parent and child models:

xml
<mujoco model="parent">
<default>
<geom rgba="1. 0. 0. 1."/>
<default class="green">
<geom rgba="0. 1. 0. 1."/>
</default>
</default>
</mujoco>

<mujoco model="child">
<default>
<joint range="0. 1."/>
<default class="stiff">
<joint stiffness="0.1"/>
</default>
</default>
</mujoco>

Then the final generated XML will be:

xml
<mujoco model="parent">
<default>
<default class="/">
<geom rgba="1. 0. 0. 1."/>
<default class="green">
<geom rgba="0. 1. 0. 1."/>
</default>
</default>
<default class="child/">
<joint range="0. 1."/>
<default class="child/stiff">
<joint stiffness="0.1"/>
</default>
</default>
</default>
</mujoco>

Global options

A model cannot be attached to another model if _any_ of the global options are
different. Global options consist of attributes of
<compiler>, <option>,
<size>, and <visual>. As with the handling of default classes, this is to
ensure that two models do not become subtly "incompatible". For example:

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!

An option is considered to be conflicting only if _both_ models _explicitly_
assign different values to it. An example of where conflicting options can
become problematic is:

python
model_1 = mjcf.RootElement()

model_2 = mjcf.RootElement()
model_2.compiler.angle = 'degree'

model_1.attach(model_2) # No error, but all angles in model_1 are now wrong!

Here, model_1 assumes MuJoCo's default angle unit of radians. Since it does
not explicitly assign a value to
compiler.angle, PyMJCF does not detect a
conflict with
angle=degree in model_2. All angles in model_1 are now
incorrectly interpreted as degrees.

Elements outside of <worldbody>

All children of non-worldbody elements, e.g. actuators or tendons, are
automatically merged in to appropriate places when a model is attached. Named
elements are prefixed as previously described.

Common gotchas

Use foo.dclass, not ~~foo.class~~

The class XML attribute corresponds to the dclass Python attribute in
PyMJCF. This is because
class is a reserved keyword in Python. However, it is
OK to use
'class' in getattr.

xml
<geom name="my_geom" class="red"/>

python
print(my_geom.class)   # SyntaxError
print(my_geom.dclass) # 'red'
print(getattr(my_geom, 'class')) # 'red'

foo.type and foo.range are fine

The type and range attributes will trigger syntax highlighting in Cider, but
they are NOT reserved words in Python.

python
my_geom.type = 'capsule'  # OK!
my_joint.range = [-1, 1] # OK!

A model can only be attached once

A model cannot be attached twice. If you require multiple copies of the same
model in your simulation, make a
deepcopy. Preferably, though, define a class
that constructs the model and just call the constructor as many times as
required.

---

Dm Control/Mujoco/README (dm_control/mujoco/README.md)

MuJoCo Python bindings

This submodule contains Python bindings for the MuJoCo physics engine. See our
tech report for further details.

Quickstart

python
from dm_control import mujoco

Load a model from an MJCF XML string.


xml_string = """
<mujoco>
<worldbody>
<light name="top" pos="0 0 1.5"/>
<geom name="floor" type="plane" size="1 1 .1"/>
<body name="box" pos="0 0 .3">
<joint name="up_down" type="slide" axis="0 0 1"/>
<geom name="box" type="box" size=".2 .2 .2" rgba="1 0 0 1"/>
<geom name="sphere" pos=".2 .2 .2" size=".1" rgba="0 1 0 1"/>
</body>
</worldbody>
</mujoco>
"""
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]

---

Dm Control/Mujoco/Wrapper/README (dm_control/mujoco/wrapper/README.md)

MuJoCo Wrapper

This package contains Python bindings for the [MuJoCo physics engine][1] using
[
ctypes][2]. The bindings and some higher-level wrapper code are automatically
generated from MuJoCo's header files by
dm_control/autowrap/autowrap.py.

The main entry point for users of the generated bindings is
[
dm_control.mujoco][3].

[1]: http://mujoco.org/
[2]: https://docs.python.org/2/library/ctypes.html
[3]: ../README.md

---

Dm Control/Suite/README (dm_control/suite/README.md)

DeepMind Control Suite.

This submodule contains the domains and tasks described in the
DeepMind Control Suite tech report.

Quickstart

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)

Illustration video

Below is a video montage of solved Control Suite tasks, with reward
visualisation enabled.

[](https://www.youtube.com/watch?v=rAai4QzcYbs)


Quadruped domain [April 2019]

Roughly based on the 'ant' model introduced by Schulman et al. 2015. Main modifications to the body are:

- 4 DoFs per leg, 1 constraining tendon.
- 3 actuators per leg: 'yaw', 'lift', 'extend'.
- Filtered position actuators with timescale of 100ms.
- Sensors include an IMU, force/torque sensors, and rangefinders.

Four tasks:

- walk and run: self-right the body then move forward at a desired speed.
-
escape: escape a bowl-shaped random terrain (uses rangefinders).
-
fetch, go to a moving ball and bring it to a target.

All behaviors in the video below were trained with Abdolmaleki et al's
MPO
.

[](https://www.youtube.com/watch?v=RhRLjbb7pBE)

---

Dm Control/Third Party/README (dm_control/third_party/README.md)

Third-party assets

This directory contains third-party assets which are licensed separately to the
the rest of
dm_control. Please see the LICENSE files within the individual
subpackages for further details.

---

Dm Control/Third Party/Ant/README (dm_control/third_party/ant/README.md)

Ant MJCF model

This model is intended for use as a walker in dm_control.locomotion. It is
based on Philipp Moritz's original Ant model, which is available from
https://github.com/pcmoritz/mujoco-control-ant. Substantial modifications
have been made to the original model and therefore this model should be regarded
as distinct for practical purposes.

---

Dm Control/Viewer/README (dm_control/viewer/README.md)

Interactive environment viewer

The dm_control.viewer library can be used to visualize and interact with a
control environment. The following example shows how to launch the viewer with
an environment from the Control Suite:

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)

For convenience we also provide a viewer launch script for the Control Suite in
dm_control/suite/explore.py.

Viewing the environment with a policy in the loop

The viewer is also capable of running the environment with a policy in the loop
to provide actions. This is done by passing the optional
policy argument to
viewer.launch. The policy should be a callable that accepts a TimeStep and
returns a numpy array of actions conforming to
environment.action_spec(). The
example below shows how to execute a random uniform policy using the viewer:

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)

Keyboard and mouse controls

The viewer contains a built in help screen that can be brought up by pressing
F1`. You will find a comprehensive description of keyboard and mouse controls
there.

Status view

Displays status of the simulation:

- State - Current status of the Runtime state machine.
- Time - Simulation clock accompanied by the current setting of time
multiplier.
- CPU - How much time per frame does physics simulation consume.
- FPS - How many frames per second is the application rendering.
- Camera - Name of the active camera.
- Paused - Is the simulation paused?
- Error - Recently caught error message.

---