|
T gx{ T(2) * bz * qz * f4 + (T(2) * bx * qy + T(2) * bz * qw) * f5 + (T(2) * bx * qz - T(2) * bz * qw) * f6 }; |
|
T gy{ (-T(4) * bx * qy - T(2) * bz * qw) * f4 + (T(2) * bx * qx + T(2) * bz * qz) * f5 + (T(2) * bx * qw + T(2) * bz * qy) * f6 }; |
|
T gz{ (-T(4) * bx * qz + T(2) * bz * qx) * f4 + (-T(2) * bx * qw + T(2) * bz * qy) * f5 + T(2) * bx * qx * f6 }; |
|
|
|
T invNorm{ SafeInvSqrt(gw * gw + gx * gx + gy * gy + gz * gz) }; |
|
return math::Quaternion<T>{ gw * invNorm, gx * invNorm, gy * invNorm, gz * invNorm }; |
|
} |
|
|
|
template<typename T, AhrsMode M> |
|
void AhrsFilter<T, M>::IntegrateGyro(const math::Vector3<T>& gyro) |
|
{ |
|
math::Quaternion<T> qGyro{ T{}, gyro.at(0, 0), gyro.at(1, 0), gyro.at(2, 0) }; |
|
math::Quaternion<T> qDot{ q * qGyro }; |
|
q.w += T(0.5) * qDot.w * Ts; |
|
q.x += T(0.5) * qDot.x * Ts; |
|
q.y += T(0.5) * qDot.y * Ts; |
|
q.z += T(0.5) * qDot.z * Ts; |
|
q.Normalize(); |
|
} |
|
|
|
template<typename T, AhrsMode M> |
|
void AhrsFilter<T, M>::MahonyStep(const math::Vector3<T>& gyro, const math::Vector3<T>& e) |
|
{ |
|
integralFb.at(0, 0) += Ki * e.at(0, 0) * Ts; |
|
integralFb.at(1, 0) += Ki * e.at(1, 0) * Ts; |
|
integralFb.at(2, 0) += Ki * e.at(2, 0) * Ts; |
|
T wx{ gyro.at(0, 0) + Kp * e.at(0, 0) + integralFb.at(0, 0) }; |
|
T wy{ gyro.at(1, 0) + Kp * e.at(1, 0) + integralFb.at(1, 0) }; |
|
T wz{ gyro.at(2, 0) + Kp * e.at(2, 0) + integralFb.at(2, 0) }; |
|
math::Quaternion<T> qGyro{ T{}, wx, wy, wz }; |
|
math::Quaternion<T> qDot{ q * qGyro }; |
|
q.w += T(0.5) * qDot.w * Ts; |
|
q.x += T(0.5) * qDot.x * Ts; |
Audit finding
AUD-0172f479320d805a1f9f35ebe4afaaeeded48913a94Problem
GradientMag()contains two Jacobian terms inconsistent with its own sixth magnetic residual. Forf6 = 2 bx (qw qy + qx qz) + bz (1 - 2 qx^2 - 2 qy^2) - mz,correct derivatives include
df6/dqx = 2 bx qz - 4 bz qxanddf6/dqy = 2 bx qw - 4 bz qy. The implementation uses different terms.Source:
numerical-toolbox-cpp/numerical/filters/active/AhrsMadgwickMahony.hpp
Lines 149 to 181 in 2f47932
Axis-aligned magnetic-field tests mask the error; arbitrary tilted MARG updates follow the wrong descent direction.
Acceptance criteria