| 
									
										
										
										
											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-09-09 12:43:04 +08:00
										 |  |  | /** 
 | 
					
						
							|  |  |  |  * @file    testNonlinearOptimizer.cpp | 
					
						
							|  |  |  |  * @brief   Unit tests for NonlinearOptimizer class | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-10 04:15:44 +08:00
										 |  |  | #include <tests/smallExample.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-24 06:47:31 +08:00
										 |  |  | #include <gtsam/slam/PriorFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/BetweenFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/Values.h>
 | 
					
						
							| 
									
										
										
										
											2013-08-19 23:32:16 +08:00
										 |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							| 
									
										
										
										
											2011-12-21 07:25:43 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-23 01:46:43 +08:00
										 |  |  | #include <gtsam/nonlinear/GaussNewtonOptimizer.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-23 11:43:28 +08:00
										 |  |  | #include <gtsam/nonlinear/DoglegOptimizer.h>
 | 
					
						
							| 
									
										
										
										
											2012-05-22 20:27:34 +08:00
										 |  |  | #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
 | 
					
						
							| 
									
										
										
										
											2013-08-06 06:31:33 +08:00
										 |  |  | #include <gtsam/linear/GaussianFactorGraph.h>
 | 
					
						
							| 
									
										
										
										
											2012-05-22 20:27:34 +08:00
										 |  |  | #include <gtsam/linear/NoiseModel.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-24 06:47:31 +08:00
										 |  |  | #include <gtsam/geometry/Pose2.h>
 | 
					
						
							| 
									
										
										
										
											2012-05-22 20:27:34 +08:00
										 |  |  | #include <gtsam/base/Matrix.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/shared_ptr.hpp>
 | 
					
						
							|  |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-22 20:27:34 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2013-10-30 23:40:22 +08:00
										 |  |  | #include <fstream>
 | 
					
						
							| 
									
										
										
										
											2012-05-22 20:27:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-05 06:46:27 +08:00
										 |  |  | const double tol = 1e-5; | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-03 03:28:21 +08:00
										 |  |  | using symbol_shorthand::X; | 
					
						
							|  |  |  | using symbol_shorthand::L; | 
					
						
							| 
									
										
										
										
											2012-02-21 08:53:35 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | TEST( NonlinearOptimizer, iterateLM ) | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // really non-linear factor graph
 | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph()); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // config far from minimum
 | 
					
						
							|  |  |  |   Point2 x0(3,0); | 
					
						
							|  |  |  |   Values config; | 
					
						
							|  |  |  |   config.insert(X(1), x0); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // normal iterate
 | 
					
						
							|  |  |  |   GaussNewtonParams gnParams; | 
					
						
							|  |  |  |   GaussNewtonOptimizer gnOptimizer(fg, config, gnParams); | 
					
						
							|  |  |  |   gnOptimizer.iterate(); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // LM iterate with lambda 0 should be the same
 | 
					
						
							|  |  |  |   LevenbergMarquardtParams lmParams; | 
					
						
							|  |  |  |   lmParams.lambdaInitial = 0.0; | 
					
						
							|  |  |  |   LevenbergMarquardtOptimizer lmOptimizer(fg, config, lmParams); | 
					
						
							|  |  |  |   lmOptimizer.iterate(); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   CHECK(assert_equal(gnOptimizer.values(), lmOptimizer.values(), 1e-9)); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearOptimizer, optimize ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph()); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // test error at minimum
 | 
					
						
							|  |  |  |   Point2 xstar(0,0); | 
					
						
							|  |  |  |   Values cstar; | 
					
						
							|  |  |  |   cstar.insert(X(1), xstar); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0.0,fg.error(cstar),0.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // test error at initial = [(1-cos(3))^2 + (sin(3))^2]*50 =
 | 
					
						
							|  |  |  |   Point2 x0(3,3); | 
					
						
							|  |  |  |   Values c0; | 
					
						
							|  |  |  |   c0.insert(X(1), x0); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(199.0,fg.error(c0),1e-3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // optimize parameters
 | 
					
						
							| 
									
										
										
										
											2013-08-06 06:31:44 +08:00
										 |  |  |   Ordering ord; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   ord.push_back(X(1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Gauss-Newton
 | 
					
						
							|  |  |  |   GaussNewtonParams gnParams; | 
					
						
							|  |  |  |   gnParams.ordering = ord; | 
					
						
							|  |  |  |   Values actual1 = GaussNewtonOptimizer(fg, c0, gnParams).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actual1),tol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Levenberg-Marquardt
 | 
					
						
							|  |  |  |   LevenbergMarquardtParams lmParams; | 
					
						
							|  |  |  |   lmParams.ordering = ord; | 
					
						
							| 
									
										
										
										
											2012-05-15 06:31:42 +08:00
										 |  |  |   Values actual2 = LevenbergMarquardtOptimizer(fg, c0, lmParams).optimize(); | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   DOUBLES_EQUAL(0,fg.error(actual2),tol); | 
					
						
							| 
									
										
										
										
											2012-03-23 11:43:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Dogleg
 | 
					
						
							| 
									
										
										
										
											2012-05-15 06:31:42 +08:00
										 |  |  |   DoglegParams dlParams; | 
					
						
							|  |  |  |   dlParams.ordering = ord; | 
					
						
							|  |  |  |   Values actual3 = DoglegOptimizer(fg, c0, dlParams).optimize(); | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   DOUBLES_EQUAL(0,fg.error(actual3),tol); | 
					
						
							| 
									
										
										
										
											2011-02-06 12:13:32 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-23 05:17:02 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-08-06 23:10:19 +08:00
										 |  |  | TEST( NonlinearOptimizer, SimpleLMOptimizer ) | 
					
						
							| 
									
										
										
										
											2010-07-23 05:17:02 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph()); | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Point2 x0(3,3); | 
					
						
							|  |  |  |   Values c0; | 
					
						
							|  |  |  |   c0.insert(X(1), x0); | 
					
						
							| 
									
										
										
										
											2010-07-23 05:17:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Values actual = LevenbergMarquardtOptimizer(fg, c0).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actual),tol); | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-07-23 05:17:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 23:10:19 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearOptimizer, SimpleGNOptimizer ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph()); | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Point2 x0(3,3); | 
					
						
							|  |  |  |   Values c0; | 
					
						
							| 
									
										
										
										
											2012-06-03 03:28:21 +08:00
										 |  |  |   c0.insert(X(1), x0); | 
					
						
							| 
									
										
										
										
											2010-08-06 23:10:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Values actual = GaussNewtonOptimizer(fg, c0).optimize(); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   DOUBLES_EQUAL(0,fg.error(actual),tol); | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-06 23:10:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2012-03-23 11:43:28 +08:00
										 |  |  | TEST( NonlinearOptimizer, SimpleDLOptimizer ) | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph()); | 
					
						
							| 
									
										
										
										
											2010-08-10 01:20:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-23 11:43:28 +08:00
										 |  |  |   Point2 x0(3,3); | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Values c0; | 
					
						
							| 
									
										
										
										
											2012-06-03 03:28:21 +08:00
										 |  |  |   c0.insert(X(1), x0); | 
					
						
							| 
									
										
										
										
											2010-08-06 23:10:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Values actual = DoglegOptimizer(fg, c0).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actual),tol); | 
					
						
							| 
									
										
										
										
											2010-08-06 23:10:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-14 00:55:31 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearOptimizer, optimization_method ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-23 01:46:43 +08:00
										 |  |  |   LevenbergMarquardtParams paramsQR; | 
					
						
							| 
									
										
										
										
											2012-05-25 23:26:30 +08:00
										 |  |  |   paramsQR.linearSolverType = LevenbergMarquardtParams::MULTIFRONTAL_QR; | 
					
						
							| 
									
										
										
										
											2012-05-15 13:08:57 +08:00
										 |  |  |   LevenbergMarquardtParams paramsChol; | 
					
						
							| 
									
										
										
										
											2012-05-25 23:26:30 +08:00
										 |  |  |   paramsChol.linearSolverType = LevenbergMarquardtParams::MULTIFRONTAL_CHOLESKY; | 
					
						
							| 
									
										
										
										
											2012-02-27 09:18:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg = example::createReallyNonlinearFactorGraph(); | 
					
						
							| 
									
										
										
										
											2011-06-14 00:55:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Point2 x0(3,3); | 
					
						
							|  |  |  |   Values c0; | 
					
						
							|  |  |  |   c0.insert(X(1), x0); | 
					
						
							| 
									
										
										
										
											2011-06-14 00:55:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Values actualMFQR = LevenbergMarquardtOptimizer(fg, c0, paramsQR).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actualMFQR),tol); | 
					
						
							| 
									
										
										
										
											2011-06-14 00:55:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-15 13:08:57 +08:00
										 |  |  |   Values actualMFChol = LevenbergMarquardtOptimizer(fg, c0, paramsChol).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actualMFChol),tol); | 
					
						
							| 
									
										
										
										
											2011-06-14 00:55:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearOptimizer, Factorization ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Values config; | 
					
						
							|  |  |  |   config.insert(X(1), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   config.insert(X(2), Pose2(1.5,0.,0.)); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   NonlinearFactorGraph graph; | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   graph += PriorFactor<Pose2>(X(1), Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3, 1e-10)); | 
					
						
							|  |  |  |   graph += BetweenFactor<Pose2>(X(1),X(2), Pose2(1.,0.,0.), noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 06:31:44 +08:00
										 |  |  |   Ordering ordering; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   ordering.push_back(X(1)); | 
					
						
							|  |  |  |   ordering.push_back(X(2)); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   LevenbergMarquardtOptimizer optimizer(graph, config, ordering); | 
					
						
							|  |  |  |   optimizer.iterate(); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(X(1), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   expected.insert(X(2), Pose2(1.,0.,0.)); | 
					
						
							|  |  |  |   CHECK(assert_equal(expected, optimizer.values(), 1e-5)); | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2012-03-23 02:02:25 +08:00
										 |  |  | TEST(NonlinearOptimizer, NullFactor) { | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   NonlinearFactorGraph fg = example::createReallyNonlinearFactorGraph(); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Add null factor
 | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   fg.push_back(NonlinearFactorGraph::sharedFactor()); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // test error at minimum
 | 
					
						
							|  |  |  |   Point2 xstar(0,0); | 
					
						
							| 
									
										
										
										
											2012-02-03 00:16:46 +08:00
										 |  |  |   Values cstar; | 
					
						
							| 
									
										
										
										
											2012-06-03 03:28:21 +08:00
										 |  |  |   cstar.insert(X(1), xstar); | 
					
						
							| 
									
										
										
										
											2012-03-23 01:46:43 +08:00
										 |  |  |   DOUBLES_EQUAL(0.0,fg.error(cstar),0.0); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // test error at initial = [(1-cos(3))^2 + (sin(3))^2]*50 =
 | 
					
						
							|  |  |  |   Point2 x0(3,3); | 
					
						
							| 
									
										
										
										
											2012-03-23 01:46:43 +08:00
										 |  |  |   Values c0; | 
					
						
							| 
									
										
										
										
											2012-06-03 03:28:21 +08:00
										 |  |  |   c0.insert(X(1), x0); | 
					
						
							| 
									
										
										
										
											2012-03-23 01:46:43 +08:00
										 |  |  |   DOUBLES_EQUAL(199.0,fg.error(c0),1e-3); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // optimize parameters
 | 
					
						
							| 
									
										
										
										
											2013-08-06 06:31:44 +08:00
										 |  |  |   Ordering ord; | 
					
						
							| 
									
										
										
										
											2012-06-03 03:28:21 +08:00
										 |  |  |   ord.push_back(X(1)); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Gauss-Newton
 | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Values actual1 = GaussNewtonOptimizer(fg, c0, ord).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actual1),tol); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Levenberg-Marquardt
 | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Values actual2 = LevenbergMarquardtOptimizer(fg, c0, ord).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actual2),tol); | 
					
						
							| 
									
										
										
										
											2012-03-23 11:43:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Dogleg
 | 
					
						
							| 
									
										
										
										
											2012-05-15 05:07:56 +08:00
										 |  |  |   Values actual3 = DoglegOptimizer(fg, c0, ord).optimize(); | 
					
						
							|  |  |  |   DOUBLES_EQUAL(0,fg.error(actual3),tol); | 
					
						
							| 
									
										
										
										
											2011-03-30 03:51:50 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  | TEST_UNSAFE(NonlinearOptimizer, MoreOptimization) { | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   fg += PriorFactor<Pose2>(0, Pose2(0, 0, 0), | 
					
						
							|  |  |  |       noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(1, 0, M_PI / 2), | 
					
						
							|  |  |  |       noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(1, 2, Pose2(1, 0, M_PI / 2), | 
					
						
							|  |  |  |       noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   init.insert(0, Pose2(3, 4, -M_PI)); | 
					
						
							|  |  |  |   init.insert(1, Pose2(10, 2, -M_PI)); | 
					
						
							|  |  |  |   init.insert(2, Pose2(11, 7, -M_PI)); | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values expected; | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   expected.insert(0, Pose2(0, 0, 0)); | 
					
						
							|  |  |  |   expected.insert(1, Pose2(1, 0, M_PI / 2)); | 
					
						
							|  |  |  |   expected.insert(2, Pose2(1, 1, M_PI)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VectorValues expectedGradient; | 
					
						
							|  |  |  |   expectedGradient.insert(0,zero(3)); | 
					
						
							|  |  |  |   expectedGradient.insert(1,zero(3)); | 
					
						
							|  |  |  |   expectedGradient.insert(2,zero(3)); | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Try LM and Dogleg
 | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   LevenbergMarquardtParams params; | 
					
						
							|  |  |  | //  params.setVerbosityLM("TRYDELTA");
 | 
					
						
							|  |  |  | //  params.setVerbosity("TERMINATION");
 | 
					
						
							|  |  |  |   params.setlambdaUpperBound(1e9); | 
					
						
							| 
									
										
										
										
											2014-02-20 22:02:24 +08:00
										 |  |  | //  params.setRelativeErrorTol(0);
 | 
					
						
							|  |  |  | //  params.setAbsoluteErrorTol(0);
 | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   //params.setlambdaInitial(10);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     LevenbergMarquardtOptimizer optimizer(fg, init, params); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // test convergence
 | 
					
						
							|  |  |  |     Values actual = optimizer.optimize(); | 
					
						
							|  |  |  |     EXPECT(assert_equal(expected, actual)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check that the gradient is zero
 | 
					
						
							|  |  |  |     GaussianFactorGraph::shared_ptr linear = optimizer.linearize(); | 
					
						
							|  |  |  |     EXPECT(assert_equal(expectedGradient,linear->gradientAtZero())); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  |   EXPECT(assert_equal(expected, DoglegOptimizer(fg, init).optimize())); | 
					
						
							| 
									
										
										
										
											2014-02-17 00:58:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-20 22:02:24 +08:00
										 |  |  | //  cout << "===================================================================================" << endl;
 | 
					
						
							| 
									
										
										
										
											2014-02-17 06:11:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   // Try LM with diagonal damping
 | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  |   Values initBetter; | 
					
						
							|  |  |  |     initBetter.insert(0, Pose2(3,4,0)); | 
					
						
							|  |  |  |     initBetter.insert(1, Pose2(10,2,M_PI/3)); | 
					
						
							|  |  |  |     initBetter.insert(2, Pose2(11,7,M_PI/2)); | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  |     params.setDiagonalDamping(true); | 
					
						
							|  |  |  |     LevenbergMarquardtOptimizer optimizer(fg, initBetter, params); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // test the diagonal
 | 
					
						
							|  |  |  |     GaussianFactorGraph::shared_ptr linear = optimizer.linearize(); | 
					
						
							| 
									
										
										
										
											2014-04-25 00:05:37 +08:00
										 |  |  |     GaussianFactorGraph damped = *optimizer.buildDampedSystem(*linear); | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  |     VectorValues d = linear->hessianDiagonal(), //
 | 
					
						
							|  |  |  |     expectedDiagonal = d + params.lambdaInitial * d; | 
					
						
							|  |  |  |     EXPECT(assert_equal(expectedDiagonal, damped.hessianDiagonal())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // test convergence (does not!)
 | 
					
						
							|  |  |  |     Values actual = optimizer.optimize(); | 
					
						
							|  |  |  |     EXPECT(assert_equal(expected, actual)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check that the gradient is zero (it is not!)
 | 
					
						
							|  |  |  |     linear = optimizer.linearize(); | 
					
						
							|  |  |  |     EXPECT(assert_equal(expectedGradient,linear->gradientAtZero())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check that the gradient is zero for damped system (it is not!)
 | 
					
						
							| 
									
										
										
										
											2014-04-25 00:05:37 +08:00
										 |  |  |     damped = *optimizer.buildDampedSystem(*linear); | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  |     VectorValues actualGradient = damped.gradientAtZero(); | 
					
						
							|  |  |  |     EXPECT(assert_equal(expectedGradient,actualGradient)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* This block was made to test the original initial guess "init"
 | 
					
						
							|  |  |  |     // Check errors at convergence and errors in direction of gradient (decreases!)
 | 
					
						
							|  |  |  |     EXPECT_DOUBLES_EQUAL(46.02558,fg.error(actual),1e-5); | 
					
						
							|  |  |  |     EXPECT_DOUBLES_EQUAL(44.742237,fg.error(actual.retract(-0.01*actualGradient)),1e-5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check that solve yields gradient (it's not equal to gradient, as predicted)
 | 
					
						
							|  |  |  |     VectorValues delta = damped.optimize(); | 
					
						
							|  |  |  |     double factor = actualGradient[0][0]/delta[0][0]; | 
					
						
							|  |  |  |     EXPECT(assert_equal(actualGradient,factor*delta)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Still pointing downhill wrt actual gradient !
 | 
					
						
							|  |  |  |     EXPECT_DOUBLES_EQUAL( 0.1056157,dot(-1*actualGradient,delta),1e-3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // delta.print("This is the delta value computed by LM with diagonal damping");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Still pointing downhill wrt expected gradient (IT DOES NOT! actually they are perpendicular)
 | 
					
						
							|  |  |  |     EXPECT_DOUBLES_EQUAL( 0.0,dot(-1*expectedGradient,delta),1e-5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check errors at convergence and errors in direction of solution (does not decrease!)
 | 
					
						
							|  |  |  |     EXPECT_DOUBLES_EQUAL(46.0254859,fg.error(actual.retract(delta)),1e-5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check errors at convergence and errors at a small step in direction of solution (does not decrease!)
 | 
					
						
							|  |  |  |     EXPECT_DOUBLES_EQUAL(46.0255,fg.error(actual.retract(0.01*delta)),1e-3); | 
					
						
							|  |  |  |     */ | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-07 06:42:01 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, MoreOptimizationWithHuber) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   fg += PriorFactor<Pose2>(0, Pose2(0,0,0), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(1,0,M_PI/2), | 
					
						
							| 
									
										
										
										
											2013-02-08 08:47:52 +08:00
										 |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(2.0), | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |                                                          noiseModel::Isotropic::Sigma(3,1))); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(1, 2, Pose2(1,0,M_PI/2), | 
					
						
							| 
									
										
										
										
											2013-02-08 08:47:52 +08:00
										 |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(3.0), | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |                                                          noiseModel::Isotropic::Sigma(3,1))); | 
					
						
							| 
									
										
										
										
											2012-11-07 06:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   init.insert(0, Pose2(10,10,0)); | 
					
						
							|  |  |  |   init.insert(1, Pose2(1,0,M_PI)); | 
					
						
							|  |  |  |   init.insert(2, Pose2(1,1,-M_PI)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(0, Pose2(0,0,0)); | 
					
						
							|  |  |  |   expected.insert(1, Pose2(1,0,M_PI/2)); | 
					
						
							|  |  |  |   expected.insert(2, Pose2(1,1,M_PI)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, GaussNewtonOptimizer(fg, init).optimize())); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, LevenbergMarquardtOptimizer(fg, init).optimize())); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, DoglegOptimizer(fg, init).optimize())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, disconnected_graph) { | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(X(1), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   expected.insert(X(2), Pose2(1.5,0.,0.)); | 
					
						
							|  |  |  |   expected.insert(X(3), Pose2(3.0,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   init.insert(X(1), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   init.insert(X(2), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   init.insert(X(3), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph graph; | 
					
						
							|  |  |  |   graph += PriorFactor<Pose2>(X(1), Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  |   graph += BetweenFactor<Pose2>(X(1),X(2), Pose2(1.5,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  |   graph += PriorFactor<Pose2>(X(3), Pose2(3.,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, LevenbergMarquardtOptimizer(graph, init).optimize())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | #include <gtsam/linear/iterative.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class IterativeLM: public LevenbergMarquardtOptimizer { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Solver specific parameters
 | 
					
						
							|  |  |  |   ConjugateGradientParameters cgParams_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   /// Constructor
 | 
					
						
							|  |  |  |   IterativeLM(const NonlinearFactorGraph& graph, const Values& initialValues, | 
					
						
							|  |  |  |       const ConjugateGradientParameters &p, | 
					
						
							|  |  |  |       const LevenbergMarquardtParams& params = LevenbergMarquardtParams()) : | 
					
						
							|  |  |  |       LevenbergMarquardtOptimizer(graph, initialValues, params), cgParams_(p) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Solve that uses conjugate gradient
 | 
					
						
							|  |  |  |   virtual VectorValues solve(const GaussianFactorGraph &gfg, | 
					
						
							|  |  |  |       const Values& initial, const NonlinearOptimizerParams& params) const { | 
					
						
							|  |  |  |     VectorValues zeros = initial.zeroVectors(); | 
					
						
							|  |  |  |     return conjugateGradientDescent(gfg, zeros, cgParams_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, subclass_solver) { | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(X(1), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   expected.insert(X(2), Pose2(1.5,0.,0.)); | 
					
						
							|  |  |  |   expected.insert(X(3), Pose2(3.0,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   init.insert(X(1), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   init.insert(X(2), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  |   init.insert(X(3), Pose2(0.,0.,0.)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph graph; | 
					
						
							|  |  |  |   graph += PriorFactor<Pose2>(X(1), Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  |   graph += BetweenFactor<Pose2>(X(1),X(2), Pose2(1.5,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  |   graph += PriorFactor<Pose2>(X(3), Pose2(3.,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ConjugateGradientParameters p; | 
					
						
							|  |  |  |   Values actual = IterativeLM(graph, init, p).optimize(); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, actual, 1e-4)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 23:40:22 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | #include <wrap/utilities.h>
 | 
					
						
							|  |  |  | TEST( NonlinearOptimizer, logfile ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Point2 x0(3,3); | 
					
						
							|  |  |  |   Values c0; | 
					
						
							|  |  |  |   c0.insert(X(1), x0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Levenberg-Marquardt
 | 
					
						
							|  |  |  |   LevenbergMarquardtParams lmParams; | 
					
						
							|  |  |  |   static const string filename("testNonlinearOptimizer.log"); | 
					
						
							|  |  |  |   lmParams.setLogFile(filename); | 
					
						
							|  |  |  |   CHECK(lmParams.getLogFile()==filename); | 
					
						
							|  |  |  |   LevenbergMarquardtOptimizer(fg, c0, lmParams).optimize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //  stringstream expected,actual;
 | 
					
						
							|  |  |  | //  ifstream ifs(("../../gtsam/tests/" + filename).c_str());
 | 
					
						
							|  |  |  | //  if(!ifs) throw std::runtime_error(filename);
 | 
					
						
							|  |  |  | //  expected << ifs.rdbuf();
 | 
					
						
							|  |  |  | //  ifs.close();
 | 
					
						
							|  |  |  | //  ifstream ifs2(filename.c_str());
 | 
					
						
							|  |  |  | //  if(!ifs2) throw std::runtime_error(filename);
 | 
					
						
							|  |  |  | //  actual << ifs2.rdbuf();
 | 
					
						
							|  |  |  | //  EXPECT(actual.str()==expected.str());
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   TestResult tr; | 
					
						
							|  |  |  |   return TestRegistry::runAllTests(tr); | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ |