/* ---------------------------------------------------------------------------- * 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 testLie.cpp * @date May, 2015 * @author Frank Dellaert * @brief unit tests for Lie group type machinery */ #include #include namespace gtsam { /// Template to construct the product Lie group of two other Lie groups, G and H /// Assumes manifold structure from G and H, and binary constructor template class ProductLieGroup: public std::pair, public LieGroup< ProductLieGroup, traits::dimension + traits::dimension> { BOOST_CONCEPT_ASSERT((IsLieGroup)); BOOST_CONCEPT_ASSERT((IsLieGroup)); typedef std::pair Base; protected: enum {dimension1 = traits::dimension}; enum {dimension2 = traits::dimension}; public: /// Default constructor yields identity ProductLieGroup():Base(traits::Identity(),traits::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::Compose(this->first,other.first), traits::Compose(this->second,other.second)); } ProductLieGroup inverse() const { return ProductLieGroup(this->first.inverse(), this->second.inverse()); } /// @} /// @name Manifold (but with derivatives) /// @{ enum {dimension = dimension1 + dimension2}; inline static size_t Dim() {return dimension;} inline size_t dim() const {return dimension;} typedef Eigen::Matrix TangentVector; typedef OptionalJacobian ChartJacobian; /// @} /// @name Lie Group /// @{ Eigen::Matrix AdjointMap() const { Eigen::Matrix A; A.setIdentity(); throw std::runtime_error("ProductLieGroup::derivatives not implemented yet"); // A.template topLeftCorner() = this->first.AdjointMap(); // A.template bottomRightCorner() = this->second.AdjointMap(); return A; } static ProductLieGroup Expmap(const TangentVector& v, ChartJacobian Hv = boost::none) { if (Hv) throw std::runtime_error("ProductLieGroup::derivatives not implemented yet"); G g = traits::Expmap(v.template head()); H h = traits::Expmap(v.template tail()); return ProductLieGroup(g,h); } static TangentVector Logmap(const ProductLieGroup& p, ChartJacobian Hp = boost::none) { if (Hp) throw std::runtime_error("ProductLieGroup::derivatives not implemented yet"); typename traits::TangentVector v1 = traits::Logmap(p.first); typename traits::TangentVector v2 = traits::Logmap(p.second); TangentVector v; v << v1, v2; return v; } struct ChartAtOrigin { static TangentVector Local(const ProductLieGroup& m, ChartJacobian Hm = boost::none) { return Logmap(m, Hm); } static ProductLieGroup Retract(const TangentVector& v, ChartJacobian Hv = boost::none) { return Expmap(v, Hv); } }; using LieGroup::inverse; // with derivative /// @} }; // Define any direct product group to be a model of the multiplicative Group concept template struct traits > : internal::LieGroupTraits< ProductLieGroup > { }; } #include #include #undef CHECK #include using namespace std; using namespace gtsam; //****************************************************************************** typedef ProductLieGroup MyPoint2Pair; // Define any direct product group to be a model of the multiplicative Group concept namespace gtsam { template<> struct traits : internal::LieGroupTraits { static void Print(const MyPoint2Pair& m, const string& s = "") { cout << s << "(" << m.first << "," << m.second << ")" << endl; } static bool Equals(const MyPoint2Pair& m1, const MyPoint2Pair& m2, double tol = 1e-8) { return m1 == m2; } }; } TEST(Lie, ProductLieGroup) { BOOST_CONCEPT_ASSERT((IsGroup)); BOOST_CONCEPT_ASSERT((IsManifold)); BOOST_CONCEPT_ASSERT((IsLieGroup)); MyPoint2Pair pair1; Vector4 d; d << 1, 2, 3, 4; MyPoint2Pair expected(Point2(1, 2), Point2(3, 4)); MyPoint2Pair pair2 = pair1.retract(d); EXPECT(assert_equal(expected, pair2, 1e-9)); EXPECT(assert_equal(d, pair1.localCoordinates(pair2), 1e-9)); } //****************************************************************************** int main() { TestResult tr; return TestRegistry::runAllTests(tr); } //******************************************************************************