| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:39:48 +08:00
										 |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | 
					
						
							| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  |  * 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:39:48 +08:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											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/BetweenFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/Values.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearConjugateGradientOptimizer.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>
 | 
					
						
							| 
									
										
										
										
											2018-10-09 09:51:20 +08:00
										 |  |  | #include <gtsam/inference/Symbol.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>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  | #include <boost/range/adaptor/map.hpp>
 | 
					
						
							| 
									
										
										
										
											2012-05-22 20:27:34 +08:00
										 |  |  | #include <boost/shared_ptr.hpp>
 | 
					
						
							|  |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  | using boost::adaptors::map_values; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   graph.addPrior(X(1), Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3, 1e-10)); | 
					
						
							| 
									
										
										
										
											2013-08-06 21:44:22 +08:00
										 |  |  |   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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-19 00:51:22 +08:00
										 |  |  |   LevenbergMarquardtParams params; | 
					
						
							|  |  |  |   LevenbergMarquardtParams::SetLegacyDefaults(¶ms); | 
					
						
							|  |  |  |   LevenbergMarquardtOptimizer optimizer(graph, config, ordering, params); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   fg.addPrior(0, Pose2(0, 0, 0), noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2016-04-16 04:54:46 +08:00
										 |  |  |   expectedGradient.insert(0,Z_3x1); | 
					
						
							|  |  |  |   expectedGradient.insert(1,Z_3x1); | 
					
						
							|  |  |  |   expectedGradient.insert(2,Z_3x1); | 
					
						
							| 
									
										
										
										
											2012-05-15 21:23:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Try LM and Dogleg
 | 
					
						
							| 
									
										
										
										
											2015-06-19 00:51:22 +08:00
										 |  |  |   LevenbergMarquardtParams params = LevenbergMarquardtParams::LegacyDefaults(); | 
					
						
							| 
									
										
										
										
											2014-02-20 13:28:15 +08:00
										 |  |  |   { | 
					
						
							|  |  |  |     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
										 |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-06-19 00:51:22 +08:00
										 |  |  |     params.diagonalDamping = true; | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  |     LevenbergMarquardtOptimizer optimizer(fg, initBetter, params); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // test the diagonal
 | 
					
						
							|  |  |  |     GaussianFactorGraph::shared_ptr linear = optimizer.linearize(); | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  |     VectorValues d = linear->hessianDiagonal(); | 
					
						
							|  |  |  |     VectorValues sqrtHessianDiagonal = d; | 
					
						
							|  |  |  |     for (Vector& v : sqrtHessianDiagonal | map_values) v = v.cwiseSqrt(); | 
					
						
							|  |  |  |     GaussianFactorGraph damped = optimizer.buildDampedSystem(*linear, sqrtHessianDiagonal); | 
					
						
							|  |  |  |     VectorValues  expectedDiagonal = d + params.lambdaInitial * d; | 
					
						
							| 
									
										
										
										
											2014-03-14 10:43:51 +08:00
										 |  |  |     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!)
 | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  |     damped = optimizer.buildDampedSystem(*linear, sqrtHessianDiagonal); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  | TEST(NonlinearOptimizer, Pose2OptimizationWithHuberNoOutlier) { | 
					
						
							| 
									
										
										
										
											2012-11-07 06:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   fg.addPrior(0, Pose2(0,0,0), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(1,1.1,M_PI/4), | 
					
						
							| 
									
										
										
										
											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))); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(1,0.9,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; | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   init.insert(0, Pose2(0,0,0)); | 
					
						
							|  |  |  |   init.insert(1, Pose2(0.961187, 0.99965, 1.1781)); | 
					
						
							| 
									
										
										
										
											2012-11-07 06:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(0, Pose2(0,0,0)); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   expected.insert(1, Pose2(0.961187, 0.99965, 1.1781)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LevenbergMarquardtParams lm_params; | 
					
						
							| 
									
										
										
										
											2020-03-04 06:39:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   auto gn_result = GaussNewtonOptimizer(fg, init).optimize(); | 
					
						
							|  |  |  |   auto lm_result = LevenbergMarquardtOptimizer(fg, init, lm_params).optimize(); | 
					
						
							| 
									
										
										
										
											2020-03-04 06:39:28 +08:00
										 |  |  |   auto dl_result = DoglegOptimizer(fg, init).optimize(); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, gn_result, 3e-2)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, lm_result, 3e-2)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, dl_result, 3e-2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, Point2LinearOptimizationWithHuber) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   fg.addPrior(0, Point2(0,0), noiseModel::Isotropic::Sigma(2,0.01)); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   fg += BetweenFactor<Point2>(0, 1, Point2(1,1.8), | 
					
						
							|  |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(1.0), | 
					
						
							|  |  |  |                                                          noiseModel::Isotropic::Sigma(2,1))); | 
					
						
							|  |  |  |   fg += BetweenFactor<Point2>(0, 1, Point2(1,0.9), | 
					
						
							|  |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(1.0), | 
					
						
							|  |  |  |                                                          noiseModel::Isotropic::Sigma(2,1))); | 
					
						
							|  |  |  |   fg += BetweenFactor<Point2>(0, 1, Point2(1,90), | 
					
						
							|  |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(1.0), | 
					
						
							|  |  |  |                                                          noiseModel::Isotropic::Sigma(2,1))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   init.insert(0, Point2(1,1)); | 
					
						
							|  |  |  |   init.insert(1, Point2(1,0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(0, Point2(0,0)); | 
					
						
							|  |  |  |   expected.insert(1, Point2(1,1.85)); | 
					
						
							| 
									
										
										
										
											2012-11-07 06:42:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  |   LevenbergMarquardtParams params; | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   auto gn_result = GaussNewtonOptimizer(fg, init).optimize(); | 
					
						
							|  |  |  |   auto lm_result = LevenbergMarquardtOptimizer(fg, init, params).optimize(); | 
					
						
							|  |  |  |   auto dl_result = DoglegOptimizer(fg, init).optimize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, gn_result, 1e-4)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, lm_result, 1e-4)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, dl_result, 1e-4)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, Pose2OptimizationWithHuber) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   fg.addPrior(0, Pose2(0,0, 0), noiseModel::Isotropic::Sigma(3,0.1)); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(0,9, M_PI/2), | 
					
						
							|  |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(0.2), | 
					
						
							|  |  |  |                                                          noiseModel::Isotropic::Sigma(3,1))); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(0, 11, M_PI/2), | 
					
						
							|  |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(0.2), | 
					
						
							|  |  |  |                                                          noiseModel::Isotropic::Sigma(3,1))); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(0, 10, M_PI/2), | 
					
						
							|  |  |  |                              noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(0.2), | 
					
						
							|  |  |  |                                                         noiseModel::Isotropic::Sigma(3,1))); | 
					
						
							|  |  |  |   fg += BetweenFactor<Pose2>(0, 1, Pose2(0,9, 0), | 
					
						
							|  |  |  |                               noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(0.2), | 
					
						
							|  |  |  |                                                          noiseModel::Isotropic::Sigma(3,1))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   init.insert(0, Pose2(0, 0, 0)); | 
					
						
							|  |  |  |   init.insert(1, Pose2(0, 10, M_PI/4)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  |   expected.insert(0, Pose2(0, 0, 0)); | 
					
						
							|  |  |  |   expected.insert(1, Pose2(0, 10, 1.45212)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LevenbergMarquardtParams params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto gn_result = GaussNewtonOptimizer(fg, init).optimize(); | 
					
						
							|  |  |  |   auto lm_result = LevenbergMarquardtOptimizer(fg, init, params).optimize(); | 
					
						
							|  |  |  |   auto dl_result = DoglegOptimizer(fg, init).optimize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, gn_result, 1e-1)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, lm_result, 1e-1)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, dl_result, 1e-1)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, RobustMeanCalculation) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values expected; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto huber = noiseModel::Robust::Create(noiseModel::mEstimator::Huber::Create(20), | 
					
						
							|  |  |  |                                           noiseModel::Isotropic::Sigma(1, 1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vector<double> pts{-10,-3,-1,1,3,10,1000}; | 
					
						
							|  |  |  |   for(auto pt : pts) { | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |     fg.addPrior(0, pt, huber); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   init.insert(0, 100.0); | 
					
						
							|  |  |  |   expected.insert(0, 3.33333333); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-13 02:31:29 +08:00
										 |  |  |   DoglegParams params_dl; | 
					
						
							|  |  |  |   params_dl.setRelativeErrorTol(1e-10); | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   auto gn_result = GaussNewtonOptimizer(fg, init).optimize(); | 
					
						
							| 
									
										
										
										
											2020-07-13 02:31:29 +08:00
										 |  |  |   auto lm_result = LevenbergMarquardtOptimizer(fg, init).optimize(); | 
					
						
							|  |  |  |   auto dl_result = DoglegOptimizer(fg, init, params_dl).optimize(); | 
					
						
							| 
									
										
										
										
											2020-03-02 08:38:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 04:22:19 +08:00
										 |  |  |   EXPECT(assert_equal(expected, gn_result, tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, lm_result, tol)); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, dl_result, tol)); | 
					
						
							| 
									
										
										
										
											2012-11-07 06:42:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   graph.addPrior(X(1), Pose2(0.,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  |   graph += BetweenFactor<Pose2>(X(1),X(2), Pose2(1.5,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   graph.addPrior(X(3), Pose2(3.,0.,0.), noiseModel::Isotropic::Sigma(3,1)); | 
					
						
							| 
									
										
										
										
											2013-09-10 00:59:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, LevenbergMarquardtOptimizer(graph, init).optimize())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | #include <gtsam/linear/iterative.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-22 02:44:00 +08:00
										 |  |  | class IterativeLM : public LevenbergMarquardtOptimizer { | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  |   /// Solver specific parameters
 | 
					
						
							|  |  |  |   ConjugateGradientParameters cgParams_; | 
					
						
							| 
									
										
										
										
											2018-10-09 09:51:20 +08:00
										 |  |  |   Values initial_; | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-22 02:44:00 +08:00
										 |  |  |  public: | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  |   /// Constructor
 | 
					
						
							|  |  |  |   IterativeLM(const NonlinearFactorGraph& graph, const Values& initialValues, | 
					
						
							| 
									
										
										
										
											2020-05-22 02:44:00 +08:00
										 |  |  |               const ConjugateGradientParameters& p, | 
					
						
							|  |  |  |               const LevenbergMarquardtParams& params = | 
					
						
							|  |  |  |                   LevenbergMarquardtParams::LegacyDefaults()) | 
					
						
							|  |  |  |       : LevenbergMarquardtOptimizer(graph, initialValues, params), | 
					
						
							|  |  |  |         cgParams_(p), | 
					
						
							|  |  |  |         initial_(initialValues) {} | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /// Solve that uses conjugate gradient
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:57:54 +08:00
										 |  |  |   VectorValues solve(const GaussianFactorGraph& gfg, | 
					
						
							|  |  |  |                              const NonlinearOptimizerParams& params) const override { | 
					
						
							| 
									
										
										
										
											2018-10-09 09:51:20 +08:00
										 |  |  |     VectorValues zeros = initial_.zeroVectors(); | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  |     return conjugateGradientDescent(gfg, zeros, cgParams_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, subclass_solver) { | 
					
						
							|  |  |  |   Values expected; | 
					
						
							| 
									
										
										
										
											2020-05-22 02:44:00 +08:00
										 |  |  |   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.)); | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							| 
									
										
										
										
											2020-05-22 02:44:00 +08:00
										 |  |  |   init.insert(X(1), Pose2(0., 0., 0.)); | 
					
						
							|  |  |  |   init.insert(X(2), Pose2(0., 0., 0.)); | 
					
						
							|  |  |  |   init.insert(X(3), Pose2(0., 0., 0.)); | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   NonlinearFactorGraph graph; | 
					
						
							| 
									
										
										
										
											2020-05-22 02:44:00 +08:00
										 |  |  |   graph.addPrior(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.addPrior(X(3), Pose2(3., 0., 0.), noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2013-10-26 02:27:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ConjugateGradientParameters p; | 
					
						
							|  |  |  |   Values actual = IterativeLM(graph, init, p).optimize(); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expected, actual, 1e-4)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 23:40:22 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 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"); | 
					
						
							| 
									
										
										
										
											2015-06-19 00:51:22 +08:00
										 |  |  |   lmParams.logFile = filename; | 
					
						
							| 
									
										
										
										
											2013-10-30 23:40:22 +08:00
										 |  |  |   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());
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-17 02:23:02 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  | //// Minimal traits example
 | 
					
						
							| 
									
										
										
										
											2016-02-17 02:23:02 +08:00
										 |  |  | struct MyType : public Vector3 { | 
					
						
							|  |  |  |   using Vector3::Vector3; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | template <> | 
					
						
							|  |  |  | struct traits<MyType> { | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  |   static bool Equals(const MyType& a, const MyType& b, double tol) { | 
					
						
							|  |  |  |     return (a - b).array().abs().maxCoeff() < tol; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-02-17 02:23:02 +08:00
										 |  |  |   static void Print(const MyType&, const string&) {} | 
					
						
							| 
									
										
										
										
											2016-06-19 14:13:59 +08:00
										 |  |  |   static int GetDimension(const MyType&) { return 3; } | 
					
						
							|  |  |  |   static MyType Retract(const MyType& a, const Vector3& b) { return a + b; } | 
					
						
							|  |  |  |   static Vector3 Local(const MyType& a, const MyType& b) { return b - a; } | 
					
						
							| 
									
										
										
										
											2016-02-17 02:23:02 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(NonlinearOptimizer, Traits) { | 
					
						
							|  |  |  |   NonlinearFactorGraph fg; | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   fg.addPrior(0, MyType(0, 0, 0), noiseModel::Isotropic::Sigma(3, 1)); | 
					
						
							| 
									
										
										
										
											2016-02-17 02:23:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Values init; | 
					
						
							|  |  |  |   init.insert(0, MyType(0,0,0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LevenbergMarquardtOptimizer optimizer(fg, init); | 
					
						
							|  |  |  |   Values actual = optimizer.optimize(); | 
					
						
							|  |  |  |   EXPECT(assert_equal(init, actual)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ |