183 lines
6.6 KiB
C++
183 lines
6.6 KiB
C++
/* ----------------------------------------------------------------------------
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
* Atlanta, Georgia 30332-0415
|
|
* All Rights Reserved
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
* See LICENSE for the license information
|
|
|
|
* -------------------------------1------------------------------------------- */
|
|
|
|
/**
|
|
* @file ProductLieGroup.h
|
|
* @date May, 2015
|
|
* @author Frank Dellaert
|
|
* @brief Group product of two Lie Groups
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <gtsam/base/Lie.h>
|
|
#include <utility> // pair
|
|
|
|
namespace gtsam {
|
|
|
|
/// Template to construct the product Lie group of two other Lie groups
|
|
/// Assumes Lie group structure for G and H
|
|
template<typename G, typename H>
|
|
class ProductLieGroup: public std::pair<G, H> {
|
|
BOOST_CONCEPT_ASSERT((IsLieGroup<G>));
|
|
BOOST_CONCEPT_ASSERT((IsLieGroup<H>));
|
|
typedef std::pair<G, H> Base;
|
|
|
|
protected:
|
|
enum {dimension1 = traits<G>::dimension};
|
|
enum {dimension2 = traits<H>::dimension};
|
|
|
|
public:
|
|
/// Default constructor yields identity
|
|
ProductLieGroup():Base(traits<G>::Identity(),traits<H>::Identity()) {}
|
|
|
|
// Construct from two subgroup elements
|
|
ProductLieGroup(const G& g, const H& h):Base(g,h) {}
|
|
|
|
// Construct from base
|
|
ProductLieGroup(const Base& base):Base(base) {}
|
|
|
|
/// @name Group
|
|
/// @{
|
|
typedef multiplicative_group_tag group_flavor;
|
|
static ProductLieGroup Identity() {return ProductLieGroup();}
|
|
|
|
ProductLieGroup operator*(const ProductLieGroup& other) const {
|
|
return ProductLieGroup(traits<G>::Compose(this->first,other.first),
|
|
traits<H>::Compose(this->second,other.second));
|
|
}
|
|
ProductLieGroup inverse() const {
|
|
return ProductLieGroup(traits<G>::Inverse(this->first), traits<H>::Inverse(this->second));
|
|
}
|
|
ProductLieGroup compose(const ProductLieGroup& g) const {
|
|
return (*this) * g;
|
|
}
|
|
ProductLieGroup between(const ProductLieGroup& g) const {
|
|
return this->inverse() * g;
|
|
}
|
|
/// @}
|
|
|
|
/// @name Manifold
|
|
/// @{
|
|
enum {dimension = dimension1 + dimension2};
|
|
inline static size_t Dim() {return dimension;}
|
|
inline size_t dim() const {return dimension;}
|
|
|
|
typedef Eigen::Matrix<double, dimension, 1> TangentVector;
|
|
typedef OptionalJacobian<dimension, dimension> ChartJacobian;
|
|
|
|
ProductLieGroup retract(const TangentVector& v, //
|
|
ChartJacobian H1 = boost::none, ChartJacobian H2 = boost::none) const {
|
|
if (H1||H2) throw std::runtime_error("ProductLieGroup::retract derivatives not implemented yet");
|
|
G g = traits<G>::Retract(this->first, v.template head<dimension1>());
|
|
H h = traits<H>::Retract(this->second, v.template tail<dimension2>());
|
|
return ProductLieGroup(g,h);
|
|
}
|
|
TangentVector localCoordinates(const ProductLieGroup& g, //
|
|
ChartJacobian H1 = boost::none, ChartJacobian H2 = boost::none) const {
|
|
if (H1||H2) throw std::runtime_error("ProductLieGroup::localCoordinates derivatives not implemented yet");
|
|
typename traits<G>::TangentVector v1 = traits<G>::Local(this->first, g.first);
|
|
typename traits<H>::TangentVector v2 = traits<H>::Local(this->second, g.second);
|
|
TangentVector v;
|
|
v << v1, v2;
|
|
return v;
|
|
}
|
|
/// @}
|
|
|
|
/// @name Lie Group
|
|
/// @{
|
|
protected:
|
|
typedef Eigen::Matrix<double, dimension, dimension> Jacobian;
|
|
typedef Eigen::Matrix<double, dimension1, dimension1> Jacobian1;
|
|
typedef Eigen::Matrix<double, dimension2, dimension2> Jacobian2;
|
|
|
|
public:
|
|
ProductLieGroup compose(const ProductLieGroup& other, ChartJacobian H1,
|
|
ChartJacobian H2 = boost::none) const {
|
|
Jacobian1 D_g_first; Jacobian2 D_h_second;
|
|
G g = traits<G>::Compose(this->first,other.first, H1 ? &D_g_first : 0);
|
|
H h = traits<H>::Compose(this->second,other.second, H1 ? &D_h_second : 0);
|
|
if (H1) {
|
|
H1->setZero();
|
|
H1->template topLeftCorner<dimension1,dimension1>() = D_g_first;
|
|
H1->template bottomRightCorner<dimension2,dimension2>() = D_h_second;
|
|
}
|
|
if (H2) *H2 = Jacobian::Identity();
|
|
return ProductLieGroup(g,h);
|
|
}
|
|
ProductLieGroup between(const ProductLieGroup& other, ChartJacobian H1,
|
|
ChartJacobian H2 = boost::none) const {
|
|
Jacobian1 D_g_first; Jacobian2 D_h_second;
|
|
G g = traits<G>::Between(this->first,other.first, H1 ? &D_g_first : 0);
|
|
H h = traits<H>::Between(this->second,other.second, H1 ? &D_h_second : 0);
|
|
if (H1) {
|
|
H1->setZero();
|
|
H1->template topLeftCorner<dimension1,dimension1>() = D_g_first;
|
|
H1->template bottomRightCorner<dimension2,dimension2>() = D_h_second;
|
|
}
|
|
if (H2) *H2 = Jacobian::Identity();
|
|
return ProductLieGroup(g,h);
|
|
}
|
|
ProductLieGroup inverse(ChartJacobian D) const {
|
|
Jacobian1 D_g_first; Jacobian2 D_h_second;
|
|
G g = traits<G>::Inverse(this->first, D ? &D_g_first : 0);
|
|
H h = traits<H>::Inverse(this->second, D ? &D_h_second : 0);
|
|
if (D) {
|
|
D->setZero();
|
|
D->template topLeftCorner<dimension1,dimension1>() = D_g_first;
|
|
D->template bottomRightCorner<dimension2,dimension2>() = D_h_second;
|
|
}
|
|
return ProductLieGroup(g,h);
|
|
}
|
|
static ProductLieGroup Expmap(const TangentVector& v, ChartJacobian Hv = boost::none) {
|
|
Jacobian1 D_g_first; Jacobian2 D_h_second;
|
|
G g = traits<G>::Expmap(v.template head<dimension1>(), Hv ? &D_g_first : 0);
|
|
H h = traits<H>::Expmap(v.template tail<dimension2>(), Hv ? &D_h_second : 0);
|
|
if (Hv) {
|
|
Hv->setZero();
|
|
Hv->template topLeftCorner<dimension1,dimension1>() = D_g_first;
|
|
Hv->template bottomRightCorner<dimension2,dimension2>() = D_h_second;
|
|
}
|
|
return ProductLieGroup(g,h);
|
|
}
|
|
static TangentVector Logmap(const ProductLieGroup& p, ChartJacobian Hp = boost::none) {
|
|
Jacobian1 D_g_first; Jacobian2 D_h_second;
|
|
typename traits<G>::TangentVector v1 = traits<G>::Logmap(p.first, Hp ? &D_g_first : 0);
|
|
typename traits<H>::TangentVector v2 = traits<H>::Logmap(p.second, Hp ? &D_h_second : 0);
|
|
TangentVector v;
|
|
v << v1, v2;
|
|
if (Hp) {
|
|
Hp->setZero();
|
|
Hp->template topLeftCorner<dimension1,dimension1>() = D_g_first;
|
|
Hp->template bottomRightCorner<dimension2,dimension2>() = D_h_second;
|
|
}
|
|
return v;
|
|
}
|
|
static TangentVector LocalCoordinates(const ProductLieGroup& p, ChartJacobian Hp = boost::none) {
|
|
return Logmap(p, Hp);
|
|
}
|
|
ProductLieGroup expmap(const TangentVector& v) const {
|
|
return compose(ProductLieGroup::Expmap(v));
|
|
}
|
|
TangentVector logmap(const ProductLieGroup& g) const {
|
|
return ProductLieGroup::Logmap(between(g));
|
|
}
|
|
/// @}
|
|
|
|
};
|
|
|
|
// Define any direct product group to be a model of the multiplicative Group concept
|
|
template<typename G, typename H>
|
|
struct traits<ProductLieGroup<G, H> > : internal::LieGroupTraits<ProductLieGroup<G, H> > {};
|
|
|
|
} // namespace gtsam
|
|
|