farm-ng-core
product_manifold.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 
12 
13 namespace sophus {
14 
15 // Credit: @bogdan at http://stackoverflow.com/q/37373602/6367128
16 template <int... Ds>
17 constexpr std::array<int, sizeof...(Ds)> cumulativeSum() {
18  int v = 0;
19  return {{v += Ds...}};
20 }
21 
22 template <concepts::Manifold... TSubManifold>
24  public:
25  using Self = ProductManifold<TSubManifold...>;
26 
27  using Tuple = std::tuple<TSubManifold...>;
28  using Scalars = std::tuple<typename TSubManifold::Scalar...>;
29 
30  static constexpr size_t kNumManifolds = sizeof...(TSubManifold);
31  static constexpr std::array<int, kNumManifolds> kManifoldSizes = {
32  {TSubManifold::kDof...}};
33  static constexpr std::array<int, kNumManifolds + 1> kManifoldStarts =
34  cumulativeSum<0, TSubManifold::kDof...>();
35 
37 
38  static constexpr size_t kNumParams = [](auto const&... sizes) {
39  size_t sum = 0;
40  (..., (sum += sizes));
41  return sum;
42  }(TSubManifold::kNumParams...);
43 
44  static constexpr size_t kDof = [](auto const&... sizes) {
45  size_t sum = 0;
46  (..., (sum += sizes));
47  return sum;
48  }(TSubManifold::kDof...);
49 
50  // Return ith diagonal block of matrix representing covariance or similar.
51  template <size_t i, class Derived>
52  static auto subBlock(Eigen::MatrixBase<Derived> const& mat) {
53  return mat
54  .template block<kManifoldSizes[i], kManifoldSizes[i]>(
56  .eval();
57  }
58 
59  using Tangent = Eigen::Vector<Scalar, kDof>;
60 
61  ProductManifold() = default;
62  ProductManifold(ProductManifold const&) = default;
63  ProductManifold& operator=(ProductManifold const&) = default;
64 
65  ProductManifold(TSubManifold const&... manifolds)
66  : manifolds_(manifolds...) {}
67 
68  // Return ith sub-manifold
69  template <size_t i>
70  auto& subManifold() {
71  return std::get<i>(manifolds_);
72  }
73 
74  // Return ith sub-manifold
75  template <size_t i>
76  auto const& subManifold() const {
77  return std::get<i>(manifolds_);
78  }
79 
80  auto oplus(Tangent const& tangent) const -> Self {
81  Self result = *this;
82  oplusImpl(
83  [](auto const& manifold, auto const& tangent) {
84  return manifold.oplus(tangent);
85  },
86  result.manifolds_,
87  tangent);
88  return result;
89  }
90 
91  auto ominus(Self const& other) const -> Tangent {
92  Tangent tangent;
93 
94  ominusImpl(
95  [](auto const& manifold, auto const& other) {
96  return manifold.ominus(other);
97  },
98  this->manifolds_,
99  other.manifolds_,
100  tangent);
101  return tangent;
102  }
103 
104  static auto tangentExamples() -> std::vector<Tangent> {
105  std::vector<Tangent> out;
106  Tangent t;
107  getTangent(t);
108  out.push_back(t);
109  return out;
110  }
111 
112  template <size_t kArrayLen>
113  static std::optional<ProductManifold<TSubManifold...>> average(
114  std::array<ProductManifold<TSubManifold...>, kArrayLen> const& range) {
115  SOPHUS_ASSERT_GE(kArrayLen, 0);
116  ProductManifold<TSubManifold...> result;
117  averageImpl<0, kArrayLen>(result, range);
118  return result;
119  }
120 
121  private:
122  template <int k, size_t kArrayLen>
123  static auto averageImpl(
125  std::array<ProductManifold<TSubManifold...>, kArrayLen> const& range);
126 
127  template <size_t i = 0>
128  static auto getTangent(Tangent& t) {
129  auto v = std::tuple_element_t<i, Tuple>::tangentExamples();
130  getBlock<i>(t) = v[0];
131  if constexpr (i < sizeof...(TSubManifold) - 1) {
132  // recurse if not at end
133  getTangent<i + 1>(t);
134  }
135  return t;
136  }
137 
138  template <size_t i = 0>
139  void oplusImpl(auto const& func, Tuple& out, Tangent const& in) const {
140  getBlock<i>(out) = func(getBlock<i>(manifolds_), getBlock<i>(in));
141 
142  if constexpr (i < sizeof...(TSubManifold) - 1) {
143  oplusImpl<i + 1>(func, out, in);
144  }
145  }
146 
147  template <size_t i = 0>
148  void ominusImpl(
149  auto const& func,
150  Tuple const& out,
151  Tuple const& in,
152  Tangent& tangent) const {
153  getBlock<i>(tangent) = func(getBlock<i>(out), getBlock<i>(in));
154 
155  if constexpr (i < sizeof...(TSubManifold) - 1) {
156  ominusImpl<i + 1>(func, out, in, tangent);
157  }
158  }
159 
160  template <size_t i>
161  static auto& getBlock(Tuple& g) {
162  return std::get<i>(g);
163  }
164 
165  template <size_t i>
166  static auto const& getBlock(Tuple const& g) {
167  return std::get<i>(g);
168  }
169 
170  template <size_t i>
171  static auto getBlock(Tangent& tangent) {
172  constexpr size_t offset = kManifoldStarts[i];
173  constexpr size_t size = kManifoldSizes[i];
174  return tangent.template segment<size>(offset);
175  }
176 
177  template <size_t i>
178  static auto getBlock(Tangent const& tangent) {
179  constexpr size_t offset = kManifoldStarts[i];
180  constexpr size_t size = kManifoldSizes[i];
181  return tangent.template segment<size>(offset);
182  }
183 
184  Tuple manifolds_;
185 };
186 
187 namespace details {
188 template <int k, size_t kArrayLen, class... TManifold>
189 struct ContainerAdapter {
190  using Container = ProductManifold<TManifold...>;
191  using ContainerArray = std::array<Container, kArrayLen>;
192  using value_type = std::decay_t<
193  decltype(std::declval<Container>().template subManifold<k>())>;
194 
195  struct Iterator {
196  using iterator_category = std::forward_iterator_tag;
197  using difference_type = std::ptrdiff_t;
198  using value_type =
199  typename ContainerAdapter<k, kArrayLen, TManifold...>::value_type;
200  using pointer = value_type const*;
201  using reference = value_type const&;
202 
203  Iterator(typename ContainerArray::const_iterator it) : it_(it) {}
204 
205  reference operator*() const { return it_->template subManifold<k>(); }
206  pointer operator->() { return &operator*(); }
207 
208  // Prefix increment
209  Iterator& operator++() {
210  it_++;
211  return *this;
212  }
213 
214  // Postfix increment
215  Iterator operator++(int) {
216  Iterator tmp = *this;
217  ++(*this);
218  return tmp;
219  }
220 
221  friend bool operator==(Iterator const& a, Iterator const& b) {
222  return a.it_ == b.it_;
223  };
224  friend bool operator!=(Iterator const& a, Iterator const& b) {
225  return a.it_ != b.it_;
226  };
227 
228  private:
229  typename ContainerArray::const_iterator it_;
230  };
231 
232  ContainerAdapter(std::array<Container, kArrayLen> const& ref) : ref(ref) {}
233 
234  using const_iterator = Iterator;
235  using iterator = Iterator;
236  Iterator cbegin() const { return Iterator(ref.cbegin()); }
237  Iterator cend() const { return Iterator(ref.cend()); }
238  Iterator begin() const { return cbegin(); }
239  Iterator end() const { return cend(); }
240 
241  std::array<Container, kArrayLen> const& ref;
242 };
243 } // namespace details
244 
245 template <concepts::Manifold... TSubManifold>
246 template <int k, size_t kArrayLen>
247 auto ProductManifold<TSubManifold...>::averageImpl(
248  ProductManifold<TSubManifold...>& result,
249  std::array<ProductManifold<TSubManifold...>, kArrayLen> const& range) {
250  details::ContainerAdapter<k, kArrayLen, TSubManifold...> adapter(range);
251  auto const maybe_avg = std::tuple_element_t<
252  k,
253  typename ProductManifold<TSubManifold...>::Tuple>::average(adapter);
254  result.template subManifold<k>() = FARM_UNWRAP(maybe_avg);
255 
256  if constexpr (k < sizeof...(TSubManifold) - 1) {
257  // recurse if not at end
258  averageImpl<k + 1, kArrayLen>(result, range);
259  }
260  return std::nullopt;
261 }
262 
263 } // namespace sophus
sophus::ProductManifold::Scalars
std::tuple< typename TSubManifold::Scalar... > Scalars
Definition: product_manifold.h:28
SOPHUS_ASSERT_GE
#define SOPHUS_ASSERT_GE(...)
Definition: common.h:42
sophus::average
auto average(TSequenceContainer const &foo_from_bar_transforms) -> std::enable_if_t< std::is_same< typename TSequenceContainer::value_type, Translation< TScalar, kPointDim > >::value, std::optional< typename TSequenceContainer::value_type > >
Definition: average.h:81
sophus::ProductManifold::kManifoldSizes
static constexpr std::array< int, kNumManifolds > kManifoldSizes
Definition: product_manifold.h:31
sophus::ProductManifold::kNumManifolds
static constexpr size_t kNumManifolds
Definition: product_manifold.h:30
manifold.h
sophus::ProductManifold::Tuple
std::tuple< TSubManifold... > Tuple
Definition: product_manifold.h:27
sophus
Image MutImage, owning images types.
Definition: num_diff.h:20
sophus::ProductManifold::tangentExamples
static auto tangentExamples() -> std::vector< Tangent >
Definition: product_manifold.h:104
sophus::cumulativeSum
constexpr std::array< int, sizeof...(Ds)> cumulativeSum()
Definition: product_manifold.h:17
sophus::ProductManifold::kDof
static constexpr size_t kDof
Definition: product_manifold.h:44
sophus::ProductManifold::ProductManifold
ProductManifold(TSubManifold const &... manifolds)
Definition: product_manifold.h:65
sophus::ProductManifold
Definition: product_manifold.h:23
sophus::operator*
auto operator*(Isometry2< TT > const &bar_from_foo, Ray< TT, 2 > const &ray_foo) -> Ray< TT, 2 >
Definition: ray.h:97
sophus::ProductManifold::ProductManifold
ProductManifold()=default
sophus::operator!=
auto operator!=(ImageSize const &lhs, ImageSize const &rhs) -> bool
Definition: image_size.cpp:37
sophus::ProductManifold::kManifoldStarts
static constexpr std::array< int, kNumManifolds+1 > kManifoldStarts
Definition: product_manifold.h:33
farm_ng::sum
auto sum(Expected< A > maybe_left, Expected< A > maybe_right) -> Expected< A >
Definition: expected_test.cpp:98
sophus::ProductManifold::average
static std::optional< ProductManifold< TSubManifold... > > average(std::array< ProductManifold< TSubManifold... >, kArrayLen > const &range)
Definition: product_manifold.h:113
sophus::ProductManifold::ominus
auto ominus(Self const &other) const -> Tangent
Definition: product_manifold.h:91
sophus::ProductManifold::kNumParams
static constexpr size_t kNumParams
Definition: product_manifold.h:38
sophus::ProductManifold::subBlock
static auto subBlock(Eigen::MatrixBase< Derived > const &mat)
Definition: product_manifold.h:52
sophus::operator==
auto operator==(Region< TT > const &lhs, Region< TT > const &rhs) -> bool
Definition: region.h:367
sophus::ProductManifold::Tangent
Eigen::Vector< Scalar, kDof > Tangent
Definition: product_manifold.h:59
sophus::ProductManifold::subManifold
auto & subManifold()
Definition: product_manifold.h:70
sophus::concepts::Manifold
concept Manifold
Definition: manifold.h:33
sophus::ProductManifold::subManifold
auto const & subManifold() const
Definition: product_manifold.h:76
sophus::ProductManifold::operator=
ProductManifold & operator=(ProductManifold const &)=default
sophus::ProductManifold::Scalar
typename std::tuple_element< 0, Scalars >::type Scalar
Definition: product_manifold.h:36
sophus::ProductManifold::oplus
auto oplus(Tangent const &tangent) const -> Self
Definition: product_manifold.h:80
core.event_service_recorder.func
func
Definition: event_service_recorder.py:420
FARM_UNWRAP
#define FARM_UNWRAP(wrapper,...)
Returns *wrapper, but panics if wrapper is nullopt or null.
Definition: logger.h:576
core.event_service.type
type
Definition: event_service.py:547