gtsam/cpp/NonlinearFactor.h

200 lines
5.7 KiB
C++

/**
* @file NonlinearFactor.h
* @brief Non-linear factor class
* @author Kai Ni
* @author Carlos Nieto
* @author Christian Potthast
* @author Frank Dellaert
*/
// \callgraph
#pragma once
#include <list>
#include <limits>
#include <boost/shared_ptr.hpp>
#include <boost/serialization/list.hpp>
#include "Factor.h"
#include "Vector.h"
#include "Matrix.h"
#include "GaussianFactor.h"
/**
* Base Class
* Just has the measurement and noise model
*/
namespace gtsam {
// forward declaration of GaussianFactor
//class GaussianFactor;
//typedef boost::shared_ptr<GaussianFactor> shared_ptr;
/**
* Nonlinear factor which assumes Gaussian noise on a measurement
* predicted by a non-linear function h.
*
* Templated on a configuration type. The configurations are typically more general
* than just vectors, e.g., Rot3 or Pose3, which are objects in non-linear manifolds.
*/
template <class Config>
class NonlinearFactor : public Factor<Config>
{
protected:
Vector z_; // measurement
double sigma_; // noise standard deviation
std::list<std::string> keys_; // keys
public:
/** Default constructor, with easily identifiable bogus values */
NonlinearFactor():z_(Vector_(2,888.0,999.0)),sigma_(0.1234567) {}
/**
* Constructor
* @param z the measurement
* @param sigma the standard deviation
*/
NonlinearFactor(const Vector& z, const double sigma) {
z_ = z;
sigma_ = sigma;
}
/** print */
void print(const std::string& s = "") const {
std::cout << "NonlinearFactor " << s << std::endl;
gtsam::print(z_, " z = ");
std::cout << " sigma = " << sigma_ << std::endl;
}
/** Check if two NonlinearFactor objects are equal */
bool equals(const Factor<Config>& f, double tol=1e-9) const {
const NonlinearFactor<Config>* p = dynamic_cast<const NonlinearFactor<Config>*> (&f);
if (p == NULL) return false;
return equal_with_abs_tol(z_,p->z_,tol) && fabs(sigma_ - p->sigma_)<=tol;
}
/** Vector of errors */
virtual Vector error_vector(const Config& c) const = 0;
/** linearize to a GaussianFactor */
virtual boost::shared_ptr<GaussianFactor> linearize(const Config& c) const = 0;
/** get functions */
double sigma() const {return sigma_;}
Vector measurement() const {return z_;}
std::list<std::string> keys() const {return keys_;}
/** calculate the error of the factor */
double error(const Config& c) const {
if (sigma_==0.0) {
Vector e = error_vector(c);
return (inner_prod(e,e)>0) ? std::numeric_limits<double>::infinity() : 0.0;
}
Vector e = error_vector(c) / sigma_;
return 0.5 * inner_prod(e,e);
};
/** get the size of the factor */
std::size_t size() const{return keys_.size();}
private:
/** Serialization function */
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(z_);
ar & BOOST_SERIALIZATION_NVP(sigma_);
ar & BOOST_SERIALIZATION_NVP(keys_);
}
}; // NonlinearFactor
/**
* a Gaussian nonlinear factor that takes 1 parameter
* Note: cannot be serialized as contains function pointers
* Specialized derived classes could do this
*/
class NonlinearFactor1 : public NonlinearFactor<VectorConfig> {
private:
std::string key_;
public:
Vector (*h_)(const Vector&);
Matrix (*H_)(const Vector&);
/** Constructor */
NonlinearFactor1(const Vector& z, // measurement
const double sigma, // variance
Vector (*h)(const Vector&), // measurement function
const std::string& key1, // key of the variable
Matrix (*H)(const Vector&)); // derivative of the measurement function
void print(const std::string& s = "") const;
/** Check if two factors are equal */
bool equals(const Factor<VectorConfig>& f, double tol=1e-9) const;
/** error function */
inline Vector error_vector(const VectorConfig& c) const {
return z_ - h_(c[key_]);
}
/** linearize a non-linearFactor1 to get a linearFactor1 */
boost::shared_ptr<GaussianFactor> linearize(const VectorConfig& c) const;
};
/**
* a Gaussian nonlinear factor that takes 2 parameters
* Note: cannot be serialized as contains function pointers
* Specialized derived classes could do this
*/
class NonlinearFactor2 : public NonlinearFactor<VectorConfig> {
private:
std::string key1_;
std::string key2_;
public:
Vector (*h_)(const Vector&, const Vector&);
Matrix (*H1_)(const Vector&, const Vector&);
Matrix (*H2_)(const Vector&, const Vector&);
/** Constructor */
NonlinearFactor2(const Vector& z, // the measurement
const double sigma, // the variance
Vector (*h)(const Vector&, const Vector&), // the measurement function
const std::string& key1, // key of the first variable
Matrix (*H1)(const Vector&, const Vector&), // derivative of h in first variable
const std::string& key2, // key of the second variable
Matrix (*H2)(const Vector&, const Vector&));// derivative of h in second variable
/** Print */
void print(const std::string& s = "") const;
/** Check if two factors are equal */
bool equals(const Factor<VectorConfig>& f, double tol=1e-9) const;
/** error function */
inline Vector error_vector(const VectorConfig& c) const {
return z_ - h_(c[key1_], c[key2_]);
}
/** Linearize a non-linearFactor2 to get a linearFactor2 */
boost::shared_ptr<GaussianFactor> linearize(const VectorConfig& c) const;
};
/* ************************************************************************* */
}