Skip to content

Commit 3634882

Browse files
nimrod-gileadicopybara-github
authored andcommitted
Free the Physics object when Environment.close is called.
Make physics.free() idempotent since sometimes it's called by __del__ functions. PiperOrigin-RevId: 717526328 Change-Id: I1df3c0141cf0d5440420ee48f805a8a71580bb13
1 parent 07b0688 commit 3634882

3 files changed

Lines changed: 18 additions & 8 deletions

File tree

dm_control/composer/environment.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,9 @@ def _recompile_physics_and_update_observables(self):
249249

250250
def _recompile_physics(self):
251251
"""Creates a new Physics using the latest MJCF model from the task."""
252-
if getattr(self, '_physics', None):
253-
self._physics.free()
252+
physics = getattr(self, '_physics', None)
253+
if physics:
254+
physics.free()
254255
self._physics = mjcf.Physics.from_mjcf_model(
255256
self._task.root_entity.mjcf_model)
256257
self._physics.legacy_step = self._legacy_step
@@ -267,9 +268,10 @@ def physics(self):
267268
"""Returns a `weakref.ProxyType` pointing to the current `mjcf.Physics`.
268269
269270
Note that the underlying `mjcf.Physics` will be destroyed whenever the MJCF
270-
model is recompiled. It is therefore unsafe for external objects to hold a
271-
reference to `environment.physics`. Attempting to access attributes of a
272-
dead `Physics` instance will result in a `ReferenceError`.
271+
model is recompiled or environment.close() is called. It is therefore unsafe
272+
for external objects to hold a reference to `environment.physics`.
273+
Attempting to access attributes of a dead `Physics` instance will result in
274+
a `ReferenceError`.
273275
"""
274276
return self._physics_proxy
275277

@@ -462,6 +464,11 @@ def _substep(self, action):
462464
self._physics.step()
463465
self._hooks.after_substep(self._physics_proxy, self._random_state)
464466

467+
def close(self):
468+
super().close()
469+
self._physics.free()
470+
self._physics = None
471+
465472
def action_spec(self):
466473
"""Returns the action specification for this environment."""
467474
return self._task.action_spec(self._physics_proxy)

dm_control/mujoco/engine.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ def free(self):
417417
with self._contexts_lock:
418418
if self._contexts:
419419
self._free_rendering_contexts()
420-
del self._data
420+
if hasattr(self, '_data'):
421+
del self._data
421422

422423
@classmethod
423424
def from_model(cls, model):

dm_control/mujoco/engine_test.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
# limitations under the License.
1414
# ============================================================================
1515

16-
"""Tests for `engine`."""
17-
1816
import copy
1917
import pickle
2018

@@ -202,6 +200,10 @@ def testRenderFlags(self):
202200
np.all(disabled == enabled),
203201
msg='Images are identical regardless of whether wireframe is enabled.')
204202

203+
def testFreeIdempotent(self):
204+
self._physics.free()
205+
self._physics.free()
206+
205207
@parameterized.parameters(((0.5, 0.5), (1, 3)), # pole
206208
((0.5, 0.1), (0, 0)), # ground
207209
((0.9, 0.9), (None, None)), # sky

0 commit comments

Comments
 (0)