Skip to content

Add source-neutral USD schema resolution - #3568

Closed
adenzler-nvidia wants to merge 23 commits into
newton-physics:mainfrom
adenzler-nvidia:adenzler/schema-resolver-design
Closed

Add source-neutral USD schema resolution#3568
adenzler-nvidia wants to merge 23 commits into
newton-physics:mainfrom
adenzler-nvidia:adenzler/schema-resolver-design

Conversation

@adenzler-nvidia

@adenzler-nvidia adenzler-nvidia commented Jul 20, 2026

Copy link
Copy Markdown
Member

Description

Adds one typed, source-neutral SchemaResolution object shared by ModelBuilder.add_usd() and consumers of populated or mapping-based scene data. Callers configure resolver priority and the fallback migration choice once, then pass the object to add_usd(..., schema_resolution=resolution) or call resolution.resolve(...) directly. Both paths use the same schema ownership, USD fallback catalog, conversions, and boolean compatibility choice.

The existing experimental schema_resolvers= argument remains as a compatibility shorthand: internally it constructs the same SchemaResolution. Supplying both arguments is rejected. use_applied_schema_fallbacks=False is the compatibility default; setting it to True on SchemaResolution selects composed applied-schema fallbacks for both PXR and non-PXR sources without migration warnings. The direct add_usd() boolean is shorthand when no shared resolution object is supplied.

The PXR adapter supplies registered schema fallbacks when available. Source-neutral consumers use the built-in catalog or explicit catalog additions, but do not need to construct PXR prims. Resolver definitions and evaluation internals remain private behind the small public object.

This first step deliberately leaves topology discovery, batching, Warp lowering, and direct builder-buffer population out of scope. Those can replace the scalar source adapter later without changing resolver configuration.

PR relationship and dependencies

Checklist

  • New or existing tests cover these changes
  • The documentation is up to date with these changes
  • CHANGELOG.md has been updated

API

from newton import ModelBuilder
from newton.usd import SchemaResolution, SchemaResolverNewton

resolution = SchemaResolution(
    [SchemaResolverNewton()],
    use_applied_schema_fallbacks=True,
)

builder = ModelBuilder()
builder.add_usd("robot.usda", schema_resolution=resolution)

values = resolution.resolve(
    prim_type,
    populated_values,
    schemas=applied_schemas,
)

The design rationale and migration/removal sequence are documented in docs/design/schema-resolution.md.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an opt-in source-neutral USD schema resolution API, schema-owned fallback catalogs, source-aware resolver mappings, importer plumbing, documentation, and regression tests. Legacy fallback behavior is audited through migration warnings while composed resolution applies schema ownership and fallback precedence.

Changes

USD schema resolution

Layer / File(s) Summary
Fallback catalog and public contract
newton/_src/usd/_schema_fallbacks.py, newton/usd.py, docs/..., CHANGELOG.md
Defines built-in schema fallbacks, documents composed resolution, and exposes SchemaResolution through newton.usd.
Composed resolution engine
newton/_src/usd/schema_resolver.py
Adds schema ownership, source-aware reads, composed fallback precedence, provenance tracking, PXR fallback lookup, and legacy/composed manager modes.
Source mappings and importer integration
newton/_src/usd/schemas.py, newton/_src/sim/builder.py, newton/_src/utils/import_usd.py
Updates resolver mappings and wires schema_resolution through USD parsing, including joint-limit and infinite-velocity handling.
Resolution and importer validation
newton/tests/test_schema_resolver.py, newton/tests/test_import_usd.py
Tests schema ownership, fallback precedence, resolver requirements, joint and mesh defaults, PhysX gains, and legacy/composed behavior.
Fallback migration validation
newton/tests/unittest_utils.py, newton/tests/test_*.py
Adds warning-capture assertions and applies them to USD import tests during the compatibility period.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: eric-heiden

Sequence Diagram(s)

sequenceDiagram
  participant ModelBuilder
  participant parse_usd
  participant SchemaResolverManager
  participant SchemaResolution
  participant SchemaRegistry
  ModelBuilder->>parse_usd: pass schema_resolution
  parse_usd->>SchemaResolverManager: configure composed resolution
  SchemaResolverManager->>SchemaResolution: resolve logical attribute
  SchemaResolution->>SchemaRegistry: query applied-schema fallback
  SchemaResolverManager-->>parse_usd: return value and provenance
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.30% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding source-neutral USD schema resolution.
✨ 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.

<!-- SPDX-License-Identifier: CC-BY-4.0 -->

# Source-neutral USD schema resolution

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This file will be removed for the final version, but it motivates the design for now so I think it's useful to have it in the PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we just migrate this doc to an Issue that the PR implements?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'd like to keep it up-to-date while the PR evolves, once final I will move the design to the PR description.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

❌ 5 Tests Failed:

Tests completed Failed Passed Skipped
3508 5 3503 581
View the top 3 failed test(s) by shortest run time
TestMenagerieUSD_WonikAllegro::test_dynamics
Stack Traces | 1.42s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\test_menagerie_usd_mujoco.py", line 1600, in test_dynamics
    raise AssertionError(
AssertionError: Step 0, qpos: max diff 3.2082e-01 > tol 5.00e-02
  at index (np.int64(15), np.int64(12)): newton(permuted)=0.3228329122066498 native=0.00201297365128994
TestMenagerieUSD_BoosterT1::test_dynamics
Stack Traces | 1.99s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\test_menagerie_usd_mujoco.py", line 1606, in test_dynamics
    raise AssertionError(
AssertionError: Step 1, qvel: max diff 4.0480e-02 > tol 3.00e-04
  at index (np.int64(17), np.int64(26)): newton(permuted)=-0.3979400098323822 native=-0.35745954513549805
TestMenagerieUSD_ShadowHand::test_dynamics
Stack Traces | 3.84s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\test_menagerie_usd_mujoco.py", line 1600, in test_dynamics
    raise AssertionError(
AssertionError: Step 1, qpos: max diff 1.5811e-03 > tol 1.00e-04
  at index (np.int64(1), np.int64(14)): newton(permuted)=-0.0010127229616045952 native=-0.0025938297621905804
TestMenagerieUSD_ApptronikApollo::test_dynamics
Stack Traces | 8.65s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\test_menagerie_usd_mujoco.py", line 1606, in test_dynamics
    raise AssertionError(
AssertionError: Step 1, qvel: max diff 1.4150e-01 > tol 1.00e-03
  at index (np.int64(28), np.int64(35)): newton(permuted)=-0.32153356075286865 native=-0.18002958595752716
TestMenagerieUSD_G1WithHands::test_dynamics
Stack Traces | 10.2s run time
Traceback (most recent call last):
  File "D:\a\newton\newton\newton\tests\test_menagerie_usd_mujoco.py", line 1606, in test_dynamics
    raise AssertionError(
AssertionError: Step 3, qvel: max diff 1.0717e-03 > tol 5.00e-04
  at index (np.int64(30), np.int64(45)): newton(permuted)=-0.010609574615955353 native=-0.01168124657124281

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Add an opt-in composed resolver path that gives applied schemas ownership
of their unauthored properties. Prefer registered PXR fallbacks and use a
built-in catalog when vendor schema plugins are unavailable, while keeping
the existing resolver behavior unchanged by default.
Preserve existing add_usd resolver results while auditing where applied USD schema fallbacks will change precedence. Emit one migration warning per import and leave the source-neutral facade to the follow-up change.
Route legacy auditing and composed resolution through one private
policy. Keep specialized joint paths on that policy so the future
fallback switch requires no public API or scattered importer edits.
Reuse authored reads while auditing future schema fallbacks, and keep
PXR-only custom getters on the legacy path when they cannot evaluate a
source-neutral fallback.

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@CHANGELOG.md`:
- Line 12: Update the Changed entry in CHANGELOG.md to include migration
guidance: instruct users to explicitly author the intended values for affected
USD schema properties before the future fallback change, preserving the
resolver’s current behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 737c985a-30bd-4256-9a6b-6be88783f3a8

📥 Commits

Reviewing files that changed from the base of the PR and between 496dd4b and c7dcee8.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • docs/api/newton_usd.rst
  • docs/concepts/usd_parsing.rst
  • docs/design/schema-resolution.md
  • docs/index.rst
  • newton/_src/sim/builder.py
  • newton/_src/usd/schema_resolver.py
  • newton/_src/utils/import_usd.py
  • newton/tests/test_import_usd.py
  • newton/tests/test_schema_resolver.py
  • newton/usd.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • newton/_src/sim/builder.py
  • docs/design/schema-resolution.md
  • newton/tests/test_schema_resolver.py
  • newton/_src/utils/import_usd.py

Comment thread CHANGELOG.md Outdated
Distinguish expected future-resolution gaps from resolver failures so compatibility auditing cannot hide callback bugs. Treat registered properties without raw fallbacks as missing and report unauditable legacy values explicitly.\n\nMake first-party partial-schema and external-asset coverage assert the exact migration warning while preserving strict handling for every unexpected warning.
Let USD consumers adopt applied-schema fallback precedence during the compatibility period. Keep legacy resolution as the default while making its deprecation actionable, and migrate the Unitree examples to exercise the target behavior.
Distinguish the release default from explicit composed and legacy choices. This keeps the later default flip internal while allowing consumers to pin either behavior during migration.
Keep the public migration switch as a conventional false-by-default boolean. Consumers can opt into applied-schema fallback precedence explicitly while existing imports retain their current behavior.
Store the migration choice as the public boolean instead of a second policy enum, and declare the source-neutral reader callback on the resolver descriptor. Reuse authored reads in specialized joint auditing, share velocity-limit handling, and attribute migration warnings to consumer code.
Preserve the builder margin when PhysX's offset fallback selects its engine default, avoiding invalid shape margins. Match the built-in joint velocity fallback to the current PhysX schema when its plugin is unavailable.
Normalize legacy and composed fallback values with the same importer rules before deciding whether migration guidance is needed. Keep warnings for effective changes while allowing equivalent upgrades to run cleanly.
Adopt the shared joint DOF resolver added on main while preserving migration-aware velocity and limit fallback handling for ordinary, merged, and D6 joints.
Remove explicit negative warning assertions from schema fallback tests. The suite-wide strict warning policy now detects regressions while positive assertions remain for warnings that are required behavior.
Rely on USD schema definitions for authoritative fallbacks instead of
maintaining a copied catalog. Keep unregistered resolvers functional through
their compatibility defaults after importer defaults.

Exercise the composed behavior in functional tests and reserve migration
warning assertions for focused compatibility coverage.
Introduce an opt-in resolution facade that shares schema ownership,
fallbacks, priority, and transformations between PXR and populated
scene consumers. Preserve the legacy resolver path while cataloging
built-in Newton, PhysX, and MuJoCo schema defaults.
Document the experimental composed-resolution API in the changelog and
user guide. Reject unknown logical keys and tailor missing-fallback
errors to source-neutral consumers so integration mistakes fail
clearly.
Add a regression for per-axis PhysX D6 limit gain lookup and record
the user-visible correction in the changelog.
Describe non-PXR consumers without tying the resolver contract or rollout
to a specific downstream integration.
Replace the opaque factory with one typed SchemaResolution object used by
both PXR and mapping sources. Route schema_resolvers through the same
private compatibility policy so setup does not change import semantics.
Treat a key present in the source-neutral defaults mapping as an explicit importer choice even when its value is None. This lets importers defer to their builder defaults without falling through to compatibility defaults stored on resolver definitions.
Let source-neutral adapters supply registered schema metadata at resolution time while keeping the PXR registry authoritative for USD imports. Remove the copied fallback catalog so unregistered schemas retain only their compatibility behavior.
@mzamoramora-nvidia

Copy link
Copy Markdown
Member

Superseded by #3984

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.

3 participants