31template <
typename DstType,
typename SrcType>
32void assignBlock(
const SrcType& source,
size_t row,
size_t column,
33 DstType* destination) {
34 constexpr int rows = SrcType::RowsAtCompileTime;
35 constexpr int columns = SrcType::ColsAtCompileTime;
36 if constexpr (rows != Eigen::Dynamic && columns != Eigen::Dynamic) {
37 destination->template block<rows, columns>(
38 static_cast<int>(row),
static_cast<int>(column)) = source;
40 destination->block(row, column, source.rows(), source.cols()) = source;
48template <
typename G,
typename H>
56template <
typename G,
typename H>
62template <
typename G,
typename H>
65 ChartJacobian H2)
const {
66 const size_t d1 = firstDim();
67 const size_t d2 = secondDim();
68 const size_t d = d1 + d2;
69 if (
static_cast<size_t>(v.size()) != d) {
70 throw std::invalid_argument(
71 "ProductLieGroup::retract tangent dimension does not match product "
74 Jacobian1 D_g_first = Jacobian1::Zero(d1, d1);
75 Jacobian1 D_g_second = Jacobian1::Zero(d1, d1);
76 Jacobian2 D_h_first = Jacobian2::Zero(d2, d2);
77 Jacobian2 D_h_second = Jacobian2::Zero(d2, d2);
80 H1 ? &D_g_first :
nullptr, H2 ? &D_g_second :
nullptr);
83 H1 ? &D_h_first :
nullptr, H2 ? &D_h_second :
nullptr);
86 assignBlock(D_g_first, 0, 0, &*H1);
87 assignBlock(D_h_first, d1, d1, &*H1);
91 assignBlock(D_g_second, 0, 0, &*H2);
92 assignBlock(D_h_second, d1, d1, &*H2);
97template <
typename G,
typename H>
98typename ProductLieGroup<G, H>::TangentVector
101 ChartJacobian H2)
const {
103 const size_t d1 = firstDim();
104 const size_t d2 = secondDim();
105 const size_t d = d1 + d2;
107 Jacobian1 D_g_second;
109 Jacobian2 D_h_second;
112 H2 ? &D_g_second :
nullptr);
115 H2 ? &D_h_second :
nullptr);
118 assignBlock(D_g_first, 0, 0, &*H1);
119 assignBlock(D_h_first, d1, d1, &*H1);
123 assignBlock(D_g_second, 0, 0, &*H2);
124 assignBlock(D_h_second, d1, d1, &*H2);
129template <
typename G,
typename H>
134 if constexpr (firstDynamic && secondDynamic) {
136 if (Hv) *Hv = Matrix::Zero(0, 0);
139 throw std::invalid_argument(
140 "ProductLieGroup::Expmap requires split tangent vectors when both "
141 "factors are dynamic");
142 }
else if constexpr (firstDynamic) {
144 throw std::invalid_argument(
145 "ProductLieGroup::Expmap tangent dimension is too small for the "
146 "fixed second factor");
148 d1 =
static_cast<size_t>(v.size() - m);
149 d2 =
static_cast<size_t>(m);
150 }
else if constexpr (secondDynamic) {
152 throw std::invalid_argument(
153 "ProductLieGroup::Expmap tangent dimension is too small for the "
154 "fixed first factor");
156 d1 =
static_cast<size_t>(
n);
157 d2 =
static_cast<size_t>(v.size() -
n);
159 d1 =
static_cast<size_t>(
n);
160 d2 =
static_cast<size_t>(m);
162 if (
static_cast<size_t>(v.size()) != d1 + d2) {
163 throw std::invalid_argument(
164 "ProductLieGroup::Expmap tangent dimension does not match product "
179 const size_t d = d1 + d2;
181 Hv->block(0, 0, d, d1) = D_g_first;
182 Hv->block(0, d1, d, d2) = D_h_second;
187template <
typename G,
typename H>
193 const size_t d1 =
static_cast<size_t>(v1.size());
194 const size_t d2 =
static_cast<size_t>(v2.size());
195 const size_t d = d1 + d2;
197 Jacobian2 D_h_second;
201 *H1 = Matrix::Zero(d, d1);
202 assignBlock(D_g_first, 0, 0, &*H1);
205 *H2 = Matrix::Zero(d, d2);
206 assignBlock(D_h_second, d1, 0, &*H2);
211template <
typename G,
typename H>
214 const size_t d1 = p.firstDim();
215 const size_t d2 = p.secondDim();
216 const size_t d = d1 + d2;
224 Jacobian2 D_h_second;
230 assignBlock(D_g_first, 0, 0, &*Hp);
231 assignBlock(D_h_second, d1, d1, &*Hp);
235template <
typename G,
typename H>
242 const size_t d1 =
static_cast<size_t>(adjG.rows());
243 const size_t d2 =
static_cast<size_t>(adjH.rows());
245 assignBlock(adjG, 0, 0, &adj);
246 assignBlock(adjH, d1, d1, &adj);
250template <
typename G,
typename H>
252 const TangentVector& xi) {
253 const size_t d =
static_cast<size_t>(xi.size());
254 size_t d1 = 0, d2 = 0;
255 if constexpr (firstDynamic && secondDynamic) {
262 throw std::invalid_argument(
263 "ProductLieGroup::adjointMap cannot infer the tangent split when "
264 "both factors are dynamic");
265 }
else if constexpr (firstDynamic) {
267 throw std::invalid_argument(
268 "ProductLieGroup::adjointMap tangent dimension is too small for "
269 "the fixed second factor");
271 d1 =
static_cast<size_t>(xi.size() - m);
272 d2 =
static_cast<size_t>(m);
273 }
else if constexpr (secondDynamic) {
275 throw std::invalid_argument(
276 "ProductLieGroup::adjointMap tangent dimension is too small for "
277 "the fixed first factor");
279 d1 =
static_cast<size_t>(
n);
280 d2 =
static_cast<size_t>(xi.size() -
n);
282 d1 =
static_cast<size_t>(
n);
283 d2 =
static_cast<size_t>(m);
286 throw std::invalid_argument(
287 "ProductLieGroup::adjointMap tangent dimension does not match "
288 "product dimension");
300template <
typename G,
typename H>
310template <
typename G,
typename H>
311template <
typename T,
int ComponentDimension>
313 const TangentVector& v,
size_t start,
size_t d) {
314 const int startIndex =
static_cast<int>(start);
315 const int runtimeIndex =
static_cast<int>(d);
316 if constexpr (ComponentDimension == Eigen::Dynamic) {
317 return v.segment(startIndex, runtimeIndex);
319 static_cast<void>(d);
320 return v.template segment<ComponentDimension>(startIndex);
324template <
typename G,
typename H>
331 return ComponentJacobian::Zero(xi.size(), xi.size());
333 return ComponentJacobian::Zero();
336 return T::adjointMap(xi);
340template <
typename G,
typename H>
341typename ProductLieGroup<G, H>::TangentVector
345 const int firstIndex =
static_cast<int>(d1);
346 const int secondIndex =
static_cast<int>(d2);
347 if constexpr (dimension == Eigen::Dynamic) {
348 TangentVector v(d1 + d2);
349 v.segment(0, firstIndex) = v1;
350 v.segment(firstIndex, secondIndex) = v2;
353 static_cast<void>(d1);
354 static_cast<void>(d2);
361template <
typename G,
typename H>
364 if constexpr (dimension == Eigen::Dynamic) {
365 return Jacobian::Zero(d, d);
367 static_cast<void>(d);
368 return Jacobian::Zero();
372template <
typename G,
typename H>
375 if (firstDim() != other.firstDim() || secondDim() != other.secondDim()) {
376 throw std::invalid_argument(std::string(
"ProductLieGroup::") + operation +
377 " requires matching component dimensions");
381template <
typename G,
typename H>
382void ProductLieGroup<G, H>::print(
const std::string& s)
const {
383 std::cout << s <<
"ProductLieGroup" << std::endl;
388template <
typename G,
int N,
typename Derived>
390 const TangentVector& v,
size_t count,
const char* operation) {
391 if constexpr (isDynamic) {
393 throw std::invalid_argument(
394 std::string(
"PowerLieGroup::") + operation +
395 " tangent dimension does not match group dimension");
398 static_cast<void>(v);
399 static_cast<void>(count);
400 static_cast<void>(operation);
404template <
typename G,
int N,
typename Derived>
406 const Derived& other,
const char* operation)
const {
407 if constexpr (isDynamic) {
408 if (
derived().size() != other.size()) {
409 throw std::invalid_argument(std::string(
"PowerLieGroup::") + operation +
410 " requires matching component counts");
413 static_cast<void>(other);
414 static_cast<void>(operation);
418template <
typename G,
int N,
typename Derived>
422 if constexpr (isDynamic) {
423 return v.segment(
offset(i), n);
425 return v.template segment<n>(i * n);
429template <
typename G,
int N,
typename Derived>
431 if constexpr (isDynamic) {
432 return Derived(count);
434 static_cast<void>(count);
439template <
typename G,
int N,
typename Derived>
440typename PowerLieGroupBase<G, N, Derived>::JacobianStorage
442 if constexpr (isDynamic) {
443 return JacobianStorage(count);
445 static_cast<void>(count);
446 return JacobianStorage();
450template <
typename G,
int N,
typename Derived>
453 if constexpr (isDynamic) {
454 v.segment(
offset(i), n) = vi;
456 v.template segment<n>(i * n) = vi;
460template <
typename G,
int N,
typename Derived>
461template <
typename MatrixType>
463 MatrixType& H,
size_t i,
const BaseJacobian& block) {
464 if constexpr (isDynamic) {
467 H.template block<n, n>(i * n, i * n) = block;
471template <
typename G,
int N,
typename Derived>
473 ChartJacobian H,
const JacobianStorage& jacobians,
size_t count) {
476 for (
size_t i = 0; i < count; ++i) {
481template <
typename G,
int N,
typename Derived>
483 const Derived& other)
const {
492template <
typename G,
int N,
typename Derived>
501template <
typename G,
int N,
typename Derived>
504 ChartJacobian H2)
const {
510 for (
size_t i = 0; i < count; ++i) {
512 H1 ? &firstJacobians[i] :
nullptr,
513 H2 ? &secondJacobians[i] :
nullptr);
520template <
typename G,
int N,
typename Derived>
521typename PowerLieGroupBase<G, N, Derived>::TangentVector
524 ChartJacobian H2)
const {
530 for (
size_t i = 0; i < count; ++i) {
534 H2 ? &secondJacobians[i] :
nullptr));
541template <
typename G,
int N,
typename Derived>
545 if constexpr (isDynamic) {
546 if (v.size() % n != 0) {
547 throw std::invalid_argument(
548 "PowerLieGroup::Expmap tangent dimension must be divisible by base "
551 count =
static_cast<size_t>(v.size() /
static_cast<Eigen::Index
>(n));
557 for (
size_t i = 0; i < count; ++i) {
565template <
typename G,
int N,
typename Derived>
566typename PowerLieGroupBase<G, N, Derived>::TangentVector
568 const size_t count = isDynamic ? p.size() : N;
571 for (
size_t i = 0; i < count; ++i) {
579template <
typename G,
int N,
typename Derived>
580typename PowerLieGroupBase<G, N, Derived>::Jacobian
589template <
typename G,
int N,
typename Derived>
591 std::cout << s <<
"PowerLieGroup" << std::endl;
597template <
typename G,
int N,
typename Derived>
600 if constexpr (isDynamic) {
601 if (
derived().size() != other.size()) {
613template <
typename G,
int N,
typename Derived>
614typename PowerLieGroupBase<G, N, Derived>::TangentVector
616 if constexpr (isDynamic) {
619 static_cast<void>(count);
620 return TangentVector::Zero();
624template <
typename G,
int N,
typename Derived>
625typename PowerLieGroupBase<G, N, Derived>::Jacobian
627 if constexpr (isDynamic) {
630 static_cast<void>(count);
631 return Jacobian::Zero();
635template <
typename G,
int N>
637 if (elements.size() != N) {
638 throw std::invalid_argument(
639 "PowerLieGroup: initializer list size must equal N");
641 std::copy(elements.begin(), elements.end(), this->begin());
Global functions in a separate testing namespace.
Definition chartTesting.h:28
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
OptionalJacobian is an Eigen::Ref like class that can take be constructed using either a fixed size o...
Definition OptionalJacobian.h:40
Detects vector-space Lie groups (Eigen column vectors, group law = addition).
Definition ProductLieGroup.h:48
ProductLieGroup retract(const TangentVector &v, ChartJacobian H1={}, ChartJacobian H2={}) const
Retract to manifold.
Definition ProductLieGroup-inl.h:63
void checkMatchingDimensions(const ProductLieGroup &other, const char *operation) const
Check that another product has matching runtime dimensions.
Definition ProductLieGroup-inl.h:373
static traits< T >::TangentVector tangentSegment(const TangentVector &v, size_t start, size_t d)
Extract a tangent segment for one factor.
Definition ProductLieGroup-inl.h:312
ProductLieGroup inverse() const
Group inverse.
Definition ProductLieGroup-inl.h:57
Jacobian AdjointMap() const
Adjoint map.
Definition ProductLieGroup-inl.h:236
static T defaultIdentity()
Return default identity for fixed-size factors and a placeholder for dynamic ones.
Definition ProductLieGroup-inl.h:302
static Jacobian zeroJacobian(size_t d)
Create a zero Jacobian with the requested runtime size.
Definition ProductLieGroup-inl.h:362
static ProductLieGroup Expmap(const TangentVector &v, ChartJacobian Hv={})
Exponential map.
Definition ProductLieGroup-inl.h:130
static traits< T >::Jacobian componentAdjointMap(const typename traits< T >::TangentVector &xi)
Compute one factor's static algebra adjoint, including vector spaces.
Definition ProductLieGroup-inl.h:326
static constexpr int n
Dimensions of the two subgroups.
Definition ProductLieGroup.h:84
static TangentVector Logmap(const ProductLieGroup &p, ChartJacobian Hp={})
Logarithmic map.
Definition ProductLieGroup-inl.h:212
ProductLieGroup()
Default constructor yields identity.
Definition ProductLieGroup.h:138
static Jacobian adjointMap(const TangentVector &xi)
Static Lie-algebra adjoint ad_xi.
Definition ProductLieGroup-inl.h:251
static TangentVector makeTangentVector(const typename traits< G >::TangentVector &v1, const typename traits< H >::TangentVector &v2, size_t d1, size_t d2)
Concatenate subgroup tangent vectors into the product tangent.
Definition ProductLieGroup-inl.h:342
ProductLieGroup operator*(const ProductLieGroup &other) const
Group multiplication.
Definition ProductLieGroup-inl.h:49
TangentVector localCoordinates(const ProductLieGroup &g, ChartJacobian H1={}, ChartJacobian H2={}) const
Local coordinates on manifold.
Definition ProductLieGroup-inl.h:99
static Derived makeResult(size_t count)
Create a result object with the requested component count.
Definition ProductLieGroup-inl.h:430
Derived operator*(const Derived &other) const
Group multiplication.
Definition ProductLieGroup-inl.h:482
static Jacobian zeroJacobian(size_t count)
Create a zero Jacobian with the requested runtime size.
Definition ProductLieGroup-inl.h:626
static void assignJacobianBlock(MatrixType &H, size_t i, const BaseJacobian &block)
Write one component block into a block-diagonal Jacobian.
Definition ProductLieGroup-inl.h:462
static TangentVector Logmap(const Derived &p, ChartJacobian Hp={})
Logarithmic map.
Definition ProductLieGroup-inl.h:567
static TangentVector zeroTangent(size_t count)
Create a zero tangent with the requested runtime size.
Definition ProductLieGroup-inl.h:615
static void assignTangentSegment(TangentVector &v, size_t i, const typename traits< G >::TangentVector &vi)
Write one component tangent into the concatenated tangent.
Definition ProductLieGroup-inl.h:451
Derived retract(const TangentVector &v, ChartJacobian H1={}, ChartJacobian H2={}) const
Retract to manifold.
Definition ProductLieGroup-inl.h:502
static void fillJacobianBlocks(ChartJacobian H, const JacobianStorage &jacobians, size_t count)
Assemble a block-diagonal Jacobian from per-component blocks.
Definition ProductLieGroup-inl.h:472
bool equals(const Derived &other, double tol=1e-9) const
Equality with tolerance.
Definition ProductLieGroup-inl.h:598
Derived inverse() const
Group inverse.
Definition ProductLieGroup-inl.h:493
const Derived & derived() const
Downcast to the derived storage type.
Definition ProductLieGroup.h:337
static Derived Expmap(const TangentVector &v, ChartJacobian Hv={})
Exponential map.
Definition ProductLieGroup-inl.h:542
size_t componentCount() const
Runtime component count.
Definition ProductLieGroup.h:353
static traits< G >::TangentVector tangentSegment(const TangentVector &v, size_t i)
Extract one component tangent from the concatenated tangent.
Definition ProductLieGroup-inl.h:420
Jacobian AdjointMap() const
Adjoint map.
Definition ProductLieGroup-inl.h:581
static void checkDynamicTangentSize(const TangentVector &v, size_t count, const char *operation)
Validate tangent size for dynamic-count groups.
Definition ProductLieGroup-inl.h:389
void print(const std::string &s="") const
Print for debugging.
Definition ProductLieGroup-inl.h:590
void checkMatchingCounts(const Derived &other, const char *operation) const
Validate matching component counts for binary operations.
Definition ProductLieGroup-inl.h:405
static size_t totalDimension(size_t count)
Total tangent dimension for a given component count.
Definition ProductLieGroup.h:343
TangentVector localCoordinates(const Derived &g, ChartJacobian H1={}, ChartJacobian H2={}) const
Local coordinates on manifold.
Definition ProductLieGroup-inl.h:522
static Eigen::Index offset(size_t i)
Definition ProductLieGroup.h:348
static JacobianStorage makeJacobianStorage(size_t count)
Create per-component Jacobian storage.
Definition ProductLieGroup-inl.h:441
PowerLieGroup()
Default constructor yields identity.
Definition ProductLieGroup.h:475