Skip to content

[Backport release/3.0.0] Drive fragment schema writers by prim path expressions - #7441

Merged
kellyguo11 merged 1 commit into
isaac-sim:release/3.0.0from
kellyguo11:codex/backport-pr-6640-release-3.0.0
Aug 31, 2026
Merged

[Backport release/3.0.0] Drive fragment schema writers by prim path expressions#7441
kellyguo11 merged 1 commit into
isaac-sim:release/3.0.0from
kellyguo11:codex/backport-pr-6640-release-3.0.0

Conversation

@kellyguo11

Copy link
Copy Markdown
Contributor

Description

Backports #6640 onto release/3.0.0.

This moves the experimental physics schema-fragment surface to prim-path expressions, adds per-family target mappings to spawner configs, makes schema API creation explicit, and keeps the PhysX/Newton tendon backends per-prim. It also fixes nested rigid-body and mass fragment targeting.

The prerequisite whole-path regular-expression matcher from #6841 is already present on the release branch. This is an exact cherry-pick -x of the merged commit.

Risk assessment

  • The source PR's 33 touched paths were identical between its develop base and the current release tip, so the commit applied without conflicts or release-specific edits; source and backport patch IDs match.
  • Legacy single-cfg values and the legacy define_* / modify_* writers are unchanged, and there are no in-tree fragment users.
  • The bounded compatibility risk is for out-of-tree users of the experimental fragment surface. They must wrap fragment lists as {"(/.*)?": [...]} and pass create_if_missing=True where API creation was previously implicit.

Type of change

  • New feature
  • Breaking change (experimental schema-fragment surface only)
  • Documentation update

Validation

  • Exact source/backport patch identity and clean release-branch application
  • git diff --check
  • Python 3.12 static compilation of the changed simulation/schema modules
  • Formatting, lint, spelling, license, and RST pre-commit hooks
  • Changelog-fragment gate against release/3.0.0
  • Upstream Drive fragment schema writers by prim path expressions #6640 CI passed pre-commit, changelog, docs, core, Newton, PhysX, wheel, x86 installation, rendering, and the targeted schema/spawner suites

The full project test and docs commands were not rerun locally because the project lockfile supports Linux and Windows, not this macOS host. Release-branch CI should provide the final platform validation. The source PR's unrelated Franka Pour dataset-contract failure and ARM runner-queue cancellation did not involve these paths.

Checklist

  • I have read and understood the contribution guidelines
  • I have made corresponding documentation changes
  • I have added tests that cover the changed behavior
  • I have added a changelog fragment for every touched source package
  • The contributor is already listed in CONTRIBUTORS.md

# Description

Moves the physics schema **fragment** surface onto prim path
expressions, so a writer targets prims
by pattern instead of traversing the subtree of a single input prim.

Since this PR was opened, isaac-sim#6841 landed the plain-regex prim path matcher
on `develop`. This PR has
been rebuilt on top of it: it no longer touches `sim/utils/queries.py`
at all, and the bespoke `**`
recursive token it originally introduced is gone. Targeting is now
expressed entirely in standard
Python regular expressions matched against whole prim paths.

## What changes

**Family writers take an expression.** `apply_rigid_body_properties`,
`apply_collision_properties`, `apply_mass_properties`,
`apply_articulation_root_properties`,
`apply_joint_drive_properties`, and the two tendon writers now take
`prim_path_expr` and resolve
targets through `find_matching_prims`. A bare prim path matches only
that prim; `f"{prim_path}/.*"`
reaches its descendants and `f"{prim_path}(/.*)?"` reaches the prim
together with its subtree.

**Spawner fields take a mapping.** The fragment fields (`rigid_props`,
`collision_props`,
`mass_props`, `articulation_props`, `joint_drive_props`,
`fixed_tendons_props`,
`spatial_tendons_props`) accept `dict[str, list[<Family>Fragment]]`. A
key is a regular-expression
**suffix appended to the prim the spawner anchors that family on**, so
it carries its own leading
`/` when it targets descendants:

| Key | Selects |
|---|---|
| `""` | the anchor prim itself |
| `"/[^/]+"` | its direct children |
| `"/.*"` | all of its descendants |
| `"(/.*)?"` | the anchor together with its descendants |

Entries apply in insertion order, so on overlapping targets later
entries override earlier ones per
attribute. Legacy single-cfg values are unaffected and still route to
the legacy writers.

```python
spawn = sim_utils.UsdFileCfg(
    usd_path=...,
    rigid_props={
        "(/.*)?": [UsdPhysicsRigidBodyCfg(rigid_body_enabled=True), PhysxRigidBodyCfg(...)],
        "/.*_hand(/.*)?": [PhysxRigidBodyCfg(max_depenetration_velocity=1.0)],
    },
)
```

**Explicit API creation.** The writers no longer apply their defining
USD API implicitly on a bare
prim. `create_if_missing=True` (and the spawner flags
`mass_props_create_if_missing`,
`articulation_props_create_if_missing`,
`joint_drive_props_create_if_missing`) applies the defining
API to matched prims that lack it.

**Articulation roots.** `apply_articulation_root_properties` authors on
every matched root and warns
when roots nest, rather than silently pruning nested ones. Asset
validity is the author's
responsibility.

**Tendon backends de-traverse.** The PhysX and Newton tendon fragment
functions now author on the
given prim only; target selection is owned by the core family writers.

**Deformable meshes accept the mapping too.** On the mesh spawner's
deformable branch,
`collision_props` given as a mapping previously failed the fragment type
check and raised. It also
passed the bare body prim to the collision writer, which under
expression matching no longer
reaches the simulation mesh authored beneath it. Mapping entries now
anchor at the body prim (e.g.
`{"/sim_mesh": [...]}`) and a bare fragment list uses a subtree pattern
to reach the collider.

## Fixes

Rigid-body and mass fragments previously reached only the outermost
schema-bearing prim on assets
with nested rigid-body hierarchies (child links authored under their
parent link prims, as produced
by the URDF importer in Isaac Sim 6.0 and later). A whole-subtree
pattern now reaches every carrier.

## Type of change

- New feature (non-breaking change which adds functionality)
- This change requires a documentation update

**Breaking within the fragment surface only.** The fragment path is
experimental and has no
in-tree users yet; legacy `define_*` / `modify_*` writers and legacy cfg
classes are untouched.
Migration for anyone already on fragments: wrap lists as `{"(/.*)?":
[...]}`, and pass
`create_if_missing=True` where an API was previously created implicitly.

## Screenshots

N/A

## Checklist
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

## Testing

Per-file, via the wrapped Python:

| Suite | Result |
|---|---|
| `test_utils_queries` | 12 passed |
| `test_schema_fragments` | 12 passed |
| `test_schema_writer_nested_targets` | 13 passed |
| `test_mass_fragments` | 9 passed |
| `test_collision_fragments` | 19 passed |
| `test_articulation_fragments` | 28 passed, 1 xfailed |
| `test_joint_drive_fragments` | 22 passed |
| `test_tendon_fragments` | 23 passed |
| `test_mesh_converter` | 15 passed |
| `test_spawn_meshes` (physx) | 3 passed |

### Note on the xfail

`test_physx_fix_root_link_migrates_preauthored_newton_root_api` is
marked `xfail`. It is not caused
by this PR. `develop`'s experience files were restructured so the schema
plugin that registered
`NewtonArticulationRootAPI` no longer loads, making it an unregistered
token schema.
`PhysicsManager._relocate_articulation_root` only migrates applied
schemas it can resolve through
`Usd.SchemaRegistry.FindAppliedAPIPrimDefinition`, so on root relocation
the token and its authored
`newton:selfCollisionEnabled` value are left stranded on the former root
link. Migrating it needs a
backend-registered schema-to-namespace mapping, which is out of scope
here — flagging it for a
follow-up.

---------

Co-authored-by: ooctipus <zhengyuz@nvidia.com>
Co-authored-by: Kelly Guo <kellyg@nvidia.com>
(cherry picked from commit 76e9cdd)
@kellyguo11
kellyguo11 requested a review from a team August 31, 2026 02:06
@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team labels Aug 31, 2026
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This backport changes schema-fragment writers and spawners to use whole-path prim expressions, adds explicit missing-API creation controls, and makes backend tendon/root handling per prim.

  • Adds expression-to-fragment mappings and shorthand normalization across file, shape, mesh, and converter spawners.
  • Refactors shared and backend schema writers for regex-selected targets, nested carriers, drives, tendons, and explicit API creation.
  • Adds backend articulation-root companion registration, documentation, changelog entries, and expanded regression coverage.

Confidence Score: 4/5

The root-relocation import-order defect should be fixed before merging because pre-authored Newton root schemas can remain stranded when an asset is processed under PhysX.

Companion handling for an unregistered Newton token is installed only by importing the optional Newton schemas package, while normal PhysX relocation does not guarantee that import and otherwise skips the schema.

Files Needing Attention: source/isaaclab/isaaclab/physics/physics_manager.py; source/isaaclab_newton/isaaclab_newton/sim/schemas/init.py

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/sim/schemas/schemas.py Replaces subtree traversal with regex-selected per-prim family writers and explicit missing-API creation.
source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py Routes fragment mappings through family-specific expressions and preserves documented bare-fragment fallback behavior.
source/isaaclab/isaaclab/physics/physics_manager.py Adds companion-schema relocation support, but correctness currently depends on optional backend-module import order.
source/isaaclab_newton/isaaclab_newton/sim/schemas/init.py Registers Newton's unregistered root-schema namespace only when the optional schemas package is imported.
source/isaaclab/isaaclab/sim/spawners/_utils.py Introduces fragment normalization, expression composition, and subtree API-detection helpers.
source/isaaclab_physx/isaaclab_physx/sim/schemas/schemas.py Adds per-prim PhysX joint and multi-instance tendon fragment application.
source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas.py Adapts Newton and MuJoCo schema fragments to per-prim dispatch.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Spawner fragment mapping] --> B[Build whole-path expression]
    B --> C[Match USD prims]
    C --> D{Family target API present?}
    D -- Yes --> E[Dispatch fragments per prim]
    D -- No and creation enabled --> F[Apply defining API]
    F --> E
    E --> G[Shared USD attributes]
    E --> H[PhysX attributes]
    E --> I[Newton attributes]
    J[Root relocation] --> K[USD schema registry]
    J --> L[Registered backend companions]
    K --> M[Move schemas and properties]
    L --> M
Loading

Reviews (1): Last reviewed commit: "Drive fragment schema writers by prim pa..." | Re-trigger Greptile

schemas_to_move = []
for schema_name in articulation_prim.GetPrimTypeInfo().GetAppliedAPISchemas():
definition = registry.FindAppliedAPIPrimDefinition(schema_name)
companion_namespace_override = _articulation_root_companion_namespace(schema_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.

P1 Companion registration depends on imports

When PhysX relocates an imported articulation carrying NewtonArticulationRootAPI before isaaclab_newton.sim.schemas has been imported, the companion lookup returns None and relocation skips the unregistered token, leaving the Newton root schema and its newton:* attributes on the former root link.

Knowledge Base Used:

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

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.

Isaac Lab Review Bot

The expression-driven fragment targeting and backend/per-prim writer split are coherent, but the backport introduces a positional API compatibility hazard, an unsafe topology-only articulation creation path, and contradictory FileCfg shorthand documentation.

  • Design and architecture: Target matching is cleanly separated from backend-specific per-prim application, including tendon handling and articulation-root companion registration. However, the topology-only articulation path combines the broad subtree expression with create_if_missing, potentially creating and fixing articulation roots on every matched descendant despite having no fragments to author.
  • API: The rigid-body, collision, and mass writer signatures insert create_if_missing into the former third-position stage slot. Existing positional callers can therefore silently pass a Stage as the creation flag and operate on the current stage instead. FileCfg also documents bare articulation, tendon, and joint-drive fragments as anchor-only even though implementation expands them across the spawn subtree.
  • Implementation: Spawner routing generally follows the new mapping model, but the topology-only branch must not forward articulation_props_create_if_missing when articulation_props is absent or empty. The three affected writer signatures should retain stage as the third parameter, and the FileCfg shorthand documentation should describe the implemented {"(/.*)?": [...]} behavior.

Significant concerns. Posted 3 actionable findings inline.

Automated review; human maintainers own approval decisions.

prim_path: str, fragments: Iterable[schemas_cfg.RigidBodyFragment], stage: Usd.Stage | None = None
prim_path_expr: str,
fragments: Iterable[schemas_cfg.RigidBodyFragment],
create_if_missing: bool = False,

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.

🟡 Warning · Api — create_if_missing inserted ahead of stage parameter

apply_rigid_body_properties, apply_collision_properties and apply_mass_properties now take create_if_missing in the third position, which previously held stage. An existing positional call apply_rigid_body_properties(path, frags, stage) silently binds the truthy Stage to create_if_missing, applying the defining API to every matched prim while authoring on the current stage. apply_articulation_root_properties and apply_joint_drive_properties keep stage third. Place create_if_missing after stage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@vidurv-nvidia @ooctipus this seems like a good comment that we can address? would be good to align the ordering, and help avoid breakage of existing user code as much as we can.

props_expr(prim_path, "(/.*)?"),
[],
fix_root_link=articulation_fix_root_link,
create_if_missing=cfg.articulation_props_create_if_missing,

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.

🟡 Warning · Implementation — Topology-only path forwards articulation creation flag

This branch runs when articulation_props is None or an empty mapping, yet still forwards articulation_props_create_if_missing with the widest expression "(/.*)?". With that flag set, apply_articulation_root_properties applies UsdPhysics.ArticulationRootAPI to every matched descendant lacking it and then fixes each resulting root. The field documents itself as "only consumed when articulation_props is given as fragments". Pass create_if_missing=False here, since no fragments are authored.

Keys are regular-expression suffixes appended to the spawn prim, so a key carries its own leading ``/`` when it
targets descendants (``""`` the anchor itself, ``"/[^/]+"`` its direct children, ``"/.*"`` everything beneath it).
Entries apply in insertion order, so on overlapping targets later entries override earlier ones per attribute. As
a shorthand for the common case, a bare fragment or a list of fragments is read as ``{"": [...]}``, i.e. the

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.

🟡 Warning · Api — FileCfg shorthand documented with wrong target

These docstrings (articulation_props, both tendon fields, joint_drive_props) state a bare fragment or list is read as {"": [...]}, the spawn prim itself. _apply_articulation_schema_properties calls fragment_mapping(..., "(/.*)?"), so the shorthand targets the spawn prim together with its descendants, as the new concept page and changelog state. Users following these docstrings will mis-scope tendon and joint-drive rules. Correct them to {"(/.*)?": [...]}.

@kellyguo11

Copy link
Copy Markdown
Contributor Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Aug 31, 2026
@kellyguo11
kellyguo11 merged commit 33687bb into isaac-sim:release/3.0.0 Aug 31, 2026
48 of 49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants