gtsam
Loading...
Searching...
No Matches
SmartProjectionFactorBase.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
25
26#include <optional>
27#include <vector>
28
29namespace gtsam {
30
37template <class CAMERA>
39 private:
40 typedef SmartFactorBase<CAMERA> Base;
42
43 protected:
48
52 mutable std::vector<Pose3, Eigen::aligned_allocator<Pose3>>
55
56 public:
58 typedef std::shared_ptr<This> shared_ptr;
59
61 typedef CAMERA Camera;
62 typedef CameraSet<CAMERA> Cameras;
63
66 using JacobianFactorType = JacobianFactorQ<Base::Dim, 2>;
67 using SharedHessianFactor = std::shared_ptr<HessianFactorType>;
68 using SharedJacobianFactor = std::shared_ptr<JacobianFactorType>;
69
74
82 const SharedNoiseModel& sharedNoiseModel,
84 : Base(sharedNoiseModel),
85 params_(params),
86 result_(TriangulationResult::Degenerate()) {}
87
90
96 void print(
97 const std::string& s = "",
98 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
99 std::cout << s << "SmartProjectionFactor\n";
100 std::cout << "linearizationMode: " << params_.linearizationMode
101 << std::endl;
102 std::cout << "triangulationParameters:\n"
103 << params_.triangulation << std::endl;
104 std::cout << "result:\n" << result_ << std::endl;
105 Base::print("", keyFormatter);
106 }
107
109 bool equals(const NonlinearFactor& p, double tol = 1e-9) const override {
110 const This* e = dynamic_cast<const This*>(&p);
111 return e && params_.linearizationMode == e->params_.linearizationMode &&
112 Base::equals(p, tol);
113 }
114
122 bool decideIfTriangulate(const Cameras& cameras) const {
123 // Several calls to linearize will be done from the same linearization
124 // point, hence it is not needed to re-triangulate. Note that this is not
125 // yet "selecting linearization", that will come later, and we only check if
126 // the current linearization is the "same" (up to tolerance) w.r.t. the last
127 // time we triangulated the point.
128
129 size_t m = cameras.size();
130
131 bool retriangulate = false;
132
133 // Definitely true if we do not have a previous linearization point or the
134 // new linearization point includes more poses.
135 if (cameraPosesTriangulation_.empty() ||
136 cameras.size() != cameraPosesTriangulation_.size())
137 retriangulate = true;
138
139 // Otherwise, check poses against cache.
140 if (!retriangulate) {
141 for (size_t i = 0; i < cameras.size(); i++) {
142 if (!cameras[i].pose().equals(cameraPosesTriangulation_[i],
143 params_.retriangulationThreshold)) {
144 retriangulate =
145 true; // at least two poses are different, hence we retriangulate
146 break;
147 }
148 }
149 }
150
151 // Store the current poses used for triangulation if we will re-triangulate.
152 if (retriangulate) {
154 cameraPosesTriangulation_.reserve(m);
155 for (size_t i = 0; i < m; i++)
156 // cameraPosesTriangulation_[i] = cameras[i].pose();
157 cameraPosesTriangulation_.push_back(cameras[i].pose());
158 }
159
160 return retriangulate;
161 }
162
170 size_t m = cameras.size();
171 if (m < 2) // if we have a single pose the corresponding factor is
172 // uninformative
173 return TriangulationResult::Degenerate();
174
175 bool retriangulate = decideIfTriangulate(cameras);
176 if (retriangulate)
178 params_.triangulation);
179 return result_;
180 }
181
188 bool triangulateForLinearize(const Cameras& cameras) const {
189 triangulateSafe(cameras); // imperative, might reset result_
190 return bool(result_);
191 }
192
194 std::shared_ptr<RegularHessianFactor<Base::Dim>> createHessianFactor(
195 const Cameras& cameras, const double _lambda = 0.0,
196 bool diagonalDamping = false) const {
197 size_t numKeys = this->keys_.size();
198 // Create structures for Hessian Factors
199 KeyVector js;
200 std::vector<Matrix> Gs(numKeys * (numKeys + 1) / 2);
201 std::vector<Vector> gs(numKeys);
202
203 if (this->measured_.size() != cameras.size())
204 throw std::runtime_error(
205 "SmartProjectionHessianFactor: this->measured_"
206 ".size() inconsistent with input");
207
209
210 if (params_.degeneracyMode == ZERO_ON_DEGENERACY && !result_) {
211 // failed: return"empty" Hessian
212 for (Matrix& m : Gs) m = Matrix::Zero(Base::Dim, Base::Dim);
213 for (Vector& v : gs) v = Vector::Zero(Base::Dim);
214 return std::make_shared<RegularHessianFactor<Base::Dim>>(this->keys_, Gs,
215 gs, 0.0);
216 }
217
218 // Jacobian could be 3D Point3 OR 2D Unit3, difference is E.cols().
219 typename Base::FBlocks Fs;
220 Matrix E;
221 Vector b;
223
224 // Whiten using noise model
225 Base::whitenJacobians(Fs, E, b);
226
227 // build augmented hessian
228 SymmetricBlockMatrix augmentedHessian = //
229 Cameras::SchurComplement(Fs, E, b, _lambda, diagonalDamping);
230
231 return std::make_shared<RegularHessianFactor<Base::Dim>>(this->keys_,
232 augmentedHessian);
233 }
234
235 // Create RegularImplicitSchurFactor factor.
236 std::shared_ptr<RegularImplicitSchurFactor<CAMERA>>
237 createRegularImplicitSchurFactor(const Cameras& cameras,
238 double _lambda) const {
241 else
242 // failed: return empty
243 return std::shared_ptr<RegularImplicitSchurFactor<CAMERA>>();
244 }
245
247 std::shared_ptr<JacobianFactorQ<Base::Dim, 2>> createJacobianQFactor(
248 const Cameras& cameras, double _lambda) const {
251 else
252 // failed: return empty
253 return std::make_shared<JacobianFactorQ<Base::Dim, 2>>(this->keys_);
254 }
255
257 std::shared_ptr<JacobianFactorQ<Base::Dim, 2>> createJacobianQFactor(
258 const Values& values, double _lambda) const {
259 return createJacobianQFactor(this->cameras(values), _lambda);
260 }
261
263 std::shared_ptr<JacobianFactor> createJacobianSVDFactor(
264 const Cameras& cameras, double _lambda) const {
267 else
268 // failed: return empty
269 return std::make_shared<JacobianFactorSVD<Base::Dim, 2>>(this->keys_);
270 }
271
273 virtual std::shared_ptr<RegularHessianFactor<Base::Dim>> linearizeToHessian(
274 const Values& values, double _lambda = 0.0) const {
275 return createHessianFactor(this->cameras(values), _lambda);
276 }
277
279 virtual std::shared_ptr<RegularImplicitSchurFactor<CAMERA>>
280 linearizeToImplicit(const Values& values, double _lambda = 0.0) const {
281 return createRegularImplicitSchurFactor(this->cameras(values), _lambda);
282 }
283
285 virtual std::shared_ptr<JacobianFactorQ<Base::Dim, 2>> linearizeToJacobian(
286 const Values& values, double _lambda = 0.0) const {
287 return createJacobianQFactor(this->cameras(values), _lambda);
288 }
289
296 std::shared_ptr<GaussianFactor> linearizeDamped(
297 const Cameras& cameras, const double _lambda = 0.0) const {
298 // depending on flag set on construction we may linearize to different
299 // linear factors
300 switch (params_.linearizationMode) {
301 case HESSIAN:
302 return createHessianFactor(cameras, _lambda);
303 case IMPLICIT_SCHUR:
304 return createRegularImplicitSchurFactor(cameras, _lambda);
305 case JACOBIAN_SVD:
306 return createJacobianSVDFactor(cameras, _lambda);
307 case JACOBIAN_Q:
308 return createJacobianQFactor(cameras, _lambda);
309 default:
310 throw std::runtime_error("SmartFactorlinearize: unknown mode");
311 }
312 }
313
320 std::shared_ptr<GaussianFactor> linearizeDamped(
321 const Values& values, const double _lambda = 0.0) const {
322 // depending on flag set on construction we may linearize to different
323 // linear factors
324 Cameras cameras = this->cameras(values);
325 return linearizeDamped(cameras, _lambda);
326 }
327
329 std::shared_ptr<GaussianFactor> linearize(
330 const Values& values) const override {
331 return linearizeDamped(values);
332 }
333
338 bool triangulateAndComputeE(Matrix& E, const Cameras& cameras) const {
339 bool nonDegenerate = triangulateForLinearize(cameras);
340 if (nonDegenerate) {
341 cameras.project2(*result_, nullptr, &E);
342 }
343 return nonDegenerate;
344 }
345
350 bool triangulateAndComputeE(Matrix& E, const Values& values) const {
351 Cameras cameras = this->cameras(values);
353 }
354
358 void computeJacobiansWithTriangulatedPoint(typename Base::FBlocks& Fs,
359 Matrix& E, Vector& b,
360 const Cameras& cameras) const {
361 if (!result_) {
362 // Handle degeneracy
363 // TODO check flag whether we should do this
364 Unit3 backProjected =
365 cameras[0].backprojectPointAtInfinity(this->measured_.at(0));
366 Base::computeJacobians(Fs, E, b, cameras, backProjected);
367 } else {
368 // valid result: just return Base version
370 }
371 }
372
374 bool triangulateAndComputeJacobians(typename Base::FBlocks& Fs, Matrix& E,
375 Vector& b, const Values& values) const {
376 Cameras cameras = this->cameras(values);
377 bool nonDegenerate = triangulateForLinearize(cameras);
378 if (nonDegenerate) computeJacobiansWithTriangulatedPoint(Fs, E, b, cameras);
379 return nonDegenerate;
380 }
381
383 bool triangulateAndComputeJacobiansSVD(typename Base::FBlocks& Fs,
384 Matrix& Enull, Vector& b,
385 const Values& values) const {
386 Cameras cameras = this->cameras(values);
387 bool nonDegenerate = triangulateForLinearize(cameras);
388 if (nonDegenerate)
390 return nonDegenerate;
391 }
392
394 Vector reprojectionErrorAfterTriangulation(const Values& values) const {
395 Cameras cameras = this->cameras(values);
396 bool nonDegenerate = triangulateForLinearize(cameras);
397 if (nonDegenerate)
399 else
400 return Vector::Zero(cameras.size() * 2);
401 }
402
411 const Cameras& cameras, std::optional<Point3> externalPoint = {}) const {
412 if (externalPoint)
413 result_ = TriangulationResult(*externalPoint);
414 else
416
417 if (result_)
418 // All good, just use version in base class
420 else if (params_.degeneracyMode == HANDLE_INFINITY) {
421 // Otherwise, manage the exceptions with rotation-only factors
422 Unit3 backprojected =
423 cameras.front().backprojectPointAtInfinity(this->measured_.at(0));
424 return Base::totalReprojectionError(cameras, backprojected);
425 } else
426 // if we don't want to manage the exceptions we discard the factor
427 return 0.0;
428 }
429
431 double error(const Values& values) const override {
432 if (this->active(values)) {
433 return totalReprojectionError(this->cameras(values));
434 } else { // else of active flag
435 return 0.0;
436 }
437 }
438
441
443 TriangulationResult point(const Values& values) const {
444 Cameras cameras = this->cameras(values);
445 return triangulateSafe(cameras);
446 }
447
449 bool isValid() const { return result_.valid(); }
450
452 bool isDegenerate() const { return result_.degenerate(); }
453
455 bool isPointBehindCamera() const { return result_.behindCamera(); }
456
458 bool isOutlier() const { return result_.outlier(); }
459
461 bool isFarPoint() const { return result_.farPoint(); }
462
463 private:
464#if GTSAM_ENABLE_BOOST_SERIALIZATION
466 friend class boost::serialization::access;
467 template <class ARCHIVE>
468 void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
469 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
470 ar& BOOST_SERIALIZATION_NVP(params_);
471 ar& BOOST_SERIALIZATION_NVP(result_);
472 ar& BOOST_SERIALIZATION_NVP(cameraPosesTriangulation_);
473 }
474#endif
475};
476
478template <class CAMERA>
480 : public Testable<SmartProjectionFactorBase<CAMERA>> {};
481
482} // namespace gtsam
Functions for triangulation.
Base class to create smart factors on poses or cameras.
Collect common parameters for SmartProjection and SmartStereoProjection factors.
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
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
TriangulationResult triangulateSafe(const CameraSet< CAMERA > &cameras, const typename CAMERA::MeasurementVector &measured, const TriangulationParameters &params)
triangulateSafe: extensive checking of the outcome
Definition triangulation.h:706
noiseModel::Base::shared_ptr SharedNoiseModel
Aliases.
Definition NoiseModel.h:846
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
A helper that implements the traits interface for GTSAM types.
Definition Testable.h:152
A set of cameras, all with their own calibration.
Definition CameraSet.h:37
static SymmetricBlockMatrix SchurComplement(const std::vector< Eigen::Matrix< double, ZDim, ND >, Eigen::aligned_allocator< Eigen::Matrix< double, ZDim, ND > > > &Fs, const Matrix &E, const Eigen::Matrix< double, N, N > &P, const Vector &b)
Do Schur complement, given Jacobian as Fs,E,P, return SymmetricBlockMatrix G = F' * F - F' * E * P * ...
Definition CameraSet.h:175
TriangulationResult is an optional point, along with the reasons why it is invalid.
Definition triangulation.h:646
Represents a 3D point on a unit sphere.
Definition Unit3.h:44
KeyVector keys_
The keys involved in this factor.
Definition Factor.h:88
A HessianFactor where all variables have the same dimension D.
Definition RegularHessianFactor.h:57
Nonlinear factor base class.
Definition NonlinearFactor.h:70
virtual bool active(const Values &c) const
Checks whether a factor should be used based on a set of values.
Definition NonlinearFactor.h:143
A non-templated config holding any types of Manifold-group elements.
Definition Values.h:65
JacobianFactor for Schur complement that uses Q noise model.
Definition JacobianFactorQ.h:27
void computeJacobians(FBlocks &Fs, Matrix &E, Vector &b, const Cameras &cameras, const POINT &point) const
Compute F, E, and b (called below in both vanilla and SVD versions), where F is a vector of derivativ...
Definition SmartFactorBase.h:318
std::shared_ptr< JacobianFactor > createJacobianSVDFactor(const Cameras &cameras, const Point3 &point, double lambda=0.0) const
Return Jacobians as JacobianFactorSVD.
Definition SmartFactorBase.h:419
std::shared_ptr< RegularImplicitSchurFactor< CAMERA > > createRegularImplicitSchurFactor(const Cameras &cameras, const Point3 &point, double lambda=0.0, bool diagonalDamping=false) const
Return Jacobians as RegularImplicitSchurFactor with raw access.
Definition SmartFactorBase.h:389
static const int Dim
Camera dimension.
Definition SmartFactorBase.h:61
std::shared_ptr< JacobianFactorQ< Dim, ZDim > > createJacobianQFactor(const Cameras &cameras, const Point3 &point, double lambda=0.0, bool diagonalDamping=false) const
Return Jacobians as JacobianFactorQ.
Definition SmartFactorBase.h:402
virtual Cameras cameras(const Values &values) const
Collect all cameras: important that in key order.
Definition SmartFactorBase.h:165
Vector unwhitenedError(const Cameras &cameras, const POINT &point, typename Cameras::FBlocks *Fs=nullptr, Matrix *E=nullptr) const
Compute reprojection errors [h(x)-z] = [cameras.project(p)-z] and derivatives.
Definition SmartFactorBase.h:211
double totalReprojectionError(const Cameras &cameras, const POINT &point) const
Calculate the error of the factor.
Definition SmartFactorBase.h:300
void computeJacobiansSVD(FBlocks &Fs, Matrix &Enull, Vector &b, const Cameras &cameras, const POINT &point) const
SVD version that produces smaller Jacobian matrices by doing an SVD decomposition on E,...
Definition SmartFactorBase.h:333
ZVector measured_
Measurements for each of the m views.
Definition SmartFactorBase.h:80
SmartFactorBase()
Default Constructor, for serialization.
Definition SmartFactorBase.h:96
void whitenJacobians(FBlocks &F, Matrix &E, Vector &b) const
Whiten the Jacobians computed by computeJacobians using noiseModel_.
Definition SmartFactorBase.h:380
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition SmartFactorBase.h:178
CameraSet< CAMERA > Cameras
The CameraSet data structure is used to refer to a set of cameras.
Definition SmartFactorBase.h:93
bool equals(const NonlinearFactor &p, double tol=1e-9) const override
equals
Definition SmartFactorBase.h:191
Definition SmartFactorParams.h:42
LinearizationMode linearizationMode
How to linearize the factor.
Definition SmartFactorParams.h:44
DegeneracyMode degeneracyMode
How to linearize the factor.
Definition SmartFactorParams.h:45
Common base for monocular smart projection factors.
Definition SmartProjectionFactorBase.h:38
double totalReprojectionError(const Cameras &cameras, std::optional< Point3 > externalPoint={}) const
Calculate the error of the factor.
Definition SmartProjectionFactorBase.h:410
std::shared_ptr< JacobianFactor > createJacobianSVDFactor(const Cameras &cameras, double _lambda) const
Different (faster) way to compute a JacobianFactorSVD factor.
Definition SmartProjectionFactorBase.h:263
bool triangulateForLinearize(const Cameras &cameras) const
Possibly re-triangulate before calculating Jacobians.
Definition SmartProjectionFactorBase.h:188
bool isOutlier() const
return the outlier state
Definition SmartProjectionFactorBase.h:458
std::shared_ptr< GaussianFactor > linearize(const Values &values) const override
linearize
Definition SmartProjectionFactorBase.h:329
std::shared_ptr< JacobianFactorQ< Base::Dim, 2 > > createJacobianQFactor(const Cameras &cameras, double _lambda) const
Create JacobianFactorQ factor.
Definition SmartProjectionFactorBase.h:247
bool decideIfTriangulate(const Cameras &cameras) const
Check if the new linearization point is the same as the one used for previous triangulation.
Definition SmartProjectionFactorBase.h:122
bool equals(const NonlinearFactor &p, double tol=1e-9) const override
equals
Definition SmartProjectionFactorBase.h:109
std::shared_ptr< RegularHessianFactor< Base::Dim > > createHessianFactor(const Cameras &cameras, const double _lambda=0.0, bool diagonalDamping=false) const
Create a Hessianfactor that is an approximation of error(p).
Definition SmartProjectionFactorBase.h:194
RegularHessianFactor< Base::Dim > HessianFactorType
Exact linear-factor types produced by this camera specialization.
Definition SmartProjectionFactorBase.h:65
~SmartProjectionFactorBase() override
Virtual destructor.
Definition SmartProjectionFactorBase.h:89
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition SmartProjectionFactorBase.h:96
std::shared_ptr< GaussianFactor > linearizeDamped(const Cameras &cameras, const double _lambda=0.0) const
Linearize to Gaussian Factor.
Definition SmartProjectionFactorBase.h:296
CAMERA Camera
Shorthand for a set of cameras.
Definition SmartProjectionFactorBase.h:61
std::shared_ptr< This > shared_ptr
Shorthand for a smart pointer to a factor.
Definition SmartProjectionFactorBase.h:58
bool triangulateAndComputeE(Matrix &E, const Values &values) const
Triangulate and compute derivative of error with respect to point.
Definition SmartProjectionFactorBase.h:350
SmartProjectionFactorBase()
Default constructor, only for serialization.
Definition SmartProjectionFactorBase.h:73
virtual std::shared_ptr< RegularHessianFactor< Base::Dim > > linearizeToHessian(const Values &values, double _lambda=0.0) const
Linearize to a Hessianfactor.
Definition SmartProjectionFactorBase.h:273
TriangulationResult triangulateSafe(const Cameras &cameras) const
Call gtsam::triangulateSafe iff we need to re-triangulate.
Definition SmartProjectionFactorBase.h:169
SmartProjectionFactorBase(const SharedNoiseModel &sharedNoiseModel, const SmartProjectionParams &params=SmartProjectionParams())
Constructor.
Definition SmartProjectionFactorBase.h:81
bool triangulateAndComputeJacobians(typename Base::FBlocks &Fs, Matrix &E, Vector &b, const Values &values) const
Version that takes values, and creates the point.
Definition SmartProjectionFactorBase.h:374
std::shared_ptr< JacobianFactorQ< Base::Dim, 2 > > createJacobianQFactor(const Values &values, double _lambda) const
Create JacobianFactorQ factor, takes values.
Definition SmartProjectionFactorBase.h:257
std::shared_ptr< GaussianFactor > linearizeDamped(const Values &values, const double _lambda=0.0) const
Linearize to Gaussian Factor.
Definition SmartProjectionFactorBase.h:320
virtual std::shared_ptr< RegularImplicitSchurFactor< CAMERA > > linearizeToImplicit(const Values &values, double _lambda=0.0) const
Linearize to an Implicit Schur factor.
Definition SmartProjectionFactorBase.h:280
std::vector< Pose3, Eigen::aligned_allocator< Pose3 > > cameraPosesTriangulation_
Definition SmartProjectionFactorBase.h:53
bool isPointBehindCamera() const
return the cheirality status flag
Definition SmartProjectionFactorBase.h:455
bool triangulateAndComputeE(Matrix &E, const Cameras &cameras) const
Triangulate and compute derivative of error with respect to point.
Definition SmartProjectionFactorBase.h:338
bool isFarPoint() const
return the farPoint state
Definition SmartProjectionFactorBase.h:461
Vector reprojectionErrorAfterTriangulation(const Values &values) const
Calculate vector of re-projection errors, before applying noise model.
Definition SmartProjectionFactorBase.h:394
bool isDegenerate() const
return the degenerate state
Definition SmartProjectionFactorBase.h:452
virtual std::shared_ptr< JacobianFactorQ< Base::Dim, 2 > > linearizeToJacobian(const Values &values, double _lambda=0.0) const
Linearize to a JacobianfactorQ.
Definition SmartProjectionFactorBase.h:285
TriangulationResult result_
Definition SmartProjectionFactorBase.h:51
bool isValid() const
Is result valid?
Definition SmartProjectionFactorBase.h:449
TriangulationResult point() const
return the landmark
Definition SmartProjectionFactorBase.h:440
bool triangulateAndComputeJacobiansSVD(typename Base::FBlocks &Fs, Matrix &Enull, Vector &b, const Values &values) const
takes values
Definition SmartProjectionFactorBase.h:383
TriangulationResult point(const Values &values) const
COMPUTE the landmark.
Definition SmartProjectionFactorBase.h:443
double error(const Values &values) const override
Calculate total reprojection error.
Definition SmartProjectionFactorBase.h:431
void computeJacobiansWithTriangulatedPoint(typename Base::FBlocks &Fs, Matrix &E, Vector &b, const Cameras &cameras) const
Compute F, E only (called below in both vanilla and SVD versions) Assumes the point has been computed...
Definition SmartProjectionFactorBase.h:358