gtsam
Loading...
Searching...
No Matches
ImuFactor.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
21
22#pragma once
23
24/* GTSAM includes */
25#include <gtsam/base/debug.h>
32
33#include <type_traits> // For std::is_same, std::enable_if
34
35namespace gtsam {
36
37// Determine default preintegration backend
38#ifdef GTSAM_LIEGROUP_PREINTEGRATION
39typedef LieGroupPreintegration DefaultPreintegrationType;
40#elif defined(GTSAM_TANGENT_PREINTEGRATION)
41typedef TangentPreintegration DefaultPreintegrationType;
42#else
43typedef ManifoldPreintegration DefaultPreintegrationType;
44#endif
45
46/*
47 * If you are using the factor, please cite:
48 * Christian Forster, Luca Carlone, Frank Dellaert, and Davide Scaramuzza,
49 * "On-Manifold Preintegration for Real-Time Visual-Inertial Odometry", IEEE
50 * Transactions on Robotics, 2017.
51 *
52 * REFERENCES:
53 * [1] G.S. Chirikjian, "Stochastic Models, Information Theory, and Lie Groups",
54 * Volume 2, 2008.
55 * [2] T. Lupton and S.Sukkarieh, "Visual-Inertial-Aided Navigation for
56 * High-Dynamic Motion in Built Environments Without Initial Conditions",
57 * TRO, 28(1):61-76, 2012.
58 * [3] L. Carlone, S. Williams, R. Roberts, "Preintegrated IMU factor:
59 * Computation of the Jacobian Matrices", Tech. Report, 2013.
60 * Available in this repo as "PreintegratedIMUJacobians.pdf".
61 * [4] C. Forster, L. Carlone, F. Dellaert, D. Scaramuzza, "IMU Preintegration
62 * on Manifold for Efficient Visual-Inertial Maximum-a-Posteriori Estimation",
63 * Robotics: Science and Systems (RSS), 2015.
64 */
65
76template <class PreintegrationType>
77class GTSAM_EXPORT PreintegratedImuMeasurementsT: public PreintegrationType {
78
79 template <class PIM> friend class ImuFactorT;
80 template <class PIM> friend class ImuFactor2T;
81
82protected:
83
86
87public:
88
93
99 PreintegratedImuMeasurementsT(const std::shared_ptr<PreintegrationParams>& p,
100 const imuBias::ConstantBias& biasHat = imuBias::ConstantBias()) :
101 PreintegrationType(p, biasHat) {
102 this->resetIntegration();
103 }
104
110 PreintegratedImuMeasurementsT(const PreintegrationType& base, const Matrix9& preintMeasCov)
111 : PreintegrationType(base),
113 this->PreintegrationType::resetIntegration();
114 }
115
119
121 void print(const std::string& s = "Preintegrated Measurements:") const override;
122
124 bool equals(const PreintegratedImuMeasurementsT<PreintegrationType>& expected, double tol = 1e-9) const;
125
127 void resetIntegration() override;
128
139 void integrateMeasurement(const Vector3& measuredAcc,
140 const Vector3& measuredOmega, const double dt) override;
141
143 Matrix preintMeasCov() const { return preintMeasCov_; }
144
173 Matrix9 residualCovariance() const {
174 // An endpoint attitude is needed only for the rotating-frame lift.
175 if (!this->params() || !this->p().omegaCoriolis ||
176 this->p().omegaCoriolis->isZero(0.0)) {
177 return residualCovarianceAt(Rot3());
178 }
180 this->predict(NavState(), this->biasHat()).attitude());
181 }
182
191 Matrix9 residualCovarianceAt(const Rot3& predictedAttitude) const {
192 Eigen::Matrix<double, 9, 9> physicalChart =
193 Eigen::Matrix<double, 9, 9>::Identity();
194 if (this->params() && this->p().omegaCoriolis) {
195 const Matrix3 rotation = predictedAttitude.matrix();
196 physicalChart.template block<3, 3>(6, 3) =
197 -rotation.transpose() *
198 skewSymmetric(*this->p().omegaCoriolis) * rotation;
199 }
200 if constexpr (std::is_same_v<PreintegrationType,
202 Matrix9 chartJacobian;
204 NavState(), this->preintegrated_, {}, &chartJacobian);
205 physicalChart *= chartJacobian;
206 }
207 return physicalChart * preintMeasCov_ * physicalChart.transpose();
208 }
209
212 template <typename PB = PreintegrationType,
213 // This method is only callable when PreintegrationType is TangentPreintegration.
214 typename = typename std::enable_if<std::is_same<PB, TangentPreintegration>::value>::type>
215 void mergeWith(const PreintegratedImuMeasurementsT<TangentPreintegration>& pim12, Matrix9* H1, Matrix9* H2) {
216 // The `this->PreintegrationType::mergeWith` implies calling TangentPreintegration's mergeWith.
217 // Since pim12 is PreintegratedImuMeasurementsT<TangentPreintegration>, it is a TangentPreintegration.
218 this->PreintegrationType::mergeWith(pim12, H1, H2);
219 // NOTE(gareth): Temporary P is needed as of Eigen 3.3
220 const Matrix9 P = *H1 * preintMeasCov_ * H1->transpose();
221 preintMeasCov_ = P + *H2 * pim12.preintMeasCov_ * H2->transpose();
222 }
223
224 private:
225#if GTSAM_ENABLE_BOOST_SERIALIZATION
227 friend class boost::serialization::access;
228 template<class ARCHIVE>
229 void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
230 namespace bs = ::boost::serialization;
231 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(PreintegrationType);
232 ar & BOOST_SERIALIZATION_NVP(preintMeasCov_);
233 }
234#endif
235};
236
237// For backward compatibility (so that the compiler flag GTSAM_TANGENT_PREINTEGRATION still
238// controls which class PreintegratedImuMeasurements uses):
239using PreintegratedImuMeasurements = PreintegratedImuMeasurementsT<DefaultPreintegrationType>;
240
253template <class PIM = PreintegratedImuMeasurements>
254class GTSAM_EXPORT ImuFactorT
255 : public NoiseModelFactorT<Vector9, Pose3, Vector3, Pose3, Vector3,
256 imuBias::ConstantBias> {
257private:
258
259 typedef ImuFactorT<PIM> This;
260 typedef NoiseModelFactorT<Vector9, Pose3, Vector3, Pose3, Vector3,
262 Base;
263
264 PIM pim_;
265
266public:
267
268 // Provide access to the Matrix& version of evaluateError:
270
272 typedef std::shared_ptr<This> shared_ptr;
273
274
277
293 ImuFactorT(Key pose_i, Key vel_i, Key pose_j, Key vel_j, Key bias,
294 const PIM& preintegratedMeasurements)
295 : Base(noiseModel::Gaussian::Covariance(
296 preintegratedMeasurements.residualCovariance()),
297 pose_i, vel_i, pose_j, vel_j, bias),
299
316 template <class Measurement = PIM>
317 ImuFactorT(Key pose_i, Key vel_i, Key pose_j, Key vel_j, Key bias,
318 const Measurement& preintegratedMeasurements,
319 const Rot3& predictedAttitude)
320 : Base(noiseModel::Gaussian::Covariance(
321 preintegratedMeasurements.residualCovarianceAt(
322 predictedAttitude)),
323 pose_i, vel_i, pose_j, vel_j, bias),
325
326 ~ImuFactorT() override {
327 }
328
330 gtsam::NonlinearFactor::shared_ptr clone() const override {
331 return std::make_shared<This>(*this);
332 }
333
336 void print(const std::string& s = "", const KeyFormatter& keyFormatter =
337 DefaultKeyFormatter) const override;
338 bool equals(const NonlinearFactor& expected, double tol = 1e-9) const override;
340
342
343 const PIM& preintegratedMeasurements() const {
344 return pim_;
345 }
346
348
350 Vector9 evaluateError(const Pose3& pose_i, const Vector3& vel_i,
351 const Pose3& pose_j, const Vector3& vel_j,
352 const imuBias::ConstantBias& bias_i,
355 OptionalMatrixType H5) const override;
356
358 template <typename MethodPIMArg = PIM,
359 // This method is only callable when PIM is PreintegratedImuMeasurementsT<TangentPreintegration>.
360 typename = typename std::enable_if<
361 std::is_same<MethodPIMArg, PreintegratedImuMeasurementsT<TangentPreintegration>>::value
362 >::type
363 >
364 static MethodPIMArg Merge(
365 const MethodPIMArg& pim01,
366 const MethodPIMArg& pim12
367 ) {
368 // When this template is instantiated:
369 // 1. MethodPIMArg = PIM. It's mirrored to avoid error C7637 from strict compilers.
370 // 2. The SFINAE condition ensures MethodPIMArg IS PreintegratedImuMeasurementsT<TangentPreintegration>.
371 // So, arguments are const PreintegratedImuMeasurementsT<TangentPreintegration>&
372 // and return is PreintegratedImuMeasurementsT<TangentPreintegration>.
373
374 if (!pim01.matchesParamsWith(pim12))
375 throw std::domain_error(
376 "Cannot merge PreintegratedImuMeasurements with different params");
377
378 if (pim01.p_->body_P_sensor)
379 throw std::domain_error(
380 "Cannot merge PreintegratedImuMeasurements with sensor pose yet");
381
382 // the bias for the merged factor will be the bias from 01
383 MethodPIMArg pim02 = pim01;
384
385 Matrix9 H1, H2;
386 pim02.mergeWith(pim12, &H1, &H2);
387
388 return pim02;
389 }
390
392 template <
393 typename MethodPIMArg = PIM,
394 // This method is only callable when PIM is PreintegratedImuMeasurementsT<TangentPreintegration>.
395 typename = typename std::enable_if<
396 std::is_same<MethodPIMArg, PreintegratedImuMeasurementsT<TangentPreintegration>>::value
397 >::type
398 >
400 const typename ImuFactorT<MethodPIMArg>::shared_ptr& f01,
401 const typename ImuFactorT<MethodPIMArg>::shared_ptr& f12
402 ) {
403 // When this template is instantiated:
404 // 1. MethodPIMArg = PIM. It's mirrored to avoid error C7637 from strict compilers.
405 // 2. The SFINAE condition ensures MethodPIMArg IS PreintegratedImuMeasurementsT<TangentPreintegration>.
406 // So, ImuFactorT<MethodPIMArg> is effectively ImuFactorT<PIM>, which is `This`.
407 // The signature effectively becomes:
408 // static typename This::shared_ptr Merge(const typename This::shared_ptr&, const typename This::shared_ptr&)
409
410 // IMU bias keys must be the same.
411 if (f01->template key<5>() != f12->template key<5>())
412 throw std::domain_error("ImuFactor::Merge: IMU bias keys must be the same");
413
414 // expect intermediate pose, velocity keys to matchup.
415 if (f01->template key<3>() != f12->template key<1>() || f01->template key<4>() != f12->template key<2>())
416 throw std::domain_error(
417 "ImuFactor::Merge: intermediate pose, velocity keys need to match up");
418
419 // return new factor
420 auto pim02 = This::Merge(f01->preintegratedMeasurements(), f12->preintegratedMeasurements());
421
422 return std::make_shared<This>( // `This` is ImuFactorT<MethodPIMArg> (i.e. ImuFactorT<PIM>)
423 f01->template key<1>(), // P0
424 f01->template key<2>(), // V0
425 f12->template key<3>(), // P2
426 f12->template key<4>(), // V2
427 f01->template key<5>(), // B
428 pim02);
429 }
430
431 private:
433#if GTSAM_ENABLE_BOOST_SERIALIZATION
434 friend class boost::serialization::access;
435 template<class ARCHIVE>
436 void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
437 // NoiseModelFactor5 instead of NoiseModelFactorN for backward compatibility
438 ar & boost::serialization::make_nvp("NoiseModelFactor5",
439 boost::serialization::base_object<Base>(*this));
440 ar & BOOST_SERIALIZATION_NVP(pim_);
441 }
442#endif
443};
444// class ImuFactorT
445
446// For backward compatibility:
447using ImuFactor = ImuFactorT<>;
448
449// operator<< for ImuFactorT
450template <class PIM>
451GTSAM_EXPORT std::ostream& operator<<(std::ostream& os, const ImuFactorT<PIM>& f);
452
457template <class PIM = PreintegratedImuMeasurements>
458class GTSAM_EXPORT ImuFactor2T
459 : public NoiseModelFactorT<Vector9, NavState, NavState,
460 imuBias::ConstantBias> {
461private:
462
463 typedef ImuFactor2T<PIM> This;
464 typedef NoiseModelFactorT<Vector9, NavState, NavState,
466 Base;
467
468 PIM pim_;
469
470public:
471
472 // Provide access to the Matrix& version of evaluateError:
474
477
489 ImuFactor2T(Key state_i, Key state_j, Key bias,
490 const PIM& preintegratedMeasurements)
491 : Base(noiseModel::Gaussian::Covariance(
492 preintegratedMeasurements.residualCovariance()),
493 state_i, state_j, bias),
495
512 template <class Measurement = PIM>
513 ImuFactor2T(Key state_i, Key state_j, Key bias,
514 const Measurement& preintegratedMeasurements,
515 const Rot3& predictedAttitude)
516 : Base(noiseModel::Gaussian::Covariance(
517 preintegratedMeasurements.residualCovarianceAt(
518 predictedAttitude)),
519 state_i, state_j, bias),
521
522 ~ImuFactor2T() override {
523 }
524
526 gtsam::NonlinearFactor::shared_ptr clone() const override {
527 return std::make_shared<This>(*this);
528 }
529
530
533 void print(const std::string& s = "", const KeyFormatter& keyFormatter =
534 DefaultKeyFormatter) const override;
535 bool equals(const NonlinearFactor& expected, double tol = 1e-9) const override;
537
539
540 const PIM& preintegratedMeasurements() const {
541 return pim_;
542 }
543
545
547 Vector9 evaluateError(const NavState& state_i, const NavState& state_j,
548 const imuBias::ConstantBias& bias_i, //
550 OptionalMatrixType H3) const override;
551
552private:
553
554#if GTSAM_ENABLE_BOOST_SERIALIZATION
556 friend class boost::serialization::access;
557 template<class ARCHIVE>
558 void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
559 // NoiseModelFactor3 instead of NoiseModelFactorN for backward compatibility
560 ar & boost::serialization::make_nvp("NoiseModelFactor3",
561 boost::serialization::base_object<Base>(*this));
562 ar & BOOST_SERIALIZATION_NVP(pim_);
563 }
564#endif
565};
566// class ImuFactor2T
567
568// For backward compatibility:
569using ImuFactor2 = ImuFactor2T<>;
570
571// operator<< for ImuFactor2T
572template <class PIM>
573GTSAM_EXPORT std::ostream& operator<<(std::ostream& os, const ImuFactor2T<PIM>& f);
574
575template <class PreintegrationType>
576struct traits<PreintegratedImuMeasurementsT<PreintegrationType>> : public Testable<PreintegratedImuMeasurementsT<PreintegrationType>> {};
577
578template <class PIM>
579struct traits<ImuFactorT<PIM>> : public Testable<ImuFactorT<PIM>> {};
580
581template <class PIM>
582struct traits<ImuFactor2T<PIM>> : public Testable<ImuFactor2T<PIM>> {};
583
584}
Global debugging flags.
Arbitrary-arity Jacobian factor with compile-time block dimensions.
GTSAM_EXPORT NavState navStateComponentWiseRetract(const NavState &state, const Vector9 &v, OptionalJacobian< 9, 9 > H1={}, OptionalJacobian< 9, 9 > H2={})
Component-wise NavState retraction independent of the optimization chart.
Definition NavState.cpp:147
IMU preintegration using the SE_2(3) group structure of NavState.
Base class for noise model factors with N variables.
Non-linear factor base classes.
STL namespace.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition Key.cpp:30
Matrix * OptionalMatrixType
This typedef will be used everywhere boost::optional<Matrix&> reference was used previously.
Definition NonlinearFactor.h:57
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition Key.h:35
Matrix3 skewSymmetric(double wx, double wy, double wz)
skew symmetric matrix returns this: 0 -wz wy wz 0 -wx -wy wx 0
Definition Matrix.h:365
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
All noise models live in the noiseModel namespace.
Definition LossFunctions.cpp:33
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
A helper that implements the traits interface for GTSAM types.
Definition Testable.h:152
A 3D pose (R,t) : (Rot3,Point3).
Definition Pose3.h:42
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition Rot3.h:65
Matrix3 matrix() const
return 3*3 rotation matrix
Definition Rot3M.cpp:261
Definition ImuBias.h:34
PreintegratedImuMeasurements accumulates (integrates) the IMU measurements (rotation rates and accele...
Definition ImuFactor.h:77
bool equals(const PreintegratedImuMeasurementsT< PreintegrationType > &expected, double tol=1e-9) const
equals
Definition ImuFactor.cpp:174
PreintegratedImuMeasurementsT(const std::shared_ptr< PreintegrationParams > &p, const imuBias::ConstantBias &biasHat=imuBias::ConstantBias())
Constructor, initializes the class with no measurements.
Definition ImuFactor.h:99
Matrix preintMeasCov() const
Definition ImuFactor.h:143
Matrix9 residualCovarianceAt(const Rot3 &predictedAttitude) const
Definition ImuFactor.h:191
void mergeWith(const PreintegratedImuMeasurementsT< TangentPreintegration > &pim12, Matrix9 *H1, Matrix9 *H2)
Merge in a different set of measurements and update bias derivatives accordingly This method is speci...
Definition ImuFactor.h:215
void print(const std::string &s="Preintegrated Measurements:") const override
print
Definition ImuFactor.cpp:167
PreintegratedImuMeasurementsT(const PreintegrationType &base, const Matrix9 &preintMeasCov)
Construct preintegrated directly from members: base class and preintMeasCov.
Definition ImuFactor.h:110
PreintegratedImuMeasurementsT()
Default constructor with default preintegration parameters.
Definition ImuFactor.h:90
void integrateMeasurement(const Vector3 &measuredAcc, const Vector3 &measuredOmega, const double dt) override
Add a single IMU measurement to the preintegration.
Definition ImuFactor.cpp:189
Matrix9 residualCovariance() const
Express the covariance propagated by the selected backend in the chart used by the IMU factor residua...
Definition ImuFactor.h:173
~PreintegratedImuMeasurementsT() override
Virtual destructor.
Definition ImuFactor.h:117
ImuFactor is a 5-ways factor involving previous state (pose and velocity of the vehicle at previous t...
Definition ImuFactor.h:256
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition ImuFactor.h:330
ImuFactorT()
Default constructor - only use for serialization.
Definition ImuFactor.h:276
static MethodPIMArg Merge(const MethodPIMArg &pim01, const MethodPIMArg &pim12)
Merge two pre-integrated measurement classes.
Definition ImuFactor.h:364
ImuFactorT(Key pose_i, Key vel_i, Key pose_j, Key vel_j, Key bias, const PIM &preintegratedMeasurements)
Constructor.
Definition ImuFactor.h:293
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition ImuFactor.cpp:223
const PreintegratedImuMeasurementsG & preintegratedMeasurements() const
Definition ImuFactor.h:343
bool equals(const NonlinearFactor &expected, double tol=1e-9) const override
Check if two factors are equal.
Definition ImuFactor.cpp:233
std::shared_ptr< This > shared_ptr
Definition ImuFactor.h:272
ImuFactorT(Key pose_i, Key vel_i, Key pose_j, Key vel_j, Key bias, const Measurement &preintegratedMeasurements, const Rot3 &predictedAttitude)
Construct a factor whose rotating-frame covariance is expressed at a supplied nominal endpoint attitu...
Definition ImuFactor.h:317
static ImuFactorT< MethodPIMArg >::shared_ptr Merge(const typename ImuFactorT< MethodPIMArg >::shared_ptr &f01, const typename ImuFactorT< MethodPIMArg >::shared_ptr &f12)
Merge two factors.
Definition ImuFactor.h:399
Vector9 evaluateError(const Pose3 &pose_i, const Vector3 &vel_i, const Pose3 &pose_j, const Vector3 &vel_j, const imuBias::ConstantBias &bias_i, OptionalMatrixType H1, OptionalMatrixType H2, OptionalMatrixType H3, OptionalMatrixType H4, OptionalMatrixType H5) const override
implement functions needed to derive from Factor
Definition ImuFactor.cpp:242
ImuFactor2 is a ternary factor that uses NavStates rather than Pose/Velocity.
Definition ImuFactor.h:460
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition ImuFactor.cpp:263
bool equals(const NonlinearFactor &expected, double tol=1e-9) const override
Check if two factors are equal.
Definition ImuFactor.cpp:273
Vector9 evaluateError(const NavState &state_i, const NavState &state_j, const imuBias::ConstantBias &bias_i, OptionalMatrixType H1, OptionalMatrixType H2, OptionalMatrixType H3) const override
implement functions needed to derive from Factor
Definition ImuFactor.cpp:282
ImuFactor2T(Key state_i, Key state_j, Key bias, const Measurement &preintegratedMeasurements, const Rot3 &predictedAttitude)
Construct a NavState factor with rotating-frame covariance frozen at a supplied nominal endpoint atti...
Definition ImuFactor.h:513
ImuFactor2T()
Default constructor - only use for serialization.
Definition ImuFactor.h:476
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition ImuFactor.h:526
ImuFactor2T(Key state_i, Key state_j, Key bias, const PIM &preintegratedMeasurements)
Constructor.
Definition ImuFactor.h:489
const PreintegratedImuMeasurementsG & preintegratedMeasurements() const
Definition ImuFactor.h:540
IMU preintegration using the SE_2(3) Lie-group structure of NavState.
Definition LieGroupPreintegration.h:32
IMU pre-integration on NavState manifold.
Definition ManifoldPreintegration.h:33
Navigation state: Pose (rotation, translation) + velocity Following Barrau20icra, this class belongs ...
Definition NavState.h:45
NavState predict(const NavState &state_i, const imuBias::ConstantBias &bias_i, const Vector3 &n_gravity, OptionalJacobian< 9, 9 > H1={}, OptionalJacobian< 9, 6 > H2={}, OptionalJacobian< 9, 3 > H3={}) const
Predict state at time j, for a given gravity vector in the nav frame.
Definition PreintegrationBase.cpp:205
const std::shared_ptr< Params > & params() const
shared pointer to params
Definition PreintegrationBase.h:98
Params & p() const
const reference to params
Definition PreintegrationBase.h:103
Parameters for pre-integration: Usage: Create just a single Params and pass a shared pointer to the c...
Definition PreintegrationParams.h:37
Integrate on the 9D tangent space of the NavState manifold.
Definition TangentPreintegration.h:28
virtual Vector9 evaluateError(const ValueTypes &... x, OptionalMatrixTypeT< ValueTypes >... H) const=0
Nonlinear factor base class.
Definition NonlinearFactor.h:70
Gaussian implements the mathematical model |R*x|^2 = |y|^2 with R'*R=inv(Sigma) where y = whiten(x) =...
Definition NoiseModel.h:192