diff --git a/.cproject b/.cproject
index 32ddccfa1..21cfaf8a6 100644
--- a/.cproject
+++ b/.cproject
@@ -743,6 +743,14 @@
true
true
+
+make
+-j2
+testNoiseModel.run
+true
+true
+true
+
make
-j2
diff --git a/cpp/NoiseModel.cpp b/cpp/NoiseModel.cpp
index af50ab360..a6e28efe0 100644
--- a/cpp/NoiseModel.cpp
+++ b/cpp/NoiseModel.cpp
@@ -2,7 +2,62 @@
* NoiseModel.cpp
*
* Created on: Jan 13, 2010
- * Author: richard
+ * Author: Richard Roberts
+ * Author: Frank Dellaert
*/
+//#include
+
#include "NoiseModel.h"
+
+namespace gtsam {
+
+ Vector Isotropic::whiten(const Vector& v) const {
+ return v * invsigma_;
+ }
+
+ Vector Isotropic::unwhiten(const Vector& v) const {
+ return v * sigma_;
+ }
+
+ Diagonal::Diagonal(const Vector& sigmas) :
+ sigmas_(sigmas), invsigmas_(1.0 / sigmas) {
+ }
+
+ Diagonal::Diagonal(const Diagonal& d) :
+ sigmas_(d.sigmas_), invsigmas_(d.invsigmas_) {
+ }
+
+ Vector Diagonal::whiten(const Vector& v) const {
+ return emul(v, invsigmas_);
+ }
+
+ Vector Diagonal::unwhiten(const Vector& v) const {
+ return emul(v, sigmas_);
+ }
+
+ Variances::Variances(const Vector& variances) {
+ sigmas_.resize(variances.size());
+ std::transform(variances.begin(), variances.end(), sigmas_.begin(), sqrt);
+ invsigmas_ = reciprocal(sigmas_);
+ }
+
+ FullCovariance::FullCovariance(const Matrix& cov) :
+ sqrt_covariance_(square_root_positive(cov)), sqrt_inv_covariance_(
+ inverse_square_root(cov)) {
+ }
+
+ FullCovariance::FullCovariance(const FullCovariance& cov) :
+ sqrt_covariance_(cov.sqrt_covariance_), sqrt_inv_covariance_(
+ cov.sqrt_inv_covariance_) {
+ }
+
+ Vector FullCovariance::whiten(const Vector& v) const {
+ return sqrt_inv_covariance_ * v;
+ }
+
+ Vector FullCovariance::unwhiten(const Vector& v) const {
+ return sqrt_covariance_ * v;
+ }
+
+} // gtsam
diff --git a/cpp/NoiseModel.h b/cpp/NoiseModel.h
index 5e37c86ab..8b84c0464 100644
--- a/cpp/NoiseModel.h
+++ b/cpp/NoiseModel.h
@@ -2,31 +2,24 @@
* NoiseModel.h
*
* Created on: Jan 13, 2010
- * Author: richard
+ * Author: Richard Roberts
+ * Author: Frank Dellaert
*/
#pragma once
-#include
-#include
-//#include
-//using namespace std;
-
#include "Vector.h"
#include "Matrix.h"
namespace gtsam {
- // Forward declaration
- class NoiseModel;
-
- /*****************************************************************************
- * NoiseModelBase is the abstract base class for all noise models. NoiseModels
+ /**
+ * NoiseModel is the abstract base class for all noise models. NoiseModels
* must implement a 'whiten' function to normalize an error vector, and an
* 'unwhiten' function to unnormalize an error vector.
*/
- class NoiseModelBase {
- public:
+ struct NoiseModel {
+
/**
* Whiten an error vector.
*/
@@ -36,82 +29,14 @@ namespace gtsam {
* Unwhiten an error vector.
*/
virtual Vector unwhiten(const Vector& v) const = 0;
-
- friend class NoiseModel;
-
- private:
- /**
- * Used internally to duplicate the object while retaining the type.
- */
- virtual boost::shared_ptr clone() const = 0;
};
-
-
- /*****************************************************************************
- * NoiseModel is a container for NoiseModelBase, which internally stores
- * a shared_ptr to a NoiseModelBase as to support fast and compact storage and
- * copies. Copying this class simply assigns the internal shared_ptr.
- */
- class NoiseModel {
- private:
- const boost::shared_ptr base_;
-
- /**
- * Fast constructor, simply assigns shared_ptr.
- */
- NoiseModel(boost::shared_ptr noiseModel): base_(noiseModel) {
- /*std::cout << "Assigning pointer" << std::endl;*/
- }
-
- public:
- /**
- * Fast copy constructor, simply assigns shared_ptr.
- */
- NoiseModel(const NoiseModel& noiseModel): base_(noiseModel.base_) { /*std::cout << "Assigning pointer" << std::endl;*/ }
-
- /**
- * Constructor that creates a fast-copyable NoiseModel class by cloning
- * a non-pointer NoiseModelBase. The type is retained and can be retrieved
- * using a dynamic_cast.
- */
- template
- NoiseModel(const T& noiseModel): base_(noiseModel.clone()) {}
-
- /**
- * Cast to boost::shared_ptr to retrieve a pointer to the
- * NoiseModelBase type. Can be used with dynamic_pointer_cast to retrieve
- * the type at runtime.
- * E.g.: dynamic_pointer_cast(noiseModel).
- */
- operator const boost::shared_ptr () const {
- return base_; }
-
- /**
- * Call the NoiseModelBase virtual whiten function
- */
- Vector whiten(const Vector& v) const { return base_->whiten(v); }
-
- /**
- * Call the NoiseModelBase virtual unwhiten function
- */
- Vector unwhiten(const Vector& v) const { return base_->unwhiten(v); }
-
- template friend boost::shared_ptr dynamic_pointer_cast(const NoiseModel& p);
- };
-
- template
- boost::shared_ptr dynamic_pointer_cast(const NoiseModel& p) {
- return boost::dynamic_pointer_cast(p.base_); }
-
-
-
- /*****************************************************************************
- * An isotropic noise model assigns the same sigma to each vector element.
+ /**
+ * An isotropic noise model corresponds to a scaled diagonal covariance
* This class has no public constructors. Instead, use either either the
* Sigma or Variance class.
*/
- class Isotropic : public NoiseModelBase {
+ class Isotropic : public NoiseModel {
protected:
double sigma_;
double invsigma_;
@@ -121,125 +46,48 @@ namespace gtsam {
sigma_(isotropic.sigma_), invsigma_(isotropic.invsigma_) {}
public:
- /**
- * Whiten error vector by dividing by sigma
- */
- virtual Vector whiten(const Vector& v) const { return v * invsigma_; }
-
- /**
- * Unwhiten error vector by multiplying by sigma
- */
- virtual Vector unwhiten(const Vector& v) const { return v * sigma_; }
-
- /**
- * Clone is used to duplicate object while retaining type
- */
- boost::shared_ptr clone() const {
- /*cout << "Cloning Isotropic" << endl;*/
- return boost::shared_ptr(new Isotropic(*this)); }
+ Vector whiten(const Vector& v) const;
+ Vector unwhiten(const Vector& v) const;
};
-
- /*****************************************************************************
- * A diagonal noise model implements a diagonal covariance matrix, with the
- * elements of the diagonal specified in a Vector. This class has no public
- * constructors, instead, use either the Sigmas or Variances class.
- */
- class Diagonal : public NoiseModelBase {
- protected:
- Vector sigmas_;
- Vector invsigmas_;
-
- Diagonal() {}
- Diagonal(const Vector& sigmas): sigmas_(sigmas), invsigmas_(1.0 / sigmas) {}
- Diagonal(const Diagonal& d): sigmas_(d.sigmas_), invsigmas_(d.invsigmas_) {}
-
- public:
- /**
- * Whiten error vector by dividing by sigmas
- */
- virtual Vector whiten(const Vector& v) const { return emul(v, invsigmas_); }
-
- /**
- * Unwhiten error vector by multiplying by sigmas
- */
- virtual Vector unwhiten(const Vector& v) const { return emul(v, sigmas_); }
-
- /**
- * Clone is used to duplicate object while retaining type
- */
- boost::shared_ptr clone() const {
- /*cout << "Cloning Isotropic" << endl;*/
- return boost::shared_ptr(new Diagonal(*this)); }
- };
-
-
- /*****************************************************************************
- * A full covariance noise model.
- */
- class FullCovariance : public NoiseModelBase {
- protected:
- Matrix sqrt_covariance_;
- Matrix sqrt_inv_covariance_;
-
- public:
- FullCovariance(const Matrix& covariance):
- sqrt_covariance_(square_root_positive(covariance)),
- sqrt_inv_covariance_(inverse_square_root(covariance)) {}
-
- FullCovariance(const FullCovariance& c):
- sqrt_covariance_(c.sqrt_covariance_), sqrt_inv_covariance_(c.sqrt_inv_covariance_) {}
-
- /**
- * Whiten error vector by dividing by sigmas
- */
- virtual Vector whiten(const Vector& v) const { return sqrt_inv_covariance_ * v; }
-
- /**
- * Unwhiten error vector by multiplying by sigmas
- */
- virtual Vector unwhiten(const Vector& v) const { return sqrt_covariance_ * v; }
-
- /**
- * Clone is used to duplicate object while retaining type
- */
- boost::shared_ptr clone() const {
- /*cout << "Cloning Isotropic" << endl;*/
- return boost::shared_ptr(new FullCovariance(*this)); }
- };
-
-
-
- /*****************************************************************************
- * An isotropic noise model using sigma, the noise standard
- * deviation.
+ /**
+ * An isotropic noise model using sigma, the standard deviation.
*/
class Sigma : public Isotropic {
public:
- Sigma(const Sigma& isotropic): Isotropic(isotropic) { /*cout << "Constructing Sigma from Sigma" << endl;*/ }
-
- Sigma(double sigma): Isotropic(sigma) { /*cout << "Constructing Sigma from double" << endl;*/ }
-
- boost::shared_ptr clone() const {
- return boost::shared_ptr(new Sigma(*this)); }
+ Sigma(const Sigma& isotropic): Isotropic(isotropic) {}
+ Sigma(double sigma): Isotropic(sigma) {}
};
-
- /*****************************************************************************
+ /**
* An isotropic noise model using the noise variance = sigma^2.
*/
class Variance : public Isotropic {
public:
Variance(const Variance& v): Isotropic(v) {}
-
Variance(double variance): Isotropic(sqrt(variance)) {}
-
- boost::shared_ptr clone() const {
- return boost::shared_ptr(new Variance(*this)); }
};
+ /**
+ * A diagonal noise model implements a diagonal covariance matrix, with the
+ * elements of the diagonal specified in a Vector. This class has no public
+ * constructors, instead, use either the Sigmas or Variances class.
+ */
+ class Diagonal : public NoiseModel {
+ protected:
+ Vector sigmas_;
+ Vector invsigmas_;
- /*****************************************************************************
+ Diagonal() {}
+ Diagonal(const Vector& sigmas);
+ Diagonal(const Diagonal& d);
+
+ public:
+ Vector whiten(const Vector& v) const;
+ Vector unwhiten(const Vector& v) const;
+ };
+
+ /**
* A diagonal noise model created by specifying a Vector of sigmas, i.e.
* standard devations, i.e. the diagonal of the square root covariance
* matrix.
@@ -247,29 +95,34 @@ namespace gtsam {
class Sigmas : public Diagonal {
public:
Sigmas(const Sigmas& s): Diagonal(s) {}
-
Sigmas(const Vector& sigmas): Diagonal(sigmas) {}
-
- boost::shared_ptr clone() const {
- return boost::shared_ptr(new Sigmas(*this)); }
};
-
- /*****************************************************************************
+ /**
* A diagonal noise model created by specifying a Vector of variances, i.e.
* i.e. the diagonal of the covariance matrix.
*/
class Variances : public Diagonal {
public:
Variances(const Variances& s): Diagonal(s) {}
+ Variances(const Vector& variances);
+ };
- Variances(const Vector& variances) {
- std::transform(variances.begin(), variances.end(), sigmas_.begin(), sqrt);
- invsigmas_ = 1.0 / sigmas_;
- }
+ /**
+ * A full covariance noise model.
+ */
+ class FullCovariance : public NoiseModel {
+ protected:
+ Matrix sqrt_covariance_;
+ Matrix sqrt_inv_covariance_;
- boost::shared_ptr clone() const {
- return boost::shared_ptr(new Variances(*this)); }
+ public:
+
+ FullCovariance(const Matrix& covariance);
+ FullCovariance(const FullCovariance& c);
+
+ Vector whiten(const Vector& v) const;
+ Vector unwhiten(const Vector& v) const;
};
}
diff --git a/cpp/testMatrix.cpp b/cpp/testMatrix.cpp
index 281c77576..9357c2e7c 100644
--- a/cpp/testMatrix.cpp
+++ b/cpp/testMatrix.cpp
@@ -606,24 +606,24 @@ TEST( matrix, inverse_square_root )
}
/* ************************************************************************* */
-//TEST( matrix, square_root_positive )
-//{
-// Matrix cov = Matrix_(3,3,
-// 4.25, 1.5, 0.0,
-// 1.5, 2.0, 0.0,
-// 0.0, 0.0, 1.0);
-//
-// Matrix expected = Matrix_(3,3,
-// -2.0,-1.0, 0.0,
-// -0.5, 1.0, 0.0,
-// 0.0, 0.0, 1.0);
-//
-// Matrix actual = square_root_positive(cov);
-//
-// CHECK(assert_equal(expected, actual));
-// CHECK(assert_equal(cov, prod(trans(actual),actual)));
-//}
+TEST( matrix, square_root_positive )
+{
+ Matrix cov = Matrix_(3,3,
+ 4.0, 0.0, 0.0,
+ 0.0, 4.0, 0.0,
+ 0.0, 0.0, 100.0
+ );
+ Matrix expected = Matrix_(3,3,
+ 2.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0,
+ 0.0, 0.0, 10.0
+ );
+
+ Matrix actual = square_root_positive(cov);
+ CHECK(assert_equal(expected, actual));
+ CHECK(assert_equal(cov, prod(trans(actual),actual)));
+}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
diff --git a/cpp/testNoiseModel.cpp b/cpp/testNoiseModel.cpp
index 8a80c6001..9f40dca99 100644
--- a/cpp/testNoiseModel.cpp
+++ b/cpp/testNoiseModel.cpp
@@ -2,7 +2,8 @@
* testNoiseModel.cpp
*
* Created on: Jan 13, 2010
- * Author: richard
+ * Author: Richard Roberts
+ * Author: Frank Dellaert
*/
#include
@@ -12,46 +13,43 @@
#include "NoiseModel.h"
using namespace std;
-using namespace boost;
using namespace gtsam;
-class TakesNoiseModel {
-public:
- NoiseModel noiseModel_;
-public:
- //template
- TakesNoiseModel(const NoiseModel& noiseModel): noiseModel_(noiseModel) {}
-};
-
-
-TEST(NoiseModel, sharedptr)
+/* ************************************************************************* */
+TEST(NoiseModel, constructors)
{
-// TakesNoiseModel tnm1(Sigma(1.0));
-// cout << endl;
-// TakesNoiseModel tnm2(tnm1.noiseModel_);
-//
-// if(dynamic_pointer_cast(tnm1.noiseModel_))
-// cout << "tnm1 has a Sigma!" << endl;
-// if(dynamic_pointer_cast(tnm1.noiseModel_))
-// cout << "tnm1 has a Variance!" << endl;
-// if(dynamic_pointer_cast(tnm1.noiseModel_))
-// cout << "tnm1 has an Isotropic!" << endl;
-// if(dynamic_pointer_cast(tnm1.noiseModel_))
-// cout << "tnm1 has a NoiseModelBase!" << endl;
-//
-// if(dynamic_pointer_cast(tnm2.noiseModel_))
-// cout << "tnm2 has a Sigma!" << endl;
-// if(dynamic_pointer_cast(tnm2.noiseModel_))
-// cout << "tnm2 has a Variance!" << endl;
-// if(dynamic_pointer_cast(tnm2.noiseModel_))
-// cout << "tnm2 has an Isotropic!" << endl;
-// if(dynamic_pointer_cast(tnm2.noiseModel_))
-// cout << "tnm2 has a NoiseModelBase!" << endl;
+ double sigma = 2, var = sigma*sigma;
+ Vector whitened = Vector_(3,5.0,10.0,15.0);
+ Vector unwhitened = Vector_(3,10.0,20.0,30.0);
+
+ // Construct noise models
+ Sigma m1(sigma);
+ Variance m2(var);
+ Sigmas m3(Vector_(3, sigma, sigma, sigma));
+ Variances m4(Vector_(3, var, var, var));
+ FullCovariance m5(Matrix_(3, 3,
+ var, 0.0, 0.0,
+ 0.0, var, 0.0,
+ 0.0, 0.0, var));
+
+ // test whiten
+ CHECK(assert_equal(whitened,m1.whiten(unwhitened)));
+ CHECK(assert_equal(whitened,m2.whiten(unwhitened)));
+ CHECK(assert_equal(whitened,m3.whiten(unwhitened)));
+ CHECK(assert_equal(whitened,m4.whiten(unwhitened)));
+ CHECK(assert_equal(whitened,m5.whiten(unwhitened)));
+
+ // test unwhiten
+ CHECK(assert_equal(unwhitened,m1.unwhiten(whitened)));
+ CHECK(assert_equal(unwhitened,m2.unwhiten(whitened)));
+ CHECK(assert_equal(unwhitened,m3.unwhiten(whitened)));
+ CHECK(assert_equal(unwhitened,m4.unwhiten(whitened)));
+ CHECK(assert_equal(unwhitened,m5.unwhiten(whitened)));
}
/* ************************************************************************* */
int main() {
- TestResult tr;
- return TestRegistry::runAllTests(tr);
+ TestResult tr;
+ return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */