Split off NoiseModelFactor (a NonlinearFactor with a NoiseModel) from NonlinearFactor (a Factor with dim, linearize, and symbolic methods). NonlinearConstraint derives from NoiseModelFactor.

release/4.3a0
Frank Dellaert 2011-09-03 03:46:19 +00:00
parent 0c34b57b92
commit 04e41f8c38
3 changed files with 144 additions and 68 deletions

View File

@ -36,11 +36,11 @@ namespace gtsam {
* significant
*/
template <class VALUES>
class NonlinearConstraint : public NonlinearFactor<VALUES> {
class NonlinearConstraint : public NoiseModelFactor<VALUES> {
protected:
typedef NonlinearConstraint<VALUES> This;
typedef NonlinearFactor<VALUES> Base;
typedef NoiseModelFactor<VALUES> Base;
/** default constructor to allow for serialization */
NonlinearConstraint() {}

View File

@ -10,7 +10,7 @@
* -------------------------------------------------------------------------- */
/**
* @file NonlinearFactor.h
* @file NoiseModelFactor.h
* @brief Non-linear factor class
* @author Frank Dellaert
* @author Richard Roberts
@ -35,8 +35,7 @@
namespace gtsam {
/**
* Nonlinear factor which assumes zero-mean Gaussian noise on the
* on a measurement predicted by a non-linear function h.
* Nonlinear factor base class
*
* Templated on a values structure type. The values structures are typically
* more general than just vectors, e.g., Rot3 or Pose3,
@ -47,10 +46,10 @@ namespace gtsam {
protected:
// Some handy typedefs
typedef Factor<Symbol> Base;
typedef NonlinearFactor<VALUES> This;
SharedNoiseModel noiseModel_; /** Noise model */
public:
typedef boost::shared_ptr<NonlinearFactor<VALUES> > shared_ptr;
@ -59,23 +58,15 @@ namespace gtsam {
NonlinearFactor() {
}
// virtual ~NonlinearFactor() {}
/** Destructor */
virtual ~NonlinearFactor() {}
/**
* Constructor
* @param noiseModel shared pointer to a noise model
* @param key1 by which to look up X value in Values
*/
NonlinearFactor(const SharedNoiseModel& noiseModel) :
noiseModel_(noiseModel) {
}
/**
* Constructor
* @param z measurement
* @param key by which to look up X value in Values
*/
NonlinearFactor(const SharedNoiseModel& noiseModel, const Symbol& key1) :
Factor<Symbol>(key1), noiseModel_(noiseModel) {
NonlinearFactor(const Symbol& key1) :
Factor<Symbol>(key1) {
}
/**
@ -83,54 +74,38 @@ namespace gtsam {
* @param j1 key of the first variable
* @param j2 key of the second variable
*/
NonlinearFactor(const SharedNoiseModel& noiseModel, const Symbol& j1, const Symbol& j2) :
Factor<Symbol>(j1,j2), noiseModel_(noiseModel) {
NonlinearFactor(const Symbol& j1, const Symbol& j2) :
Factor<Symbol>(j1,j2) {
}
/**
* Constructor - arbitrary number of keys
* @param keys is the set of Symbols in the factor
*/
NonlinearFactor(const SharedNoiseModel& noiseModel, const std::set<Symbol>& keys) :
Factor<Symbol>(keys), noiseModel_(noiseModel) {
NonlinearFactor(const std::set<Symbol>& keys) :
Factor<Symbol>(keys) {
}
/** print */
virtual void print(const std::string& s = "") const {
std::cout << s << ": NonlinearFactor\n";
noiseModel_->print(" noise model");
}
/** Check if two NonlinearFactor objects are equal */
virtual bool equals(const NonlinearFactor<VALUES>& f, double tol = 1e-9) const {
return noiseModel_->equals(*f.noiseModel_, tol);
}
/**
* calculate the error of the factor
* Override for systems with unusual noise models
* Vector of errors, unwhitened
* This is the raw error i.e. (h(x)-z) in case of NoiseModelFactor derived class
*/
virtual double error(const VALUES& c) const {
return 0.5 * noiseModel_->Mahalanobis(unwhitenedError(c));
}
/** get the dimension of the factor (number of rows on linearization) */
size_t dim() const {
return noiseModel_->dim();
}
/** access to the noise model */
SharedNoiseModel get_noiseModel() const {
return noiseModel_;
}
/** Vector of errors, unwhitened ! */
virtual Vector unwhitenedError(const VALUES& c) const = 0;
/** Vector of errors, whitened ! */
Vector whitenedError(const VALUES& c) const {
return noiseModel_->whiten(unwhitenedError(c));
}
/**
* Calculate the error of the factor
* This is typically equal to log-likelihood, e.g. 0.5(h(x)-z)^2/sigma^2 in case of Gaussian.
* You can override this for systems with unusual noise models.
*/
virtual double error(const VALUES& c) const = 0;
/** get the dimension of the factor (number of rows on linearization) */
virtual size_t dim() const = 0;
/** linearize to a GaussianFactor */
virtual boost::shared_ptr<GaussianFactor>
@ -142,6 +117,109 @@ namespace gtsam {
*/
virtual IndexFactor::shared_ptr symbolic(const Ordering& ordering) const = 0;
}; // \class NonlinearFactor
/**
* Nonlinear factor which assumes a zero-mean noise model
* on a measurement predicted by a non-linear function h.
* The noise model is typically Gaussian, but robust error models are also supported.
*/
template<class VALUES>
class NoiseModelFactor: public NonlinearFactor<VALUES>, public Testable<NoiseModelFactor<VALUES> > {
protected:
// handy typedefs
typedef NonlinearFactor<VALUES> Base;
typedef NoiseModelFactor<VALUES> This;
SharedNoiseModel noiseModel_; /** Noise model */
public:
typedef boost::shared_ptr<NoiseModelFactor<VALUES> > shared_ptr;
/** Default constructor for I/O only */
NoiseModelFactor() {
}
/** Destructor */
virtual ~NoiseModelFactor() {}
/**
* Constructor
* @param noiseModel shared pointer to a noise model
*/
NoiseModelFactor(const SharedNoiseModel& noiseModel) :
noiseModel_(noiseModel) {
}
/**
* Constructor
* @param z measurement
* @param key by which to look up X value in Values
*/
NoiseModelFactor(const SharedNoiseModel& noiseModel, const Symbol& key1) :
Base(key1), noiseModel_(noiseModel) {
}
/**
* Constructor
* @param j1 key of the first variable
* @param j2 key of the second variable
*/
NoiseModelFactor(const SharedNoiseModel& noiseModel, const Symbol& j1, const Symbol& j2) :
Base(j1,j2), noiseModel_(noiseModel) {
}
/**
* Constructor - arbitrary number of keys
* @param keys is the set of Symbols in the factor
*/
NoiseModelFactor(const SharedNoiseModel& noiseModel, const std::set<Symbol>& keys) :
Base(keys), noiseModel_(noiseModel) {
}
/** print */
virtual void print(const std::string& s = "") const {
std::cout << s << ": NoiseModelFactor\n";
noiseModel_->print(" noise model");
}
/** Check if two NoiseModelFactor objects are equal */
virtual bool equals(const NoiseModelFactor<VALUES>& f, double tol = 1e-9) const {
return noiseModel_->equals(*f.noiseModel_, tol);
}
/** get the dimension of the factor (number of rows on linearization) */
virtual size_t dim() const {
return noiseModel_->dim();
}
/** access to the noise model */
SharedNoiseModel get_noiseModel() const {
return noiseModel_;
}
/**
* Vector of errors, whitened
* This is the raw error, i.e., i.e. (h(x)-z)/sigma in case of a Gaussian
*/
Vector whitenedError(const VALUES& c) const {
return noiseModel_->whiten(unwhitenedError(c));
}
/**
* Calculate the error of the factor.
* This is the log-likelihood, e.g. 0.5(h(x)-z)^2/sigma^2 in case of Gaussian.
* In this class, we take the raw prediction error h(x)-z, ask the noise model
* to transform it to (h(x)-z)^2/sigma^2, and then multiply by 0.5.
*/
virtual double error(const VALUES& c) const {
return 0.5 * noiseModel_->Mahalanobis(unwhitenedError(c));
}
private:
/** Serialization function */
@ -149,11 +227,11 @@ namespace gtsam {
template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("Factor",
boost::serialization::base_object<Factor<Symbol> >(*this));
boost::serialization::base_object<Base >(*this));
ar & BOOST_SERIALIZATION_NVP(noiseModel_);
}
}; // \class NonlinearFactor
}; // \class NoiseModelFactor
/**
@ -165,7 +243,7 @@ namespace gtsam {
* This allows a graph to have factors with measurements of mixed type.
*/
template<class VALUES, class KEY>
class NonlinearFactor1: public NonlinearFactor<VALUES> {
class NonlinearFactor1: public NoiseModelFactor<VALUES> {
public:
@ -177,7 +255,7 @@ namespace gtsam {
// The value of the key. Not const to allow serialization
KEY key_;
typedef NonlinearFactor<VALUES> Base;
typedef NoiseModelFactor<VALUES> Base;
typedef NonlinearFactor1<VALUES, KEY> This;
public:
@ -215,8 +293,7 @@ namespace gtsam {
/** error function h(x)-z, unwhitened !!! */
inline Vector unwhitenedError(const VALUES& x) const {
const KEY& j = key_;
const X& xj = x[j];
const X& xj = x[key_];
return evaluateError(xj);
}
@ -262,7 +339,7 @@ namespace gtsam {
friend class boost::serialization::access;
template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("NonlinearFactor",
ar & boost::serialization::make_nvp("NoiseModelFactor",
boost::serialization::base_object<Base>(*this));
ar & BOOST_SERIALIZATION_NVP(key_);
}
@ -273,7 +350,7 @@ namespace gtsam {
* A Gaussian nonlinear factor that takes 2 parameters
*/
template<class VALUES, class KEY1, class KEY2>
class NonlinearFactor2: public NonlinearFactor<VALUES> {
class NonlinearFactor2: public NoiseModelFactor<VALUES> {
public:
@ -287,7 +364,7 @@ namespace gtsam {
KEY1 key1_;
KEY2 key2_;
typedef NonlinearFactor<VALUES> Base;
typedef NoiseModelFactor<VALUES> Base;
typedef NonlinearFactor2<VALUES, KEY1, KEY2> This;
public:
@ -385,7 +462,7 @@ namespace gtsam {
friend class boost::serialization::access;
template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("NonlinearFactor",
ar & boost::serialization::make_nvp("NoiseModelFactor",
boost::serialization::base_object<Base>(*this));
ar & BOOST_SERIALIZATION_NVP(key1_);
ar & BOOST_SERIALIZATION_NVP(key2_);
@ -399,7 +476,7 @@ namespace gtsam {
* A Gaussian nonlinear factor that takes 3 parameters
*/
template<class VALUES, class KEY1, class KEY2, class KEY3>
class NonlinearFactor3: public NonlinearFactor<VALUES> {
class NonlinearFactor3: public NoiseModelFactor<VALUES> {
public:
@ -415,7 +492,7 @@ namespace gtsam {
KEY2 key2_;
KEY3 key3_;
typedef NonlinearFactor<VALUES> Base;
typedef NoiseModelFactor<VALUES> Base;
typedef NonlinearFactor3<VALUES, KEY1, KEY2, KEY3> This;
public:
@ -526,7 +603,7 @@ namespace gtsam {
friend class boost::serialization::access;
template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("NonlinearFactor",
ar & boost::serialization::make_nvp("NoiseModelFactor",
boost::serialization::base_object<Base>(*this));
ar & BOOST_SERIALIZATION_NVP(key1_);
ar & BOOST_SERIALIZATION_NVP(key2_);

View File

@ -86,10 +86,9 @@ TEST( NonlinearFactor, NonlinearFactor )
Graph::sharedFactor factor = fg[0];
// calculate the error_vector from the factor "f1"
// the expected value for the whitened error from the factor
// error_vector / sigma = [0.1 0.1]/0.1 = [1;1]
Vector actual_e = factor->whitenedError(cfg);
CHECK(assert_equal(ones(2),actual_e));
// error_vector = [0.1 0.1]
Vector actual_e = factor->unwhitenedError(cfg);
CHECK(assert_equal(0.1*ones(2),actual_e));
// error = 0.5 * [1 1] * [1;1] = 1
double expected = 1.0;