Fix CCD narrowphase reporting margin-biased contact distances#1188
Merged
adenzler-nvidia merged 1 commit intoFeb 26, 2026
Merged
Conversation
The CCD (GJK/EPA) path inflates each geom by 0.5 * pair_margin in the support function, but the returned dist was never corrected back to the true surface-to-surface distance. This caused dist to be off by pair_margin compared to the primitive narrowphase, breaking the constraint pipeline which expects un-inflated distances. Add `dist += margin` after the early-exit check in eval_ccd_write_contact to restore consistency with the primitive path.
071cfc4 to
1d10b7d
Compare
5 tasks
thowell
approved these changes
Feb 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
0.5 * pair_marginin thesupport()function, but the returneddistwas never corrected back to the true surface-to-surface distance. This causeddistto be off bypair_margincompared to the primitive narrowphase, breaking the constraint pipeline (pos = dist - includemargin) which expects un-inflated distances.dist += marginafter the early-exit check ineval_ccd_write_contactto restore consistency with the primitive narrowphase path.test_ccd_margin_distthat verifies CCD contact distances match classic MuJoCo for two boxes separated by 0.05 m withmargin=0.1, gap=0.1on each geom.Details
The
support()function incollision_gjk.pyinflates shapes by0.5 * geom.margin(line 189-190). Both geoms are set tomargin = pair_marginbefore CCD runs, so the total inflation ispair_margin. The GJK/EPA distance is therefore relative to the inflated geometry, not the true surfaces.The primitive narrowphase (e.g.
sphere_sphere,box_box) reports true geometric distances without margin. The constraint pipeline then checkspos = dist - includemargin < 0to activate constraints. Without this fix, CCD pairs activate constraints too early because theirdistis already margin-biased.Example: Two boxes 0.05 m apart with
pair_margin = 0.2:dist = 0.05(correct)dist = -0.15(wrong, off bypair_margin)dist = 0.05(correct)Test plan
test_ccd_margin_distpasses — CCD dist matches classic MuJoCocollision_driver_testtests pass