Skip to content

Commit 53678cd

Browse files
committed
Refactor schema cfgs to separate solver-common from PhysX-specific fields
Split RigidBodyPropertiesCfg and JointDrivePropertiesCfg into solver-common base classes and PhysX-specific subclasses (PhysxRigidBodyPropertiesCfg, PhysxJointDrivePropertiesCfg). Each solver-specific cfg declares _usd_applied_schema, _usd_namespace, and _usd_attr_name_map metadata so that modify_rigid_body_properties and modify_joint_drive_properties write attributes generically without backend-specific branching. This prepares the schema layer for adding additional solver backends (e.g. MuJoCo) without modifying the modify functions.
1 parent caab0de commit 53678cd

97 files changed

Lines changed: 369 additions & 252 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

source/isaaclab/config/extension.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
# Note: Semantic Versioning is used: https://semver.org/
4-
version = "4.6.1"
4+
version = "4.6.2"
55

66
# Description
77
title = "Isaac Lab framework for Robot Learning"

source/isaaclab/docs/CHANGELOG.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
11
Changelog
22
---------
33

4+
4.6.2 (2026-04-14)
5+
~~~~~~~~~~~~~~~~~~~
6+
7+
Changed
8+
^^^^^^^
9+
10+
* Refactored :class:`~isaaclab.sim.schemas.RigidBodyPropertiesCfg` to contain only
11+
solver-common properties (``rigid_body_enabled``, ``kinematic_enabled``). PhysX-specific
12+
properties are now in :class:`~isaaclab.sim.schemas.PhysxRigidBodyPropertiesCfg`.
13+
14+
- **Migration:** Replace ``RigidBodyPropertiesCfg(disable_gravity=True, ...)`` with
15+
``PhysxRigidBodyPropertiesCfg(disable_gravity=True, ...)``.
16+
17+
* Refactored :class:`~isaaclab.sim.schemas.JointDrivePropertiesCfg` to contain only
18+
solver-common properties (``drive_type``, ``max_effort``, ``stiffness``, ``damping``,
19+
``ensure_drives_exist``). The PhysX-specific ``max_velocity`` field is now in
20+
:class:`~isaaclab.sim.schemas.PhysxJointDrivePropertiesCfg`.
21+
22+
- **Migration:** Replace ``JointDrivePropertiesCfg(max_velocity=5.0, ...)`` with
23+
``PhysxJointDrivePropertiesCfg(max_velocity=5.0, ...)``.
24+
25+
* Refactored :meth:`~isaaclab.sim.schemas.modify_rigid_body_properties` and
26+
:meth:`~isaaclab.sim.schemas.modify_joint_drive_properties` to use class-level
27+
metadata (``_usd_applied_schema``, ``_usd_namespace``) from the cfg for writing
28+
solver-specific attributes, eliminating backend-specific branching.
29+
30+
431
4.6.1 (2026-04-14)
532
~~~~~~~~~~~~~~~~~~
633

source/isaaclab/isaaclab/sim/__init__.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ __all__ = [
4646
"JointDrivePropertiesCfg",
4747
"MassPropertiesCfg",
4848
"MeshCollisionPropertiesCfg",
49+
"PhysxJointDrivePropertiesCfg",
50+
"PhysxRigidBodyPropertiesCfg",
4951
"RigidBodyPropertiesCfg",
5052
"SDFMeshPropertiesCfg",
5153
"SpatialTendonPropertiesCfg",
@@ -210,6 +212,8 @@ from .schemas import (
210212
JointDrivePropertiesCfg,
211213
MassPropertiesCfg,
212214
MeshCollisionPropertiesCfg,
215+
PhysxJointDrivePropertiesCfg,
216+
PhysxRigidBodyPropertiesCfg,
213217
RigidBodyPropertiesCfg,
214218
SDFMeshPropertiesCfg,
215219
SpatialTendonPropertiesCfg,

source/isaaclab/isaaclab/sim/schemas/__init__.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ __all__ = [
3434
"JointDrivePropertiesCfg",
3535
"MassPropertiesCfg",
3636
"MeshCollisionPropertiesCfg",
37+
"PhysxJointDrivePropertiesCfg",
38+
"PhysxRigidBodyPropertiesCfg",
3739
"RigidBodyPropertiesCfg",
3840
"SDFMeshPropertiesCfg",
3941
"SpatialTendonPropertiesCfg",
@@ -74,6 +76,8 @@ from .schemas_cfg import (
7476
JointDrivePropertiesCfg,
7577
MassPropertiesCfg,
7678
MeshCollisionPropertiesCfg,
79+
PhysxJointDrivePropertiesCfg,
80+
PhysxRigidBodyPropertiesCfg,
7781
RigidBodyPropertiesCfg,
7882
SDFMeshPropertiesCfg,
7983
SpatialTendonPropertiesCfg,

source/isaaclab/isaaclab/sim/schemas/schemas.py

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,16 @@ def define_rigid_body_properties(
280280
def modify_rigid_body_properties(
281281
prim_path: str, cfg: schemas_cfg.RigidBodyPropertiesCfg, stage: Usd.Stage | None = None
282282
) -> bool:
283-
"""Modify PhysX parameters for a rigid body prim.
283+
"""Modify parameters for a rigid body prim.
284284
285-
A `rigid body`_ is a single body that can be simulated by PhysX. It can be either dynamic or kinematic.
286-
A dynamic body responds to forces and collisions. A `kinematic body`_ can be moved by the user, but does not
287-
respond to forces. They are similar to having static bodies that can be moved around.
285+
A `rigid body`_ is a single body that can be simulated by a physics engine. It can be either dynamic
286+
or kinematic. A dynamic body responds to forces and collisions. A `kinematic body`_ can be moved by
287+
the user, but does not respond to forces. They are similar to having static bodies that can be moved
288+
around.
288289
289-
The schema comprises of attributes that belong to the `RigidBodyAPI`_ and `PhysxRigidBodyAPI`_.
290-
schemas. The latter contains the PhysX parameters for the rigid body.
290+
The function handles solver-common properties from :class:`~schemas_cfg.RigidBodyPropertiesCfg`
291+
(written via the `RigidBodyAPI`_) and, when the cfg is a :class:`~schemas_cfg.PhysxRigidBodyPropertiesCfg`,
292+
also sets PhysX-specific properties (written via the `PhysxRigidBodyAPI`_).
291293
292294
.. note::
293295
This function is decorated with :func:`apply_nested` that sets the properties to all the prims
@@ -300,7 +302,9 @@ def modify_rigid_body_properties(
300302
301303
Args:
302304
prim_path: The prim path to the rigid body.
303-
cfg: The configuration for the rigid body.
305+
cfg: The configuration for the rigid body. Can be
306+
:class:`~schemas_cfg.RigidBodyPropertiesCfg` for solver-common properties or
307+
:class:`~schemas_cfg.PhysxRigidBodyPropertiesCfg` for PhysX-specific properties.
304308
stage: The stage where to find the prim. Defaults to None, in which case the
305309
current stage is used.
306310
@@ -318,21 +322,26 @@ def modify_rigid_body_properties(
318322
return False
319323
# retrieve the USD rigid-body api
320324
usd_rigid_body_api = UsdPhysics.RigidBodyAPI(rigid_body_prim)
321-
# ensure PhysX rigid body API is applied
322-
applied_schemas = rigid_body_prim.GetAppliedSchemas()
323-
if "PhysxRigidBodyAPI" not in applied_schemas:
324-
rigid_body_prim.AddAppliedSchema("PhysxRigidBodyAPI")
325325

326-
# convert to dict
327-
cfg = cfg.to_dict()
328-
# set into USD API
326+
# read solver-specific metadata from the cfg instance
327+
namespace = getattr(cfg, "_usd_namespace", None)
328+
applied_schema = getattr(cfg, "_usd_applied_schema", None)
329+
330+
# convert to dict, filtering out class metadata (underscore-prefixed keys)
331+
cfg_dict = {k: v for k, v in cfg.to_dict().items() if not k.startswith("_")}
332+
333+
# set into USD API (solver-common properties)
329334
for attr_name in ["rigid_body_enabled", "kinematic_enabled"]:
330-
value = cfg.pop(attr_name, None)
335+
value = cfg_dict.pop(attr_name, None)
331336
safe_set_attribute_on_usd_schema(usd_rigid_body_api, attr_name, value, camel_case=True)
332-
# set into PhysX API (prim attributes under physxRigidBody:*)
333-
for attr_name, value in cfg.items():
337+
338+
# set solver-specific properties using class metadata (namespace + applied schema)
339+
if applied_schema:
340+
if applied_schema not in rigid_body_prim.GetAppliedSchemas():
341+
rigid_body_prim.AddAppliedSchema(applied_schema)
342+
for attr_name, value in cfg_dict.items():
334343
safe_set_attribute_on_usd_prim(
335-
rigid_body_prim, f"physxRigidBody:{to_camel_case(attr_name, 'cC')}", value, camel_case=False
344+
rigid_body_prim, f"{namespace}:{to_camel_case(attr_name, 'cC')}", value, camel_case=False
336345
)
337346
# success
338347
return True
@@ -615,15 +624,16 @@ def activate_contact_sensors(prim_path: str, threshold: float = 0.0, stage: Usd.
615624
def modify_joint_drive_properties(
616625
prim_path: str, cfg: schemas_cfg.JointDrivePropertiesCfg, stage: Usd.Stage | None = None
617626
) -> bool:
618-
"""Modify PhysX parameters for a joint prim.
627+
"""Modify parameters for a joint prim.
619628
620629
This function checks if the input prim is a prismatic or revolute joint and applies the joint drive schema
621630
on it. If the joint is a tendon (i.e., it has the `PhysxTendonAxisAPI`_ schema applied on it), then the joint
622631
drive schema is not applied.
623632
624-
Based on the configuration, this method modifies the properties of the joint drive. These properties are
625-
based on the `UsdPhysics.DriveAPI`_ schema. For more information on the properties, please refer to the
626-
official documentation.
633+
The function handles solver-common properties from :class:`~schemas_cfg.JointDrivePropertiesCfg`
634+
(written via the `UsdPhysics.DriveAPI`_) and, when the cfg is a
635+
:class:`~schemas_cfg.PhysxJointDrivePropertiesCfg`, also sets PhysX-specific properties
636+
(written via the `PhysxJointAPI`_).
627637
628638
.. caution::
629639
@@ -633,10 +643,13 @@ def modify_joint_drive_properties(
633643
634644
.. _UsdPhysics.DriveAPI: https://openusd.org/dev/api/class_usd_physics_drive_a_p_i.html
635645
.. _PhysxTendonAxisAPI: https://docs.omniverse.nvidia.com/kit/docs/omni_usd_schema_physics/104.2/class_physx_schema_physx_tendon_axis_a_p_i.html
646+
.. _PhysxJointAPI: https://docs.omniverse.nvidia.com/kit/docs/omni_usd_schema_physics/104.2/class_physx_schema_physx_joint_a_p_i.html
636647
637648
Args:
638649
prim_path: The prim path where to apply the joint drive schema.
639-
cfg: The configuration for the joint drive.
650+
cfg: The configuration for the joint drive. Can be
651+
:class:`~schemas_cfg.JointDrivePropertiesCfg` for solver-common properties or
652+
:class:`~schemas_cfg.PhysxJointDrivePropertiesCfg` for PhysX-specific properties.
640653
stage: The stage where to find the prim. Defaults to None, in which case the
641654
current stage is used.
642655
@@ -672,52 +685,55 @@ def modify_joint_drive_properties(
672685
usd_drive_api = UsdPhysics.DriveAPI(prim, drive_api_name)
673686
if not usd_drive_api:
674687
usd_drive_api = UsdPhysics.DriveAPI.Apply(prim, drive_api_name)
675-
# ensure PhysX joint API is applied
676-
if "PhysxJointAPI" not in applied_schemas_str:
677-
prim.AddAppliedSchema("PhysxJointAPI")
678688

679-
# mapping from configuration name to USD attribute name
689+
# read solver-specific metadata from the cfg instance
690+
namespace = getattr(cfg, "_usd_namespace", None)
691+
applied_schema = getattr(cfg, "_usd_applied_schema", None)
692+
attr_name_map = getattr(cfg, "_usd_attr_name_map", {})
693+
694+
# mapping from configuration name to USD attribute name (for solver-common fields)
680695
cfg_to_usd_map = {
681-
"max_velocity": "max_joint_velocity",
682696
"max_effort": "max_force",
683697
"drive_type": "type",
684698
}
685-
# convert to dict
686-
cfg = cfg.to_dict()
699+
# convert to dict, filtering out class metadata (underscore-prefixed keys)
700+
cfg_dict = {k: v for k, v in cfg.to_dict().items() if not k.startswith("_")}
687701

688702
# ensure_drives_exist: if both stiffness and damping are zero on the authored drive,
689703
# set a minimal stiffness so that backends like Newton recognise the drive as active.
690-
ensure_drives = cfg.pop("ensure_drives_exist", False)
691-
if ensure_drives and cfg["stiffness"] is None and cfg["damping"] is None:
704+
ensure_drives = cfg_dict.pop("ensure_drives_exist", False)
705+
if ensure_drives and cfg_dict["stiffness"] is None and cfg_dict["damping"] is None:
692706
# read the current values from the drive
693707
cur_stiffness = usd_drive_api.GetStiffnessAttr().Get()
694708
cur_damping = usd_drive_api.GetDampingAttr().Get()
695709
if (cur_stiffness is None or cur_stiffness == 0.0) and (cur_damping is None or cur_damping == 0.0):
696-
cfg["stiffness"] = 1e-3
710+
cfg_dict["stiffness"] = 1e-3
697711

698712
# check if linear drive
699713
is_linear_drive = prim.IsA(UsdPhysics.PrismaticJoint)
700714
# convert values for angular drives from radians to degrees units
701715
if not is_linear_drive:
702-
if cfg["max_velocity"] is not None:
716+
if cfg_dict.get("max_velocity") is not None:
703717
# rad / s --> deg / s
704-
cfg["max_velocity"] = cfg["max_velocity"] * 180.0 / math.pi
705-
if cfg["stiffness"] is not None:
718+
cfg_dict["max_velocity"] = cfg_dict["max_velocity"] * 180.0 / math.pi
719+
if cfg_dict["stiffness"] is not None:
706720
# N-m/rad --> N-m/deg
707-
cfg["stiffness"] = cfg["stiffness"] * math.pi / 180.0
708-
if cfg["damping"] is not None:
721+
cfg_dict["stiffness"] = cfg_dict["stiffness"] * math.pi / 180.0
722+
if cfg_dict["damping"] is not None:
709723
# N-m-s/rad --> N-m-s/deg
710-
cfg["damping"] = cfg["damping"] * math.pi / 180.0
711-
712-
# set into PhysX API (prim attributes under physxJoint:*)
713-
for attr_name in ["max_velocity"]:
714-
value = cfg.pop(attr_name, None)
715-
usd_attr_name = cfg_to_usd_map[attr_name]
716-
safe_set_attribute_on_usd_prim(
717-
prim, f"physxJoint:{to_camel_case(usd_attr_name, 'cC')}", value, camel_case=False
718-
)
719-
# set into USD API
720-
for attr_name, attr_value in cfg.items():
724+
cfg_dict["damping"] = cfg_dict["damping"] * math.pi / 180.0
725+
726+
# set solver-specific properties using class metadata (namespace + applied schema + attr name map)
727+
if applied_schema:
728+
if applied_schema not in applied_schemas_str:
729+
prim.AddAppliedSchema(applied_schema)
730+
for attr_name in list(attr_name_map):
731+
value = cfg_dict.pop(attr_name, None)
732+
usd_attr_name = attr_name_map[attr_name]
733+
safe_set_attribute_on_usd_prim(prim, f"{namespace}:{usd_attr_name}", value, camel_case=False)
734+
735+
# set into USD API (solver-common properties)
736+
for attr_name, attr_value in cfg_dict.items():
721737
attr_name = cfg_to_usd_map.get(attr_name, attr_name)
722738
safe_set_attribute_on_usd_schema(usd_drive_api, attr_name, attr_value, camel_case=True)
723739

source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,18 @@ class ArticulationRootPropertiesCfg:
5555

5656
@configclass
5757
class RigidBodyPropertiesCfg:
58-
"""Properties to apply to a rigid body.
58+
"""Solver-common properties to apply to a rigid body.
59+
60+
Contains only properties from the `UsdPhysics.RigidBodyAPI`_ that are common across all
61+
simulation backends. For PhysX-specific properties, use :class:`PhysxRigidBodyPropertiesCfg`.
5962
6063
See :meth:`modify_rigid_body_properties` for more information.
6164
6265
.. note::
6366
If the values are None, they are not modified. This is useful when you want to set only a subset of
6467
the properties and leave the rest as-is.
68+
69+
.. _UsdPhysics.RigidBodyAPI: https://openusd.org/dev/api/class_usd_physics_rigid_body_a_p_i.html
6570
"""
6671

6772
rigid_body_enabled: bool | None = None
@@ -76,6 +81,28 @@ class RigidBodyPropertiesCfg:
7681
For more information on kinematic bodies, please refer to the `documentation <https://openusd.org/release/wp_rigid_body_physics.html#kinematic-bodies>`_.
7782
"""
7883

84+
85+
@configclass
86+
class PhysxRigidBodyPropertiesCfg(RigidBodyPropertiesCfg):
87+
"""PhysX-specific rigid body properties.
88+
89+
Extends :class:`RigidBodyPropertiesCfg` with properties from the `PhysxRigidBodyAPI`_ schema.
90+
91+
See :meth:`modify_rigid_body_properties` for more information.
92+
93+
.. note::
94+
If the values are None, they are not modified. This is useful when you want to set only a subset of
95+
the properties and leave the rest as-is.
96+
97+
.. _PhysxRigidBodyAPI: https://docs.omniverse.nvidia.com/kit/docs/omni_usd_schema_physics/104.2/class_physx_schema_physx_rigid_body_a_p_i.html
98+
"""
99+
100+
# -- Class metadata (not dataclass fields) --
101+
# USD schema to apply on the prim before writing solver-specific attributes.
102+
_usd_applied_schema = "PhysxRigidBodyAPI"
103+
# Prim attribute namespace for solver-specific fields.
104+
_usd_namespace = "physxRigidBody"
105+
79106
disable_gravity: bool | None = None
80107
"""Disable gravity for the actor."""
81108

@@ -185,13 +212,18 @@ class MassPropertiesCfg:
185212

186213
@configclass
187214
class JointDrivePropertiesCfg:
188-
"""Properties to define the drive mechanism of a joint.
215+
"""Solver-common properties to define the drive mechanism of a joint.
216+
217+
Contains only properties from the `UsdPhysics.DriveAPI`_ that are common across all
218+
simulation backends. For PhysX-specific properties, use :class:`PhysxJointDrivePropertiesCfg`.
189219
190220
See :meth:`modify_joint_drive_properties` for more information.
191221
192222
.. note::
193223
If the values are None, they are not modified. This is useful when you want to set only a subset of
194224
the properties and leave the rest as-is.
225+
226+
.. _UsdPhysics.DriveAPI: https://openusd.org/dev/api/class_usd_physics_drive_a_p_i.html
195227
"""
196228

197229
drive_type: Literal["force", "acceleration"] | None = None
@@ -204,15 +236,6 @@ class JointDrivePropertiesCfg:
204236
max_effort: float | None = None
205237
"""Maximum effort that can be applied to the joint (in kg-m^2/s^2)."""
206238

207-
max_velocity: float | None = None
208-
"""Maximum velocity of the joint.
209-
210-
The unit depends on the joint model:
211-
212-
* For linear joints, the unit is m/s.
213-
* For angular joints, the unit is rad/s.
214-
"""
215-
216239
stiffness: float | None = None
217240
"""Stiffness of the joint drive.
218241
@@ -244,6 +267,39 @@ class JointDrivePropertiesCfg:
244267
"""
245268

246269

270+
@configclass
271+
class PhysxJointDrivePropertiesCfg(JointDrivePropertiesCfg):
272+
"""PhysX-specific joint drive properties.
273+
274+
Extends :class:`JointDrivePropertiesCfg` with properties from the `PhysxJointAPI`_ schema.
275+
276+
See :meth:`modify_joint_drive_properties` for more information.
277+
278+
.. note::
279+
If the values are None, they are not modified. This is useful when you want to set only a subset of
280+
the properties and leave the rest as-is.
281+
282+
.. _PhysxJointAPI: https://docs.omniverse.nvidia.com/kit/docs/omni_usd_schema_physics/104.2/class_physx_schema_physx_joint_a_p_i.html
283+
"""
284+
285+
# -- Class metadata (not dataclass fields) --
286+
# USD schema to apply on the prim before writing solver-specific attributes.
287+
_usd_applied_schema = "PhysxJointAPI"
288+
# Prim attribute namespace for solver-specific fields.
289+
_usd_namespace = "physxJoint"
290+
# Mapping from cfg field names to USD attribute names (already in camelCase).
291+
_usd_attr_name_map = {"max_velocity": "maxJointVelocity"}
292+
293+
max_velocity: float | None = None
294+
"""Maximum velocity of the joint.
295+
296+
The unit depends on the joint model:
297+
298+
* For linear joints, the unit is m/s.
299+
* For angular joints, the unit is rad/s.
300+
"""
301+
302+
247303
@configclass
248304
class FixedTendonPropertiesCfg:
249305
"""Properties to define fixed tendons of an articulation.

0 commit comments

Comments
 (0)