| 
									
										
										
										
											2011-01-20 23:42:11 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file testNonlinearISAM | 
					
						
							|  |  |  |  * @author Alex Cunningham | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-24 06:46:55 +08:00
										 |  |  | #include <gtsam/slam/BetweenFactor.h>
 | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  | #include <gtsam/slam/BearingRangeFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/PriorFactor.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-24 06:46:55 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearEquality.h>
 | 
					
						
							| 
									
										
										
										
											2011-11-18 05:20:04 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearISAM.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-24 06:46:55 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/Values.h>
 | 
					
						
							| 
									
										
										
										
											2013-08-19 23:32:16 +08:00
										 |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-24 06:46:55 +08:00
										 |  |  | #include <gtsam/linear/Sampler.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Pose2.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-20 23:42:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const double tol=1e-5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(testNonlinearISAM, markov_chain ) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   int reorder_interval = 2; | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |   NonlinearISAM isamChol(reorder_interval, EliminatePreferCholesky); // create an ISAM object
 | 
					
						
							|  |  |  |   NonlinearISAM isamQR(reorder_interval, EliminateQR); // create an ISAM object
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-24 02:22:25 +08:00
										 |  |  |   SharedDiagonal model = noiseModel::Diagonal::Sigmas(Vector3(3.0, 3.0, 0.5)); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Sampler sampler(model, 42u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create initial graph
 | 
					
						
							|  |  |  |   Pose2 cur_pose; // start at origin
 | 
					
						
							|  |  |  |   NonlinearFactorGraph start_factors; | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |   start_factors += NonlinearEquality<Pose2>(0, cur_pose); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   init.insert(0, cur_pose); | 
					
						
							|  |  |  |   expected.insert(0, cur_pose); | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |   isamChol.update(start_factors, init); | 
					
						
							|  |  |  |   isamQR.update(start_factors, init); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // loop for a period of time to verify memory usage
 | 
					
						
							|  |  |  |   size_t nrPoses = 21; | 
					
						
							|  |  |  |   Pose2 z(1.0, 2.0, 0.1); | 
					
						
							|  |  |  |   for (size_t i=1; i<=nrPoses; ++i) { | 
					
						
							|  |  |  |     NonlinearFactorGraph new_factors; | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |     new_factors += BetweenFactor<Pose2>(i-1, i, z, model); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     Values new_init; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cur_pose = cur_pose.compose(z); | 
					
						
							|  |  |  |     new_init.insert(i, cur_pose.retract(sampler.sample())); | 
					
						
							|  |  |  |     expected.insert(i, cur_pose); | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |     isamChol.update(new_factors, new_init); | 
					
						
							|  |  |  |     isamQR.update(new_factors, new_init); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // verify values - all but the last one should be very close
 | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |   Values actualChol = isamChol.estimate(); | 
					
						
							|  |  |  |   for (size_t i=0; i<nrPoses; ++i) { | 
					
						
							|  |  |  |     EXPECT(assert_equal(expected.at<Pose2>(i), actualChol.at<Pose2>(i), tol)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   Values actualQR = isamQR.estimate(); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   for (size_t i=0; i<nrPoses; ++i) { | 
					
						
							| 
									
										
										
										
											2013-08-07 03:56:48 +08:00
										 |  |  |     EXPECT(assert_equal(expected.at<Pose2>(i), actualQR.at<Pose2>(i), tol)); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-01-20 23:42:11 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(testNonlinearISAM, markov_chain_with_disconnects ) { | 
					
						
							|  |  |  |   int reorder_interval = 2; | 
					
						
							|  |  |  |   NonlinearISAM isamChol(reorder_interval, EliminatePreferCholesky); // create an ISAM object
 | 
					
						
							|  |  |  |   NonlinearISAM isamQR(reorder_interval, EliminateQR); // create an ISAM object
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-24 02:22:25 +08:00
										 |  |  |   SharedDiagonal model3 = noiseModel::Diagonal::Sigmas(Vector3(3.0, 3.0, 0.5)); | 
					
						
							|  |  |  |   SharedDiagonal model2 = noiseModel::Diagonal::Sigmas(Vector2(2.0, 2.0)); | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  |   Sampler sampler(model3, 42u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create initial graph
 | 
					
						
							|  |  |  |   Pose2 cur_pose; // start at origin
 | 
					
						
							|  |  |  |   NonlinearFactorGraph start_factors; | 
					
						
							|  |  |  |   start_factors += NonlinearEquality<Pose2>(0, cur_pose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   init.insert(0, cur_pose); | 
					
						
							|  |  |  |   expected.insert(0, cur_pose); | 
					
						
							|  |  |  |   isamChol.update(start_factors, init); | 
					
						
							|  |  |  |   isamQR.update(start_factors, init); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   size_t nrPoses = 21; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create a constrained constellation of landmarks
 | 
					
						
							|  |  |  |   Key lm1 = nrPoses+1, lm2 = nrPoses+2, lm3 = nrPoses+3; | 
					
						
							|  |  |  |   Point2 landmark1(3., 4.), landmark2(6., 4.), landmark3(6., 9.); | 
					
						
							|  |  |  |   expected.insert(lm1, landmark1); | 
					
						
							|  |  |  |   expected.insert(lm2, landmark2); | 
					
						
							|  |  |  |   expected.insert(lm3, landmark3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // loop for a period of time to verify memory usage
 | 
					
						
							|  |  |  |   Pose2 z(1.0, 2.0, 0.1); | 
					
						
							|  |  |  |   for (size_t i=1; i<=nrPoses; ++i) { | 
					
						
							|  |  |  |     NonlinearFactorGraph new_factors; | 
					
						
							|  |  |  |     new_factors += BetweenFactor<Pose2>(i-1, i, z, model3); | 
					
						
							|  |  |  |     Values new_init; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cur_pose = cur_pose.compose(z); | 
					
						
							|  |  |  |     new_init.insert(i, cur_pose.retract(sampler.sample())); | 
					
						
							|  |  |  |     expected.insert(i, cur_pose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Add a floating landmark constellation
 | 
					
						
							|  |  |  |     if (i == 7) { | 
					
						
							|  |  |  |       new_factors += PriorFactor<Point2>(lm1, landmark1, model2); | 
					
						
							|  |  |  |       new_factors += PriorFactor<Point2>(lm2, landmark2, model2); | 
					
						
							|  |  |  |       new_factors += PriorFactor<Point2>(lm3, landmark3, model2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Initialize to origin
 | 
					
						
							|  |  |  |       new_init.insert(lm1, Point2()); | 
					
						
							|  |  |  |       new_init.insert(lm2, Point2()); | 
					
						
							|  |  |  |       new_init.insert(lm3, Point2()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     isamChol.update(new_factors, new_init); | 
					
						
							|  |  |  |     isamQR.update(new_factors, new_init); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // verify values - all but the last one should be very close
 | 
					
						
							|  |  |  |   Values actualChol = isamChol.estimate(); | 
					
						
							|  |  |  |   for (size_t i=0; i<nrPoses; ++i) | 
					
						
							|  |  |  |     EXPECT(assert_equal(expected.at<Pose2>(i), actualChol.at<Pose2>(i), tol)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values actualQR = isamQR.estimate(); | 
					
						
							|  |  |  |   for (size_t i=0; i<nrPoses; ++i) | 
					
						
							|  |  |  |     EXPECT(assert_equal(expected.at<Pose2>(i), actualQR.at<Pose2>(i), tol)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Check landmarks
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm1), actualChol.at<Point2>(lm1), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm2), actualChol.at<Point2>(lm2), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm3), actualChol.at<Point2>(lm3), tol)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm1), actualQR.at<Point2>(lm1), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm2), actualQR.at<Point2>(lm2), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm3), actualQR.at<Point2>(lm3), tol)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(testNonlinearISAM, markov_chain_with_reconnect ) { | 
					
						
							|  |  |  |   int reorder_interval = 2; | 
					
						
							|  |  |  |   NonlinearISAM isamChol(reorder_interval, EliminatePreferCholesky); // create an ISAM object
 | 
					
						
							|  |  |  |   NonlinearISAM isamQR(reorder_interval, EliminateQR); // create an ISAM object
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-24 02:22:25 +08:00
										 |  |  |   SharedDiagonal model3 = noiseModel::Diagonal::Sigmas(Vector3(3.0, 3.0, 0.5)); | 
					
						
							|  |  |  |   SharedDiagonal model2 = noiseModel::Diagonal::Sigmas(Vector2(2.0, 2.0)); | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  |   Sampler sampler(model3, 42u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create initial graph
 | 
					
						
							|  |  |  |   Pose2 cur_pose; // start at origin
 | 
					
						
							|  |  |  |   NonlinearFactorGraph start_factors; | 
					
						
							|  |  |  |   start_factors += NonlinearEquality<Pose2>(0, cur_pose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   init.insert(0, cur_pose); | 
					
						
							|  |  |  |   expected.insert(0, cur_pose); | 
					
						
							|  |  |  |   isamChol.update(start_factors, init); | 
					
						
							|  |  |  |   isamQR.update(start_factors, init); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   size_t nrPoses = 21; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create a constrained constellation of landmarks
 | 
					
						
							|  |  |  |   Key lm1 = nrPoses+1, lm2 = nrPoses+2, lm3 = nrPoses+3; | 
					
						
							|  |  |  |   Point2 landmark1(3., 4.), landmark2(6., 4.), landmark3(6., 9.); | 
					
						
							|  |  |  |   expected.insert(lm1, landmark1); | 
					
						
							|  |  |  |   expected.insert(lm2, landmark2); | 
					
						
							|  |  |  |   expected.insert(lm3, landmark3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // loop for a period of time to verify memory usage
 | 
					
						
							|  |  |  |   Pose2 z(1.0, 2.0, 0.1); | 
					
						
							|  |  |  |   for (size_t i=1; i<=nrPoses; ++i) { | 
					
						
							|  |  |  |     NonlinearFactorGraph new_factors; | 
					
						
							|  |  |  |     new_factors += BetweenFactor<Pose2>(i-1, i, z, model3); | 
					
						
							|  |  |  |     Values new_init; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cur_pose = cur_pose.compose(z); | 
					
						
							|  |  |  |     new_init.insert(i, cur_pose.retract(sampler.sample())); | 
					
						
							|  |  |  |     expected.insert(i, cur_pose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Add a floating landmark constellation
 | 
					
						
							|  |  |  |     if (i == 7) { | 
					
						
							|  |  |  |       new_factors += PriorFactor<Point2>(lm1, landmark1, model2); | 
					
						
							|  |  |  |       new_factors += PriorFactor<Point2>(lm2, landmark2, model2); | 
					
						
							|  |  |  |       new_factors += PriorFactor<Point2>(lm3, landmark3, model2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Initialize to origin
 | 
					
						
							|  |  |  |       new_init.insert(lm1, Point2()); | 
					
						
							|  |  |  |       new_init.insert(lm2, Point2()); | 
					
						
							|  |  |  |       new_init.insert(lm3, Point2()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Reconnect with observation later
 | 
					
						
							|  |  |  |     if (i == 15) { | 
					
						
							|  |  |  |       new_factors += BearingRangeFactor<Pose2, Point2>( | 
					
						
							|  |  |  |           i, lm1, cur_pose.bearing(landmark1), cur_pose.range(landmark1), model2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     isamChol.update(new_factors, new_init); | 
					
						
							|  |  |  |     isamQR.update(new_factors, new_init); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // verify values - all but the last one should be very close
 | 
					
						
							|  |  |  |   Values actualChol = isamChol.estimate(); | 
					
						
							|  |  |  |   for (size_t i=0; i<nrPoses; ++i) | 
					
						
							| 
									
										
										
										
											2014-08-14 12:25:49 +08:00
										 |  |  |     EXPECT(assert_equal(expected.at<Pose2>(i), actualChol.at<Pose2>(i), 1e-4)); | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values actualQR = isamQR.estimate(); | 
					
						
							|  |  |  |   for (size_t i=0; i<nrPoses; ++i) | 
					
						
							| 
									
										
										
										
											2014-08-14 12:25:49 +08:00
										 |  |  |     EXPECT(assert_equal(expected.at<Pose2>(i), actualQR.at<Pose2>(i), 1e-4)); | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Check landmarks
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm1), actualChol.at<Point2>(lm1), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm2), actualChol.at<Point2>(lm2), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm3), actualChol.at<Point2>(lm3), tol)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm1), actualQR.at<Point2>(lm1), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm2), actualQR.at<Point2>(lm2), tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected.at<Point2>(lm3), actualQR.at<Point2>(lm3), tol)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-20 23:42:11 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { TestResult tr; return TestRegistry::runAllTests(tr); } | 
					
						
							|  |  |  | /* ************************************************************************* */ |