Skip to content

Commit 5c155e1

Browse files
DeepMindcopybara-github
authored andcommitted
Add assetdir functionality to pymjcf.
PiperOrigin-RevId: 618313406 Change-Id: I24d8e277ad15c284ddd2c6a2e8c7ab53b2392068
1 parent 5e8eac1 commit 5c155e1

4 files changed

Lines changed: 51 additions & 8 deletions

File tree

dm_control/mjcf/attribute.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -511,24 +511,41 @@ def _get_asset_from_path(self, path):
511511
_, basename = os.path.split(path)
512512
filename, extension = os.path.splitext(basename)
513513

514-
# Look in the dict of pre-loaded assets before checking the filesystem.
515-
try:
514+
assetdir = None
515+
if self._parent.namescope.has_identifier(
516+
constants.BASEPATH, constants.ASSETDIR_NAMESPACE
517+
):
518+
assetdir = self._parent.namescope.get(
519+
constants.BASEPATH, constants.ASSETDIR_NAMESPACE
520+
)
521+
522+
if path in self._parent.namescope.assets:
523+
# Look in the dict of pre-loaded assets before checking the filesystem.
516524
contents = self._parent.namescope.assets[path]
517-
except KeyError:
525+
else:
518526
# Construct the full path to the asset file, prefixed by the path to the
519527
# model directory, and by `meshdir` or `texturedir` if appropriate.
520528
path_parts = []
521529
if self._parent.namescope.model_dir:
522530
path_parts.append(self._parent.namescope.model_dir)
523-
try:
524-
base_path = self._parent.namescope.get(constants.BASEPATH,
525-
self._path_namespace)
531+
532+
if self._parent.namescope.has_identifier(
533+
constants.BASEPATH, self._path_namespace
534+
):
535+
base_path = self._parent.namescope.get(
536+
constants.BASEPATH, self._path_namespace
537+
)
526538
path_parts.append(base_path)
527-
except KeyError:
528-
pass
539+
elif (
540+
self._path_namespace
541+
in (constants.TEXTUREDIR_NAMESPACE, constants.MESHDIR_NAMESPACE)
542+
and assetdir is not None
543+
):
544+
path_parts.append(assetdir)
529545
path_parts.append(path)
530546
full_path = os.path.join(*path_parts) # pylint: disable=no-value-for-parameter
531547
contents = resources.GetResource(full_path)
548+
532549
if self._parent.tag == constants.SKIN:
533550
return SkinAsset(contents=contents, parent=self._parent,
534551
extension=extension, prefix=filename)

dm_control/mjcf/constants.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
TENDON = 'tendon'
4040
WORLDBODY = 'worldbody'
4141

42+
# Path namespaces.
43+
MESHDIR_NAMESPACE = 'mesh'
44+
TEXTUREDIR_NAMESPACE = 'texture'
45+
ASSETDIR_NAMESPACE = 'asset'
46+
4247
MJDATA_TRIGGERS_DIRTY = [
4348
'qpos', 'qvel', 'act', 'ctrl', 'qfrc_applied', 'xfrc_applied']
4449
MJMODEL_DOESNT_TRIGGER_DIRTY = [

dm_control/mjcf/export_with_assets_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
_ASSETS_DIR = os.path.join(os.path.dirname(__file__), 'test_assets')
2929
_TEST_MODEL_WITH_ASSETS = os.path.join(_ASSETS_DIR, 'model_with_assets.xml')
30+
_TEST_MODEL_WITH_ASSETDIR = os.path.join(_ASSETS_DIR, 'model_with_assetdir.xml')
3031
_TEST_MODEL_WITHOUT_ASSETS = os.path.join(_ASSETS_DIR, 'lego_brick.xml')
3132

3233

@@ -42,6 +43,7 @@ class ExportWithAssetsTest(parameterized.TestCase):
4243

4344
@parameterized.named_parameters(
4445
('with_assets', _TEST_MODEL_WITH_ASSETS, 'mujoco_with_assets.xml'),
46+
('with_assetdir', _TEST_MODEL_WITH_ASSETDIR, 'mujoco_with_assetdir.xml'),
4547
('without_assets', _TEST_MODEL_WITHOUT_ASSETS, 'mujoco.xml'),)
4648
def test_export_model(self, xml_path, out_xml_name):
4749
"""Save processed MJCF model."""
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<mujoco model="Textured cube and mesh">
2+
<compiler assetdir="meshes" texturedir="textures"/>
3+
<asset>
4+
<mesh name="cube" file="cube.stl"/>
5+
<mesh name="another_cube" file="more_meshes/cube.stl"/>
6+
<mesh name="unused_asset_should_not_cause_problems" file="cube.stl"/>
7+
<mesh name="cube_msh" file="cube.msh"/>
8+
<texture name="texture" file="deepmind.png"/>
9+
<material name="mat_texture" texture="texture"/>
10+
<hfield name="hill" file="../textures/deepmind.png" size="0.5 0.5 0.5 0.1"/>
11+
</asset>
12+
<worldbody>
13+
<light diffuse=".5 .5 .5" pos="0 0 3" dir="0 0 -1"/>
14+
<geom type="mesh" mesh="cube" material="mat_texture"/>
15+
<geom type="mesh" mesh="another_cube" material="mat_texture" pos="2.5 0. 0."/>
16+
<geom type="mesh" mesh="cube_msh" material="mat_texture" pos="4. 0. 0."/>
17+
<geom type="hfield" hfield="hill" pos="1.2 0. 0" rgba="0. 0.9 0. 1" size="40 40 0.1"/>
18+
</worldbody>
19+
</mujoco>

0 commit comments

Comments
 (0)