gtsam
Loading...
Searching...
No Matches
ShonanAveraging.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010-2019, 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
18
19#pragma once
20
21#include <gtsam/base/Matrix.h>
22#include <gtsam/base/Vector.h>
23#include <gtsam/dllexport.h>
24#include <gtsam/geometry/Rot2.h>
25#include <gtsam/geometry/Rot3.h>
29#include <gtsam/slam/dataset.h>
30
31#include <Eigen/Sparse>
32#include <optional>
33#include <string>
34#include <type_traits>
35#include <utility>
36#include <vector>
37
38namespace gtsam {
41
43template <size_t d>
44struct GTSAM_EXPORT ShonanAveragingParameters {
45 // Select Rot2 or Rot3 interface based template parameter d
46 using Rot = typename std::conditional<d == 2, Rot2, Rot3>::type;
47 using Anchor = std::pair<size_t, Rot>;
48
49 // Parameters themselves:
52 Anchor anchor;
53 double alpha;
54 double beta;
55 double gamma;
60
61 ShonanAveragingParameters(const LevenbergMarquardtParams &lm =
62 LevenbergMarquardtParams::CeresDefaults(),
63 const std::string &method = "JACOBI",
64 double optimalityThreshold = -1e-4,
65 double alpha = 0.0, double beta = 1.0,
66 double gamma = 0.0);
67
68 LevenbergMarquardtParams getLMParams() const { return lm; }
69
70 void setOptimalityThreshold(double value) { optimalityThreshold = value; }
71 double getOptimalityThreshold() const { return optimalityThreshold; }
72
73 void setAnchor(size_t index, const Rot &value) { anchor = {index, value}; }
74 std::pair<size_t, Rot> getAnchor() const { return anchor; }
75
76 void setAnchorWeight(double value) { alpha = value; }
77 double getAnchorWeight() const { return alpha; }
78
79 void setKarcherWeight(double value) { beta = value; }
80 double getKarcherWeight() const { return beta; }
81
82 void setGaugesWeight(double value) { gamma = value; }
83 double getGaugesWeight() const { return gamma; }
84
85 void setUseHuber(bool value) { useHuber = value; }
86 bool getUseHuber() const { return useHuber; }
87
88 void setCertifyOptimality(bool value) { certifyOptimality = value; }
89 bool getCertifyOptimality() const { return certifyOptimality; }
90
92 void print(const std::string &s = "") const {
93 std::cout << (s.empty() ? s : s + " ");
94 std::cout << " ShonanAveragingParameters: " << std::endl;
95 std::cout << " alpha: " << alpha << std::endl;
96 std::cout << " beta: " << beta << std::endl;
97 std::cout << " gamma: " << gamma << std::endl;
98 std::cout << " useHuber: " << useHuber << std::endl;
99 }
100};
101
102using ShonanAveragingParameters2 = ShonanAveragingParameters<2>;
103using ShonanAveragingParameters3 = ShonanAveragingParameters<3>;
104
120template <size_t d>
121class GTSAM_EXPORT ShonanAveraging {
122 public:
123 using Sparse = Eigen::SparseMatrix<double>;
124
125 // Define the Parameters type and use its typedef of the rotation type:
126 using Parameters = ShonanAveragingParameters<d>;
127 using Rot = typename Parameters::Rot;
128
129 // We store SO(d) BetweenFactors to get noise model
130 using Measurements = std::vector<BinaryMeasurement<Rot>>;
131
132 private:
133 Parameters parameters_;
134 Measurements measurements_;
135 size_t nrUnknowns_;
136 Sparse D_; // Sparse (diagonal) degree matrix
137 Sparse Q_; // Sparse measurement matrix, == \tilde{R} in Eriksson18cvpr
138 Sparse L_; // connection Laplacian L = D - Q, needed for optimality check
139
141 NonlinearFactorGraph buildFastSyncGraph() const;
142
144 std::shared_ptr<LevenbergMarquardtOptimizer> createOptimizerAt(
145 size_t p, const Values &initial,
146 const std::optional<Ordering> &ordering) const;
147
149 std::pair<Values, double> run(const Values &initial, size_t min_p,
150 size_t max_p,
151 const std::optional<Ordering> &ordering) const;
152
157 Sparse buildQ() const;
158
160 Sparse buildD() const;
161
162 public:
165
168 ShonanAveraging(const Measurements &measurements,
169 const Parameters &parameters = Parameters());
170
174
176 size_t nrUnknowns() const { return nrUnknowns_; }
177
179 size_t numberMeasurements() const { return measurements_.size(); }
180
182 const BinaryMeasurement<Rot> &measurement(size_t k) const {
183 return measurements_[k];
184 }
185
192 Measurements makeNoiseModelRobust(const Measurements &measurements,
193 double k = 1.345) const {
194 Measurements robustMeasurements;
195 for (auto &measurement : measurements) {
196 auto model = measurement.noiseModel();
197 const auto &robust =
198 std::dynamic_pointer_cast<noiseModel::Robust>(model);
199
200 SharedNoiseModel robust_model;
201 // Check if the noise model is already robust
202 if (robust) {
203 robust_model = model;
204 } else {
205 // make robust
206 robust_model = noiseModel::Robust::Create(
207 noiseModel::mEstimator::Huber::Create(k), model);
208 }
210 measurement.measured(), robust_model);
211 robustMeasurements.push_back(meas);
212 }
213 return robustMeasurements;
214 }
215
217 const Rot &measured(size_t k) const { return measurements_[k].measured(); }
218
220 const KeyVector &keys(size_t k) const { return measurements_[k].keys(); }
221
225
226 Sparse D() const { return D_; }
227 Matrix denseD() const { return Matrix(D_); }
228 Sparse Q() const { return Q_; }
229 Matrix denseQ() const { return Matrix(Q_); }
230 Sparse L() const { return L_; }
231 Matrix denseL() const { return Matrix(L_); }
232
234 Sparse computeLambda(const Matrix &S) const;
235
237 Matrix computeLambda_(const Values &values) const {
238 return Matrix(computeLambda(values));
239 }
240
242 Matrix computeLambda_(const Matrix &S) const {
243 return Matrix(computeLambda(S));
244 }
245
247 Sparse computeA(const Values &values) const;
248
250 Sparse computeA(const Matrix &S) const;
251
253 Matrix computeA_(const Values &values) const {
254 return Matrix(computeA(values));
255 }
256
258 static Matrix StiefelElementMatrix(const Values &values);
259
264 double computeMinEigenValue(const Values &values,
265 Vector *minEigenVector) const;
266
268 double computeMinEigenValue(const Values& values) const {
269 return computeMinEigenValue(values, nullptr);
270 }
271
273 double computeMinEigenValue(const Values& values,
274 Vector& minEigenVector) const {
275 return computeMinEigenValue(values, &minEigenVector);
276 }
277
282 double computeMinEigenValueAP(const Values &values,
283 Vector *minEigenVector = nullptr) const;
284
286 Values roundSolutionS(const Matrix &S) const;
287
289 static VectorValues TangentVectorValues(size_t p, const Vector &v);
290
292 Matrix riemannianGradient(size_t p, const Values &values) const;
293
298 static Values LiftwithDescent(size_t p, const Values &values,
299 const Vector &minEigenVector);
300
309 size_t p, const Values &values, const Vector &minEigenVector,
310 double minEigenValue, double gradienTolerance = 1e-2,
311 double preconditionedGradNormTolerance = 1e-4) const;
315
320 NonlinearFactorGraph buildGraphAt(size_t p) const;
321
327 Values initializeRandomlyAt(size_t p, std::mt19937 &rng) const;
328
330 Values initializeRandomlyAt(size_t p) const;
331
336 double costAt(size_t p, const Values &values) const;
337
343 Sparse computeLambda(const Values &values) const;
344
350 std::pair<double, Vector> computeMinEigenVector(const Values &values) const;
351
356 bool checkOptimality(const Values &values) const;
357
364 std::shared_ptr<LevenbergMarquardtOptimizer> createOptimizerAt(
365 size_t p, const Values &initial) const;
366
373 Values tryOptimizingAt(size_t p, const Values &initial) const;
374
379 Values projectFrom(size_t p, const Values &values) const;
380
385 Values roundSolution(const Values &values) const;
386
388 template <class T>
389 static Values LiftTo(size_t p, const Values &values) {
390 Values result;
391 for (const auto& it : values.extract<T>()) {
392 result.insert(it.first, SOn::Lift(p, it.second.matrix()));
393 }
394 return result;
395 }
396
400
405 double cost(const Values &values) const;
406
414 Values initializeRandomly(std::mt19937 &rng) const;
415
417 Values initializeRandomly() const;
418
426 std::pair<Values, double> run(const Values &initial, size_t min_p = d,
427 size_t max_p = 10) const;
428
435 std::pair<Values, double> run(size_t min_p = d, size_t max_p = 10) const;
437
447 template <typename T>
448 inline std::vector<BinaryMeasurement<T>> maybeRobust(
449 const std::vector<BinaryMeasurement<T>> &measurements,
450 bool useRobustModel = false) const {
451 return useRobustModel ? makeNoiseModelRobust(measurements) : measurements;
452 }
453};
454
455// Subclasses for d=2 and d=3 that explicitly instantiate, as well as provide a
456// convenience interface with file access.
457
458class GTSAM_EXPORT ShonanAveraging2 : public ShonanAveraging<2> {
459 public:
460 ShonanAveraging2(const Measurements &measurements,
461 const Parameters &parameters = Parameters());
462 explicit ShonanAveraging2(std::string g2oFile,
463 const Parameters &parameters = Parameters());
464 ShonanAveraging2(const BetweenFactorPose2s &factors,
465 const Parameters &parameters = Parameters());
466};
467
468class GTSAM_EXPORT ShonanAveraging3 : public ShonanAveraging<3> {
469 public:
470 ShonanAveraging3(const Measurements &measurements,
471 const Parameters &parameters = Parameters());
472 explicit ShonanAveraging3(std::string g2oFile,
473 const Parameters &parameters = Parameters());
474
475 // TODO(frank): Deprecate after we land pybind wrapper
476 ShonanAveraging3(const BetweenFactorPose3s &factors,
477 const Parameters &parameters = Parameters());
478};
479} // namespace gtsam
typedef and functions to augment Eigen's MatrixXd
typedef and functions to augment Eigen's VectorXd
2D rotation
3D rotation represented as a rotation matrix or quaternion
Factor Graph Values.
Parameters for Levenberg-Marquardt trust-region scheme.
Binary measurement represents a measurement between two keys in a graph. A binary measurement is simi...
utility functions for loading datasets
Global functions in a separate testing namespace.
Definition chartTesting.h:28
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition Key.h:91
noiseModel::Base::shared_ptr SharedNoiseModel
Aliases.
Definition NoiseModel.h:846
static SO Lift(size_t n, const Eigen::MatrixBase< Derived > &R)
Definition SOn.h:105
VectorValues represents a collection of vector-valued variables associated each with a unique integer...
Definition VectorValues.h:73
This class performs Levenberg-Marquardt nonlinear optimization.
Definition LevenbergMarquardtOptimizer.h:35
Parameters for Levenberg-Marquardt optimization.
Definition LevenbergMarquardtParams.h:36
Definition NonlinearFactorGraph.h:57
A non-templated config holding any types of Manifold-group elements.
Definition Values.h:65
void insert(Key j, const Value &val)
Add a variable with the given j, throws KeyAlreadyExists<J> if j is already present.
Definition Values.cpp:170
Values extract(const KeyVector &keys) const
Returns a new Values holding copies of the values at the given keys, whatever their types.
Definition Values.cpp:252
Definition BinaryMeasurement.h:37
Parameters governing optimization etc.
Definition ShonanAveraging.h:44
double alpha
Definition ShonanAveraging.h:53
void print(const std::string &s="") const
Print the parameters and flags used for rotation averaging.
Definition ShonanAveraging.h:92
LevenbergMarquardtParams lm
Definition ShonanAveraging.h:50
bool useHuber
Definition ShonanAveraging.h:57
double optimalityThreshold
Definition ShonanAveraging.h:51
double beta
Definition ShonanAveraging.h:54
double gamma
Definition ShonanAveraging.h:55
Anchor anchor
Definition ShonanAveraging.h:52
bool certifyOptimality
Definition ShonanAveraging.h:59
Sparse D() const
Sparse version of D.
Definition ShonanAveraging.h:226
std::pair< double, Vector > computeMinEigenVector(const Values &values) const
Compute minimum eigenvalue for optimality check.
Definition ShonanAveraging.cpp:789
const BinaryMeasurement< Rot > & measurement(size_t k) const
k^th binary measurement
Definition ShonanAveraging.h:182
Measurements makeNoiseModelRobust(const Measurements &measurements, double k=1.345) const
Update factors to use robust Huber loss.
Definition ShonanAveraging.h:192
double computeMinEigenValue(const Values &values) const
Compute the minimum eigenvalue without requesting its eigenvector.
Definition ShonanAveraging.h:268
Values roundSolution(const Values &values) const
Project from SO(p)^N to Rot2^N or Rot3^N Values should be of type SO(p).
Definition ShonanAveraging.cpp:343
Values roundSolutionS(const Matrix &S) const
Project pxdN Stiefel manifold matrix S to Rot3^N.
std::vector< BinaryMeasurement< T > > maybeRobust(const std::vector< BinaryMeasurement< T > > &measurements, bool useRobustModel=false) const
Helper function to convert measurements to robust noise model if flag is set.
Definition ShonanAveraging.h:448
Values initializeWithDescent(size_t p, const Values &values, const Vector &minEigenVector, double minEigenValue, double gradienTolerance=1e-2, double preconditionedGradNormTolerance=1e-4) const
Given some values at p-1, return new values at p, by doing a line search along the descent direction,...
Definition ShonanAveraging.cpp:862
Sparse L() const
Sparse version of L.
Definition ShonanAveraging.h:230
static VectorValues TangentVectorValues(size_t p, const Vector &v)
Create a VectorValues with eigenvector v_i.
Definition ShonanAveraging.cpp:805
const Rot & measured(size_t k) const
k^th measurement, as a Rot.
Definition ShonanAveraging.h:217
static Values LiftwithDescent(size_t p, const Values &values, const Vector &minEigenVector)
Lift up the dimension of values in type SO(p-1) with descent direction provided by minEigenVector and...
Definition ShonanAveraging.cpp:853
Sparse Q() const
Sparse version of Q.
Definition ShonanAveraging.h:228
Matrix denseD() const
Dense version of D.
Definition ShonanAveraging.h:227
size_t nrUnknowns() const
Return number of unknowns.
Definition ShonanAveraging.h:176
Values projectFrom(size_t p, const Values &values) const
Project from SO(p) to Rot2 or Rot3 Values should be of type SO(p).
size_t numberMeasurements() const
Return number of measurements.
Definition ShonanAveraging.h:179
Matrix denseL() const
Dense version of L.
Definition ShonanAveraging.h:231
Matrix computeLambda_(const Matrix &S) const
Dense versions of computeLambda for wrapper/testing.
Definition ShonanAveraging.h:242
Sparse computeLambda(const Matrix &S) const
Version that takes pxdN Stiefel manifold elements.
Definition ShonanAveraging.cpp:478
Matrix denseQ() const
Dense version of Q.
Definition ShonanAveraging.h:229
double costAt(size_t p, const Values &values) const
Calculate cost for SO(p) Values should be of type SO(p).
Definition ShonanAveraging.cpp:194
const KeyVector & keys(size_t k) const
Keys for k^th measurement, as a vector of Key values.
Definition ShonanAveraging.h:220
ShonanAveraging(const Measurements &measurements, const Parameters &parameters=Parameters())
Construct from set of relative measurements (given as BetweenFactor<Rot3> for now) NoiseModel must be...
Definition ShonanAveraging.cpp:126
bool checkOptimality(const Values &values) const
Check optimality.
Definition ShonanAveraging.cpp:798
Sparse computeA(const Values &values) const
Compute A matrix whose Eigenvalues we will examine.
Definition ShonanAveraging.cpp:518
Values tryOptimizingAt(size_t p, const Values &initial) const
Try to optimize at SO(p).
Definition ShonanAveraging.cpp:231
Matrix computeLambda_(const Values &values) const
Dense versions of computeLambda for wrapper/testing.
Definition ShonanAveraging.h:237
Values initializeRandomlyAt(size_t p, std::mt19937 &rng) const
Create initial Values of type SO(p).
Definition ShonanAveraging.cpp:917
double computeMinEigenValue(const Values &values, Vector *minEigenVector) const
Compute minimum eigenvalue for optimality check.
Definition ShonanAveraging.cpp:755
Matrix riemannianGradient(size_t p, const Values &values) const
Calculate the riemannian gradient of F(values) at values.
Definition ShonanAveraging.cpp:827
double computeMinEigenValue(const Values &values, Vector &minEigenVector) const
Compute the minimum eigenvalue and write its eigenvector.
Definition ShonanAveraging.h:273
Matrix computeA_(const Values &values) const
Dense version of computeA for wrapper/testing.
Definition ShonanAveraging.h:253
NonlinearFactorGraph buildGraphAt(size_t p) const
Build graph for SO(p).
Definition ShonanAveraging.cpp:169
static Values LiftTo(size_t p, const Values &values)
Lift Values of type T to SO(p).
Definition ShonanAveraging.h:389