-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial cut on full quaternion IMU conversion #2894
Changes from 1 commit
ad5fdc0
765495f
2ab598a
5d9926d
2fe435e
22d0888
8561b57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,6 +83,8 @@ STATIC_FASTRAM float smallAngleCosZ; | |
|
||
STATIC_FASTRAM bool isAccelUpdatedAtLeastOnce; | ||
|
||
FASTRAM fpMat3_t magDeclinationRMat; // Rotation matrix for magnetic declination correction (Earth frame) | ||
|
||
FASTRAM fpQuaternion_t orientation; | ||
FASTRAM attitudeEulerAngles_t attitude; // absolute angle inclination in multiple of 0.1 degree 180 deg = 1800 | ||
STATIC_FASTRAM_UNIT_TESTED float rMat[3][3]; | ||
|
@@ -148,10 +150,21 @@ void imuInit(void) | |
isAccelUpdatedAtLeastOnce = false; | ||
gpsHeadingInitialized = false; | ||
|
||
// Create magnetic declination matrix | ||
const int deg = compassConfig()->mag_declination / 100; | ||
const int min = compassConfig()->mag_declination % 100; | ||
imuSetMagneticDeclination(deg + min / 60.0f); | ||
|
||
quaternionInitUnit(&orientation); | ||
imuComputeRotationMatrix(); | ||
} | ||
|
||
void imuSetMagneticDeclination(float declinationDeg) | ||
{ | ||
fpAxisAngle_t axisAngle = { .axis = { .v = { 0.0f, 0.0f, 1.0f } }, .angle = DEGREES_TO_RADIANS(declinationDeg) }; | ||
rotationMatrixFromAxisAngle(&magDeclinationRMat, &axisAngle); | ||
} | ||
|
||
void imuTransformVectorBodyToEarth(fpVector3_t * v) | ||
{ | ||
// From body frame to earth frame | ||
|
@@ -277,6 +290,9 @@ static void imuMahonyAHRSupdate(float dt, const fpVector3_t * gyroBF, const fpVe | |
// Ignore magnetic inclination | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (this is projection into XY (or NE) plane |
||
vMag.z = 0.0f; | ||
|
||
// Apply magnetic declination correction | ||
rotationMatrixRotateVector(&vMag, &vMag, &magDeclinationRMat); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be easier (and actually cleaner) to use true north vector ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ledvinap you're a genius! It didn't occur to me that I can just figure our true North vector from declination 👍 |
||
|
||
// Normalize to unit vector | ||
vectorNormalize(&vMag, &vMag); | ||
|
||
|
@@ -404,7 +420,7 @@ STATIC_UNIT_TESTED void imuUpdateEulerAngles(void) | |
/* Compute pitch/roll angles */ | ||
attitude.values.roll = RADIANS_TO_DECIDEGREES(atan2_approx(rMat[2][1], rMat[2][2])); | ||
attitude.values.pitch = RADIANS_TO_DECIDEGREES((0.5f * M_PIf) - acos_approx(-rMat[2][0])); | ||
attitude.values.yaw = RADIANS_TO_DECIDEGREES(-atan2_approx(rMat[1][0], rMat[0][0])) + mag.magneticDeclination; | ||
attitude.values.yaw = RADIANS_TO_DECIDEGREES(-atan2_approx(rMat[1][0], rMat[0][0])); | ||
|
||
if (attitude.values.yaw < 0) | ||
attitude.values.yaw += 3600; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3x3 and 3x4 matrix typedef maybe be better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intend to eventually phase out
rMat
so I don't want to touch it at all.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes ...
converting quaternion to matrix + matrix multiplication is fastest way to do quaternion rotation, even when transforming single vector.
In imu, conversion is amortized, so using 'temporary' matrix is nice and quite cheap optimization.
Another use of mat34 is sensor calibration - it can represent all calibration transformations (sensor alignment, axis scaling, offset, cross-axis sensitivity) in compact and mathematically sound way ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, worth doing than. Will look into it in a separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just keep this option open,in can be implemented later ...