Skip to content

Commit bd4cd0e

Browse files
DeepMindalimuldal
authored andcommitted
Default to setting max_geom to the estimated max number of renderable geoms in the model
The previous fixed default of 1000 meant that geoms were sometimes omitted for complex scenes. PiperOrigin-RevId: 319497192 Change-Id: I852430de4660838557ed51707fbd1ecf2509c03a
1 parent 50f22fe commit bd4cd0e

4 files changed

Lines changed: 48 additions & 14 deletions

File tree

dm_control/mujoco/engine.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ def __init__(self,
590590
height=240,
591591
width=320,
592592
camera_id=-1,
593-
max_geom=1000):
593+
max_geom=None):
594594
"""Initializes a new `Camera`.
595595
596596
Args:
@@ -601,8 +601,9 @@ def __init__(self,
601601
camera, which is always defined. A nonnegative integer or string
602602
corresponds to a fixed camera, which must be defined in the model XML.
603603
If `camera_id` is a string then the camera must also be named.
604-
max_geom: (optional) An integer specifying the maximum number of geoms
605-
that can be represented in the scene.
604+
max_geom: Optional integer specifying the maximum number of geoms that can
605+
be rendered in the same scene. If None this will be chosen automatically
606+
based on the estimated maximum number of renderable geoms in the model.
606607
Raises:
607608
ValueError: If `camera_id` is outside the valid range, or if `width` or
608609
`height` exceed the dimensions of MuJoCo's offscreen framebuffer.

dm_control/mujoco/wrapper/core.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -850,19 +850,48 @@ def free(self):
850850
}
851851

852852

853+
def _estimate_max_renderable_geoms(model):
854+
"""Estimates the maximum number of renderable geoms for a given model."""
855+
# Only one type of object frame can be rendered at once.
856+
max_nframes = max(
857+
[model.nbody, model.ngeom, model.nsite, model.ncam, model.nlight])
858+
# This is probably an underestimate, but it is unlikely that all possible
859+
# rendering options will be enabled simultaneously, or that all renderable
860+
# geoms will be present within the viewing frustum at the same time.
861+
return (
862+
3 * max_nframes + # 1 geom per axis for each frame.
863+
4 * model.ngeom + # geom itself + contacts + 2 * split contact forces.
864+
3 * model.nbody + # COM + inertia box + perturbation force.
865+
model.nsite +
866+
model.ntendon +
867+
model.njnt +
868+
model.nu +
869+
model.nskin +
870+
model.ncam +
871+
model.nlight)
872+
873+
853874
class MjvScene(wrappers.MjvSceneWrapper): # pylint: disable=missing-docstring
854875

855-
def __init__(self, model=None, max_geom=1000):
876+
def __init__(self, model=None, max_geom=None):
856877
"""Initializes a new `MjvScene` instance.
857878
858879
Args:
859880
model: (optional) An `MjModel` instance.
860881
max_geom: (optional) An integer specifying the maximum number of geoms
861-
that can be represented in the scene.
882+
that can be represented in the scene. If None, this will be chosen
883+
automatically based on `model`.
862884
"""
863885
model_ptr = model.ptr if model is not None else None
864886
scene_ptr = ctypes.pointer(types.MJVSCENE())
865887

888+
if max_geom is None:
889+
if model is None:
890+
max_renderable_geoms = 0
891+
else:
892+
max_renderable_geoms = _estimate_max_renderable_geoms(model)
893+
max_geom = max(1000, max_renderable_geoms)
894+
866895
# Allocate and initialize resources for the abstract scene.
867896
mjlib.mjv_makeScene(model_ptr, scene_ptr, max_geom)
868897

dm_control/viewer/renderer_test.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,16 @@ def test_cycling_backward_through_labeling_modes(self):
295295

296296
class SceneCameraTest(parameterized.TestCase):
297297

298-
def setUp(self):
298+
@mock.patch.object(renderer.wrapper.core,
299+
'_estimate_max_renderable_geoms',
300+
return_value=1000)
301+
@mock.patch.object(renderer.wrapper.core.mjlib, 'mjv_makeScene')
302+
def setUp(self, mock_make_scene, _):
299303
super(SceneCameraTest, self).setUp()
300304
self.model = mock.MagicMock()
301305
self.data = mock.MagicMock()
302306
self.options = mock.MagicMock()
303-
with mock.patch.object(renderer.wrapper.core.mjlib,
304-
'mjv_makeScene') as mock_make_scene:
305-
self.camera = renderer.SceneCamera(self.model, self.data, self.options)
307+
self.camera = renderer.SceneCamera(self.model, self.data, self.options)
306308
mock_make_scene.assert_called_once()
307309

308310
def test_freelook_mode(self):
@@ -394,16 +396,18 @@ def test_is_camera_initialized(self, frustum_near, frustum_far, result):
394396

395397
class RaycastsTest(absltest.TestCase):
396398

397-
def setUp(self):
399+
@mock.patch.object(renderer.wrapper.core,
400+
'_estimate_max_renderable_geoms',
401+
return_value=1000)
402+
@mock.patch.object(renderer.wrapper.core.mjlib, 'mjv_makeScene')
403+
def setUp(self, mock_make_scene, _):
398404
super(RaycastsTest, self).setUp()
399405
self.model = mock.MagicMock()
400406
self.data = mock.MagicMock()
401407
self.options = mock.MagicMock()
402408

403409
self.viewport = mock.MagicMock()
404-
with mock.patch.object(renderer.wrapper.core.mjlib,
405-
'mjv_makeScene') as mock_make_scene:
406-
self.camera = renderer.SceneCamera(self.model, self.data, self.options)
410+
self.camera = renderer.SceneCamera(self.model, self.data, self.options)
407411
mock_make_scene.assert_called_once()
408412
self.initialize_camera(True)
409413

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def is_excluded(s):
177177

178178
setup(
179179
name='dm_control',
180-
version='0.0.319404054',
180+
version='0.0.319497192',
181181
description='Continuous control environments and MuJoCo Python bindings.',
182182
author='DeepMind',
183183
license='Apache License, Version 2.0',

0 commit comments

Comments
 (0)