Skip to content

Adding RigidBody USD data classes and writers #5976

Open
vidurv-nvidia wants to merge 10 commits into
isaac-sim:developfrom
vidurv-nvidia:vidurv/schema-frag-framework
Open

Adding RigidBody USD data classes and writers #5976
vidurv-nvidia wants to merge 10 commits into
isaac-sim:developfrom
vidurv-nvidia:vidurv/schema-frag-framework

Conversation

@vidurv-nvidia

@vidurv-nvidia vidurv-nvidia commented Jun 4, 2026

Copy link
Copy Markdown

Description

Summary (PR 1 of 2 — additive, no behavior change)

Introduces single-namespace schema fragments so a prim can carry rigid-body properties from multiple USD namespaces at once (physics:, physxRigidBody:, mjc:), with core naming no backend. Purely additive — existing cfgs and the deprecated RigidBodyPropertiesCfg class are untouched.

  • core: SchemaFragment, RigidBodyFragment, UsdPhysicsRigidBodyCfg; apply_namespaced (generic per-fragment writer) and apply_rigid_body_properties (applies a fragment list with UsdPhysics.RigidBodyAPI as the implicit anchor).
  • spawner: rigid_props accepts a fragment list; legacy single cfgs keep working via a transition bridge (shapes/meshes/from_files/mesh_converter).
  • backends: PhysxRigidBodyCfg (physx), MujocoRigidBodyCfg (newton).
  • new test_schema_fragments.py + exports.

PR 2 (stacked) flips RigidBodyPropertiesCfg to a deprecation factory and migrates all call sites: vidurv-nvidia#4 (review after this lands).

Test Plan

  • test_schema_fragments.py — 7 passed
  • pre-commit clean · ./isaaclab.sh -d docs build clean
  • CI

First slice of the staged physics schema-cfg refactor (collision / mass / joint-drive / … follow later). Draft for review of the fragment API shape.

Type of change

  • New feature (non-breaking change which adds functionality)

Screenshots

N/A — no user-facing visual changes.

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks (ruff + ruff-format) on the changed files
  • I have made corresponding changes to the documentation (the public API reference is auto-generated via ./isaaclab.sh -d; not separately authored)
  • My changes generate no new warnings
  • I have added tests that prove my feature works
  • I have added a changelog fragment under source/<pkg>/changelog.d/ for every touched package
  • I have added my name to CONTRIBUTORS.md

Introduce single-namespace schema "fragments" so a prim can carry
rigid-body properties from multiple USD namespaces at once, while core
names no backend. This change is purely additive: existing cfgs and the
deprecated RigidBodyPropertiesCfg class are untouched.

- core: SchemaFragment base, RigidBodyFragment marker, UsdPhysicsRigidBodyCfg;
  apply_namespaced (generic per-fragment writer) and apply_rigid_body_properties
  (applies a fragment list with UsdPhysics.RigidBodyAPI as the implicit anchor).
- spawner rigid_props slot accepts a fragment list; legacy single cfgs keep
  working via a transition bridge in the shapes/meshes/from_files/mesh_converter
  writers.
- isaaclab_physx: add PhysxRigidBodyCfg. isaaclab_newton: add MujocoRigidBodyCfg.
- exports + a new test_schema_fragments.py.

First of a two-PR stack; the migration of call sites and the
RigidBodyPropertiesCfg deprecation follow in a dependent PR.

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔄 Incremental Review Update (commits c61c237...1a809a3)

Changes Since Last Review

The new commits update comments in 4 files:

  • mesh_converter.py
  • from_files.py
  • meshes.py
  • shapes.py

Change Summary: Replaced "transition routing" with "transition shim, remove later" in comments marking the dual-path logic for schema fragments vs legacy configs.

Assessment

LGTM for this increment — these are documentation/comment improvements only:

  • More explicit language ("shim" + "remove later") makes the temporary nature clearer
  • Helps future maintainers understand this code is transitional
  • No functional changes

Previous Review Findings Still Apply

The architectural observations from my initial review remain valid:

  1. The StopIteration risk from bare next() calls in schemas.py still exists
  2. The if not prim.GetPrim().HasAPI(...) truthiness pattern in _apply_to_prim could mask issues
  3. CI changelog job failure (unrelated to this PR)

No new issues introduced by this commit. Ready for merge once CI passes.


🔄 Incremental Review Update (commits 1a809a3...559c57a)

Changes Since Last Review

Type annotation improvements in schemas.py:

  • Added from collections.abc import Iterable import
  • Added type hint to apply_namespaced(): cfg: schemas_cfg.SchemaFragment
  • Added type hint to apply_rigid_body_properties(): fragments: Iterable[schemas_cfg.RigidBodyFragment]

Assessment

LGTM — These are strictly type annotation additions. Improves IDE support and static analysis without any behavioral change. Good housekeeping.

No new issues. Previous findings (bare next(), HasAPI truthiness) remain unchanged in this diff.


Automated incremental review by IsaacLab Review Bot 🤖


🔄 Incremental Review Update (commits 559c57a...8c2b75d)

Changes Since Last Review

The new commits (559c57a8c2b75d) contain no changes to the schema/fragment files that are the focus of this PR. The diff consists entirely of unrelated work merged into the branch:

  • Circular buffer stack_dim mode and performance improvements
  • Image normalization utilities (isaaclab.utils.images, Warp fused kernel)
  • Locomotion task consolidation (ant/humanoid refactoring, Gym ID renames)
  • Template generator improvements and tests
  • Newton version bumps (v1.2.0 → v1.2.1rc2), ls_parallel deprecation
  • OVPhysX version pin, OVRTX error messaging
  • Minor fixes: Fabric logging level, cartpole camera frame-stack perf

Assessment

No impact on the schema fragment code under review — the core PR files (schemas.py, schemas_cfg.py, etc.) are untouched in this increment.

Previous Review Findings Still Apply

  1. The StopIteration risk from bare next() calls in schemas.py still exists
  2. The if not prim.GetPrim().HasAPI(...) truthiness pattern in _apply_to_prim could mask issues

No new issues introduced.


Automated incremental review by IsaacLab Review Bot 🤖


🔄 Incremental Review Update (commits 8c2b75d...2a8b8e7)

Changes Since Last Review

This commit directly addresses all three inline review comments from earlier reviews:

✅ P1: Missing prim validity check — RESOLVED

Both apply_namespaced() and apply_rigid_body_properties() now validate the prim at the given path and raise ValueError if invalid, preventing silent no-ops.

✅ P2: apply_rigid_body_properties always returns True — RESOLVED

The function now aggregates per-fragment return values with success = bool(func(...)) and success, honoring the boolean contract established by modify_* writers.

✅ P2: Fragile func-field exclusion by name — RESOLVED

Introduced _non_usd_fields: ClassVar[frozenset] on SchemaFragment. The apply loop now checks f.name in non_usd_fields (which always includes "func") rather than hardcoding a single name. Subclasses can declare additional non-USD bookkeeping fields explicitly.

New Tests Added

Four targeted tests in test_schema_fragments.py:

  • test_apply_namespaced_raises_on_invalid_prim — validates the ValueError guard
  • test_apply_rigid_body_properties_raises_on_invalid_prim — same for the aggregate applier
  • test_apply_rigid_body_properties_aggregates_fragment_results — verifies False propagation
  • test_apply_namespaced_skips_declared_non_usd_fields — confirms _non_usd_fields opt-out

Assessment

All previous review concerns are addressed. The implementation is clean and well-tested. Minor observations:

  • The non_usd_fields union (getattr(...) | {"func"}) ensures backward compat even if a subclass forgets to inherit the base frozenset — good defensive design.
  • Tests use a custom @configclass subclass to verify the mechanism generically.

No new issues introduced. This PR is ready for merge once CI is green.


Automated incremental review by IsaacLab Review Bot 🤖


🔄 Incremental Review Update (commits 2a8b8e7...fb864c0)

Changes Since Last Review

This commit simplifies the non-USD field handling by removing the _non_usd_fields mechanism introduced in the previous iteration and replacing it with a stricter invariant:

Key Changes:

  1. schemas.py: Removed _non_usd_fields set; the apply loop now only skips func (hardcoded). Added a namespace-presence guard: if _usd_namespace is None, apply_namespaced() raises ValueError immediately — enforcing that every fragment must declare where its fields go.
  2. schemas_cfg.py: Removed _non_usd_fields: ClassVar and its docstring. Added a comprehensive .. important:: docstring explaining the design invariant: all dataclass fields (except func) are USD attributes, and non-USD state belongs on the spawner cfg or as writer kwargs.
  3. test_schema_fragments.py: Replaced test_apply_namespaced_skips_declared_non_usd_fields with test_apply_namespaced_raises_without_namespace — verifying the new ValueError guard fires when _usd_namespace is None.

Assessment

LGTM — this is a good simplification. Instead of providing an opt-out mechanism for non-USD fields (which invites misuse), the framework now forbids them entirely with a clear error message. This is a better design because:

  • Fail-fast: misconfigured fragments are caught immediately at apply time
  • Simpler API: no _non_usd_fields to maintain or remember
  • Clear guidance: the error message tells users where non-USD state should live (spawner cfg or writer kwargs)
  • The func field remains the single hardcoded exception, which is fine since it is framework machinery

Previous Review Findings

  1. StopIteration risk from bare next() — not addressed in this commit (likely outside PR scope)
  2. HasAPI truthiness — unchanged

No new issues introduced. PR remains ready for merge once CI is green.


Automated incremental review by IsaacLab Review Bot 🤖


🔄 Incremental Review Update (commits fb864c0...419e9ef)

Changes Since Last Review

This update is a branch rebase/merge from develop bringing in a large volume of unrelated upstream changes. The diff contains ~80 files spanning:

  • Cloner refactoring: scene.clone_environments() replaced by explicit cloner.ClonePlan.from_env_0() + cloner.replicate() across all direct-workflow envs and templates
  • PhysX replication: physx_replicate.pyreplicate.py with new PhysxReplicateContext class and queue_physx_replication() pattern
  • Task renaming (breaking): Gym IDs drop -v0 suffix (Isaac-Reach-Franka-v0Isaac-Reach-Franka, etc.); lift tasks consolidated under isaaclab_tasks.core.lift
  • Reach MDP removal: isaaclab_tasks.core.reach.mdp deleted; reward terms moved to isaaclab.envs.mdp
  • Deformable soft-lift consolidation: lift_franka_soft merged into lift.config.franka_soft; shared deformable MDP terms moved to isaaclab_tasks.core.lift.mdp
  • Preset CLI simplification: fold_preset_tokens() removed; typed selectors (physics=/renderer=) now parsed directly by Hydra resolver with type validation
  • Visualizer improvements: Newton contact rendering fallback, infinite plane expansion, Viser grid caching, set_camera_view() API
  • Dependency updates: newton[sim] pinned to 1.2.1 (from git RC), isaaclab_ppisp made optional, isaaclab_physx version bump to 1.1.4
  • ISP import fix: isaaclab_ppisp import now wrapped in try/except with descriptive error
  • skrl JAX fix: preloads jax.experimental.multihost_utils submodule
  • AutoMate collision stack: gpu_collision_stack_size=2**27 added; placeholder assembly ID validation

Assessment

No changes to the PR's core schema fragment files (schemas.py, schemas_cfg.py, test_schema_fragments.py, the RigidBody USD data classes and writers). This is purely a branch synchronization bringing in upstream develop changes.

No new issues introduced to the schema fragment framework by this merge. The upstream changes are well-structured and follow established patterns (e.g., the cloner refactoring is consistent across all envs).

Previous Review Findings

All prior observations remain unchanged (addressed or out-of-scope for this PR):

  1. Bare next() StopIteration risk — unchanged
  2. HasAPI truthiness pattern — unchanged

Automated incremental review by IsaacLab Review Bot 🤖


🔄 Incremental Review Update (commits fb864c0...419e9ef)

Changes Since Last Review

This update is a branch rebase/merge from develop bringing in 28 commits of upstream changes. The schema fragment files received only minor comment simplifications:

  • schemas.py: Editorial cleanup of comments in apply_namespaced() and apply_rigid_body_properties() — more concise language, no logic changes

The bulk of the diff (~80+ files) is unrelated upstream work merged into the branch (cloner refactoring, task renaming, visualizer improvements, dependency updates, etc.).

Previous Review Concerns

  1. P1: Missing prim validity check — Fixed in earlier commit, verified still present
  2. P2: apply_rigid_body_properties returns True — Fixed in earlier commit, verified still present
  3. P2: Fragile func-field exclusion — Addressed by simpler design (fail if no namespace)

Assessment

No new issues introduced. The schema fragment framework code is unchanged in substance — only comments were tightened. All prior review concerns were addressed in earlier commits and remain in place.

PR remains ready for merge once CI is green.


Automated incremental review by IsaacLab Review Bot 🤖


🔄 Incremental Review Update (commits 419e9ef...b7456fc)

Changes Since Last Review

2 commits touching 2 files:

  1. CONTRIBUTORS.md: Added "Vidur Vij" to the contributors list (alphabetically correct placement between Tyler Lum and Virgilio Gómez Lambo).

  2. source/isaaclab/test/sim/test_schema_fragments.py: Removed "Task N --" prefixes from all test section headers (e.g., Task 1 -- SchemaFragment baseSchemaFragment base). This is a cosmetic cleanup — test logic is entirely unchanged.

Assessment

LGTM — These are purely housekeeping changes:

  • Contributor addition is appropriate for the PR author
  • Test header cleanup removes stale task-numbering artifacts that are no longer relevant now that the implementation is complete
  • No functional code changes whatsoever

Previous Review Status

All prior review concerns were addressed in earlier commits and remain in place:

  1. ✅ Prim validity checks — still present
  2. apply_rigid_body_properties return value aggregation — still present
  3. ✅ Namespace-presence guard (simplified design) — still present

PR remains ready for merge once CI is green.


Automated incremental review by IsaacLab Review Bot 🤖

@vidurv-nvidia

Copy link
Copy Markdown
Author

Thanks for the review! Responses below.

#1RigidBodyAPI(prim) truthiness — respectfully, this is not a bug. For a single-apply API schema, the pxr Python wrapper's __bool__ reflects whether the API is applied on the prim (the schema object is only valid when applied), so if not UsdPhysics.RigidBodyAPI(prim): ...Apply(prim) is correct. This is the same idiom the existing define_rigid_body_properties has shipped with. Verified empirically on this build:

prim = UsdGeom.Xform.Define(stage, "/W").GetPrim()
bool(UsdPhysics.RigidBodyAPI(prim))   # -> False   (HasAPI -> False)
UsdPhysics.RigidBodyAPI.Apply(prim)
bool(UsdPhysics.RigidBodyAPI(prim))   # -> True    (HasAPI -> True)

So the anchor is applied for a bare [UsdPhysicsRigidBodyCfg(...)] list (no PhysX fragment needed), and the bool(UsdPhysics.RigidBodyAPI(prim)) assertion in test_apply_rigid_body_properties_composes_namespaces is meaningful rather than coincidental. Happy to switch to prim.HasAPI(UsdPhysics.RigidBodyAPI) if preferred for explicitness, but the behavior is correct as-is.

#3 — type annotation on fragments: fixed. apply_rigid_body_properties(... fragments: Iterable[RigidBodyFragment] ...) and apply_namespaced(cfg: SchemaFragment, ...) are now annotated.

#2 — DRY the 4 spawner transition shims: intentional for now. The if isinstance(f, SchemaFragment) branch is a deliberate transition shim that routes legacy single cfgs to the legacy writer and fragment lists to apply_*; it's commented (# transition shim, remove later: ...) and is removed once the call sites are migrated and the legacy cfgs are dropped. Keeping it inline (rather than a shared helper) keeps each spawn site's diff self-contained and the eventual deletion trivial. This is the first of a per-family stack of additive PRs that reuse the same pattern.

#4sim/__init__.pyi reordering: that's ruff/isort re-sorting the import block; no manual change. Agreed it inflates the diff but it's tool-enforced.

#5 noted, no action.

@vidurv-nvidia vidurv-nvidia changed the title feat(schemas): rigid-body schema-fragment API (1/2, additive) Adding RigidBody USD data classes and writers Jun 5, 2026
# 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_*

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transition shim — remove at the end of the migration. A fragment list routes to apply_rigid_body_properties; a legacy single cfg falls through to the existing define_/modify_ writer, so current behavior is unchanged (this PR is purely additive). Collapses to one unconditional apply_* call once call sites move to fragments and the legacy cfgs are dropped.

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)
# apply rigid properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> define_*)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transition shim — remove at the end of the migration. A fragment list routes to apply_rigid_body_properties; a legacy single cfg falls through to the existing define_/modify_ writer, so current behavior is unchanged (this PR is purely additive). Collapses to one unconditional apply_* call once call sites move to fragments and the legacy cfgs are dropped.

# 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_*

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transition shim — remove at the end of the migration. A fragment list routes to apply_rigid_body_properties; a legacy single cfg falls through to the existing define_/modify_ writer, so current behavior is unchanged (this PR is purely additive). Collapses to one unconditional apply_* call once call sites move to fragments and the legacy cfgs are dropped.

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
# apply rigid body properties (transition shim, remove later: fragment list -> apply_*; legacy cfg -> define_*)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transition shim — remove at the end of the migration. A fragment list routes to apply_rigid_body_properties; a legacy single cfg falls through to the existing define_/modify_ writer, so current behavior is unchanged (this PR is purely additive). Collapses to one unconditional apply_* call once call sites move to fragments and the legacy cfgs are dropped.

stage = get_current_stage()
prim = stage.GetPrimAtPath(prim_path)
if not UsdPhysics.RigidBodyAPI(prim):
UsdPhysics.RigidBodyAPI.Apply(prim)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implicit anchor: no fragment owns RigidBodyAPI (the PhysX/mjc fragments are inert add-ons without it), so the family writer applies it once regardless of which fragments are passed — which is why UsdPhysicsRigidBodyCfg._usd_applied_schema is None.

@vidurv-nvidia vidurv-nvidia marked this pull request as ready for review June 5, 2026 21:20
@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Introduces a schema-fragment API for rigid-body USD authoring, allowing a prim to carry properties from multiple namespaces (physics:, physxRigidBody:, mjc:) via a composable list of RigidBodyFragment objects. The existing RigidBodyPropertiesCfg path is untouched; transition shims in the spawners route fragment lists to the new apply_rigid_body_properties writer while legacy cfgs continue through the old define_/modify_ path.

  • Added SchemaFragment, RigidBodyFragment, UsdPhysicsRigidBodyCfg (core), PhysxRigidBodyCfg (physx), and MujocoRigidBodyCfg (newton) with class-level _usd_namespace/_usd_applied_schema metadata; apply_namespaced and apply_rigid_body_properties implement the generic and family writers respectively.
  • Widened RigidObjectSpawnerCfg.rigid_props to accept a list[RigidBodyFragment]; all four spawner sites (shapes, meshes, from-files, mesh-converter) were updated with identical dispatch shims.
  • Added test_schema_fragments.py with 7 tests covering metadata, per-namespace writes, multi-namespace composition, spawner routing, public imports, invalid-prim guards, and aggregate return.

Confidence Score: 4/5

Safe to merge for new projects using the fragment API on single prims, but the dispatching shim in _spawn_from_usd_file produces silently incomplete writes for USD assets that carry RigidBodyAPI on multiple nested links.

The transition shim in from_files.py routes the new fragment path to apply_rigid_body_properties, which targets only the root prim. The legacy path it replaced called modify_rigid_body_properties, whose @apply_nested decorator walks the full prim hierarchy and writes to every child that already has RigidBodyAPI. For a robot USD asset with several articulation links, a user who switches to the new fragment API will only see the property written to the root — all child links are silently left with their prior values.

source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py — the fragment-path dispatch in _spawn_from_usd_file does not propagate fragment writes to nested rigid-body prims.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/sim/schemas/schemas.py Adds apply_namespaced and apply_rigid_body_properties — both include prim validity guards; logic is correct for single-prim write. Missing @apply_nested equivalent in apply_rigid_body_properties creates a behavioral asymmetry vs. the legacy modify_rigid_body_properties when called on hierarchical USD assets.
source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py Adds SchemaFragment, RigidBodyFragment, and UsdPhysicsRigidBodyCfg. ClassVar metadata pattern is correct; func default as import string is consistent with the codebase.
source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py Transition shim routes fragment lists to apply_rigid_body_properties, which lacks the @apply_nested traversal that the replaced modify_rigid_body_properties call had, producing silent incomplete writes for hierarchical USD assets.
source/isaaclab/isaaclab/sim/spawners/spawner_cfg.py Widens rigid_props type to accept a fragment list; union type and docstring are clear.
source/isaaclab_physx/isaaclab_physx/sim/schemas/schemas_cfg.py Adds PhysxRigidBodyCfg fragment with physxRigidBody namespace and PhysxRigidBodyAPI applied schema; all fields match the PhysX API.
source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py Adds MujocoRigidBodyCfg fragment with mjc namespace; gravcomp field and null applied-schema are correctly specified.
source/isaaclab/test/sim/test_schema_fragments.py 7 tests covering fragment metadata, per-namespace writes, multi-namespace composition, spawner routing, public imports, invalid-prim guards, and aggregate return.

Reviews (2): Last reviewed commit: "test(schemas): drop internal plan task n..." | Re-trigger Greptile

Comment on lines +438 to +451
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.RigidBodyAPI(prim):
UsdPhysics.RigidBodyAPI.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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Missing prim validity check — silent failure on invalid path

Both apply_namespaced and apply_rigid_body_properties skip the prim.IsValid() guard that every analogous define_*/modify_* function in this file uses. If prim_path does not exist in the stage, stage.GetPrimAtPath returns an invalid UsdPrim; prim.GetAppliedSchemas() returns [], prim.AddAppliedSchema(...) and safe_set_attribute_on_usd_prim silently no-op (or emit a TF error), and the function still returns True. define_rigid_body_properties (line 476) raises ValueError in this case. The missing check means the new fragment path gives callers no indication that nothing was written.

Comment on lines +448 to +451
for cfg in fragments:
func = cfg.func if callable(cfg.func) else string_to_callable(cfg.func)
func(cfg, prim_path, stage)
return True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 apply_rigid_body_properties always returns True regardless of per-fragment failures

func(cfg, prim_path, stage) may return False (e.g. a custom fragment applier signals a failure). The return is currently discarded and the outer function unconditionally returns True. modify_rigid_body_properties returns False when the API is not applied. Propagating the aggregate result keeps the contract consistent.

Suggested change
for cfg in fragments:
func = cfg.func if callable(cfg.func) else string_to_callable(cfg.func)
func(cfg, prim_path, stage)
return True
ok = True
for cfg in fragments:
func = cfg.func if callable(cfg.func) else string_to_callable(cfg.func)
ok = func(cfg, prim_path, stage) and ok
return ok

Comment on lines +243 to +246
for f in dataclasses.fields(cfg):
if f.name == "func":
continue
value = getattr(cfg, f.name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Fragile func-field exclusion by hard-coded name

Skipping the field via f.name == "func" is a maintenance hazard: any future non-USD metadata field added to a SchemaFragment subclass will be silently written as a USD attribute unless the exclusion list in apply_namespaced is also updated. A class-level _non_usd_fields set makes the policy explicit.

Suggested change
for f in dataclasses.fields(cfg):
if f.name == "func":
continue
value = getattr(cfg, f.name)
_non_usd_fields = getattr(type(cfg), "_non_usd_fields", frozenset()) | {"func"}
for f in dataclasses.fields(cfg):
if f.name in _non_usd_fields:
continue
value = getattr(cfg, f.name)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

…e non-USD fields

Address review feedback on the rigid-body schema-fragment API:

- apply_namespaced and apply_rigid_body_properties now raise ValueError on
  an invalid prim path, matching the legacy define_/modify_ writers instead
  of silently no-op'ing and still returning True.
- apply_rigid_body_properties aggregates each fragment applier's boolean
  result so a reported failure is not masked by the always-applied anchor.
- apply_namespaced skips fields named in a fragment's _non_usd_fields set
  (in addition to func), so future non-USD bookkeeping fields opt out
  explicitly rather than leaking as namespaced USD attributes.
…t set

Per design review, fragments carry only USD-attribute fields plus func --
non-USD/bookkeeping state lives on the spawner cfg or as a writer kwarg
(e.g. fix_root_link, ensure_drives_exist). Replace the _non_usd_fields
opt-out skip-list with the invariant enforced loudly:

- Drop the _non_usd_fields ClassVar; restore the simple func-only skip.
- apply_namespaced raises ValueError when a fragment has no _usd_namespace,
  turning a misconfigured (non-USD) field from a silent None: write into a
  loud failure. Non-scalar value types already raise in
  safe_set_attribute_on_usd_prim.
- Document the invariant on SchemaFragment.

Field-name validation against the USD schema registry is intentionally
deferred to the codegen/CI sync-check: a runtime registry check would
false-positive on namespace-only fragments (e.g. mjc:gravcomp) that own no
applied schema.
The SchemaFragment docstring carries the invariant rationale, so collapse
the inline comments in apply_namespaced / apply_rigid_body_properties to
terse intent. No behavior change.
assert abs(prim.GetAttribute("physxRigidBody:linearDamping").Get() - 0.2) < 1e-6
assert abs(prim.GetAttribute("mjc:gravcomp").Get() - 1.0) < 1e-6


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-------------------------------------------------------------------------------------

Task 6 -- spawner slot accepts a fragment list + transition routing

-------------------------------------------------------------------------------------

remember to remove ai comments like this :D

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed :)

The section banners referenced internal planning task numbers; replace
with self-contained descriptions.
@vidurv-nvidia vidurv-nvidia requested a review from ooctipus June 9, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants