manifold.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2022 Google Inc. All rights reserved.
  3. // 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: sameeragarwal@google.com (Sameer Agarwal)
  30. #ifndef CERES_PUBLIC_MANIFOLD_H_
  31. #define CERES_PUBLIC_MANIFOLD_H_
  32. #include <Eigen/Core>
  33. #include <algorithm>
  34. #include <array>
  35. #include <memory>
  36. #include <utility>
  37. #include <vector>
  38. #include "ceres/internal/disable_warnings.h"
  39. #include "ceres/internal/export.h"
  40. #include "ceres/types.h"
  41. #include "glog/logging.h"
  42. namespace ceres {
  43. // In sensor fusion problems, often we have to model quantities that live in
  44. // spaces known as Manifolds, for example the rotation/orientation of a sensor
  45. // that is represented by a quaternion.
  46. //
  47. // Manifolds are spaces which locally look like Euclidean spaces. More
  48. // precisely, at each point on the manifold there is a linear space that is
  49. // tangent to the manifold. It has dimension equal to the intrinsic dimension of
  50. // the manifold itself, which is less than or equal to the ambient space in
  51. // which the manifold is embedded.
  52. //
  53. // For example, the tangent space to a point on a sphere in three dimensions is
  54. // the two dimensional plane that is tangent to the sphere at that point. There
  55. // are two reasons tangent spaces are interesting:
  56. //
  57. // 1. They are Eucliean spaces so the usual vector space operations apply there,
  58. // which makes numerical operations easy.
  59. // 2. Movement in the tangent space translate into movements along the manifold.
  60. // Movements perpendicular to the tangent space do not translate into
  61. // movements on the manifold.
  62. //
  63. // Returning to our sphere example, moving in the 2 dimensional plane
  64. // tangent to the sphere and projecting back onto the sphere will move you away
  65. // from the point you started from but moving along the normal at the same point
  66. // and the projecting back onto the sphere brings you back to the point.
  67. //
  68. // The Manifold interface defines two operations (and their derivatives)
  69. // involving the tangent space, allowing filtering and optimization to be
  70. // performed on said manifold:
  71. //
  72. // 1. x_plus_delta = Plus(x, delta)
  73. // 2. delta = Minus(x_plus_delta, x)
  74. //
  75. // "Plus" computes the result of moving along delta in the tangent space at x,
  76. // and then projecting back onto the manifold that x belongs to. In Differential
  77. // Geometry this is known as a "Retraction". It is a generalization of vector
  78. // addition in Euclidean spaces.
  79. //
  80. // Given two points on the manifold, "Minus" computes the change delta to x in
  81. // the tangent space at x, that will take it to x_plus_delta.
  82. //
  83. // Let us now consider two examples.
  84. //
  85. // The Euclidean space R^n is the simplest example of a manifold. It has
  86. // dimension n (and so does its tangent space) and Plus and Minus are the
  87. // familiar vector sum and difference operations.
  88. //
  89. // Plus(x, delta) = x + delta = y,
  90. // Minus(y, x) = y - x = delta.
  91. //
  92. // A more interesting case is SO(3), the special orthogonal group in three
  93. // dimensions - the space of 3x3 rotation matrices. SO(3) is a three dimensional
  94. // manifold embedded in R^9 or R^(3x3). So points on SO(3) are represented using
  95. // 9 dimensional vectors or 3x3 matrices, and points in its tangent spaces are
  96. // represented by 3 dimensional vectors.
  97. //
  98. // Defining Plus and Minus are defined in terms of the matrix Exp and Log
  99. // operations as follows:
  100. //
  101. // Let Exp(p, q, r) = [cos(theta) + cp^2, -sr + cpq , sq + cpr ]
  102. // [sr + cpq , cos(theta) + cq^2, -sp + cqr ]
  103. // [-sq + cpr , sp + cqr , cos(theta) + cr^2]
  104. //
  105. // where: theta = sqrt(p^2 + q^2 + r^2)
  106. // s = sinc(theta)
  107. // c = (1 - cos(theta))/theta^2
  108. //
  109. // and Log(x) = 1/(2 sinc(theta))[x_32 - x_23, x_13 - x_31, x_21 - x_12]
  110. //
  111. // where: theta = acos((Trace(x) - 1)/2)
  112. //
  113. // Then,
  114. //
  115. // Plus(x, delta) = x Exp(delta)
  116. // Minus(y, x) = Log(x^T y)
  117. //
  118. // For Plus and Minus to be mathematically consistent, the following identities
  119. // must be satisfied at all points x on the manifold:
  120. //
  121. // 1. Plus(x, 0) = x.
  122. // 2. For all y, Plus(x, Minus(y, x)) = y.
  123. // 3. For all delta, Minus(Plus(x, delta), x) = delta.
  124. // 4. For all delta_1, delta_2
  125. // |Minus(Plus(x, delta_1), Plus(x, delta_2)) <= |delta_1 - delta_2|
  126. //
  127. // Briefly:
  128. // (1) Ensures that the tangent space is "centered" at x, and the zero vector is
  129. // the identity element.
  130. // (2) Ensures that any y can be reached from x.
  131. // (3) Ensures that Plus is an injective (one-to-one) map.
  132. // (4) Allows us to define a metric on the manifold.
  133. //
  134. // Additionally we require that Plus and Minus be sufficiently smooth. In
  135. // particular they need to be differentiable everywhere on the manifold.
  136. //
  137. // For more details, please see
  138. //
  139. // "Integrating Generic Sensor Fusion Algorithms with Sound State
  140. // Representations through Encapsulation of Manifolds"
  141. // By C. Hertzberg, R. Wagner, U. Frese and L. Schroder
  142. // https://arxiv.org/pdf/1107.1119.pdf
  143. class CERES_EXPORT Manifold {
  144. public:
  145. virtual ~Manifold();
  146. // Dimension of the ambient space in which the manifold is embedded.
  147. virtual int AmbientSize() const = 0;
  148. // Dimension of the manifold/tangent space.
  149. virtual int TangentSize() const = 0;
  150. // x_plus_delta = Plus(x, delta),
  151. //
  152. // A generalization of vector addition in Euclidean space, Plus computes the
  153. // result of moving along delta in the tangent space at x, and then projecting
  154. // back onto the manifold that x belongs to.
  155. //
  156. // x and x_plus_delta are AmbientSize() vectors.
  157. // delta is a TangentSize() vector.
  158. //
  159. // Return value indicates if the operation was successful or not.
  160. virtual bool Plus(const double* x,
  161. const double* delta,
  162. double* x_plus_delta) const = 0;
  163. // Compute the derivative of Plus(x, delta) w.r.t delta at delta = 0, i.e.
  164. //
  165. // (D_2 Plus)(x, 0)
  166. //
  167. // jacobian is a row-major AmbientSize() x TangentSize() matrix.
  168. //
  169. // Return value indicates whether the operation was successful or not.
  170. virtual bool PlusJacobian(const double* x, double* jacobian) const = 0;
  171. // tangent_matrix = ambient_matrix * (D_2 Plus)(x, 0)
  172. //
  173. // ambient_matrix is a row-major num_rows x AmbientSize() matrix.
  174. // tangent_matrix is a row-major num_rows x TangentSize() matrix.
  175. //
  176. // Return value indicates whether the operation was successful or not.
  177. //
  178. // This function is only used by the GradientProblemSolver, where the
  179. // dimension of the parameter block can be large and it may be more efficient
  180. // to compute this product directly rather than first evaluating the Jacobian
  181. // into a matrix and then doing a matrix vector product.
  182. //
  183. // Because this is not an often used function, we provide a default
  184. // implementation for convenience. If performance becomes an issue then the
  185. // user should consider implementing a specialization.
  186. virtual bool RightMultiplyByPlusJacobian(const double* x,
  187. const int num_rows,
  188. const double* ambient_matrix,
  189. double* tangent_matrix) const;
  190. // y_minus_x = Minus(y, x)
  191. //
  192. // Given two points on the manifold, Minus computes the change to x in the
  193. // tangent space at x, that will take it to y.
  194. //
  195. // x and y are AmbientSize() vectors.
  196. // y_minus_x is a TangentSize() vector.
  197. //
  198. // Return value indicates if the operation was successful or not.
  199. virtual bool Minus(const double* y,
  200. const double* x,
  201. double* y_minus_x) const = 0;
  202. // Compute the derivative of Minus(y, x) w.r.t y at y = x, i.e
  203. //
  204. // (D_1 Minus) (x, x)
  205. //
  206. // Jacobian is a row-major TangentSize() x AmbientSize() matrix.
  207. //
  208. // Return value indicates whether the operation was successful or not.
  209. virtual bool MinusJacobian(const double* x, double* jacobian) const = 0;
  210. };
  211. // The Euclidean manifold is another name for the ordinary vector space R^size,
  212. // where the plus and minus operations are the usual vector addition and
  213. // subtraction:
  214. // Plus(x, delta) = x + delta
  215. // Minus(y, x) = y - x.
  216. //
  217. // The class works with dynamic and static ambient space dimensions. If the
  218. // ambient space dimensions is know at compile time use
  219. //
  220. // EuclideanManifold<3> manifold;
  221. //
  222. // If the ambient space dimensions is not known at compile time the template
  223. // parameter needs to be set to ceres::DYNAMIC and the actual dimension needs
  224. // to be provided as a constructor argument:
  225. //
  226. // EuclideanManifold<ceres::DYNAMIC> manifold(ambient_dim);
  227. template <int Size>
  228. class EuclideanManifold final : public Manifold {
  229. public:
  230. static_assert(Size == ceres::DYNAMIC || Size >= 0,
  231. "The size of the manifold needs to be non-negative.");
  232. static_assert(ceres::DYNAMIC == Eigen::Dynamic,
  233. "ceres::DYNAMIC needs to be the same as Eigen::Dynamic.");
  234. EuclideanManifold() : size_{Size} {
  235. static_assert(
  236. Size != ceres::DYNAMIC,
  237. "The size is set to dynamic. Please call the constructor with a size.");
  238. }
  239. explicit EuclideanManifold(int size) : size_(size) {
  240. if (Size != ceres::DYNAMIC) {
  241. CHECK_EQ(Size, size)
  242. << "Specified size by template parameter differs from the supplied "
  243. "one.";
  244. } else {
  245. CHECK_GE(size_, 0)
  246. << "The size of the manifold needs to be non-negative.";
  247. }
  248. }
  249. int AmbientSize() const override { return size_; }
  250. int TangentSize() const override { return size_; }
  251. bool Plus(const double* x_ptr,
  252. const double* delta_ptr,
  253. double* x_plus_delta_ptr) const override {
  254. Eigen::Map<const AmbientVector> x(x_ptr, size_);
  255. Eigen::Map<const AmbientVector> delta(delta_ptr, size_);
  256. Eigen::Map<AmbientVector> x_plus_delta(x_plus_delta_ptr, size_);
  257. x_plus_delta = x + delta;
  258. return true;
  259. }
  260. bool PlusJacobian(const double* x_ptr, double* jacobian_ptr) const override {
  261. Eigen::Map<MatrixJacobian> jacobian(jacobian_ptr, size_, size_);
  262. jacobian.setIdentity();
  263. return true;
  264. }
  265. bool RightMultiplyByPlusJacobian(const double* x,
  266. const int num_rows,
  267. const double* ambient_matrix,
  268. double* tangent_matrix) const override {
  269. std::copy_n(ambient_matrix, num_rows * size_, tangent_matrix);
  270. return true;
  271. }
  272. bool Minus(const double* y_ptr,
  273. const double* x_ptr,
  274. double* y_minus_x_ptr) const override {
  275. Eigen::Map<const AmbientVector> x(x_ptr, size_);
  276. Eigen::Map<const AmbientVector> y(y_ptr, size_);
  277. Eigen::Map<AmbientVector> y_minus_x(y_minus_x_ptr, size_);
  278. y_minus_x = y - x;
  279. return true;
  280. }
  281. bool MinusJacobian(const double* x_ptr, double* jacobian_ptr) const override {
  282. Eigen::Map<MatrixJacobian> jacobian(jacobian_ptr, size_, size_);
  283. jacobian.setIdentity();
  284. return true;
  285. }
  286. private:
  287. static constexpr bool IsDynamic = (Size == ceres::DYNAMIC);
  288. using AmbientVector = Eigen::Matrix<double, Size, 1>;
  289. using MatrixJacobian = Eigen::Matrix<double, Size, Size, Eigen::RowMajor>;
  290. int size_{};
  291. };
  292. // Hold a subset of the parameters inside a parameter block constant.
  293. class CERES_EXPORT SubsetManifold final : public Manifold {
  294. public:
  295. SubsetManifold(int size, const std::vector<int>& constant_parameters);
  296. int AmbientSize() const override;
  297. int TangentSize() const override;
  298. bool Plus(const double* x,
  299. const double* delta,
  300. double* x_plus_delta) const override;
  301. bool PlusJacobian(const double* x, double* jacobian) const override;
  302. bool RightMultiplyByPlusJacobian(const double* x,
  303. const int num_rows,
  304. const double* ambient_matrix,
  305. double* tangent_matrix) const override;
  306. bool Minus(const double* y,
  307. const double* x,
  308. double* y_minus_x) const override;
  309. bool MinusJacobian(const double* x, double* jacobian) const override;
  310. private:
  311. const int tangent_size_ = 0;
  312. std::vector<bool> constancy_mask_;
  313. };
  314. // Implements the manifold for a Hamilton quaternion as defined in
  315. // https://en.wikipedia.org/wiki/Quaternion. Quaternions are represented as
  316. // unit norm 4-vectors, i.e.
  317. //
  318. // q = [q0; q1; q2; q3], |q| = 1
  319. //
  320. // is the ambient space representation.
  321. //
  322. // q0 scalar part.
  323. // q1 coefficient of i.
  324. // q2 coefficient of j.
  325. // q3 coefficient of k.
  326. //
  327. // where: i*i = j*j = k*k = -1 and i*j = k, j*k = i, k*i = j.
  328. //
  329. // The tangent space is R^3, which relates to the ambient space through the
  330. // Plus and Minus operations defined as:
  331. //
  332. // Plus(x, delta) = [cos(|delta|); sin(|delta|) * delta / |delta|] * x
  333. // Minus(y, x) = to_delta(y * x^{-1})
  334. //
  335. // where "*" is the quaternion product and because q is a unit quaternion
  336. // (|q|=1), q^-1 = [q0; -q1; -q2; -q3]
  337. //
  338. // and to_delta( [q0; u_{3x1}] ) = u / |u| * atan2(|u|, q0)
  339. class CERES_EXPORT QuaternionManifold final : public Manifold {
  340. public:
  341. int AmbientSize() const override { return 4; }
  342. int TangentSize() const override { return 3; }
  343. bool Plus(const double* x,
  344. const double* delta,
  345. double* x_plus_delta) const override;
  346. bool PlusJacobian(const double* x, double* jacobian) const override;
  347. bool Minus(const double* y,
  348. const double* x,
  349. double* y_minus_x) const override;
  350. bool MinusJacobian(const double* x, double* jacobian) const override;
  351. };
  352. // Implements the quaternion manifold for Eigen's representation of the
  353. // Hamilton quaternion. Geometrically it is exactly the same as the
  354. // QuaternionManifold defined above. However, Eigen uses a different internal
  355. // memory layout for the elements of the quaternion than what is commonly
  356. // used. It stores the quaternion in memory as [q1, q2, q3, q0] or
  357. // [x, y, z, w] where the real (scalar) part is last.
  358. //
  359. // Since Ceres operates on parameter blocks which are raw double pointers this
  360. // difference is important and requires a different manifold.
  361. class CERES_EXPORT EigenQuaternionManifold final : public Manifold {
  362. public:
  363. int AmbientSize() const override { return 4; }
  364. int TangentSize() const override { return 3; }
  365. bool Plus(const double* x,
  366. const double* delta,
  367. double* x_plus_delta) const override;
  368. bool PlusJacobian(const double* x, double* jacobian) const override;
  369. bool Minus(const double* y,
  370. const double* x,
  371. double* y_minus_x) const override;
  372. bool MinusJacobian(const double* x, double* jacobian) const override;
  373. };
  374. } // namespace ceres
  375. // clang-format off
  376. #include "ceres/internal/reenable_warnings.h"
  377. // clang-format on
  378. #endif // CERES_PUBLIC_MANIFOLD_H_