| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | 
					
						
							|  |  |  |  |  * Atlanta, Georgia 30332-0415 | 
					
						
							|  |  |  |  |  * All Rights Reserved | 
					
						
							|  |  |  |  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  * See LICENSE for the license information | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2025-04-28 09:11:30 +08:00
										 |  |  |  |  * @file IEKF_NavstateExample.cpp | 
					
						
							|  |  |  |  |  * @brief InvariantEKF on NavState (SE_2(3)) with IMU (predict) and GPS (update) | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  |  * @date April 25, 2025 | 
					
						
							|  |  |  |  |  * @authors Scott Baker, Matt Kielo, Frank Dellaert | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #include <gtsam/base/Matrix.h>
 | 
					
						
							|  |  |  |  | #include <gtsam/base/OptionalJacobian.h>
 | 
					
						
							| 
									
										
										
										
											2025-04-28 09:11:30 +08:00
										 |  |  |  | #include <gtsam/navigation/InvariantEKF.h>
 | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  | #include <gtsam/navigation/NavState.h>
 | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-25 09:11:26 +08:00
										 |  |  |  | #include <iostream>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | using namespace std; | 
					
						
							|  |  |  |  | using namespace gtsam; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  | /**
 | 
					
						
							|  |  |  |  |  * @brief Left-invariant dynamics for NavState. | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |  * @param imu  6×1 vector [a; ω]: linear acceleration and angular velocity. | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  |  * @return     9×1 tangent: [ω; 0₃; a]. | 
					
						
							|  |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-04-28 01:35:24 +08:00
										 |  |  |  | Vector9 dynamics(const Vector6& imu) { | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  |   auto a = imu.head<3>(); | 
					
						
							|  |  |  |  |   auto w = imu.tail<3>(); | 
					
						
							|  |  |  |  |   Vector9 xi; | 
					
						
							|  |  |  |  |   xi << w, Vector3::Zero(), a; | 
					
						
							|  |  |  |  |   return xi; | 
					
						
							| 
									
										
										
										
											2025-04-25 09:11:26 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  | /**
 | 
					
						
							|  |  |  |  |  * @brief GPS measurement model: returns position and its Jacobian. | 
					
						
							|  |  |  |  |  * @param X    Current state. | 
					
						
							|  |  |  |  |  * @param H    Optional 3×9 Jacobian w.r.t. X. | 
					
						
							|  |  |  |  |  * @return     3×1 position vector. | 
					
						
							|  |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | Vector3 h_gps(const NavState& X, OptionalJacobian<3, 9> H = {}) { | 
					
						
							| 
									
										
										
										
											2025-04-28 09:03:34 +08:00
										 |  |  |  |   return X.position(H); | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | int main() { | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |   // Initial state & covariances
 | 
					
						
							|  |  |  |  |   NavState X0;  // R=I, v=0, t=0
 | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  |   Matrix9 P0 = Matrix9::Identity() * 0.1; | 
					
						
							| 
									
										
										
										
											2025-04-28 09:11:30 +08:00
										 |  |  |  |   InvariantEKF<NavState> ekf(X0, P0); | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |   // Noise & timestep
 | 
					
						
							|  |  |  |  |   double dt = 1.0; | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  |   Matrix9 Q = Matrix9::Identity() * 0.01; | 
					
						
							|  |  |  |  |   Matrix3 R = Matrix3::Identity() * 0.5; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |   // Two IMU samples [a; ω]
 | 
					
						
							|  |  |  |  |   Vector6 imu1; | 
					
						
							|  |  |  |  |   imu1 << 0.1, 0, 0, 0, 0.2, 0; | 
					
						
							|  |  |  |  |   Vector6 imu2; | 
					
						
							|  |  |  |  |   imu2 << 0, 0.3, 0, 0.4, 0, 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // Two GPS fixes
 | 
					
						
							|  |  |  |  |   Vector3 z1; | 
					
						
							|  |  |  |  |   z1 << 0.3, 0, 0; | 
					
						
							|  |  |  |  |   Vector3 z2; | 
					
						
							|  |  |  |  |   z2 << 0.6, 0, 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   cout << "=== Init ===\nX: " << ekf.state() << "\nP: " << ekf.covariance() | 
					
						
							|  |  |  |  |        << "\n\n"; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // --- first predict/update ---
 | 
					
						
							|  |  |  |  |   ekf.predict(dynamics(imu1), dt, Q); | 
					
						
							|  |  |  |  |   cout << "--- After predict 1 ---\nX: " << ekf.state() | 
					
						
							|  |  |  |  |        << "\nP: " << ekf.covariance() << "\n\n"; | 
					
						
							| 
									
										
										
										
											2025-04-26 23:47:46 +08:00
										 |  |  |  |   ekf.update(h_gps, z1, R); | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |   cout << "--- After update 1 ---\nX: " << ekf.state() | 
					
						
							|  |  |  |  |        << "\nP: " << ekf.covariance() << "\n\n"; | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |   // --- second predict/update ---
 | 
					
						
							|  |  |  |  |   ekf.predict(dynamics(imu2), dt, Q); | 
					
						
							|  |  |  |  |   cout << "--- After predict 2 ---\nX: " << ekf.state() | 
					
						
							|  |  |  |  |        << "\nP: " << ekf.covariance() << "\n\n"; | 
					
						
							| 
									
										
										
										
											2025-04-26 23:47:46 +08:00
										 |  |  |  |   ekf.update(h_gps, z2, R); | 
					
						
							| 
									
										
										
										
											2025-04-27 22:40:28 +08:00
										 |  |  |  |   cout << "--- After update 2 ---\nX: " << ekf.state() | 
					
						
							|  |  |  |  |        << "\nP: " << ekf.covariance() << "\n"; | 
					
						
							| 
									
										
										
										
											2025-04-26 03:02:30 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2025-04-27 00:30:55 +08:00
										 |  |  |  | } |