fix: remove planar half-space correction for on-plane distance=0 constraints #38

Open
forbes wants to merge 2 commits from fix/planar-halfspace-drag-flip into main
Owner

When a PlanarConstraint has distance=0 (point already on the plane), the half-space tracker used dot(z_i, z_j) as its indicator with a correction function that reflects the body through the plane.

When combined with a Cylindrical joint, legitimate rotation about the cylinder axis causes the body's planar face normal to rotate. After ~90 degrees, the dot product crosses zero, triggering the correction which teleports the body to the other side of the plane. The C++ validator then rejects every subsequent drag step as 'flipped orientation' (>91 degrees).

Fix: Return a tracking-only HalfSpace (no correction_fn) when the point is already on the plane. This matches the pattern used by Cylindrical, Revolute, and Concentric half-space trackers. The cross-product residuals in PlanarConstraint already enforce normal alignment via the solver, so the correction is redundant and harmful during drag.

All 286 solver tests pass.

When a PlanarConstraint has distance=0 (point already on the plane), the half-space tracker used dot(z_i, z_j) as its indicator with a correction function that reflects the body through the plane. When combined with a Cylindrical joint, legitimate rotation about the cylinder axis causes the body's planar face normal to rotate. After ~90 degrees, the dot product crosses zero, triggering the correction which teleports the body to the other side of the plane. The C++ validator then rejects every subsequent drag step as 'flipped orientation' (>91 degrees). **Fix:** Return a tracking-only HalfSpace (no correction_fn) when the point is already on the plane. This matches the pattern used by Cylindrical, Revolute, and Concentric half-space trackers. The cross-product residuals in PlanarConstraint already enforce normal alignment via the solver, so the correction is redundant and harmful during drag. All 286 solver tests pass.
forbes added 1 commit 2026-02-26 13:46:30 +00:00
When a PlanarConstraint has distance=0 (point already on plane), the
half-space tracker was using dot(z_i, z_j) as its indicator and providing
a correction function that reflects the body through the plane.

When combined with a Cylindrical joint, legitimate rotation about the
cylinder axis causes the body's planar face normal to rotate. After ~90
degrees, the dot product crosses zero, triggering the correction which
teleports the body to the other side of the plane. The C++ validator
then rejects every subsequent drag step as 'flipped orientation'.

Fix: return a tracking-only HalfSpace (no correction_fn) when the point
is already on the plane. This matches the pattern used by Cylindrical,
Revolute, and Concentric half-space trackers. The cross-product residuals
in PlanarConstraint already enforce normal alignment via the solver
itself, so the correction is redundant and harmful during drag.
forbes force-pushed fix/planar-halfspace-drag-flip from fa34dc0d49 to 85a607228d 2026-02-26 15:03:41 +00:00 Compare
forbes added 1 commit 2026-02-26 17:07:01 +00:00
PlanarConstraint's point-in-plane residual used a body-attached normal
(z_j) that rotates with body_j. When combined with CylindricalConstraint,
which allows rotation about the shared axis, the plane normal tilts
during Newton iteration. This allows the body to drift along the cylinder
axis while technically satisfying the rotated distance residual.

Fix: snapshot the world-frame normal at system-build time (as Const
nodes) and use it in the distance residual. The cross-product residuals
still use body-attached normals to enforce parallelism. Only the
distance residual needs the fixed reference direction.

Works for any offset value: (p_i - p_j) · z_ref - offset = 0.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/planar-halfspace-drag-flip:fix/planar-halfspace-drag-flip
git checkout fix/planar-halfspace-drag-flip
Sign in to join this conversation.