Skip to content

Commit cb46dde

Browse files
committed
Add preintegration on Gal(3) (W.I.P.)
- no IMU biases - preintegration covariance propagation is for RI error
1 parent 02b578e commit cb46dde

File tree

2 files changed

+85
-28
lines changed

2 files changed

+85
-28
lines changed

gtsam/navigation/GalileanImuFactor.cpp

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,65 @@ PreintegratedImuMeasurementsG::PreintegratedImuMeasurementsG(
2727

2828
// -- Integration API ---------------------------------------------------------
2929
void PreintegratedImuMeasurementsG::resetIntegration() {
30-
throw std::runtime_error("Not implemented: resetIntegration");
30+
preintMatrix_ = Gal3().Identity();
31+
preintMeasCov_.setZero();
32+
preintBiasJacobian_.setZero();
3133
}
3234

3335
void PreintegratedImuMeasurementsG::integrateMeasurement(
3436
const Vector3& measuredAcc, const Vector3& measuredOmega, double dt) {
35-
throw std::runtime_error("Not implemented: integrateMeasurement");
37+
// Correct measurements for bias and construct input
38+
Vector3 acc = biasHat_.correctAccelerometer(measuredAcc);
39+
Vector3 omega = biasHat_.correctGyroscope(measuredOmega);
40+
if (p_->body_P_sensor) {
41+
const auto& bRs = p_->body_P_sensor->rotation();
42+
acc = bRs * acc;
43+
omega = bRs * omega;
44+
}
45+
Vector10 wInput = Vector10::Zero();
46+
wInput.head<3>() = omega;
47+
wInput.segment<3>(3) = acc;
48+
wInput(9) = 1.0; // time scale
49+
Matrix10 Jl;
50+
Gal3 wExp = Gal3::Expmap(-wInput * dt, Jl).inverse();
51+
Matrix10 preintMatrixAdjoint = preintMatrix_.AdjointMap();
52+
53+
// Propagate mean - from eq. (22) in the paper
54+
preintMatrix_ = preintMatrix_.compose(wExp);
55+
56+
// Propagate covariance - from eq. (35) in the paper
57+
// IMPORTANT: the covariance propagation is based on the Right-Invariant (RI)
58+
// error since the equivariant error (34) is by definition RI. If we want to
59+
// use the Left-Invariant (LI) error to use NavState in the error formulation
60+
// for the factor, we need to change the covariance propagation accordingly
61+
// with the Adjoint. For RI error, the A_ matrix is identity.
62+
Matrix10 B_ = preintMatrixAdjoint * Jl * dt;
63+
Matrix10 Qd = Matrix10::Zero();
64+
Qd.block<3, 3>(0, 0) = p_->gyroscopeCovariance / dt;
65+
Qd.block<3, 3>(3, 3) = p_->accelerometerCovariance / dt;
66+
preintMeasCov_.noalias() += B_ * Qd * B_.transpose();
67+
68+
// Propagate bias Jacobian - from eq. (38) in the paper
69+
Matrix20 phiBiasJacobian = Matrix20::Identity();
70+
phiBiasJacobian.block<10, 10>(9, 9) = -preintMatrixAdjoint * Jl * dt;
71+
preintBiasJacobian_ = phiBiasJacobian * preintBiasJacobian_;
3672
}
3773

3874
// -- print / equals ----------------------------------------------------------
3975
void PreintegratedImuMeasurementsG::print(const std::string& s) const {
40-
throw std::runtime_error("Not implemented: print");
76+
std::cout << (s.empty() ? s : s + "\n")
77+
<< "PreintegratedImuMeasurementsG:" << std::endl;
78+
std::cout << " preintMatrix_: " << preintMatrix_ << std::endl;
79+
std::cout << " preintMeasCov_: \n" << preintMeasCov_ << std::endl;
80+
std::cout << " preintBiasJacobian_: \n" << preintBiasJacobian_ << std::endl;
81+
std::cout << " biasHat_: " << biasHat_.vector().transpose() << std::endl;
4182
}
4283
bool PreintegratedImuMeasurementsG::equals(
4384
const PreintegratedImuMeasurementsG& o, double tol) const {
44-
throw std::runtime_error("Not implemented: equals");
85+
return p_->equals(*o.p_, tol) && biasHat_.equals(o.biasHat_, tol) &&
86+
preintMatrix_.equals(o.preintMatrix_, tol) &&
87+
equal_with_abs_tol(preintMeasCov_, o.preintMeasCov_, tol) &&
88+
equal_with_abs_tol(preintBiasJacobian_, o.preintBiasJacobian_, tol);
4589
}
4690

4791
} // namespace gtsam

gtsam/navigation/GalileanImuFactor.h

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@
3232

3333
#include <gtsam/base/Matrix.h>
3434
#include <gtsam/basis/Chebyshev2.h>
35+
#include <gtsam/geometry/Gal3.h>
3536
#include <gtsam/navigation/ImuBias.h>
3637
#include <gtsam/navigation/ImuFactor.h>
3738
#include <gtsam/navigation/NavState.h>
3839
#include <gtsam/navigation/PreintegrationBase.h>
39-
#include <gtsam/navigation/PreintegrationParams.h>
40+
#include <gtsam/navigation/PreintegrationCombinedParams.h>
4041

4142
#include <optional>
4243
#include <vector>
@@ -47,8 +48,17 @@ namespace gtsam {
4748
class GTSAM_EXPORT PreintegratedImuMeasurementsG : public PreintegrationBase {
4849
using Base = PreintegrationBase;
4950
using Params = PreintegrationBase::Params;
50-
51-
std::shared_ptr<Params> p_;
51+
using Matrix10 = Eigen::Matrix<double, 10, 10>;
52+
using Matrix20 = Eigen::Matrix<double, 20, 20>;
53+
54+
protected:
55+
std::shared_ptr<Params> p_; ///< Preintegration parameters
56+
Gal3 preintMatrix_; ///< Preintegration Matrix (Galilean group element)
57+
Matrix20 preintBiasJacobian_; ///< Jacobian w.r.t. bias states
58+
Matrix10 preintMeasCov_; ///< Preintegration covariance
59+
///< The dimension of the preintegration covariance matrix is 10x10
60+
///< Because it includes Galilean Group (n=10)
61+
///< preintROTATION, preintVELOCITY, preintPOSITION, preintTIME
5262

5363
public:
5464
// Constructors (stubs)
@@ -57,29 +67,33 @@ class GTSAM_EXPORT PreintegratedImuMeasurementsG : public PreintegrationBase {
5767
const imuBias::ConstantBias& biasHat = {});
5868

5969
// Public (const) accessors – stubs
60-
double deltaTij() const {
61-
throw std::runtime_error("Not implemented: deltaTij");
62-
}
63-
Rot3 deltaRij() const override {
64-
throw std::runtime_error("Not implemented: deltaRij");
65-
}
66-
Vector3 deltaPij() const override {
67-
throw std::runtime_error("Not implemented: deltaPij");
68-
}
69-
Vector3 deltaVij() const override {
70-
throw std::runtime_error("Not implemented: deltaVij");
71-
}
70+
double deltaTij() const { return preintMatrix_.time(); }
71+
Rot3 deltaRij() const override { return preintMatrix_.rotation(); }
72+
Vector3 deltaPij() const override { return preintMatrix_.translation(); }
73+
Vector3 deltaVij() const override { return preintMatrix_.velocity(); }
7274
NavState deltaXij() const override {
73-
throw std::runtime_error("Not implemented: deltaXij");
74-
}
75-
Matrix9 preintMeasCov() const {
76-
throw std::runtime_error("Not implemented: preintMeasCov");
75+
return NavState(preintMatrix_.rotation(), preintMatrix_.translation(),
76+
preintMatrix_.velocity());
7777
}
78+
Matrix9 preintMeasCov() const { return preintMeasCov_.block<9, 9>(0, 0); }
7879

7980
// Bias correction (first‑order) – stub
8081
Vector9 biasCorrectedDelta(const imuBias::ConstantBias& bias_i,
8182
OptionalJacobian<9, 6> H = {}) const override {
82-
throw std::runtime_error("Not implemented: biasCorrectedDelta");
83+
const imuBias::ConstantBias biasIncr = bias_i - biasHat_;
84+
Gal3 correctedPreintMatrix =
85+
Gal3::Expmap(preintBiasJacobian_.block<10, 6>(0, 0) * biasIncr.vector())
86+
.compose(preintMatrix_);
87+
88+
Vector9 xi;
89+
NavState::dR(xi) = Rot3::Logmap(correctedPreintMatrix.rotation());
90+
NavState::dP(xi) = correctedPreintMatrix.translation();
91+
NavState::dV(xi) = correctedPreintMatrix.velocity();
92+
93+
if (H) {
94+
throw std::runtime_error("Not implemented: biasCorrectedDelta Jacobian");
95+
}
96+
return xi;
8397
}
8498

8599
// integration API
@@ -94,10 +108,9 @@ class GTSAM_EXPORT PreintegratedImuMeasurementsG : public PreintegrationBase {
94108
bool equals(const PreintegratedImuMeasurementsG& other,
95109
double tol = 1e-9) const;
96110

97-
void update(const Vector3& measuredAcc, const Vector3& measuredOmega,
98-
const double dt, Matrix9* A, Matrix93* B, Matrix93* C) override {
99-
throw std::runtime_error("Not implemented: update");
100-
}
111+
// void update(const Vector3& measuredAcc, const Vector3& measuredOmega,
112+
// const double dt, Matrix9* A, Matrix93* B, Matrix93* C) override
113+
// {}
101114
};
102115

103116
// Tell GTSAM about PreintegratedImuMeasurementsG print/equals:

0 commit comments

Comments
 (0)