ManifoldEKF.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
25 #pragma once
26 
27 #include <gtsam/base/Matrix.h>
29 #include <gtsam/base/Vector.h>
30 #include <gtsam/base/Manifold.h> // Include for traits and IsManifold
31 
32 #include <Eigen/Dense>
33 #include <string>
34 #include <stdexcept>
35 #include <type_traits>
36 
37 namespace gtsam {
38 
64  template <typename M>
65  class ManifoldEKF {
66  public:
68  static constexpr int Dim = traits<M>::dimension;
69 
76 
77 
83  ManifoldEKF(const M& X0, const Covariance& P0) : X_(X0) {
84  static_assert(IsManifold<M>::value,
85  "Template parameter M must be a GTSAM Manifold.");
86 
87  if constexpr (Dim == Eigen::Dynamic) {
89  // Validate dimensions of initial covariance P0.
90  if (P0.rows() != n_ || P0.cols() != n_) {
91  throw std::invalid_argument(
92  "ManifoldEKF: Initial covariance P0 dimensions (" +
93  std::to_string(P0.rows()) + "x" + std::to_string(P0.cols()) +
94  ") do not match state's tangent space dimension (" +
95  std::to_string(n_) + ").");
96  }
97  }
98  else {
99  n_ = Dim;
100  }
101 
102  P_ = P0;
103  }
104 
105  virtual ~ManifoldEKF() = default;
106 
108  const M& state() const { return X_; }
109 
111  const Covariance& covariance() const { return P_; }
112 
114  int dimension() const { return n_; }
115 
128  void predict(const M& X_next, const Jacobian& F, const Covariance& Q) {
129  if constexpr (Dim == Eigen::Dynamic) {
130  if (F.rows() != n_ || F.cols() != n_ || Q.rows() != n_ || Q.cols() != n_) {
131  throw std::invalid_argument(
132  "ManifoldEKF::predict: Dynamic F/Q dimensions must match state dimension " +
133  std::to_string(n_) + ".");
134  }
135  }
136 
137  X_ = X_next;
138  P_ = F * P_ * F.transpose() + Q;
139  }
140 
151  template <typename Measurement>
152  void update(const Measurement& prediction,
154  const Measurement& z,
156 
157  static_assert(IsManifold<Measurement>::value,
158  "Template parameter Measurement must be a GTSAM Manifold for LocalCoordinates.");
159 
160  static constexpr int MeasDim = traits<Measurement>::dimension;
161 
162  int m_runtime;
163  if constexpr (MeasDim == Eigen::Dynamic) {
165  if (traits<Measurement>::GetDimension(prediction) != m_runtime) {
166  throw std::invalid_argument(
167  "ManifoldEKF::update: Dynamic measurement 'prediction' and 'z' have different dimensions.");
168  }
169  if (H.rows() != m_runtime || H.cols() != n_ || R.rows() != m_runtime || R.cols() != m_runtime) {
170  throw std::invalid_argument(
171  "ManifoldEKF::update: Jacobian H or Noise R dimensions mismatch for dynamic measurement.");
172  }
173  }
174  else {
175  m_runtime = MeasDim;
176  if constexpr (Dim == Eigen::Dynamic) {
177  if (H.cols() != n_) {
178  throw std::invalid_argument(
179  "ManifoldEKF::update: Jacobian H columns must match state dimension " + std::to_string(n_) + ".");
180  }
181  }
182  }
183 
184  // Innovation: y = z - h(x_pred). In tangent space: local(h(x_pred), z)
185  typename traits<Measurement>::TangentVector innovation =
186  traits<Measurement>::Local(prediction, z);
187 
188  // Innovation covariance: S = H P H^T + R
189  // S will be Eigen::Matrix<double, MeasDim, MeasDim>
190  Eigen::Matrix<double, MeasDim, MeasDim> S = H * P_ * H.transpose() + R;
191 
192  // Kalman Gain: K = P H^T S^-1
193  // K will be Eigen::Matrix<double, Dim, MeasDim>
194  Eigen::Matrix<double, Dim, MeasDim> K = P_ * H.transpose() * S.inverse();
195 
196  // Correction vector in tangent space of M: delta_xi = K * innovation
197  const TangentVector delta_xi = K * innovation; // delta_xi is Dim x 1 (or n_ x 1 if dynamic)
198 
199  // Update state using retract: X_new = retract(X_old, delta_xi)
200  X_ = traits<M>::Retract(X_, delta_xi);
201 
202  // Update covariance using Joseph form for numerical stability
203  Jacobian I_n; // Eigen::Matrix<double, Dim, Dim>
204  if constexpr (Dim == Eigen::Dynamic) {
205  I_n = Jacobian::Identity(n_, n_);
206  }
207  else {
208  I_n = Jacobian::Identity();
209  }
210 
211  // I_KH will be Eigen::Matrix<double, Dim, Dim>
212  Jacobian I_KH = I_n - K * H;
213  P_ = I_KH * P_ * I_KH.transpose() + K * R * K.transpose();
214  }
215 
228  template <typename Measurement, typename MeasurementFunction>
229  void update(MeasurementFunction&& h, const Measurement& z,
231  static_assert(IsManifold<Measurement>::value,
232  "Template parameter Measurement must be a GTSAM Manifold.");
233 
234  static constexpr int MeasDim = traits<Measurement>::dimension;
235 
236  int m_runtime;
237  if constexpr (MeasDim == Eigen::Dynamic) {
239  }
240  else {
241  m_runtime = MeasDim;
242  }
243 
244  // Predict measurement and get Jacobian H = dh/dlocal(X)
245  Matrix H(m_runtime, n_);
246  Measurement prediction = h(X_, H);
247 
248  // Call the other update function
249  update(prediction, H, z, R);
250  }
251 
252  protected:
253  M X_;
255  int n_;
256  };
257 
258 } // namespace gtsam
H
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate set rrange[*:*] noreverse nowriteback set trange[*:*] noreverse nowriteback set urange[*:*] noreverse nowriteback set vrange[*:*] noreverse nowriteback set xlabel matrix size set x2label set timefmt d m y n H
Definition: gnuplot_common_settings.hh:74
gtsam::ManifoldEKF::n_
int n_
Runtime tangent space dimension of M.
Definition: ManifoldEKF.h:255
gtsam::ManifoldEKF< G >::TangentVector
typename traits< G >::TangentVector TangentVector
Tangent vector type for the manifold M.
Definition: ManifoldEKF.h:71
Vector.h
typedef and functions to augment Eigen's VectorXd
gtsam::ManifoldEKF::ManifoldEKF
ManifoldEKF(const M &X0, const Covariance &P0)
Definition: ManifoldEKF.h:83
Matrix.h
typedef and functions to augment Eigen's MatrixXd
gtsam::ManifoldEKF::X_
M X_
Manifold state estimate.
Definition: ManifoldEKF.h:253
gtsam::Matrix
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
h
const double h
Definition: testSimpleHelicopter.cpp:19
gtsam::ManifoldEKF::predict
void predict(const M &X_next, const Jacobian &F, const Covariance &Q)
Definition: ManifoldEKF.h:128
Q
Quaternion Q
Definition: testQuaternion.cpp:27
gtsam::ManifoldEKF::~ManifoldEKF
virtual ~ManifoldEKF()=default
gtsam::Measurement
This is the base class for all measurement types.
Definition: Measurement.h:11
gtsam::ManifoldEKF::covariance
const Covariance & covariance() const
Definition: ManifoldEKF.h:111
gtsam::ManifoldEKF::state
const M & state() const
Definition: ManifoldEKF.h:108
gtsam::ManifoldEKF::P_
Covariance P_
Covariance (Eigen::Matrix<double, Dim, Dim>).
Definition: ManifoldEKF.h:254
Eigen::Dynamic
const int Dynamic
Definition: Constants.h:22
gtsam::ManifoldEKF::update
void update(MeasurementFunction &&h, const Measurement &z, const Eigen::Matrix< double, traits< Measurement >::dimension, traits< Measurement >::dimension > &R)
Definition: ManifoldEKF.h:229
gtsam::ManifoldEKF::dimension
int dimension() const
Definition: ManifoldEKF.h:114
Manifold.h
Base class and basic functions for Manifold types.
OptionalJacobian.h
Special class for optional Jacobian arguments.
pybind_wrapper_test_script.z
z
Definition: pybind_wrapper_test_script.py:61
gtsam::ManifoldEKF::update
void update(const Measurement &prediction, const Eigen::Matrix< double, traits< Measurement >::dimension, Dim > &H, const Measurement &z, const Eigen::Matrix< double, traits< Measurement >::dimension, traits< Measurement >::dimension > &R)
Definition: ManifoldEKF.h:152
gtsam::symbol_shorthand::F
Key F(std::uint64_t j)
Definition: inference/Symbol.h:153
Eigen::Quaternion
The quaternion class used to represent 3D orientations and rotations.
Definition: ForwardDeclarations.h:293
gtsam::ManifoldEKF
Extended Kalman Filter on a generic manifold M.
Definition: ManifoldEKF.h:65
gtsam
traits
Definition: ABC.h:17
gtsam::traits
Definition: Group.h:36
K
#define K
Definition: igam.h:8
gtsam::ManifoldEKF::Dim
static constexpr int Dim
Compile-time dimension of the manifold M.
Definition: ManifoldEKF.h:68
Eigen::Matrix< double, Dim, Dim >
M
abc_eqf_lib::State< N > M
Definition: ABC_EQF_Demo.cpp:17
P0
static double P0[5]
Definition: ndtri.c:59
test_callbacks.value
value
Definition: test_callbacks.py:162
R
Rot2 R(Rot2::fromAngle(0.1))
S
DiscreteKey S(1, 2)


gtsam
Author(s):
autogenerated on Wed May 28 2025 03:01:44