Skip to content

Respect USD schema default applicability - #3556

Closed
devshahofficial wants to merge 2 commits into
newton-physics:mainfrom
devshahofficial:devshahofficial/schema-resolver-provenance
Closed

Respect USD schema default applicability#3556
devshahofficial wants to merge 2 commits into
newton-physics:mainfrom
devshahofficial:devshahofficial/schema-resolver-provenance

Conversation

@devshahofficial

@devshahofficial devshahofficial commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Description

Give USD resolution a single result carrying the value, winning resolver, and source: authored, importer default, applicable schema default, or unresolved.

Built-in resolvers now declare applicability per prim type and, where necessary, per key. Mapping defaults therefore cannot leak from a configured solver schema onto unrelated prims. MuJoCo joint-limit semantics plus Newton SDF and hydroelastic defaults use the shared provenance-aware path.

Third-party resolver subclasses that do not declare applicability keep their legacy always-applicable behavior.

Closes #3307.

Checklist

  • New or existing tests cover these changes
  • The documentation is up to date with these changes
  • CHANGELOG.md has been updated (if user-facing change)

Test plan

uv run --extra dev -m newton.tests -k test_schema_resolver
uv run --extra dev -m newton.tests -k test_sdf_usd
uvx pre-commit run -a

The resolver suite passes 34 tests. The SDF suite passes 10 CPU-capable tests and skips 14 CUDA-only tests on this machine.

Bug fix

Steps to reproduce:

  1. Configure Newton, PhysX, and MuJoCo schema resolvers.
  2. Import a prim that does not apply the first resolver schema.
  3. Observe the first configured resolver injecting its hardcoded mapping default on main.

Minimal reproduction:

import newton
from newton.usd import SchemaResolverNewton

builder = newton.ModelBuilder()
builder.add_usd(stage, schema_resolvers=[SchemaResolverNewton()])

Summary by CodeRabbit

  • Bug Fixes

    • Corrected USD schema defaults so they apply only when the corresponding API/schema is applicable to the prim.
    • Improved USD importer resolution for joint limits/gains, SDF targets, and hydroelastic parameters, with corrected precedence and mutual exclusivity handling.
    • Preserved resolution provenance so importer behavior follows the correct authored, caller default, or schema-default source.
    • Refined handling for unresolved and invalid attribute values (including hydroelastic enabled/kh defaults).
  • Documentation

    • Updated USD “Resolution Hierarchy” guidance to match the new applicable-schema-default behavior and provenance outcomes.
  • Tests

    • Expanded schema-resolver and provenance coverage for applicability-gated defaults and layered fallbacks.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

USD schema resolution now gates mapping defaults by schema applicability and preserves resolution provenance. Import paths use this metadata for joint-limit, SDF, and hydroelastic defaults, with updated resolver mappings, documentation, changelog, and tests.

Changes

USD resolution and importer integration

Layer / File(s) Summary
Resolver applicability and provenance
newton/_src/usd/schema_resolver.py
Adds applicability checks and a provenance-bearing Resolution result for authored, importer-default, schema-default, and unresolved values.
Resolver schema mappings
newton/_src/usd/schemas.py
Adds Newton, PhysX, and MuJoCo applicability metadata and updates selected SDF and hydroelastic defaults.
Importer integration and validation
newton/_src/utils/import_usd.py, newton/tests/test_schema_resolver.py, docs/concepts/usd_parsing.rst, CHANGELOG.md
Uses resolution provenance in importer paths and updates tests, documentation, and changelog entries.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant USDPrim
  participant SchemaResolverManager
  participant import_usd
  USDPrim->>SchemaResolverManager: resolve attribute
  SchemaResolverManager-->>import_usd: value, resolver, and source
  import_usd->>import_usd: apply importer fallback semantics
Loading

Possibly related PRs

Suggested labels: usd

Suggested reviewers: mzamoramora-nvidia, adenzler-nvidia

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement the resolver precedence, provenance, applicability contracts, and test coverage requested by #3307.
Out of Scope Changes check ✅ Passed The diffs stay focused on USD resolver behavior, related importer updates, tests, docs, and changelog notes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main change: making USD schema defaults apply only when the schema is actually applicable.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
newton/_src/usd/schemas.py (1)

312-322: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stale comment: "-inf is the unset sentinel" no longer describes several of the fields below it.

The unchanged comment block above this mapping ("-inf is the 'unset' sentinel (same convention as gap / shell_thickness above)") now only applies to sdf_narrow_band_inner/outer, sdf_target_voxel_size, and sdf_padding. sdf_max_resolution (64), sdf_texture_format ("uint16"), hydroelastic_enabled (False), and kh (1.0e10) were changed to concrete defaults that are now gated by _is_applicable instead of using the -inf sentinel convention. A reader relying on the comment could wrongly assume all these fields still use -inf as "unset".

📝 Suggested comment update
-            # SDF configuration — from NewtonSDFCollisionAPI. `-inf` is the
-            # "unset" sentinel (same convention as gap / shell_thickness above).
+            # SDF configuration — from NewtonSDFCollisionAPI. `-inf` is the
+            # "unset" sentinel for the narrow-band/voxel-size/padding fields below
+            # (same convention as gap / shell_thickness above); sdf_max_resolution,
+            # sdf_texture_format, hydroelastic_enabled, and kh use concrete defaults
+            # gated by API applicability instead.
             "sdf_max_resolution": SchemaAttribute("newton:sdfMaxResolution", 64),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@newton/_src/usd/schemas.py` around lines 312 - 322, Update the comment above
the SDF configuration mapping to state that the “-inf” unset sentinel applies
only to sdf_narrow_band_inner, sdf_narrow_band_outer, sdf_target_voxel_size, and
sdf_padding. Do not imply that sdf_max_resolution, sdf_texture_format,
hydroelastic_enabled, or kh use the sentinel, since they have concrete defaults.
newton/_src/usd/schema_resolver.py (1)

133-155: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider caching per-prim applied-schema lookups.

_is_applicable calls prim.GetAppliedSchemas() and, for every candidate api name, usd.has_applied_api_schema(prim, name) (which itself re-reads the raw apiSchemas metadata). This is invoked from resolve()'s schema-default loop for every configured resolver × key that reaches that stage (e.g. a shape can have a dozen+ SDF/margin/gap/mass keys), with no caching across calls for the same prim. On large scenes this repeats USD metadata parsing many times per prim.

Also, since SchemaResolverManager.resolve() now calls resolver._is_applicable(...) externally, consider dropping the leading underscore (e.g. is_applicable) to reflect that it's part of the cross-class contract rather than a resolver-private helper.

♻️ Sketch: cache applied-schema set per prim within a resolve session
+    def _cached_applied_schemas(self, prim: Usd.Prim) -> set[str]:
+        cache = getattr(self, "_applied_schema_cache", None)
+        if cache is None:
+            cache = self._applied_schema_cache = {}
+        path = str(prim.GetPath())
+        if path not in cache:
+            cache[path] = {str(name).split(":", 1)[0] for name in prim.GetAppliedSchemas()}
+        return cache[path]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@newton/_src/usd/schema_resolver.py` around lines 133 - 155, Update
_is_applicable to is_applicable and adjust SchemaResolverManager.resolve() and
all other call sites to use the public cross-class contract. Cache each prim’s
applied-schema information once per resolve session, including the data needed
by usd.has_applied_api_schema, and reuse it across resolver/key checks while
preserving existing applicability and exception behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@newton/_src/usd/schema_resolver.py`:
- Around line 133-155: Update _is_applicable to is_applicable and adjust
SchemaResolverManager.resolve() and all other call sites to use the public
cross-class contract. Cache each prim’s applied-schema information once per
resolve session, including the data needed by usd.has_applied_api_schema, and
reuse it across resolver/key checks while preserving existing applicability and
exception behavior.

In `@newton/_src/usd/schemas.py`:
- Around line 312-322: Update the comment above the SDF configuration mapping to
state that the “-inf” unset sentinel applies only to sdf_narrow_band_inner,
sdf_narrow_band_outer, sdf_target_voxel_size, and sdf_padding. Do not imply that
sdf_max_resolution, sdf_texture_format, hydroelastic_enabled, or kh use the
sentinel, since they have concrete defaults.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 2cfd199f-884a-4548-b21a-30545eb49018

📥 Commits

Reviewing files that changed from the base of the PR and between 26327db and 5b3e90d.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • docs/concepts/usd_parsing.rst
  • newton/_src/usd/schema_resolver.py
  • newton/_src/usd/schemas.py
  • newton/_src/utils/import_usd.py
  • newton/tests/test_schema_resolver.py

@devshahofficial

Copy link
Copy Markdown
Contributor Author

@coderabbitai Addressed both valid nits in d26c1c2: applied-schema/type data is cached per manager with metadata-signature invalidation, and the SDF sentinel comment now distinguishes sentinel-backed fields from concrete defaults. I kept _is_applicable protected intentionally because SchemaResolver is public and exposing that helper would expand the API before the resolver design is approved. Validation: 34 resolver tests and 24 SDF tests pass (14 CUDA-only skips), plus the full pre-commit suite.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@devshahofficial Thanks for addressing both nits and for the thorough validation. Keeping SchemaResolver._is_applicable protected is appropriate here—the public API should not grow ahead of the resolver design approval.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Track resolver provenance and apply mapping defaults only when their USD
schema applies to the prim. Route MuJoCo limit, SDF, and hydroelastic
default decisions through the shared resolution contract.
Cache applied-schema and typed-prim metadata across resolver keys while invalidating on authored schema changes. Clarify which SDF fields use sentinel versus concrete defaults.
@devshahofficial
devshahofficial force-pushed the devshahofficial/schema-resolver-provenance branch from d26c1c2 to d68f27e Compare July 18, 2026 09:09
@devshahofficial
devshahofficial marked this pull request as ready for review July 18, 2026 09:13
@jcarius-nv
jcarius-nv requested a review from andrewkaufman July 20, 2026 12:58
@adenzler-nvidia

Copy link
Copy Markdown
Member

closing this in favor of #3572. Please excuse the late notice, but I have been working on the same thing for an internal project for a while, and my PR is is part of a series trying to get the pxr- dependency out of the schemaResolvers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redesign USD schema resolver precedence and provenance

2 participants