Skip to content

Add Newton SDF collision schema config#5926

Merged
ooctipus merged 2 commits into
isaac-sim:developfrom
maxkra15:max/newton-sdf-collision-api
Jun 3, 2026
Merged

Add Newton SDF collision schema config#5926
ooctipus merged 2 commits into
isaac-sim:developfrom
maxkra15:max/newton-sdf-collision-api

Conversation

@maxkra15
Copy link
Copy Markdown

@maxkra15 maxkra15 commented Jun 2, 2026

Description

Adds a Newton SDF collision schema config surface to IsaacLab.

This PR introduces NewtonSDFCollisionPropertiesCfg, allowing IsaacLab users to author Newton SDF and hydroelastic collision
USD attributes from Python configs. The new config writes NewtonSDFCollisionAPI metadata and the corresponding newton:*
attributes for SDF resolution, narrow band, voxel size, texture format, padding, hydroelastic enablement, and hydroelastic
stiffness.

The change also wires the new config through the existing public export paths:

  • isaaclab_newton.sim.schemas
  • isaaclab.sim
  • isaaclab.sim.schemas
  • isaaclab.sim.schemas.schemas_cfg

Documentation, shim tests, Newton schema tests, and changelog fragments are included.

Type of change

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

Screenshots

Not applicable.

Checklist

  • I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/
    contributing.html)
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

Validation

Ran the following checks locally:

  • git diff --check
  • ruff check
  • ruff format --check
  • pre-commit run --files ...
  • python3 -m py_compile ...
  • pytest source/isaaclab/test/sim/test_schemas_shim.py
    • 145 passed
  • pytest source/isaaclab_newton/test/sim/test_newton_schemas.py
    • 17 passed

Signed-off-by: Maximilian Krause <maximiliank@nvidia.com>
@maxkra15 maxkra15 requested a review from ooctipus June 2, 2026 20:32
@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team labels Jun 2, 2026
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

Review: Add Newton SDF collision schema config

Overall this is a clean, well-structured addition. The new NewtonSDFCollisionPropertiesCfg integrates smoothly into the existing schema hierarchy and the shim/export paths are wired correctly. Tests and docs are comprehensive.

Findings

1. Minor robustness concern in test helper _has_authored_api_schema (low severity)

In test_newton_schemas.py, the helper iterates over ("explicitItems", "prependedItems", "appendedItems", "addedItems") via getattr. If the SdfListOp variant returned by GetMetadata("apiSchemas") doesn't have one of these attributes, an AttributeError would be raised. Consider guarding with hasattr:

return any(
    schema_name in getattr(api_schemas, item_list, [])
    for item_list in ("explicitItems", "prependedItems", "appendedItems", "addedItems")
)

2. No bounds validation on physical fields (informational)

Fields like sdf_max_resolution, sdf_target_voxel_size, sdf_padding, and hydroelastic_stiffness accept any numeric value including negatives or zero. While this is consistent with the existing PropertiesCfg pattern in the codebase (validation happens at the Newton runtime level), consider documenting acceptable ranges in the docstrings — especially since sdf_max_resolution "must be divisible by 8" per the docstring but this constraint isn't enforced.

3. sdf_max_resolution divisibility-by-8 constraint (suggestion)

The docstring states "Newton requires this value to be divisible by 8". A __post_init__ check (or a note that Newton's importer raises if violated) would help users catch misconfigurations early. Not blocking, but would improve DX.

4. Formatting-only changes inflate the diff (nit)

The frozenset({...}) → multi-line reformatting in sim/__init__.py and sim/schemas/__init__.py is style-only (presumably from ruff format). This is fine but makes the diff harder to review. In future PRs, separating formatter-driven changes from functional ones helps reviewers.

5. Test coverage is solid ✓

Three test cases covering:

  • Full attribute write + API schema application
  • Base-only fields don't trigger SDF schema
  • All-None config applies no schema

This covers the key behavioral contract. The shim tests also correctly verify Newton forwarding end-to-end.

Summary

Aspect Status
API design ✅ Clean single-inheritance from NewtonCollisionPropertiesCfg
USD schema wiring _usd_namespace, _usd_applied_schema correctly set
Shim exports ✅ All 4 export paths updated consistently
Type safety Literal type for texture format
Tests ✅ Comprehensive
Docs ✅ RST + hierarchy diagram updated
CI ⏳ Some checks still pending

Verdict: Looks good. The suggestions above are non-blocking improvements. Nice work! 👍


Update (6c6b2fd): Reviewed 1 new commit. This is a documentation-only fix to schema_cfgs.rst that adds the missing NewtonMeshCollisionPropertiesCfg entry to the collision schema hierarchy diagram, making it consistent with the actual class structure. The tree now correctly shows both NewtonMeshCollisionPropertiesCfg and NewtonSDFCollisionPropertiesCfg as children of NewtonCollisionPropertiesCfg. LGTM — no concerns with this change.

@maxkra15 maxkra15 requested review from kellyguo11 and removed request for kellyguo11 June 2, 2026 21:43
@maxkra15 maxkra15 marked this pull request as ready for review June 2, 2026 21:48
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 2, 2026

Greptile Summary

Introduces NewtonSDFCollisionPropertiesCfg, a new @configclass that extends NewtonCollisionPropertiesCfg with eight SDF generation and hydroelastic contact fields (sdf_max_resolution, sdf_narrow_band_inner/outer, sdf_target_voxel_size, sdf_texture_format, sdf_padding, hydroelastic_enabled, hydroelastic_stiffness). The class is wired through all four public export paths and documented with tests, changelogs, and API docs.

  • The new config follows the established per-declaring-class MRO routing: base fields route to NewtonCollisionAPI, SDF-specific fields route to NewtonSDFCollisionAPI, keeping both schemas optional/sparse.
  • sdf_texture_format is a Literal string field routed via safe_set_attribute_on_usd_prim, which creates String-typed USD attributes rather than the Token type typically expected by USD schemas for enumerated choices; whether Newton's importer tolerates this depends on how it reads the attribute.
  • The docstring documents a divisibility-by-8 constraint on sdf_max_resolution but no validation is enforced at construction time.

Confidence Score: 4/5

The PR is safe to merge; all changes are additive and well-isolated. The main area worth a second look is how sdf_texture_format is written to USD.

The implementation is consistent with all existing Newton schema patterns and the shim forwarding is correct across all four export paths. Two non-blocking concerns exist: sdf_texture_format is written via safe_set_attribute_on_usd_prim which creates String-typed attributes for Python str values — if Newton's USD importer expects a Token-typed attribute, this would silently produce the wrong Sdf type (the tests only verify the value, not the type); and the documented divisibility-by-8 requirement on sdf_max_resolution has no enforcement, so an invalid value is not caught until Newton import time.

source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py — specifically the sdf_texture_format field routing and the missing sdf_max_resolution guard.

Important Files Changed

Filename Overview
source/isaaclab_newton/isaaclab_newton/sim/schemas/schemas_cfg.py Adds NewtonSDFCollisionPropertiesCfg with 8 SDF/hydroelastic fields; sdf_texture_format is routed through safe_set_attribute_on_usd_prim which creates String-typed USD attributes, potentially mismatching the Token type expected by NewtonSDFCollisionAPI; no divisibility-by-8 guard for sdf_max_resolution despite the documented constraint.
source/isaaclab_newton/test/sim/test_newton_schemas.py Adds three new SDF collision tests; prim translations updated to avoid overlap; tests verify values but not the USD attribute type (String vs Token) for sdf_texture_format, so a type mismatch would go undetected.
source/isaaclab/test/sim/test_schemas_shim.py Adds NEWTON_FORWARDED_NAMES list with NewtonSDFCollisionPropertiesCfg and three parametrized shim tests covering schemas, sim namespace, and schemas_cfg submodule; correct and complete.
source/isaaclab/isaaclab/sim/schemas/schemas_cfg.py Adds NewtonSDFCollisionPropertiesCfg to _NEWTON_FORWARDS frozenset; straightforward one-line addition consistent with the existing forwarding pattern.
docs/source/overview/core-concepts/schema_cfgs.rst Documents NewtonSDFCollisionPropertiesCfg as the only child of NewtonCollisionPropertiesCfg in the hierarchy tree, omitting NewtonMeshCollisionPropertiesCfg as a sibling, creating an inconsistent tree.
source/isaaclab/isaaclab/sim/init.py Adds NewtonSDFCollisionPropertiesCfg to _NEWTON_FORWARDS and reformats frozenset literals; functional change is correct, purely additive.
source/isaaclab_newton/isaaclab_newton/sim/schemas/init.pyi Adds NewtonSDFCollisionPropertiesCfg to all and re-exports it; consistent with all other cfg exports in the stub.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["NewtonSDFCollisionPropertiesCfg(...)"] --> B["define_collision_properties(prim_path, cfg)"]
    B --> C["UsdPhysics.CollisionAPI.Apply(prim)"]
    B --> D["modify_collision_properties(prim_path, cfg)"]
    D --> E["_apply_namespaced_schemas(prim, cfg, cfg_dict)"]
    E --> F{"Per-declaring-class MRO routing"}
    F -->|"CollisionBaseCfg fields\ncollision_enabled"| G["physics:* namespace\nno schema applied"]
    F -->|"NewtonCollisionPropertiesCfg fields\ncontact_margin, contact_gap"| H["newton:* namespace\nAddAppliedSchema NewtonCollisionAPI"]
    F -->|"NewtonSDFCollisionPropertiesCfg fields\nsdf_max_resolution, sdf_texture_format, etc."| I["newton:* namespace\nAddAppliedSchema NewtonSDFCollisionAPI"]
    H --> J["safe_set_attribute_on_usd_prim\nnewton:contactMargin, newton:contactGap"]
    I --> K["safe_set_attribute_on_usd_prim\nnewton:sdfMaxResolution, newton:sdfTextureFormat\nnewton:hydroelasticEnabled, etc."]
Loading

Reviews (1): Last reviewed commit: "Add Newton SDF collision schema config" | Re-trigger Greptile

Comment on lines +239 to +243
sdf_texture_format: Literal["uint8", "uint16", "float32"] | None = None
"""Subgrid texture storage format for generated SDFs.

Written to ``newton:sdfTextureFormat`` via ``NewtonSDFCollisionAPI``.
"""
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 sdf_texture_format may be authored as a String attribute instead of a Token

safe_set_attribute_on_usd_prim maps Python str values to Sdf.ValueTypeNames.String (see prims.py:371-372). If NewtonSDFCollisionAPI defines newton:sdfTextureFormat as a token-typed attribute (the typical USD convention for enumerated choices), the attribute will be created with the wrong Sdf type when it does not already exist on the prim. Newton's importer may then silently ignore or misread it. The tests only assert prim.GetAttribute("newton:sdfTextureFormat").Get() == "float32", which passes for both String and Token typed attributes and does not catch the mismatch. Consider routing sdf_texture_format via _usd_field_exceptions with an explicit Token-typed write path (as drive_type is handled for UsdPhysics.DriveAPI), or add an assertion on GetTypeName() in the test.

Comment on lines +211 to +218
sdf_max_resolution: int | None = None
"""Maximum SDF grid dimension.

Newton requires this value to be divisible by 8. If
:attr:`sdf_target_voxel_size` is also authored, Newton uses the target voxel
size and ignores this resolution.
Written to ``newton:sdfMaxResolution`` via ``NewtonSDFCollisionAPI``.
"""
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 The docstring explicitly states "Newton requires this value to be divisible by 8", but there is no runtime guard. A caller who passes sdf_max_resolution=65 will silently write an invalid value to USD and only discover the error at Newton import time. A cheap __post_init__ check would surface the problem at config construction time where the stack trace is much more actionable.

Suggested change
sdf_max_resolution: int | None = None
"""Maximum SDF grid dimension.
Newton requires this value to be divisible by 8. If
:attr:`sdf_target_voxel_size` is also authored, Newton uses the target voxel
size and ignores this resolution.
Written to ``newton:sdfMaxResolution`` via ``NewtonSDFCollisionAPI``.
"""
sdf_max_resolution: int | None = None
"""Maximum SDF grid dimension.
Newton requires this value to be divisible by 8. If
:attr:`sdf_target_voxel_size` is also authored, Newton uses the target voxel
size and ignores this resolution.
Written to ``newton:sdfMaxResolution`` via ``NewtonSDFCollisionAPI``.
"""
def __post_init__(self):
if self.sdf_max_resolution is not None and self.sdf_max_resolution % 8 != 0:
raise ValueError(
f"'sdf_max_resolution' must be divisible by 8, got {self.sdf_max_resolution}."
)

Comment thread docs/source/overview/core-concepts/schema_cfgs.rst
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Signed-off-by: ooctipus <zhengyuz@nvidia.com>
@maxkra15 maxkra15 requested a review from AntoineRichard June 3, 2026 07:01
@ooctipus ooctipus merged commit 271f930 into isaac-sim:develop Jun 3, 2026
60 of 61 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