group::traits, and group::compose

release/4.3a0
dellaert 2014-12-06 11:37:14 +01:00
parent 07ef30039a
commit ddeb764912
2 changed files with 109 additions and 82 deletions

View File

@ -23,8 +23,9 @@ namespace traits {
* @brief Associate a unique tag with each of the main GTSAM concepts * @brief Associate a unique tag with each of the main GTSAM concepts
*/ */
//@{ //@{
template <class T> template<class T>
struct structure_category; // specializations should be derived from one of the following tags struct structure_category;
// specializations should be derived from one of the following tags
//@} //@}
/** /**
@ -32,97 +33,111 @@ struct structure_category; // specializations should be derived from one of the
* @brief Possible values for traits::structure_category<T>::type * @brief Possible values for traits::structure_category<T>::type
*/ */
//@{ //@{
struct manifold_tag {}; struct manifold_tag {
struct group_tag {}; };
struct lie_group_tag : public manifold_tag, public group_tag {}; struct group_tag {
struct vector_space_tag : public lie_group_tag {}; };
struct lie_group_tag: public manifold_tag, public group_tag {
};
struct vector_space_tag: public lie_group_tag {
};
//@} //@}
} // namespace traits }// namespace traits
namespace traits { namespace traits {
/** @name Manifold Traits */ /** @name Manifold Traits */
//@{ //@{
template <class Manifold> struct TangentVector; template<class Manifold> struct TangentVector;
template <class Manifold> struct DefaultChart; template<class Manifold> struct DefaultChart;
//@} //@}
} // namespace traits }// namespace traits
/* /*
template<class T> template<class T>
class ManifoldConcept { class ManifoldConcept {
public: public:
typedef T Manifold; typedef T Manifold;
typedef typename traits::TangentVector<T>::type TangentVector; typedef typename traits::TangentVector<T>::type TangentVector;
typedef typename traits::DefaultChart<T>::type DefaultChart; typedef typename traits::DefaultChart<T>::type DefaultChart;
static const size_t dim = traits::dimension<T>::value; static const size_t dim = traits::dimension<T>::value;
BOOST_CONCEPT_USAGE(ManifoldConcept) { BOOST_CONCEPT_USAGE(ManifoldConcept) {
BOOST_STATIC_ASSERT(boost::is_base_of<traits::manifold_tag, traits::structure<Manifold> >); BOOST_STATIC_ASSERT(boost::is_base_of<traits::manifold_tag, traits::structure<Manifold> >);
BOOST_STATIC_ASSERT(TangentVector::SizeAtCompileTime == dim); BOOST_STATIC_ASSERT(TangentVector::SizeAtCompileTime == dim);
// no direct usage for manifold since most usage is through a chart // no direct usage for manifold since most usage is through a chart
} }
private: private:
Manifold p; Manifold p;
TangentVector v; TangentVector v;
}; };
template<class C> template<class C>
class ChartConcept { class ChartConcept {
public: public:
typedef C Chart; typedef C Chart;
typedef typename traits::Manifold<Chart>::type Manifold; typedef typename traits::Manifold<Chart>::type Manifold;
typedef typename traits::TangentVector<Manifold>::type TangentVector; typedef typename traits::TangentVector<Manifold>::type TangentVector;
BOOST_CONCEPT_USAGE(ChartConcept) { BOOST_CONCEPT_USAGE(ChartConcept) {
v = Chart::local(p,q); // returns local coordinates of q w.r.t. origin p v = Chart::local(p,q); // returns local coordinates of q w.r.t. origin p
q = Chart::retract(p,v); // returns retracted update of p with v q = Chart::retract(p,v); // returns retracted update of p with v
} }
private: private:
Manifold p,q; Manifold p,q;
TangentVector v; TangentVector v;
}; };
*/ */
namespace group {
template<typename G>
G compose(const G&g, const G& h);
namespace traits { namespace traits {
/** @name Group Traits */ /** @name Group Traits */
//@{ //@{
template <class Group> struct identity; template<class G> struct identity;
template <class Group> struct group_flavor; template<class G> struct flavor;
//@} //@}
/** @name Group Flavor Tags */ /** @name Group Flavor Tags */
//@{ //@{
struct additive_group_tag {}; struct additive_tag {
struct multiplicative_group_tag {}; };
struct multiplicative_tag {
};
//@} //@}
} // namespace traits } // \ namespace traits
} // \ namespace group
/** /**
* Group Concept * Group Concept
*/ */
template<class G> template<typename G>
class Group { class Group {
public: public:
typedef typename traits::identity<G>::value_type identity_value_type;
typedef typename traits::group_flavor<G>::type group_flavor_tag;
typedef typename traits::structure_category<G>::type structure_category_tag; typedef typename traits::structure_category<G>::type structure_category_tag;
typedef typename group::traits::identity<G>::value_type identity_value_type;
typedef typename group::traits::flavor<G>::type group_flavor_tag;
BOOST_CONCEPT_USAGE(Group) { BOOST_CONCEPT_USAGE(Group) {
e = traits::identity<G>::value; using group::compose;
// BOOST_STATIC_ASSERT(boost::is_base_of<traits::group_tag,typename traits::structure_category<Group>::type>::value ); BOOST_STATIC_ASSERT(
boost::is_base_of<traits::group_tag, structure_category_tag>::value);
e = group::traits::identity<G>::value;
pq = compose(p, q);
// G ip = inverse(p); // G ip = inverse(p);
// G pq = compose(p, q);
// G d = between(p, q); // G d = between(p, q);
// test = equal(p, q); // test = equal(p, q);
// test2 = operator_usage(p, q, traits::group_flavor<Group>::type); // test2 = operator_usage(p, q, group::traits::_flavor<Group>::type);
} }
bool check_invariants(const G& a, const G& b) { bool check_invariants(const G& a, const G& b) {
@ -134,54 +149,53 @@ public:
} }
private: private:
G p, q, e; G e, p, q, pq, ip, d;
bool test, test2; bool test, test2;
bool operator_usage(const G& a, const G& b, bool operator_usage(const G& a, const G& b,
traits::multiplicative_group_tag) { group::traits::multiplicative_tag) {
return equal(compose(a, b), a * b); return equal(compose(a, b), a * b);
} }
bool operator_usage(const G& a, const G& b, traits::additive_group_tag) { bool operator_usage(const G& a, const G& b, group::traits::additive_tag) {
return equal(compose(a, b), a + b); return equal(compose(a, b), a + b);
} }
}; };
/* /*
template <class L> template <class L>
class LieGroupConcept : public GroupConcept<L>, public ManifoldConcept<L> { class LieGroupConcept : public GroupConcept<L>, public ManifoldConcept<L> {
BOOST_CONCEPT_USAGE(LieGroupConcept) { BOOST_CONCEPT_USAGE(LieGroupConcept) {
BOOST_STATIC_ASSERT(boost::is_base_of<traits::lie_group_tag, traits::structure<L> >); BOOST_STATIC_ASSERT(boost::is_base_of<traits::lie_group_tag, traits::structure<L> >);
} }
}; };
template <class V> template <class V>
class VectorSpaceConcept : public LieGroupConcept { class VectorSpaceConcept : public LieGroupConcept {
typedef typename traits::DefaultChart<V>::type Chart; typedef typename traits::DefaultChart<V>::type Chart;
typedef typename GroupConcept<V>::identity identity; typedef typename GroupConcept<V>::identity identity;
BOOST_CONCEPT_USAGE(VectorSpaceConcept) { BOOST_CONCEPT_USAGE(VectorSpaceConcept) {
BOOST_STATIC_ASSERT(boost::is_base_of<traits::vector_space_tag, traits::structure<L> >); BOOST_STATIC_ASSERT(boost::is_base_of<traits::vector_space_tag, traits::structure<L> >);
r = p+q; r = p+q;
r = -p; r = -p;
r = p-q; r = p-q;
} }
bool check_invariants(const V& a, const V& b) { bool check_invariants(const V& a, const V& b) {
return equal(compose(a, b), a+b) return equal(compose(a, b), a+b)
&& equal(inverse(a), -a) && equal(inverse(a), -a)
&& equal(between(a, b), b-a) && equal(between(a, b), b-a)
&& equal(Chart::retract(a, b), a+b) && equal(Chart::retract(a, b), a+b)
&& equal(Chart::local(a, b), b-a); && equal(Chart::local(a, b), b-a);
} }
private: private:
V p,q,r; V p,q,r;
}; };
*/ */
} // namespace gtsam } // namespace gtsam

View File

@ -35,17 +35,28 @@ public:
}; };
namespace traits { namespace traits {
/// Define Cyclic to be a model of the Group concept
template<size_t N> struct structure_category<Cyclic<N> > { template<size_t N> struct structure_category<Cyclic<N> > {
typedef group_tag type; typedef group_tag type;
}; };
} // \namespace traits
namespace group {
template<size_t N>
Cyclic<N> compose(const Cyclic<N>&g, const Cyclic<N>& h);
namespace traits {
/// Define the trait that specifies Cyclic's identity element
template<size_t N> struct identity<Cyclic<N> > { template<size_t N> struct identity<Cyclic<N> > {
static const Cyclic<N> value; static const Cyclic<N> value;
typedef Cyclic<N> value_type; typedef Cyclic<N> value_type;
}; };
template<size_t N> struct group_flavor<Cyclic<N> > { /// Define the trait that asserts Cyclic is an additive group
typedef additive_group_tag type; template<size_t N> struct flavor<Cyclic<N> > {
typedef additive_tag type;
}; };
} // \namespace traits } // \namespace traits
} // \namespace group
} // \namespace gtsam } // \namespace gtsam
@ -57,10 +68,12 @@ template<size_t N> struct group_flavor<Cyclic<N> > {
namespace gtsam { namespace gtsam {
namespace group {
namespace traits { namespace traits {
template<size_t N> template<size_t N>
const Cyclic<N> identity<Cyclic<N> >::value = Cyclic<N>(0); const Cyclic<N> identity<Cyclic<N> >::value = Cyclic<N>(0);
} // \namespace traits } // \namespace traits
} // \namespace group
} // \namespace gtsam } // \namespace gtsam
@ -81,7 +94,7 @@ typedef Cyclic<6> G; // Let's use the cyclic group of order 6
//****************************************************************************** //******************************************************************************
TEST(Cyclic, Concept) { TEST(Cyclic, Concept) {
EXPECT_LONGS_EQUAL(0,traits::identity<G>::value); EXPECT_LONGS_EQUAL(0, group::traits::identity<G>::value);
BOOST_CONCEPT_ASSERT((Group<G>)); BOOST_CONCEPT_ASSERT((Group<G>));
} }