@@ -695,46 +695,93 @@ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_parti
695
695
}
696
696
697
697
template <typename T, bool with_gyro_bias, bool with_accel_bias>
698
- void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_only(Vector3 const & acc_meas, T tempC) {
699
-
700
- // Accel magnitude sanity check
701
- T g_meas = acc_meas.norm ();
702
- if (std::abs (g_meas - gravity_magnitude_) > T (2.0 * gravity_magnitude_)) {
703
- return ; // reject this update
704
- }
698
+ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_only(
699
+ Vector3 const & acc_meas, T tempC)
700
+ {
701
+ // Gate accel magnitude
702
+ const T g_meas = acc_meas.norm ();
703
+ if (std::abs (g_meas - gravity_magnitude_) > T (2.0 ) * gravity_magnitude_) return ;
705
704
705
+ // Predicted specific force
706
706
const Vector3 v1hat = accelerometer_measurement_func (tempC);
707
707
708
- // Cext: (3 x NX)
709
- Matrix<T, 3 , NX> Cext = Matrix<T, 3 , NX>::Zero ();
710
- // d f_b / d (attitude error)
711
- Cext.template block <3 ,3 >(0 ,0 ) = -skew_symmetric_matrix (v1hat);
712
- // d f_b / d a_w
713
- Cext.template block <3 ,3 >(0 , OFF_AW) = R_wb ();
708
+ // Jacobians wrt the only columns C touches
709
+ const Matrix3 J_att = -skew_symmetric_matrix (v1hat); // d f / d θ
710
+ const Matrix3 J_aw = R_wb (); // d f / d a_w
711
+ Matrix3 J_ba; // d f / d b_a
712
+ if constexpr (with_accel_bias) J_ba.setIdentity ();
713
+
714
+ const Vector3 r = acc_meas - v1hat;
715
+
716
+ // Column offsets
717
+ constexpr int OFF_TH = 0 ; // attitude error starts at 0
718
+ const int off_aw = OFF_AW;
719
+ const int off_ba = OFF_BA;
720
+
721
+ // S = C P Cᵀ + Racc (3×3)
722
+ Matrix3 S_mat = Racc;
723
+
724
+ const Matrix3 P_th_th = Pext.template block <3 ,3 >(OFF_TH, OFF_TH);
725
+ const Matrix3 P_th_aw = Pext.template block <3 ,3 >(OFF_TH, off_aw);
726
+ const Matrix3 P_aw_aw = Pext.template block <3 ,3 >(off_aw, off_aw);
727
+
728
+ S_mat.noalias () += J_att * P_th_th * J_att.transpose ();
729
+ S_mat.noalias () += J_att * P_th_aw * J_aw.transpose ();
730
+ S_mat.noalias () += J_aw * P_th_aw.transpose () * J_att.transpose ();
731
+ S_mat.noalias () += J_aw * P_aw_aw * J_aw.transpose ();
732
+
714
733
if constexpr (with_accel_bias) {
715
- Cext.template block <3 ,3 >(0 ,OFF_BA) = Matrix3::Identity (); // d f_b / d b_acc
734
+ const Matrix3 P_th_ba = Pext.template block <3 ,3 >(OFF_TH, off_ba);
735
+ const Matrix3 P_aw_ba = Pext.template block <3 ,3 >(off_aw, off_ba);
736
+ const Matrix3 P_ba_ba = Pext.template block <3 ,3 >(off_ba, off_ba);
737
+
738
+ S_mat.noalias () += J_att * P_th_ba * J_ba.transpose ();
739
+ S_mat.noalias () += J_aw * P_aw_ba * J_ba.transpose ();
740
+
741
+ S_mat.noalias () += J_ba * P_th_ba.transpose () * J_att.transpose ();
742
+ S_mat.noalias () += J_ba * P_aw_ba.transpose () * J_aw.transpose ();
743
+
744
+ S_mat.noalias () += J_ba * P_ba_ba * J_ba.transpose ();
716
745
}
717
746
718
- Vector3 inno = acc_meas - v1hat;
747
+ // PCᵀ = P Cᵀ (NX×3)
748
+ Eigen::Matrix<T,NX,3 > PCt; PCt.setZero ();
749
+ {
750
+ const auto P_all_th = Pext.template block <NX,3 >(0 , OFF_TH);
751
+ const auto P_all_aw = Pext.template block <NX,3 >(0 , off_aw);
752
+ PCt.noalias () += P_all_th * J_att.transpose ();
753
+ PCt.noalias () += P_all_aw * J_aw.transpose ();
719
754
720
- Matrix3 S_mat = Cext * Pext * Cext.transpose () + Racc;
721
- Matrix<T, NX, 3 > PCt = Pext * Cext.transpose ();
755
+ if constexpr (with_accel_bias) {
756
+ const auto P_all_ba = Pext.template block <NX,3 >(0 , off_ba);
757
+ PCt.noalias () += P_all_ba * J_ba.transpose (); // J_ba = I
758
+ }
759
+ }
722
760
761
+ // K = PCᵀ S^{-1}
723
762
Eigen::LDLT<Matrix3> ldlt (S_mat);
724
763
if (ldlt.info () != Eigen::Success) {
725
- S_mat += Matrix3::Identity () * std::max (std::numeric_limits<T>::epsilon (), T (1e-6 ) * Racc.norm ());
764
+ S_mat += Matrix3::Identity ()
765
+ * std::max (std::numeric_limits<T>::epsilon (), T (1e-6 ) * Racc.norm ());
726
766
ldlt.compute (S_mat);
727
767
if (ldlt.info () != Eigen::Success) return ;
728
768
}
729
- Matrix<T, NX, 3 > K = PCt * ldlt.solve (Matrix3::Identity ());
769
+ const Eigen:: Matrix<T,NX,3 > K = PCt * ldlt.solve (Matrix3::Identity ());
730
770
731
- xext.noalias () += K * inno;
771
+ // State & Covariance (Joseph, full P)
772
+ xext.noalias () += K * r;
732
773
733
- MatrixNX I = MatrixNX::Identity ();
734
- Pext = (I - K * Cext) * Pext * (I - K * Cext). transpose () + K * Racc * K. transpose () ;
735
- Pext = T ( 0.5 ) * (Pext + Pext .transpose () );
774
+ const Eigen::Matrix<T, 3 ,NX> CP = PCt. transpose (); // CP = (PCᵀ)ᵀ
775
+ const Eigen::Matrix<T,NX,NX> KCP = K * CP ;
776
+ const Eigen::Matrix<T,NX,NX> KSKt = K * S_mat * K .transpose ();
736
777
778
+ Pext.noalias () -= KCP;
779
+ Pext.noalias () -= KCP.transpose ();
780
+ Pext.noalias () += KSKt;
781
+
782
+ Pext = T (0.5 ) * (Pext + Pext.transpose ());
737
783
applyQuaternionCorrectionFromErrorState ();
784
+ Pbase = Pext.topLeftCorner (BASE_N, BASE_N);
738
785
}
739
786
740
787
template <typename T, bool with_gyro_bias, bool with_accel_bias>
0 commit comments