Added computeInformation function to GaussianFactor to properly compute information matrix including noise models, and using it to fix bug in Marginals where noise model was not being accounted for (only affects when hard constraints are used)

release/4.3a0
Richard Roberts 2012-05-23 20:56:22 +00:00
parent 5a3316af9e
commit 6e2312294c
6 changed files with 57 additions and 15 deletions

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include <gtsam/base/Matrix.h>
#include <gtsam/inference/IndexFactor.h> #include <gtsam/inference/IndexFactor.h>
#include <string> #include <string>
@ -88,6 +89,16 @@ namespace gtsam {
/** Return the dimension of the variable pointed to by the given key iterator */ /** Return the dimension of the variable pointed to by the given key iterator */
virtual size_t getDim(const_iterator variable) const = 0; virtual size_t getDim(const_iterator variable) const = 0;
/** Return the augmented information matrix represented by this GaussianFactor.
* The augmented information matrix contains the information matrix with an
* additional column holding the information vector, and an additional row
* holding the transpose of the information vector. The lower-right entry
* contains the constant error term (when \f$ \delta x = 0 \f$). The
* augmented information matrix is described in more detail in HessianFactor,
* which in fact stores an augmented information matrix.
*/
virtual Matrix computeInformation() const = 0;
/** Clone a factor (make a deep copy) */ /** Clone a factor (make a deep copy) */
virtual GaussianFactor::shared_ptr clone() const = 0; virtual GaussianFactor::shared_ptr clone() const = 0;

View File

@ -324,6 +324,11 @@ HessianFactor::constColumn HessianFactor::linearTerm() const {
return info_.rangeColumn(0, this->size(), this->size(), 0); return info_.rangeColumn(0, this->size(), this->size(), 0);
} }
/* ************************************************************************* */
Matrix HessianFactor::computeInformation() const {
return info_.full().selfadjointView<Eigen::Upper>();
}
/* ************************************************************************* */ /* ************************************************************************* */
double HessianFactor::error(const VectorValues& c) const { double HessianFactor::error(const VectorValues& c) const {
// error 0.5*(f - 2*x'*g + x'*G*x) // error 0.5*(f - 2*x'*g + x'*G*x)

View File

@ -270,6 +270,23 @@ namespace gtsam {
* @return The linear term \f$ g \f$ */ * @return The linear term \f$ g \f$ */
constColumn linearTerm() const; constColumn linearTerm() const;
/** Return the augmented information matrix represented by this GaussianFactor.
* The augmented information matrix contains the information matrix with an
* additional column holding the information vector, and an additional row
* holding the transpose of the information vector. The lower-right entry
* contains the constant error term (when \f$ \delta x = 0 \f$). The
* augmented information matrix is described in more detail in HessianFactor,
* which in fact stores an augmented information matrix.
*
* For HessianFactor, this is the same as info() except that this function
* returns a complete symmetric matrix whereas info() returns a matrix where
* only the upper triangle is valid, but should be interpreted as symmetric.
* This is because info() returns only a reference to the internal
* representation of the augmented information matrix, which stores only the
* upper triangle.
*/
virtual Matrix computeInformation() const;
// Friend unit test classes // Friend unit test classes
friend class ::ConversionConstructorHessianFactorTest; friend class ::ConversionConstructorHessianFactorTest;
friend class ::Constructor1HessianFactorTest; friend class ::Constructor1HessianFactorTest;

View File

@ -271,6 +271,12 @@ namespace gtsam {
return 0.5 * weighted.dot(weighted); return 0.5 * weighted.dot(weighted);
} }
/* ************************************************************************* */
Matrix JacobianFactor::computeInformation() const {
Matrix AbWhitened = Ab_.full();
model_->WhitenInPlace(AbWhitened);
return AbWhitened.transpose() * AbWhitened;
}
/* ************************************************************************* */ /* ************************************************************************* */
Vector JacobianFactor::operator*(const VectorValues& x) const { Vector JacobianFactor::operator*(const VectorValues& x) const {

View File

@ -155,6 +155,16 @@ namespace gtsam {
Vector error_vector(const VectorValues& c) const; /** (A*x-b)/sigma */ Vector error_vector(const VectorValues& c) const; /** (A*x-b)/sigma */
virtual double error(const VectorValues& c) const; /** 0.5*(A*x-b)'*D*(A*x-b) */ virtual double error(const VectorValues& c) const; /** 0.5*(A*x-b)'*D*(A*x-b) */
/** Return the augmented information matrix represented by this GaussianFactor.
* The augmented information matrix contains the information matrix with an
* additional column holding the information vector, and an additional row
* holding the transpose of the information vector. The lower-right entry
* contains the constant error term (when \f$ \delta x = 0 \f$). The
* augmented information matrix is described in more detail in HessianFactor,
* which in fact stores an augmented information matrix.
*/
virtual Matrix computeInformation() const;
/** Check if the factor contains no information, i.e. zero rows. This does /** Check if the factor contains no information, i.e. zero rows. This does
* not necessarily mean that the factor involves no variables (to check for * not necessarily mean that the factor involves no variables (to check for
* involving no variables use keys().empty()). * involving no variables use keys().empty()).

View File

@ -69,16 +69,9 @@ Matrix Marginals::marginalInformation(Key variable) const {
marginalFactor = bayesTree_.marginalFactor(index, EliminateQR); marginalFactor = bayesTree_.marginalFactor(index, EliminateQR);
// Get information matrix (only store upper-right triangle) // Get information matrix (only store upper-right triangle)
if(typeid(*marginalFactor) == typeid(JacobianFactor)) { Matrix info = marginalFactor->computeInformation();
JacobianFactor::constABlock A = static_cast<const JacobianFactor&>(*marginalFactor).getA(); const int dim = info.rows() - 1;
return A.transpose() * A; // Compute A'A return info.topLeftCorner(dim,dim); // Take the non-augmented part of the information matrix
} else if(typeid(*marginalFactor) == typeid(HessianFactor)) {
const HessianFactor& hessian = static_cast<const HessianFactor&>(*marginalFactor);
const size_t dim = hessian.getDim(hessian.begin());
return hessian.info().topLeftCorner(dim,dim).selfadjointView<Eigen::Upper>(); // Take the non-augmented part of the information matrix
} else {
throw runtime_error("Internal error: Marginals::marginalInformation expected either a JacobianFactor or HessianFactor");
}
} }
/* ************************************************************************* */ /* ************************************************************************* */