blob: ba7579deca08df1ffad1b55934ad6d88c5942bd9 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
Austin Schuh1d1e6ea2020-12-23 21:56:30 -08002// Copyright 2019 Google Inc. All rights reserved.
Austin Schuh70cc9552019-01-21 19:46:48 -08003// http://ceres-solver.org/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: keir@google.com (Keir Mierle)
30// sameeragarwal@google.com (Sameer Agarwal)
31
32#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
33#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
34
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080035#include <array>
36#include <memory>
Austin Schuh70cc9552019-01-21 19:46:48 -080037#include <vector>
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080038
Austin Schuh70cc9552019-01-21 19:46:48 -080039#include "ceres/internal/disable_warnings.h"
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080040#include "ceres/internal/port.h"
Austin Schuh70cc9552019-01-21 19:46:48 -080041
42namespace ceres {
43
44// Purpose: Sometimes parameter blocks x can overparameterize a problem
45//
46// min f(x)
47// x
48//
49// In that case it is desirable to choose a parameterization for the
50// block itself to remove the null directions of the cost. More
51// generally, if x lies on a manifold of a smaller dimension than the
52// ambient space that it is embedded in, then it is numerically and
53// computationally more effective to optimize it using a
54// parameterization that lives in the tangent space of that manifold
55// at each point.
56//
57// For example, a sphere in three dimensions is a 2 dimensional
58// manifold, embedded in a three dimensional space. At each point on
59// the sphere, the plane tangent to it defines a two dimensional
60// tangent space. For a cost function defined on this sphere, given a
61// point x, moving in the direction normal to the sphere at that point
62// is not useful. Thus a better way to do a local optimization is to
63// optimize over two dimensional vector delta in the tangent space at
64// that point and then "move" to the point x + delta, where the move
65// operation involves projecting back onto the sphere. Doing so
66// removes a redundant dimension from the optimization, making it
67// numerically more robust and efficient.
68//
69// More generally we can define a function
70//
71// x_plus_delta = Plus(x, delta),
72//
73// where x_plus_delta has the same size as x, and delta is of size
74// less than or equal to x. The function Plus, generalizes the
75// definition of vector addition. Thus it satisfies the identify
76//
77// Plus(x, 0) = x, for all x.
78//
79// A trivial version of Plus is when delta is of the same size as x
80// and
81//
82// Plus(x, delta) = x + delta
83//
84// A more interesting case if x is two dimensional vector, and the
85// user wishes to hold the first coordinate constant. Then, delta is a
86// scalar and Plus is defined as
87//
88// Plus(x, delta) = x + [0] * delta
89// [1]
90//
91// An example that occurs commonly in Structure from Motion problems
92// is when camera rotations are parameterized using Quaternion. There,
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080093// it is useful to only make updates orthogonal to that 4-vector
94// defining the quaternion. One way to do this is to let delta be a 3
Austin Schuh70cc9552019-01-21 19:46:48 -080095// dimensional vector and define Plus to be
96//
97// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
98//
99// The multiplication between the two 4-vectors on the RHS is the
100// standard quaternion product.
101//
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800102// Given f and a point x, optimizing f can now be restated as
Austin Schuh70cc9552019-01-21 19:46:48 -0800103//
104// min f(Plus(x, delta))
105// delta
106//
107// Given a solution delta to this problem, the optimal value is then
108// given by
109//
110// x* = Plus(x, delta)
111//
112// The class LocalParameterization defines the function Plus and its
113// Jacobian which is needed to compute the Jacobian of f w.r.t delta.
114class CERES_EXPORT LocalParameterization {
115 public:
116 virtual ~LocalParameterization();
117
118 // Generalization of the addition operation,
119 //
120 // x_plus_delta = Plus(x, delta)
121 //
122 // with the condition that Plus(x, 0) = x.
123 virtual bool Plus(const double* x,
124 const double* delta,
125 double* x_plus_delta) const = 0;
126
127 // The jacobian of Plus(x, delta) w.r.t delta at delta = 0.
128 //
129 // jacobian is a row-major GlobalSize() x LocalSize() matrix.
130 virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0;
131
132 // local_matrix = global_matrix * jacobian
133 //
134 // global_matrix is a num_rows x GlobalSize row major matrix.
135 // local_matrix is a num_rows x LocalSize row major matrix.
136 // jacobian(x) is the matrix returned by ComputeJacobian at x.
137 //
138 // This is only used by GradientProblem. For most normal uses, it is
139 // okay to use the default implementation.
140 virtual bool MultiplyByJacobian(const double* x,
141 const int num_rows,
142 const double* global_matrix,
143 double* local_matrix) const;
144
145 // Size of x.
146 virtual int GlobalSize() const = 0;
147
148 // Size of delta.
149 virtual int LocalSize() const = 0;
150};
151
152// Some basic parameterizations
153
154// Identity Parameterization: Plus(x, delta) = x + delta
155class CERES_EXPORT IdentityParameterization : public LocalParameterization {
156 public:
157 explicit IdentityParameterization(int size);
158 virtual ~IdentityParameterization() {}
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800159 bool Plus(const double* x,
160 const double* delta,
161 double* x_plus_delta) const override;
162 bool ComputeJacobian(const double* x, double* jacobian) const override;
163 bool MultiplyByJacobian(const double* x,
164 const int num_cols,
165 const double* global_matrix,
166 double* local_matrix) const override;
167 int GlobalSize() const override { return size_; }
168 int LocalSize() const override { return size_; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800169
170 private:
171 const int size_;
172};
173
174// Hold a subset of the parameters inside a parameter block constant.
175class CERES_EXPORT SubsetParameterization : public LocalParameterization {
176 public:
177 explicit SubsetParameterization(int size,
178 const std::vector<int>& constant_parameters);
179 virtual ~SubsetParameterization() {}
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800180 bool Plus(const double* x,
181 const double* delta,
182 double* x_plus_delta) const override;
183 bool ComputeJacobian(const double* x, double* jacobian) const override;
184 bool MultiplyByJacobian(const double* x,
185 const int num_cols,
186 const double* global_matrix,
187 double* local_matrix) const override;
188 int GlobalSize() const override {
Austin Schuh70cc9552019-01-21 19:46:48 -0800189 return static_cast<int>(constancy_mask_.size());
190 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800191 int LocalSize() const override { return local_size_; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800192
193 private:
194 const int local_size_;
195 std::vector<char> constancy_mask_;
196};
197
198// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
199// with * being the quaternion multiplication operator. Here we assume
200// that the first element of the quaternion vector is the real (cos
201// theta) part.
202class CERES_EXPORT QuaternionParameterization : public LocalParameterization {
203 public:
204 virtual ~QuaternionParameterization() {}
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800205 bool Plus(const double* x,
206 const double* delta,
207 double* x_plus_delta) const override;
208 bool ComputeJacobian(const double* x, double* jacobian) const override;
209 int GlobalSize() const override { return 4; }
210 int LocalSize() const override { return 3; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800211};
212
213// Implements the quaternion local parameterization for Eigen's representation
214// of the quaternion. Eigen uses a different internal memory layout for the
215// elements of the quaternion than what is commonly used. Specifically, Eigen
216// stores the elements in memory as [x, y, z, w] where the real part is last
217// whereas it is typically stored first. Note, when creating an Eigen quaternion
218// through the constructor the elements are accepted in w, x, y, z order. Since
219// Ceres operates on parameter blocks which are raw double pointers this
220// difference is important and requires a different parameterization.
221//
222// Plus(x, delta) = [sin(|delta|) delta / |delta|, cos(|delta|)] * x
223// with * being the quaternion multiplication operator.
224class CERES_EXPORT EigenQuaternionParameterization
225 : public ceres::LocalParameterization {
226 public:
227 virtual ~EigenQuaternionParameterization() {}
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800228 bool Plus(const double* x,
229 const double* delta,
230 double* x_plus_delta) const override;
231 bool ComputeJacobian(const double* x, double* jacobian) const override;
232 int GlobalSize() const override { return 4; }
233 int LocalSize() const override { return 3; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800234};
235
236// This provides a parameterization for homogeneous vectors which are commonly
237// used in Structure for Motion problems. One example where they are used is
238// in representing points whose triangulation is ill-conditioned. Here
239// it is advantageous to use an over-parameterization since homogeneous vectors
240// can represent points at infinity.
241//
242// The plus operator is defined as
243// Plus(x, delta) =
244// [sin(0.5 * |delta|) * delta / |delta|, cos(0.5 * |delta|)] * x
245// with * defined as an operator which applies the update orthogonal to x to
246// remain on the sphere. We assume that the last element of x is the scalar
247// component. The size of the homogeneous vector is required to be greater than
248// 1.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800249class CERES_EXPORT HomogeneousVectorParameterization
250 : public LocalParameterization {
Austin Schuh70cc9552019-01-21 19:46:48 -0800251 public:
252 explicit HomogeneousVectorParameterization(int size);
253 virtual ~HomogeneousVectorParameterization() {}
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800254 bool Plus(const double* x,
255 const double* delta,
256 double* x_plus_delta) const override;
257 bool ComputeJacobian(const double* x, double* jacobian) const override;
258 int GlobalSize() const override { return size_; }
259 int LocalSize() const override { return size_ - 1; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800260
261 private:
262 const int size_;
263};
264
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800265// This provides a parameterization for lines, where the line is
266// over-parameterized by an origin point and a direction vector. So the
267// parameter vector size needs to be two times the ambient space dimension,
268// where the first half is interpreted as the origin point and the second half
269// as the direction.
270//
271// The plus operator for the line direction is the same as for the
272// HomogeneousVectorParameterization. The update of the origin point is
273// perpendicular to the line direction before the update.
274//
275// This local parameterization is a special case of the affine Grassmannian
276// manifold (see https://en.wikipedia.org/wiki/Affine_Grassmannian_(manifold))
277// for the case Graff_1(R^n).
278template <int AmbientSpaceDimension>
279class LineParameterization : public LocalParameterization {
280 public:
281 static_assert(AmbientSpaceDimension >= 2,
282 "The ambient space must be at least 2");
283
284 bool Plus(const double* x,
285 const double* delta,
286 double* x_plus_delta) const override;
287 bool ComputeJacobian(const double* x, double* jacobian) const override;
288 int GlobalSize() const override { return 2 * AmbientSpaceDimension; }
289 int LocalSize() const override { return 2 * (AmbientSpaceDimension - 1); }
290};
291
Austin Schuh70cc9552019-01-21 19:46:48 -0800292// Construct a local parameterization by taking the Cartesian product
293// of a number of other local parameterizations. This is useful, when
294// a parameter block is the cartesian product of two or more
295// manifolds. For example the parameters of a camera consist of a
296// rotation and a translation, i.e., SO(3) x R^3.
297//
Austin Schuh70cc9552019-01-21 19:46:48 -0800298// Example usage:
299//
300// ProductParameterization product_param(new QuaterionionParameterization(),
301// new IdentityParameterization(3));
302//
303// is the local parameterization for a rigid transformation, where the
304// rotation is represented using a quaternion.
305class CERES_EXPORT ProductParameterization : public LocalParameterization {
306 public:
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800307 ProductParameterization(const ProductParameterization&) = delete;
308 ProductParameterization& operator=(const ProductParameterization&) = delete;
309 virtual ~ProductParameterization() {}
Austin Schuh70cc9552019-01-21 19:46:48 -0800310 //
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800311 // NOTE: The constructor takes ownership of the input local
Austin Schuh70cc9552019-01-21 19:46:48 -0800312 // parameterizations.
313 //
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800314 template <typename... LocalParams>
315 ProductParameterization(LocalParams*... local_params)
316 : local_params_(sizeof...(LocalParams)),
317 local_size_{0},
318 global_size_{0},
319 buffer_size_{0} {
320 constexpr int kNumLocalParams = sizeof...(LocalParams);
321 static_assert(kNumLocalParams >= 2,
322 "At least two local parameterizations must be specified.");
Austin Schuh70cc9552019-01-21 19:46:48 -0800323
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800324 using LocalParameterizationPtr = std::unique_ptr<LocalParameterization>;
Austin Schuh70cc9552019-01-21 19:46:48 -0800325
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800326 // Wrap all raw pointers into std::unique_ptr for exception safety.
327 std::array<LocalParameterizationPtr, kNumLocalParams> local_params_array{
328 LocalParameterizationPtr(local_params)...};
Austin Schuh70cc9552019-01-21 19:46:48 -0800329
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800330 // Initialize internal state.
331 for (int i = 0; i < kNumLocalParams; ++i) {
332 LocalParameterizationPtr& param = local_params_[i];
333 param = std::move(local_params_array[i]);
334
335 buffer_size_ =
336 std::max(buffer_size_, param->LocalSize() * param->GlobalSize());
337 global_size_ += param->GlobalSize();
338 local_size_ += param->LocalSize();
339 }
340 }
341
342 bool Plus(const double* x,
343 const double* delta,
344 double* x_plus_delta) const override;
345 bool ComputeJacobian(const double* x,
346 double* jacobian) const override;
347 int GlobalSize() const override { return global_size_; }
348 int LocalSize() const override { return local_size_; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800349
350 private:
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800351 std::vector<std::unique_ptr<LocalParameterization>> local_params_;
Austin Schuh70cc9552019-01-21 19:46:48 -0800352 int local_size_;
353 int global_size_;
354 int buffer_size_;
355};
356
357} // namespace ceres
358
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800359// clang-format off
Austin Schuh70cc9552019-01-21 19:46:48 -0800360#include "ceres/internal/reenable_warnings.h"
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800361#include "ceres/internal/line_parameterization.h"
Austin Schuh70cc9552019-01-21 19:46:48 -0800362
363#endif // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_