4.8 KiB
GTSAM Concepts
As discussed in Generic Programming Techniques, concepts define
- associated types
- valid expressions, like functions and values
- invariants
- complexity guarantees
Below we discuss the most important concepts use in GTSAM, and after that we discuss how they are implemented/used/enforced.
Manifold
To optimize over continuous types, we assume they are manifolds. This is central to GTSAM and hence discussed in some more detail below.
Manifolds and charts are intimately linked concepts. We are only interested here in differentiable manifolds, continuous spaces that can be locally approximated at any point using a local vector space, called the tangent space. A chart is an invertible map from the manifold to the vector space.
In GTSAM we assume that a manifold type can yield such a chart at any point, and we require that a functor defaultChart
is available that, when called for any point on the manifold, returns a Chart type.
- values:
dimension
- types:
Vector
, type that lives in tangent space *DefaultChart
is the type of the chart returned by the functordefaultChart
- functor
defaultChart
, returns aDefaultChart
- invariants:
defaultChart::result_type == DefaultChart::type
Anything else?
Chart
- types:
Manifold
, a pointer back to the type - values:
retract
,local
Are these values? They are just methods. Anything else?
Group
- values:
identity
- values:
compose
,inverse
, (between
)
Lie Group
Implements both MANIFOLD and GROUP
Vector Space
Lie Group where compose == +
Testable
Unit tests heavily depend on the following two functions being defined for all types that need to be tested:
- functions:
print
,equals
Implementation
GTSAM Types start with Uppercase, e.g., gtsam::Point2
, and are models of the TESTABLE, MANIFOLD, GROUP, LIE_GROUP, and VECTOR_SPACE concepts. gtsam::traits
is our way to associate these concepts with types, and we also define a limited number of gtsam::tags
to select the correct implementation of certain functions at compile time (tag dispatching).
traits
We will not use Eigen-style or STL-style traits, that define many properties at once. Rather, we use boost::mpl style meta-programming functions to facilitate meta-programming.
Traits allow us to play with types that are outside GTSAM control, e.g., Eigen::VectorXd
.
The naming conventions are as follows:
-
Types:
gtsam::traits::SomeAssociatedType<T>::type
, i.e., they are MixedCase and define atype
, for example:template<> gtsam::traits::TangentVector<Point2> { typedef Vector2 type; }
-
Values:
gtsam::traits::someValue<T>::value
, i.e., they are mixedCase starting with a lowercase letter and define avalue
, but also avalue_type
. For example:template<> gtsam::traits::dimension<Point2> { static const int value = 2; typedef const int value_type; // const ? }
-
Functors:
gtsam::traits::someFunctor<T>::type
, i.e., they are mixedCase starting with a lowercase letter and define a functortype
. The funcor itself should define aresult_type
. Examplestruct Point2::retract { typedef Point2 result_type; Point2 p_; retract(const Point2& p) : p_(p) {} Point2 operator()(const Vector2& v) { return Point2(p.x()+v[0], p.y()+v[1]); } } template<> gtsam::traits::retract<Point2> { typedef Point2::retract type; }
The above is still up in the air. Do we need the type indirection? Could we just inherit the trait like so
template<> gtsam::traits::retract<Point2> : Point2::retract { }
In which case we could just say
gtsam::traits::retract<Point2>(p)(v)
.
tags
Concepts are associated with a tag.
gtsam::tags::manifold_tag
gtsam::tags::group_tag
gtsam::tags::lie_group_tag
gtsam::tags::vector_space_tag
Can be queried gtsam::traits::structure_tag<T>
Examples
An example of implementing a Manifold is here:
// GTSAM type
class Rot2 {
...
class Chart {
...
}
}
namespace gtsam {
namespace traits {
template<>
struct DefaultChart<Rot2> {
typedef Rot2::Chart type;
}
template<>
struct Manifold<Rot2::Chart> {
typedef Rot2 type;
}
template<>
struct Vector<Rot2::Chart> {
typedef Vector2 type;
}
}