fix: clamp acos argument in Rotation3::euler_angles_ordered to avoid NaN (#1481)#1611
Open
teddytennant wants to merge 1 commit into
Open
Conversation
Floating-point rounding in the chained matrix products computing `o_t` can push `o_t.m33` slightly outside `[-1, 1]` (e.g. -1.0000000000000002 for a near-nadir orientation), so `acos` returns NaN and silently poisons the whole returned angle array. Clamp the argument into the valid range before calling `acos`, mirroring the existing handling in `Matrix::angle`. Fixes dimforge#1481.
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.
What
Rotation3::euler_angles_orderedcomputes the middle Euler angle asangles[1] = o_t.m33.acos(). This clampso_t.m33into[-1, 1]before callingacos:Why
For a valid rotation matrix
m33lies in[-1, 1], but floating-point rounding in the chained matrix productso_t = c * self.matrix() * (c.transpose() * r1l)can pushm33slightly outside that range (e.g.-1.0000000000000002for a near-nadir orientation).acosof an out-of-domain argument returnsNaN, which silently poisons the returned angle array.This mirrors the existing precedent in
Matrix::angle, which already clamps the cosine viasimd_clamp(-one, one)before callingacos.Testing
Added a regression test
euler_angles_ordered_issue_1481intests/geometry/rotation.rsusing a unit quaternion whose rotation matrix hasm33just below-1. Before the fix the middle angle comes back asNaN([2.677945044588987, NaN, 0.0]); after the fix all three angles are finite.cargo fmt --checkandcargo clippyare both clean (no new warnings introduced by this change).Fixes #1481.