smooth
A C++ library for Lie theory
Loading...
Searching...
No Matches
submanifold.hpp
1// Copyright (C) 2021-2022 Petter Nilsson. MIT License.
2
3#pragma once
4
5#include <algorithm>
6
8
9SMOOTH_BEGIN_NAMESPACE
10
14template<Manifold M>
16{
17public:
21 SubManifold() : SubManifold(traits::man<M>::Default(), traits::man<M>::Default()) {}
22
37 SubManifold(const M & m0, const M & m, Eigen::Ref<const Eigen::VectorXi> fixed_dims = Eigen::VectorXi::Zero(0))
38 : m_m0(m0), m_m(m), m_fixed_dims(fixed_dims)
39 {
40 [[maybe_unused]] const auto in_range_pred = [&](auto x) { return x >= 0 && x < ::smooth::dof(m_m0); };
41 assert(std::ranges::all_of(fixed_dims, in_range_pred));
42 std::sort(m_fixed_dims.begin(), m_fixed_dims.end());
43 m_calc.setZero(::smooth::dof(m_m0));
44 }
45
49 SubManifold(const M & m0, Eigen::Ref<const Eigen::VectorXi> fixed_dims) : SubManifold(m0, m0, fixed_dims) {}
50
52 const M & m() const { return m_m; }
53
55 const M & m0() const { return m_m0; }
56
58 const Eigen::VectorXi & fixed_dims() const { return m_fixed_dims; }
59
61 Eigen::Index dof() const { return ::smooth::dof(m_m0) - m_fixed_dims.size(); }
62
64 template<typename Derived>
65 SubManifold<M> rplus(const Eigen::MatrixBase<Derived> & a) const
66 {
67 assert(dof() == a.size());
68 m_calc.setZero(::smooth::dof(m_m0));
69 for (auto i = 0, j = 0, k = 0; i < m_calc.size(); ++i) {
70 // i: full range
71 // j: reduced range
72 // k: idx in fixed_dims
73 if (k >= m_fixed_dims.size() || i != m_fixed_dims(k)) {
74 m_calc(i) = a(j++);
75 } else {
76 ++k;
77 }
78 }
79 return SubManifold<M>(m_m0, traits::man<M>::rplus(m_m, m_calc), m_fixed_dims);
80 }
81
83 Eigen::Vector<typename traits::man<M>::Scalar, -1> rminus(const SubManifold<M> & other) const
84 {
85 assert(m_fixed_dims.isApprox(other.fixed_dims()));
86 assert(m_m0.isApprox(other.m0()));
87
88 m_calc = traits::man<M>::rminus(m_m, other.m());
89
90 Eigen::Vector<typename traits::man<M>::Scalar, -1> ret;
91 ret.setZero(dof());
92 for (auto i = 0, j = 0, k = 0; i < m_calc.size(); ++i) {
93 // i: full range
94 // j: reduced range
95 // k: idx in fixed_dims
96 if (k >= m_fixed_dims.size() || i != m_fixed_dims(k)) {
97 ret(j++) = m_calc(i);
98 } else {
99 ++k;
100 }
101 }
102 return ret;
103 }
104
105private:
106 M m_m0{};
107 M m_m{};
108 Eigen::VectorXi m_fixed_dims{};
109
110 // calculation vector
111 mutable Tangent<M> m_calc{};
112};
113
114namespace traits {
115
117template<Manifold M>
118struct man<SubManifold<M>>
119{
120 using Scalar = man<M>::Scalar;
122 template<typename NewScalar>
124
125 static constexpr int Dof = -1;
126
127 static inline Eigen::Index dof(const PlainObject & m) { return m.dof(); }
128
129 static inline PlainObject Default(Eigen::Index dof)
130 {
131 Eigen::VectorXi fixed_dims = Eigen::VectorXi::Zero(0);
132 return PlainObject(man<M>::Default(dof));
133 }
134
135 template<typename NewScalar>
136 static inline CastT<NewScalar> cast(const PlainObject & m)
137 {
138 return CastT<NewScalar>(
139 man<M>::template cast<NewScalar>(m.m()), man<M>::template cast<NewScalar>(m.m0()), m.fixed_dims());
140 }
141
142 template<typename Derived>
143 static inline PlainObject rplus(const PlainObject & m, const Eigen::MatrixBase<Derived> & a)
144 {
145 return m.rplus(a);
146 }
147
148 static inline Eigen::Vector<Scalar, Dof> rminus(const PlainObject & m1, const PlainObject & m2)
149 {
150 return m1.rminus(m2);
151 }
152};
153
154} // namespace traits
155
156SMOOTH_END_NAMESPACE
A Submanifold is a subspace of a manifold defined by an origin m0 and a tangent subspace.
const M & m() const
Access value in embedded space.
SubManifold< M > rplus(const Eigen::MatrixBase< Derived > &a) const
Right-plus.
SubManifold()
Construct with full tangent space.
Eigen::Index dof() const
Degrees of freedom.
SubManifold(const M &m0, Eigen::Ref< const Eigen::VectorXi > fixed_dims)
As above, but with m = m0.
const M & m0() const
Access origin in embedded space.
const Eigen::VectorXi & fixed_dims() const
Access active dimensions.
Eigen::Vector< typename traits::man< M >::Scalar, -1 > rminus(const SubManifold< M > &other) const
Right-minus.
SubManifold(const M &m0, const M &m, Eigen::Ref< const Eigen::VectorXi > fixed_dims=Eigen::VectorXi::Zero(0))
Create a sub-manifold of M defined as [ x \in M : x = x0 \oplus \sum_k \alpha_k e_{i_k},...
PlainObject< M > Default()
Default-initialized Manifold with static dof.
Definition manifold.hpp:135
Eigen::Vector< Scalar< M >, Dof< M > > Tangent
Tangent as a Dof-length vector.
Definition manifold.hpp:106
typename traits::man< M >::Scalar Scalar
Manifold scalar type.
Definition manifold.hpp:88
Eigen::Index dof(const M &m)
Manifold degrees of freedom (tangent space dimension)
Definition manifold.hpp:145
Tangent< M > rminus(const M &g1, const Mo &g2)
Manifold right-minus.
Definition manifold.hpp:172
PlainObject< M > rplus(const M &m, const Eigen::MatrixBase< Derived > &a)
Manifold right-plus.
Definition manifold.hpp:163
typename traits::man< M >::template CastT< NewScalar > CastT
Cast'ed type.
Definition manifold.hpp:100
CastT< NewScalar, M > cast(const M &m)
Cast to different scalar type.
Definition manifold.hpp:154
typename traits::man< M >::PlainObject PlainObject
Manifold default type.
Definition manifold.hpp:94
Trait class for making a class a Manifold instance via specialization.
Definition manifold.hpp:21