@@ -700,45 +700,104 @@ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_parti
700
700
}
701
701
702
702
template <typename T, bool with_gyro_bias, bool with_accel_bias>
703
- void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_only(Vector3 const & acc_meas, T tempC) {
704
-
705
- // Accel magnitude sanity check
703
+ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_only(
704
+ Vector3 const & acc_meas, T tempC)
705
+ {
706
+ // Sanity check on accel magnitude
706
707
T g_meas = acc_meas.norm ();
707
708
if (std::abs (g_meas - gravity_magnitude_) > T (2.0 * gravity_magnitude_)) {
708
- return ; // reject this update
709
+ return ; // reject
709
710
}
710
711
711
712
const Vector3 v1hat = accelerometer_measurement_func (tempC);
712
713
713
- // Cext: (3 x NX)
714
- Matrix<T, 3 , NX> Cext = Matrix<T, 3 , NX>::Zero ();
715
- // d f_b / d (attitude error)
716
- Cext.template block <3 ,3 >(0 ,0 ) = -skew_symmetric_matrix (v1hat);
717
- // d f_b / d a_w
718
- Cext.template block <3 ,3 >(0 , OFF_AW) = R_wb ();
714
+ constexpr int n_att = 3 ; // attitude error
715
+ constexpr int n_aw = 3 ; // world accel state
716
+ constexpr int n_ba = with_accel_bias ? 3 : 0 ;
717
+ constexpr int n_sub = n_att + n_aw + n_ba;
718
+
719
+ // Build reduced measurement Jacobian C_sub (3×n_sub)
720
+ Eigen::Matrix<T,3 ,n_sub> C_sub;
721
+ C_sub.template block <3 ,3 >(0 ,0 ) = -skew_symmetric_matrix (v1hat); // attitude
722
+ C_sub.template block <3 ,3 >(0 ,n_att) = R_wb (); // a_w
719
723
if constexpr (with_accel_bias) {
720
- Cext .template block <3 ,3 >(0 ,OFF_BA ) = Matrix3::Identity (); // d f_b / d b_acc
724
+ C_sub .template block <3 ,3 >(0 ,n_att+n_aw ) = Matrix3::Identity (); // bias
721
725
}
722
726
727
+ // Innovation
723
728
Vector3 inno = acc_meas - v1hat;
724
729
725
- Matrix3 S_mat = Cext * Pext * Cext.transpose () + Racc;
726
- Matrix<T, NX, 3 > PCt = Pext * Cext.transpose ();
730
+ // Extract sub-covariance P_sub from Pext
731
+ Eigen::Matrix<T,n_sub,n_sub> P_sub;
732
+ // att
733
+ P_sub.template block <3 ,3 >(0 ,0 ) = Pext.template block <3 ,3 >(0 ,0 );
734
+ // a_w
735
+ P_sub.template block <3 ,3 >(n_att,n_att) = Pext.template block <3 ,3 >(OFF_AW,OFF_AW);
736
+ // cross att↔a_w
737
+ P_sub.template block <3 ,3 >(0 ,n_att) = Pext.template block <3 ,3 >(0 ,OFF_AW);
738
+ P_sub.template block <3 ,3 >(n_att,0 ) = P_sub.template block <3 ,3 >(0 ,n_att).transpose ();
739
+
740
+ if constexpr (with_accel_bias) {
741
+ // b_acc
742
+ P_sub.template block <3 ,3 >(n_att+n_aw,n_att+n_aw) =
743
+ Pext.template block <3 ,3 >(OFF_BA,OFF_BA);
744
+ // cross att↔b_acc
745
+ P_sub.template block <3 ,3 >(0 ,n_att+n_aw) = Pext.template block <3 ,3 >(0 ,OFF_BA);
746
+ P_sub.template block <3 ,3 >(n_att+n_aw,0 ) = P_sub.template block <3 ,3 >(0 ,n_att+n_aw).transpose ();
747
+ // cross a_w↔b_acc
748
+ P_sub.template block <3 ,3 >(n_att,n_att+n_aw) = Pext.template block <3 ,3 >(OFF_AW,OFF_BA);
749
+ P_sub.template block <3 ,3 >(n_att+n_aw,n_att) = P_sub.template block <3 ,3 >(n_att,n_att+n_aw).transpose ();
750
+ }
751
+
752
+ // Innovation covariance S (3×3)
753
+ Matrix3 S_mat = C_sub * P_sub * C_sub.transpose () + Racc;
727
754
728
755
Eigen::LDLT<Matrix3> ldlt (S_mat);
729
756
if (ldlt.info () != Eigen::Success) {
730
- S_mat += Matrix3::Identity () * std::max (std::numeric_limits<T>::epsilon (), T (1e-6 ) * Racc.norm ());
757
+ S_mat += Matrix3::Identity () *
758
+ std::max (std::numeric_limits<T>::epsilon (), T (1e-6 ) * Racc.norm ());
731
759
ldlt.compute (S_mat);
732
760
if (ldlt.info () != Eigen::Success) return ;
733
761
}
734
- Matrix<T, NX, 3 > K = PCt * ldlt.solve (Matrix3::Identity ());
735
762
736
- xext.noalias () += K * inno;
763
+ // Kalman gain (n_sub×3)
764
+ Eigen::Matrix<T,n_sub,3 > K_sub = P_sub * C_sub.transpose () * ldlt.solve (Matrix3::Identity ());
737
765
738
- MatrixNX I = MatrixNX::Identity ();
739
- Pext = (I - K * Cext) * Pext * (I - K * Cext).transpose () + K * Racc * K.transpose ();
740
- Pext = T (0.5 ) * (Pext + Pext.transpose ());
766
+ // State update (only relevant states)
767
+ auto dx_sub = K_sub * inno;
768
+ xext.template segment <3 >(0 ) += dx_sub.template segment <3 >(0 ); // attitude error
769
+ xext.template segment <3 >(OFF_AW) += dx_sub.template segment <3 >(n_att); // a_w
770
+ if constexpr (with_accel_bias) {
771
+ xext.template segment <3 >(OFF_BA) += dx_sub.template segment <3 >(n_att+n_aw); // bias
772
+ }
773
+
774
+ // Joseph covariance update on sub-block
775
+ Eigen::Matrix<T,n_sub,n_sub> I_sub = Eigen::Matrix<T,n_sub,n_sub>::Identity ();
776
+ Eigen::Matrix<T,n_sub,n_sub> P_sub_new =
777
+ (I_sub - K_sub * C_sub) * P_sub * (I_sub - K_sub * C_sub).transpose ()
778
+ + K_sub * Racc * K_sub.transpose ();
779
+
780
+ // Write back P_sub_new into Pext
781
+ // att
782
+ Pext.template block <3 ,3 >(0 ,0 ) = P_sub_new.template block <3 ,3 >(0 ,0 );
783
+ // a_w
784
+ Pext.template block <3 ,3 >(OFF_AW,OFF_AW) = P_sub_new.template block <3 ,3 >(n_att,n_att);
785
+ // cross att↔a_w
786
+ Pext.template block <3 ,3 >(0 ,OFF_AW) = P_sub_new.template block <3 ,3 >(0 ,n_att);
787
+ Pext.template block <3 ,3 >(OFF_AW,0 ) = P_sub_new.template block <3 ,3 >(n_att,0 );
788
+
789
+ if constexpr (with_accel_bias) {
790
+ // b_acc
791
+ Pext.template block <3 ,3 >(OFF_BA,OFF_BA) = P_sub_new.template block <3 ,3 >(n_att+n_aw,n_att+n_aw);
792
+ // cross att↔b_acc
793
+ Pext.template block <3 ,3 >(0 ,OFF_BA) = P_sub_new.template block <3 ,3 >(0 ,n_att+n_aw);
794
+ Pext.template block <3 ,3 >(OFF_BA,0 ) = P_sub_new.template block <3 ,3 >(n_att+n_aw,0 );
795
+ // cross a_w↔b_acc
796
+ Pext.template block <3 ,3 >(OFF_AW,OFF_BA) = P_sub_new.template block <3 ,3 >(n_att,n_att+n_aw);
797
+ Pext.template block <3 ,3 >(OFF_BA,OFF_AW) = P_sub_new.template block <3 ,3 >(n_att+n_aw,n_att);
798
+ }
741
799
800
+ // Apply quaternion correction
742
801
applyQuaternionCorrectionFromErrorState ();
743
802
}
744
803
0 commit comments