Conversation
Fixes the transient angular velocity spike reported in Field-Robotics-Japan#155: after the accumulated rotation passes a multiple of 2*pi, the angular velocity goes wild for one sample. Quaternions double-cover rotations -- q and -q describe the same attitude -- and consecutive transform.rotation samples can land on opposite hemispheres of that cover. The delta quaternion then has w < 0, and ToAngleAxis reports the LONG way around: ~(360 deg - delta) about the inverted axis instead of the true small increment. Divided by dt this shows up as a one-sample angular velocity spike of roughly 2*pi/dt (thousands of deg/s), exactly at full-turn boundaries. Negate the delta quaternion when w < 0 (a no-op as a rotation) so ToAngleAxis always measures the short arc. The delta-to-rate math moves into a public static AngularVelocityBetween() so it is unit testable; ImuAngularVelocityTests covers the plain small step, the issue's full-turn boundary crossing (AngleAxis(359) -> AngleAxis(1), which spiked before the fix), and the negated-representation equivalence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Fixes #155
Symptom
The moment an object carrying the IMU passes a multiple of 2π of
accumulated rotation (i.e. every full turn), the reported angular
velocity goes wild for exactly one sample — roughly 2π/dt, which is
about 7200 deg/s at a 50 Hz update rate.
Root cause
Quaternions double-cover rotations: q and −q describe the same
attitude. Consecutive
transform.rotationsamples can land on oppositehemispheres of that cover, and when they do, the delta
Quaternion.Inverse(last) * currentcomes out with w < 0.ToAngleAxison such a quaternion reports the long way around —~(360° − δ) about the inverted axis instead of the true small increment
δ. Divided by dt, that is the one-sample spike, and it lands exactly at
full-turn boundaries.
Fix
before calling
ToAngleAxis(a no-op as a rotation), so the shortarc is always measured.
extracted into
public static IMUSensor.AngularVelocityBetween( previous, current, dt), called fromUpdateSensorOnce(). Behaviouris otherwise unchanged.
Tests (EditMode:
Tests/Editor/ImuAngularVelocityTests.cs)SmallStep_ReportsTheRotationRateFullTurnBoundary_DoesNotSpikeAngleAxis(359°) → AngleAxis(1°)) — the exact scenario of this issueNegatedRepresentation_IsTheSameRotationVerified with the Unity Test Runner (6000.3.21f1, batchmode, EditMode):
3/3 pass with the fix; with the fold removed, exactly the two boundary
tests fail while the plain-step test still passes, so the tests isolate
this specific defect.
Impact
All downstream consumers of the angular velocity. Attitude-integrating
consumers (e.g. an AHRS) are barely affected, because rotating by
(2π − δ) about the inverted axis is almost the same attitude as
rotating by δ about the true axis — but anything using the raw rate
(rate logging, rate sanity checks that drop the sample, controllers)
sees a real glitch once per full turn.