Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f4e50a3
adds custom implementation of changing prim property
Mayankm96 Jan 5, 2026
1483c08
adapts our own create prim property
Mayankm96 Jan 5, 2026
6118aa4
makes tests parametrized
Mayankm96 Jan 5, 2026
abc7a52
removes is_custom where applicable
Mayankm96 Jan 5, 2026
6df8f00
removes default timecode arg
Mayankm96 Jan 5, 2026
eed4b5f
fixes test
Mayankm96 Jan 5, 2026
40901bd
passes stage over for creating mdl material
Mayankm96 Jan 5, 2026
0b22165
Merge branch 'main' into feature/remove-change-prim-command
Mayankm96 Jan 6, 2026
6558e8c
fixes type-hinting
Mayankm96 Jan 6, 2026
6a72e1e
remove unused imports
Mayankm96 Jan 6, 2026
b921d47
removes unused imports
Mayankm96 Jan 6, 2026
1edfe21
Merge branch 'main' into feature/remove-change-prim-command
Mayankm96 Jan 6, 2026
9ce2474
fixes warning
Mayankm96 Jan 6, 2026
c357910
fixes bug
Mayankm96 Jan 6, 2026
9208712
Merge branch 'main' into feature/remove-change-prim-command
Mayankm96 Jan 7, 2026
737f369
fixes some docs
Mayankm96 Jan 7, 2026
38fd045
makes code more robust
Mayankm96 Jan 7, 2026
db4424d
switches back to kit commands
Mayankm96 Jan 7, 2026
c469b95
fixes naming
Mayankm96 Jan 7, 2026
914de9d
reverts
Mayankm96 Jan 7, 2026
18a440d
Merge branch 'main' into feature/remove-change-prim-command
Mayankm96 Jan 7, 2026
8bdbc20
Merge branch 'main' into feature/remove-change-prim-command
Mayankm96 Jan 8, 2026
b9fe765
fixes error log level
Mayankm96 Jan 8, 2026
a4c9eb6
updates changelog
Mayankm96 Jan 8, 2026
40a6543
fix doc
Mayankm96 Jan 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions source/isaaclab/isaaclab/markers/visualization_markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import torch
from dataclasses import MISSING

import omni.kit.commands
import omni.physx.scripts.utils as physx_utils
from pxr import Gf, PhysxSchema, Sdf, Usd, UsdGeom, UsdPhysics, Vt

Expand Down Expand Up @@ -396,18 +395,12 @@ def _process_prototype_prim(self, prim: Usd.Prim):
child_prim.SetInstanceable(False)
# check if prim is a mesh -> if so, make it invisible to secondary rays
if child_prim.IsA(UsdGeom.Gprim):
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "ChangePropertyCommand" kit command
sim_utils.attach_stage_to_usd_context(attaching_early=True)

# invisible to secondary rays such as depth images
omni.kit.commands.execute(
"ChangePropertyCommand",
prop_path=Sdf.Path(f"{child_prim.GetPrimPath().pathString}.primvars:invisibleToSecondaryRays"),
sim_utils.change_prim_property(
prop_path=f"{child_prim.GetPrimPath().pathString}.primvars:invisibleToSecondaryRays",
value=True,
prev=None,
stage=prim.GetStage(),
type_to_create_if_not_exist=Sdf.ValueTypeNames.Bool,
usd_context_name=prim.GetStage(),
)
# add children to list
all_prims += child_prim.GetChildren()
Expand Down
28 changes: 8 additions & 20 deletions source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
add_labels,
bind_physics_material,
bind_visual_material,
change_prim_property,
clone,
create_prim,
get_current_stage,
get_first_matching_child_prim,
is_current_stage_in_memory,
select_usd_variants,
set_prim_visibility,
)
Expand Down Expand Up @@ -230,25 +230,13 @@ def spawn_ground_plane(
# Change the color of the plane
# Warning: This is specific to the default grid plane asset.
if cfg.color is not None:
# avoiding this step if stage is in memory since the "ChangePropertyCommand" kit command
# is not supported in stage in memory
if is_current_stage_in_memory():
logger.warning(
"Ground plane color modification is not supported while the stage is in memory. Skipping operation."
)

else:
prop_path = f"{prim_path}/Looks/theGrid/Shader.inputs:diffuse_tint"

# change the color
omni.kit.commands.execute(
"ChangePropertyCommand",
prop_path=Sdf.Path(prop_path),
value=Gf.Vec3f(*cfg.color),
prev=None,
type_to_create_if_not_exist=Sdf.ValueTypeNames.Color3f,
usd_context_name=stage,
)
# change the color
change_prim_property(
prop_path=f"{prim_path}/Looks/theGrid/Shader.inputs:diffuse_tint",
value=Gf.Vec3f(*cfg.color),
stage=stage,
type_to_create_if_not_exist=Sdf.ValueTypeNames.Color3f,
)
# Remove the light from the ground plane
# It isn't bright enough and messes up with the user's lighting settings
omni.kit.commands.execute("ToggleVisibilitySelectedPrims", selected_paths=[f"{prim_path}/SphereLight"], stage=stage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@ def spawn_preview_surface(prim_path: str, cfg: visual_materials_cfg.PreviewSurfa
# since stage in memory is not supported by the "CreatePreviewSurfaceMaterialPrim" kit command
attach_stage_to_usd_context(attaching_early=True)

# note: this command does not support passing 'stage' as an argument
omni.kit.commands.execute("CreatePreviewSurfaceMaterialPrim", mtl_path=prim_path, select_new_prim=False)
else:
raise ValueError(f"A prim already exists at path: '{prim_path}'.")

# obtain prim
prim = stage.GetPrimAtPath(f"{prim_path}/Shader")
# check prim is valid
if not prim.IsValid():
raise ValueError(f"Failed to create preview surface material at path: '{prim_path}'.")
# apply properties
cfg = cfg.to_dict()
cfg = cfg.to_dict() # type: ignore
del cfg["func"]
for attr_name, attr_value in cfg.items():
safe_set_attribute_on_usd_prim(prim, f"inputs:{attr_name}", attr_value, camel_case=True)
Expand Down Expand Up @@ -108,23 +112,23 @@ def spawn_from_mdl_file(prim_path: str, cfg: visual_materials_cfg.MdlMaterialCfg

# spawn material if it doesn't exist.
if not stage.GetPrimAtPath(prim_path).IsValid():
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "CreateMdlMaterialPrim" kit command
attach_stage_to_usd_context(attaching_early=True)

# extract material name from path
material_name = cfg.mdl_path.split("/")[-1].split(".")[0]
omni.kit.commands.execute(
"CreateMdlMaterialPrim",
mtl_url=cfg.mdl_path.format(NVIDIA_NUCLEUS_DIR=NVIDIA_NUCLEUS_DIR),
mtl_name=material_name,
mtl_path=prim_path,
stage=stage,
select_new_prim=False,
)
else:
raise ValueError(f"A prim already exists at path: '{prim_path}'.")
# obtain prim
prim = stage.GetPrimAtPath(f"{prim_path}/Shader")
# check prim is valid
if not prim.IsValid():
raise ValueError(f"Failed to create MDL material at path: '{prim_path}'.")
# apply properties
cfg = cfg.to_dict()
del cfg["func"]
Expand Down
15 changes: 4 additions & 11 deletions source/isaaclab/isaaclab/sim/spawners/sensors/sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
import logging
from typing import TYPE_CHECKING

import omni.kit.commands
from pxr import Sdf, Usd

from isaaclab.sim.utils import attach_stage_to_usd_context, clone, create_prim, get_current_stage
from isaaclab.sim.utils import change_prim_property, clone, create_prim, get_current_stage
from isaaclab.utils import to_camel_case

if TYPE_CHECKING:
Expand Down Expand Up @@ -94,17 +93,11 @@ def spawn_camera(

# lock camera from viewport (this disables viewport movement for camera)
if cfg.lock_camera:
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "ChangePropertyCommand" kit command
attach_stage_to_usd_context(attaching_early=True)

omni.kit.commands.execute(
"ChangePropertyCommand",
prop_path=Sdf.Path(f"{prim_path}.omni:kit:cameraLock"),
change_prim_property(
prop_path=f"{prim_path}.omni:kit:cameraLock",
value=True,
prev=None,
stage=stage,
type_to_create_if_not_exist=Sdf.ValueTypeNames.Bool,
usd_context_name=stage,
)
# decide the custom attributes to add
if cfg.projection_type == "pinhole":
Expand Down
125 changes: 102 additions & 23 deletions source/isaaclab/isaaclab/sim/utils/prims.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

from .queries import find_matching_prim_paths
from .semantics import add_labels
from .stage import attach_stage_to_usd_context, get_current_stage, get_current_stage_id
from .stage import get_current_stage, get_current_stage_id
from .transforms import convert_world_pose_to_local, standardize_xform_ops

if TYPE_CHECKING:
Expand Down Expand Up @@ -384,21 +384,105 @@ def safe_set_attribute_on_usd_prim(prim: Usd.Prim, attr_name: str, value: Any, c
f"Cannot set attribute '{attr_name}' with value '{value}'. Please modify the code to support this type."
)

# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "ChangePropertyCommand" kit command
attach_stage_to_usd_context(attaching_early=True)

# change property
omni.kit.commands.execute(
"ChangePropertyCommand",
prop_path=Sdf.Path(f"{prim.GetPath()}.{attr_name}"),
# change property using the change_prim_property function
change_prim_property(
prop_path=f"{prim.GetPath()}.{attr_name}",
value=value,
prev=None,
stage=prim.GetStage(),
type_to_create_if_not_exist=sdf_type,
usd_context_name=prim.GetStage(),
)


def change_prim_property(
prop_path: str | Sdf.Path,
value: Any,
stage: Usd.Stage | None = None,
type_to_create_if_not_exist: Sdf.ValueTypeNames | None = None,
is_custom: bool = False,
) -> bool:
"""Change or create a property value on a USD prim.

This is a simplified property setter that works with the current edit target. If you need
complex layer management, use :class:`omni.kit.commands.ChangePropertyCommand` instead.

By default, this function changes the value of the property when it exists. If the property
doesn't exist, :attr:`type_to_create_if_not_exist` must be provided to create it.

Note:
The attribute :attr:`value` must be the correct type for the property.
For example, if the property is a float, the value must be a float.
If it is supposed to be a RGB color, the value must be of type :class:`Gf.Vec3f`.

Args:
prop_path: Property path in the format ``/World/Prim.propertyName``.
value: Value to set. If None, the attribute value goes to its default value.
If the attribute has no default value, it is a silent no-op.
stage: The USD stage. Defaults to None, in which case the current stage is used.
type_to_create_if_not_exist: If not None and property doesn't exist, a new property will
be created with the given type and value. Defaults to None.
is_custom: If the property is created, specify if it is a custom property (not part of
the schema). Defaults to False.

Returns:
True if the property was successfully changed, False otherwise.

Raises:
ValueError: If the prim does not exist at the specified path.

Example:
>>> import isaaclab.sim as sim_utils
>>> from pxr import Sdf
>>>
>>> # Change an existing property
>>> sim_utils.change_prim_property(
... prop_path="/World/Cube.size",
... value=2.0
... )
True
>>>
>>> # Create a new custom property
>>> sim_utils.change_prim_property(
... prop_path="/World/Cube.customValue",
... value=42,
... type_to_create_if_not_exist=Sdf.ValueTypeNames.Int,
... is_custom=True
... )
True
"""
# get stage handle
stage = get_current_stage() if stage is None else stage

# convert to Sdf.Path if needed
prop_path = Sdf.Path(prop_path) if isinstance(prop_path, str) else prop_path

# get the prim path
prim_path = prop_path.GetAbsoluteRootOrPrimPath()
prim = stage.GetPrimAtPath(prim_path)
if not prim or not prim.IsValid():
raise ValueError(f"Prim does not exist at path: '{prim_path}'")

# get or create the property
prop = stage.GetPropertyAtPath(prop_path)

if not prop:
if type_to_create_if_not_exist is not None:
# create new attribute on the prim
prop = prim.CreateAttribute(prop_path.name, type_to_create_if_not_exist, is_custom)
else:
logger.error(f"Property {prop_path} does not exist and 'type_to_create_if_not_exist' was not provided.")
return False

if not prop:
logger.error(f"Failed to get or create property at path: '{prop_path}'")
return False

# set the value
if value is None:
return bool(prop.Clear())
else:
return bool(prop.Set(value, Usd.TimeCode.Default()))


"""
Exporting.
"""
Expand Down Expand Up @@ -853,19 +937,14 @@ def _add_reference_to_prim(prim: Usd.Prim) -> Usd.Prim:
ret_val = get_metrics_assembler_interface().check_layers(
stage.GetRootLayer().identifier, sdf_layer.identifier, stage_id
)
# log that metric assembler did not detect any issues
if ret_val["ret_val"]:
try:
import omni.metrics.assembler.ui

omni.kit.commands.execute(
"AddReference", stage=stage, prim_path=prim.GetPath(), reference=Sdf.Reference(usd_path)
)

return prim
except Exception:
return _add_reference_to_prim(prim)
else:
return _add_reference_to_prim(prim)
logger.info(
"Metric assembler detected no issues between the current stage and the referenced USD file at path:"
f" {usd_path}"
)
# add reference to the prim
return _add_reference_to_prim(prim)


def get_usd_references(prim_path: str, stage: Usd.Stage | None = None) -> list[str]:
Expand Down
Loading