gtsam/gtsam_unstable/nonlinear/LinearizedFactor.cpp

148 lines
5.1 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 LinearizedFactor.cpp
* @brief A dummy factor that allows a linear factor to act as a nonlinear factor
* @author Alex Cunningham
*/
#include <iostream>
#include <boost/foreach.hpp>
#include <gtsam_unstable/nonlinear/LinearizedFactor.h>
namespace gtsam {
using namespace std;
/* ************************************************************************* */
LinearizedFactor::LinearizedFactor(JacobianFactor::shared_ptr lin_factor,
const KeyLookup& decoder, const Values& lin_points)
: Base(lin_factor->get_model()), b_(lin_factor->getb()), model_(lin_factor->get_model()) {
BOOST_FOREACH(const Index& idx, *lin_factor) {
// find full symbol
KeyLookup::const_iterator decode_it = decoder.find(idx);
if (decode_it == decoder.end())
throw runtime_error("LinearizedFactor: could not find index in decoder!");
Key key(decode_it->second);
// extract linearization point
assert(lin_points.exists(key));
this->lin_points_.insert(key, lin_points.at(key)); // NOTE: will not overwrite
// extract Jacobian
Matrix A = lin_factor->getA(lin_factor->find(idx));
this->matrices_.insert(std::make_pair(key, A));
// store keys
this->keys_.push_back(key);
}
}
/* ************************************************************************* */
LinearizedFactor::LinearizedFactor(JacobianFactor::shared_ptr lin_factor,
const Ordering& ordering, const Values& lin_points)
: Base(lin_factor->get_model()), b_(lin_factor->getb()), model_(lin_factor->get_model()) {
const KeyLookup decoder = ordering.invert();
BOOST_FOREACH(const Index& idx, *lin_factor) {
// find full symbol
KeyLookup::const_iterator decode_it = decoder.find(idx);
if (decode_it == decoder.end())
throw runtime_error("LinearizedFactor: could not find index in decoder!");
Key key(decode_it->second);
// extract linearization point
assert(lin_points.exists(key));
this->lin_points_.insert(key, lin_points.at(key)); // NOTE: will not overwrite
// extract Jacobian
Matrix A = lin_factor->getA(lin_factor->find(idx));
this->matrices_.insert(std::make_pair(key, A));
// store keys
this->keys_.push_back(key);
}
}
/* ************************************************************************* */
Vector LinearizedFactor::unwhitenedError(const Values& c,
boost::optional<std::vector<Matrix>&> H) const {
// extract the points in the new values
Vector ret = - b_;
if (H) H->resize(this->size());
size_t i=0;
BOOST_FOREACH(Key key, this->keys()) {
const Value& newPt = c.at(key);
const Value& linPt = lin_points_.at(key);
Vector d = linPt.localCoordinates_(newPt);
const Matrix& A = matrices_.at(key);
ret += A * d;
if (H) (*H)[i++] = A;
}
return ret;
}
/* ************************************************************************* */
boost::shared_ptr<GaussianFactor>
LinearizedFactor::linearize(const Values& c, const Ordering& ordering) const {
// sort by varid - only known at linearization time
typedef std::map<Index, Matrix> VarMatrixMap;
VarMatrixMap sorting_terms;
BOOST_FOREACH(const KeyMatrixMap::value_type& p, matrices_)
sorting_terms.insert(std::make_pair(ordering[p.first], p.second));
// move into terms
std::vector<std::pair<Index, Matrix> > terms;
BOOST_FOREACH(const VarMatrixMap::value_type& p, sorting_terms)
terms.push_back(p);
// compute rhs: adjust current by whitened update
Vector b = unwhitenedError(c) + b_; // remove original b
this->noiseModel_->whitenInPlace(b);
return boost::shared_ptr<GaussianFactor>(new JacobianFactor(terms, b - b_, model_));
}
/* ************************************************************************* */
void LinearizedFactor::print(const std::string& s, const KeyFormatter& keyFormatter) const {
this->noiseModel_->print(s + std::string(" model"));
BOOST_FOREACH(const KeyMatrixMap::value_type& p, matrices_) {
gtsam::print(p.second, keyFormatter(p.first));
}
gtsam::print(b_, std::string("b"));
std::cout << " nonlinear keys: ";
BOOST_FOREACH(const Key& key, this->keys())
cout << keyFormatter(key) << " ";
lin_points_.print("Linearization Point");
}
/* ************************************************************************* */
bool LinearizedFactor::equals(const LinearizedFactor& other, double tol) const {
if (!Base::equals(other, tol)
|| !lin_points_.equals(other.lin_points_, tol)
|| !equal_with_abs_tol(b_, other.b_, tol)
|| !model_->equals(*other.model_, tol)
|| matrices_.size() != other.matrices_.size())
return false;
KeyMatrixMap::const_iterator map1 = matrices_.begin(), map2 = other.matrices_.begin();
for (; map1 != matrices_.end(), map2 != other.matrices_.end(); ++map1, ++map2)
if ((map1->first != map2->first) || !equal_with_abs_tol(map1->second, map2->second, tol))
return false;
return true;
}
} // \namespace gtsam