gtsam
Loading...
Searching...
No Matches
ProductLieGroup-inl.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7
8 * See LICENSE for the license information
9
10 * -------------------------------------------------------------------------- */
11
20
21#pragma once
22
23namespace {
24
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;
39 } else {
40 destination->block(row, column, source.rows(), source.cols()) = source;
41 }
42}
43
44} // namespace
45
46namespace gtsam {
47
48template <typename G, typename H>
50 const ProductLieGroup& other) const {
51 checkMatchingDimensions(other, "operator*");
52 return ProductLieGroup(traits<G>::Compose(this->first, other.first),
53 traits<H>::Compose(this->second, other.second));
54}
55
56template <typename G, typename H>
61
62template <typename G, typename H>
64 ChartJacobian H1,
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 "
72 "dimension");
73 }
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);
78 G g =
79 traits<G>::Retract(this->first, tangentSegment<G>(v, 0, d1),
80 H1 ? &D_g_first : nullptr, H2 ? &D_g_second : nullptr);
81 H h =
82 traits<H>::Retract(this->second, tangentSegment<H>(v, d1, d2),
83 H1 ? &D_h_first : nullptr, H2 ? &D_h_second : nullptr);
84 if (H1) {
85 *H1 = zeroJacobian(d);
86 assignBlock(D_g_first, 0, 0, &*H1);
87 assignBlock(D_h_first, d1, d1, &*H1);
88 }
89 if (H2) {
90 *H2 = zeroJacobian(d);
91 assignBlock(D_g_second, 0, 0, &*H2);
92 assignBlock(D_h_second, d1, d1, &*H2);
93 }
94 return ProductLieGroup(g, h);
95}
96
97template <typename G, typename H>
98typename ProductLieGroup<G, H>::TangentVector
100 ChartJacobian H1,
101 ChartJacobian H2) const {
102 checkMatchingDimensions(g, "localCoordinates");
103 const size_t d1 = firstDim();
104 const size_t d2 = secondDim();
105 const size_t d = d1 + d2;
106 Jacobian1 D_g_first;
107 Jacobian1 D_g_second;
108 Jacobian2 D_h_first;
109 Jacobian2 D_h_second;
110 const auto v1 =
111 traits<G>::Local(this->first, g.first, H1 ? &D_g_first : nullptr,
112 H2 ? &D_g_second : nullptr);
113 const auto v2 =
114 traits<H>::Local(this->second, g.second, H1 ? &D_h_first : nullptr,
115 H2 ? &D_h_second : nullptr);
116 if (H1) {
117 *H1 = zeroJacobian(d);
118 assignBlock(D_g_first, 0, 0, &*H1);
119 assignBlock(D_h_first, d1, d1, &*H1);
120 }
121 if (H2) {
122 *H2 = zeroJacobian(d);
123 assignBlock(D_g_second, 0, 0, &*H2);
124 assignBlock(D_h_second, d1, d1, &*H2);
125 }
126 return makeTangentVector(v1, v2, d1, d2);
127}
128
129template <typename G, typename H>
131 ChartJacobian Hv) {
132 size_t d1 = 0;
133 size_t d2 = 0;
134 if constexpr (firstDynamic && secondDynamic) {
135 if (v.size() == 0) {
136 if (Hv) *Hv = Matrix::Zero(0, 0);
137 return ProductLieGroup();
138 }
139 throw std::invalid_argument(
140 "ProductLieGroup::Expmap requires split tangent vectors when both "
141 "factors are dynamic");
142 } else if constexpr (firstDynamic) {
143 if (v.size() < m) {
144 throw std::invalid_argument(
145 "ProductLieGroup::Expmap tangent dimension is too small for the "
146 "fixed second factor");
147 }
148 d1 = static_cast<size_t>(v.size() - m);
149 d2 = static_cast<size_t>(m);
150 } else if constexpr (secondDynamic) {
151 if (v.size() < n) {
152 throw std::invalid_argument(
153 "ProductLieGroup::Expmap tangent dimension is too small for the "
154 "fixed first factor");
155 }
156 d1 = static_cast<size_t>(n);
157 d2 = static_cast<size_t>(v.size() - n);
158 } else {
159 d1 = static_cast<size_t>(n);
160 d2 = static_cast<size_t>(m);
161 }
162 if (static_cast<size_t>(v.size()) != d1 + d2) {
163 throw std::invalid_argument(
164 "ProductLieGroup::Expmap tangent dimension does not match product "
165 "dimension");
166 }
167
168 Matrix D_g_first;
169 Matrix D_h_second;
170 const auto v1 = tangentSegment<G>(v, 0, d1);
171 const auto v2 = tangentSegment<H>(v, d1, d2);
172 ProductLieGroup result =
173 Expmap(v1, v2,
178 if (Hv) {
179 const size_t d = d1 + d2;
180 *Hv = zeroJacobian(d);
181 Hv->block(0, 0, d, d1) = D_g_first;
182 Hv->block(0, d1, d, d2) = D_h_second;
183 }
184 return result;
185}
186
187template <typename G, typename H>
189 const Eigen::Ref<const typename traits<G>::TangentVector>& v1,
190 const Eigen::Ref<const typename traits<H>::TangentVector>& v2,
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;
196 Jacobian1 D_g_first;
197 Jacobian2 D_h_second;
198 G g = traits<G>::Expmap(v1, H1 ? &D_g_first : nullptr);
199 H h = traits<H>::Expmap(v2, H2 ? &D_h_second : nullptr);
200 if (H1) {
201 *H1 = Matrix::Zero(d, d1);
202 assignBlock(D_g_first, 0, 0, &*H1);
203 }
204 if (H2) {
205 *H2 = Matrix::Zero(d, d2);
206 assignBlock(D_h_second, d1, 0, &*H2);
207 }
208 return ProductLieGroup(g, h);
209}
210
211template <typename G, typename H>
212typename ProductLieGroup<G, H>::TangentVector ProductLieGroup<G, H>::Logmap(
213 const ProductLieGroup& p, ChartJacobian Hp) {
214 const size_t d1 = p.firstDim();
215 const size_t d2 = p.secondDim();
216 const size_t d = d1 + d2;
217 if (!Hp) {
218 const auto v1 = traits<G>::Logmap(p.first);
219 const auto v2 = traits<H>::Logmap(p.second);
220 return makeTangentVector(v1, v2, d1, d2);
221 }
222
223 Jacobian1 D_g_first;
224 Jacobian2 D_h_second;
225 typename traits<G>::TangentVector v1 = traits<G>::Logmap(p.first, &D_g_first);
226 typename traits<H>::TangentVector v2 =
227 traits<H>::Logmap(p.second, &D_h_second);
228 TangentVector v = makeTangentVector(v1, v2, d1, d2);
229 *Hp = zeroJacobian(d);
230 assignBlock(D_g_first, 0, 0, &*Hp);
231 assignBlock(D_h_second, d1, d1, &*Hp);
232 return v;
233}
234
235template <typename G, typename H>
236typename ProductLieGroup<G, H>::Jacobian ProductLieGroup<G, H>::AdjointMap()
237 const {
238 // The two algebras are independent:
239 // Ad_(g,h) = diag(Ad_G(g), Ad_H(h)).
240 const auto adjG = traits<G>::AdjointMap(this->first);
241 const auto adjH = traits<H>::AdjointMap(this->second);
242 const size_t d1 = static_cast<size_t>(adjG.rows());
243 const size_t d2 = static_cast<size_t>(adjH.rows());
244 Jacobian adj = zeroJacobian(d1 + d2);
245 assignBlock(adjG, 0, 0, &adj);
246 assignBlock(adjH, d1, d1, &adj);
247 return adj;
248}
249
250template <typename G, typename H>
251typename ProductLieGroup<G, H>::Jacobian ProductLieGroup<G, H>::adjointMap(
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) {
258 // Both factors are abelian, so the result is zero regardless of where
259 // the concatenated tangent is split.
260 return zeroJacobian(d);
261 }
262 throw std::invalid_argument(
263 "ProductLieGroup::adjointMap cannot infer the tangent split when "
264 "both factors are dynamic");
265 } else if constexpr (firstDynamic) {
266 if (xi.size() < m) {
267 throw std::invalid_argument(
268 "ProductLieGroup::adjointMap tangent dimension is too small for "
269 "the fixed second factor");
270 }
271 d1 = static_cast<size_t>(xi.size() - m);
272 d2 = static_cast<size_t>(m);
273 } else if constexpr (secondDynamic) {
274 if (xi.size() < n) {
275 throw std::invalid_argument(
276 "ProductLieGroup::adjointMap tangent dimension is too small for "
277 "the fixed first factor");
278 }
279 d1 = static_cast<size_t>(n);
280 d2 = static_cast<size_t>(xi.size() - n);
281 } else {
282 d1 = static_cast<size_t>(n);
283 d2 = static_cast<size_t>(m);
284 }
285 if (d != d1 + d2) {
286 throw std::invalid_argument(
287 "ProductLieGroup::adjointMap tangent dimension does not match "
288 "product dimension");
289 }
290
291 const auto a = tangentSegment<G>(xi, 0, d1);
292 const auto b = tangentSegment<H>(xi, d1, d2);
293
294 Jacobian ad = zeroJacobian(d);
295 assignBlock(componentAdjointMap<G>(a), 0, 0, &ad);
296 assignBlock(componentAdjointMap<H>(b), d1, d1, &ad);
297 return ad;
298}
299
300template <typename G, typename H>
301template <typename T>
303 if constexpr (traits<T>::dimension == Eigen::Dynamic) {
304 return T();
305 } else {
306 return traits<T>::Identity();
307 }
308}
309
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);
318 } else {
319 static_cast<void>(d);
320 return v.template segment<ComponentDimension>(startIndex);
321 }
322}
323
324template <typename G, typename H>
325template <typename T>
327 const typename traits<T>::TangentVector& xi) {
328 using ComponentJacobian = typename traits<T>::Jacobian;
330 if constexpr (traits<T>::dimension == Eigen::Dynamic) {
331 return ComponentJacobian::Zero(xi.size(), xi.size());
332 } else {
333 return ComponentJacobian::Zero();
334 }
335 } else {
336 return T::adjointMap(xi);
337 }
338}
339
340template <typename G, typename H>
341typename ProductLieGroup<G, H>::TangentVector
343 const typename traits<G>::TangentVector& v1,
344 const typename traits<H>::TangentVector& v2, size_t d1, size_t d2) {
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;
351 return v;
352 } else {
353 static_cast<void>(d1);
354 static_cast<void>(d2);
355 TangentVector v;
356 v << v1, v2;
357 return v;
358 }
359}
360
361template <typename G, typename H>
362typename ProductLieGroup<G, H>::Jacobian ProductLieGroup<G, H>::zeroJacobian(
363 size_t d) {
364 if constexpr (dimension == Eigen::Dynamic) {
365 return Jacobian::Zero(d, d);
366 } else {
367 static_cast<void>(d);
368 return Jacobian::Zero();
370}
371
372template <typename G, typename H>
374 const ProductLieGroup& other, const char* operation) const {
375 if (firstDim() != other.firstDim() || secondDim() != other.secondDim()) {
376 throw std::invalid_argument(std::string("ProductLieGroup::") + operation +
377 " requires matching component dimensions");
378 }
380
381template <typename G, typename H>
382void ProductLieGroup<G, H>::print(const std::string& s) const {
383 std::cout << s << "ProductLieGroup" << std::endl;
384 traits<G>::Print(this->first, " first");
385 traits<H>::Print(this->second, " second");
386}
387
388template <typename G, int N, typename Derived>
390 const TangentVector& v, size_t count, const char* operation) {
391 if constexpr (isDynamic) {
392 if (static_cast<size_t>(v.size()) != totalDimension(count)) {
393 throw std::invalid_argument(
394 std::string("PowerLieGroup::") + operation +
395 " tangent dimension does not match group dimension");
396 }
397 } else {
398 static_cast<void>(v);
399 static_cast<void>(count);
400 static_cast<void>(operation);
401 }
402}
403
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");
411 }
412 } else {
413 static_cast<void>(other);
414 static_cast<void>(operation);
415 }
416}
418template <typename G, int N, typename Derived>
421 size_t i) {
422 if constexpr (isDynamic) {
423 return v.segment(offset(i), n);
424 } else {
425 return v.template segment<n>(i * n);
426 }
427}
428
429template <typename G, int N, typename Derived>
431 if constexpr (isDynamic) {
432 return Derived(count);
433 } else {
434 static_cast<void>(count);
435 return Derived();
436 }
437}
438
439template <typename G, int N, typename Derived>
440typename PowerLieGroupBase<G, N, Derived>::JacobianStorage
442 if constexpr (isDynamic) {
443 return JacobianStorage(count);
444 } else {
445 static_cast<void>(count);
446 return JacobianStorage();
447 }
448}
449
450template <typename G, int N, typename Derived>
452 TangentVector& v, size_t i, const typename traits<G>::TangentVector& vi) {
453 if constexpr (isDynamic) {
454 v.segment(offset(i), n) = vi;
455 } else {
456 v.template segment<n>(i * n) = vi;
457 }
458}
459
460template <typename G, int N, typename Derived>
461template <typename MatrixType>
463 MatrixType& H, size_t i, const BaseJacobian& block) {
464 if constexpr (isDynamic) {
465 H.block(offset(i), offset(i), n, n) = block;
466 } else {
467 H.template block<n, n>(i * n, i * n) = block;
468 }
469}
470
471template <typename G, int N, typename Derived>
473 ChartJacobian H, const JacobianStorage& jacobians, size_t count) {
474 if (!H) return;
475 *H = zeroJacobian(count);
476 for (size_t i = 0; i < count; ++i) {
477 assignJacobianBlock(*H, i, jacobians[i]);
478 }
479}
480
481template <typename G, int N, typename Derived>
483 const Derived& other) const {
484 checkMatchingCounts(other, "operator*");
485 Derived result = makeResult(componentCount());
486 for (size_t i = 0; i < componentCount(); ++i) {
487 result[i] = traits<G>::Compose(derived()[i], other[i]);
488 }
489 return result;
490}
491
492template <typename G, int N, typename Derived>
494 Derived result = makeResult(componentCount());
495 for (size_t i = 0; i < componentCount(); ++i) {
496 result[i] = traits<G>::Inverse(derived()[i]);
497 }
498 return result;
499}
500
501template <typename G, int N, typename Derived>
502Derived PowerLieGroupBase<G, N, Derived>::retract(const TangentVector& v,
503 ChartJacobian H1,
504 ChartJacobian H2) const {
505 const size_t count = componentCount();
506 checkDynamicTangentSize(v, count, "retract");
507 JacobianStorage firstJacobians = makeJacobianStorage(count);
508 JacobianStorage secondJacobians = makeJacobianStorage(count);
509 Derived result = makeResult(count);
510 for (size_t i = 0; i < count; ++i) {
511 result[i] = traits<G>::Retract(derived()[i], tangentSegment(v, i),
512 H1 ? &firstJacobians[i] : nullptr,
513 H2 ? &secondJacobians[i] : nullptr);
514 }
515 fillJacobianBlocks(H1, firstJacobians, count);
516 fillJacobianBlocks(H2, secondJacobians, count);
517 return result;
518}
519
520template <typename G, int N, typename Derived>
521typename PowerLieGroupBase<G, N, Derived>::TangentVector
523 ChartJacobian H1,
524 ChartJacobian H2) const {
525 checkMatchingCounts(g, "localCoordinates");
526 const size_t count = componentCount();
527 JacobianStorage firstJacobians = makeJacobianStorage(count);
528 JacobianStorage secondJacobians = makeJacobianStorage(count);
529 TangentVector v = zeroTangent(componentCount());
530 for (size_t i = 0; i < count; ++i) {
532 v, i,
533 traits<G>::Local(derived()[i], g[i], H1 ? &firstJacobians[i] : nullptr,
534 H2 ? &secondJacobians[i] : nullptr));
535 }
536 fillJacobianBlocks(H1, firstJacobians, count);
537 fillJacobianBlocks(H2, secondJacobians, count);
538 return v;
539}
540
541template <typename G, int N, typename Derived>
542Derived PowerLieGroupBase<G, N, Derived>::Expmap(const TangentVector& v,
543 ChartJacobian Hv) {
544 size_t count = 0;
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 "
549 "group dimension");
550 }
551 count = static_cast<size_t>(v.size() / static_cast<Eigen::Index>(n));
552 } else {
553 count = N;
554 }
555 JacobianStorage jacobians = makeJacobianStorage(count);
556 Derived result = makeResult(count);
557 for (size_t i = 0; i < count; ++i) {
558 result[i] =
559 traits<G>::Expmap(tangentSegment(v, i), Hv ? &jacobians[i] : nullptr);
560 }
561 fillJacobianBlocks(Hv, jacobians, count);
562 return result;
563}
564
565template <typename G, int N, typename Derived>
566typename PowerLieGroupBase<G, N, Derived>::TangentVector
567PowerLieGroupBase<G, N, Derived>::Logmap(const Derived& p, ChartJacobian Hp) {
568 const size_t count = isDynamic ? p.size() : N;
569 TangentVector v = zeroTangent(count);
570 JacobianStorage jacobians = makeJacobianStorage(count);
571 for (size_t i = 0; i < count; ++i) {
573 traits<G>::Logmap(p[i], Hp ? &jacobians[i] : nullptr));
574 }
575 fillJacobianBlocks(Hp, jacobians, count);
576 return v;
577}
578
579template <typename G, int N, typename Derived>
580typename PowerLieGroupBase<G, N, Derived>::Jacobian
582 Jacobian adj = zeroJacobian(componentCount());
583 for (size_t i = 0; i < componentCount(); ++i) {
585 }
586 return adj;
587}
588
589template <typename G, int N, typename Derived>
590void PowerLieGroupBase<G, N, Derived>::print(const std::string& s) const {
591 std::cout << s << "PowerLieGroup" << std::endl;
592 for (size_t i = 0; i < componentCount(); ++i) {
593 traits<G>::Print(derived()[i], " component[" + std::to_string(i) + "]");
594 }
595}
596
597template <typename G, int N, typename Derived>
599 double tol) const {
600 if constexpr (isDynamic) {
601 if (derived().size() != other.size()) {
602 return false;
603 }
604 }
605 for (size_t i = 0; i < componentCount(); ++i) {
606 if (!traits<G>::Equals(derived()[i], other[i], tol)) {
607 return false;
608 }
609 }
610 return true;
611}
612
613template <typename G, int N, typename Derived>
614typename PowerLieGroupBase<G, N, Derived>::TangentVector
616 if constexpr (isDynamic) {
617 return TangentVector::Zero(totalDimension(count));
618 } else {
619 static_cast<void>(count);
620 return TangentVector::Zero();
621 }
622}
623
624template <typename G, int N, typename Derived>
625typename PowerLieGroupBase<G, N, Derived>::Jacobian
627 if constexpr (isDynamic) {
628 return Jacobian::Zero(totalDimension(count), totalDimension(count));
629 } else {
630 static_cast<void>(count);
631 return Jacobian::Zero();
632 }
633}
634
635template <typename G, int N>
636PowerLieGroup<G, N>::PowerLieGroup(const std::initializer_list<G>& elements) {
637 if (elements.size() != N) {
638 throw std::invalid_argument(
639 "PowerLieGroup: initializer list size must equal N");
640 }
641 std::copy(elements.begin(), elements.end(), this->begin());
642}
643
644} // namespace gtsam
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