Skip to content

Fix Newton contact buffer sizing when solver naconmax exceeds the collision pipeline estimate - #6850

Open
fatimaanes wants to merge 2 commits into
isaac-sim:developfrom
fatimaanes:fix/newton-rslrl-contact-buffer-naconmax
Open

Fix Newton contact buffer sizing when solver naconmax exceeds the collision pipeline estimate#6850
fatimaanes wants to merge 2 commits into
isaac-sim:developfrom
fatimaanes:fix/newton-rslrl-contact-buffer-naconmax

Conversation

@fatimaanes

Copy link
Copy Markdown
Collaborator

Description

Isaac-Velocity-Rough-G1 with presets=newton_mjwarp and --rl_library rsl_rl crashes at sim.reset():

ValueError: MuJoCo naconmax (25600) exceeds contacts.rigid_contact_max (3840).
Create Contacts with at least rigid_contact_max=25600.
naconmax          = nconmax(100) x num_envs(256) = 25600   solver internal buffer
rigid_contact_max = ~15/env auto-estimate x 256  = 3840    collision-pipeline buffer

Root cause. On the use_mujoco_contacts=False (RSL-RL sensor) path, the base _initialize_contacts
in newton_manager.py sizes NewtonManager._contacts from the collision pipeline alone and never
consults the solver's naconmax. _update_sensors -> solver.update_contacts() then requires
buffer >= naconmax, so 3840 < 25600 raises. The mjwarp_manager.py override already sizes to
solver.get_max_contact_count() for the use_mujoco_contacts=True path; the base path was missing
the same logic. This is a buffer-sizing bug, not a Newton/mujoco_warp version regression.

Fix. Grow _contacts to solver.get_max_contact_count() when the solver demands more. The buffer
only grows, so the allocation is unchanged wherever the pipeline estimate is already large enough.

No linked issue.

Verification

Reproduced and fixed on an NVIDIA L40 at 256 envs with the exact failing invocation. Before: crash at
iteration 0. After: the run completes its iterations with no naconmax error.

To confirm the larger buffer is genuinely populated rather than silently empty, CollisionPipeline.collide
and the Newton contact sensor were instrumented and compared against an unpatched control run made legal
by lowering nconmax:

at reset unpatched (buffer 3840) patched (buffer 25600)
rigid_contact_count 4535 (118% of capacity) 4530 (17.7%)
bodies reporting >1 N 421 421
max contact force 2369.5 N 2432.3 N

Contact counts and sensor forces track the control run, so the patch changes buffer capacity only, not
contact generation. Note that the unpatched buffer was itself overflowing at reset (4535 contacts into
3840 slots), so contacts were being dropped even in configurations where the guard does not fire.

A config-level gap=0.0 workaround was ruled out: naconmax stayed at 25600 and the crash was unchanged.

Known limitation. This sizes the buffer to naconmax only. Where naconmax is smaller than the number
of contacts the pipeline actually generates, the pipeline's own ~15/env auto-estimate can still
under-allocate. That pre-existing sizing question is out of scope here.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots

N/A

Checklist

  • I have read and understood the contribution guidelines
  • 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 added a changelog fragment under source/<pkg>/changelog.d/ for every touched package (do not edit CHANGELOG.rst or bump extension.toml — CI handles that)
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

Note on the two unchecked boxes: no documentation pages are affected, and the fix is verified by the
instrumented before/after runs above rather than by an added unit test — happy to add a regression test
if maintainers would like one.

Base _initialize_contacts sized NewtonManager._contacts from the collision
pipeline alone (rigid_contact_max = ~15/env auto-estimate = 3840 at 256 envs)
and never consulted the solver's naconmax (nconmax=100 x 256 = 25600). On the
use_mujoco_contacts=False (RSL-RL) path, _update_sensors ->
solver.update_contacts() requires buffer >= naconmax, so Isaac-Velocity-Rough-G1
with presets=newton_mjwarp crashed at sim.reset():

  ValueError: MuJoCo naconmax (25600) exceeds contacts.rigid_contact_max (3840).

Grow _contacts to solver.get_max_contact_count() when the solver demands more,
mirroring the existing mjwarp_manager.py override for the
use_mujoco_contacts=True path. The buffer only grows; the allocation is
unchanged wherever the pipeline estimate is already large enough.

Verified on an NVIDIA L40 at 256 envs. Instrumenting CollisionPipeline.collide
and the contact sensor shows the grown buffer holds the same contacts as an
unpatched control run (4530 vs 4535 rigid contacts at reset, 421 bodies
reporting >1 N in both), and the failing rsl_rl invocation runs to completion
with no naconmax error. The pipeline emits ~4.5k contacts at reset, so the
3840-slot buffer was overflowing at 118% fill and silently dropping contacts
even where the guard did not fire. A config-level gap=0.0 was ruled out:
naconmax stayed at 25600 and the crash was unchanged.
@fatimaanes
fatimaanes requested a review from a team August 2, 2026 06:56
@github-actions github-actions Bot added bug Something isn't working isaac-lab Related to Isaac Lab team labels Aug 2, 2026
@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR fixes Newton contact-buffer initialization when a solver requires more contacts than the collision pipeline estimates.

  • Queries the active solver for its maximum contact count.
  • Reallocates the contact buffer only when additional capacity is required.
  • Adds a changelog fragment documenting the reset-time failure and corrected behavior.

Confidence Score: 5/5

The PR appears safe to merge, with the contact buffer enlarged only when the active solver requires greater capacity.

The changed initialization follows the established MJWarp contact-allocation pattern, preserves the model-requested contact attributes, and leaves configurations with an already sufficient pipeline buffer unchanged.

Important Files Changed

Filename Overview
source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py Grows pipeline-created contact storage to the solver-reported maximum while preserving existing sizing when already sufficient; no actionable defect was identified.
source/isaaclab_newton/changelog.d/fanes-rslrl-contact-buffer-naconmax.rst Accurately documents the affected path, reset-time error, and solver-aware sizing fix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Initialize Newton contacts] --> B[Create collision-pipeline contacts]
    B --> C{Solver exposes maximum contact count?}
    C -- No --> D[Keep pipeline-sized buffer]
    C -- Yes --> E{Solver maximum exceeds buffer?}
    E -- No --> D
    E -- Yes --> F[Allocate larger Contacts buffer]
    D --> G[Collision and sensor updates]
    F --> G
Loading

Reviews (1): Last reviewed commit: "fix(newton): size RSL-RL contact buffer ..." | Re-trigger Greptile

@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 change grow-sizes the base Newton collision contact buffer from solver.get_max_contact_count() when the solver requirement exceeds the pipeline estimate, addressing the use_mujoco_contacts=False reset failure. The package changelog fragment is present and correctly categorized.

  • Design and architecture: The solver-capability check is confined to contact initialization and preserves the collision pipeline as the producer. It mirrors the existing internal-contact sizing behavior without changing manager construction or ownership. The duplicated sizing policy is a minor maintenance tradeoff but does not require pre-merge action.
  • API: No public symbols, signatures, or return types change. _contacts remains a Contacts instance, allocation is grow-only, and configurations whose pipeline estimate already satisfies the solver requirement retain their existing allocation.
  • Implementation: The changed path compares the solver maximum against rigid_contact_max, reallocates only when necessary, and preserves the model-requested contact attributes. The proposed soft-contact concern is not established by the supplied context: there is no evidence that a solver entering this growth branch supports or requires nonzero pipeline soft-contact capacity.

No blocking issues. No inline issue met the actionable-evidence threshold; the assessment above records the review feedback.

Automated review; human maintainers own approval decisions.

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

Labels

bug Something isn't working isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants