ekf2: migrate mag yaw fusion to SymForce

This commit is contained in:
bresch 2022-10-17 16:36:25 +02:00 committed by Mathieu Bresciani
parent a41b6f416e
commit 10f9ac148f
1 changed files with 7 additions and 128 deletions

View File

@ -45,6 +45,8 @@
#include "python/ekf_derivation/generated/compute_mag_innov_innov_var_and_hx.h"
#include "python/ekf_derivation/generated/compute_mag_y_innov_var_and_h.h"
#include "python/ekf_derivation/generated/compute_mag_z_innov_var_and_h.h"
#include "python/ekf_derivation/generated/compute_yaw_321_innov_var_and_h.h"
#include "python/ekf_derivation/generated/compute_yaw_312_innov_var_and_h.h"
#include <mathlib/mathlib.h>
@ -225,131 +227,13 @@ bool Ekf::fuseYaw(const float innovation, const float variance, estimator_aid_so
{
aid_src_status.innovation = innovation;
// assign intermediate state variables
const float q0 = _state.quat_nominal(0);
const float q1 = _state.quat_nominal(1);
const float q2 = _state.quat_nominal(2);
const float q3 = _state.quat_nominal(3);
Vector24f H_YAW;
// choose A or B computational paths to avoid singularity in derivation at +-90 degrees yaw
bool canUseA = false;
bool canUseB = false;
float SA0;
float SA1;
float SA2;
float SA3;
float SA4;
float SA5_inv;
float SB0;
float SB1;
float SB2;
float SB3;
float SB4;
float SB5_inv;
const bool fuse_yaw_321 = shouldUse321RotationSequence(_R_to_earth);
if (fuse_yaw_321) {
// calculate 321 yaw observation matrix
SA0 = 2*q3;
SA1 = 2*q2;
SA2 = SA0*q0 + SA1*q1;
SA3 = sq(q0) + sq(q1) - sq(q2) - sq(q3);
SB0 = 2*q0;
SB1 = 2*q1;
SB2 = SB0*q3 + SB1*q2;
SB4 = sq(q0) + sq(q1) - sq(q2) - sq(q3);
if (shouldUse321RotationSequence(_R_to_earth)) {
sym::ComputeYaw321InnovVarAndH(getStateAtFusionHorizonAsVector(), P, variance, FLT_EPSILON, &aid_src_status.innovation_variance, &H_YAW);
} else {
// calculate 312 yaw observation matrix
SA0 = 2*q3;
SA1 = 2*q2;
SA2 = SA0*q0 - SA1*q1;
SA3 = sq(q0) - sq(q1) + sq(q2) - sq(q3);
SB0 = 2*q0;
SB1 = 2*q1;
SB2 = -SB0*q3 + SB1*q2;
SB4 = -sq(q0) + sq(q1) - sq(q2) + sq(q3);
}
if (sq(SA3) > 1e-6f) {
SA4 = 1.f/sq(SA3);
SA5_inv = sq(SA2)*SA4 + 1.f;
canUseA = fabsf(SA5_inv) > 1e-6f;
}
if (sq(SB2) > 1e-6f) {
SB3 = 1.f/sq(SB2);
SB5_inv = SB3*sq(SB4) + 1.f;
canUseB = fabsf(SB5_inv) > 1e-6f;
}
Vector4f H_YAW;
if (canUseA && (!canUseB || fabsf(SA5_inv) >= fabsf(SB5_inv))) {
const float SA5 = 1.f/SA5_inv;
const float SA6 = 1.f/SA3;
const float SA7 = SA2*SA4;
const float SA8 = 2*SA7;
const float SA9 = 2*SA6;
if (fuse_yaw_321) {
// calculate 321 yaw observation matrix
H_YAW(0) = SA5*(SA0*SA6 - SA8*q0);
H_YAW(1) = SA5*(SA1*SA6 - SA8*q1);
H_YAW(2) = SA5*(SA1*SA7 + SA9*q1);
H_YAW(3) = SA5*(SA0*SA7 + SA9*q0);
} else {
// calculate 312 yaw observation matrix
H_YAW(0) = SA5*(SA0*SA6 - SA8*q0);
H_YAW(1) = SA5*(-SA1*SA6 + SA8*q1);
H_YAW(2) = SA5*(-SA1*SA7 - SA9*q1);
H_YAW(3) = SA5*(SA0*SA7 + SA9*q0);
}
} else if (canUseB && (!canUseA || fabsf(SB5_inv) > fabsf(SA5_inv))) {
const float SB5 = 1.f/SB5_inv;
const float SB6 = 1.f/SB2;
const float SB7 = SB3*SB4;
const float SB8 = 2*SB7;
const float SB9 = 2*SB6;
if (fuse_yaw_321) {
// calculate 321 yaw observation matrix
H_YAW(0) = -SB5*(SB0*SB6 - SB8*q3);
H_YAW(1) = -SB5*(SB1*SB6 - SB8*q2);
H_YAW(2) = -SB5*(-SB1*SB7 - SB9*q2);
H_YAW(3) = -SB5*(-SB0*SB7 - SB9*q3);
} else {
// calculate 312 yaw observation matrix
H_YAW(0) = -SB5*(-SB0*SB6 + SB8*q3);
H_YAW(1) = -SB5*(SB1*SB6 - SB8*q2);
H_YAW(2) = -SB5*(-SB1*SB7 - SB9*q2);
H_YAW(3) = -SB5*(SB0*SB7 + SB9*q3);
}
} else {
return false;
}
// Calculate innovation variance and Kalman gains, taking advantage of the fact that only the first 4 elements in H are non zero
// calculate the innovation variance
aid_src_status.innovation_variance = variance;
for (unsigned row = 0; row <= 3; row++) {
float tmp = 0.0f;
for (uint8_t col = 0; col <= 3; col++) {
tmp += P(row, col) * H_YAW(col);
}
aid_src_status.innovation_variance += H_YAW(row) * tmp;
sym::ComputeYaw312InnovVarAndH(getStateAtFusionHorizonAsVector(), P, variance, FLT_EPSILON, &aid_src_status.innovation_variance, &H_YAW);
}
float heading_innov_var_inv = 0.f;
@ -427,12 +311,7 @@ bool Ekf::fuseYaw(const float innovation, const float variance, estimator_aid_so
_innov_check_fail_status.flags.reject_yaw = false;
}
// copy observation jacobian
SparseVector24f<0,1,2,3> Hfusion;
Hfusion.at<0>() = H_YAW(0);
Hfusion.at<1>() = H_YAW(1);
Hfusion.at<2>() = H_YAW(2);
Hfusion.at<3>() = H_YAW(3);
SparseVector24f<0,1,2,3> Hfusion(H_YAW);
if (measurementUpdate(Kfusion, Hfusion, aid_src_status.innovation)) {