diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7c63d42f56ec..ee6967f09fc6 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -184,6 +184,7 @@ Guidelines for modifications: * Tsz Ki GAO * Tyler Lum * Victor Khaustov +* Vidur Vij * Virgilio Gómez Lambo * Vladimir Fokow * Wei Yang diff --git a/source/isaaclab/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst b/source/isaaclab/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst new file mode 100644 index 000000000000..d868abb3fc1e --- /dev/null +++ b/source/isaaclab/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst @@ -0,0 +1,7 @@ +Added +^^^^^ + +* Added :func:`~isaaclab.utils.renderers.isaac_rtx_per_env_scene_partition_enabled` to + query whether per-environment Isaac RTX scene partitioning is enabled. Set + ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` to enable authoring of + ``primvars:omni:scenePartition`` and ``omni:scenePartition`` on the USD stage. diff --git a/source/isaaclab/changelog.d/jmart-cartpole-rtx.minor.rst b/source/isaaclab/changelog.d/jmart-cartpole-rtx.minor.rst deleted file mode 100644 index c7b1de77a767..000000000000 --- a/source/isaaclab/changelog.d/jmart-cartpole-rtx.minor.rst +++ /dev/null @@ -1,12 +0,0 @@ -Added -^^^^^ - -* Added the :meth:`~isaaclab.physics.physics_manager.PhysicsManager.provides_implicit_damping` and - :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.provides_temporal_camera_data` capability - classmethods on the runtime backend bases, so physics and renderer backends declare whether a - camera observation carries the temporal information a policy needs to infer velocity (used to - decide frame stacking). Base defaults: physics has implicit damping (``True``); a renderer - provides no temporal data (``False``). -* Added :meth:`~isaaclab.renderers.Renderer.resolve_class` to resolve a renderer's implementation - class from its configuration without instantiating it (so tasks can query the above classmethod - before a simulation exists). diff --git a/source/isaaclab/changelog.d/jmart-dr-reset.rst b/source/isaaclab/changelog.d/jmart-dr-reset.rst deleted file mode 100644 index 9088b9800e13..000000000000 --- a/source/isaaclab/changelog.d/jmart-dr-reset.rst +++ /dev/null @@ -1,9 +0,0 @@ -Fixed -^^^^^ - -* Fixed a crash where :class:`~isaaclab.envs.mdp.randomize_visual_color` used in ``reset`` mode - raised ``AttributeError: 'NoneType' object has no attribute 'link_count'`` during environment - startup on the PhysX backend. The randomizer authored USD (``SetInstanceable`` and material - binding) on the articulation root prim, which invalidated the PhysX articulation view so that - the subsequent at-play body-name resolution dereferenced a ``None`` metatype. It now scopes to - descendant visual prims, mirroring :class:`~isaaclab.envs.mdp.randomize_visual_texture_material`. diff --git a/source/isaaclab/changelog.d/vidurv-schema-frag-mass.minor.rst b/source/isaaclab/changelog.d/vidurv-schema-frag-mass.minor.rst new file mode 100644 index 000000000000..eed3a03d7341 --- /dev/null +++ b/source/isaaclab/changelog.d/vidurv-schema-frag-mass.minor.rst @@ -0,0 +1,18 @@ +Added +^^^^^ + +* Added the mass schema-fragment API: the :class:`~isaaclab.sim.schemas.MassFragment` marker and + :class:`~isaaclab.sim.schemas.MassCfg` (writes ``physics:mass`` / ``physics:density`` via + ``UsdPhysics.MassAPI``). The legacy :class:`~isaaclab.sim.schemas.MassPropertiesCfg` remains the + canonical name and continues to work unchanged. +* Added :func:`~isaaclab.sim.schemas.apply_mass_properties`, which applies a list of mass fragments + with ``UsdPhysics.MassAPI`` as the implicit anchor. + +Changed +^^^^^^^ + +* Changed the spawner ``mass_props`` slot + (:attr:`~isaaclab.sim.spawners.RigidObjectSpawnerCfg.mass_props`) to also accept a single + :class:`~isaaclab.sim.schemas.MassFragment` or a list of them. Legacy + :class:`~isaaclab.sim.schemas.MassPropertiesCfg` cfgs continue to work through a transition bridge + in the spawn writers. diff --git a/source/isaaclab/changelog.d/vidurv-schema-fragments.minor.rst b/source/isaaclab/changelog.d/vidurv-schema-fragments.minor.rst new file mode 100644 index 000000000000..49cea07c0068 --- /dev/null +++ b/source/isaaclab/changelog.d/vidurv-schema-fragments.minor.rst @@ -0,0 +1,19 @@ +Added +^^^^^ + +* Added the single-namespace schema-fragment API: :class:`~isaaclab.sim.schemas.SchemaFragment`, + the :class:`~isaaclab.sim.schemas.RigidBodyFragment` marker, and + :class:`~isaaclab.sim.schemas.UsdPhysicsRigidBodyCfg`. Each fragment carries + ``_usd_namespace`` / ``_usd_applied_schema`` metadata and a ``func`` applier so a prim can + carry rigid-body properties from multiple USD namespaces at once. +* Added :func:`~isaaclab.sim.schemas.apply_namespaced` (generic fragment writer) and + :func:`~isaaclab.sim.schemas.apply_rigid_body_properties` (applies a list of rigid-body + fragments with ``UsdPhysics.RigidBodyAPI`` as the implicit anchor). + +Changed +^^^^^^^ + +* Changed the spawner ``rigid_props`` slot + (:attr:`~isaaclab.sim.spawners.RigidObjectSpawnerCfg.rigid_props`) to also accept a list of + :class:`~isaaclab.sim.schemas.RigidBodyFragment` fragments. Legacy single cfgs continue to + work through a transition bridge in the spawn writers. diff --git a/source/isaaclab/config/extension.toml b/source/isaaclab/config/extension.toml index 6fd0197bebd3..bb4ba3ffbdf4 100644 --- a/source/isaaclab/config/extension.toml +++ b/source/isaaclab/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "7.0.5" +version = "7.1.0" # Description title = "Isaac Lab framework for Robot Learning" diff --git a/source/isaaclab/docs/CHANGELOG.rst b/source/isaaclab/docs/CHANGELOG.rst index ba7727cba561..b08a87ffdead 100644 --- a/source/isaaclab/docs/CHANGELOG.rst +++ b/source/isaaclab/docs/CHANGELOG.rst @@ -1,6 +1,37 @@ Changelog --------- +7.1.0 (2026-06-24) +~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Added the :meth:`~isaaclab.physics.physics_manager.PhysicsManager.provides_implicit_damping` and + :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.provides_temporal_camera_data` capability + classmethods on the runtime backend bases, so physics and renderer backends declare whether a + camera observation carries the temporal information a policy needs to infer velocity (used to + decide frame stacking). Base defaults: physics has implicit damping (``True``); a renderer + provides no temporal data (``False``). +* Added :meth:`~isaaclab.renderers.Renderer.resolve_class` to resolve a renderer's implementation + class from its configuration without instantiating it (so tasks can query the above classmethod + before a simulation exists). + +Fixed +^^^^^ + +* Fixed a crash where :class:`~isaaclab.envs.mdp.randomize_visual_color` used in ``reset`` mode + raised ``AttributeError: 'NoneType' object has no attribute 'link_count'`` during environment + startup on the PhysX backend. The randomizer authored USD (``SetInstanceable`` and material + binding) on the articulation root prim, which invalidated the PhysX articulation view so that + the subsequent at-play body-name resolution dereferenced a ``None`` metatype. It now scopes to + descendant visual prims, mirroring :class:`~isaaclab.envs.mdp.randomize_visual_texture_material`. +* Fixed the wheel-builder ``newton[sim]`` dependency pin to use Newton commit + ``79e95bf5571d70a0a46c8eaedc80644531d27368``, including the + RenderContext triangle-mesh construction fix from `newton-physics/newton#3199 + `_. + + 7.0.5 (2026-06-23) ~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab/isaaclab/sim/__init__.pyi b/source/isaaclab/isaaclab/sim/__init__.pyi index 05b76be4270c..dc5d6207e855 100644 --- a/source/isaaclab/isaaclab/sim/__init__.pyi +++ b/source/isaaclab/isaaclab/sim/__init__.pyi @@ -45,6 +45,8 @@ __all__ = [ "DeformableBodyPropertiesCfg", "FixedTendonPropertiesCfg", "JointDriveBaseCfg", + "MassCfg", + "MassFragment", "MassPropertiesCfg", "MeshCollisionPropertiesCfg", "MujocoJointDrivePropertiesCfg", @@ -59,6 +61,12 @@ __all__ = [ "PhysxJointDrivePropertiesCfg", "PhysxRigidBodyPropertiesCfg", "RigidBodyBaseCfg", + "RigidBodyFragment", + "SchemaFragment", + "UsdPhysicsRigidBodyCfg", + "apply_mass_properties", + "apply_namespaced", + "apply_rigid_body_properties", "SDFMeshPropertiesCfg", "SpatialTendonPropertiesCfg", "TriangleMeshPropertiesCfg", @@ -192,8 +200,6 @@ __all__ = [ "XformPrimView", ] -from .simulation_cfg import RenderCfg, SimulationCfg -from .simulation_context import SimulationContext, build_simulation_context from .converters import ( AssetConverterBase, AssetConverterBaseCfg, @@ -208,22 +214,6 @@ from .schemas import ( MESH_APPROXIMATION_TOKENS, PHYSX_MESH_COLLISION_CFGS, USD_MESH_COLLISION_CFGS, - activate_contact_sensors, - define_articulation_root_properties, - define_collision_properties, - define_deformable_body_properties, - define_mass_properties, - define_mesh_collision_properties, - define_rigid_body_properties, - modify_articulation_root_properties, - modify_collision_properties, - modify_deformable_body_properties, - modify_fixed_tendon_properties, - modify_joint_drive_properties, - modify_mass_properties, - modify_mesh_collision_properties, - modify_rigid_body_properties, - modify_spatial_tendon_properties, ArticulationRootPropertiesCfg, BoundingCubePropertiesCfg, BoundingSpherePropertiesCfg, @@ -234,16 +224,42 @@ from .schemas import ( DeformableBodyPropertiesCfg, FixedTendonPropertiesCfg, JointDriveBaseCfg, + MassCfg, + MassFragment, MassPropertiesCfg, MeshCollisionPropertiesCfg, PhysxJointDrivePropertiesCfg, PhysxRigidBodyPropertiesCfg, RigidBodyBaseCfg, + RigidBodyFragment, + SchemaFragment, SDFMeshPropertiesCfg, SpatialTendonPropertiesCfg, TriangleMeshPropertiesCfg, TriangleMeshSimplificationPropertiesCfg, + UsdPhysicsRigidBodyCfg, + activate_contact_sensors, + apply_mass_properties, + apply_namespaced, + apply_rigid_body_properties, + define_articulation_root_properties, + define_collision_properties, + define_deformable_body_properties, + define_mass_properties, + define_mesh_collision_properties, + define_rigid_body_properties, + modify_articulation_root_properties, + modify_collision_properties, + modify_deformable_body_properties, + modify_fixed_tendon_properties, + modify_joint_drive_properties, + modify_mass_properties, + modify_mesh_collision_properties, + modify_rigid_body_properties, + modify_spatial_tendon_properties, ) +from .simulation_cfg import RenderCfg, SimulationCfg +from .simulation_context import SimulationContext, build_simulation_context # Forwarded to isaaclab_newton.sim.schemas via __getattr__ shim MujocoJointDrivePropertiesCfg = ... @@ -256,46 +272,22 @@ NewtonMeshCollisionPropertiesCfg = ... NewtonRigidBodyPropertiesCfg = ... NewtonSDFCollisionPropertiesCfg = ... from .spawners import ( - SpawnerCfg, - RigidObjectSpawnerCfg, - DeformableObjectSpawnerCfg, - spawn_from_mjcf, - spawn_from_urdf, - spawn_from_usd, - spawn_from_usd_with_compliant_contact_material, - spawn_ground_plane, - GroundPlaneCfg, - MjcfFileCfg, - UrdfFileCfg, - UsdFileCfg, - UsdFileWithCompliantContactCfg, - spawn_light, + CapsuleCfg, + ConeCfg, + CuboidCfg, + CylinderCfg, CylinderLightCfg, + DeformableBodyMaterialBaseCfg, + DeformableBodyMaterialCfg, + DeformableObjectSpawnerCfg, DiskLightCfg, DistantLightCfg, DomeLightCfg, - LightCfg, - SphereLightCfg, - spawn_rigid_body_material, - spawn_deformable_body_material, - PhysicsMaterialCfg, - RigidBodyMaterialCfg, - DeformableBodyMaterialBaseCfg, - DeformableBodyMaterialCfg, - SurfaceDeformableBodyMaterialBaseCfg, - SurfaceDeformableBodyMaterialCfg, - spawn_from_mdl_file, - spawn_preview_surface, + FisheyeCameraCfg, GlassMdlCfg, + GroundPlaneCfg, + LightCfg, MdlFileCfg, - PreviewSurfaceCfg, - VisualMaterialCfg, - spawn_mesh_capsule, - spawn_mesh_cone, - spawn_mesh_cuboid, - spawn_mesh_cylinder, - spawn_mesh_rectangle, - spawn_mesh_sphere, MeshCapsuleCfg, MeshCfg, MeshConeCfg, @@ -303,83 +295,111 @@ from .spawners import ( MeshCylinderCfg, MeshRectangleCfg, MeshSphereCfg, - spawn_camera, - spawn_sensor_frame, - FisheyeCameraCfg, + MjcfFileCfg, + MultiAssetSpawnerCfg, + MultiUsdFileCfg, + PhysicsMaterialCfg, PinholeCameraCfg, + PreviewSurfaceCfg, + RigidBodyMaterialCfg, + RigidObjectSpawnerCfg, SensorFrameCfg, + ShapeCfg, + SpawnerCfg, + SphereCfg, + SphereLightCfg, + SurfaceDeformableBodyMaterialBaseCfg, + SurfaceDeformableBodyMaterialCfg, + UrdfFileCfg, + UsdFileCfg, + UsdFileWithCompliantContactCfg, + VisualMaterialCfg, + spawn_camera, spawn_capsule, spawn_cone, spawn_cuboid, spawn_cylinder, - spawn_sphere, - CapsuleCfg, - ConeCfg, - CuboidCfg, - CylinderCfg, - ShapeCfg, - SphereCfg, + spawn_deformable_body_material, + spawn_from_mdl_file, + spawn_from_mjcf, + spawn_from_urdf, + spawn_from_usd, + spawn_from_usd_with_compliant_contact_material, + spawn_ground_plane, + spawn_light, + spawn_mesh_capsule, + spawn_mesh_cone, + spawn_mesh_cuboid, + spawn_mesh_cylinder, + spawn_mesh_rectangle, + spawn_mesh_sphere, spawn_multi_asset, spawn_multi_usd_file, - MultiAssetSpawnerCfg, - MultiUsdFileCfg, + spawn_preview_surface, + spawn_rigid_body_material, + spawn_sensor_frame, + spawn_sphere, ) from .utils import ( + add_labels, add_reference_to_stage, - get_stage_up_axis, - traverse_stage, - get_prim_at_path, - get_prim_path, - is_prim_path_valid, - define_prim, - get_prim_type_name, - get_next_free_path, + add_usd_reference, + apply_nested, + bind_physics_material, + bind_visual_material, + change_prim_property, + check_missing_labels, + clear_stage, + clone, + close_stage, + convert_world_pose_to_local, + count_total_labels, + create_new_stage, create_prim, + define_prim, delete_prim, - make_uninstanceable, - set_prim_visibility, - safe_set_attribute_on_usd_schema, - safe_set_attribute_on_usd_prim, - change_prim_property, export_prim_to_file, - apply_nested, - clone, - bind_visual_material, - bind_physics_material, - add_usd_reference, - get_usd_references, - select_usd_variants, - get_next_free_prim_path, - get_first_matching_ancestor_prim, - get_first_matching_child_prim, - get_all_matching_child_prims, find_first_matching_prim, - find_matching_prims, - matches_path_expr_prefix, - resolve_matching_prims_from_source, - find_matching_prim_paths, find_global_fixed_joint_prim, - add_labels, + find_matching_prim_paths, + find_matching_prims, + get_all_matching_child_prims, + get_current_stage, + get_current_stage_id, + get_first_matching_ancestor_prim, + get_first_matching_child_prim, get_labels, - remove_labels, - check_missing_labels, - count_total_labels, - resolve_paths, - create_new_stage, + get_next_free_path, + get_next_free_prim_path, + get_prim_at_path, + get_prim_path, + get_prim_type_name, + get_stage_up_axis, + get_usd_references, is_current_stage_in_memory, + is_prim_path_valid, + make_uninstanceable, + matches_path_expr_prefix, open_stage, - use_stage, - update_stage, + remove_labels, + resolve_matching_prims_from_source, + resolve_paths, + resolve_prim_pose, + resolve_prim_scale, + safe_set_attribute_on_usd_prim, + safe_set_attribute_on_usd_schema, save_stage, - close_stage, - clear_stage, - get_current_stage, - get_current_stage_id, + select_usd_variants, + set_prim_visibility, standardize_xform_ops, + traverse_stage, + update_stage, + use_stage, validate_standard_xform_ops, - resolve_prim_pose, - resolve_prim_scale, - convert_world_pose_to_local, ) -from .views import BaseFrameView, UsdFrameView, FrameView -from .views import XformPrimView # deprecated alias +from .views import ( + BaseFrameView, + FrameView, + UsdFrameView, + XformPrimView, # deprecated alias +) diff --git a/source/isaaclab/isaaclab/sim/converters/mesh_converter.py b/source/isaaclab/isaaclab/sim/converters/mesh_converter.py index 74ba8b470c3a..52fe977b86b1 100644 --- a/source/isaaclab/isaaclab/sim/converters/mesh_converter.py +++ b/source/isaaclab/isaaclab/sim/converters/mesh_converter.py @@ -182,12 +182,20 @@ def _convert_asset(self, cfg: MeshConverterCfg): # Apply mass and rigid body properties after everything else # Properties are applied to the top level prim to avoid the case where all instances of this # asset unintentionally share the same rigid body properties - # apply mass properties + # apply mass properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> define_*) if cfg.mass_props is not None: - schemas.define_mass_properties(prim_path=xform_prim.GetPath(), cfg=cfg.mass_props, stage=stage) - # apply rigid body properties + mass_frags = cfg.mass_props if isinstance(cfg.mass_props, (list, tuple)) else [cfg.mass_props] + if mass_frags and all(isinstance(f, schemas.SchemaFragment) for f in mass_frags): + schemas.apply_mass_properties(str(xform_prim.GetPath()), mass_frags, stage=stage) + else: + schemas.define_mass_properties(prim_path=xform_prim.GetPath(), cfg=cfg.mass_props, stage=stage) + # apply rigid body properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> define_*) if cfg.rigid_props is not None: - schemas.define_rigid_body_properties(prim_path=xform_prim.GetPath(), cfg=cfg.rigid_props, stage=stage) + rigid_frags = cfg.rigid_props if isinstance(cfg.rigid_props, (list, tuple)) else [cfg.rigid_props] + if rigid_frags and all(isinstance(f, schemas.SchemaFragment) for f in rigid_frags): + schemas.apply_rigid_body_properties(str(xform_prim.GetPath()), rigid_frags, stage=stage) + else: + schemas.define_rigid_body_properties(prim_path=xform_prim.GetPath(), cfg=cfg.rigid_props, stage=stage) # Save changes to USD stage stage.Save() diff --git a/source/isaaclab/isaaclab/sim/schemas/__init__.pyi b/source/isaaclab/isaaclab/sim/schemas/__init__.pyi index 49eff741c8c8..a6ea01a293d4 100644 --- a/source/isaaclab/isaaclab/sim/schemas/__init__.pyi +++ b/source/isaaclab/isaaclab/sim/schemas/__init__.pyi @@ -8,6 +8,9 @@ __all__ = [ "PHYSX_MESH_COLLISION_CFGS", "USD_MESH_COLLISION_CFGS", "activate_contact_sensors", + "apply_mass_properties", + "apply_namespaced", + "apply_rigid_body_properties", "define_actuator_properties", "define_articulation_root_properties", "define_collision_properties", @@ -31,8 +34,13 @@ __all__ = [ "DeformableBodyPropertiesBaseCfg", "DeformableBodyPropertiesCfg", "JointDriveBaseCfg", + "MassCfg", + "MassFragment", "MassPropertiesCfg", "MeshCollisionBaseCfg", + "RigidBodyFragment", + "SchemaFragment", + "UsdPhysicsRigidBodyCfg", "MujocoJointDrivePropertiesCfg", "MujocoRigidBodyPropertiesCfg", "NewtonArticulationRootPropertiesCfg", @@ -50,6 +58,9 @@ from .schemas import ( PHYSX_MESH_COLLISION_CFGS, USD_MESH_COLLISION_CFGS, activate_contact_sensors, + apply_mass_properties, + apply_namespaced, + apply_rigid_body_properties, define_articulation_root_properties, define_collision_properties, define_deformable_body_properties, @@ -77,9 +88,14 @@ from .schemas_cfg import ( DeformableBodyPropertiesBaseCfg, DeformableBodyPropertiesCfg, JointDriveBaseCfg, + MassCfg, + MassFragment, MassPropertiesCfg, MeshCollisionBaseCfg, RigidBodyBaseCfg, + RigidBodyFragment, + SchemaFragment, + UsdPhysicsRigidBodyCfg, ) # Forwarded to isaaclab_newton.sim.schemas via __getattr__ shim diff --git a/source/isaaclab/isaaclab/sim/schemas/schemas.py b/source/isaaclab/isaaclab/sim/schemas/schemas.py index 23f53b105cb3..825bce54f9b0 100644 --- a/source/isaaclab/isaaclab/sim/schemas/schemas.py +++ b/source/isaaclab/isaaclab/sim/schemas/schemas.py @@ -9,6 +9,7 @@ import dataclasses import logging import math +from collections.abc import Iterable import numpy as np import warp as wp @@ -16,7 +17,7 @@ from pxr import Sdf, Usd, UsdGeom, UsdPhysics from isaaclab.sim.utils.stage import get_current_stage -from isaaclab.utils.string import to_camel_case +from isaaclab.utils.string import string_to_callable, to_camel_case from ..utils import ( apply_nested, @@ -214,6 +215,53 @@ class that declares it (walking the MRO). Each group writes under that class's safe_set_attribute_on_usd_prim(prim, f"{namespace}:{usd_attr}", value, camel_case=False) +def apply_namespaced(cfg: schemas_cfg.SchemaFragment, prim_path: str, stage: Usd.Stage | None = None) -> bool: + """Default fragment applier: apply the fragment's schema and write its namespaced attrs. + + Reads :attr:`~isaaclab.sim.schemas.SchemaFragment._usd_namespace` / + :attr:`~isaaclab.sim.schemas.SchemaFragment._usd_applied_schema` from the cfg's class. If the + fragment owns an applied schema, it is applied (once). Each non-``None`` dataclass field is + written as ``:``; the ``func`` field is skipped. ``None`` fields + are left unchanged on the prim (partial update). + + Args: + cfg: The fragment instance carrying ``_usd_namespace`` / ``_usd_applied_schema`` metadata. + prim_path: The prim path to author on. + stage: The stage where to find the prim. Defaults to None, in which case the current + stage is used. + + Returns: + True if the properties were successfully set. + """ + if stage is None: + stage = get_current_stage() + prim = stage.GetPrimAtPath(prim_path) + # fail loudly on an invalid path (matches the legacy define_/modify_ writers) + if not prim.IsValid(): + raise ValueError(f"Prim path '{prim_path}' is not valid.") + namespace = type(cfg)._usd_namespace + applied = type(cfg)._usd_applied_schema + # every fragment field is a namespaced USD attribute, so a namespace is required + if namespace is None: + raise ValueError( + f"Fragment '{type(cfg).__name__}' has no '_usd_namespace' set. Every fragment field is" + " authored as ':', so a USD namespace is required; non-USD state must" + " live on the spawner cfg or be passed as a writer keyword argument, not as a fragment" + " field." + ) + if applied and applied not in prim.GetAppliedSchemas(): + prim.AddAppliedSchema(applied) + for f in dataclasses.fields(cfg): + # ``func`` is the only non-USD field; non-scalar values raise in the setter + if f.name == "func": + continue + value = getattr(cfg, f.name) + if value is None: + continue + safe_set_attribute_on_usd_prim(prim, f"{namespace}:{to_camel_case(f.name, 'cC')}", value, camel_case=False) + return True + + """ Articulation root properties. """ @@ -386,6 +434,40 @@ def modify_articulation_root_properties( """ +def apply_rigid_body_properties( + prim_path: str, fragments: Iterable[schemas_cfg.RigidBodyFragment], stage: Usd.Stage | None = None +) -> bool: + """Apply a list of rigid-body fragments to a prim. + + Applies ``UsdPhysics.RigidBodyAPI`` as the implicit anchor (the defining schema for a rigid + body), then dispatches each fragment via its :attr:`~isaaclab.sim.schemas.SchemaFragment.func`. + Backend fragments carry backend-specific funcs, so core never imports a backend. + + Args: + prim_path: The prim path to apply the rigid-body schemas on. + fragments: An iterable of :class:`~isaaclab.sim.schemas.RigidBodyFragment` instances. + stage: The stage where to find the prim. Defaults to None, in which case the current + stage is used. + + Returns: + True if the properties were successfully set. + """ + if stage is None: + stage = get_current_stage() + prim = stage.GetPrimAtPath(prim_path) + # fail loudly on an invalid path (matches the legacy define_rigid_body_properties writer) + if not prim.IsValid(): + raise ValueError(f"Prim path '{prim_path}' is not valid.") + if not UsdPhysics.RigidBodyAPI(prim): + UsdPhysics.RigidBodyAPI.Apply(prim) + # aggregate per-fragment results so a reported failure is not masked by the always-applied anchor + success = True + for cfg in fragments: + func = cfg.func if callable(cfg.func) else string_to_callable(cfg.func) + success = bool(func(cfg, prim_path, stage)) and success + return success + + def define_rigid_body_properties(prim_path: str, cfg: schemas_cfg.RigidBodyBaseCfg, stage: Usd.Stage | None = None): """Apply the rigid body schema on the input prim and set its properties. @@ -569,6 +651,32 @@ def modify_collision_properties( """ +def apply_mass_properties(prim_path: str, fragments, stage: Usd.Stage | None = None) -> bool: + """Apply a list of mass fragments to a prim. + + Applies ``UsdPhysics.MassAPI`` as the implicit anchor (the defining schema for mass properties), + then dispatches each fragment via its :attr:`~isaaclab.sim.schemas.SchemaFragment.func`. + + Args: + prim_path: The prim path to apply the mass schemas on. + fragments: An iterable of :class:`~isaaclab.sim.schemas.MassFragment` instances. + stage: The stage where to find the prim. Defaults to None, in which case the current + stage is used. + + Returns: + True if the properties were successfully set. + """ + if stage is None: + stage = get_current_stage() + prim = stage.GetPrimAtPath(prim_path) + if not UsdPhysics.MassAPI(prim): + UsdPhysics.MassAPI.Apply(prim) + for cfg in fragments: + func = cfg.func if callable(cfg.func) else string_to_callable(cfg.func) + func(cfg, prim_path, stage) + return True + + def define_mass_properties(prim_path: str, cfg: schemas_cfg.MassPropertiesCfg, stage: Usd.Stage | None = None): """Apply the mass schema on the input prim and set its properties. diff --git a/source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py b/source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py index 4eaec2004e91..0343e9bd3625 100644 --- a/source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py +++ b/source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py @@ -6,6 +6,7 @@ from __future__ import annotations import warnings +from collections.abc import Callable from typing import ClassVar, Literal from isaaclab.utils.configclass import configclass @@ -106,6 +107,75 @@ def _deprecate_field_alias(cfg, alias: str, canonical: str) -> None: setattr(cfg, alias, None) +@configclass +class SchemaFragment: + """Base for a single-namespace USD-schema config fragment. + + Each subclass mirrors exactly one USD applied schema. The fragment carries class-level + metadata describing which USD namespace its fields write to (:attr:`_usd_namespace`) and + which applied schema, if any, it owns (:attr:`_usd_applied_schema`). The :attr:`func` + field names the callable that applies the fragment to a prim; the default generic applier + (:func:`~isaaclab.sim.schemas.apply_namespaced`) reads the metadata and writes each + non-``None`` field as ``:``. Irregular APIs override + :attr:`func` with a custom applier. + + .. note:: + A fragment present in a spawner slot means its schema is applied. ``None`` fields are + left unchanged on the prim (partial update). + + .. important:: + Every dataclass field other than :attr:`func` is authored as a USD attribute + ``<_usd_namespace>:``. A fragment must not carry non-USD/bookkeeping + fields -- such state belongs on the spawner cfg or as a writer keyword argument (this is + why ``fix_root_link`` / ``ensure_drives_exist`` are not fragment fields). The generic + applier (:func:`~isaaclab.sim.schemas.apply_namespaced`) enforces the invariant: it raises + when a fragment has no ``_usd_namespace``, and unsupported (non-scalar) value types raise + when written. + """ + + # -- Class metadata (not dataclass fields) -- + _usd_namespace: ClassVar[str | None] = None + _usd_applied_schema: ClassVar[str | None] = None + + func: Callable | str = "isaaclab.sim.schemas:apply_namespaced" + """Callable (or its ``module:attr`` import string) that applies this fragment to a prim. + + Resolved via :func:`~isaaclab.utils.string.string_to_callable` when a string. The callable + signature is ``func(cfg, prim_path, stage)``. + """ + + +@configclass +class RigidBodyFragment(SchemaFragment): + """Marker base for rigid-body fragments; types the ``rigid_props`` slot.""" + + pass + + +@configclass +class UsdPhysicsRigidBodyCfg(RigidBodyFragment): + """``physics:*`` rigid-body attributes from `UsdPhysics.RigidBodyAPI`_. + + The ``UsdPhysics.RigidBodyAPI`` schema is applied as the implicit anchor by the rigid-body + family writer, so this fragment owns no applied schema of its own. + + .. _UsdPhysics.RigidBodyAPI: https://openusd.org/dev/api/class_usd_physics_rigid_body_a_p_i.html + """ + + _usd_namespace: ClassVar[str | None] = "physics" + _usd_applied_schema: ClassVar[str | None] = None # RigidBodyAPI applied by the family anchor + + rigid_body_enabled: bool | None = None + """Whether to enable or disable the rigid body.""" + + kinematic_enabled: bool | None = None + """Determines whether the body is kinematic or not. + + A kinematic body is moved through animated or user-defined poses; the simulation still + derives velocities for it based on the external motion. + """ + + @configclass class ArticulationRootBaseCfg: """Solver-common properties to apply to the root of an articulation. @@ -335,6 +405,48 @@ class MassPropertiesCfg: """ +@configclass +class MassFragment(SchemaFragment): + """Marker base for mass fragments; types the ``mass_props`` slot.""" + + pass + + +@configclass +class MassCfg(MassFragment): + """``physics:*`` mass attributes from `UsdPhysics.MassAPI`_. + + The ``UsdPhysics.MassAPI`` schema is applied as the implicit anchor by the mass family writer + (:func:`~isaaclab.sim.schemas.apply_mass_properties`), so this fragment owns no applied schema + of its own. Mirrors the legacy :class:`MassPropertiesCfg`. + + .. note:: + A fragment present in a spawner slot means its schema is applied. ``None`` fields are left + unchanged on the prim (partial update). + + .. _UsdPhysics.MassAPI: https://openusd.org/dev/api/class_usd_physics_mass_a_p_i.html + """ + + _usd_namespace: ClassVar[str | None] = "physics" + _usd_applied_schema: ClassVar[str | None] = None # MassAPI applied by the family anchor + + mass: float | None = None + """The mass of the rigid body [kg]. + + Writes ``physics:mass`` via :class:`UsdPhysics.MassAPI`. + + Note: + If non-zero, the mass is ignored and the density is used to compute the mass. + """ + + density: float | None = None + """The density of the rigid body [kg/m^3]. + + Writes ``physics:density`` via :class:`UsdPhysics.MassAPI`. The density indirectly defines the + mass of the rigid body. It is generally computed using the collision approximation of the body. + """ + + @configclass class JointDriveBaseCfg: """Solver-common properties to define the drive mechanism of a joint. diff --git a/source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py b/source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py index 3a6fa939a63e..836aa893b937 100644 --- a/source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py +++ b/source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py @@ -344,13 +344,22 @@ def _spawn_from_usd_file( # modify rigid body properties if cfg.rigid_props is not None: - schemas.modify_rigid_body_properties(prim_path, cfg.rigid_props) + # transition shim, remove later: new fragment list -> apply_*; legacy single cfg -> modify_* + rigid_frags = cfg.rigid_props if isinstance(cfg.rigid_props, (list, tuple)) else [cfg.rigid_props] + if rigid_frags and all(isinstance(f, schemas.SchemaFragment) for f in rigid_frags): + schemas.apply_rigid_body_properties(prim_path, rigid_frags) + else: + schemas.modify_rigid_body_properties(prim_path, cfg.rigid_props) # modify collision properties if cfg.collision_props is not None: schemas.modify_collision_properties(prim_path, cfg.collision_props) - # modify mass properties + # modify mass properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> modify_*) if cfg.mass_props is not None: - schemas.modify_mass_properties(prim_path, cfg.mass_props) + mass_frags = cfg.mass_props if isinstance(cfg.mass_props, (list, tuple)) else [cfg.mass_props] + if mass_frags and all(isinstance(f, schemas.SchemaFragment) for f in mass_frags): + schemas.apply_mass_properties(prim_path, mass_frags) + else: + schemas.modify_mass_properties(prim_path, cfg.mass_props) # modify articulation root properties if cfg.articulation_props is not None: @@ -368,10 +377,18 @@ def _spawn_from_usd_file( # without it — actuatorgravcomp has no effect since there are no forces to route. # Only auto-populates when the user did not already set ``gravcomp`` themselves; # an explicit ``MujocoRigidBodyPropertiesCfg(gravcomp=0.5)`` is preserved as-is. - from isaaclab_newton.sim.schemas.schemas_cfg import MujocoJointDrivePropertiesCfg, MujocoRigidBodyPropertiesCfg + from isaaclab_newton.sim.schemas.schemas_cfg import ( + MujocoJointDrivePropertiesCfg, + MujocoRigidBodyCfg, + MujocoRigidBodyPropertiesCfg, + ) - body_gravcomp_unset = ( - not isinstance(cfg.rigid_props, MujocoRigidBodyPropertiesCfg) or cfg.rigid_props.gravcomp is None + # gravcomp may be authored either via the legacy MujocoRigidBodyPropertiesCfg or via a + # MujocoRigidBodyCfg fragment in a rigid_props list. Treat either as "already set". + rigid_props_list = cfg.rigid_props if isinstance(cfg.rigid_props, (list, tuple)) else [cfg.rigid_props] + body_gravcomp_unset = not any( + isinstance(f, (MujocoRigidBodyPropertiesCfg, MujocoRigidBodyCfg)) and f.gravcomp is not None + for f in rigid_props_list ) if ( isinstance(cfg.joint_drive_props, MujocoJointDrivePropertiesCfg) diff --git a/source/isaaclab/isaaclab/sim/spawners/meshes/meshes.py b/source/isaaclab/isaaclab/sim/spawners/meshes/meshes.py index cfc7f51b9ff2..0d9e0597445f 100644 --- a/source/isaaclab/isaaclab/sim/spawners/meshes/meshes.py +++ b/source/isaaclab/isaaclab/sim/spawners/meshes/meshes.py @@ -441,8 +441,16 @@ def _spawn_mesh_geom_from_mesh( # note: we apply the rigid properties to the parent prim in case of rigid objects. if cfg.rigid_props is not None: - # apply mass properties + # apply mass properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> define_*) if cfg.mass_props is not None: - schemas.define_mass_properties(prim_path, cfg.mass_props, stage=stage) - # apply rigid properties - schemas.define_rigid_body_properties(prim_path, cfg.rigid_props, stage=stage) + mass_frags = cfg.mass_props if isinstance(cfg.mass_props, (list, tuple)) else [cfg.mass_props] + if mass_frags and all(isinstance(f, schemas.SchemaFragment) for f in mass_frags): + schemas.apply_mass_properties(prim_path, mass_frags, stage=stage) + else: + schemas.define_mass_properties(prim_path, cfg.mass_props, stage=stage) + # apply rigid properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> define_*) + rigid_frags = cfg.rigid_props if isinstance(cfg.rigid_props, (list, tuple)) else [cfg.rigid_props] + if rigid_frags and all(isinstance(f, schemas.SchemaFragment) for f in rigid_frags): + schemas.apply_rigid_body_properties(prim_path, rigid_frags, stage=stage) + else: + schemas.define_rigid_body_properties(prim_path, cfg.rigid_props, stage=stage) diff --git a/source/isaaclab/isaaclab/sim/spawners/shapes/shapes.py b/source/isaaclab/isaaclab/sim/spawners/shapes/shapes.py index 9e8eafc1c578..785d36f8aea2 100644 --- a/source/isaaclab/isaaclab/sim/spawners/shapes/shapes.py +++ b/source/isaaclab/isaaclab/sim/spawners/shapes/shapes.py @@ -319,7 +319,17 @@ def _spawn_geom_from_prim_type( # note: we apply rigid properties in the end to later make the instanceable prim # apply mass properties if cfg.mass_props is not None: - schemas.define_mass_properties(prim_path, cfg.mass_props, stage=stage) + # transition shim, remove later: new fragment list -> apply_*; legacy single cfg -> define_* + mass_frags = cfg.mass_props if isinstance(cfg.mass_props, (list, tuple)) else [cfg.mass_props] + if mass_frags and all(isinstance(f, schemas.SchemaFragment) for f in mass_frags): + schemas.apply_mass_properties(prim_path, mass_frags, stage=stage) + else: + schemas.define_mass_properties(prim_path, cfg.mass_props, stage=stage) # apply rigid body properties if cfg.rigid_props is not None: - schemas.define_rigid_body_properties(prim_path, cfg.rigid_props, stage=stage) + # transition shim, remove later: new fragment list -> apply_*; legacy single cfg -> define_* + rigid_frags = cfg.rigid_props if isinstance(cfg.rigid_props, (list, tuple)) else [cfg.rigid_props] + if rigid_frags and all(isinstance(f, schemas.SchemaFragment) for f in rigid_frags): + schemas.apply_rigid_body_properties(prim_path, rigid_frags, stage=stage) + else: + schemas.define_rigid_body_properties(prim_path, cfg.rigid_props, stage=stage) diff --git a/source/isaaclab/isaaclab/sim/spawners/spawner_cfg.py b/source/isaaclab/isaaclab/sim/spawners/spawner_cfg.py index 3f1eef72a2fa..d492e0cae1db 100644 --- a/source/isaaclab/isaaclab/sim/spawners/spawner_cfg.py +++ b/source/isaaclab/isaaclab/sim/spawners/spawner_cfg.py @@ -82,14 +82,27 @@ class RigidObjectSpawnerCfg(SpawnerCfg): to the prim outside of the properties available by default when spawning the prim. """ - mass_props: schemas.MassPropertiesCfg | None = None - """Mass properties.""" + mass_props: schemas.MassPropertiesCfg | schemas.MassFragment | list[schemas.MassFragment] | None = None + """Mass properties. - rigid_props: schemas.RigidBodyBaseCfg | None = None + Accepts either a single legacy :class:`~isaaclab.sim.schemas.MassPropertiesCfg` or a list of + :class:`~isaaclab.sim.schemas.MassFragment` fragments (e.g. ``[MassCfg(...)]``). When a fragment + list is given, ``UsdPhysics.MassAPI`` is applied as the implicit anchor and each fragment writes + its own namespace. + """ + + rigid_props: schemas.RigidBodyBaseCfg | schemas.RigidBodyFragment | list[schemas.RigidBodyFragment] | None = None """Rigid body properties. + Accepts either a single legacy cfg (e.g. :class:`~isaaclab.sim.schemas.RigidBodyBaseCfg`) or a + list of :class:`~isaaclab.sim.schemas.RigidBodyFragment` fragments + (e.g. ``[UsdPhysicsRigidBodyCfg(...), PhysxRigidBodyCfg(...)]``). When a fragment list is given, + ``UsdPhysics.RigidBodyAPI`` is applied as the implicit anchor and each fragment writes its own + namespace. + For making a rigid object static, set the :attr:`schemas.RigidBodyBaseCfg.kinematic_enabled` - as True. This will make the object static and will not be affected by gravity or other forces. + (or :attr:`~isaaclab.sim.schemas.UsdPhysicsRigidBodyCfg.kinematic_enabled`) as True. This will + make the object static and will not be affected by gravity or other forces. """ collision_props: schemas.CollisionPropertiesCfg | None = None diff --git a/source/isaaclab/isaaclab/utils/renderers.py b/source/isaaclab/isaaclab/utils/renderers.py new file mode 100644 index 000000000000..171204e95014 --- /dev/null +++ b/source/isaaclab/isaaclab/utils/renderers.py @@ -0,0 +1,18 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Renderer-related utility helpers.""" + +import os + + +def isaac_rtx_per_env_scene_partition_enabled() -> bool: + """Return whether per-environment RTX scene partitioning is enabled. + + Partitioning is opt-in: set ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` + to enable authoring of ``primvars:omni:scenePartition`` and ``omni:scenePartition`` + on the USD stage. + """ + return os.environ.get("ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION", "0") == "1" diff --git a/source/isaaclab/pyproject.toml b/source/isaaclab/pyproject.toml index 03511cf9f6db..e3169ab0dc33 100644 --- a/source/isaaclab/pyproject.toml +++ b/source/isaaclab/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "isaaclab" -version = "7.0.5" +version = "7.1.0" description = "Extension providing main framework interfaces and abstractions for robot learning." license = {text = "BSD-3-Clause"} authors = [{name = "Isaac Lab Project Developers"}] diff --git a/source/isaaclab/test/sim/test_mass_fragments.py b/source/isaaclab/test/sim/test_mass_fragments.py new file mode 100644 index 000000000000..c470e0e3c7d9 --- /dev/null +++ b/source/isaaclab/test/sim/test_mass_fragments.py @@ -0,0 +1,112 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Launch Isaac Sim Simulator first.""" + +from isaaclab.app import AppLauncher + +# launch omniverse app +simulation_app = AppLauncher(headless=True).app + +"""Rest everything follows.""" + +from pxr import UsdGeom, UsdPhysics + +import isaaclab.sim as sim_utils +from isaaclab.sim import SimulationCfg, SimulationContext + + +def _make_xform(stage, path="/World/Body"): + UsdGeom.Xform.Define(stage, path) + return stage.GetPrimAtPath(path) + + +# ------------------------------------------------------------------------------------- +# Fragment metadata -- MassFragment marker, MassCfg +# ------------------------------------------------------------------------------------- + + +def test_fragment_metadata_defaults(): + from isaaclab.sim.schemas import MassCfg, MassFragment, SchemaFragment + + cfg = MassCfg(mass=2.0) + assert isinstance(cfg, MassFragment) and isinstance(cfg, SchemaFragment) + assert type(cfg)._usd_namespace == "physics" + assert type(cfg)._usd_applied_schema is None # anchor applies MassAPI, not the fragment + assert cfg.func == "isaaclab.sim.schemas:apply_namespaced" + assert cfg.mass == 2.0 and cfg.density is None + + +# ------------------------------------------------------------------------------------- +# apply_namespaced writes only the set fields under the physics namespace +# ------------------------------------------------------------------------------------- + + +def test_apply_namespaced_writes_only_set_fields(): + from isaaclab.sim.schemas import MassCfg, apply_namespaced + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + prim = _make_xform(stage) + UsdPhysics.MassAPI.Apply(prim) + apply_namespaced(MassCfg(mass=3.0), "/World/Body", stage) + assert abs(prim.GetAttribute("physics:mass").Get() - 3.0) < 1e-6 + # None field must not be authored (density exists as a MassAPI fallback attr) + assert not prim.GetAttribute("physics:density").HasAuthoredValue() + + +# ------------------------------------------------------------------------------------- +# apply_mass_properties dispatch (implicit MassAPI anchor) +# ------------------------------------------------------------------------------------- + + +def test_apply_mass_properties_applies_anchor_and_writes_fields(): + from isaaclab.sim.schemas import MassCfg, apply_mass_properties + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + _make_xform(stage, "/World/B2") + apply_mass_properties("/World/B2", [MassCfg(mass=5.0, density=100.0)], stage) + prim = stage.GetPrimAtPath("/World/B2") + assert bool(UsdPhysics.MassAPI(prim)) # implicit anchor applied + assert abs(prim.GetAttribute("physics:mass").Get() - 5.0) < 1e-6 + assert abs(prim.GetAttribute("physics:density").Get() - 100.0) < 1e-6 + + +# ------------------------------------------------------------------------------------- +# spawner slot accepts a fragment list + transition routing +# ------------------------------------------------------------------------------------- + + +def test_spawn_shape_with_mass_fragment_list(): + from isaaclab.sim.schemas import MassCfg, UsdPhysicsRigidBodyCfg + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + cfg = sim_utils.CuboidCfg( + size=(1, 1, 1), + rigid_props=[UsdPhysicsRigidBodyCfg(rigid_body_enabled=True)], + mass_props=[MassCfg(mass=4.0)], + ) + cfg.func("/World/Cube", cfg) + prim = sim_utils.get_current_stage().GetPrimAtPath("/World/Cube") + assert bool(UsdPhysics.MassAPI(prim)) + assert abs(prim.GetAttribute("physics:mass").Get() - 4.0) < 1e-6 + + +# ------------------------------------------------------------------------------------- +# public imports +# ------------------------------------------------------------------------------------- + + +def test_public_imports(): + from isaaclab.sim.schemas import ( # noqa: F401 + MassCfg, + MassFragment, + SchemaFragment, + apply_mass_properties, + ) diff --git a/source/isaaclab/test/sim/test_schema_fragments.py b/source/isaaclab/test/sim/test_schema_fragments.py new file mode 100644 index 000000000000..b76239963da2 --- /dev/null +++ b/source/isaaclab/test/sim/test_schema_fragments.py @@ -0,0 +1,237 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Launch Isaac Sim Simulator first.""" + +from isaaclab.app import AppLauncher + +# launch omniverse app +simulation_app = AppLauncher(headless=True).app + +"""Rest everything follows.""" + +import pytest + +from pxr import UsdGeom, UsdPhysics + +import isaaclab.sim as sim_utils +from isaaclab.sim import SimulationCfg, SimulationContext + + +def _make_xform(stage, path="/World/Body"): + UsdGeom.Xform.Define(stage, path) + return stage.GetPrimAtPath(path) + + +# ------------------------------------------------------------------------------------- +# SchemaFragment base, RigidBodyFragment marker, UsdPhysicsRigidBodyCfg +# ------------------------------------------------------------------------------------- + + +def test_fragment_metadata_defaults(): + from isaaclab.sim.schemas import RigidBodyFragment, SchemaFragment, UsdPhysicsRigidBodyCfg + + cfg = UsdPhysicsRigidBodyCfg(rigid_body_enabled=True) + assert isinstance(cfg, RigidBodyFragment) and isinstance(cfg, SchemaFragment) + assert type(cfg)._usd_namespace == "physics" + assert type(cfg)._usd_applied_schema is None # anchor applies RigidBodyAPI, not the fragment + assert cfg.func == "isaaclab.sim.schemas:apply_namespaced" + assert cfg.rigid_body_enabled is True and cfg.kinematic_enabled is None + + +# ------------------------------------------------------------------------------------- +# apply_namespaced generic applier +# ------------------------------------------------------------------------------------- + + +def test_apply_namespaced_writes_only_set_fields(): + from isaaclab.sim.schemas import UsdPhysicsRigidBodyCfg, apply_namespaced + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + prim = _make_xform(stage) + UsdPhysics.RigidBodyAPI.Apply(prim) + apply_namespaced(UsdPhysicsRigidBodyCfg(rigid_body_enabled=True), "/World/Body", stage) + assert prim.GetAttribute("physics:rigidBodyEnabled").Get() is True + # ``kinematicEnabled`` is a RigidBodyAPI fallback attr (so HasAttribute is True), but the + # None field must not be authored by apply_namespaced. + assert not prim.GetAttribute("physics:kinematicEnabled").HasAuthoredValue() + + +# ------------------------------------------------------------------------------------- +# PhysxRigidBodyCfg (isaaclab_physx) +# ------------------------------------------------------------------------------------- + + +def test_physx_rigid_body_fragment_writes_physx_namespace(): + from isaaclab_physx.sim.schemas import PhysxRigidBodyCfg + + from isaaclab.sim.schemas import apply_namespaced + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + prim = _make_xform(stage, "/World/B2") + UsdPhysics.RigidBodyAPI.Apply(prim) + apply_namespaced(PhysxRigidBodyCfg(linear_damping=0.1, disable_gravity=True), "/World/B2", stage) + assert abs(prim.GetAttribute("physxRigidBody:linearDamping").Get() - 0.1) < 1e-6 + assert prim.GetAttribute("physxRigidBody:disableGravity").Get() is True + + +# ------------------------------------------------------------------------------------- +# MujocoRigidBodyCfg (isaaclab_newton) +# ------------------------------------------------------------------------------------- + + +def test_mujoco_rigid_body_fragment_writes_mjc_namespace(): + from isaaclab_newton.sim.schemas import MujocoRigidBodyCfg + + from isaaclab.sim.schemas import apply_namespaced + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + prim = _make_xform(stage, "/World/B3") + UsdPhysics.RigidBodyAPI.Apply(prim) + apply_namespaced(MujocoRigidBodyCfg(gravcomp=1.0), "/World/B3", stage) + assert abs(prim.GetAttribute("mjc:gravcomp").Get() - 1.0) < 1e-6 + + +# ------------------------------------------------------------------------------------- +# apply_rigid_body_properties dispatch (implicit anchor + multi-namespace) +# ------------------------------------------------------------------------------------- + + +def test_apply_rigid_body_properties_composes_namespaces(): + from isaaclab_newton.sim.schemas import MujocoRigidBodyCfg + from isaaclab_physx.sim.schemas import PhysxRigidBodyCfg + + from isaaclab.sim.schemas import UsdPhysicsRigidBodyCfg, apply_rigid_body_properties + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + _make_xform(stage, "/World/B4") + apply_rigid_body_properties( + "/World/B4", + [ + UsdPhysicsRigidBodyCfg(rigid_body_enabled=True), + PhysxRigidBodyCfg(linear_damping=0.2), + MujocoRigidBodyCfg(gravcomp=1.0), + ], + stage, + ) + prim = stage.GetPrimAtPath("/World/B4") + assert bool(UsdPhysics.RigidBodyAPI(prim)) # implicit anchor applied + assert prim.GetAttribute("physics:rigidBodyEnabled").Get() is True + assert abs(prim.GetAttribute("physxRigidBody:linearDamping").Get() - 0.2) < 1e-6 + assert abs(prim.GetAttribute("mjc:gravcomp").Get() - 1.0) < 1e-6 + + +# ------------------------------------------------------------------------------------- +# spawner slot accepts a fragment list + transition routing +# ------------------------------------------------------------------------------------- + + +def test_spawn_shape_with_rigid_fragment_list(): + from isaaclab_physx.sim.schemas import PhysxRigidBodyCfg + + from isaaclab.sim.schemas import UsdPhysicsRigidBodyCfg + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + cfg = sim_utils.CuboidCfg( + size=(1, 1, 1), + rigid_props=[UsdPhysicsRigidBodyCfg(rigid_body_enabled=True), PhysxRigidBodyCfg(linear_damping=0.3)], + ) + cfg.func("/World/Cube", cfg) + prim = sim_utils.get_current_stage().GetPrimAtPath("/World/Cube") + assert bool(UsdPhysics.RigidBodyAPI(prim)) + assert abs(prim.GetAttribute("physxRigidBody:linearDamping").Get() - 0.3) < 1e-6 + + +# ------------------------------------------------------------------------------------- +# public imports +# ------------------------------------------------------------------------------------- + + +def test_public_imports(): + from isaaclab_newton.sim.schemas import MujocoRigidBodyCfg # noqa: F401 + from isaaclab_physx.sim.schemas import PhysxRigidBodyCfg # noqa: F401 + + from isaaclab.sim.schemas import ( # noqa: F401 + RigidBodyFragment, + SchemaFragment, + UsdPhysicsRigidBodyCfg, + apply_namespaced, + apply_rigid_body_properties, + ) + + +# ------------------------------------------------------------------------------------- +# Review follow-ups -- prim-validity guard, aggregated return, namespace invariant guard +# ------------------------------------------------------------------------------------- + + +def test_apply_namespaced_raises_on_invalid_prim(): + from isaaclab.sim.schemas import UsdPhysicsRigidBodyCfg, apply_namespaced + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + # no prim authored at this path -> GetPrimAtPath returns an invalid prim + with pytest.raises(ValueError): + apply_namespaced(UsdPhysicsRigidBodyCfg(rigid_body_enabled=True), "/World/DoesNotExist", stage) + + +def test_apply_rigid_body_properties_raises_on_invalid_prim(): + from isaaclab.sim.schemas import UsdPhysicsRigidBodyCfg, apply_rigid_body_properties + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + with pytest.raises(ValueError): + apply_rigid_body_properties("/World/DoesNotExist", [UsdPhysicsRigidBodyCfg(rigid_body_enabled=True)], stage) + + +def test_apply_rigid_body_properties_aggregates_fragment_results(): + from isaaclab.sim.schemas import UsdPhysicsRigidBodyCfg, apply_rigid_body_properties + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + _make_xform(stage, "/World/Agg") + + # a fragment whose applier reports failure must make the aggregate return False + failing = UsdPhysicsRigidBodyCfg(rigid_body_enabled=True) + failing.func = lambda cfg, prim_path, stage=None: False + assert apply_rigid_body_properties("/World/Agg", [failing], stage) is False + + # all-succeeding fragments return True + ok = UsdPhysicsRigidBodyCfg(rigid_body_enabled=True) + assert apply_rigid_body_properties("/World/Agg", [ok], stage) is True + + +def test_apply_namespaced_raises_without_namespace(): + from typing import ClassVar + + from isaaclab.sim.schemas import RigidBodyFragment, apply_namespaced + from isaaclab.utils import configclass + + @configclass + class _NoNamespaceFragment(RigidBodyFragment): + # deliberately leaves ``_usd_namespace`` as None, violating the fragment invariant that + # every field is authored as a namespaced USD attribute + _usd_namespace: ClassVar[str | None] = None + rigid_body_enabled: bool | None = None + + sim_utils.create_new_stage() + SimulationContext(SimulationCfg(dt=0.01)) + stage = sim_utils.get_current_stage() + prim = _make_xform(stage, "/World/NoNs") + UsdPhysics.RigidBodyAPI.Apply(prim) + with pytest.raises(ValueError): + apply_namespaced(_NoNamespaceFragment(rigid_body_enabled=True), "/World/NoNs", stage) diff --git a/source/isaaclab_newton/changelog.d/jmart-cartpole-rtx.minor.rst b/source/isaaclab_newton/changelog.d/jmart-cartpole-rtx.minor.rst deleted file mode 100644 index fc7a261e769f..000000000000 --- a/source/isaaclab_newton/changelog.d/jmart-cartpole-rtx.minor.rst +++ /dev/null @@ -1,7 +0,0 @@ -Added -^^^^^ - -* Overrode :meth:`provides_implicit_damping` on :class:`NewtonManager` to return ``False`` (its - symplectic integrator has no implicit damping) and :meth:`provides_temporal_camera_data` on - :class:`NewtonWarpRenderer` to return ``False`` (the rasterizer accumulates no temporal data), - so camera tasks can auto-enable frame stacking for the Newton combos that need it. diff --git a/source/isaaclab_newton/changelog.d/vidurv-schema-fragments.minor.rst b/source/isaaclab_newton/changelog.d/vidurv-schema-fragments.minor.rst new file mode 100644 index 000000000000..a4cb8ef1dddf --- /dev/null +++ b/source/isaaclab_newton/changelog.d/vidurv-schema-fragments.minor.rst @@ -0,0 +1,7 @@ +Added +^^^^^ + +* Added :class:`~isaaclab_newton.sim.schemas.MujocoRigidBodyCfg`, the ``mjc:*`` single-namespace + rigid-body fragment (``mjc:gravcomp``) for Newton's MuJoCo solver. It composes with + :class:`~isaaclab.sim.schemas.UsdPhysicsRigidBodyCfg` and + :class:`~isaaclab_physx.sim.schemas.PhysxRigidBodyCfg` in a ``rigid_props`` fragment list. diff --git a/source/isaaclab_newton/config/extension.toml b/source/isaaclab_newton/config/extension.toml index e634a251cfc0..d2e4ba3d446a 100644 --- a/source/isaaclab_newton/config/extension.toml +++ b/source/isaaclab_newton/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "1.0.4" +version = "1.1.0" # Description title = "Newton simulation interfaces for IsaacLab core package" diff --git a/source/isaaclab_newton/docs/CHANGELOG.rst b/source/isaaclab_newton/docs/CHANGELOG.rst index 1e92f80043e8..45dfdd21f71a 100644 --- a/source/isaaclab_newton/docs/CHANGELOG.rst +++ b/source/isaaclab_newton/docs/CHANGELOG.rst @@ -1,6 +1,26 @@ Changelog --------- +1.1.0 (2026-06-24) +~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Overrode :meth:`provides_implicit_damping` on :class:`NewtonManager` to return ``False`` (its + symplectic integrator has no implicit damping) and :meth:`provides_temporal_camera_data` on + :class:`NewtonWarpRenderer` to return ``False`` (the rasterizer accumulates no temporal data), + so camera tasks can auto-enable frame stacking for the Newton combos that need it. + +Fixed +^^^^^ + +* Fixed the ``newton[sim]`` dependency pin to use Newton commit + ``79e95bf5571d70a0a46c8eaedc80644531d27368``, including the + RenderContext triangle-mesh construction fix from `newton-physics/newton#3199 + `_. + + 1.0.4 (2026-06-23) ~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_newton/isaaclab_newton/sim/schemas/__init__.pyi b/source/isaaclab_newton/isaaclab_newton/sim/schemas/__init__.pyi index e546498ee4aa..89ca2d068afb 100644 --- a/source/isaaclab_newton/isaaclab_newton/sim/schemas/__init__.pyi +++ b/source/isaaclab_newton/isaaclab_newton/sim/schemas/__init__.pyi @@ -5,6 +5,7 @@ __all__ = [ "MujocoJointDrivePropertiesCfg", + "MujocoRigidBodyCfg", "MujocoRigidBodyPropertiesCfg", "NewtonArticulationRootPropertiesCfg", "NewtonCollisionPropertiesCfg", @@ -18,6 +19,7 @@ __all__ = [ from .schemas_cfg import ( MujocoJointDrivePropertiesCfg, + MujocoRigidBodyCfg, MujocoRigidBodyPropertiesCfg, NewtonArticulationRootPropertiesCfg, NewtonCollisionPropertiesCfg, diff --git a/source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py b/source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py index a7b0d0082577..4c99379e1ad8 100644 --- a/source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py +++ b/source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py @@ -14,6 +14,7 @@ JointDriveBaseCfg, MeshCollisionBaseCfg, RigidBodyBaseCfg, + RigidBodyFragment, ) from isaaclab.sim.spawners.materials.physics_materials_cfg import RigidBodyMaterialBaseCfg from isaaclab.utils.configclass import configclass @@ -84,6 +85,31 @@ class MujocoRigidBodyPropertiesCfg(NewtonRigidBodyPropertiesCfg): """ +@configclass +class MujocoRigidBodyCfg(RigidBodyFragment): + """``mjc:*`` rigid-body attributes for Newton's MuJoCo solver. + + A single-namespace fragment (see :class:`~isaaclab.sim.schemas.SchemaFragment`) carrying + body-level gravity compensation. The ``mjc`` namespace has no applied schema; the + ``UsdPhysics.RigidBodyAPI`` anchor is applied by + :func:`~isaaclab.sim.schemas.apply_rigid_body_properties`. + + .. note:: + A ``newton:*`` rigid-body fragment is reserved but currently empty (Newton has no native + ``newton:`` rigid-body attributes today). + """ + + _usd_namespace: ClassVar[str | None] = "mjc" + _usd_applied_schema: ClassVar[str | None] = None + + gravcomp: float | None = None + """Gravity compensation scale for the body [dimensionless]. + + ``0.0`` = no compensation; ``1.0`` = full compensation. Written to ``mjc:gravcomp``. Body-level + gravcomp must be set for joint-level ``actuatorgravcomp`` to have any effect. + """ + + @configclass class NewtonJointDrivePropertiesCfg(JointDriveBaseCfg): """Newton-targeted joint drive properties. diff --git a/source/isaaclab_newton/pyproject.toml b/source/isaaclab_newton/pyproject.toml index 880c175855d5..68c9fbae4ebc 100644 --- a/source/isaaclab_newton/pyproject.toml +++ b/source/isaaclab_newton/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "isaaclab_newton" -version = "1.0.4" +version = "1.1.0" description = "Extension providing IsaacLab with Newton specific abstractions." license = {text = "BSD-3-Clause"} authors = [{name = "Isaac Lab Project Developers"}] @@ -27,7 +27,7 @@ all = [ "prettytable>=3.3.0", "PyOpenGL-accelerate>=3.1.0", "pyglet>=2.1.6,<3", - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", ] [tool.setuptools] diff --git a/source/isaaclab_ov/changelog.d/extend-test-distance-aovs.rst b/source/isaaclab_ov/changelog.d/extend-test-distance-aovs.rst new file mode 100644 index 000000000000..e2a7880fc16c --- /dev/null +++ b/source/isaaclab_ov/changelog.d/extend-test-distance-aovs.rst @@ -0,0 +1,6 @@ +Fixed +^^^^^ + +* Fixed ``distance_to_camera`` incorrectly mapping to ``DistanceToImagePlaneSD`` in the OVRTX + renderer backend. It now correctly uses ``DistanceToCameraSD``, matching the intended semantics + of eye-space ray length versus perpendicular image-plane distance. diff --git a/source/isaaclab_ov/changelog.d/jmart-cartpole-rtx.minor.rst b/source/isaaclab_ov/changelog.d/jmart-cartpole-rtx.minor.rst deleted file mode 100644 index 86cfb672bf0b..000000000000 --- a/source/isaaclab_ov/changelog.d/jmart-cartpole-rtx.minor.rst +++ /dev/null @@ -1,6 +0,0 @@ -Added -^^^^^ - -* Overrode :meth:`provides_temporal_camera_data` on :class:`OVRTXRenderer` to return ``True`` - only for the ``rgb``/``rgba`` beauty buffer (temporally accumulated by DLSS), matching Isaac RTX; - other AOVs return ``False``. diff --git a/source/isaaclab_ov/config/extension.toml b/source/isaaclab_ov/config/extension.toml index e4ec845231d9..5c240c1cf43a 100644 --- a/source/isaaclab_ov/config/extension.toml +++ b/source/isaaclab_ov/config/extension.toml @@ -1,5 +1,5 @@ [package] -version = "0.4.6" +version = "0.5.0" title = "Omniverse renderers for IsaacLab" description = "Extension providing Omniverse renderers (OVRTX, ovphysx, etc.) for tiled camera rendering." readme = "docs/README.md" diff --git a/source/isaaclab_ov/docs/CHANGELOG.rst b/source/isaaclab_ov/docs/CHANGELOG.rst index 4307aa7707a4..b6bc15626d66 100644 --- a/source/isaaclab_ov/docs/CHANGELOG.rst +++ b/source/isaaclab_ov/docs/CHANGELOG.rst @@ -1,6 +1,17 @@ Changelog --------- +0.5.0 (2026-06-24) +~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Overrode :meth:`provides_temporal_camera_data` on :class:`OVRTXRenderer` to return ``True`` + only for the ``rgb``/``rgba`` beauty buffer (temporally accumulated by DLSS), matching Isaac RTX; + other AOVs return ``False``. + + 0.4.6 (2026-06-16) ~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py index 08d5855f33cf..359e1c4bd365 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py @@ -757,7 +757,7 @@ def _process_render_frame(self, render_data: OVRTXRenderData, frame, output_buff tiled_data = wp.from_dlpack(mapping.tensor) self._extract_rgba_tiles(render_data, tiled_data, output_buffers, buffer_key) - for depth_var in ["DistanceToImagePlaneSD", "DepthSD"]: + for depth_var in ["DistanceToCameraSD", "DistanceToImagePlaneSD", "DepthSD"]: if depth_var not in frame.render_vars: continue with frame.render_vars[depth_var].map(device=Device.CUDA) as mapping: diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py index e774703dc68f..be91d46f14e4 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py @@ -18,13 +18,17 @@ def get_render_var_config(data_types: list[str]) -> tuple[str, str, str]: """Return (render_var_path, render_var_name, source_name) from data_types.""" use_depth = any(dt in ["depth", "distance_to_image_plane", "distance_to_camera"] for dt in data_types) + use_distance_to_camera = "distance_to_camera" in data_types and not any( + dt in ["depth", "distance_to_image_plane"] for dt in data_types + ) use_albedo = "albedo" in data_types use_semantic = "semantic_segmentation" in data_types use_rgb = any(dt in ["rgb", "rgba"] for dt in data_types) use_hdr = "rgb_hdr" in data_types if use_depth and not (use_rgb or use_albedo or use_semantic): - return "/Render/Vars/depth", "depth", "DistanceToImagePlaneSD" + source = "DistanceToCameraSD" if use_distance_to_camera else "DistanceToImagePlaneSD" + return "/Render/Vars/depth", "depth", source if use_albedo and not (use_rgb or use_semantic): return "/Render/Vars/albedo", "albedo", "DiffuseAlbedoSD" if use_semantic and not (use_rgb or use_albedo): diff --git a/source/isaaclab_ov/pyproject.toml b/source/isaaclab_ov/pyproject.toml index e24cd26ee96f..6a8b4704efdb 100644 --- a/source/isaaclab_ov/pyproject.toml +++ b/source/isaaclab_ov/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "isaaclab_ov" -version = "0.4.6" +version = "0.5.0" description = "Extension providing Omniverse renderers (OVRTX, ovphysx, etc.) for tiled camera rendering." license = {text = "BSD-3-Clause"} authors = [{name = "Isaac Lab Project Developers"}] diff --git a/source/isaaclab_physx/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst b/source/isaaclab_physx/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst new file mode 100644 index 000000000000..826584fd2dba --- /dev/null +++ b/source/isaaclab_physx/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst @@ -0,0 +1,7 @@ +Changed +^^^^^^^ + +* Changed :meth:`~isaaclab_physx.renderers.IsaacRtxRenderer.prepare_stage` to skip authoring + ``primvars:omni:scenePartition`` and ``omni:scenePartition`` by default. Set the environment + variable ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` to re-enable + per-environment scene partitioning for Isaac RTX rendering. diff --git a/source/isaaclab_physx/changelog.d/jmart-cartpole-rtx.minor.rst b/source/isaaclab_physx/changelog.d/jmart-cartpole-rtx.minor.rst deleted file mode 100644 index 1f2a1c956e42..000000000000 --- a/source/isaaclab_physx/changelog.d/jmart-cartpole-rtx.minor.rst +++ /dev/null @@ -1,6 +0,0 @@ -Added -^^^^^ - -* Overrode :meth:`provides_temporal_camera_data` on :class:`IsaacRtxRenderer` to return ``True`` - only for the ``rgb``/``rgba`` beauty buffer (temporally accumulated by DLSS); the depth, albedo, - simple_shading, and segmentation AOVs return ``False`` as they bypass DLSS. diff --git a/source/isaaclab_physx/changelog.d/vidurv-schema-fragments.minor.rst b/source/isaaclab_physx/changelog.d/vidurv-schema-fragments.minor.rst new file mode 100644 index 000000000000..6bd8bcac8b86 --- /dev/null +++ b/source/isaaclab_physx/changelog.d/vidurv-schema-fragments.minor.rst @@ -0,0 +1,8 @@ +Added +^^^^^ + +* Added :class:`~isaaclab_physx.sim.schemas.PhysxRigidBodyCfg`, the ``physxRigidBody:*`` + single-namespace rigid-body fragment (PhysX ``PhysxRigidBodyAPI``). It carries the PhysX + damping / velocity-limit / solver-iteration / sleep fields plus ``disable_gravity``, and + composes with :class:`~isaaclab.sim.schemas.UsdPhysicsRigidBodyCfg` in a ``rigid_props`` + fragment list. diff --git a/source/isaaclab_physx/config/extension.toml b/source/isaaclab_physx/config/extension.toml index 519859d53fc1..1640fb94cafe 100644 --- a/source/isaaclab_physx/config/extension.toml +++ b/source/isaaclab_physx/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "2.0.2" +version = "2.1.0" # Description title = "PhysX simulation interfaces for IsaacLab core package" diff --git a/source/isaaclab_physx/docs/CHANGELOG.rst b/source/isaaclab_physx/docs/CHANGELOG.rst index 6f7c55b3b0ba..a503a8c4ca41 100644 --- a/source/isaaclab_physx/docs/CHANGELOG.rst +++ b/source/isaaclab_physx/docs/CHANGELOG.rst @@ -1,6 +1,25 @@ Changelog --------- +2.1.0 (2026-06-24) +~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Overrode :meth:`provides_temporal_camera_data` on :class:`IsaacRtxRenderer` to return ``True`` + only for the ``rgb``/``rgba`` beauty buffer (temporally accumulated by DLSS); the depth, albedo, + simple_shading, and segmentation AOVs return ``False`` as they bypass DLSS. + +Fixed +^^^^^ + +* Fixed the optional ``newton[sim]`` dependency pin to use Newton commit + ``79e95bf5571d70a0a46c8eaedc80644531d27368``, including the + RenderContext triangle-mesh construction fix from `newton-physics/newton#3199 + `_. + + 2.0.2 (2026-06-17) ~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_physx/isaaclab_physx/renderers/isaac_rtx_renderer.py b/source/isaaclab_physx/isaaclab_physx/renderers/isaac_rtx_renderer.py index 6fa530c52514..5eecd87242b9 100644 --- a/source/isaaclab_physx/isaaclab_physx/renderers/isaac_rtx_renderer.py +++ b/source/isaaclab_physx/isaaclab_physx/renderers/isaac_rtx_renderer.py @@ -22,6 +22,7 @@ from isaaclab.app.settings_manager import get_settings_manager from isaaclab.renderers import BaseRenderer, RenderBufferKind, RenderBufferSpec from isaaclab.renderers.camera_render_spec import CameraRenderSpec +from isaaclab.utils.renderers import isaac_rtx_per_env_scene_partition_enabled from isaaclab.utils.version import get_isaac_sim_version from isaaclab.utils.warp.kernels import reshape_tiled_image from isaaclab.utils.warp.warp_math import clamp_depth_to_inf_wp, replace_inf_depth_wp @@ -187,12 +188,28 @@ def supported_output_types(self) -> dict[RenderBufferKind, RenderBufferSpec]: def prepare_stage(self, stage: Usd.Stage, num_envs: int) -> None: """Author per-env ``omni:scenePartition`` attributes for RTX cull-by-env rendering. - For each ``/World/envs/env_{i}`` root, writes the inheriting primvar + Authoring is only performed when + ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` is set. + When the variable is absent the method is a no-op and no ``primvars:omni:scenePartition`` + or ``omni:scenePartition`` attributes are written to the stage. + + When enabled, for each ``/World/envs/env_{i}`` root, writes the inheriting primvar ``primvars:omni:scenePartition`` (token ``env_{i}``) on the root and the matching non-primvar ``omni:scenePartition`` token on every :class:`UsdGeom.Camera` descendant. RTX honors primvar inheritance, so the env-root primvar propagates to all descendant geometry and isolates each env's render tile. See :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.prepare_stage`.""" + + if not isaac_rtx_per_env_scene_partition_enabled(): + return + + logger.debug( + "Per-environment RTX scene partitioning is enabled" + " (ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1)." + " Authoring primvars:omni:scenePartition on %d env(s).", + num_envs, + ) + root_layer = stage.GetRootLayer() token_type = Sdf.ValueTypeNames.Token with Sdf.ChangeBlock(): diff --git a/source/isaaclab_physx/isaaclab_physx/sim/schemas/__init__.pyi b/source/isaaclab_physx/isaaclab_physx/sim/schemas/__init__.pyi index b542edf9f454..10d2502ddf2b 100644 --- a/source/isaaclab_physx/isaaclab_physx/sim/schemas/__init__.pyi +++ b/source/isaaclab_physx/isaaclab_physx/sim/schemas/__init__.pyi @@ -23,6 +23,7 @@ __all__ = [ "PhysxDeformableCollisionPropertiesCfg", "PhysxFixedTendonPropertiesCfg", "PhysxJointDrivePropertiesCfg", + "PhysxRigidBodyCfg", "PhysxRigidBodyPropertiesCfg", "PhysxSDFMeshPropertiesCfg", "PhysxSpatialTendonPropertiesCfg", @@ -57,6 +58,7 @@ from .schemas_cfg import ( PhysxDeformableCollisionPropertiesCfg, PhysxFixedTendonPropertiesCfg, PhysxJointDrivePropertiesCfg, + PhysxRigidBodyCfg, PhysxRigidBodyPropertiesCfg, PhysxSDFMeshPropertiesCfg, PhysxSpatialTendonPropertiesCfg, diff --git a/source/isaaclab_physx/isaaclab_physx/sim/schemas/schemas_cfg.py b/source/isaaclab_physx/isaaclab_physx/sim/schemas/schemas_cfg.py index 2eacd969e949..18a5de023f90 100644 --- a/source/isaaclab_physx/isaaclab_physx/sim/schemas/schemas_cfg.py +++ b/source/isaaclab_physx/isaaclab_physx/sim/schemas/schemas_cfg.py @@ -15,6 +15,7 @@ JointDriveBaseCfg, MeshCollisionBaseCfg, RigidBodyBaseCfg, + RigidBodyFragment, ) from isaaclab.utils.configclass import configclass @@ -261,6 +262,64 @@ class PhysxRigidBodyPropertiesCfg(RigidBodyBaseCfg): """The mass-normalized kinetic energy threshold below which an actor may participate in stabilization.""" +@configclass +class PhysxRigidBodyCfg(RigidBodyFragment): + """``physxRigidBody:*`` rigid-body attributes from `PhysxRigidBodyAPI`_. + + A single-namespace fragment (see :class:`~isaaclab.sim.schemas.SchemaFragment`) for the + PhysX rigid-body add-on schema. Applied alongside :class:`~isaaclab.sim.schemas.UsdPhysicsRigidBodyCfg` + via :func:`~isaaclab.sim.schemas.apply_rigid_body_properties`. + + .. _PhysxRigidBodyAPI: https://docs.omniverse.nvidia.com/kit/docs/omni_usd_schema_physics/104.2/class_physx_schema_physx_rigid_body_a_p_i.html + """ + + _usd_namespace: ClassVar[str | None] = "physxRigidBody" + _usd_applied_schema: ClassVar[str | None] = "PhysxRigidBodyAPI" + + linear_damping: float | None = None + """Linear damping coefficient for the body [1/s].""" + + angular_damping: float | None = None + """Angular damping coefficient for the body [1/s].""" + + max_linear_velocity: float | None = None + """Maximum linear velocity for the body [m/s].""" + + max_angular_velocity: float | None = None + """Maximum angular velocity for the body [deg/s].""" + + max_depenetration_velocity: float | None = None + """Maximum depenetration velocity permitted to be introduced by the solver [m/s].""" + + max_contact_impulse: float | None = None + """The limit on the impulse that may be applied at a contact [N·s].""" + + enable_gyroscopic_forces: bool | None = None + """Enables computation of gyroscopic forces on the rigid body.""" + + retain_accelerations: bool | None = None + """Carries over forces/accelerations over sub-steps.""" + + solver_position_iteration_count: int | None = None + """Solver position iteration counts for the body.""" + + solver_velocity_iteration_count: int | None = None + """Solver velocity iteration counts for the body.""" + + sleep_threshold: float | None = None + """Mass-normalized kinetic energy threshold below which an actor may go to sleep [m²/s²].""" + + stabilization_threshold: float | None = None + """Mass-normalized kinetic energy threshold below which an actor may participate in stabilization [m²/s²].""" + + disable_gravity: bool | None = None + """Disable gravity for the body. + + PhysX honors this per-body via ``physxRigidBody:disableGravity``: setting True excludes the + body from world gravity integration. + """ + + @configclass class RigidBodyPropertiesCfg(PhysxRigidBodyPropertiesCfg): """Deprecated: use :class:`PhysxRigidBodyPropertiesCfg` or :class:`~isaaclab.sim.schemas.RigidBodyBaseCfg`. diff --git a/source/isaaclab_physx/pyproject.toml b/source/isaaclab_physx/pyproject.toml index f63c83809f95..305c6d17d1b4 100644 --- a/source/isaaclab_physx/pyproject.toml +++ b/source/isaaclab_physx/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "isaaclab_physx" -version = "2.0.2" +version = "2.1.0" description = "Extension providing IsaacLab with PhysX specific abstractions." license = {text = "BSD-3-Clause"} authors = [{name = "Isaac Lab Project Developers"}] @@ -24,7 +24,7 @@ Repository = "https://github.com/isaac-sim/IsaacLab" [project.optional-dependencies] newton = [ - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", ] [tool.setuptools] diff --git a/source/isaaclab_physx/test/renderers/test_isaac_rtx_renderer_scene_partitioning.py b/source/isaaclab_physx/test/renderers/test_isaac_rtx_renderer_scene_partitioning.py index c54bf9ee85ef..22c3ae59a75f 100644 --- a/source/isaaclab_physx/test/renderers/test_isaac_rtx_renderer_scene_partitioning.py +++ b/source/isaaclab_physx/test/renderers/test_isaac_rtx_renderer_scene_partitioning.py @@ -17,6 +17,12 @@ ``isaacsim_ci`` test file in its own app, so keeping these tests isolated here gives them a clean renderer and exercises the real single-scene use case. +Per-env scene partitioning is gated behind the +``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION`` environment variable and is off +by default. Tests that verify partitioning is *active* use the ``enable_scene_partition`` +fixture, which sets the variable for the duration of the test and restores the previous +state afterwards. + Launch Isaac Sim Simulator first. """ @@ -32,6 +38,7 @@ import pytest import torch import warp as wp +from isaaclab_physx.renderers.isaac_rtx_renderer import IsaacRtxRenderer, IsaacRtxRendererCfg import isaaclab.sim as sim_utils from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg @@ -42,9 +49,42 @@ from isaaclab_assets.robots.kuka_allegro import KUKA_ALLEGRO_CFG +_ENV_VAR = "ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION" + + +@pytest.fixture() +def enable_scene_partition(monkeypatch): + """Set ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` for the duration of one test.""" + monkeypatch.setenv(_ENV_VAR, "1") + + +@pytest.mark.isaacsim_ci +def test_partitioning_disabled_by_default(monkeypatch): + """``primvars:omni:scenePartition`` must NOT be authored when the env var is absent. + + The feature is off by default; this test confirms that :meth:`IsaacRtxRenderer.prepare_stage` + is a no-op without ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1``. + """ + from pxr import Usd + + monkeypatch.delenv(_ENV_VAR, raising=False) + + stage = Usd.Stage.CreateInMemory() + world = stage.DefinePrim("/World", "Xform") # noqa: F841 + env0 = stage.DefinePrim("/World/envs/env_0", "Xform") # noqa: F841 + + renderer = object.__new__(IsaacRtxRenderer) + renderer.cfg = IsaacRtxRendererCfg() + renderer.prepare_stage(stage, num_envs=1) + + prim = stage.GetPrimAtPath("/World/envs/env_0") + assert not prim.HasAttribute("primvars:omni:scenePartition"), ( + "primvars:omni:scenePartition must not be authored when partitioning is disabled." + ) + @pytest.mark.isaacsim_ci -def test_partitioning_isolates_rigid_object(): +def test_partitioning_isolates_rigid_object(enable_scene_partition): """Per-env :class:`~isaaclab.assets.RigidObject` instances at unique world positions render as visibly different per-env tiles when RTX honors ``primvars:omni:scenePartition``.""" @@ -111,7 +151,7 @@ class _Scene(InteractiveSceneCfg): @pytest.mark.isaacsim_ci -def test_partitioning_isolates_articulation(): +def test_partitioning_isolates_articulation(enable_scene_partition): """Per-env :class:`~isaaclab.assets.Articulation` instances driven to wildly different joint poses render as visibly different per-env tiles when RTX honors top-level scene partitions.""" diff --git a/source/isaaclab_tasks/changelog.d/extend-test-distance-aovs.rst b/source/isaaclab_tasks/changelog.d/extend-test-distance-aovs.rst new file mode 100644 index 000000000000..735bf4d24276 --- /dev/null +++ b/source/isaaclab_tasks/changelog.d/extend-test-distance-aovs.rst @@ -0,0 +1,7 @@ +Added +^^^^^ + +* Added golden-image rendering tests for ``distance_to_camera`` and ``distance_to_image_plane`` + AOV types across the Cartpole, DexSuite Kuka, and Shadow Hand camera environments. + Test-local subclasses of the relevant env and camera configs are used so the production + task API remains unchanged. diff --git a/source/isaaclab_tasks/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst b/source/isaaclab_tasks/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst new file mode 100644 index 000000000000..0731b9c88cb1 --- /dev/null +++ b/source/isaaclab_tasks/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst @@ -0,0 +1,6 @@ +Added +^^^^^ + +* Added ``enable_scene_partition`` pytest fixture and enabled Isaac RTX per-environment scene + partitioning in rendering correctness tests for cartpole and registered camera tasks as a + temporary workaround. diff --git a/source/isaaclab_tasks/changelog.d/jmart-cartpole-rtx.rst b/source/isaaclab_tasks/changelog.d/jmart-cartpole-rtx.rst deleted file mode 100644 index c25a345722f7..000000000000 --- a/source/isaaclab_tasks/changelog.d/jmart-cartpole-rtx.rst +++ /dev/null @@ -1,13 +0,0 @@ -Fixed -^^^^^ - -* Fixed the camera-based Cartpole task failing to converge under Newton physics with the RTX - ``depth``, ``albedo``, and ``simple_shading`` AOV observations. These AOVs bypass DLSS temporal - accumulation, so the observation carried no temporal cue for the policy to infer velocity from - (Newton's symplectic integrator has no implicit damping). The ``frame_stack`` default resolver - now enables 2-frame stacking for these Newton + RTX AOVs, matching the existing Newton + Warp - behavior; Newton + RTX ``rgb`` keeps single-frame observations as DLSS already supplies the cue. - The resolver reads backend capability classmethods - (:meth:`~isaaclab.physics.physics_manager.PhysicsManager.provides_implicit_damping`, - :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.provides_temporal_camera_data`) resolved - from the configs, instead of hard-coding backend types in the task. diff --git a/source/isaaclab_tasks/config/extension.toml b/source/isaaclab_tasks/config/extension.toml index 781b51f6cca7..e05d772e49a6 100644 --- a/source/isaaclab_tasks/config/extension.toml +++ b/source/isaaclab_tasks/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "8.0.4" +version = "8.0.5" # Description title = "Isaac Lab Environments" diff --git a/source/isaaclab_tasks/docs/CHANGELOG.rst b/source/isaaclab_tasks/docs/CHANGELOG.rst index 540363429b2c..aff3e0f19094 100644 --- a/source/isaaclab_tasks/docs/CHANGELOG.rst +++ b/source/isaaclab_tasks/docs/CHANGELOG.rst @@ -1,6 +1,24 @@ Changelog --------- +8.0.5 (2026-06-24) +~~~~~~~~~~~~~~~~~~ + +Fixed +^^^^^ + +* Fixed the camera-based Cartpole task failing to converge under Newton physics with the RTX + ``depth``, ``albedo``, and ``simple_shading`` AOV observations. These AOVs bypass DLSS temporal + accumulation, so the observation carried no temporal cue for the policy to infer velocity from + (Newton's symplectic integrator has no implicit damping). The ``frame_stack`` default resolver + now enables 2-frame stacking for these Newton + RTX AOVs, matching the existing Newton + Warp + behavior; Newton + RTX ``rgb`` keeps single-frame observations as DLSS already supplies the cue. + The resolver reads backend capability classmethods + (:meth:`~isaaclab.physics.physics_manager.PhysicsManager.provides_implicit_damping`, + :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.provides_temporal_camera_data`) resolved + from the configs, instead of hard-coding backend types in the task. + + 8.0.4 (2026-06-23) ~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_camera_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_camera_env_cfg.py index 9811bfa8526e..55066df4e8d6 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_camera_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_camera_env_cfg.py @@ -134,7 +134,10 @@ def validate_config(self): "Choose a compatible preset, e.g. presets=newton_renderer,rgb." ) - if set(self.tiled_camera.data_types) == {"depth"} and self.feature_extractor.enabled: + non_depth_data_types = set(self.tiled_camera.data_types).difference( + {"depth", "distance_to_image_plane", "distance_to_camera"} + ) + if self.tiled_camera.data_types and not non_depth_data_types and self.feature_extractor.enabled: raise ValueError( "Depth-only camera data type is intended for benchmarking only. " "The keypoint-regression CNN cannot be meaningfully trained from depth alone. " diff --git a/source/isaaclab_tasks/pyproject.toml b/source/isaaclab_tasks/pyproject.toml index 988ef4966925..00bf52e4cf6c 100644 --- a/source/isaaclab_tasks/pyproject.toml +++ b/source/isaaclab_tasks/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "isaaclab_tasks" -version = "8.0.4" +version = "8.0.5" description = "Extension containing suite of environments for robot learning." license = {text = "BSD-3-Clause"} authors = [{name = "Isaac Lab Project Developers"}] diff --git a/source/isaaclab_tasks/test/conftest.py b/source/isaaclab_tasks/test/conftest.py index 4cc0cca45509..b37173affaa8 100644 --- a/source/isaaclab_tasks/test/conftest.py +++ b/source/isaaclab_tasks/test/conftest.py @@ -13,4 +13,12 @@ import os import sys +import pytest + sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + + +@pytest.fixture() +def enable_scene_partition(monkeypatch): + """Set ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` for the duration of one test.""" + monkeypatch.setenv("ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION", "1") diff --git a/source/isaaclab_tasks/test/core/test_rendering_cartpole.py b/source/isaaclab_tasks/test/core/test_rendering_cartpole.py index 6f10a80a1d4b..5ac49d76df33 100644 --- a/source/isaaclab_tasks/test/core/test_rendering_cartpole.py +++ b/source/isaaclab_tasks/test/core/test_rendering_cartpole.py @@ -32,6 +32,6 @@ @pytest.mark.parametrize("physics_backend,renderer,data_type", PHYSICS_RENDERER_AOV_COMBINATIONS) -def test_rendering_cartpole(physics_backend, renderer, data_type): +def test_rendering_cartpole(physics_backend, renderer, data_type, enable_scene_partition): """Test cartpole environment rendering correctness.""" rendering_test_cartpole(physics_backend, renderer, data_type, _COMPARISON_SCORES) diff --git a/source/isaaclab_tasks/test/core/test_rendering_registered_tasks.py b/source/isaaclab_tasks/test/core/test_rendering_registered_tasks.py index e66538c46c1c..fd2f7535a7da 100644 --- a/source/isaaclab_tasks/test/core/test_rendering_registered_tasks.py +++ b/source/isaaclab_tasks/test/core/test_rendering_registered_tasks.py @@ -86,7 +86,7 @@ def _collect_camera_outputs(env: object) -> dict[str, dict[str, torch.Tensor]]: @pytest.mark.parametrize("task_id, presets, env_name", _RENDER_CORRECTNESS_TASK_IDS) -def test_rendering_registered_tasks(task_id: str, presets: str | None, env_name: str): +def test_rendering_registered_tasks(task_id: str, presets: str | None, env_name: str, enable_scene_partition): """Test registered tasks rendering correctness.""" env = None diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/newton-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/cartpole/newton-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..0a26486d7f85 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/newton-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8929af0b155ac73e4dd74dd70dbc502fb78bd962248e5c46f88972a0a7e3e80e +size 538 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/newton-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/cartpole/newton-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..0387686a7a78 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/newton-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea4e6ba2251666e4df0c937fbd123489f2a06939bda9e674d5f84eb5c8831f7d +size 422 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/newton-ovrtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/cartpole/newton-ovrtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..0a26486d7f85 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/newton-ovrtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8929af0b155ac73e4dd74dd70dbc502fb78bd962248e5c46f88972a0a7e3e80e +size 538 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/newton-ovrtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/cartpole/newton-ovrtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..0387686a7a78 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/newton-ovrtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea4e6ba2251666e4df0c937fbd123489f2a06939bda9e674d5f84eb5c8831f7d +size 422 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/ovphysx-ovrtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/cartpole/ovphysx-ovrtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..0a26486d7f85 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/ovphysx-ovrtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8929af0b155ac73e4dd74dd70dbc502fb78bd962248e5c46f88972a0a7e3e80e +size 538 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/ovphysx-ovrtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/cartpole/ovphysx-ovrtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..0387686a7a78 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/ovphysx-ovrtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea4e6ba2251666e4df0c937fbd123489f2a06939bda9e674d5f84eb5c8831f7d +size 422 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/physx-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/cartpole/physx-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..0a26486d7f85 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/physx-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8929af0b155ac73e4dd74dd70dbc502fb78bd962248e5c46f88972a0a7e3e80e +size 538 diff --git a/source/isaaclab_tasks/test/golden_images/cartpole/physx-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/cartpole/physx-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..0387686a7a78 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/cartpole/physx-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea4e6ba2251666e4df0c937fbd123489f2a06939bda9e674d5f84eb5c8831f7d +size 422 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..a4626ba44f33 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41ecbb1dbb608dbc9aa4b172fcbff57333a741e36b85ea937930b593eba774c1 +size 588 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..d823d5d96998 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f401da10698c1025957c57b8ca5ee359dab0449a78613941e3d9841df595794 +size 568 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-ovrtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-ovrtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..d823d5d96998 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-ovrtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f401da10698c1025957c57b8ca5ee359dab0449a78613941e3d9841df595794 +size 568 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-ovrtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-ovrtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..d823d5d96998 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/newton-ovrtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f401da10698c1025957c57b8ca5ee359dab0449a78613941e3d9841df595794 +size 568 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/physx-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/physx-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..a4626ba44f33 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/physx-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41ecbb1dbb608dbc9aa4b172fcbff57333a741e36b85ea937930b593eba774c1 +size 588 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/physx-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/physx-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..d823d5d96998 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_hetero/physx-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f401da10698c1025957c57b8ca5ee359dab0449a78613941e3d9841df595794 +size 568 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..d87fea10d447 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:084f049a7b700ea75716f77e0c80e307c38f414b5da68be34ebad3c1ebe453a9 +size 551 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..bf4b0e0290dd --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c003b10810539f538464992860c74ee3bf531b8b4e9b6e0ebe84041d42dba643 +size 532 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-ovrtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-ovrtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..bf4b0e0290dd --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-ovrtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c003b10810539f538464992860c74ee3bf531b8b4e9b6e0ebe84041d42dba643 +size 532 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-ovrtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-ovrtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..bf4b0e0290dd --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/newton-ovrtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c003b10810539f538464992860c74ee3bf531b8b4e9b6e0ebe84041d42dba643 +size 532 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/physx-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/physx-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..d87fea10d447 --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/physx-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:084f049a7b700ea75716f77e0c80e307c38f414b5da68be34ebad3c1ebe453a9 +size 551 diff --git a/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/physx-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/physx-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..bf4b0e0290dd --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/dexsuite_kuka_homo/physx-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c003b10810539f538464992860c74ee3bf531b8b4e9b6e0ebe84041d42dba643 +size 532 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..2b472cbaac9e --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b991b49bc8061c5cb0fa33f4f940547c532919179c7c7fa384b8c6c796dfa949 +size 4039 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..3893ecf7729d --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d249747e56b41ada8e507c138979791ef6f558043eb23c9f65d6826220eac5f1 +size 3752 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..2b472cbaac9e --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b991b49bc8061c5cb0fa33f4f940547c532919179c7c7fa384b8c6c796dfa949 +size 4039 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..3893ecf7729d --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d249747e56b41ada8e507c138979791ef6f558043eb23c9f65d6826220eac5f1 +size 3752 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-distance_to_camera.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-distance_to_camera.png new file mode 100644 index 000000000000..0987d3f567ea --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-distance_to_camera.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ace1d37f1fa54bd692808ead80ef19470aa3da2efd4c43d7ef1f3ed1b3155bf7 +size 4025 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-distance_to_image_plane.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-distance_to_image_plane.png new file mode 100644 index 000000000000..a38beb8f053f --- /dev/null +++ b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-distance_to_image_plane.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ddd7a52ad1de3f636d29d53bb156d04ac222d1318fc9574617712b53d796508 +size 3681 diff --git a/source/isaaclab_tasks/test/rendering_test_utils.py b/source/isaaclab_tasks/test/rendering_test_utils.py index 2e35bc1f0d54..6fd98dbbd9c9 100644 --- a/source/isaaclab_tasks/test/rendering_test_utils.py +++ b/source/isaaclab_tasks/test/rendering_test_utils.py @@ -83,6 +83,8 @@ "simple_shading_full_mdl", "semantic_segmentation", "depth", + "distance_to_camera", + "distance_to_image_plane", ) @@ -621,12 +623,27 @@ def rendering_test_shadow_hand( if physics_backend == "ovphysx": pytest.skip("ovphysx is not supported yet.") + from isaaclab.utils.configclass import configclass + from isaaclab_tasks.core.reorient.config.shadow_hand.shadow_hand_camera_env import ShadowHandCameraEnv - from isaaclab_tasks.core.reorient.config.shadow_hand.shadow_hand_camera_env_cfg import ShadowHandCameraEnvCfg + from isaaclab_tasks.core.reorient.config.shadow_hand.shadow_hand_camera_env_cfg import ( + ShadowHandCameraEnvCfg, + ShadowHandTiledCameraCfg, + _ShadowHandBaseTiledCameraCfg, + ) + + @configclass + class _ShadowHandTiledCameraTestCfg(ShadowHandTiledCameraCfg): + distance_to_camera = _ShadowHandBaseTiledCameraCfg(data_types=["distance_to_camera"]) + distance_to_image_plane = _ShadowHandBaseTiledCameraCfg(data_types=["distance_to_image_plane"]) + + @configclass + class _ShadowHandCameraTestEnvCfg(ShadowHandCameraEnvCfg): + tiled_camera = _ShadowHandTiledCameraTestCfg() override_args = [f"presets={_physics_preset_name(physics_backend)},{renderer},{data_type}"] - env_cfg = ShadowHandCameraEnvCfg() + env_cfg = _ShadowHandCameraTestEnvCfg() env_cfg = _apply_overrides_to_env_cfg(env_cfg, override_args) env_cfg.scene.num_envs = 4 @@ -634,7 +651,7 @@ def rendering_test_shadow_hand( if renderer == "ovrtx_renderer": _redirect_ovrtx_renderer_log_to_stdout(env_cfg) - if data_type == "depth": + if data_type in {"depth", "distance_to_camera", "distance_to_image_plane"}: # Disable CNN forward pass as it cannot be meaningfully trained from depth alone and will raise a ValueError. env_cfg.feature_extractor.enabled = False @@ -667,10 +684,28 @@ def rendering_test_cartpole( data_type: str, comparison_scores: list[dict], ) -> None: + from isaaclab.utils.configclass import configclass + from isaaclab_tasks.core.cartpole.cartpole_direct_camera_env import CartpoleCameraEnv - from isaaclab_tasks.core.cartpole.cartpole_direct_camera_env_cfg import CartpoleCameraEnvCfg + from isaaclab_tasks.core.cartpole.cartpole_direct_camera_env_cfg import CartpoleCameraEnvCfg, CartpoleTiledCameraCfg + + @configclass + class _CartpoleTiledCameraTestCfg(CartpoleTiledCameraCfg): + distance_to_camera = CartpoleTiledCameraCfg.BaseCartpoleTiledCameraCfg(data_types=["distance_to_camera"]) + distance_to_image_plane = CartpoleTiledCameraCfg.BaseCartpoleTiledCameraCfg( + data_types=["distance_to_image_plane"] + ) + + @configclass + class _CartpoleCameraTestEnvCfg(CartpoleCameraEnvCfg): + distance_to_camera = CartpoleCameraEnvCfg.BaseCartpoleCameraEnvCfg( + observation_space=[1, 100, 100], tiled_camera=_CartpoleTiledCameraTestCfg() + ) + distance_to_image_plane = CartpoleCameraEnvCfg.BaseCartpoleCameraEnvCfg( + observation_space=[1, 100, 100], tiled_camera=_CartpoleTiledCameraTestCfg() + ) - env_cfg = CartpoleCameraEnvCfg() + env_cfg = _CartpoleCameraTestEnvCfg() env_cfg = _apply_overrides_to_env_cfg( env_cfg, [f"presets={_physics_preset_name(physics_backend)},{renderer},{data_type}"] ) @@ -713,11 +748,48 @@ def rendering_test_dexsuite_kuka( pytest.skip("ovphysx is not supported yet.") from isaaclab.envs import ManagerBasedRLEnv + from isaaclab.sensors import CameraCfg + from isaaclab.utils.configclass import configclass + from isaaclab_tasks.core.dexsuite.config.kuka_allegro.camera_cfg import ( + BASE_CAMERA_CFG, + BaseTiledCameraCfg, + SingleCameraObservationsCfg, + ) from isaaclab_tasks.core.dexsuite.config.kuka_allegro.dexsuite_kuka_allegro_camera_env_cfg import ( + _SCENE_KWARGS, DexsuiteKukaAllegroLiftCameraEnvCfg, + SingleCameraSceneCfg, + ) + from isaaclab_tasks.core.dexsuite.config.kuka_allegro.dexsuite_kuka_allegro_env_cfg import ( + DexsuiteKukaAllegroLiftEnvCfg, ) + @configclass + class _DexsuiteBaseTiledCameraTestCfg(BaseTiledCameraCfg): + distance_to_camera64 = BASE_CAMERA_CFG.replace(data_types=["distance_to_camera"], width=64, height=64) + distance_to_camera128 = BASE_CAMERA_CFG.replace(data_types=["distance_to_camera"], width=128, height=128) + distance_to_camera256 = BASE_CAMERA_CFG.replace(data_types=["distance_to_camera"], width=256, height=256) + distance_to_image_plane64 = BASE_CAMERA_CFG.replace(data_types=["distance_to_image_plane"], width=64, height=64) + distance_to_image_plane128 = BASE_CAMERA_CFG.replace( + data_types=["distance_to_image_plane"], width=128, height=128 + ) + distance_to_image_plane256 = BASE_CAMERA_CFG.replace( + data_types=["distance_to_image_plane"], width=256, height=256 + ) + + @configclass + class _DexsuiteSingleCameraTestSceneCfg(SingleCameraSceneCfg): + base_camera: CameraCfg = _DexsuiteBaseTiledCameraTestCfg() + + @configclass + class _DexsuiteKukaAllegroLiftCameraTestEnvCfg(DexsuiteKukaAllegroLiftCameraEnvCfg): + single_camera = DexsuiteKukaAllegroLiftEnvCfg( + scene=_DexsuiteSingleCameraTestSceneCfg(**_SCENE_KWARGS), + observations=SingleCameraObservationsCfg(), + ) + default = single_camera + override_arg = f"presets={_physics_preset_name(physics_backend)},{renderer},{data_type}64,single_camera" # The default setup uses heterogeneous environments with multiple asset spawner to place random objects. @@ -725,7 +797,7 @@ def rendering_test_dexsuite_kuka( if setup_homogeneous_envs: override_arg += ",cube" - env_cfg = DexsuiteKukaAllegroLiftCameraEnvCfg() + env_cfg = _DexsuiteKukaAllegroLiftCameraTestEnvCfg() env_cfg = _apply_overrides_to_env_cfg(env_cfg, [override_arg]) env_cfg.scene.num_envs = 4 diff --git a/source/isaaclab_visualizers/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst b/source/isaaclab_visualizers/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst new file mode 100644 index 000000000000..664c13b13b67 --- /dev/null +++ b/source/isaaclab_visualizers/changelog.d/isaac-rtx-per-env-scene-partition-env-var.rst @@ -0,0 +1,7 @@ +Changed +^^^^^^^ + +* Changed :class:`~isaaclab_visualizers.kit.KitVisualizer` to skip authoring the + ``omni:scenePartition`` attribute on the viewport camera by default. Set + ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1`` to re-enable per-environment + scene partitioning for the Kit viewport camera. diff --git a/source/isaaclab_visualizers/config/extension.toml b/source/isaaclab_visualizers/config/extension.toml index e02c29a67cad..4fe46a909a09 100644 --- a/source/isaaclab_visualizers/config/extension.toml +++ b/source/isaaclab_visualizers/config/extension.toml @@ -1,7 +1,7 @@ [package] # Semantic Versioning is used: https://semver.org/ -version = "1.0.1" +version = "1.0.2" # Description category = "isaaclab" diff --git a/source/isaaclab_visualizers/docs/CHANGELOG.rst b/source/isaaclab_visualizers/docs/CHANGELOG.rst index cd4c8d8a6410..a68605282274 100644 --- a/source/isaaclab_visualizers/docs/CHANGELOG.rst +++ b/source/isaaclab_visualizers/docs/CHANGELOG.rst @@ -1,6 +1,18 @@ Changelog --------- +1.0.2 (2026-06-24) +~~~~~~~~~~~~~~~~~~ + +Fixed +^^^^^ + +* Fixed the visualizer extras' ``newton[sim]`` dependency pin to use Newton + commit ``79e95bf5571d70a0a46c8eaedc80644531d27368``, including the + RenderContext triangle-mesh construction fix from `newton-physics/newton#3199 + `_. + + 1.0.1 (2026-06-14) ~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer.py b/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer.py index 1f8bec44fbc4..4aa0d40892d0 100644 --- a/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer.py +++ b/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer.py @@ -30,6 +30,7 @@ resolve_tiled_env_indices, ) from isaaclab.utils.math import create_rotation_matrix_from_view, quat_from_matrix +from isaaclab.utils.renderers import isaac_rtx_per_env_scene_partition_enabled from isaaclab.visualizers.base_visualizer import BaseVisualizer from isaaclab_visualizers.newton_adapter import resolve_visible_env_indices @@ -513,9 +514,25 @@ def _apply_viewport_camera_scene_partition(self, usd_stage: Usd.Stage, num_envs: ``omni:scenePartition`` token. Interactive viewport cameras live outside ``/World/envs`` and are created by Kit, so they do not inherit the env-root primvar authored by :class:`~isaaclab.scene.InteractiveScene`. + + This method is a no-op unless ``ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1``, + matching the opt-in behaviour of + :meth:`~isaaclab_physx.renderers.IsaacRtxRenderer.prepare_stage`. """ + + if not isaac_rtx_per_env_scene_partition_enabled(): + return + if num_envs <= 0 or self._controlled_camera_path is None: return + + logger.debug( + "[KitVisualizer] Per-environment Isaac RTX scene partitioning is enabled" + " (ISAAC_LAB_ENABLE_ISAAC_RTX_PER_ENV_SCENE_PARTITION=1)." + " Authoring omni:scenePartition attribute onto viewport camera '%s'.", + self._controlled_camera_path, + ) + env_id = self._resolved_visible_env_ids[0] if self._resolved_visible_env_ids else 0 camera_prim = usd_stage.GetPrimAtPath(self._controlled_camera_path) if not camera_prim.IsValid() or not camera_prim.IsA(UsdGeom.Camera): diff --git a/source/isaaclab_visualizers/pyproject.toml b/source/isaaclab_visualizers/pyproject.toml index 9b0aeefcf3e7..970de1d79423 100644 --- a/source/isaaclab_visualizers/pyproject.toml +++ b/source/isaaclab_visualizers/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "isaaclab-visualizers" -version = "1.0.1" +version = "1.0.2" description = "Visualizer backends for Isaac Lab (Kit, Newton, Rerun, Viser)." license = {text = "BSD-3-Clause"} authors = [{name = "Isaac Lab Project Developers"}] @@ -29,24 +29,24 @@ Repository = "https://github.com/isaac-sim/IsaacLab" kit = [] newton = [ "warp-lang", - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", "PyOpenGL-accelerate", "pyglet>=2.1.6,<3", "imgui-bundle>=1.92.5", "typing-extensions>=4.15.0", ] rerun = [ - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", "rerun-sdk>=0.29.0", "pyarrow==22.0.0", ] viser = [ - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", "viser>=1.0.16", ] all = [ "imgui-bundle>=1.92.5", - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", "PyOpenGL-accelerate", "pyglet>=2.1.6,<3", # Match rerun-sdk's supported Arrow stack and avoid resolver drift across environments. diff --git a/tools/wheel_builder/res/python_packages.toml b/tools/wheel_builder/res/python_packages.toml index db104ce02f0c..72926c0a93d3 100644 --- a/tools/wheel_builder/res/python_packages.toml +++ b/tools/wheel_builder/res/python_packages.toml @@ -88,7 +88,7 @@ pyproject.optional-dependencies.all = [ # ================================================================================ { "newton" = [ "warp-lang==1.14.0", - "newton[sim] @ git+https://github.com/newton-physics/newton.git@811968bfb7cc7ff4e37b9260a2ba56930a3e605e", + "newton[sim] @ git+https://github.com/newton-physics/newton.git@79e95bf5571d70a0a46c8eaedc80644531d27368", "PyOpenGL-accelerate==3.1.10" ] }, # ================================================================================