farm-ng-core
unit_vector.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 
11 #include "sophus/common/common.h"
13 
14 #include <Eigen/Dense>
15 
16 namespace sophus {
17 
18 // Forward declarations
19 template <class TScalar, int kN>
20 class UnitVector;
21 
22 // Convenience typedefs
23 template <class TScalar>
25 template <class TScalar>
27 
30 
31 namespace linalg {
32 template <class TScalar, int kDim>
34  public:
35  using Scalar = TScalar;
36 
37  static int constexpr kDof = kDim - 1;
38  static int constexpr kNumParams = kDim;
39 
40  using Params = Eigen::Vector<Scalar, kNumParams>;
41  using Tangent = Eigen::Vector<Scalar, kDof>;
42 
43  static auto unitX() -> UnitVector<Scalar, kDim> {
44  return UnitVector<Scalar, kDim>::fromUnitVector(Params::UnitX());
45  }
46 
47  static auto unitY() -> UnitVector<Scalar, kDim> {
48  return UnitVector<Scalar, kDim>::fromUnitVector(Params::UnitY());
49  }
50 
51  static auto unitZ() -> UnitVector<Scalar, kDim> {
52  return UnitVector<Scalar, kDim>::fromUnitVector(Params::UnitZ());
53  }
54 
55  static auto areParamsValid(Params const& unit_vector)
56  -> sophus::Expected<Success> {
57  static const Scalar kThr = kEpsilon<Scalar>;
58  const Scalar squared_norm = unit_vector.squaredNorm();
59  using std::abs;
60  if (!(abs(squared_norm - 1.0) <= kThr)) {
61  return SOPHUS_UNEXPECTED(
62  "unit vector ({}) is not of unit length.\n"
63  "Squared norm: {}, thr: {}",
64  unit_vector.transpose(),
65  squared_norm,
66  kThr);
67  }
68  return sophus::Expected<Success>{};
69  }
70 
71  static auto oplus(Params const& params, Tangent const& delta) -> Params {
72  return matRx(params) * exp(delta);
73  }
74 
75  static auto ominus(Params const& lhs_params, Params const& rhs_params)
76  -> Tangent {
77  return log((matRx(lhs_params).transpose() * rhs_params).eval());
78  }
79 
80  static auto paramsExamples() -> std::vector<Params> {
81  return std::vector<Params>(
82  {Params::UnitX(), Params::UnitY(), -Params::UnitX(), -Params::UnitY()});
83  }
84  static auto invalidParamsExamples() -> std::vector<Params> {
85  return std::vector<Params>(
86  {Params::Zero(), Params::Ones(), 2.0 * Params::UnitX()});
87  }
88 
89  static auto tangentExamples() -> std::vector<Tangent> {
90  return std::vector<Tangent>({
91  Tangent::Zero(),
92  0.01 * Tangent::UnitX(),
93  0.001 * Tangent::Ones(),
94  });
95  }
96 
97  private:
98  static auto matRx(Params const& params)
99  -> Eigen::Matrix<Scalar, kNumParams, kNumParams> {
100  static Eigen::Vector<TScalar, kDim> const kUnitX =
101  Eigen::Vector<TScalar, kDim>::UnitX();
102  if ((kUnitX - params).squaredNorm() < kEpsilon<Scalar>) {
103  return Eigen::Matrix<Scalar, kNumParams, kNumParams>::Identity();
104  }
105  Params v = params - kUnitX;
106  return Eigen::Matrix<Scalar, kNumParams, kNumParams>::Identity() -
107  2.0 * (v * v.transpose()) / v.squaredNorm();
108  }
109 
110  static auto exp(Tangent const& delta) -> Params {
111  using std::cos;
112  Params params;
113  Scalar theta = delta.norm();
114  params[0] = cos(theta);
115  params.template tail<kDof>() = sinc(theta) * delta;
116  return params;
117  }
118 
119  static auto log(Params const& params) -> Tangent {
120  using std::atan2;
121 
122  static Tangent const kUnitX = Tangent::UnitX();
123  Scalar x = params[0];
124  Tangent tail = params.template tail<kDof>();
125  Scalar theta = tail.norm();
126 
127  if (abs(theta) < kEpsilon<Scalar>) {
128  return atan2(Scalar(0.0), x) * kUnitX;
129  }
130 
131  return (1.0 / theta) * atan2(theta, x) * tail;
132  }
133 
134  static auto sinc(Scalar x) -> Scalar {
135  using std::abs;
136  using std::sin;
137  if (abs(x) < kEpsilon<Scalar>) {
138  return 1.0 - (1.0 / 6.0) * (x * x);
139  }
140  return sin(x) / x;
141  }
142 };
143 
144 } // namespace linalg
145 
146 template <class TScalar, int kN>
147 class UnitVector : public linalg::UnitVectorImpl<TScalar, kN> {
148  public:
149  using Scalar = TScalar;
151  static_assert(concepts::ManifoldImpl<Impl>);
152 
153  static int constexpr kDof = kN - 1;
154  static int constexpr kNumParams = kN;
155  using Tangent = Eigen::Vector<Scalar, kDof>;
156  using Params = Eigen::Vector<Scalar, kNumParams>;
157 
158  static auto tryFromUnitVector(Eigen::Matrix<TScalar, kN, 1> const& v)
159  -> Expected<UnitVector> {
160  SOPHUS_TRY(auto, maybe_valid, Impl::areParamsValid(v));
161  UnitVector unit_vector;
162  unit_vector.vector_ = v;
163  return unit_vector;
164  }
165 
166  static auto fromParams(Eigen::Matrix<TScalar, kN, 1> const& v) -> UnitVector {
167  Expected<UnitVector> e_vec = tryFromUnitVector(v);
168  if (!e_vec.has_value()) {
169  SOPHUS_PANIC("{}", e_vec.error());
170  }
171  return e_vec.value();
172  }
173 
174  // Precondition: v must be of unit length.
175  static auto fromUnitVector(Eigen::Matrix<TScalar, kN, 1> const& v)
176  -> UnitVector {
177  return fromParams(v);
178  }
179 
180  static auto fromVectorAndNormalize(Eigen::Matrix<TScalar, kN, 1> const& v)
181  -> UnitVector {
182  return fromUnitVector(v.normalized());
183  }
184 
185  auto oplus(Tangent const& delta) const -> UnitVector {
186  UnitVector v;
187  v.vector_ = Impl::oplus(vector_, delta);
188  return v;
189  }
190 
191  auto ominus(UnitVector const& rhs_params) const -> Tangent {
192  return Impl::ominus(vector_, rhs_params.vector_);
193  }
194 
195  void setParams(Eigen::Matrix<TScalar, kN, 1> const& v) const {
197  vector_.params = v;
198  }
199 
200  [[nodiscard]] auto params() const -> Eigen::Matrix<TScalar, kN, 1> const& {
201  return vector_;
202  }
203 
204  [[nodiscard]] auto vector() const -> Eigen::Matrix<TScalar, kN, 1> const& {
205  return vector_;
206  }
207 
208  [[nodiscard]] auto unsafeMutPtr() { return this->vector_.data(); }
209  [[nodiscard]] auto ptr() const { return this->vector_.data(); }
210 
211  UnitVector(UnitVector const&) = default;
212  auto operator=(UnitVector const&) -> UnitVector& = default;
213 
214  template <concepts::Range TSequenceContainer>
215  static auto average(TSequenceContainer const& range) -> UnitVector {
216  size_t const len = std::distance(std::begin(range), std::end(range));
217  SOPHUS_ASSERT_GE(len, 0);
218 
219  Params params = Params::Zero();
220  for (auto const& m : range) {
221  params += m.params();
222  }
223  return fromVectorAndNormalize(params / len);
224  }
225 
226  private:
227  UnitVector() {}
228 
229  // Class invariant: v_ is of unit length.
230  Eigen::Matrix<TScalar, kN, 1> vector_;
231 };
232 
233 static_assert(concepts::Manifold<UnitVector<double, 3>>);
234 
235 } // namespace sophus
SOPHUS_PANIC
#define SOPHUS_PANIC(...)
Definition: common.h:50
SOPHUS_ASSERT_GE
#define SOPHUS_ASSERT_GE(...)
Definition: common.h:42
sophus::linalg::UnitVectorImpl::paramsExamples
static auto paramsExamples() -> std::vector< Params >
Definition: unit_vector.h:80
Eigen
Definition: params.h:72
sophus::linalg::UnitVectorImpl
Definition: unit_vector.h:33
sophus::linalg::UnitVectorImpl::kDof
static constexpr int kDof
Definition: unit_vector.h:37
SOPHUS_ASSERT
#define SOPHUS_ASSERT(...)
Definition: common.h:40
sophus::UnitVector::fromVectorAndNormalize
static auto fromVectorAndNormalize(Eigen::Matrix< TScalar, kN, 1 > const &v) -> UnitVector
Definition: unit_vector.h:180
sophus::linalg::UnitVectorImpl::unitX
static auto unitX() -> UnitVector< Scalar, kDim >
Definition: unit_vector.h:43
sophus::UnitVector
Definition: lie_group.h:14
manifold.h
sophus
Image MutImage, owning images types.
Definition: num_diff.h:20
sophus::linalg::UnitVectorImpl::Scalar
TScalar Scalar
Definition: unit_vector.h:35
sophus::UnitVector::ptr
auto ptr() const
Definition: unit_vector.h:209
sophus::UnitVector::kNumParams
static constexpr int kNumParams
Definition: unit_vector.h:154
sophus::UnitVector::params
auto params() const -> Eigen::Matrix< TScalar, kN, 1 > const &
Definition: unit_vector.h:200
sophus::linalg::UnitVectorImpl::kNumParams
static constexpr int kNumParams
Definition: unit_vector.h:38
sophus::UnitVector::Params
Eigen::Vector< Scalar, kNumParams > Params
Definition: unit_vector.h:156
sophus::UnitVector::ominus
auto ominus(UnitVector const &rhs_params) const -> Tangent
Definition: unit_vector.h:191
sophus::UnitVector::vector
auto vector() const -> Eigen::Matrix< TScalar, kN, 1 > const &
Definition: unit_vector.h:204
sophus::UnitVector::kDof
static constexpr int kDof
Definition: unit_vector.h:153
sophus::linalg::UnitVectorImpl::Params
Eigen::Vector< Scalar, kNumParams > Params
Definition: unit_vector.h:40
sophus::linalg::UnitVectorImpl::ominus
static auto ominus(Params const &lhs_params, Params const &rhs_params) -> Tangent
Definition: unit_vector.h:75
sophus::UnitVector::unsafeMutPtr
auto unsafeMutPtr()
Definition: unit_vector.h:208
SOPHUS_UNEXPECTED
#define SOPHUS_UNEXPECTED(...)
Definition: common.h:57
sophus::transpose
auto transpose(TPoint p)
Definition: vector_space.h:233
sophus::linalg::UnitVectorImpl::areParamsValid
static auto areParamsValid(Params const &unit_vector) -> sophus::Expected< Success >
Definition: unit_vector.h:55
sophus::linalg::UnitVectorImpl::unitZ
static auto unitZ() -> UnitVector< Scalar, kDim >
Definition: unit_vector.h:51
sophus::linalg::UnitVectorImpl::unitY
static auto unitY() -> UnitVector< Scalar, kDim >
Definition: unit_vector.h:47
sophus::linalg::UnitVectorImpl::invalidParamsExamples
static auto invalidParamsExamples() -> std::vector< Params >
Definition: unit_vector.h:84
sophus::UnitVector::fromParams
static auto fromParams(Eigen::Matrix< TScalar, kN, 1 > const &v) -> UnitVector
Definition: unit_vector.h:166
sophus::UnitVector::tryFromUnitVector
static auto tryFromUnitVector(Eigen::Matrix< TScalar, kN, 1 > const &v) -> Expected< UnitVector >
Definition: unit_vector.h:158
common.h
sophus::UnitVector::average
static auto average(TSequenceContainer const &range) -> UnitVector
Definition: unit_vector.h:215
sophus::UnitVector::operator=
auto operator=(UnitVector const &) -> UnitVector &=default
sophus::linalg::UnitVectorImpl::Tangent
Eigen::Vector< Scalar, kDof > Tangent
Definition: unit_vector.h:41
sophus::UnitVector::fromUnitVector
static auto fromUnitVector(Eigen::Matrix< TScalar, kN, 1 > const &v) -> UnitVector
Definition: unit_vector.h:175
sophus::concepts::Manifold
concept Manifold
Definition: manifold.h:33
sophus::linalg::UnitVectorImpl::tangentExamples
static auto tangentExamples() -> std::vector< Tangent >
Definition: unit_vector.h:89
sophus::eval
auto eval(TPoint const &p)
Definition: vector_space.h:44
sophus::UnitVector::Tangent
Eigen::Vector< Scalar, kDof > Tangent
Definition: unit_vector.h:155
SOPHUS_TRY
#define SOPHUS_TRY(...)
Definition: common.h:55
sophus::UnitVector::oplus
auto oplus(Tangent const &delta) const -> UnitVector
Definition: unit_vector.h:185
sophus::UnitVector::setParams
void setParams(Eigen::Matrix< TScalar, kN, 1 > const &v) const
Definition: unit_vector.h:195
sophus::UnitVector::Scalar
TScalar Scalar
Definition: unit_vector.h:149
sophus::linalg::UnitVectorImpl::oplus
static auto oplus(Params const &params, Tangent const &delta) -> Params
Definition: unit_vector.h:71