gtsam/gtsam/base/Value.h

177 lines
7.3 KiB
C++

/* ----------------------------------------------------------------------------
* 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
* -------------------------------------------------------------------------- */
/**
* @file Value.h
* @brief The interface class for any variable that can be optimized or used in a factor.
* @author Richard Roberts
* @date Jan 14, 2012
*/
#pragma once
#include <memory>
#include <boost/serialization/assume_abstract.hpp>
#include <gtsam/base/Vector.h>
namespace gtsam {
/**
* This is the interface class for any value that may be used as a variable
* assignment in a factor graph, and which you must derive to create new
* variable types to use with gtsam. Examples of built-in classes
* implementing this are mainly in geometry, including Rot3, Pose2, etc.
*
* This interface specifies pure virtual retract_(), localCoordinates_() and
* equals_() functions that work with pointers and references to this interface
* class, i.e. the base class. These functions allow containers, such as
* Values can operate generically on Value objects, retracting or computing
* local coordinates for many Value objects of different types.
*
* Inhereting from the DerivedValue class templated provides a generic implementation of
* the pure virtual functions retract_(), localCoordinates_(), and equals_(), eliminating
* the need to implement these functions in your class. Note that you must inheret from
* DerivedValue templated on the class you are defining. For example you cannot define
* the following
* \code
* class Rot3 : public DerivedValue<Point3>{ \\classdef }
* \endcode
*
* Using the above practice, here is an example of implementing a typical
* class derived from Value:
* \code
class GTSAM_EXPORT Rot3 : public DerivedValue<Rot3> {
public:
// Constructor, there is never a need to call the Value base class constructor.
Rot3() { ... }
// Print for unit tests and debugging (virtual, implements Value::print())
virtual void print(const std::string& str = "") const;
// Equals working directly with Rot3 objects (non-virtual, non-overriding!)
bool equals(const Rot3& other, double tol = 1e-9) const;
// Tangent space dimensionality (virtual, implements Value::dim())
virtual size_t dim() const {
return 3;
}
// retract working directly with Rot3 objects (non-virtual, non-overriding!)
Rot3 retract(const Vector& delta) const {
// Math to implement a 3D rotation retraction e.g. exponential map
return Rot3(result);
}
// localCoordinates working directly with Rot3 objects (non-virtual, non-overriding!)
Vector localCoordinates(const Rot3& r2) const {
// Math to implement 3D rotation localCoordinates, e.g. logarithm map
return Vector(result);
}
};
\endcode
*/
class GTSAM_EXPORT Value {
public:
/** Clone this value in a special memory pool, must be deleted with Value::deallocate_, *not* with the 'delete' operator. */
virtual Value* clone_() const = 0;
/** Deallocate a raw pointer of this value */
virtual void deallocate_() const = 0;
/** Clone this value (normal clone on the heap, delete with 'delete' operator) */
virtual boost::shared_ptr<Value> clone() const = 0;
/** Compare this Value with another for equality. */
virtual bool equals_(const Value& other, double tol = 1e-9) const = 0;
/** Print this value, for debugging and unit tests */
virtual void print(const std::string& str = "") const = 0;
/** Return the dimensionality of the tangent space of this value. This is
* the dimensionality of \c delta passed into retract() and of the vector
* returned by localCoordinates().
* @return The dimensionality of the tangent space
*/
virtual size_t dim() const = 0;
/** Increment the value, by mapping from the vector delta in the tangent
* space of the current value back to the manifold to produce a new,
* incremented value.
* @param delta The delta vector in the tangent space of this value, by
* which to increment this value.
*/
virtual Value* retract_(const Vector& delta) const = 0;
/** Compute the coordinates in the tangent space of this value that
* retract() would map to \c value.
* @param value The value whose coordinates should be determined in the
* tangent space of the value on which this function is called.
* @return The coordinates of \c value in the tangent space of \c this.
*/
virtual Vector localCoordinates_(const Value& value) const = 0;
/** Assignment operator */
virtual Value& operator=(const Value& rhs) {
//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;
template<typename Chart>
const Chart& getChart() const;
/** Virutal destructor */
virtual ~Value() {}
private:
/** Empty serialization function.
*
* There are two important things that users need to do to serialize derived objects in Values successfully:
* (Those derived objects are stored in Values as pointer to this abstract base class Value)
*
* 1. All DERIVED classes derived from Value must put the following line in their serialization function:
* \code
ar & boost::serialization::make_nvp("DERIVED", boost::serialization::base_object<Value>(*this));
\endcode
* or, alternatively
* \code
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Value);
\endcode
* See: http://www.boost.org/doc/libs/release/libs/serialization/doc/serialization.html#runtimecasting
*
* 2. The source module that includes archive class headers to serialize objects of derived classes
* (boost/archive/text_oarchive.h, for example) must *export* all derived classes, using either
* BOOST_CLASS_EXPORT or BOOST_CLASS_EXPORT_GUID macros:
\code
BOOST_CLASS_EXPORT(DERIVED_CLASS_1)
BOOST_CLASS_EXPORT_GUID(DERIVED_CLASS_2, "DERIVED_CLASS_2_ID_STRING")
\endcode
* See: http://www.boost.org/doc/libs/release/libs/serialization/doc/serialization.html#derivedpointers
* http://www.boost.org/doc/libs/release/libs/serialization/doc/serialization.html#export
* http://www.boost.org/doc/libs/release/libs/serialization/doc/serialization.html#instantiation\
* http://www.boost.org/doc/libs/release/libs/serialization/doc/special.html#export
* http://www.boost.org/doc/libs/release/libs/serialization/doc/traits.html#export
* The last two links explain why these export lines have to be in the same source module that includes
* any of the archive class headers.
* */
friend class boost::serialization::access;
template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int version) {}
};
} /* namespace gtsam */
BOOST_SERIALIZATION_ASSUME_ABSTRACT(gtsam::Value)