gtsam
Loading...
Searching...
No Matches
WnoaFactor.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
19
20#pragma once
21
22#include <gtsam/base/Lie.h>
23#include <gtsam/base/Testable.h>
24#include <gtsam/base/VectorSpace.h>
32
33#include <cassert>
34
35namespace gtsam {
36
53template <class Pose>
55 : public NoiseModelFactorN<Pose, typename traits<Pose>::TangentVector, Pose,
56 typename traits<Pose>::TangentVector> {
57 // Check that Pose type is a testable Lie group
58 GTSAM_CONCEPT_ASSERT(IsTestable<Pose>);
59 // We currently support vector spaces and Lie groups
60 static_assert(std::is_same_v<typename traits<Pose>::structure_category,
62 std::is_same_v<typename traits<Pose>::structure_category,
64 "Pose type must be either a Lie group or vector space");
65
66 GTSAM_CONCEPT_ASSERT(IsLieGroup<Pose>);
67
68 public:
69 static constexpr int dim = traits<Pose>::dimension;
70 using Velocity = typename gtsam::traits<Pose>::TangentVector;
71
72 private:
73 // Convenient typedefs
74 using MatrixN = Eigen::Matrix<double, dim, dim>;
75 using VectorN = Eigen::Matrix<double, dim, 1>;
76 using Matrix2N = Eigen::Matrix<double, 2 * dim, 2 * dim>;
77 using Vector2N = Eigen::Matrix<double, 2 * dim, 1>;
78 using MatrixNx2N = Eigen::Matrix<double, dim, 2 * dim>;
80 typedef WnoaMotionFactor This;
81
82 double deltaT_;
83
84 inline static const MatrixN kIdentity = MatrixN::Identity();
85 inline static const MatrixN kZero = MatrixN::Zero();
86
104 static void ComputeRelativePose(const Pose& p1, const Pose& p2,
105 const Velocity& v2, VectorN& xi,
106 MatrixN& invJr, MatrixN* dxi_dT1,
107 MatrixN* dxi_dT2, MatrixN* dvErr_dxi) {
108 // Local variable for the relative pose in the tangent space
109 // Note that p1 = T(t_k), p2 = T(t_{k+1})
110 // compute xi = log(T_k^-1 T_{k+1})^check
111 MatrixN dBetween_p1;
112 auto p12 = traits<Pose>::Between(p1, p2, dxi_dT1 ? &dBetween_p1 : nullptr);
113 xi = traits<Pose>::Logmap(p12, &invJr);
114 if (dxi_dT1) *dxi_dT1 = invJr * dBetween_p1;
115 if (dxi_dT2) *dxi_dT2 = invJr;
116
117 // Derivative of velocity error wrt xi
118 if (dvErr_dxi) {
119 // Zero for vector spaces, use an approximation for Lie groups
120 if constexpr (std::is_same_v<typename traits<Pose>::structure_category,
122 dvErr_dxi->setZero();
123 } else {
124 // For Lie groups
125 auto ad_v2 = Pose::adjointMap(v2);
126 auto ad_xi = Pose::adjointMap(xi);
127 *dvErr_dxi = -ad_v2 / 2.0 -
128 (Pose::adjointMap(ad_xi * v2) + ad_xi * ad_v2) / 12.0;
129 }
130 }
131 }
132
133 public:
134 // Provide access to the Matrix& version of evaluateError:
136
150 WnoaMotionFactor(const StateData& state_k, const StateData& state_kp1,
151 const VectorN& q_psd_diag)
152 : Base() {
153 // define keys
154 this->keys_ = {state_k.pose, state_k.velocity, state_kp1.pose,
155 state_kp1.velocity};
156 // define timestep
157 this->deltaT_ = state_kp1.time - state_k.time;
158 assert(this->deltaT_ > 0.0 &&
159 "Time difference between input states must be positive.");
160 // define noise model
161 this->noiseModel_ = BuildWnoaNoiseModel(this->deltaT_, q_psd_diag);
162 }
163
174 WnoaMotionFactor(Key poseKey0, Key velKey0, Key poseKey1, Key velKey1,
175 const double deltaT, const VectorN& q_psd_diag)
176 : Base(BuildWnoaNoiseModel(deltaT, q_psd_diag), poseKey0, velKey0,
177 poseKey1, velKey1),
178 deltaT_(deltaT) {}
179
180 ~WnoaMotionFactor() override {}
181
184
185 void print(
186 const std::string& s = "",
187 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
188 std::cout << s << "WnoaMotionFactor(" << keyFormatter(this->key1()) << ","
189 << keyFormatter(this->key2()) << "," << keyFormatter(this->key3())
190 << "," << keyFormatter(this->key4()) << ")\n";
191 this->noiseModel_->print(" noise model: ");
192 }
193
195 bool equals(const NonlinearFactor& expected,
196 double tol = 1e-9) const override {
197 const This* e = dynamic_cast<const This*>(&expected);
198 return e != nullptr && Base::equals(*e, tol);
199 }
200
201
220 Vector evaluateError(const Pose& p1, const Velocity& v1, const Pose& p2,
221 const Velocity& v2, OptionalMatrixType Hp1,
223 OptionalMatrixType Hv2) const override {
224 VectorN xi;
225 MatrixN invJr;
226 MatrixN dxi_dT1;
227 MatrixN dxi_dT2;
228 MatrixN dvErr_dxi;
229 if (Hp1 || Hp2) {
230 ComputeRelativePose(p1, p2, v2, xi, invJr, &dxi_dT1, &dxi_dT2,
231 &dvErr_dxi);
232 } else {
233 ComputeRelativePose(p1, p2, v2, xi, invJr, nullptr, nullptr, nullptr);
234 }
235
236 // Compute error for local state vector (pose, velocity) in tangent space
237 Vector2N err;
238 err.template head<dim>() = xi - deltaT_ * v1;
239 err.template tail<dim>() = invJr * v2 - v1;
240
241 // Compute Final Jacobians
242 if (Hp1) {
243 // Derivative of error wrt pose p1
244 Hp1->resize(2 * dim, dim);
245 Hp1->template block<dim, dim>(0, 0) = dxi_dT1;
246 Hp1->template block<dim, dim>(dim, 0) = dvErr_dxi * dxi_dT1;
247 }
248 if (Hv1) {
249 // Derivative of error wrt velocity v1
250 Hv1->resize(2 * dim, dim);
251 Hv1->template block<dim, dim>(0, 0) = -deltaT_ * kIdentity;
252 Hv1->template block<dim, dim>(dim, 0) = -kIdentity;
253 }
254 if (Hp2) {
255 // Derivative of error wrt pose p2
256 Hp2->resize(2 * dim, dim);
257 Hp2->template block<dim, dim>(0, 0) = dxi_dT2;
258 Hp2->template block<dim, dim>(dim, 0) = dvErr_dxi * dxi_dT2;
259 }
260 if (Hv2) {
261 // Derivative of error wrt velocity v2
262 Hv2->resize(2 * dim, dim);
263 Hv2->template block<dim, dim>(0, 0) = kZero;
264 Hv2->template block<dim, dim>(dim, 0) = invJr;
265 }
266
267 return err;
268 }
269
282 static Matrix2N BuildWnoaCovariance(double timestep,
283 const VectorN& q_psd_diag) {
284 //
285 Matrix2N covariance;
286 const MatrixN Q_diag = q_psd_diag.asDiagonal();
287 covariance.template topLeftCorner<dim, dim>() =
288 (1.0 / 3.0 * std::pow(timestep, 3)) * Q_diag;
289 covariance.template topRightCorner<dim, dim>() =
290 (0.5 * std::pow(timestep, 2)) * Q_diag;
291 covariance.template bottomLeftCorner<dim, dim>() =
292 (0.5 * std::pow(timestep, 2)) * Q_diag;
293 covariance.template bottomRightCorner<dim, dim>() = timestep * Q_diag;
294 return covariance;
295 }
296
304 static Matrix2N BuildInverseWnoaCovariance(double dt,
305 const VectorN& q_psd_diag) {
306 // construct the inverse covariance matrix for the WNOA factor
307 Matrix2N inverse_covariance;
308 const MatrixN Q_inv_diag = q_psd_diag.cwiseInverse().asDiagonal();
309 const double dt2 = dt * dt, dt3 = dt2 * dt;
310 inverse_covariance.template topLeftCorner<dim, dim>() =
311 (12.0 / dt3) * Q_inv_diag;
312 inverse_covariance.template topRightCorner<dim, dim>() =
313 (-6.0 / dt2) * Q_inv_diag;
314 inverse_covariance.template bottomLeftCorner<dim, dim>() =
315 (-6.0 / dt2) * Q_inv_diag;
316 inverse_covariance.template bottomRightCorner<dim, dim>() =
317 (4.0 / dt) * Q_inv_diag;
318
319 return inverse_covariance;
320 }
321
332 static inline noiseModel::Gaussian::shared_ptr BuildWnoaNoiseModel(
333 double timestep, const VectorN& q_psd_diag) {
335 BuildWnoaCovariance(timestep, q_psd_diag));
336 }
337
347 static Matrix2N TransitionFunction(double deltaT) {
348 // Construct the transition matrix for the WNOA factor
349 Matrix2N F;
350 F.template topLeftCorner<dim, dim>() = kIdentity;
351 F.template topRightCorner<dim, dim>() = deltaT * kIdentity;
352 F.template bottomLeftCorner<dim, dim>() = kZero;
353 F.template bottomRightCorner<dim, dim>() = kIdentity;
354 return F;
355 }
356
370 static Matrix2N ComputeJacobianPrev(const std::pair<Pose, Velocity>& pv1,
371 const std::pair<Pose, Velocity>& pv2,
372 double deltaT) {
373 // corresponds to F in (11.20) in SER
374 const auto& p1 = pv1.first;
375 const auto& p2 = pv2.first;
376 const auto& v2 = pv2.second;
377
378 VectorN xi;
379 MatrixN invJr;
380 MatrixN dxi_dT1;
381 MatrixN dvErr_dxi;
382 ComputeRelativePose(p1, p2, v2, xi, invJr, &dxi_dT1, nullptr, &dvErr_dxi);
383
384 Matrix2N F;
385 // first column is pose, second column is velocity
386 F.template topLeftCorner<dim, dim>() = dxi_dT1;
387 F.template topRightCorner<dim, dim>() = -deltaT * kIdentity;
388 F.template bottomLeftCorner<dim, dim>() = dvErr_dxi * dxi_dT1;
389 F.template bottomRightCorner<dim, dim>() = -kIdentity;
390 return F;
391 }
392
406 static Matrix2N ComputeJacobianNext(const std::pair<Pose, Velocity>& pv1,
407 const std::pair<Pose, Velocity>& pv2,
408 double deltaT) {
409 // corresponds to E in (11.21) in SER
410 const auto& p1 = pv1.first;
411 const auto& p2 = pv2.first;
412 const auto& v2 = pv2.second;
413
414 VectorN xi;
415 MatrixN invJr;
416 MatrixN dxi_dT2;
417 MatrixN dvErr_dxi;
418 ComputeRelativePose(p1, p2, v2, xi, invJr, nullptr, &dxi_dT2, &dvErr_dxi);
419
420 Matrix2N E;
421 // First column is pose, second column is velocity
422 E.template topLeftCorner<dim, dim>() = dxi_dT2;
423 E.template topRightCorner<dim, dim>() = kZero;
424 E.template bottomLeftCorner<dim, dim>() = dvErr_dxi * dxi_dT2;
425 E.template bottomRightCorner<dim, dim>() = invJr;
426 return -E;
427 }
428};
429
430// Make factors testable
431template <class Pose>
433 : public Testable<WnoaMotionFactor<Pose>> {};
434
435} // namespace gtsam
Concept check for values that can be used in unit tests.
Base class and basic functions for Lie types.
3D Point
3D Pose manifold SO(3) x R^3 and group SE(3)
2D Point
2D Pose
1D Point
Introduces a lightweight struct for identifying states in continuous-time estimation and interpolatio...
Non-linear factor base classes.
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
NoiseModelFactorT< Vector, ValueTypes... > NoiseModelFactorN
Noise model factor with N value types and dynamic-sized error vector.
Definition NoiseModelFactorN.h:561
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
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
tag to assert a type is a Lie group
Definition Lie.h:271
Lie Group Concept.
Definition Lie.h:377
A testable concept check that should be placed in applicable unit tests and in generic algorithms.
Definition Testable.h:59
A helper that implements the traits interface for GTSAM types.
Definition Testable.h:152
tag to assert a type is a vector space
Definition VectorSpace.h:21
KeyVector keys_
The keys involved in this factor.
Definition Factor.h:88
bool equals(const This &other, double tol=1e-9) const
check equality
Definition Factor.cpp:42
static shared_ptr Covariance(const Matrix &covariance, bool smart=true)
A Gaussian noise model created by specifying a covariance matrix.
Definition NoiseModel.cpp:116
virtual Vector evaluateError(const ValueTypes &... x, OptionalMatrixTypeT< ValueTypes >... H) const=0
Nonlinear factor base class.
Definition NonlinearFactor.h:70
WNOA (White Noise on Acceleration) motion prior factor.
Definition WnoaFactor.h:56
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition WnoaFactor.h:185
static Matrix2N TransitionFunction(double deltaT)
Transition matrix for the WNOA prior.
Definition WnoaFactor.h:347
static Matrix2N ComputeJacobianPrev(const std::pair< Pose, Velocity > &pv1, const std::pair< Pose, Velocity > &pv2, double deltaT)
Compute interpolation Jacobian with respect to the previous (left) state.
Definition WnoaFactor.h:370
bool equals(const NonlinearFactor &expected, double tol=1e-9) const override
equals
Definition WnoaFactor.h:195
Vector evaluateError(const Pose &p1, const Velocity &v1, const Pose &p2, const Velocity &v2, OptionalMatrixType Hp1, OptionalMatrixType Hv1, OptionalMatrixType Hp2, OptionalMatrixType Hv2) const override
Evaluate the WNOA factor residual and optional Jacobians.
Definition WnoaFactor.h:220
static Matrix2N BuildInverseWnoaCovariance(double dt, const VectorN &q_psd_diag)
Build the inverse of the WNOA discretized process covariance.
Definition WnoaFactor.h:304
static Matrix2N ComputeJacobianNext(const std::pair< Pose, Velocity > &pv1, const std::pair< Pose, Velocity > &pv2, double deltaT)
Compute interpolation Jacobian with respect to the next (right) state.
Definition WnoaFactor.h:406
static Matrix2N BuildWnoaCovariance(double timestep, const VectorN &q_psd_diag)
Build the continuous-time WNOA discretized process covariance.
Definition WnoaFactor.h:282
static noiseModel::Gaussian::shared_ptr BuildWnoaNoiseModel(double timestep, const VectorN &q_psd_diag)
Convenience helper to construct a Gaussian noise model from q_psd_diag.
Definition WnoaFactor.h:332
WnoaMotionFactor(Key poseKey0, Key velKey0, Key poseKey1, Key velKey1, const double deltaT, const VectorN &q_psd_diag)
Construct a WNOA factor given explicit keys and timestep.
Definition WnoaFactor.h:174
WnoaMotionFactor(const StateData &state_k, const StateData &state_kp1, const VectorN &q_psd_diag)
Construct a WNOA motion factor from two StateData entries.
Definition WnoaFactor.h:150
Lightweight container for states used for continuous-time estimation and interpolation.
Definition WnoaStateData.h:39
double time
Timestamp (seconds) associated with this state.
Definition WnoaStateData.h:42
Key pose
Key of the pose variable.
Definition WnoaStateData.h:40
Key velocity
Key of the velocity variable.
Definition WnoaStateData.h:41