Fix Newton contact buffer sizing when solver naconmax exceeds the collision pipeline estimate - #6850
Conversation
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.
Greptile SummaryThe PR fixes Newton contact-buffer initialization when a solver requires more contacts than the collision pipeline estimates.
Confidence Score: 5/5The 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
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
Reviews (1): Last reviewed commit: "fix(newton): size RSL-RL contact buffer ..." | Re-trigger Greptile |
There was a problem hiding this comment.
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.
_contactsremains aContactsinstance, 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.
Description
Isaac-Velocity-Rough-G1withpresets=newton_mjwarpand--rl_library rsl_rlcrashes atsim.reset():Root cause. On the
use_mujoco_contacts=False(RSL-RL sensor) path, the base_initialize_contactsin
newton_manager.pysizesNewtonManager._contactsfrom the collision pipeline alone and neverconsults the solver's
naconmax._update_sensors -> solver.update_contacts()then requiresbuffer >= naconmax, so3840 < 25600raises. Themjwarp_manager.pyoverride already sizes tosolver.get_max_contact_count()for theuse_mujoco_contacts=Truepath; the base path was missingthe same logic. This is a buffer-sizing bug, not a Newton/mujoco_warp version regression.
Fix. Grow
_contactstosolver.get_max_contact_count()when the solver demands more. The bufferonly 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
naconmaxerror.To confirm the larger buffer is genuinely populated rather than silently empty,
CollisionPipeline.collideand the Newton contact sensor were instrumented and compared against an unpatched control run made legal
by lowering
nconmax:rigid_contact_countContact 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.0workaround was ruled out:naconmaxstayed at 25600 and the crash was unchanged.Known limitation. This sizes the buffer to
naconmaxonly. Wherenaconmaxis smaller than the numberof 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
Screenshots
N/A
Checklist
pre-commitchecks with./isaaclab.sh --formatsource/<pkg>/changelog.d/for every touched package (do not editCHANGELOG.rstor bumpextension.toml— CI handles that)CONTRIBUTORS.mdor my name already exists thereNote 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.