2012-07-11 02:15:51 +08:00
|
|
|
/**
|
|
|
|
|
* @file LinearContainerFactor.cpp
|
|
|
|
|
*
|
|
|
|
|
* @date Jul 6, 2012
|
|
|
|
|
* @author Alex Cunningham
|
|
|
|
|
*/
|
|
|
|
|
|
2012-11-22 03:41:24 +08:00
|
|
|
#include <gtsam/nonlinear/LinearContainerFactor.h>
|
2013-08-02 05:57:33 +08:00
|
|
|
#include <gtsam/linear/HessianFactor.h>
|
2013-08-02 05:57:43 +08:00
|
|
|
#include <gtsam/linear/JacobianFactor.h>
|
2013-08-02 05:57:33 +08:00
|
|
|
#include <gtsam/linear/VectorValues.h>
|
2013-08-09 02:33:51 +08:00
|
|
|
#include <gtsam/linear/GaussianFactorGraph.h>
|
2012-07-11 02:15:51 +08:00
|
|
|
|
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
|
|
|
|
|
namespace gtsam {
|
|
|
|
|
|
2012-08-27 09:11:37 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
void LinearContainerFactor::initializeLinearizationPoint(const Values& linearizationPoint) {
|
2012-10-02 22:40:07 +08:00
|
|
|
if (!linearizationPoint.empty()) {
|
|
|
|
|
linearizationPoint_ = Values();
|
|
|
|
|
BOOST_FOREACH(const gtsam::Key& key, this->keys()) {
|
|
|
|
|
linearizationPoint_->insert(key, linearizationPoint.at(key));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
linearizationPoint_ = boost::none;
|
|
|
|
|
}
|
2012-08-27 09:11:37 +08:00
|
|
|
}
|
|
|
|
|
|
2012-09-04 01:22:09 +08:00
|
|
|
/* ************************************************************************* */
|
2013-08-02 05:57:33 +08:00
|
|
|
LinearContainerFactor::LinearContainerFactor(const GaussianFactor::shared_ptr& factor,
|
2012-10-02 22:40:07 +08:00
|
|
|
const boost::optional<Values>& linearizationPoint)
|
2013-08-09 02:33:51 +08:00
|
|
|
: NonlinearFactor(factor->keys()), factor_(factor), linearizationPoint_(linearizationPoint) {
|
2012-09-04 01:22:09 +08:00
|
|
|
}
|
|
|
|
|
|
2012-07-11 02:15:51 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
LinearContainerFactor::LinearContainerFactor(
|
2013-08-02 05:57:33 +08:00
|
|
|
const JacobianFactor& factor, const Values& linearizationPoint)
|
2013-08-09 02:33:51 +08:00
|
|
|
: NonlinearFactor(factor.keys()), factor_(factor.clone()) {
|
2012-10-02 22:40:07 +08:00
|
|
|
initializeLinearizationPoint(linearizationPoint);
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
LinearContainerFactor::LinearContainerFactor(
|
2013-08-02 05:57:33 +08:00
|
|
|
const HessianFactor& factor, const Values& linearizationPoint)
|
2013-08-09 02:33:51 +08:00
|
|
|
: NonlinearFactor(factor.keys()), factor_(factor.clone()) {
|
2012-10-02 22:40:07 +08:00
|
|
|
initializeLinearizationPoint(linearizationPoint);
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
LinearContainerFactor::LinearContainerFactor(
|
2013-08-02 05:57:33 +08:00
|
|
|
const GaussianFactor::shared_ptr& factor, const Values& linearizationPoint)
|
2013-08-09 02:33:51 +08:00
|
|
|
: NonlinearFactor(factor->keys()), factor_(factor->clone()) {
|
2012-10-02 22:40:07 +08:00
|
|
|
initializeLinearizationPoint(linearizationPoint);
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
void LinearContainerFactor::print(const std::string& s, const KeyFormatter& keyFormatter) const {
|
2012-10-02 22:40:07 +08:00
|
|
|
Base::print(s+"LinearContainerFactor", keyFormatter);
|
|
|
|
|
if (factor_)
|
|
|
|
|
factor_->print(" Stored Factor", keyFormatter);
|
|
|
|
|
if (linearizationPoint_)
|
|
|
|
|
linearizationPoint_->print(" LinearizationPoint", keyFormatter);
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
bool LinearContainerFactor::equals(const NonlinearFactor& f, double tol) const {
|
2012-10-02 22:40:07 +08:00
|
|
|
const LinearContainerFactor* jcf = dynamic_cast<const LinearContainerFactor*>(&f);
|
|
|
|
|
if (!jcf || !factor_->equals(*jcf->factor_, tol) || !NonlinearFactor::equals(f))
|
|
|
|
|
return false;
|
|
|
|
|
if (!linearizationPoint_ && !jcf->linearizationPoint_)
|
|
|
|
|
return true;
|
|
|
|
|
if (linearizationPoint_ && jcf->linearizationPoint_)
|
|
|
|
|
return linearizationPoint_->equals(*jcf->linearizationPoint_, tol);
|
|
|
|
|
return false;
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
double LinearContainerFactor::error(const Values& c) const {
|
2012-10-02 22:40:07 +08:00
|
|
|
if (!linearizationPoint_)
|
|
|
|
|
return 0;
|
2012-08-27 09:11:37 +08:00
|
|
|
|
2012-11-22 03:02:13 +08:00
|
|
|
// Extract subset of values for comparison
|
2012-10-02 22:40:07 +08:00
|
|
|
Values csub;
|
|
|
|
|
BOOST_FOREACH(const gtsam::Key& key, keys())
|
|
|
|
|
csub.insert(key, c.at(key));
|
2012-08-27 09:11:37 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
// create dummy ordering for evaluation
|
2013-08-02 05:57:33 +08:00
|
|
|
VectorValues delta = linearizationPoint_->localCoordinates(csub);
|
2012-08-27 09:11:37 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
// compute error
|
|
|
|
|
double error = factor_->error(delta);
|
2012-08-27 09:11:37 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
return error;
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
size_t LinearContainerFactor::dim() const {
|
2012-10-02 22:40:07 +08:00
|
|
|
if (isJacobian())
|
|
|
|
|
return toJacobian()->get_model()->dim();
|
|
|
|
|
else
|
|
|
|
|
return 1; // Hessians don't have true dimension
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2013-08-02 05:57:33 +08:00
|
|
|
GaussianFactor::shared_ptr LinearContainerFactor::linearize(const Values& c) const {
|
2012-11-22 03:02:13 +08:00
|
|
|
if (!hasLinearizationPoint())
|
2013-08-02 05:57:33 +08:00
|
|
|
return factor_;
|
2012-11-22 03:02:13 +08:00
|
|
|
|
|
|
|
|
// Extract subset of values
|
|
|
|
|
Values subsetC;
|
|
|
|
|
BOOST_FOREACH(const gtsam::Key& key, this->keys())
|
|
|
|
|
subsetC.insert(key, c.at(key));
|
|
|
|
|
|
|
|
|
|
// Determine delta between linearization points using new ordering
|
2013-08-02 05:57:33 +08:00
|
|
|
VectorValues delta = linearizationPoint_->localCoordinates(subsetC);
|
2012-11-22 03:02:13 +08:00
|
|
|
|
|
|
|
|
// clone and reorder linear factor to final ordering
|
2013-08-02 05:57:33 +08:00
|
|
|
GaussianFactor::shared_ptr linFactor = factor_->clone();
|
2012-11-22 03:02:13 +08:00
|
|
|
if (isJacobian()) {
|
2013-08-02 05:57:33 +08:00
|
|
|
JacobianFactor::shared_ptr jacFactor = boost::dynamic_pointer_cast<JacobianFactor>(linFactor);
|
2013-04-16 22:58:09 +08:00
|
|
|
jacFactor->getb() = -jacFactor->unweighted_error(delta);
|
2012-11-22 03:02:13 +08:00
|
|
|
} else {
|
2013-08-02 05:57:33 +08:00
|
|
|
HessianFactor::shared_ptr hesFactor = boost::dynamic_pointer_cast<HessianFactor>(linFactor);
|
2012-11-22 03:02:13 +08:00
|
|
|
size_t dim = hesFactor->linearTerm().size();
|
2013-08-02 05:57:33 +08:00
|
|
|
Eigen::Block<HessianFactor::Block> Gview = hesFactor->info().block(0, 0, dim, dim);
|
2013-08-17 03:42:25 +08:00
|
|
|
Vector deltaVector = delta.vector(keys());
|
2012-12-18 22:21:02 +08:00
|
|
|
Vector G_delta = Gview.selfadjointView<Eigen::Upper>() * deltaVector;
|
2013-04-16 22:58:09 +08:00
|
|
|
hesFactor->constantTerm() += deltaVector.dot(G_delta) - 2.0 * deltaVector.dot(hesFactor->linearTerm());
|
|
|
|
|
hesFactor->linearTerm() -= G_delta;
|
2012-11-22 03:02:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return linFactor;
|
2012-08-22 02:48:04 +08:00
|
|
|
}
|
|
|
|
|
|
2012-07-11 02:15:51 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
bool LinearContainerFactor::isJacobian() const {
|
2013-08-13 02:21:33 +08:00
|
|
|
return dynamic_cast<const JacobianFactor*>(factor_.get()) != 0;
|
2012-11-22 03:02:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
bool LinearContainerFactor::isHessian() const {
|
2013-08-13 02:21:33 +08:00
|
|
|
return dynamic_cast<const HessianFactor*>(factor_.get()) != 0;
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2013-08-02 05:57:33 +08:00
|
|
|
JacobianFactor::shared_ptr LinearContainerFactor::toJacobian() const {
|
|
|
|
|
return boost::dynamic_pointer_cast<JacobianFactor>(factor_);
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2013-08-02 05:57:33 +08:00
|
|
|
HessianFactor::shared_ptr LinearContainerFactor::toHessian() const {
|
|
|
|
|
return boost::dynamic_pointer_cast<HessianFactor>(factor_);
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2013-08-02 05:57:33 +08:00
|
|
|
GaussianFactor::shared_ptr LinearContainerFactor::negateToGaussian() const {
|
|
|
|
|
GaussianFactor::shared_ptr result = factor_->negate();
|
2013-08-09 02:33:51 +08:00
|
|
|
return result;
|
2012-07-11 02:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
2012-08-21 02:28:19 +08:00
|
|
|
/* ************************************************************************* */
|
2013-08-02 05:57:33 +08:00
|
|
|
NonlinearFactor::shared_ptr LinearContainerFactor::negateToNonlinear() const {
|
|
|
|
|
GaussianFactor::shared_ptr antifactor = factor_->negate(); // already has keys in place
|
2013-08-09 02:33:51 +08:00
|
|
|
return NonlinearFactor::shared_ptr(new LinearContainerFactor(antifactor, linearizationPoint_));
|
2012-08-21 02:28:19 +08:00
|
|
|
}
|
|
|
|
|
|
2012-08-22 02:48:04 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
NonlinearFactorGraph LinearContainerFactor::convertLinearGraph(
|
2013-08-02 05:57:33 +08:00
|
|
|
const GaussianFactorGraph& linear_graph, const Values& linearizationPoint)
|
|
|
|
|
{
|
2012-10-02 22:40:07 +08:00
|
|
|
NonlinearFactorGraph result;
|
2013-08-02 05:57:33 +08:00
|
|
|
BOOST_FOREACH(const GaussianFactor::shared_ptr& f, linear_graph)
|
2012-10-02 22:40:07 +08:00
|
|
|
if (f)
|
|
|
|
|
result.push_back(NonlinearFactorGraph::sharedFactor(
|
2013-08-02 05:57:33 +08:00
|
|
|
new LinearContainerFactor(f, linearizationPoint)));
|
2012-10-02 22:40:07 +08:00
|
|
|
return result;
|
2012-08-22 02:48:04 +08:00
|
|
|
}
|
|
|
|
|
|
2012-07-11 02:15:51 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
} // \namespace gtsam
|
|
|
|
|
|