gtsam  4.0.0
gtsam
Group.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 
21 #pragma once
22 
23 #include <gtsam/base/Testable.h>
24 
25 #include <boost/concept_check.hpp>
26 #include <boost/concept/requires.hpp>
27 #include <boost/type_traits/is_base_of.hpp>
28 #include <boost/static_assert.hpp>
29 #include <utility>
30 
31 namespace gtsam {
32 
34 struct group_tag {};
35 
39 
40 template <typename T> struct traits;
41 
45 template<typename G>
46 class IsGroup {
47 public:
48  typedef typename traits<G>::structure_category structure_category_tag;
49  typedef typename traits<G>::group_flavor flavor_tag;
50  //typedef typename traits<G>::identity::value_type identity_value_type;
51 
52  BOOST_CONCEPT_USAGE(IsGroup) {
53  BOOST_STATIC_ASSERT_MSG(
54  (boost::is_base_of<group_tag, structure_category_tag>::value),
55  "This type's structure_category trait does not assert it as a group (or derived)");
56  e = traits<G>::Identity();
57  e = traits<G>::Compose(g, h);
58  e = traits<G>::Between(g, h);
59  e = traits<G>::Inverse(g);
60  operator_usage(flavor);
61  // todo: how do we test the act concept? or do we even need to?
62  }
63 
64 private:
65  void operator_usage(multiplicative_group_tag) {
66  e = g * h;
67  //e = -g; // todo this should work, but it is failing for Quaternions
68  }
69  void operator_usage(additive_group_tag) {
70  e = g + h;
71  e = h - g;
72  e = -g;
73  }
74 
75  flavor_tag flavor;
76  G e, g, h;
77  bool b;
78 };
79 
81 template<typename G>
83 check_group_invariants(const G& a, const G& b, double tol = 1e-9) {
84  G e = traits<G>::Identity();
88 }
89 
90 namespace internal {
91 
94 template<class Class>
95 struct MultiplicativeGroupTraits {
96  typedef group_tag structure_category;
97  typedef multiplicative_group_tag group_flavor;
98  static Class Identity() { return Class::identity(); }
99  static Class Compose(const Class &g, const Class & h) { return g * h;}
100  static Class Between(const Class &g, const Class & h) { return g.inverse() * h;}
101  static Class Inverse(const Class &g) { return g.inverse();}
102 };
103 
105 template<class Class>
106 struct MultiplicativeGroup : MultiplicativeGroupTraits<Class>, Testable<Class> {};
107 
110 template<class Class>
111 struct AdditiveGroupTraits {
112  typedef group_tag structure_category;
113  typedef additive_group_tag group_flavor;
114  static Class Identity() { return Class::identity(); }
115  static Class Compose(const Class &g, const Class & h) { return g + h;}
116  static Class Between(const Class &g, const Class & h) { return h - g;}
117  static Class Inverse(const Class &g) { return -g;}
118 };
119 
121 template<class Class>
122 struct AdditiveGroup : AdditiveGroupTraits<Class>, Testable<Class> {};
123 
124 } // namespace internal
125 
127 template<typename G>
128 BOOST_CONCEPT_REQUIRES(((IsGroup<G>)),(G)) //
129 compose_pow(const G& g, size_t n) {
130  if (n == 0) return traits<G>::Identity();
131  else if (n == 1) return g;
132  else return traits<G>::Compose(compose_pow(g, n - 1), g);
133 }
134 
137 template<typename G, typename H>
138 class DirectProduct: public std::pair<G, H> {
139  BOOST_CONCEPT_ASSERT((IsGroup<G>));
140  BOOST_CONCEPT_ASSERT((IsGroup<H>));
141 
142 public:
144  DirectProduct():std::pair<G,H>(traits<G>::Identity(),traits<H>::Identity()) {}
145 
146  // Construct from two subgroup elements
147  DirectProduct(const G& g, const H& h):std::pair<G,H>(g,h) {}
148 
149  // identity
150  static DirectProduct identity() { return DirectProduct(); }
151 
152  DirectProduct operator*(const DirectProduct& other) const {
153  return DirectProduct(traits<G>::Compose(this->first, other.first),
154  traits<H>::Compose(this->second, other.second));
155  }
156  DirectProduct inverse() const {
157  return DirectProduct(this->first.inverse(), this->second.inverse());
158  }
159 };
160 
161 // Define any direct product group to be a model of the multiplicative Group concept
162 template<typename G, typename H>
163 struct traits<DirectProduct<G, H> > :
164  internal::MultiplicativeGroupTraits<DirectProduct<G, H> > {};
165 
168 template<typename G, typename H>
169 class DirectSum: public std::pair<G, H> {
170  BOOST_CONCEPT_ASSERT((IsGroup<G>)); // TODO(frank): check additive
171  BOOST_CONCEPT_ASSERT((IsGroup<H>)); // TODO(frank): check additive
172 
173  const G& g() const { return this->first; }
174  const H& h() const { return this->second;}
175 
176 public:
178  DirectSum():std::pair<G,H>(traits<G>::Identity(),traits<H>::Identity()) {}
179 
180  // Construct from two subgroup elements
181  DirectSum(const G& g, const H& h):std::pair<G,H>(g,h) {}
182 
183  // identity
184  static DirectSum identity() { return DirectSum(); }
185 
186  DirectSum operator+(const DirectSum& other) const {
187  return DirectSum(g()+other.g(), h()+other.h());
188  }
189  DirectSum operator-(const DirectSum& other) const {
190  return DirectSum(g()-other.g(), h()-other.h());
191  }
192  DirectSum operator-() const {
193  return DirectSum(- g(), - h());
194  }
195 };
196 
197 // Define direct sums to be a model of the Additive Group concept
198 template<typename G, typename H>
199 struct traits<DirectSum<G, H> > :
200  internal::AdditiveGroupTraits<DirectSum<G, H> > {};
201 
202 } // namespace gtsam
203 
212 #define GTSAM_CONCEPT_GROUP_INST(T) template class gtsam::IsGroup<T>;
213 #define GTSAM_CONCEPT_GROUP_TYPE(T) typedef gtsam::IsGroup<T> _gtsam_IsGroup_##T;
Group operator syntax flavors.
Definition: Group.h:37
DirectProduct()
Default constructor yields identity.
Definition: Group.h:144
Template to construct the direct sum of two additive groups Assumes existence of three additive opera...
Definition: Group.h:169
Group Concept.
Definition: Group.h:46
tag to assert a type is a group
Definition: Group.h:34
Definition: Group.h:38
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition: concepts.h:30
BOOST_CONCEPT_REQUIRES(((IsGroup< G >)),(bool)) check_group_invariants(const G &a
Check invariants.
Definition: Group.h:138
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
Concept check for values that can be used in unit tests.
DirectSum()
Default constructor yields identity.
Definition: Group.h:178