| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  *  @file   testIterative.cpp | 
					
						
							|  |  |  |  *  @brief  Unit tests for iterative methods | 
					
						
							|  |  |  |  *  @author Frank Dellaert | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-26 04:10:33 +08:00
										 |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:38:53 +08:00
										 |  |  | // TODO: DANGEROUS, create shared pointers
 | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  | #define GTSAM_MAGIC_GAUSSIAN 3
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | #define GTSAM_MAGIC_KEY
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-20 01:23:19 +08:00
										 |  |  | #include <gtsam/inference/Ordering.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | #include <gtsam/linear/VectorValues.h>
 | 
					
						
							| 
									
										
										
										
											2010-08-20 01:23:19 +08:00
										 |  |  | #include <gtsam/slam/smallExample.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/pose2SLAM.h>
 | 
					
						
							|  |  |  | #include <gtsam/linear/SubgraphPreconditioner.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/FactorGraph-inl.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph-inl.h>
 | 
					
						
							|  |  |  | #include <gtsam/linear/iterative-inl.h>
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							| 
									
										
										
										
											2010-01-19 13:33:44 +08:00
										 |  |  | using namespace example; | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-14 13:52:20 +08:00
										 |  |  | static bool verbose = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( Iterative, steepestDescent ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Expected solution
 | 
					
						
							|  |  |  | 	Ordering ord; | 
					
						
							|  |  |  | 	ord += "l1", "x1", "x2"; | 
					
						
							|  |  |  | 	GaussianFactorGraph fg = createGaussianFactorGraph(); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues expected = fg.optimize(ord); // destructive
 | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Do gradient descent
 | 
					
						
							|  |  |  | 	GaussianFactorGraph fg2 = createGaussianFactorGraph(); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues zero = createZeroDelta(); | 
					
						
							|  |  |  | 	VectorValues actual = steepestDescent(fg2, zero, verbose); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 	CHECK(assert_equal(expected,actual,1e-2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( Iterative, conjugateGradientDescent ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Expected solution
 | 
					
						
							|  |  |  | 	Ordering ord; | 
					
						
							|  |  |  | 	ord += "l1", "x1", "x2"; | 
					
						
							|  |  |  | 	GaussianFactorGraph fg = createGaussianFactorGraph(); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues expected = fg.optimize(ord); // destructive
 | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// create graph and get matrices
 | 
					
						
							|  |  |  | 	GaussianFactorGraph fg2 = createGaussianFactorGraph(); | 
					
						
							|  |  |  | 	Matrix A; | 
					
						
							|  |  |  | 	Vector b; | 
					
						
							|  |  |  | 	Vector x0 = gtsam::zero(6); | 
					
						
							|  |  |  | 	boost::tie(A, b) = fg2.matrix(ord); | 
					
						
							|  |  |  | 	Vector expectedX = Vector_(6, -0.1, 0.1, -0.1, -0.1, 0.1, -0.2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Do conjugate gradient descent, System version
 | 
					
						
							|  |  |  | 	System Ab(A, b); | 
					
						
							| 
									
										
										
										
											2010-02-14 13:52:20 +08:00
										 |  |  | 	Vector actualX = conjugateGradientDescent(Ab, x0, verbose); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 	CHECK(assert_equal(expectedX,actualX,1e-9)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Do conjugate gradient descent, Matrix version
 | 
					
						
							| 
									
										
										
										
											2010-02-14 13:52:20 +08:00
										 |  |  | 	Vector actualX2 = conjugateGradientDescent(A, b, x0, verbose); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 	CHECK(assert_equal(expectedX,actualX2,1e-9)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Do conjugate gradient descent on factor graph
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues zero = createZeroDelta(); | 
					
						
							|  |  |  | 	VectorValues actual = conjugateGradientDescent(fg2, zero, verbose); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 	CHECK(assert_equal(expected,actual,1e-2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Test method
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues actual2 = fg2.conjugateGradientDescent(zero, verbose); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:10:07 +08:00
										 |  |  | 	CHECK(assert_equal(expected,actual2,1e-2)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-11 06:59:50 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | /*TEST( Iterative, conjugateGradientDescent_hard_constraint )
 | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	typedef Pose2Values::Key Key; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	Pose2Values config; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 	config.insert(1, Pose2(0.,0.,0.)); | 
					
						
							|  |  |  | 	config.insert(2, Pose2(1.5,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Pose2Graph graph; | 
					
						
							|  |  |  | 	Matrix cov = eye(3); | 
					
						
							|  |  |  | 	graph.push_back(Pose2Graph::sharedFactor(new Pose2Factor(Key(1), Key(2), Pose2(1.,0.,0.), cov))); | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 	graph.addHardConstraint(1, config[1]); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues zeros; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 	zeros.insert("x1",zero(3)); | 
					
						
							|  |  |  | 	zeros.insert("x2",zero(3)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GaussianFactorGraph fg = graph.linearize(config); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues actual = conjugateGradientDescent(fg, zeros, true, 1e-3, 1e-5, 10); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues expected; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 	expected.insert("x1", zero(3)); | 
					
						
							|  |  |  | 	expected.insert("x2", Vector_(-0.5,0.,0.)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(expected, actual)); | 
					
						
							| 
									
										
										
										
											2010-07-11 06:59:50 +08:00
										 |  |  | }*/ | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-28 18:48:48 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | TEST( Iterative, conjugateGradientDescent_soft_constraint ) | 
					
						
							| 
									
										
										
										
											2009-12-28 18:48:48 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	Pose2Values config; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 	config.insert(1, Pose2(0.,0.,0.)); | 
					
						
							|  |  |  | 	config.insert(2, Pose2(1.5,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Pose2Graph graph; | 
					
						
							| 
									
										
										
										
											2010-08-08 11:10:29 +08:00
										 |  |  | 	graph.addPrior(1, Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3, 1e-10)); | 
					
						
							|  |  |  | 	graph.addConstraint(1,2, Pose2(1.,0.,0.), noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues zeros; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 	zeros.insert("x1",zero(3)); | 
					
						
							|  |  |  | 	zeros.insert("x2",zero(3)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 05:17:47 +08:00
										 |  |  | 	boost::shared_ptr<GaussianFactorGraph> fg = graph.linearize(config); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues actual = conjugateGradientDescent(*fg, zeros, verbose, 1e-3, 1e-5, 100); | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues expected; | 
					
						
							| 
									
										
										
										
											2010-01-16 13:08:29 +08:00
										 |  |  | 	expected.insert("x1", zero(3)); | 
					
						
							|  |  |  | 	expected.insert("x2", Vector_(3,-0.5,0.,0.)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(expected, actual)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( Iterative, subgraphPCG ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	typedef Pose2Values::Key Key; | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	Pose2Values theta_bar; | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 	theta_bar.insert(1, Pose2(0.,0.,0.)); | 
					
						
							|  |  |  | 	theta_bar.insert(2, Pose2(1.5,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Pose2Graph graph; | 
					
						
							| 
									
										
										
										
											2010-08-08 11:10:29 +08:00
										 |  |  | 	graph.addPrior(1, Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3, 1e-10)); | 
					
						
							|  |  |  | 	graph.addConstraint(1,2, Pose2(1.,0.,0.), noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// generate spanning tree and create ordering
 | 
					
						
							|  |  |  | 	PredecessorMap<Key> tree = graph.findMinimumSpanningTree<Key, Pose2Factor>(); | 
					
						
							|  |  |  | 	list<Key> keys = predecessorMap2Keys(tree); | 
					
						
							|  |  |  | 	list<Symbol> symbols; | 
					
						
							|  |  |  | 	symbols.resize(keys.size()); | 
					
						
							|  |  |  | 	std::transform(keys.begin(), keys.end(), symbols.begin(), key2symbol<Key>); | 
					
						
							|  |  |  | 	Ordering ordering(symbols); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Key root = keys.back(); | 
					
						
							|  |  |  | 	Pose2Graph T, C; | 
					
						
							|  |  |  | 	graph.split<Key, Pose2Factor>(tree, T, C); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// build the subgraph PCG system
 | 
					
						
							| 
									
										
										
										
											2010-02-22 05:17:47 +08:00
										 |  |  | 	boost::shared_ptr<GaussianFactorGraph> Ab1_ = T.linearize(theta_bar); | 
					
						
							|  |  |  | 	SubgraphPreconditioner::sharedFG Ab1 = T.linearize(theta_bar); | 
					
						
							|  |  |  | 	SubgraphPreconditioner::sharedFG Ab2 = C.linearize(theta_bar); | 
					
						
							|  |  |  | 	SubgraphPreconditioner::sharedBayesNet Rc1 = Ab1_->eliminate_(ordering); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	SubgraphPreconditioner::sharedValues xbar = optimize_(*Rc1); | 
					
						
							| 
									
										
										
										
											2010-01-23 09:03:47 +08:00
										 |  |  | 	SubgraphPreconditioner system(Ab1, Ab2, Rc1, xbar); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues zeros = VectorValues::zero(*xbar); | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 	// Solve the subgraph PCG
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues ybar = conjugateGradients<SubgraphPreconditioner, VectorValues, | 
					
						
							| 
									
										
										
										
											2010-02-14 13:52:20 +08:00
										 |  |  | 			Errors> (system, zeros, verbose, 1e-5, 1e-5, 100); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues actual = system.x(ybar); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues expected; | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 	expected.insert("x1", zero(3)); | 
					
						
							|  |  |  | 	expected.insert("x2", Vector_(3, -0.5, 0., 0.)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(expected, actual)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-12-28 18:48:48 +08:00
										 |  |  | int main() { | 
					
						
							|  |  |  | 	TestResult tr; | 
					
						
							|  |  |  | 	return TestRegistry::runAllTests(tr); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-12-28 17:44:30 +08:00
										 |  |  | /* ************************************************************************* */ |