Skip to content

Commit aca83ff

Browse files
nimrod-gileadicopybara-github
authored andcommitted
Add a document about migrating dm_control client code after MuJoCo python bindings change.
PiperOrigin-RevId: 433559491 Change-Id: Ia64262001ce02a6e62391e780e0ad962409ca644
1 parent 6bbaf99 commit aca83ff

File tree

2 files changed

+151
-1
lines changed

2 files changed

+151
-1
lines changed

migration_guide_1.0.md

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# dm_control: 1.0.0 update guide
2+
3+
With 1.0.0, we changed the way dm_control uses the MuJoCo physics simulator, and
4+
migrated to new python bindings. For most users, this will require no code
5+
changes. However, some more advanced users will need to change their code
6+
slightly. Below is a list of known changes that need to be made. Please contact
7+
us if you've had to make any further changes that are not listed below.
8+
9+
## Required changes
10+
11+
`dm_control.mujoco.wrapper.mjbindings.types` should not be used This module was
12+
specific to the previous implementation of the dm_control python bindings. For
13+
example, `types.MJRRECT` should be replaced with `mujoco.MjrRect`.
14+
15+
### `MjData.contact` has changed
16+
17+
`MjData.contact` (often accessed as Physics.data.contact) used to offer an
18+
interface similar to a numpy structured array. For example, `data.contact.geom1`
19+
used to be a numpy array of geom IDs.
20+
21+
With the recent update, `MjData.contact` will appear as a list of MjContact
22+
structs. Code that used to operate on the structured array will have to change.
23+
For example, the following code would get an array containing the contact
24+
distance for all contacts that involve geom_id:
25+
26+
```
27+
contact = physics.data.contact
28+
involves_geom = (contact.geom1 == geom_id) | (contact.geom2 == geom_id)
29+
dists = contact[involves_geom].dist
30+
```
31+
32+
After the upgrade:
33+
34+
```
35+
contacts = physics.data.contact
36+
dists = [
37+
c.dist for c in contacts if c.geom1 == geom_id or c.geom2 == geom_id
38+
]
39+
```
40+
41+
### `.ptr.contents` will not work
42+
43+
Code that accesses `.ptr.contents` on objects such as `MjvScene` will need to be
44+
updated. In most cases, simply using `scene` instead of `scene.ptr.contents`
45+
will work.
46+
47+
### Different exceptions will be thrown from MuJoCo
48+
49+
Code (mostly in tests) that expects `dm_control.mujoco.wrapper.core.Error`
50+
exceptions, will receive different exceptions, thrown by the `mujoco` library.
51+
These will often be `ValueError` (for errors caused by input parameters), or
52+
`mujoco.FatalError` (for low level errors in MuJoCo).
53+
54+
### Better error handling
55+
56+
The Python interpreter no longer crashes out when
57+
[`mju_error`](https://mujoco.readthedocs.io/en/latest/APIreference.html#mju-error)
58+
is called. Instead, `mju_error` calls are translated into `mujoco.FatalError`
59+
exceptions in Python.
60+
61+
When Python callables are used as user-defined MuJoCo callbacks, they are now
62+
permitted to raise exceptions, which will be correctly propagated back down the
63+
Python call stack.
64+
65+
### Change of signature for `mj_saveModel`
66+
67+
[`mj_saveModel`](https://mujoco.readthedocs.io/en/latest/APIreference.html#mj-savemodel)
68+
now expects a numpy `uint8` array rather than a ctypes string buffer, and
69+
doesn't require a "size" parameter (it's inferred from the numpy array size).
70+
71+
Before:
72+
```
73+
model_size = mjlib.mj_sizeModel(model.ptr)
74+
buf = ctypes.create_string_buffer(model_size)
75+
mjlib.mj_saveModel(model.ptr, None, buf, model_size)
76+
```
77+
78+
After:
79+
```
80+
model_size = mujoco.mj_sizeModel(model)
81+
buf = np.empty(model_size, np.uint8)
82+
mjlib.mj_saveModel(model.ptr, None, buf)
83+
```
84+
85+
## Optional changes
86+
87+
The following are some changes that can make your code more concise, but are not
88+
required for it to continue working.
89+
90+
### Use the mujoco module directly, instead of mjlib
91+
92+
Existing code that uses `dm_control.mujoco.wrapper.mjbindings.mjlib` can
93+
directly replace these modules with mujoco. Code that uses `enums` or
94+
`constants` from `dm_control.mujoco.wrapper.mjbindings` can also use mujoco,
95+
with slight type changes. All mujoco functions will accept the old enum values
96+
or the new ones.
97+
98+
Before:
99+
```
100+
import dm_control.mujoco.wrapper.mjbindings
101+
mjlib = mjbindings.mjlib
102+
103+
mjlib.mj_objectVelocity(
104+
physics.model.ptr, physics.data.ptr,
105+
enums.mjtObj.mjOBJ_SITE,
106+
site_id, vel, 0)
107+
```
108+
109+
After:
110+
```
111+
import mujoco
112+
113+
mujoco.mj_objectVelocity(
114+
physics.model.ptr, physics.data.ptr,
115+
mujoco.mjtObj.mjOBJ_SITE,
116+
site_id, vel, 0)
117+
```
118+
119+
### Assume structs are correctly initialized and memory is managed
120+
121+
The MuJoCo C API includes functions that manage the memory for certain structs.
122+
Those include functions that allocate memory (e.g. `mj_makeModel`,
123+
`mj_makeData`, `mjv_makeScene`), functions that free memory (e.g.
124+
`mj_deleteModel`, `mj_deleteData`, `mjv_freeScene`), and functions that reset a
125+
struct to its default value (e.g. `mjv_defaultOption`, `mj_defaultVisual`).
126+
127+
The new Python bindings take care of this. Wrapper classes like
128+
`mujoco.MjvScene` will automatically allocate memory when they're created, and
129+
release it when they're deleted, and be created with default values set.
130+
131+
As such, allocating and freeing functions are not available through the mujoco
132+
Python bindings. The "default" functions are still available, but in most cases
133+
the calls can simply be removed.
134+
135+
Before:
136+
```
137+
from dm_control.mujoco import wrapper
138+
from dm_control.mujoco.wrapper import mjbindings
139+
mjlib = mjbindings.mjlib
140+
141+
scene_option = wrapper.core.MjvOption()
142+
mjlib.mjv_defaultOption(scene_option.ptr)
143+
```
144+
145+
After:
146+
```
147+
from dm_control.mujoco import wrapper
148+
149+
scene_option = wrapper.core.MjvOption()
150+
```

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def is_excluded(s):
193193

194194
setup(
195195
name='dm_control',
196-
version='0.0.433501881',
196+
version='0.0.433559491',
197197
description='Continuous control environments and MuJoCo Python bindings.',
198198
author='DeepMind',
199199
license='Apache License, Version 2.0',

0 commit comments

Comments
 (0)