gtsam/gtsam/base/OptionalJacobian.h

188 lines
4.6 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 OptionalJacobian.h
* @brief Special class for optional Jacobian arguments
* @author Frank Dellaert
* @author Natesh Srinivasan
* @date Nov 28, 2014
*/
#pragma once
#include <Eigen/Dense>
#ifndef OPTIONALJACOBIAN_NOBOOST
#include <boost/optional.hpp>
#endif
namespace gtsam {
/**
* OptionalJacobian is an Eigen::Ref like class that can take be constructed using
* either a fixed size or dynamic Eigen matrix. In the latter case, the dynamic
* matrix will be resized. Finally, there is a constructor that takes
* boost::none, the default constructor acts like boost::none, and
* boost::optional<Eigen::MatrixXd&> is also supported for backwards compatibility.
* Below this class, a dynamic version is also implemented.
*/
template<int Rows, int Cols>
class OptionalJacobian {
public:
/// ::Jacobian size type
typedef Eigen::Matrix<double, Rows, Cols> Jacobian;
private:
Eigen::Map<Jacobian> map_; /// View on constructor argument, if given
// Trick from http://eigen.tuxfamily.org/dox/group__TutorialMapClass.html
// uses "placement new" to make map_ usurp the memory of the fixed size matrix
void usurp(double* data) {
new (&map_) Eigen::Map<Jacobian>(data);
}
public:
/// Default constructor acts like boost::none
OptionalJacobian() :
map_(NULL) {
}
/// Constructor that will usurp data of a fixed-size matrix
OptionalJacobian(Jacobian& fixed) :
map_(NULL) {
usurp(fixed.data());
}
/// Constructor that will usurp data of a fixed-size matrix, pointer version
OptionalJacobian(Jacobian* fixedPtr) :
map_(NULL) {
if (fixedPtr)
usurp(fixedPtr->data());
}
/// Constructor that will resize a dynamic matrix (unless already correct)
OptionalJacobian(Eigen::MatrixXd& dynamic) :
map_(NULL) {
dynamic.resize(Rows, Cols); // no malloc if correct size
usurp(dynamic.data());
}
#ifndef OPTIONALJACOBIAN_NOBOOST
/// Constructor with boost::none just makes empty
OptionalJacobian(boost::none_t /*none*/) :
map_(NULL) {
}
/// Constructor compatible with old-style derivatives
OptionalJacobian(const boost::optional<Eigen::MatrixXd&> optional) :
map_(NULL) {
if (optional) {
optional->resize(Rows, Cols);
usurp(optional->data());
}
}
#endif
/// Return true is allocated, false if default constructor was used
operator bool() const {
return map_.data() != NULL;
}
/// De-reference, like boost optional
Eigen::Map<Jacobian>& operator*() {
return map_;
}
/// TODO: operator->()
Eigen::Map<Jacobian>* operator->(){ return &map_; }
};
// The pure dynamic specialization of this is needed to support
// variable-sized types. Note that this is designed to work like the
// boost optional scheme from GTSAM 3.
template<>
class OptionalJacobian<Eigen::Dynamic, Eigen::Dynamic> {
public:
/// Jacobian size type
typedef Eigen::MatrixXd Jacobian;
private:
Jacobian* pointer_; /// View on constructor argument, if given
public:
/// Default constructor acts like boost::none
OptionalJacobian() :
pointer_(NULL) {
}
/// Constructor that will resize a dynamic matrix (unless already correct)
OptionalJacobian(Eigen::MatrixXd& dynamic) :
pointer_(&dynamic) {
}
#ifndef OPTIONALJACOBIAN_NOBOOST
/// Constructor with boost::none just makes empty
OptionalJacobian(boost::none_t /*none*/) :
pointer_(NULL) {
}
/// Constructor compatible with old-style derivatives
OptionalJacobian(const boost::optional<Eigen::MatrixXd&> optional) :
pointer_(NULL) {
if (optional) pointer_ = &(*optional);
}
#endif
/// Return true is allocated, false if default constructor was used
operator bool() const {
return pointer_!=NULL;
}
/// De-reference, like boost optional
Jacobian& operator*() {
return *pointer_;
}
/// TODO: operator->()
Jacobian* operator->(){ return pointer_; }
};
// forward declare
template <typename T> struct traits;
/**
* @brief: meta-function to generate JacobianTA optional reference
* Used mainly by Expressions
* @param T return type
* @param A argument type
*/
template<class T, class A>
struct MakeOptionalJacobian {
typedef OptionalJacobian<traits<T>::dimension,
traits<A>::dimension> type;
};
} // namespace gtsam