gtsam
Loading...
Searching...
No Matches
RelativeTranslationFactor.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
27
28#pragma once
29
30#include <gtsam/base/Matrix.h>
31#include <gtsam/constrained/QcqpProblem.h>
32#include <gtsam/constrained/QpCost.h>
33#include <gtsam/geometry/Rot2.h>
34#include <gtsam/geometry/Rot3.h>
37
38#include <cmath>
39#include <stdexcept>
40#include <string>
41#include <type_traits>
42
43namespace gtsam {
44
45template <int d>
47 : public NoiseModelFactorN<
48 typename std::conditional<d == 2, Rot2, Rot3>::type,
49 Eigen::Matrix<double, d, 1>, Eigen::Matrix<double, d, 1>> {
50 static_assert(d == 2 || d == 3,
51 "RelativeTranslationFactor supports d = 2 or 3.");
52
53 using Rot = typename std::conditional<d == 2, Rot2, Rot3>::type;
54 using Point = Eigen::Matrix<double, d, 1>;
56
57 Point measured_;
58 double weight_;
59
60 public:
62
70 RelativeTranslationFactor(Key rotationKey, Key translationKey1,
71 Key translationKey2, const Point& measured,
72 double weight)
73 : Base(noiseModel::Unit::Create(d), rotationKey, translationKey1,
74 translationKey2),
75 measured_(measured),
76 weight_(weight) {
77 if (weight <= 0.0) {
78 throw std::invalid_argument(
79 "RelativeTranslationFactor: weight must be positive.");
80 }
81 }
82
83 const Point& measured() const { return measured_; }
84 double weight() const { return weight_; }
85
86 void print(
87 const std::string& s = "",
88 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
89 std::cout << s << "RelativeTranslationFactor(" << keyFormatter(this->key1())
90 << "," << keyFormatter(this->key2()) << ","
91 << keyFormatter(this->key3()) << ") weight=" << weight_
92 << " measured=[" << measured_.transpose() << "]\n";
93 }
94
95 bool equals(const NonlinearFactor& other, double tol = 1e-9) const override {
96 const auto* e = dynamic_cast<const RelativeTranslationFactor*>(&other);
97 return e != nullptr && Base::equals(other, tol) &&
98 traits<Point>::Equals(measured_, e->measured_, tol) &&
99 std::abs(weight_ - e->weight_) < tol;
100 }
101
103 Vector evaluateError(const Rot& Ri, const Point& ti, const Point& tj,
105 OptionalMatrixType H3) const override {
106 const double sw = std::sqrt(weight_);
107
108 Matrix rotationJacobian;
109 const Point rotated =
110 Ri.rotate(measured_, H1 ? &rotationJacobian : nullptr);
111
112 if (H1) *H1 = -sw * rotationJacobian;
113 if (H2) *H2 = -sw * Matrix::Identity(d, d);
114 if (H3) *H3 = sw * Matrix::Identity(d, d);
115 return sw * (tj - ti - rotated);
116 }
117
118 gtsam::NonlinearFactor::shared_ptr clone() const override {
119 return std::static_pointer_cast<gtsam::NonlinearFactor>(
120 gtsam::NonlinearFactor::shared_ptr(
121 new RelativeTranslationFactor(*this)));
122 }
123
126 NonlinearEqualityConstraints* constraints,
127 size_t columnDimension = 1) const override {
128 if (columnDimension == 0) {
129 throw std::invalid_argument(
130 "RelativeTranslationFactor::qcqpFactors requires a positive "
131 "columnDimension.");
132 }
133 if (columnDimension == 1) {
134 qcqpFactorsForVector(costs, constraints);
135 return;
136 }
137 if (columnDimension < static_cast<size_t>(d)) {
138 throw std::invalid_argument(
139 "RelativeTranslationFactor::qcqpFactors requires columnDimension "
140 ">= d.");
141 }
142 if (!costs) {
143 throw std::invalid_argument(
144 "RelativeTranslationFactor::qcqpFactors: costs is null.");
145 }
146
147 const double sw = std::sqrt(weight_);
148 Matrix B = Matrix::Zero(1, d + 2);
149 B.block(0, 0, 1, d) = -sw * measured_.transpose(); // rotation row
150 B(0, d) = -sw; // pose i translation
151 B(0, d + 1) = sw; // pose j translation
152
153 const Matrix Q = B.transpose() * B;
154 const SymmetricBlockMatrix blockQ(std::vector<DenseIndex>{d, 1, 1}, Q);
155 costs->push_back(std::make_shared<QpCost>(
156 KeyVector{this->key1(), this->key2(), this->key3()}, blockQ,
157 columnDimension));
158 }
159
160 private:
162 void qcqpFactorsForVector(NonlinearFactorGraph* costs,
163 NonlinearEqualityConstraints* constraints) const {
164 if (!costs) {
165 throw std::invalid_argument(
166 "RelativeTranslationFactor::qcqpFactors: costs is null.");
167 }
168
169 constexpr int kRotationDim = traits<Rot>::QcqpVectorDim;
170 constexpr int kPointDim = traits<Point>::QcqpVectorDim;
171 const double sw = std::sqrt(weight_);
172
173 // Express R*measured in the non-homogeneous rotation coordinates.
174 Matrix rotateMeasurement;
175 if constexpr (d == 2) {
176 // [[mx,-my],[my,mx]] [c,s]' = R(c,s)*measured.
177 rotateMeasurement.resize(2, 2);
178 rotateMeasurement << measured_(0), -measured_(1), measured_(1),
179 measured_(0);
180 } else {
181 // (measured' kron I) vec(R), in column-major order.
182 rotateMeasurement = Matrix::Zero(d, d * d);
183 for (int column = 0; column < d; ++column) {
184 rotateMeasurement.block(0, column * d, d, d) =
185 measured_(column) * Matrix::Identity(d, d);
186 }
187 }
188
189 Matrix B = Matrix::Zero(d, kRotationDim + 2 * kPointDim);
190 B.block(0, 1, d, kRotationDim - 1) = -sw * rotateMeasurement;
191 B.block(0, kRotationDim + 1, d, d) = -sw * Matrix::Identity(d, d);
192 B.block(0, kRotationDim + kPointDim + 1, d, d) =
193 sw * Matrix::Identity(d, d);
194
195 InsertQcqpConstraints<Rot, 1>(this->key1(), constraints);
196 InsertQcqpConstraints<Point, 1>(this->key2(), constraints);
197 InsertQcqpConstraints<Point, 1>(this->key3(), constraints);
198
199 const Matrix Q = B.transpose() * B;
200 const SymmetricBlockMatrix blockQ(
201 std::vector<DenseIndex>{kRotationDim, kPointDim, kPointDim}, Q);
202 costs->push_back(std::make_shared<QpCost>(
203 KeyVector{this->key1(), this->key2(), this->key3()}, blockQ));
204 }
205};
206
207using RelativeTranslationFactor2 = RelativeTranslationFactor<2>;
208using RelativeTranslationFactor3 = RelativeTranslationFactor<3>;
209
210} // namespace gtsam
typedef and functions to augment Eigen's MatrixXd
2D rotation
3D rotation represented as a rotation matrix or quaternion
Base class for noise model factors with N variables.
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
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition Key.h:91
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
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
This class stores a dense matrix and allows it to be accessed as a collection of blocks.
Definition SymmetricBlockMatrix.h:80
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition FactorGraph.h:147
bool equals(const This &other, double tol=1e-9) const
check equality
Definition Factor.cpp:42
virtual Vector evaluateError(const ValueTypes &... x, OptionalMatrixTypeT< ValueTypes >... H) const=0
Nonlinear factor base class.
Definition NonlinearFactor.h:70
Definition NonlinearFactorGraph.h:57
Definition RelativeTranslationFactor.h:49
bool equals(const NonlinearFactor &other, double tol=1e-9) const override
Check if two factors are equal.
Definition RelativeTranslationFactor.h:95
Vector evaluateError(const Rot &Ri, const Point &ti, const Point &tj, OptionalMatrixType H1, OptionalMatrixType H2, OptionalMatrixType H3) const override
Weighted residual sqrt(weight) * (t_j - t_i - R_i * measured).
Definition RelativeTranslationFactor.h:103
RelativeTranslationFactor(Key rotationKey, Key translationKey1, Key translationKey2, const Point &measured, double weight)
Definition RelativeTranslationFactor.h:70
void qcqpFactors(NonlinearFactorGraph *costs, NonlinearEqualityConstraints *constraints, size_t columnDimension=1) const override
Add this translation factor as a QCQP cost when traits exist.
Definition RelativeTranslationFactor.h:125
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
Print.
Definition RelativeTranslationFactor.h:86
gtsam::NonlinearFactor::shared_ptr clone() const override
Creates a shared_ptr clone of the factor - needs to be specialized to allow for subclasses.
Definition RelativeTranslationFactor.h:118