se2.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. /// @file
  2. /// Special Euclidean group SE(2) - rotation and translation in 2d.
  3. #ifndef SOPHUS_SE2_HPP
  4. #define SOPHUS_SE2_HPP
  5. #include "so2.hpp"
  6. namespace Sophus {
  7. template <class Scalar_, int Options = 0>
  8. class SE2;
  9. using SE2d = SE2<double>;
  10. using SE2f = SE2<float>;
  11. } // namespace Sophus
  12. namespace Eigen {
  13. namespace internal {
  14. template <class Scalar_, int Options>
  15. struct traits<Sophus::SE2<Scalar_, Options>> {
  16. using Scalar = Scalar_;
  17. using TranslationType = Sophus::Vector2<Scalar, Options>;
  18. using SO2Type = Sophus::SO2<Scalar, Options>;
  19. };
  20. template <class Scalar_, int Options>
  21. struct traits<Map<Sophus::SE2<Scalar_>, Options>>
  22. : traits<Sophus::SE2<Scalar_, Options>> {
  23. using Scalar = Scalar_;
  24. using TranslationType = Map<Sophus::Vector2<Scalar>, Options>;
  25. using SO2Type = Map<Sophus::SO2<Scalar>, Options>;
  26. };
  27. template <class Scalar_, int Options>
  28. struct traits<Map<Sophus::SE2<Scalar_> const, Options>>
  29. : traits<Sophus::SE2<Scalar_, Options> const> {
  30. using Scalar = Scalar_;
  31. using TranslationType = Map<Sophus::Vector2<Scalar> const, Options>;
  32. using SO2Type = Map<Sophus::SO2<Scalar> const, Options>;
  33. };
  34. } // namespace internal
  35. } // namespace Eigen
  36. namespace Sophus {
  37. /// SE2 base type - implements SE2 class but is storage agnostic.
  38. ///
  39. /// SE(2) is the group of rotations and translation in 2d. It is the
  40. /// semi-direct product of SO(2) and the 2d Euclidean vector space. The class
  41. /// is represented using a composition of SO2Group for rotation and a 2-vector
  42. /// for translation.
  43. ///
  44. /// SE(2) is neither compact, nor a commutative group.
  45. ///
  46. /// See SO2Group for more details of the rotation representation in 2d.
  47. ///
  48. template <class Derived>
  49. class SE2Base {
  50. public:
  51. using Scalar = typename Eigen::internal::traits<Derived>::Scalar;
  52. using TranslationType =
  53. typename Eigen::internal::traits<Derived>::TranslationType;
  54. using SO2Type = typename Eigen::internal::traits<Derived>::SO2Type;
  55. /// Degrees of freedom of manifold, number of dimensions in tangent space
  56. /// (two for translation, three for rotation).
  57. static int constexpr DoF = 3;
  58. /// Number of internal parameters used (tuple for complex, two for
  59. /// translation).
  60. static int constexpr num_parameters = 4;
  61. /// Group transformations are 3x3 matrices.
  62. static int constexpr N = 3;
  63. using Transformation = Matrix<Scalar, N, N>;
  64. using Point = Vector2<Scalar>;
  65. using HomogeneousPoint = Vector3<Scalar>;
  66. using Line = ParametrizedLine2<Scalar>;
  67. using Tangent = Vector<Scalar, DoF>;
  68. using Adjoint = Matrix<Scalar, DoF, DoF>;
  69. /// For binary operations the return type is determined with the
  70. /// ScalarBinaryOpTraits feature of Eigen. This allows mixing concrete and Map
  71. /// types, as well as other compatible scalar types such as Ceres::Jet and
  72. /// double scalars with SE2 operations.
  73. template <typename OtherDerived>
  74. using ReturnScalar = typename Eigen::ScalarBinaryOpTraits<
  75. Scalar, typename OtherDerived::Scalar>::ReturnType;
  76. template <typename OtherDerived>
  77. using SE2Product = SE2<ReturnScalar<OtherDerived>>;
  78. template <typename PointDerived>
  79. using PointProduct = Vector2<ReturnScalar<PointDerived>>;
  80. template <typename HPointDerived>
  81. using HomogeneousPointProduct = Vector3<ReturnScalar<HPointDerived>>;
  82. /// Adjoint transformation
  83. ///
  84. /// This function return the adjoint transformation ``Ad`` of the group
  85. /// element ``A`` such that for all ``x`` it holds that
  86. /// ``hat(Ad_A * x) = A * hat(x) A^{-1}``. See hat-operator below.
  87. ///
  88. SOPHUS_FUNC Adjoint Adj() const {
  89. Matrix<Scalar, 2, 2> const& R = so2().matrix();
  90. Transformation res;
  91. res.setIdentity();
  92. res.template topLeftCorner<2, 2>() = R;
  93. res(0, 2) = translation()[1];
  94. res(1, 2) = -translation()[0];
  95. return res;
  96. }
  97. /// Returns copy of instance casted to NewScalarType.
  98. ///
  99. template <class NewScalarType>
  100. SOPHUS_FUNC SE2<NewScalarType> cast() const {
  101. return SE2<NewScalarType>(so2().template cast<NewScalarType>(),
  102. translation().template cast<NewScalarType>());
  103. }
  104. /// Returns derivative of this * exp(x) wrt x at x=0.
  105. ///
  106. SOPHUS_FUNC Matrix<Scalar, num_parameters, DoF> Dx_this_mul_exp_x_at_0()
  107. const {
  108. Matrix<Scalar, num_parameters, DoF> J;
  109. Sophus::Vector2<Scalar> const c = unit_complex();
  110. Scalar o(0);
  111. J(0, 0) = o;
  112. J(0, 1) = o;
  113. J(0, 2) = -c[1];
  114. J(1, 0) = o;
  115. J(1, 1) = o;
  116. J(1, 2) = c[0];
  117. J(2, 0) = c[0];
  118. J(2, 1) = -c[1];
  119. J(2, 2) = o;
  120. J(3, 0) = c[1];
  121. J(3, 1) = c[0];
  122. J(3, 2) = o;
  123. return J;
  124. }
  125. /// Returns group inverse.
  126. ///
  127. SOPHUS_FUNC SE2<Scalar> inverse() const {
  128. SO2<Scalar> const invR = so2().inverse();
  129. return SE2<Scalar>(invR, invR * (translation() * Scalar(-1)));
  130. }
  131. /// Logarithmic map
  132. ///
  133. /// Computes the logarithm, the inverse of the group exponential which maps
  134. /// element of the group (rigid body transformations) to elements of the
  135. /// tangent space (twist).
  136. ///
  137. /// To be specific, this function computes ``vee(logmat(.))`` with
  138. /// ``logmat(.)`` being the matrix logarithm and ``vee(.)`` the vee-operator
  139. /// of SE(2).
  140. ///
  141. SOPHUS_FUNC Tangent log() const {
  142. using std::abs;
  143. Tangent upsilon_theta;
  144. Scalar theta = so2().log();
  145. upsilon_theta[2] = theta;
  146. Scalar halftheta = Scalar(0.5) * theta;
  147. Scalar halftheta_by_tan_of_halftheta;
  148. Vector2<Scalar> z = so2().unit_complex();
  149. Scalar real_minus_one = z.x() - Scalar(1.);
  150. if (abs(real_minus_one) < Constants<Scalar>::epsilon()) {
  151. halftheta_by_tan_of_halftheta =
  152. Scalar(1.) - Scalar(1. / 12) * theta * theta;
  153. } else {
  154. halftheta_by_tan_of_halftheta = -(halftheta * z.y()) / (real_minus_one);
  155. }
  156. Matrix<Scalar, 2, 2> V_inv;
  157. V_inv << halftheta_by_tan_of_halftheta, halftheta, -halftheta,
  158. halftheta_by_tan_of_halftheta;
  159. upsilon_theta.template head<2>() = V_inv * translation();
  160. return upsilon_theta;
  161. }
  162. /// Normalize SO2 element
  163. ///
  164. /// It re-normalizes the SO2 element.
  165. ///
  166. SOPHUS_FUNC void normalize() { so2().normalize(); }
  167. /// Returns 3x3 matrix representation of the instance.
  168. ///
  169. /// It has the following form:
  170. ///
  171. /// | R t |
  172. /// | o 1 |
  173. ///
  174. /// where ``R`` is a 2x2 rotation matrix, ``t`` a translation 2-vector and
  175. /// ``o`` a 2-column vector of zeros.
  176. ///
  177. SOPHUS_FUNC Transformation matrix() const {
  178. Transformation homogenious_matrix;
  179. homogenious_matrix.template topLeftCorner<2, 3>() = matrix2x3();
  180. homogenious_matrix.row(2) =
  181. Matrix<Scalar, 1, 3>(Scalar(0), Scalar(0), Scalar(1));
  182. return homogenious_matrix;
  183. }
  184. /// Returns the significant first two rows of the matrix above.
  185. ///
  186. SOPHUS_FUNC Matrix<Scalar, 2, 3> matrix2x3() const {
  187. Matrix<Scalar, 2, 3> matrix;
  188. matrix.template topLeftCorner<2, 2>() = rotationMatrix();
  189. matrix.col(2) = translation();
  190. return matrix;
  191. }
  192. /// Assignment-like operator from OtherDerived.
  193. ///
  194. template <class OtherDerived>
  195. SOPHUS_FUNC SE2Base<Derived>& operator=(SE2Base<OtherDerived> const& other) {
  196. so2() = other.so2();
  197. translation() = other.translation();
  198. return *this;
  199. }
  200. /// Group multiplication, which is rotation concatenation.
  201. ///
  202. template <typename OtherDerived>
  203. SOPHUS_FUNC SE2Product<OtherDerived> operator*(
  204. SE2Base<OtherDerived> const& other) const {
  205. return SE2Product<OtherDerived>(
  206. so2() * other.so2(), translation() + so2() * other.translation());
  207. }
  208. /// Group action on 2-points.
  209. ///
  210. /// This function rotates and translates a two dimensional point ``p`` by the
  211. /// SE(2) element ``bar_T_foo = (bar_R_foo, t_bar)`` (= rigid body
  212. /// transformation):
  213. ///
  214. /// ``p_bar = bar_R_foo * p_foo + t_bar``.
  215. ///
  216. template <typename PointDerived,
  217. typename = typename std::enable_if<
  218. IsFixedSizeVector<PointDerived, 2>::value>::type>
  219. SOPHUS_FUNC PointProduct<PointDerived> operator*(
  220. Eigen::MatrixBase<PointDerived> const& p) const {
  221. return so2() * p + translation();
  222. }
  223. /// Group action on homogeneous 2-points. See above for more details.
  224. ///
  225. template <typename HPointDerived,
  226. typename = typename std::enable_if<
  227. IsFixedSizeVector<HPointDerived, 3>::value>::type>
  228. SOPHUS_FUNC HomogeneousPointProduct<HPointDerived> operator*(
  229. Eigen::MatrixBase<HPointDerived> const& p) const {
  230. const PointProduct<HPointDerived> tp =
  231. so2() * p.template head<2>() + p(2) * translation();
  232. return HomogeneousPointProduct<HPointDerived>(tp(0), tp(1), p(2));
  233. }
  234. /// Group action on lines.
  235. ///
  236. /// This function rotates and translates a parametrized line
  237. /// ``l(t) = o + t * d`` by the SE(2) element:
  238. ///
  239. /// Origin ``o`` is rotated and translated using SE(2) action
  240. /// Direction ``d`` is rotated using SO(2) action
  241. ///
  242. SOPHUS_FUNC Line operator*(Line const& l) const {
  243. return Line((*this) * l.origin(), so2() * l.direction());
  244. }
  245. /// In-place group multiplication. This method is only valid if the return
  246. /// type of the multiplication is compatible with this SO2's Scalar type.
  247. ///
  248. template <typename OtherDerived,
  249. typename = typename std::enable_if<
  250. std::is_same<Scalar, ReturnScalar<OtherDerived>>::value>::type>
  251. SOPHUS_FUNC SE2Base<Derived>& operator*=(SE2Base<OtherDerived> const& other) {
  252. *static_cast<Derived*>(this) = *this * other;
  253. return *this;
  254. }
  255. /// Returns internal parameters of SE(2).
  256. ///
  257. /// It returns (c[0], c[1], t[0], t[1]),
  258. /// with c being the unit complex number, t the translation 3-vector.
  259. ///
  260. SOPHUS_FUNC Sophus::Vector<Scalar, num_parameters> params() const {
  261. Sophus::Vector<Scalar, num_parameters> p;
  262. p << so2().params(), translation();
  263. return p;
  264. }
  265. /// Returns rotation matrix.
  266. ///
  267. SOPHUS_FUNC Matrix<Scalar, 2, 2> rotationMatrix() const {
  268. return so2().matrix();
  269. }
  270. /// Takes in complex number, and normalizes it.
  271. ///
  272. /// Precondition: The complex number must not be close to zero.
  273. ///
  274. SOPHUS_FUNC void setComplex(Sophus::Vector2<Scalar> const& complex) {
  275. return so2().setComplex(complex);
  276. }
  277. /// Sets ``so3`` using ``rotation_matrix``.
  278. ///
  279. /// Precondition: ``R`` must be orthogonal and ``det(R)=1``.
  280. ///
  281. SOPHUS_FUNC void setRotationMatrix(Matrix<Scalar, 2, 2> const& R) {
  282. SOPHUS_ENSURE(isOrthogonal(R), "R is not orthogonal:\n %", R);
  283. SOPHUS_ENSURE(R.determinant() > Scalar(0), "det(R) is not positive: %",
  284. R.determinant());
  285. typename SO2Type::ComplexTemporaryType const complex(
  286. Scalar(0.5) * (R(0, 0) + R(1, 1)), Scalar(0.5) * (R(1, 0) - R(0, 1)));
  287. so2().setComplex(complex);
  288. }
  289. /// Mutator of SO3 group.
  290. ///
  291. SOPHUS_FUNC
  292. SO2Type& so2() { return static_cast<Derived*>(this)->so2(); }
  293. /// Accessor of SO3 group.
  294. ///
  295. SOPHUS_FUNC
  296. SO2Type const& so2() const {
  297. return static_cast<Derived const*>(this)->so2();
  298. }
  299. /// Mutator of translation vector.
  300. ///
  301. SOPHUS_FUNC
  302. TranslationType& translation() {
  303. return static_cast<Derived*>(this)->translation();
  304. }
  305. /// Accessor of translation vector
  306. ///
  307. SOPHUS_FUNC
  308. TranslationType const& translation() const {
  309. return static_cast<Derived const*>(this)->translation();
  310. }
  311. /// Accessor of unit complex number.
  312. ///
  313. SOPHUS_FUNC
  314. typename Eigen::internal::traits<Derived>::SO2Type::ComplexT const&
  315. unit_complex() const {
  316. return so2().unit_complex();
  317. }
  318. };
  319. /// SE2 using default storage; derived from SE2Base.
  320. template <class Scalar_, int Options>
  321. class SE2 : public SE2Base<SE2<Scalar_, Options>> {
  322. public:
  323. using Base = SE2Base<SE2<Scalar_, Options>>;
  324. static int constexpr DoF = Base::DoF;
  325. static int constexpr num_parameters = Base::num_parameters;
  326. using Scalar = Scalar_;
  327. using Transformation = typename Base::Transformation;
  328. using Point = typename Base::Point;
  329. using HomogeneousPoint = typename Base::HomogeneousPoint;
  330. using Tangent = typename Base::Tangent;
  331. using Adjoint = typename Base::Adjoint;
  332. using SO2Member = SO2<Scalar, Options>;
  333. using TranslationMember = Vector2<Scalar, Options>;
  334. using Base::operator=;
  335. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  336. /// Default constructor initializes rigid body motion to the identity.
  337. ///
  338. SOPHUS_FUNC SE2();
  339. /// Copy constructor
  340. ///
  341. SOPHUS_FUNC SE2(SE2 const& other) = default;
  342. /// Copy-like constructor from OtherDerived
  343. ///
  344. template <class OtherDerived>
  345. SOPHUS_FUNC SE2(SE2Base<OtherDerived> const& other)
  346. : so2_(other.so2()), translation_(other.translation()) {
  347. static_assert(std::is_same<typename OtherDerived::Scalar, Scalar>::value,
  348. "must be same Scalar type");
  349. }
  350. /// Constructor from SO3 and translation vector
  351. ///
  352. template <class OtherDerived, class D>
  353. SOPHUS_FUNC SE2(SO2Base<OtherDerived> const& so2,
  354. Eigen::MatrixBase<D> const& translation)
  355. : so2_(so2), translation_(translation) {
  356. static_assert(std::is_same<typename OtherDerived::Scalar, Scalar>::value,
  357. "must be same Scalar type");
  358. static_assert(std::is_same<typename D::Scalar, Scalar>::value,
  359. "must be same Scalar type");
  360. }
  361. /// Constructor from rotation matrix and translation vector
  362. ///
  363. /// Precondition: Rotation matrix needs to be orthogonal with determinant
  364. /// of 1.
  365. ///
  366. SOPHUS_FUNC
  367. SE2(typename SO2<Scalar>::Transformation const& rotation_matrix,
  368. Point const& translation)
  369. : so2_(rotation_matrix), translation_(translation) {}
  370. /// Constructor from rotation angle and translation vector.
  371. ///
  372. SOPHUS_FUNC SE2(Scalar const& theta, Point const& translation)
  373. : so2_(theta), translation_(translation) {}
  374. /// Constructor from complex number and translation vector
  375. ///
  376. /// Precondition: ``complex`` must not be close to zero.
  377. SOPHUS_FUNC SE2(Vector2<Scalar> const& complex, Point const& translation)
  378. : so2_(complex), translation_(translation) {}
  379. /// Constructor from 3x3 matrix
  380. ///
  381. /// Precondition: Rotation matrix needs to be orthogonal with determinant
  382. /// of 1. The last row must be ``(0, 0, 1)``.
  383. ///
  384. SOPHUS_FUNC explicit SE2(Transformation const& T)
  385. : so2_(T.template topLeftCorner<2, 2>().eval()),
  386. translation_(T.template block<2, 1>(0, 2)) {}
  387. /// This provides unsafe read/write access to internal data. SO(2) is
  388. /// represented by a complex number (two parameters). When using direct write
  389. /// access, the user needs to take care of that the complex number stays
  390. /// normalized.
  391. ///
  392. SOPHUS_FUNC Scalar* data() {
  393. // so2_ and translation_ are layed out sequentially with no padding
  394. return so2_.data();
  395. }
  396. /// Const version of data() above.
  397. ///
  398. SOPHUS_FUNC Scalar const* data() const {
  399. /// so2_ and translation_ are layed out sequentially with no padding
  400. return so2_.data();
  401. }
  402. /// Accessor of SO3
  403. ///
  404. SOPHUS_FUNC SO2Member& so2() { return so2_; }
  405. /// Mutator of SO3
  406. ///
  407. SOPHUS_FUNC SO2Member const& so2() const { return so2_; }
  408. /// Mutator of translation vector
  409. ///
  410. SOPHUS_FUNC TranslationMember& translation() { return translation_; }
  411. /// Accessor of translation vector
  412. ///
  413. SOPHUS_FUNC TranslationMember const& translation() const {
  414. return translation_;
  415. }
  416. /// Returns derivative of exp(x) wrt. x.
  417. ///
  418. SOPHUS_FUNC static Sophus::Matrix<Scalar, num_parameters, DoF> Dx_exp_x(
  419. Tangent const& upsilon_theta) {
  420. using std::abs;
  421. using std::cos;
  422. using std::pow;
  423. using std::sin;
  424. Sophus::Matrix<Scalar, num_parameters, DoF> J;
  425. Sophus::Vector<Scalar, 2> upsilon = upsilon_theta.template head<2>();
  426. Scalar theta = upsilon_theta[2];
  427. if (abs(theta) < Constants<Scalar>::epsilon()) {
  428. Scalar const o(0);
  429. Scalar const i(1);
  430. // clang-format off
  431. J << o, o, o, o, o, i, i, o, -Scalar(0.5) * upsilon[1], o, i,
  432. Scalar(0.5) * upsilon[0];
  433. // clang-format on
  434. return J;
  435. }
  436. Scalar const c0 = sin(theta);
  437. Scalar const c1 = cos(theta);
  438. Scalar const c2 = 1.0 / theta;
  439. Scalar const c3 = c0 * c2;
  440. Scalar const c4 = -c1 + Scalar(1);
  441. Scalar const c5 = c2 * c4;
  442. Scalar const c6 = c1 * c2;
  443. Scalar const c7 = pow(theta, -2);
  444. Scalar const c8 = c0 * c7;
  445. Scalar const c9 = c4 * c7;
  446. Scalar const o = Scalar(0);
  447. J(0, 0) = o;
  448. J(0, 1) = o;
  449. J(0, 2) = -c0;
  450. J(1, 0) = o;
  451. J(1, 1) = o;
  452. J(1, 2) = c1;
  453. J(2, 0) = c3;
  454. J(2, 1) = -c5;
  455. J(2, 2) =
  456. -c3 * upsilon[1] + c6 * upsilon[0] - c8 * upsilon[0] + c9 * upsilon[1];
  457. J(3, 0) = c5;
  458. J(3, 1) = c3;
  459. J(3, 2) =
  460. c3 * upsilon[0] + c6 * upsilon[1] - c8 * upsilon[1] - c9 * upsilon[0];
  461. return J;
  462. }
  463. /// Returns derivative of exp(x) wrt. x_i at x=0.
  464. ///
  465. SOPHUS_FUNC static Sophus::Matrix<Scalar, num_parameters, DoF>
  466. Dx_exp_x_at_0() {
  467. Sophus::Matrix<Scalar, num_parameters, DoF> J;
  468. Scalar const o(0);
  469. Scalar const i(1);
  470. // clang-format off
  471. J << o, o, o, o, o, i, i, o, o, o, i, o;
  472. // clang-format on
  473. return J;
  474. }
  475. /// Returns derivative of exp(x).matrix() wrt. ``x_i at x=0``.
  476. ///
  477. SOPHUS_FUNC static Transformation Dxi_exp_x_matrix_at_0(int i) {
  478. return generator(i);
  479. }
  480. /// Group exponential
  481. ///
  482. /// This functions takes in an element of tangent space (= twist ``a``) and
  483. /// returns the corresponding element of the group SE(2).
  484. ///
  485. /// The first two components of ``a`` represent the translational part
  486. /// ``upsilon`` in the tangent space of SE(2), while the last three components
  487. /// of ``a`` represents the rotation vector ``omega``.
  488. /// To be more specific, this function computes ``expmat(hat(a))`` with
  489. /// ``expmat(.)`` being the matrix exponential and ``hat(.)`` the hat-operator
  490. /// of SE(2), see below.
  491. ///
  492. SOPHUS_FUNC static SE2<Scalar> exp(Tangent const& a) {
  493. Scalar theta = a[2];
  494. SO2<Scalar> so2 = SO2<Scalar>::exp(theta);
  495. Scalar sin_theta_by_theta;
  496. Scalar one_minus_cos_theta_by_theta;
  497. using std::abs;
  498. if (abs(theta) < Constants<Scalar>::epsilon()) {
  499. Scalar theta_sq = theta * theta;
  500. sin_theta_by_theta = Scalar(1.) - Scalar(1. / 6.) * theta_sq;
  501. one_minus_cos_theta_by_theta =
  502. Scalar(0.5) * theta - Scalar(1. / 24.) * theta * theta_sq;
  503. } else {
  504. sin_theta_by_theta = so2.unit_complex().y() / theta;
  505. one_minus_cos_theta_by_theta =
  506. (Scalar(1.) - so2.unit_complex().x()) / theta;
  507. }
  508. Vector2<Scalar> trans(
  509. sin_theta_by_theta * a[0] - one_minus_cos_theta_by_theta * a[1],
  510. one_minus_cos_theta_by_theta * a[0] + sin_theta_by_theta * a[1]);
  511. return SE2<Scalar>(so2, trans);
  512. }
  513. /// Returns closest SE3 given arbitrary 4x4 matrix.
  514. ///
  515. template <class S = Scalar>
  516. static SOPHUS_FUNC enable_if_t<std::is_floating_point<S>::value, SE2>
  517. fitToSE2(Matrix3<Scalar> const& T) {
  518. return SE2(SO2<Scalar>::fitToSO2(T.template block<2, 2>(0, 0)),
  519. T.template block<2, 1>(0, 2));
  520. }
  521. /// Returns the ith infinitesimal generators of SE(2).
  522. ///
  523. /// The infinitesimal generators of SE(2) are:
  524. ///
  525. /// ```
  526. /// | 0 0 1 |
  527. /// G_0 = | 0 0 0 |
  528. /// | 0 0 0 |
  529. ///
  530. /// | 0 0 0 |
  531. /// G_1 = | 0 0 1 |
  532. /// | 0 0 0 |
  533. ///
  534. /// | 0 -1 0 |
  535. /// G_2 = | 1 0 0 |
  536. /// | 0 0 0 |
  537. /// ```
  538. ///
  539. /// Precondition: ``i`` must be in 0, 1 or 2.
  540. ///
  541. SOPHUS_FUNC static Transformation generator(int i) {
  542. SOPHUS_ENSURE(i >= 0 || i <= 2, "i should be in range [0,2].");
  543. Tangent e;
  544. e.setZero();
  545. e[i] = Scalar(1);
  546. return hat(e);
  547. }
  548. /// hat-operator
  549. ///
  550. /// It takes in the 3-vector representation (= twist) and returns the
  551. /// corresponding matrix representation of Lie algebra element.
  552. ///
  553. /// Formally, the hat()-operator of SE(3) is defined as
  554. ///
  555. /// ``hat(.): R^3 -> R^{3x33}, hat(a) = sum_i a_i * G_i`` (for i=0,1,2)
  556. ///
  557. /// with ``G_i`` being the ith infinitesimal generator of SE(2).
  558. ///
  559. /// The corresponding inverse is the vee()-operator, see below.
  560. ///
  561. SOPHUS_FUNC static Transformation hat(Tangent const& a) {
  562. Transformation Omega;
  563. Omega.setZero();
  564. Omega.template topLeftCorner<2, 2>() = SO2<Scalar>::hat(a[2]);
  565. Omega.col(2).template head<2>() = a.template head<2>();
  566. return Omega;
  567. }
  568. /// Lie bracket
  569. ///
  570. /// It computes the Lie bracket of SE(2). To be more specific, it computes
  571. ///
  572. /// ``[omega_1, omega_2]_se2 := vee([hat(omega_1), hat(omega_2)])``
  573. ///
  574. /// with ``[A,B] := AB-BA`` being the matrix commutator, ``hat(.)`` the
  575. /// hat()-operator and ``vee(.)`` the vee()-operator of SE(2).
  576. ///
  577. SOPHUS_FUNC static Tangent lieBracket(Tangent const& a, Tangent const& b) {
  578. Vector2<Scalar> upsilon1 = a.template head<2>();
  579. Vector2<Scalar> upsilon2 = b.template head<2>();
  580. Scalar theta1 = a[2];
  581. Scalar theta2 = b[2];
  582. return Tangent(-theta1 * upsilon2[1] + theta2 * upsilon1[1],
  583. theta1 * upsilon2[0] - theta2 * upsilon1[0], Scalar(0));
  584. }
  585. /// Construct pure rotation.
  586. ///
  587. static SOPHUS_FUNC SE2 rot(Scalar const& x) {
  588. return SE2(SO2<Scalar>(x), Sophus::Vector2<Scalar>::Zero());
  589. }
  590. /// Draw uniform sample from SE(2) manifold.
  591. ///
  592. /// Translations are drawn component-wise from the range [-1, 1].
  593. ///
  594. template <class UniformRandomBitGenerator>
  595. static SE2 sampleUniform(UniformRandomBitGenerator& generator) {
  596. std::uniform_real_distribution<Scalar> uniform(Scalar(-1), Scalar(1));
  597. return SE2(SO2<Scalar>::sampleUniform(generator),
  598. Vector2<Scalar>(uniform(generator), uniform(generator)));
  599. }
  600. /// Construct a translation only SE(2) instance.
  601. ///
  602. template <class T0, class T1>
  603. static SOPHUS_FUNC SE2 trans(T0 const& x, T1 const& y) {
  604. return SE2(SO2<Scalar>(), Vector2<Scalar>(x, y));
  605. }
  606. static SOPHUS_FUNC SE2 trans(Vector2<Scalar> const& xy) {
  607. return SE2(SO2<Scalar>(), xy);
  608. }
  609. /// Construct x-axis translation.
  610. ///
  611. static SOPHUS_FUNC SE2 transX(Scalar const& x) {
  612. return SE2::trans(x, Scalar(0));
  613. }
  614. /// Construct y-axis translation.
  615. ///
  616. static SOPHUS_FUNC SE2 transY(Scalar const& y) {
  617. return SE2::trans(Scalar(0), y);
  618. }
  619. /// vee-operator
  620. ///
  621. /// It takes the 3x3-matrix representation ``Omega`` and maps it to the
  622. /// corresponding 3-vector representation of Lie algebra.
  623. ///
  624. /// This is the inverse of the hat()-operator, see above.
  625. ///
  626. /// Precondition: ``Omega`` must have the following structure:
  627. ///
  628. /// | 0 -d a |
  629. /// | d 0 b |
  630. /// | 0 0 0 |
  631. ///
  632. SOPHUS_FUNC static Tangent vee(Transformation const& Omega) {
  633. SOPHUS_ENSURE(
  634. Omega.row(2).template lpNorm<1>() < Constants<Scalar>::epsilon(),
  635. "Omega: \n%", Omega);
  636. Tangent upsilon_omega;
  637. upsilon_omega.template head<2>() = Omega.col(2).template head<2>();
  638. upsilon_omega[2] = SO2<Scalar>::vee(Omega.template topLeftCorner<2, 2>());
  639. return upsilon_omega;
  640. }
  641. protected:
  642. SO2Member so2_;
  643. TranslationMember translation_;
  644. };
  645. template <class Scalar, int Options>
  646. SE2<Scalar, Options>::SE2() : translation_(TranslationMember::Zero()) {
  647. static_assert(std::is_standard_layout<SE2>::value,
  648. "Assume standard layout for the use of offsetof check below.");
  649. static_assert(
  650. offsetof(SE2, so2_) + sizeof(Scalar) * SO2<Scalar>::num_parameters ==
  651. offsetof(SE2, translation_),
  652. "This class assumes packed storage and hence will only work "
  653. "correctly depending on the compiler (options) - in "
  654. "particular when using [this->data(), this-data() + "
  655. "num_parameters] to access the raw data in a contiguous fashion.");
  656. }
  657. } // namespace Sophus
  658. namespace Eigen {
  659. /// Specialization of Eigen::Map for ``SE2``; derived from SE2Base.
  660. ///
  661. /// Allows us to wrap SE2 objects around POD array.
  662. template <class Scalar_, int Options>
  663. class Map<Sophus::SE2<Scalar_>, Options>
  664. : public Sophus::SE2Base<Map<Sophus::SE2<Scalar_>, Options>> {
  665. public:
  666. using Base = Sophus::SE2Base<Map<Sophus::SE2<Scalar_>, Options>>;
  667. using Scalar = Scalar_;
  668. using Transformation = typename Base::Transformation;
  669. using Point = typename Base::Point;
  670. using HomogeneousPoint = typename Base::HomogeneousPoint;
  671. using Tangent = typename Base::Tangent;
  672. using Adjoint = typename Base::Adjoint;
  673. using Base::operator=;
  674. using Base::operator*=;
  675. using Base::operator*;
  676. SOPHUS_FUNC
  677. Map(Scalar* coeffs)
  678. : so2_(coeffs),
  679. translation_(coeffs + Sophus::SO2<Scalar>::num_parameters) {}
  680. /// Mutator of SO3
  681. ///
  682. SOPHUS_FUNC Map<Sophus::SO2<Scalar>, Options>& so2() { return so2_; }
  683. /// Accessor of SO3
  684. ///
  685. SOPHUS_FUNC Map<Sophus::SO2<Scalar>, Options> const& so2() const {
  686. return so2_;
  687. }
  688. /// Mutator of translation vector
  689. ///
  690. SOPHUS_FUNC Map<Sophus::Vector2<Scalar>, Options>& translation() {
  691. return translation_;
  692. }
  693. /// Accessor of translation vector
  694. ///
  695. SOPHUS_FUNC Map<Sophus::Vector2<Scalar>, Options> const& translation() const {
  696. return translation_;
  697. }
  698. protected:
  699. Map<Sophus::SO2<Scalar>, Options> so2_;
  700. Map<Sophus::Vector2<Scalar>, Options> translation_;
  701. };
  702. /// Specialization of Eigen::Map for ``SE2 const``; derived from SE2Base.
  703. ///
  704. /// Allows us to wrap SE2 objects around POD array.
  705. template <class Scalar_, int Options>
  706. class Map<Sophus::SE2<Scalar_> const, Options>
  707. : public Sophus::SE2Base<Map<Sophus::SE2<Scalar_> const, Options>> {
  708. public:
  709. using Base = Sophus::SE2Base<Map<Sophus::SE2<Scalar_> const, Options>>;
  710. using Scalar = Scalar_;
  711. using Transformation = typename Base::Transformation;
  712. using Point = typename Base::Point;
  713. using HomogeneousPoint = typename Base::HomogeneousPoint;
  714. using Tangent = typename Base::Tangent;
  715. using Adjoint = typename Base::Adjoint;
  716. using Base::operator*=;
  717. using Base::operator*;
  718. SOPHUS_FUNC Map(Scalar const* coeffs)
  719. : so2_(coeffs),
  720. translation_(coeffs + Sophus::SO2<Scalar>::num_parameters) {}
  721. /// Accessor of SO3
  722. ///
  723. SOPHUS_FUNC Map<Sophus::SO2<Scalar> const, Options> const& so2() const {
  724. return so2_;
  725. }
  726. /// Accessor of translation vector
  727. ///
  728. SOPHUS_FUNC Map<Sophus::Vector2<Scalar> const, Options> const& translation()
  729. const {
  730. return translation_;
  731. }
  732. protected:
  733. Map<Sophus::SO2<Scalar> const, Options> const so2_;
  734. Map<Sophus::Vector2<Scalar> const, Options> const translation_;
  735. };
  736. } // namespace Eigen
  737. #endif