| 
									
										
										
										
											2025-04-25 09:12:19 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 00:24:00 +08:00
										 |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | 
					
						
							| 
									
										
										
										
											2025-04-25 09:12:19 +08:00
										 |  |  |  * 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-29 12:20:41 +08:00
										 |  |  |  /**
 | 
					
						
							|  |  |  |   * @file    InvariantEKF.h | 
					
						
							|  |  |  |   * @brief   Left-Invariant Extended Kalman Filter implementation. | 
					
						
							|  |  |  |   * | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |   * This file defines the InvariantEKF class template, inheriting from LieGroupEKF, | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |   * which specifically implements the Left-Invariant EKF formulation. It restricts | 
					
						
							|  |  |  |   * prediction methods to only those based on group composition (state-independent | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |   * motion models), hiding the state-dependent prediction variants from LieGroupEKF. | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |   * | 
					
						
							|  |  |  |   * @date    April 24, 2025 | 
					
						
							|  |  |  |   * @authors Scott Baker, Matt Kielo, Frank Dellaert | 
					
						
							|  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2025-04-25 09:12:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							| 
									
										
										
										
											2025-04-27 00:24:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  | #include <gtsam/navigation/LieGroupEKF.h> // Include the base class
 | 
					
						
							| 
									
										
										
										
											2025-05-09 12:25:35 +08:00
										 |  |  | #include <gtsam/base/Lie.h> // For traits (needed for AdjointMap, Expmap)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 00:24:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-25 09:12:19 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /**
 | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |    * @class InvariantEKF | 
					
						
							|  |  |  |    * @brief Left-Invariant Extended Kalman Filter on a Lie group G. | 
					
						
							| 
									
										
										
										
											2025-04-27 00:24:00 +08:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |    * @tparam G Lie group type (must satisfy LieGroup concept). | 
					
						
							| 
									
										
										
										
											2025-04-27 00:14:12 +08:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |    * This filter inherits from LieGroupEKF but restricts the prediction interface | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |    * to only the left-invariant prediction methods: | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |    * 1. Prediction via group composition: `predict(const G& U, const Covariance& Q)` | 
					
						
							|  |  |  |    * 2. Prediction via tangent control vector: `predict(const TangentVector& u, double dt, const Covariance& Q)` | 
					
						
							| 
									
										
										
										
											2025-04-28 08:42:17 +08:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |    * The state-dependent prediction methods from LieGroupEKF are hidden. | 
					
						
							|  |  |  |    * The update step remains the same as in ManifoldEKF/LieGroupEKF. | 
					
						
							| 
									
										
										
										
											2025-05-09 22:40:20 +08:00
										 |  |  |    * For details on how static and dynamic dimensions are handled, please refer to | 
					
						
							|  |  |  |    * the `ManifoldEKF` class documentation. | 
					
						
							| 
									
										
										
										
											2025-04-28 08:42:17 +08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |   template <typename G> | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |   class InvariantEKF : public LieGroupEKF<G> { | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |   public: | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |     using Base = LieGroupEKF<G>; ///< Base class type
 | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |     using TangentVector = typename Base::TangentVector; ///< Tangent vector type
 | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |     /// Jacobian for group-specific operations like AdjointMap. Eigen::Matrix<double, Dim, Dim>.
 | 
					
						
							| 
									
										
										
										
											2025-05-09 12:25:35 +08:00
										 |  |  |     using Jacobian = typename Base::Jacobian; | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |     /// Covariance matrix type. Eigen::Matrix<double, Dim, Dim>.
 | 
					
						
							|  |  |  |     using Covariance = typename Base::Covariance; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-09 12:25:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Constructor: forwards to LieGroupEKF constructor. | 
					
						
							|  |  |  |      * @param X0 Initial state on Lie group G. | 
					
						
							| 
									
										
										
										
											2025-05-09 22:40:20 +08:00
										 |  |  |      * @param P0 Initial covariance in the tangent space at X0. | 
					
						
							| 
									
										
										
										
											2025-05-09 12:25:35 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2025-05-09 22:40:20 +08:00
										 |  |  |     InvariantEKF(const G& X0, const Covariance& P0) : Base(X0, P0) {} | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |     // We hide state-dependent predict methods from LieGroupEKF by only providing the
 | 
					
						
							| 
									
										
										
										
											2025-05-09 12:25:35 +08:00
										 |  |  |     // invariant predict methods below.
 | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Predict step via group composition (Left-Invariant): | 
					
						
							|  |  |  |      *   X_{k+1} = X_k * U | 
					
						
							|  |  |  |      *   P_{k+1} = Ad_{U^{-1}} P_k Ad_{U^{-1}}^T + Q | 
					
						
							| 
									
										
										
										
											2025-05-09 12:25:35 +08:00
										 |  |  |      * where Ad_{U^{-1}} is the Adjoint map of U^{-1}. | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @param U Lie group element representing the motion increment. | 
					
						
							| 
									
										
										
										
											2025-05-09 22:40:20 +08:00
										 |  |  |      * @param Q Process noise covariance. | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |     void predict(const G& U, const Covariance& Q) { | 
					
						
							| 
									
										
										
										
											2025-05-10 03:46:25 +08:00
										 |  |  |       this->X_ = traits<G>::Compose(this->X_, U); | 
					
						
							|  |  |  |       const G U_inv = traits<G>::Inverse(U); | 
					
						
							|  |  |  |       const Jacobian A = traits<G>::AdjointMap(U_inv); | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |       // P_ is Covariance. A is Jacobian. Q is Covariance.
 | 
					
						
							|  |  |  |       // All are Eigen::Matrix<double,Dim,Dim>.
 | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |       this->P_ = A * this->P_ * A.transpose() + Q; | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Predict step via tangent control vector: | 
					
						
							|  |  |  |      *   U = Expmap(u * dt) | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |      * Then calls predict(U, Q). | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @param u Tangent space control vector. | 
					
						
							|  |  |  |      * @param dt Time interval. | 
					
						
							| 
									
										
										
										
											2025-05-09 22:40:20 +08:00
										 |  |  |      * @param Q Process noise covariance matrix. | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2025-05-09 12:48:07 +08:00
										 |  |  |     void predict(const TangentVector& u, double dt, const Covariance& Q) { | 
					
						
							| 
									
										
										
										
											2025-05-10 03:48:56 +08:00
										 |  |  |       G U; | 
					
						
							|  |  |  |       if constexpr (std::is_same_v<G, Matrix>) { | 
					
						
							|  |  |  |         const Matrix& X = static_cast<const Matrix&>(this->X_); | 
					
						
							|  |  |  |         U.resize(X.rows(), X.cols()); | 
					
						
							|  |  |  |         Eigen::Map<Vector>(static_cast<Matrix&>(U).data(), U.size()) = u * dt; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         U = traits<G>::Expmap(u * dt); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2025-05-07 21:55:45 +08:00
										 |  |  |       predict(U, Q); // Call the group composition predict
 | 
					
						
							| 
									
										
										
										
											2025-04-29 12:20:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   }; // InvariantEKF
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace gtsam
 |