241 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
| /**
 | |
|  * @file LinearContainerFactor.cpp
 | |
|  *
 | |
|  * @date Jul 6, 2012
 | |
|  * @author Alex Cunningham
 | |
|  */
 | |
| 
 | |
| #include <gtsam_unstable/nonlinear/LinearContainerFactor.h>
 | |
| 
 | |
| #include <boost/foreach.hpp>
 | |
| 
 | |
| namespace gtsam {
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| void LinearContainerFactor::rekeyFactor(const Ordering& ordering) {
 | |
| 	Ordering::InvertedMap invOrdering = ordering.invert(); // TODO: inefficient - make more selective ordering invert
 | |
| 	rekeyFactor(invOrdering);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| void LinearContainerFactor::rekeyFactor(const Ordering::InvertedMap& invOrdering) {
 | |
| 	BOOST_FOREACH(Index& idx, factor_->keys()) {
 | |
| 		Key fullKey = invOrdering.find(idx)->second;
 | |
| 		idx = fullKey;
 | |
| 		keys_.push_back(fullKey);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| void LinearContainerFactor::initializeLinearizationPoint(const Values& linearizationPoint) {
 | |
| 	if (!linearizationPoint.empty()) {
 | |
| 		linearizationPoint_ = Values();
 | |
| 		BOOST_FOREACH(const gtsam::Key& key, this->keys()) {
 | |
| 			linearizationPoint_->insert(key, linearizationPoint.at(key));
 | |
| 		}
 | |
| 	} else {
 | |
| 		linearizationPoint_ = boost::none;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(const GaussianFactor::shared_ptr& factor,
 | |
| 		const boost::optional<Values>& linearizationPoint)
 | |
| : factor_(factor), linearizationPoint_(linearizationPoint) {
 | |
| 	// Extract keys stashed in linear factor
 | |
| 	BOOST_FOREACH(const Index& idx, factor_->keys())
 | |
| 		keys_.push_back(idx);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(
 | |
| 		const JacobianFactor& factor, const Ordering& ordering,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor.clone()) {
 | |
| 	rekeyFactor(ordering);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(
 | |
| 		const HessianFactor& factor, const Ordering& ordering,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor.clone()) {
 | |
| 	rekeyFactor(ordering);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(
 | |
| 		const GaussianFactor::shared_ptr& factor, const Ordering& ordering,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor->clone()) {
 | |
| 	rekeyFactor(ordering);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(
 | |
| 		const GaussianFactor::shared_ptr& factor,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor->clone())
 | |
| {
 | |
| 	// Extract keys stashed in linear factor
 | |
| 	BOOST_FOREACH(const Index& idx, factor_->keys())
 | |
| 		keys_.push_back(idx);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(const JacobianFactor& factor,
 | |
| 		const Ordering::InvertedMap& inverted_ordering,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor.clone()) {
 | |
| 	rekeyFactor(inverted_ordering);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(const HessianFactor& factor,
 | |
| 		const Ordering::InvertedMap& inverted_ordering,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor.clone()) {
 | |
| 	rekeyFactor(inverted_ordering);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| LinearContainerFactor::LinearContainerFactor(
 | |
| 		const GaussianFactor::shared_ptr& factor,
 | |
| 		const Ordering::InvertedMap& ordering,
 | |
| 		const Values& linearizationPoint)
 | |
| : factor_(factor->clone()) {
 | |
| 	rekeyFactor(ordering);
 | |
| 	initializeLinearizationPoint(linearizationPoint);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| void LinearContainerFactor::print(const std::string& s, const KeyFormatter& keyFormatter) const {
 | |
| 	Base::print(s+"LinearContainerFactor", keyFormatter);
 | |
| 	if (factor_)
 | |
| 		factor_->print("   Stored Factor", keyFormatter);
 | |
| 	if (linearizationPoint_)
 | |
| 		linearizationPoint_->print("   LinearizationPoint", keyFormatter);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| bool LinearContainerFactor::equals(const NonlinearFactor& f, double tol) const {
 | |
| 	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;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| double LinearContainerFactor::error(const Values& c) const {
 | |
| 	if (!linearizationPoint_)
 | |
| 		return 0;
 | |
| 
 | |
| 	// Extract subset of values for comparision
 | |
| 	Values csub;
 | |
| 	BOOST_FOREACH(const gtsam::Key& key, keys())
 | |
| 		csub.insert(key, c.at(key));
 | |
| 
 | |
| 	// create dummy ordering for evaluation
 | |
| 	Ordering ordering = *csub.orderingArbitrary();
 | |
| 	VectorValues delta = linearizationPoint_->localCoordinates(csub, ordering);
 | |
| 
 | |
| 	// Change keys on stored factor
 | |
| 	BOOST_FOREACH(gtsam::Index& index, factor_->keys())
 | |
| 		index = ordering[index];
 | |
| 
 | |
| 	// compute error
 | |
| 	double error = factor_->error(delta);
 | |
| 
 | |
| 	// change keys back
 | |
| 	factor_->keys() = keys();
 | |
| 
 | |
| 	return error;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| size_t LinearContainerFactor::dim() const {
 | |
| 	if (isJacobian())
 | |
| 		return toJacobian()->get_model()->dim();
 | |
| 	else
 | |
| 		return 1; // Hessians don't have true dimension
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| GaussianFactor::shared_ptr LinearContainerFactor::order(const Ordering& ordering) const {
 | |
| 	// clone factor
 | |
| 	boost::shared_ptr<GaussianFactor> result = factor_->clone();
 | |
| 
 | |
| 	// rekey
 | |
| 	BOOST_FOREACH(Index& key, result->keys())
 | |
| 		key = ordering[key];
 | |
| 
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| GaussianFactor::shared_ptr LinearContainerFactor::linearize(
 | |
| 		const Values& c, const Ordering& ordering) const {
 | |
| 	return order(ordering);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| bool LinearContainerFactor::isJacobian() const {
 | |
| 	return boost::shared_dynamic_cast<JacobianFactor>(factor_);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| JacobianFactor::shared_ptr LinearContainerFactor::toJacobian() const {
 | |
| 	return boost::shared_dynamic_cast<JacobianFactor>(factor_);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| HessianFactor::shared_ptr LinearContainerFactor::toHessian() const {
 | |
| 	return boost::shared_dynamic_cast<HessianFactor>(factor_);
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| GaussianFactor::shared_ptr LinearContainerFactor::negate(const Ordering& ordering) const {
 | |
| 	GaussianFactor::shared_ptr result = factor_->negate();
 | |
| 	BOOST_FOREACH(Key& key, result->keys())
 | |
| 		key = ordering[key];
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| NonlinearFactor::shared_ptr LinearContainerFactor::negate() const {
 | |
| 	GaussianFactor::shared_ptr antifactor = factor_->negate(); // already has keys in place
 | |
| 	return NonlinearFactor::shared_ptr(new LinearContainerFactor(antifactor,linearizationPoint_));
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| NonlinearFactorGraph LinearContainerFactor::convertLinearGraph(
 | |
| 		const GaussianFactorGraph& linear_graph,	const Ordering& ordering) {
 | |
| 	return convertLinearGraph(linear_graph, ordering.invert());
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| NonlinearFactorGraph LinearContainerFactor::convertLinearGraph(
 | |
| 		const GaussianFactorGraph& linear_graph,	const InvertedOrdering& invOrdering) {
 | |
| 	NonlinearFactorGraph result;
 | |
| 	BOOST_FOREACH(const GaussianFactor::shared_ptr& f, linear_graph)
 | |
| 		if (f)
 | |
| 			result.push_back(NonlinearFactorGraph::sharedFactor(new LinearContainerFactor(f, invOrdering)));
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| } // \namespace gtsam
 | |
| 
 | |
| 
 | |
| 
 |