triangulation.cpp
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 
21 
24 
25 namespace gtsam {
26 
28  const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>&
29  projection_matrices,
30  const Point2Vector& measurements, double rank_tol) {
31  // number of cameras
32  size_t m = projection_matrices.size();
33 
34  // Allocate DLT matrix
35  Matrix A = Matrix::Zero(m * 2, 4);
36 
37  for (size_t i = 0; i < m; i++) {
38  size_t row = i * 2;
39  const Matrix34& projection = projection_matrices.at(i);
40  const Point2& p = measurements.at(i);
41 
42  // build system of equations
43  // [A_1; A_2; A_3] x = [b_1; b_2; b_3]
44  // [b_3 * A_1 - b_1 * A_3] x = 0
45  // [b_3 * A_2 - b_2 * A_3] x = 0
46  // A' x = 0
47  // A' 2x4 = [b_3 * A_1 - b_1 * A_3; b_3 * A_2 - b_2 * A_3]
48  A.row(row) = p.x() * projection.row(2) - projection.row(0);
49  A.row(row + 1) = p.y() * projection.row(2) - projection.row(1);
50  }
51  const auto [rank, error, v] = DLT(A, rank_tol);
52 
53  if (rank < 3) throw(TriangulationUnderconstrainedException());
54 
55  return v;
56 }
57 
59  const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>&
60  projection_matrices,
61  const std::vector<Unit3>& measurements, double rank_tol) {
62  // number of cameras
63  size_t m = projection_matrices.size();
64 
65  // Allocate DLT matrix
66  Matrix A = Matrix::Zero(m * 2, 4);
67 
68  for (size_t i = 0; i < m; i++) {
69  size_t row = i * 2;
70  const Matrix34& projection = projection_matrices.at(i);
71  const Point3& p =
72  measurements.at(i)
73  .point3(); // to get access to x,y,z of the bearing vector
74 
75  // build system of equations
76  A.row(row) = p.x() * projection.row(2) - p.z() * projection.row(0);
77  A.row(row + 1) = p.y() * projection.row(2) - p.z() * projection.row(1);
78  }
79  const auto [rank, error, v] = DLT(A, rank_tol);
80 
81  if (rank < 3) throw(TriangulationUnderconstrainedException());
82 
83  return v;
84 }
85 
86 Point3 triangulateLOST(const std::vector<Pose3>& poses,
87  const Point3Vector& calibratedMeasurements,
88  const SharedIsotropic& measurementNoise,
89  double rank_tol) {
90  size_t m = calibratedMeasurements.size();
91  assert(m == poses.size());
92 
93  // Construct the system matrices.
94  Matrix A = Matrix::Zero(m * 2, 3);
95  Matrix b = Matrix::Zero(m * 2, 1);
96 
97  for (size_t i = 0; i < m; i++) {
98  const Pose3& wTi = poses[i];
99  // TODO(akshay-krishnan): are there better ways to select j?
100  int j = (i + 1) % m;
101  const Pose3& wTj = poses[j];
102 
103  Point3 d_ij = wTj.translation() - wTi.translation();
104  Point3 wZi = wTi.rotation().rotate(calibratedMeasurements[i]);
105  Point3 wZj = wTj.rotation().rotate(calibratedMeasurements[j]);
106  double num_i = wZi.cross(wZj).norm();
107  double den_i = d_ij.cross(wZj).norm();
108 
109  // Handle q_i = 0 (or NaN), which arises if the measurement vectors, wZi and
110  // wZj, coincide (or the baseline vector coincides with the jth measurement
111  // vector).
112  if (num_i == 0 || den_i == 0) {
113  bool success = false;
114  for (size_t k = 2; k < m; k++) {
115  j = (i + k) % m;
116  const Pose3& wTj = poses[j];
117 
118  d_ij = wTj.translation() - wTi.translation();
119  wZj = wTj.rotation().rotate(calibratedMeasurements[j]);
120  num_i = wZi.cross(wZj).norm();
121  den_i = d_ij.cross(wZj).norm();
122  if (num_i > 0 && den_i > 0) {
123  success = true;
124  break;
125  }
126  }
127  if (!success) throw(TriangulationUnderconstrainedException());
128  }
129 
130  // Note: Setting q_i = 1.0 gives same results as DLT.
131  const double q_i = num_i / (measurementNoise->sigma() * den_i);
132 
133  const Matrix23 coefficientMat =
134  q_i * skewSymmetric(calibratedMeasurements[i]).topLeftCorner(2, 3) *
135  wTi.rotation().matrix().transpose();
136 
137  A.block<2, 3>(2 * i, 0) << coefficientMat;
138  b.block<2, 1>(2 * i, 0) << coefficientMat * wTi.translation();
139  }
140 
141  Eigen::ColPivHouseholderQR<Matrix> A_Qr = A.colPivHouseholderQr();
142  A_Qr.setThreshold(rank_tol);
143 
144  if (A_Qr.rank() < 3) throw(TriangulationUnderconstrainedException());
145 
146  return A_Qr.solve(b);
147 }
148 
150  const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>&
151  projection_matrices,
152  const Point2Vector& measurements, double rank_tol) {
153  Vector4 v =
154  triangulateHomogeneousDLT(projection_matrices, measurements, rank_tol);
155  // Create 3D point from homogeneous coordinates
156  return Point3(v.head<3>() / v[3]);
157 }
158 
160  const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>&
161  projection_matrices,
162  const std::vector<Unit3>& measurements, double rank_tol) {
163  // contrary to previous triangulateDLT, this is now taking Unit3 inputs
164  Vector4 v =
165  triangulateHomogeneousDLT(projection_matrices, measurements, rank_tol);
166  // Create 3D point from homogeneous coordinates
167  return Point3(v.head<3>() / v[3]);
168 }
169 
178  Key landmarkKey) {
179  // Maybe we should consider Gauss-Newton?
183  params.lambdaInitial = 1;
184  params.lambdaFactor = 10;
185  params.maxIterations = 100;
186  params.absoluteErrorTol = 1.0;
190 
191  LevenbergMarquardtOptimizer optimizer(graph, values, params);
192  Values result = optimizer.optimize();
193 
194  return result.at<Point3>(landmarkKey);
195 }
196 
197 } // namespace gtsam
Matrix3f m
std::vector< Point3, Eigen::aligned_allocator< Point3 > > Point3Vector
Definition: Point3.h:39
const Solve< ColPivHouseholderQR< _MatrixType >, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: SolverBase.h:106
const MATRIX::ConstRowXpr row(const MATRIX &A, size_t j)
Definition: base/Matrix.h:221
const Point3 & translation(OptionalJacobian< 3, 6 > Hself={}) const
get translation
Definition: Pose3.cpp:308
virtual const Values & optimize()
const ValueType at(Key j) const
Definition: Values-inl.h:204
Vector2 Point2
Definition: Point2.h:32
double lambdaFactor
The amount by which to multiply or divide lambda when adjusting lambda (default: 10.0)
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
std::tuple< int, double, Vector > DLT(const Matrix &A, double rank_tol)
Definition: Matrix.cpp:566
leaf::MyValues values
Verbosity verbosity
The printing verbosity during optimization (default SILENT)
noiseModel::Isotropic::shared_ptr SharedIsotropic
Definition: NoiseModel.h:745
NonlinearFactorGraph graph
double absoluteErrorTol
The maximum absolute error decrease to stop iterating (default 1e-5)
static const SmartProjectionParams params
Base class for all pinhole cameras.
Point3 triangulateLOST(const std::vector< Pose3 > &poses, const Point3Vector &calibratedMeasurements, const SharedIsotropic &measurementNoise, double rank_tol)
Triangulation using the LOST (Linear Optimal Sine Triangulation) algorithm proposed in https://arxiv...
Values result
STL compatible allocator to use with types requiring a non standrad alignment.
Definition: Memory.h:878
Point3 triangulateDLT(const std::vector< Matrix34, Eigen::aligned_allocator< Matrix34 >> &projection_matrices, const Point2Vector &measurements, double rank_tol)
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
Functions for triangulation.
Array< int, Dynamic, 1 > v
Point3 optimize(const NonlinearFactorGraph &graph, const Values &values, Key landmarkKey)
A nonlinear optimizer that uses the Levenberg-Marquardt trust-region scheme.
Exception thrown by triangulateDLT when SVD returns rank < 3.
Definition: triangulation.h:42
const G & b
Definition: Group.h:86
traits
Definition: chartTesting.h:28
ColPivHouseholderQR & setThreshold(const RealScalar &threshold)
Matrix3 skewSymmetric(double wx, double wy, double wz)
Definition: base/Matrix.h:400
Expression< Point2 > projection(f, p_cam)
Matrix3 matrix() const
Definition: Rot3M.cpp:218
std::vector< Point2, Eigen::aligned_allocator< Point2 > > Point2Vector
Definition: Point2.h:49
float * p
Vector4 triangulateHomogeneousDLT(const std::vector< Matrix34, Eigen::aligned_allocator< Matrix34 >> &projection_matrices, const Point2Vector &measurements, double rank_tol)
static double error
Definition: testRot3.cpp:37
const Rot3 & rotation(OptionalJacobian< 3, 6 > Hself={}) const
get rotation
Definition: Pose3.cpp:315
Vector3 Point3
Definition: Point3.h:38
Point3 rotate(const Point3 &p, OptionalJacobian< 3, 3 > H1={}, OptionalJacobian< 3, 3 > H2={}) const
Definition: Rot3M.cpp:148
VerbosityLM verbosityLM
The verbosity level for Levenberg-Marquardt (default: SILENT), see also NonlinearOptimizerParams::ver...
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
LinearSolverType linearSolverType
The type of linear solver to use in the nonlinear optimizer.
std::ptrdiff_t j
size_t maxIterations
The maximum iterations to stop iterating (default 100)
double lambdaInitial
The initial Levenberg-Marquardt damping term (default: 1e-5)


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:40:33