farm-ng-core
rotation2.h
Go to the documentation of this file.
1 // Copyright (c) 2011, Hauke Strasdat
2 // Copyright (c) 2012, Steven Lovegrove
3 // Copyright (c) 2021, farm-ng, inc.
4 //
5 // Use of this source code is governed by an MIT-style
6 // license that can be found in the LICENSE file or at
7 // https://opensource.org/licenses/MIT.
8 
9 #pragma once
10 
14 
15 namespace sophus {
16 namespace lie {
17 
18 template <class TScalar>
20  public:
21  using Scalar = TScalar;
23 
24  static bool constexpr kIsOriginPreserving = true;
25  static bool constexpr kIsAxisDirectionPreserving = false;
26  static bool constexpr kIsDirectionVectorPreserving = false;
27  static bool constexpr kIsShapePreserving = true;
28  static bool constexpr kIisSizePreserving = true;
29  static bool constexpr kIisParallelLinePreserving = true;
30 
31  static int const kDof = 1;
32  static int const kNumParams = 2;
33  static int const kPointDim = 2;
34  static int const kAmbientDim = 2;
35 
36  using Tangent = Eigen::Vector<Scalar, kDof>;
37  using Params = Eigen::Vector<Scalar, kNumParams>;
38  using Point = Eigen::Vector<Scalar, kPointDim>;
39 
40  template <class TCompatibleScalar>
41  using ScalarReturn = typename Eigen::
42  ScalarBinaryOpTraits<Scalar, TCompatibleScalar>::ReturnType;
43 
44  template <class TCompatibleScalar>
45  using ParamsReturn =
46  Eigen::Vector<ScalarReturn<TCompatibleScalar>, kNumParams>;
47 
48  template <class TCompatibleScalar>
49  using PointReturn = Eigen::Vector<ScalarReturn<TCompatibleScalar>, kPointDim>;
50 
51  template <class TCompatibleScalar>
52  using UnitVectorReturn =
54 
55  // constructors and factories
56 
57  static auto identityParams() -> Params {
58  return Eigen::Vector<Scalar, 2>(1.0, 0.0);
59  }
60 
61  static auto areParamsValid(Params const& unit_complex)
62  -> sophus::Expected<Success> {
63  static const Scalar kThr = kEpsilon<Scalar>;
64  const Scalar squared_norm = unit_complex.squaredNorm();
65  using std::abs;
66  if (!(abs(squared_norm - 1.0) <= kThr)) {
67  return SOPHUS_UNEXPECTED(
68  "complex number ({}, {}) is not unit length.\n"
69  "Squared norm: {}, thr: {}",
70  unit_complex[0],
71  unit_complex[1],
72  squared_norm,
73  kThr);
74  }
75  return sophus::Expected<Success>{};
76  }
77 
78  static auto hasShortestPathAmbiguity(Params const& foo_from_bar) -> bool {
79  using std::abs;
80  TScalar angle = abs(Rotation2Impl::log(foo_from_bar)[0]);
81  TScalar const k_pi = kPi<TScalar>; // NOLINT
82  return abs(angle - k_pi) / (angle + k_pi) < kEpsilon<TScalar>;
83  }
84 
85  // Manifold / Lie Group concepts
86 
87  static auto exp(Tangent const& angle) -> Params {
88  using std::cos;
89  using std::sin;
90  return Eigen::Vector<Scalar, 2>(cos(angle[0]), sin(angle[0]));
91  }
92 
93  static auto log(Params const& unit_complex) -> Tangent {
94  using std::atan2;
95  return Eigen::Vector<Scalar, 1>{atan2(unit_complex.y(), unit_complex.x())};
96  }
97 
98  static auto hat(Tangent const& angle)
99  -> Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim> {
100  return Eigen::Matrix<Scalar, 2, 2>{
101  {Scalar(0.0), Scalar(-angle[0])}, {Scalar(angle[0]), Scalar(0.0)}};
102  }
103 
104  static auto vee(Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim> const& mat)
105  -> Eigen::Matrix<Scalar, kDof, 1> {
106  return Eigen::Matrix<Scalar, kDof, 1>{mat(1, 0)};
107  }
108 
109  // group operations
110 
111  static auto inverse(Params const& unit_complex) -> Params {
112  return Params(unit_complex.x(), -unit_complex.y());
113  }
114 
115  template <class TCompatibleScalar>
116  static auto multiplication(
117  Params const& lhs_params,
118  Eigen::Matrix<TCompatibleScalar, 2, 1> const& rhs_params)
120  auto result = Complex::multiplication(lhs_params, rhs_params);
121  auto const squared_norm = result.squaredNorm();
122 
123  // We can assume that the squared-norm is close to 1 since we deal with a
124  // unit complex number. Due to numerical precision issues, there might
125  // be a small drift after pose concatenation. Hence, we need to renormalizes
126  // the complex number here.
127  // Since squared-norm is close to 1, we do not need to calculate the costly
128  // square-root, but can use an approximation around 1 (see
129  // http://stackoverflow.com/a/12934750 for details).
130  if (squared_norm != 1.0) {
131  auto const scale = 2.0 / (1.0 + squared_norm);
132  return scale * result;
133  }
134  return result;
135  }
136 
137  // Group actions
138  template <class TCompatibleScalar>
139  static auto action(
140  Params const& unit_complex,
141  Eigen::Matrix<TCompatibleScalar, 2, 1> const& point)
143  return Complex::multiplication(unit_complex, point);
144  }
145 
146  template <class TCompatibleScalar>
147  static auto action(
148  Params const& unit_complex,
149  UnitVector<TCompatibleScalar, kPointDim> const& direction_vector)
152  Complex::multiplication(unit_complex, direction_vector.params()));
153  }
154 
155  static auto toAmbient(Point const& point)
156  -> Eigen::Vector<Scalar, kAmbientDim> {
157  return point;
158  }
159 
160  static auto adj(Params const& /*unused*/)
161  -> Eigen::Matrix<Scalar, kDof, kDof> {
162  return Eigen::Matrix<Scalar, 1, 1>::Identity();
163  }
164 
165  // matrices
166 
167  static auto compactMatrix(Params const& unit_complex)
168  -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
169  return Eigen::Matrix<Scalar, 2, 2>{
170  {unit_complex.x(), -unit_complex.y()},
171  {unit_complex.y(), unit_complex.x()}};
172  }
173 
174  static auto matrix(Params const& unit_complex)
175  -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
176  return compactMatrix(unit_complex);
177  }
178 
179  // Sub-group concepts
180  static auto matV(Params const& params, Tangent const& theta)
181  -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
182  Scalar sin_theta_by_theta;
183  Scalar one_minus_cos_theta_by_theta;
184  using std::abs;
185 
186  if (abs(theta[0]) < kEpsilon<Scalar>) {
187  Scalar theta_sq = theta[0] * theta[0];
188  sin_theta_by_theta = Scalar(1.) - Scalar(1. / 6.) * theta_sq;
189  one_minus_cos_theta_by_theta =
190  Scalar(0.5) * theta[0] - Scalar(1. / 24.) * theta[0] * theta_sq;
191  } else {
192  sin_theta_by_theta = params.y() / theta[0];
193  one_minus_cos_theta_by_theta = (Scalar(1.) - params.x()) / theta[0];
194  }
195  return Eigen::Matrix<Scalar, 2, 2>(
196  {{sin_theta_by_theta, -one_minus_cos_theta_by_theta},
197  {one_minus_cos_theta_by_theta, sin_theta_by_theta}});
198  }
199 
200  static auto matVInverse(Params const& z, Tangent const& theta)
201  -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
202  Scalar halftheta = Scalar(0.5) * theta[0];
203  Scalar halftheta_by_tan_of_halftheta;
204 
205  Scalar real_minus_one = z.x() - Scalar(1.);
206  if (abs(real_minus_one) < kEpsilon<Scalar>) {
207  halftheta_by_tan_of_halftheta =
208  Scalar(1.) - Scalar(1. / 12) * theta[0] * theta[0];
209  } else {
210  halftheta_by_tan_of_halftheta = -(halftheta * z.y()) / (real_minus_one);
211  }
212  Eigen::Matrix<Scalar, 2, 2> v_inv;
213  v_inv << halftheta_by_tan_of_halftheta, halftheta, -halftheta,
214  halftheta_by_tan_of_halftheta;
215  return v_inv;
216  }
217 
218  static auto adjOfTranslation(Params const& /*unused*/, Point const& point)
219  -> Eigen::Matrix<Scalar, kPointDim, kDof> {
220  return Eigen::Matrix<Scalar, 2, 1>(point[1], -point[0]);
221  }
222 
223  static auto adOfTranslation(Point const& point)
224  -> Eigen::Matrix<Scalar, kPointDim, kDof> {
225  return Eigen::Vector2<Scalar>(point[1], -point[0]);
226  }
227 
228  // derivatives
229  static auto ad(Tangent const&) -> Eigen::Matrix<Scalar, kDof, kDof> {
230  return Eigen::Matrix<Scalar, 1, 1>::Zero();
231  }
232 
233  static auto dxExpX(Tangent const& theta)
234  -> Eigen::Matrix<Scalar, kNumParams, kDof> {
235  using std::cos;
236  using std::sin;
237  return Eigen::Matrix<Scalar, kNumParams, kDof>(
238  -sin(theta[0]), cos(theta[0]));
239  }
240 
241  static auto dxExpXAt0() -> Eigen::Matrix<Scalar, kNumParams, kDof> {
242  return Eigen::Matrix<Scalar, kNumParams, kDof>(0.0, 1.0);
243  }
244 
245  static auto dxExpXTimesPointAt0(Point const& point)
246  -> Eigen::Matrix<Scalar, kNumParams, kDof> {
247  return Eigen::Matrix<Scalar, 2, 1>(-point[1], point[0]);
248  }
249 
250  static auto dxThisMulExpXAt0(Params const& unit_complex)
251  -> Eigen::Matrix<Scalar, kNumParams, kDof> {
252  return -Eigen::Matrix<Scalar, 2, 1>(unit_complex[1], -unit_complex[0]);
253  }
254 
255  static auto dxLogThisInvTimesXAtThis(Params const& unit_complex)
256  -> Eigen::Matrix<Scalar, kDof, kNumParams> {
257  return Eigen::Matrix<Scalar, 1, 2>(-unit_complex[1], unit_complex[0]);
258  }
259 
260  // for tests
261 
262  static auto tangentExamples() -> std::vector<Tangent> {
263  return std::vector<Tangent>({
264  Tangent{Scalar(0.0)},
265  Tangent{Scalar(0.00001)},
266  Tangent{Scalar(1.0)},
267  Tangent{Scalar(-1.0)},
268  Tangent{Scalar(5.0)},
269  Tangent{Scalar(0.5 * kPi<Scalar>)},
270  Tangent{Scalar(0.5 * kPi<Scalar> + 0.00001)},
271  });
272  }
273 
274  static auto paramsExamples() -> std::vector<Params> {
275  return std::vector<Params>({
278  Rotation2Impl::exp(Tangent{Scalar(0.5 * kPi<Scalar>)}),
279  Rotation2Impl::exp(Tangent{Scalar(kPi<Scalar>)}),
280  });
281  }
282 
283  static auto invalidParamsExamples() -> std::vector<Params> {
284  return std::vector<Params>({
285  Params::Zero(),
286  Params::Ones(),
287  2.0 * Params::UnitX(),
288  });
289  }
290 };
291 
292 } // namespace lie
293 } // namespace sophus
sophus::lie::Rotation2Impl::action
static auto action(Params const &unit_complex, Eigen::Matrix< TCompatibleScalar, 2, 1 > const &point) -> PointReturn< TCompatibleScalar >
Definition: rotation2.h:139
sophus::lie::Rotation2Impl::dxExpXAt0
static auto dxExpXAt0() -> Eigen::Matrix< Scalar, kNumParams, kDof >
Definition: rotation2.h:241
lie_group.h
sophus::lie::Rotation2Impl::matV
static auto matV(Params const &params, Tangent const &theta) -> Eigen::Matrix< Scalar, kPointDim, kPointDim >
Definition: rotation2.h:180
sophus::lie::Rotation2Impl::kIisParallelLinePreserving
static constexpr bool kIisParallelLinePreserving
Definition: rotation2.h:29
sophus::lie::Rotation2Impl::kPointDim
static const int kPointDim
Definition: rotation2.h:33
sophus::lie::Rotation2Impl::kIsShapePreserving
static constexpr bool kIsShapePreserving
Definition: rotation2.h:27
sophus::UnitVector
Definition: lie_group.h:14
sophus
Image MutImage, owning images types.
Definition: num_diff.h:20
sophus::lie::Rotation2Impl::vee
static auto vee(Eigen::Matrix< Scalar, kAmbientDim, kAmbientDim > const &mat) -> Eigen::Matrix< Scalar, kDof, 1 >
Definition: rotation2.h:104
sophus::lie::Rotation2Impl::compactMatrix
static auto compactMatrix(Params const &unit_complex) -> Eigen::Matrix< Scalar, kPointDim, kPointDim >
Definition: rotation2.h:167
sophus::lie::Rotation2Impl::action
static auto action(Params const &unit_complex, UnitVector< TCompatibleScalar, kPointDim > const &direction_vector) -> UnitVectorReturn< TCompatibleScalar >
Definition: rotation2.h:147
sophus::lie::Rotation2Impl::kNumParams
static const int kNumParams
Definition: rotation2.h:32
sophus::lie::Rotation2Impl::kIisSizePreserving
static constexpr bool kIisSizePreserving
Definition: rotation2.h:28
sophus::lie::Rotation2Impl::areParamsValid
static auto areParamsValid(Params const &unit_complex) -> sophus::Expected< Success >
Definition: rotation2.h:61
sophus::lie::Rotation2Impl::matrix
static auto matrix(Params const &unit_complex) -> Eigen::Matrix< Scalar, kPointDim, kPointDim >
Definition: rotation2.h:174
sophus::lie::Rotation2Impl::tangentExamples
static auto tangentExamples() -> std::vector< Tangent >
Definition: rotation2.h:262
sophus::lie::Rotation2Impl::kIsDirectionVectorPreserving
static constexpr bool kIsDirectionVectorPreserving
Definition: rotation2.h:26
sophus::lie::Rotation2Impl::adOfTranslation
static auto adOfTranslation(Point const &point) -> Eigen::Matrix< Scalar, kPointDim, kDof >
Definition: rotation2.h:223
sophus::ComplexImpl
Definition: complex.h:17
complex.h
sophus::lie::Rotation2Impl::dxExpX
static auto dxExpX(Tangent const &theta) -> Eigen::Matrix< Scalar, kNumParams, kDof >
Definition: rotation2.h:233
sophus::lie::Rotation2Impl::kAmbientDim
static const int kAmbientDim
Definition: rotation2.h:34
sophus::lie::Rotation2Impl::hat
static auto hat(Tangent const &angle) -> Eigen::Matrix< Scalar, kAmbientDim, kAmbientDim >
Definition: rotation2.h:98
sophus::lie::Rotation2Impl::hasShortestPathAmbiguity
static auto hasShortestPathAmbiguity(Params const &foo_from_bar) -> bool
Definition: rotation2.h:78
SOPHUS_UNEXPECTED
#define SOPHUS_UNEXPECTED(...)
Definition: common.h:57
sophus::lie::Rotation2Impl::kIsAxisDirectionPreserving
static constexpr bool kIsAxisDirectionPreserving
Definition: rotation2.h:25
sophus::lie::Rotation2Impl::multiplication
static auto multiplication(Params const &lhs_params, Eigen::Matrix< TCompatibleScalar, 2, 1 > const &rhs_params) -> ParamsReturn< TCompatibleScalar >
Definition: rotation2.h:116
sophus::lie::Rotation2Impl::toAmbient
static auto toAmbient(Point const &point) -> Eigen::Vector< Scalar, kAmbientDim >
Definition: rotation2.h:155
sophus::lie::Rotation2Impl::PointReturn
Eigen::Vector< ScalarReturn< TCompatibleScalar >, kPointDim > PointReturn
Definition: rotation2.h:49
sophus::lie::Rotation2Impl::inverse
static auto inverse(Params const &unit_complex) -> Params
Definition: rotation2.h:111
sophus::lie::Rotation2Impl::adjOfTranslation
static auto adjOfTranslation(Params const &, Point const &point) -> Eigen::Matrix< Scalar, kPointDim, kDof >
Definition: rotation2.h:218
unit_vector.h
sophus::lie::Rotation2Impl::ScalarReturn
typename Eigen::ScalarBinaryOpTraits< Scalar, TCompatibleScalar >::ReturnType ScalarReturn
Definition: rotation2.h:42
sophus::lie::Rotation2Impl::dxThisMulExpXAt0
static auto dxThisMulExpXAt0(Params const &unit_complex) -> Eigen::Matrix< Scalar, kNumParams, kDof >
Definition: rotation2.h:250
sophus::UnitVector::fromParams
static auto fromParams(Eigen::Matrix< TScalar, kN, 1 > const &v) -> UnitVector
Definition: unit_vector.h:166
sophus::lie::Rotation2Impl::invalidParamsExamples
static auto invalidParamsExamples() -> std::vector< Params >
Definition: rotation2.h:283
sophus::lie::Rotation2Impl::log
static auto log(Params const &unit_complex) -> Tangent
Definition: rotation2.h:93
sophus::lie::Rotation2Impl::exp
static auto exp(Tangent const &angle) -> Params
Definition: rotation2.h:87
sophus::lie::Rotation2Impl::kIsOriginPreserving
static constexpr bool kIsOriginPreserving
Definition: rotation2.h:24
sophus::lie::Rotation2Impl::Scalar
TScalar Scalar
Definition: rotation2.h:21
sophus::ComplexImpl::multiplication
static auto multiplication(Eigen::Vector< Scalar, 2 > const &lhs_real_imag, Eigen::Vector< TCompatibleScalar, 2 > const &rhs_real_imag) -> ParamsReturn< TCompatibleScalar >
Definition: complex.h:64
sophus::lie::Rotation2Impl::ad
static auto ad(Tangent const &) -> Eigen::Matrix< Scalar, kDof, kDof >
Definition: rotation2.h:229
sophus::lie::Rotation2Impl::dxExpXTimesPointAt0
static auto dxExpXTimesPointAt0(Point const &point) -> Eigen::Matrix< Scalar, kNumParams, kDof >
Definition: rotation2.h:245
sophus::lie::Rotation2Impl::Tangent
Eigen::Vector< Scalar, kDof > Tangent
Definition: rotation2.h:36
sophus::lie::Rotation2Impl::dxLogThisInvTimesXAtThis
static auto dxLogThisInvTimesXAtThis(Params const &unit_complex) -> Eigen::Matrix< Scalar, kDof, kNumParams >
Definition: rotation2.h:255
sophus::lie::Rotation2Impl::Params
Eigen::Vector< Scalar, kNumParams > Params
Definition: rotation2.h:37
sophus::lie::Rotation2Impl
Definition: rotation2.h:19
sophus::lie::Rotation2Impl::Point
Eigen::Vector< Scalar, kPointDim > Point
Definition: rotation2.h:38
sophus::lie::Rotation2Impl::paramsExamples
static auto paramsExamples() -> std::vector< Params >
Definition: rotation2.h:274
sophus::lie::Rotation2Impl::kDof
static const int kDof
Definition: rotation2.h:31
sophus::lie::Rotation2Impl::ParamsReturn
Eigen::Vector< ScalarReturn< TCompatibleScalar >, kNumParams > ParamsReturn
Definition: rotation2.h:46
sophus::lie::Rotation2Impl::matVInverse
static auto matVInverse(Params const &z, Tangent const &theta) -> Eigen::Matrix< Scalar, kPointDim, kPointDim >
Definition: rotation2.h:200
sophus::lie::Rotation2Impl::identityParams
static auto identityParams() -> Params
Definition: rotation2.h:57
sophus::lie::Rotation2Impl::adj
static auto adj(Params const &) -> Eigen::Matrix< Scalar, kDof, kDof >
Definition: rotation2.h:160