@@ -244,19 +244,6 @@ class EIGEN_ALIGN_MAX Kalman3D_Wave {
244
244
Matrix3 R_wb () const { return qref.toRotationMatrix (); } // world→body
245
245
Matrix3 R_bw () const { return qref.toRotationMatrix ().transpose (); } // body→world
246
246
247
- // world→body rotation that contains only roll & pitch (no yaw)
248
- // Constructed by aligning world +Z (down) to the current body +Z,
249
- // via the minimal rotation. This eliminates any rotation about +Z (yaw).
250
- Matrix3 R_wb_tilt_only () const {
251
- const Vector3 ez_w (0 ,0 ,1 ); // world down
252
- const Matrix3 Rwb = R_wb (); // full world→body
253
- const Vector3 ez_b = (Rwb * ez_w).normalized (); // world down expressed in body
254
- // Minimal rotation mapping ez_w -> ez_b
255
- Eigen::Quaternion<T> q_tilt = Eigen::Quaternion<T>::FromTwoVectors (ez_w, ez_b);
256
- q_tilt.normalize ();
257
- return q_tilt.toRotationMatrix (); // yaw-free world→body
258
- }
259
-
260
247
// Helpers and original methods kept
261
248
void measurement_update_partial (const Eigen::Ref<const Vector3>& meas, const Eigen::Ref<const Vector3>& vhat, const Eigen::Ref<const Matrix3>& Rm);
262
249
Matrix3 skew_symmetric_matrix (const Eigen::Ref<const Vector3>& vec) const ;
@@ -539,38 +526,26 @@ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_parti
539
526
}
540
527
541
528
template <typename T, bool with_gyro_bias, bool with_accel_bias>
542
- void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_only(
543
- Vector3 const & acc_meas, T tempC)
544
- {
545
- // Magnitude gate (unchanged)
529
+ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_only(Vector3 const & acc_meas, T tempC) {
530
+
531
+ // Accel magnitude sanity check
546
532
T g_meas = acc_meas.norm ();
547
533
if (std::abs (g_meas - gravity_magnitude_) > T (2.0 * gravity_magnitude_)) {
548
- return ;
534
+ return ; // reject this update
549
535
}
550
536
551
537
const Vector3 v1hat = accelerometer_measurement_func (tempC);
552
538
553
- // Build Cext
539
+ // Cext: (3 x NX)
554
540
Matrix<T, 3 , NX> Cext = Matrix<T, 3 , NX>::Zero ();
555
-
556
- // Base attitude part before projection
557
- Matrix3 J_att = -skew_symmetric_matrix (v1hat);
558
-
559
- // Unit body "down" axis (yaw axis) — columns along this are yaw
560
- const Vector3 gb = (R_wb () * Vector3 (0 ,0 ,1 )).normalized ();
561
-
562
- // Project Jacobian onto the roll/pitch subspace: (I - gb gbᵀ) kills yaw column
563
- const Matrix3 Prollpitch = Matrix3::Identity () - gb * gb.transpose ();
564
- Cext.template block <3 ,3 >(0 ,0 ) = Prollpitch * J_att; // ← yaw-insensitive
565
-
566
- // Sensitivity wrt a_w (unchanged, but use yaw-free rotation in the model)
567
- Cext.template block <3 ,3 >(0 , OFF_AW) = R_wb_tilt_only ();
568
-
541
+ // d f_b / d (attitude error)
542
+ Cext.template block <3 ,3 >(0 ,0 ) = -skew_symmetric_matrix (v1hat);
543
+ // d f_b / d a_w
544
+ Cext.template block <3 ,3 >(0 , OFF_AW) = R_wb ();
569
545
if constexpr (with_accel_bias) {
570
- Cext.template block <3 ,3 >(0 ,OFF_BA) = Matrix3::Identity ();
546
+ Cext.template block <3 ,3 >(0 ,OFF_BA) = Matrix3::Identity (); // d f_b / d b_acc
571
547
}
572
548
573
- // Innovation & standard Kalman math (unchanged)
574
549
Vector3 inno = acc_meas - v1hat;
575
550
576
551
Matrix3 S_mat = Cext * Pext * Cext.transpose () + Racc;
@@ -590,13 +565,8 @@ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_acc_o
590
565
Pext = (I - K * Cext) * Pext * (I - K * Cext).transpose () + K * Racc * K.transpose ();
591
566
Pext = T (0.5 ) * (Pext + Pext.transpose ());
592
567
593
- // Apply quaternion correction; then explicitly remove any residual yaw error component
594
568
applyQuaternionCorrectionFromErrorState ();
595
-
596
- // Keep only roll/pitch small-angle error; zero yaw component along gb
597
- Eigen::Matrix<T,3 ,1 > dth = xext.template head <3 >();
598
- T dpsi = dth.dot (gb);
599
- xext.template head <3 >() = dth - gb * dpsi; // strip yaw
569
+ xext.template head <3 >().setZero ();
600
570
}
601
571
602
572
template <typename T, bool with_gyro_bias, bool with_accel_bias>
@@ -677,20 +647,19 @@ void Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::measurement_update_mag_o
677
647
xext.template head <3 >().setZero ();
678
648
}
679
649
680
- // specific force prediction: f_b = R_tilt (a_w - g) + b_a(temp)
681
- // NOTE: R_tilt = roll/pitch only. Yaw does not enter this model.
650
+ // specific force prediction: f_b = R_wb (a_w - g) + b_a(temp)
651
+ // with temp correction: b_a(temp) = b_a0 + k_a * (tempC - tempC_ref)
682
652
template <typename T, bool with_gyro_bias, bool with_accel_bias>
683
653
Matrix<T,3 ,1 >
684
654
Kalman3D_Wave<T, with_gyro_bias, with_accel_bias>::accelerometer_measurement_func(T tempC) const {
685
655
const Vector3 g_world (0 ,0 ,+gravity_magnitude_);
686
656
const Vector3 aw = xext.template segment <3 >(OFF_AW);
687
657
688
- const Matrix3 Rt = R_wb_tilt_only (); // ← yaw-free rotation
689
- Vector3 fb = Rt * (aw - g_world);
658
+ Vector3 fb = R_wb () * (aw - g_world);
690
659
691
660
if constexpr (with_accel_bias) {
692
661
Vector3 ba0 = xext.template segment <3 >(OFF_BA);
693
- Vector3 ba = ba0 + k_a_ * (tempC - tempC_ref);
662
+ Vector3 ba = ba0 + k_a_ * (tempC - tempC_ref); // temperature related drift
694
663
fb += ba;
695
664
}
696
665
return fb;
0 commit comments