diff --git a/source/extensions/omni.isaac.orbit/config/extension.toml b/source/extensions/omni.isaac.orbit/config/extension.toml index 7ae012c7d4..747aa6e64a 100644 --- a/source/extensions/omni.isaac.orbit/config/extension.toml +++ b/source/extensions/omni.isaac.orbit/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "0.9.10" +version = "0.9.11" # Description title = "ORBIT framework for Robot Learning" diff --git a/source/extensions/omni.isaac.orbit/docs/CHANGELOG.rst b/source/extensions/omni.isaac.orbit/docs/CHANGELOG.rst index 6c353304f8..b145bf62e3 100644 --- a/source/extensions/omni.isaac.orbit/docs/CHANGELOG.rst +++ b/source/extensions/omni.isaac.orbit/docs/CHANGELOG.rst @@ -1,6 +1,17 @@ Changelog --------- +0.9.11 (2023-10-17) +~~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Added the support for semantic tags into the :class:`omni.isaac.orbit.sim.spawner.SpawnerCfg` class. This allows + the user to specify the semantic tags for a prim when spawning it into the scene. It follows the same format as + Omniverse Replicator. + + 0.9.10 (2023-10-16) ~~~~~~~~~~~~~~~~~~~ diff --git a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/lights/lights.py b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/lights/lights.py index 58b20cf75d..178de3ed14 100644 --- a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/lights/lights.py +++ b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/lights/lights.py @@ -55,10 +55,10 @@ def spawn_light( cfg = cfg.to_dict() # delete spawner func specific parameters del cfg["prim_type"] - # delete meta parameters from base class - del cfg["func"] - del cfg["visible"] - del cfg["copy_from_source"] + # delete custom attributes in the config that are not USD parameters + non_usd_cfg_param_names = ["func", "copy_from_source", "visible", "semantic_tags"] + for param_name in non_usd_cfg_param_names: + del cfg[param_name] # set into USD API for attr_name, value in cfg.items(): # special operation for texture properties diff --git a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/sensors/sensors.py b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/sensors/sensors.py index 30e3a5bb3f..b40ab3b3c4 100644 --- a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/sensors/sensors.py +++ b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/sensors/sensors.py @@ -97,6 +97,8 @@ def spawn_camera( attribute_types = CUSTOM_PINHOLE_CAMERA_ATTRIBUTES else: attribute_types = CUSTOM_FISHEYE_CAMERA_ATTRIBUTES + # custom attributes in the config that are not USD Camera parameters + non_usd_cfg_param_names = ["func", "copy_from_source", "lock_camera", "visible", "semantic_tags"] # get camera prim prim = prim_utils.get_prim_at_path(prim_path) @@ -110,7 +112,7 @@ def spawn_camera( # set attribute values for param_name, param_value in cfg.__dict__.items(): # check if value is valid - if param_value is None or param_name in ["func", "copy_from_source", "lock_camera", "visible"]: + if param_value is None or param_name in non_usd_cfg_param_names: continue # obtain prim property name if param_name in attribute_types: diff --git a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/spawner_cfg.py b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/spawner_cfg.py index 1b18ff4c2c..63756e865c 100644 --- a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/spawner_cfg.py +++ b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/spawners/spawner_cfg.py @@ -38,6 +38,22 @@ class SpawnerCfg: visible: bool = True """Whether the spawned asset should be visible. Defaults to True.""" + semantic_tags: list[tuple[str, str]] | None = None + """List of semantic tags to add to the spawned asset. Defaults to None, + which means no semantic tags will be added. + + The semantic tags follow the `Replicator Semantic` tagging system. Each tag is a tuple of the + form ``(type, data)``, where ``type`` is the type of the tag and ``data`` is the semantic label + associated with the tag. For example, to annotate a spawned asset in the class avocado, the semantic + tag would be ``[("class", "avocado")]``. + + You can specify multiple semantic tags by passing in a list of tags. For example, to annotate a + spawned asset in the class avocado and the color green, the semantic tags would be + ``[("class", "avocado"), ("color", "green")]``. + + .. _Replicator Semantic: https://docs.omniverse.nvidia.com/extensions/latest/ext_replicator/semantics_schema_editor.html + """ + copy_from_source: bool = True """Whether to copy the asset from the source prim or inherit it. Defaults to True. diff --git a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/utils.py b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/utils.py index c43b8aca7c..895bbc9df1 100644 --- a/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/utils.py +++ b/source/extensions/omni.isaac.orbit/omni/isaac/orbit/sim/utils.py @@ -15,7 +15,7 @@ import omni.kit.commands from omni.isaac.cloner import Cloner from omni.isaac.version import get_version -from pxr import PhysxSchema, Sdf, Usd, UsdPhysics, UsdShade +from pxr import PhysxSchema, Sdf, Semantics, Usd, UsdPhysics, UsdShade from omni.isaac.orbit.utils.string import to_camel_case @@ -220,6 +220,21 @@ def wrapper(prim_path: str, cfg: SpawnerCfg, *args, **kwargs): # set the prim visibility if hasattr(cfg, "visible"): prim_utils.set_prim_visibility(prim, cfg.visible) + # set the semantic annotations + if hasattr(cfg, "semantic_tags") and cfg.semantic_tags is not None: + # note: taken from replicator scripts.utils.utils.py + for semantic_type, semantic_value in cfg.semantic_tags: + # deal with spaces by replacing them with underscores + semantic_type_sanitized = semantic_type.replace(" ", "_") + semantic_value_sanitized = semantic_value.replace(" ", "_") + # set the semantic API for the instance + instance_name = f"{semantic_type_sanitized}_{semantic_value_sanitized}" + sem = Semantics.SemanticsAPI.Apply(prim, instance_name) + # create semantic type and data attributes + sem.CreateSemanticTypeAttr() + sem.CreateSemanticDataAttr() + sem.GetSemanticTypeAttr().Set(semantic_type) + sem.GetSemanticDataAttr().Set(semantic_value) # activate rigid body contact sensors if hasattr(cfg, "activate_contact_sensors") and cfg.activate_contact_sensors: schemas.activate_contact_sensors(prim_paths[0], cfg.activate_contact_sensors) diff --git a/source/extensions/omni.isaac.orbit/test/sim/test_spawn_sensors.py b/source/extensions/omni.isaac.orbit/test/sim/test_spawn_sensors.py index 1f88eed9e1..97d37619c2 100644 --- a/source/extensions/omni.isaac.orbit/test/sim/test_spawn_sensors.py +++ b/source/extensions/omni.isaac.orbit/test/sim/test_spawn_sensors.py @@ -101,10 +101,13 @@ def _validate_properties_on_prim(self, prim_path: str, cfg: object, custom_attr: cfg: The configuration object. custom_attr: The custom attributes for sensor. """ + # delete custom attributes in the config that are not USD parameters + non_usd_cfg_param_names = ["func", "copy_from_source", "lock_camera", "visible", "semantic_tags"] + # get prim prim = prim_utils.get_prim_at_path(prim_path) for attr_name, attr_value in cfg.__dict__.items(): # skip names we know are not present - if attr_name in ["func", "copy_from_source", "lock_camera", "visible"] or attr_value is None: + if attr_name in non_usd_cfg_param_names or attr_value is None: continue # obtain prim property name if attr_name in custom_attr: