Comments, formatting, some TODO questions
parent
e0c4d84dd7
commit
329e7f1383
|
@ -11,9 +11,10 @@
|
|||
|
||||
/*
|
||||
* @file ChartValue.h
|
||||
* @date Jan 26, 2012
|
||||
* @brief
|
||||
* @date October, 2014
|
||||
* @author Michael Bosse, Abel Gawel, Renaud Dube
|
||||
* based on DrivedValue.h by Duy Nguyen Ta
|
||||
* based on DerivedValue.h by Duy Nguyen Ta
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -39,25 +40,44 @@
|
|||
#endif
|
||||
//////////////////
|
||||
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
// ChartValue is derived from GenericValue<T> and Chart so that Chart can be zero sized (as in DefaultChart<T>)
|
||||
// if the Chart is a member variable then it won't ever be zero sized.
|
||||
/**
|
||||
* ChartValue is derived from GenericValue<T> and Chart so that
|
||||
* Chart can be zero sized (as in DefaultChart<T>)
|
||||
* if the Chart is a member variable then it won't ever be zero sized.
|
||||
*/
|
||||
template<class T, class Chart_ = DefaultChart<T> >
|
||||
class ChartValue: public GenericValue<T>, public Chart_ {
|
||||
|
||||
BOOST_CONCEPT_ASSERT((ChartConcept<Chart_>));
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
typedef Chart_ Chart;
|
||||
|
||||
public:
|
||||
ChartValue() : GenericValue<T>(T()) {}
|
||||
ChartValue(const T& value) : GenericValue<T>(value) {}
|
||||
template<typename C>
|
||||
ChartValue(const T& value, C chart_initializer) : GenericValue<T>(value), Chart(chart_initializer) {}
|
||||
|
||||
virtual ~ChartValue() {}
|
||||
/// Default Constructor. TODO might not make sense for some types
|
||||
ChartValue() :
|
||||
GenericValue<T>(T()) {
|
||||
}
|
||||
|
||||
/// Construct froma value
|
||||
ChartValue(const T& value) :
|
||||
GenericValue<T>(value) {
|
||||
}
|
||||
|
||||
/// Construct from a value and initialize the chart
|
||||
template<typename C>
|
||||
ChartValue(const T& value, C chart_initializer) :
|
||||
GenericValue<T>(value), Chart(chart_initializer) {
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~ChartValue() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a duplicate object returned as a pointer to the generic Value interface.
|
||||
|
@ -85,18 +105,16 @@ class ChartValue : public GenericValue<T>, public Chart_ {
|
|||
return boost::make_shared<ChartValue>(*this);
|
||||
}
|
||||
|
||||
/// just use the equals_ defined in GenericValue
|
||||
// virtual bool equals_(const Value& p, double tol = 1e-9) const {
|
||||
// }
|
||||
|
||||
/// Chart Value interface version of retract
|
||||
virtual Value* retract_(const Vector& delta) const {
|
||||
// Call retract on the derived class using the retract trait function
|
||||
const T retractResult = Chart::retract(GenericValue<T>::value(), delta);
|
||||
|
||||
// Create a Value pointer copy of the result
|
||||
void* resultAsValuePlace = boost::singleton_pool<PoolTag, sizeof(ChartValue)>::malloc();
|
||||
Value* resultAsValue = new(resultAsValuePlace) ChartValue(retractResult, static_cast<const Chart&>(*this));
|
||||
void* resultAsValuePlace =
|
||||
boost::singleton_pool<PoolTag, sizeof(ChartValue)>::malloc();
|
||||
Value* resultAsValue = new (resultAsValuePlace) ChartValue(retractResult,
|
||||
static_cast<const Chart&>(*this));
|
||||
|
||||
// Return the pointer to the Value base class
|
||||
return resultAsValue;
|
||||
|
@ -105,7 +123,8 @@ class ChartValue : public GenericValue<T>, public Chart_ {
|
|||
/// Generic Value interface version of localCoordinates
|
||||
virtual Vector localCoordinates_(const Value& value2) const {
|
||||
// Cast the base class Value pointer to a templated generic class pointer
|
||||
const GenericValue<T>& genericValue2 = static_cast<const GenericValue<T>&>(value2);
|
||||
const GenericValue<T>& genericValue2 =
|
||||
static_cast<const GenericValue<T>&>(value2);
|
||||
|
||||
// Return the result of calling localCoordinates trait on the derived class
|
||||
return Chart::local(GenericValue<T>::value(), genericValue2.value());
|
||||
|
@ -113,7 +132,8 @@ class ChartValue : public GenericValue<T>, public Chart_ {
|
|||
|
||||
/// Non-virtual version of retract
|
||||
ChartValue retract(const Vector& delta) const {
|
||||
return ChartValue(Chart::retract(GenericValue<T>::value(), delta),static_cast<const Chart&>(*this));
|
||||
return ChartValue(Chart::retract(GenericValue<T>::value(), delta),
|
||||
static_cast<const Chart&>(*this));
|
||||
}
|
||||
|
||||
/// Non-virtual version of localCoordinates
|
||||
|
@ -121,8 +141,10 @@ class ChartValue : public GenericValue<T>, public Chart_ {
|
|||
return localCoordinates_(value2);
|
||||
}
|
||||
|
||||
/// Return run-time dimensionality
|
||||
virtual size_t dim() const {
|
||||
return Chart::getDimension(GenericValue<T>::value()); // need functional form here since the dimension may be dynamic
|
||||
// need functional form here since the dimension may be dynamic
|
||||
return Chart::getDimension(GenericValue<T>::value());
|
||||
}
|
||||
|
||||
/// Assignment operator
|
||||
|
@ -136,6 +158,7 @@ class ChartValue : public GenericValue<T>, public Chart_ {
|
|||
}
|
||||
|
||||
protected:
|
||||
|
||||
// implicit assignment operator for (const ChartValue& rhs) works fine here
|
||||
/// Assignment operator, protected because only the Value or DERIVED
|
||||
/// assignment operators should be used.
|
||||
|
@ -145,44 +168,52 @@ protected:
|
|||
// }
|
||||
|
||||
private:
|
||||
|
||||
/// Fake Tag struct for singleton pool allocator. In fact, it is never used!
|
||||
struct PoolTag { };
|
||||
struct PoolTag {
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/// @}
|
||||
/// @name Advanced Interface
|
||||
/// @{
|
||||
|
||||
/** Serialization function */
|
||||
friend class boost::serialization::access;
|
||||
template<class ARCHIVE>
|
||||
void serialize(ARCHIVE & ar, const unsigned int version) {
|
||||
// ar & boost::serialization::make_nvp("value",);
|
||||
// todo: implement a serialization for charts
|
||||
ar & boost::serialization::make_nvp("GenericValue", boost::serialization::base_object< GenericValue<T> >(*this));
|
||||
ar
|
||||
& boost::serialization::make_nvp("GenericValue",
|
||||
boost::serialization::base_object<GenericValue<T> >(*this));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
// Define
|
||||
namespace traits {
|
||||
template <typename T, typename Chart>
|
||||
struct dimension<ChartValue<T, Chart> > : public dimension<Chart> {};
|
||||
}
|
||||
|
||||
/// The dimension of a ChartValue is the dimension of the chart
|
||||
template<typename T, typename Chart>
|
||||
struct dimension<ChartValue<T, Chart> > : public dimension<Chart> {
|
||||
// TODO Frank thinks dimension is a property of type, chart should conform
|
||||
};
|
||||
|
||||
} // \ traits
|
||||
|
||||
/// Get the chart from a Value
|
||||
template<typename Chart>
|
||||
const Chart& Value::getChart() const {
|
||||
// define Value::cast here since now ChartValue has been declared
|
||||
return dynamic_cast<const Chart&>(*this);
|
||||
}
|
||||
|
||||
/// Convenience function that can be used to make an expression to convert a value to a chart
|
||||
template<typename T>
|
||||
ChartValue<T> convertToChartValue(const T& value, boost::optional<Eigen::Matrix<double, traits::dimension<T>::value, traits::dimension<T>::value >& > H=boost::none) {
|
||||
ChartValue<T> convertToChartValue(const T& value,
|
||||
boost::optional<
|
||||
Eigen::Matrix<double, traits::dimension<T>::value,
|
||||
traits::dimension<T>::value>&> H = boost::none) {
|
||||
if (H) {
|
||||
*H = Eigen::Matrix<double, traits::dimension<T>::value, traits::dimension<T>::value >::Identity();
|
||||
*H = Eigen::Matrix<double, traits::dimension<T>::value,
|
||||
traits::dimension<T>::value>::Identity();
|
||||
}
|
||||
return ChartValue<T>(value);
|
||||
}
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
|
||||
/*
|
||||
* @file GenericValue.h
|
||||
* @date Jan 26, 2012
|
||||
* @brief Wraps any type T so it can play as a Value
|
||||
* @date October, 2014
|
||||
* @author Michael Bosse, Abel Gawel, Renaud Dube
|
||||
* based on DrivedValue.h by Duy Nguyen Ta
|
||||
* based on DerivedValue.h by Duy Nguyen Ta
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -22,6 +23,7 @@
|
|||
|
||||
namespace gtsam {
|
||||
|
||||
// To play as a GenericValue, we need the following traits
|
||||
namespace traits {
|
||||
|
||||
// trait to wrap the default equals of types
|
||||
|
@ -30,6 +32,7 @@ template<typename T>
|
|||
return a.equals(b, tol);
|
||||
}
|
||||
|
||||
// trait to wrap the default print of types
|
||||
template<typename T>
|
||||
void print(const T& obj, const std::string& str) {
|
||||
obj.print(str);
|
||||
|
@ -37,20 +40,40 @@ void print(const T& obj, const std::string& str) {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps any type T so it can play as a Value
|
||||
*/
|
||||
template<class T>
|
||||
class GenericValue: public Value {
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
protected:
|
||||
T value_;
|
||||
|
||||
T value_; ///< The wrapped value
|
||||
|
||||
public:
|
||||
GenericValue(const T& value) : value_(value) {}
|
||||
|
||||
const T& value() const { return value_; }
|
||||
T& value() { return value_; }
|
||||
/// Construct from value
|
||||
GenericValue(const T& value) :
|
||||
value_(value) {
|
||||
}
|
||||
|
||||
virtual ~GenericValue() {}
|
||||
/// Return a constant value
|
||||
const T& value() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Return the value
|
||||
T& value() {
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~GenericValue() {
|
||||
}
|
||||
|
||||
/// equals implementing generic Value interface
|
||||
virtual bool equals_(const Value& p, double tol = 1e-9) const {
|
||||
|
@ -60,22 +83,28 @@ public:
|
|||
return traits::equals<T>(this->value_, genericValue2.value_, tol);
|
||||
}
|
||||
|
||||
// non virtual equals function
|
||||
/// non virtual equals function, uses traits
|
||||
bool equals(const GenericValue &other, double tol = 1e-9) const {
|
||||
return traits::equals<T>(this->value(), other.value(), tol);
|
||||
}
|
||||
|
||||
/// Virtual print function, uses traits
|
||||
virtual void print(const std::string& str) const {
|
||||
traits::print<T>(value_, str);
|
||||
}
|
||||
|
||||
// Serialization below:
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template<class ARCHIVE>
|
||||
void serialize(ARCHIVE & ar, const unsigned int version) {
|
||||
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Value);
|
||||
ar & BOOST_SERIALIZATION_NVP(value_);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Assignment operator for this class not needed since GenricValue<T> is an abstract class
|
||||
|
||||
// Assignment operator for this class not needed since GenericValue<T> is an abstract class
|
||||
|
||||
};
|
||||
|
||||
|
@ -85,5 +114,4 @@ template<typename ValueType>
|
|||
return dynamic_cast<const GenericValue<ValueType>&>(*this).value();
|
||||
}
|
||||
|
||||
|
||||
} /* namespace gtsam */
|
||||
|
|
|
@ -67,9 +67,12 @@ struct is_manifold: public boost::false_type {
|
|||
};
|
||||
|
||||
// dimension, can return Eigen::Dynamic (-1) if not known at compile time
|
||||
// defaults to dynamic, TODO makes sense ?
|
||||
typedef boost::integral_constant<int, Eigen::Dynamic> Dynamic;
|
||||
template<typename T>
|
||||
struct dimension : public Dynamic {}; //default to dynamic
|
||||
struct dimension: public Dynamic {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* zero<T>::value is intended to be the origin of a canonical coordinate system
|
||||
|
@ -140,7 +143,8 @@ struct zero<Eigen::Matrix<double, M, N, Options> > : public boost::integral_cons
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T> struct is_chart : public boost::false_type {};
|
||||
template<typename T> struct is_chart: public boost::false_type {
|
||||
};
|
||||
|
||||
} // \ namespace traits
|
||||
|
||||
|
@ -164,8 +168,10 @@ struct DefaultChart {
|
|||
|
||||
namespace traits {
|
||||
// populate default traits
|
||||
template <typename T> struct is_chart<DefaultChart<T> > : public boost::true_type {};
|
||||
template <typename T> struct dimension<DefaultChart<T> > : public dimension<T> {};
|
||||
template<typename T> struct is_chart<DefaultChart<T> > : public boost::true_type {
|
||||
};
|
||||
template<typename T> struct dimension<DefaultChart<T> > : public dimension<T> {
|
||||
};
|
||||
}
|
||||
|
||||
template<class C>
|
||||
|
@ -198,7 +204,6 @@ struct ChartConcept {
|
|||
int dim_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* CanonicalChart<Chart<T> > is a chart around zero<T>::value
|
||||
* Canonical<T> is CanonicalChart<DefaultChart<T> >
|
||||
|
@ -220,7 +225,8 @@ template<typename C> struct CanonicalChart {
|
|||
return Chart::retract(traits::zero<type>::value(), v);
|
||||
}
|
||||
};
|
||||
template <typename T> struct Canonical : public CanonicalChart<DefaultChart<T> > {};
|
||||
template<typename T> struct Canonical: public CanonicalChart<DefaultChart<T> > {
|
||||
};
|
||||
|
||||
// double
|
||||
|
||||
|
@ -248,8 +254,7 @@ template<int M, int N, int Options>
|
|||
struct DefaultChart<Eigen::Matrix<double, M, N, Options> > {
|
||||
typedef Eigen::Matrix<double, M, N, Options> type;
|
||||
typedef type T;
|
||||
typedef Eigen::Matrix<double, traits::dimension<T>::value, 1> vector;
|
||||
BOOST_STATIC_ASSERT_MSG((M!=Eigen::Dynamic && N!=Eigen::Dynamic),
|
||||
typedef Eigen::Matrix<double, traits::dimension<T>::value, 1> vector;BOOST_STATIC_ASSERT_MSG((M!=Eigen::Dynamic && N!=Eigen::Dynamic),
|
||||
"DefaultChart has not been implemented yet for dynamically sized matrices");
|
||||
static vector local(const T& origin, const T& other) {
|
||||
T diff = other - origin;
|
||||
|
|
|
@ -124,6 +124,7 @@ namespace gtsam {
|
|||
//needs a empty definition so recursion in implicit derived assignment operators work
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Cast to known ValueType */
|
||||
template<typename ValueType>
|
||||
const ValueType& cast() const;
|
||||
|
|
|
@ -300,6 +300,7 @@ namespace gtsam {
|
|||
void Values::insert(Key j, const ValueType& val) {
|
||||
insert(j, static_cast<const Value&>(ChartValue<ValueType, Chart>(val)));
|
||||
}
|
||||
|
||||
// overloaded insert with chart initializer
|
||||
template<typename ValueType, typename Chart, typename ChartInit>
|
||||
void Values::insert(Key j, const ValueType& val, ChartInit chart) {
|
||||
|
@ -311,11 +312,13 @@ namespace gtsam {
|
|||
void Values::update(Key j, const ValueType& val) {
|
||||
update(j, static_cast<const Value&>(ChartValue<ValueType, DefaultChart<ValueType> >(val)));
|
||||
}
|
||||
|
||||
// update with custom chart
|
||||
template <typename ValueType, typename Chart>
|
||||
void Values::update(Key j, const ValueType& val) {
|
||||
update(j, static_cast<const Value&>(ChartValue<ValueType, Chart>(val)));
|
||||
}
|
||||
|
||||
// update with chart initializer, /todo: perhaps there is a way to init chart from old value...
|
||||
template<typename ValueType, typename Chart, typename ChartInit>
|
||||
void Values::update(Key j, const ValueType& val, ChartInit chart) {
|
||||
|
|
|
@ -251,15 +251,18 @@ namespace gtsam {
|
|||
/** Add a set of variables, throws KeyAlreadyExists<J> if a key is already present */
|
||||
void insert(const Values& values);
|
||||
|
||||
/** Templated verion to add a variable with the given j,
|
||||
/** Templated version to add a variable with the given j,
|
||||
* throws KeyAlreadyExists<J> if j is already present
|
||||
* if no chart is specified, the DefaultChart<ValueType> is used
|
||||
*/
|
||||
template <typename ValueType>
|
||||
void insert(Key j, const ValueType& val);
|
||||
|
||||
/// overloaded insert version that also specifies a chart
|
||||
template <typename ValueType, typename Chart>
|
||||
void insert(Key j, const ValueType& val);
|
||||
// overloaded insert version that also specifies a chart initializer
|
||||
|
||||
/// overloaded insert version that also specifies a chart initializer
|
||||
template <typename ValueType, typename Chart, typename ChartInit>
|
||||
void insert(Key j, const ValueType& val, ChartInit chart);
|
||||
|
||||
|
@ -273,14 +276,18 @@ namespace gtsam {
|
|||
/** single element change of existing element */
|
||||
void update(Key j, const Value& val);
|
||||
|
||||
/** Templated verion to update a variable with the given j,
|
||||
/** Templated version to update a variable with the given j,
|
||||
* throws KeyAlreadyExists<J> if j is already present
|
||||
* if no chart is specified, the DefaultChart<ValueType> is used
|
||||
*/
|
||||
template <typename T>
|
||||
void update(Key j, const T& val);
|
||||
|
||||
/// overloaded insert version that also specifies a chart
|
||||
template <typename T, typename Chart>
|
||||
void update(Key j, const T& val);
|
||||
|
||||
/// overloaded insert version that also specifies a chart initializer
|
||||
template <typename T, typename Chart, typename ChartInit>
|
||||
void update(Key j, const T& val, ChartInit chart);
|
||||
|
||||
|
|
Loading…
Reference in New Issue