2012-09-04 02:01:24 +08:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
2019-02-11 22:39:48 +08:00
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
2012-09-04 02:01:24 +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
|
|
|
|
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file testIterative.cpp
|
|
|
|
* @brief Unit tests for iterative methods
|
|
|
|
* @author Frank Dellaert
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <tests/smallExample.h>
|
2012-09-05 11:06:22 +08:00
|
|
|
#include <gtsam/slam/BetweenFactor.h>
|
|
|
|
#include <gtsam/nonlinear/NonlinearEquality.h>
|
2013-08-19 23:32:16 +08:00
|
|
|
#include <gtsam/inference/Symbol.h>
|
2012-09-05 11:06:22 +08:00
|
|
|
#include <gtsam/linear/iterative.h>
|
|
|
|
#include <gtsam/geometry/Pose2.h>
|
2012-09-04 02:01:24 +08:00
|
|
|
|
|
|
|
#include <CppUnitLite/TestHarness.h>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace gtsam;
|
|
|
|
using namespace example;
|
|
|
|
using symbol_shorthand::X; // to create pose keys
|
|
|
|
using symbol_shorthand::L; // to create landmark keys
|
|
|
|
|
2012-09-05 11:06:22 +08:00
|
|
|
static ConjugateGradientParameters parameters;
|
|
|
|
// add following below to add printing:
|
|
|
|
// parameters.verbosity_ = ConjugateGradientParameters::COMPLEXITY;
|
2012-09-04 02:01:24 +08:00
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
TEST( Iterative, steepestDescent )
|
|
|
|
{
|
2012-10-02 22:40:07 +08:00
|
|
|
// Create factor graph
|
2013-08-06 21:44:22 +08:00
|
|
|
GaussianFactorGraph fg = createGaussianFactorGraph();
|
2012-09-04 02:01:24 +08:00
|
|
|
|
|
|
|
// eliminate and solve
|
2013-08-06 21:44:22 +08:00
|
|
|
VectorValues expected = fg.optimize();
|
2012-09-04 02:01:24 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
// Do gradient descent
|
2013-08-06 06:31:44 +08:00
|
|
|
VectorValues zero = VectorValues::Zero(expected); // TODO, how do we do this normally?
|
|
|
|
VectorValues actual = steepestDescent(fg, zero, parameters);
|
2012-10-02 22:40:07 +08:00
|
|
|
CHECK(assert_equal(expected,actual,1e-2));
|
2012-09-04 02:01:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
TEST( Iterative, conjugateGradientDescent )
|
|
|
|
{
|
2012-09-05 11:06:22 +08:00
|
|
|
// Create factor graph
|
2013-08-06 21:44:22 +08:00
|
|
|
GaussianFactorGraph fg = createGaussianFactorGraph();
|
2012-09-05 11:06:22 +08:00
|
|
|
|
|
|
|
// eliminate and solve
|
2013-08-06 21:44:22 +08:00
|
|
|
VectorValues expected = fg.optimize();
|
2012-09-05 11:06:22 +08:00
|
|
|
|
|
|
|
// get matrices
|
2016-04-16 04:54:46 +08:00
|
|
|
Vector x0 = Z_6x1;
|
2023-02-05 01:42:39 +08:00
|
|
|
const auto [A, b] = fg.jacobian();
|
2014-11-23 08:35:27 +08:00
|
|
|
Vector expectedX = (Vector(6) << -0.1, 0.1, -0.1, -0.1, 0.1, -0.2).finished();
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// Do conjugate gradient descent, System version
|
|
|
|
System Ab(A, b);
|
|
|
|
Vector actualX = conjugateGradientDescent(Ab, x0, parameters);
|
|
|
|
CHECK(assert_equal(expectedX,actualX,1e-9));
|
|
|
|
|
|
|
|
// Do conjugate gradient descent, Matrix version
|
|
|
|
Vector actualX2 = conjugateGradientDescent(A, b, x0, parameters);
|
|
|
|
CHECK(assert_equal(expectedX,actualX2,1e-9));
|
|
|
|
|
|
|
|
// Do conjugate gradient descent on factor graph
|
2013-08-06 06:31:44 +08:00
|
|
|
VectorValues zero = VectorValues::Zero(expected);
|
|
|
|
VectorValues actual = conjugateGradientDescent(fg, zero, parameters);
|
2012-10-02 22:40:07 +08:00
|
|
|
CHECK(assert_equal(expected,actual,1e-2));
|
2012-09-04 02:01:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2012-09-05 11:06:22 +08:00
|
|
|
TEST( Iterative, conjugateGradientDescent_hard_constraint )
|
2012-09-04 02:01:24 +08:00
|
|
|
{
|
2012-09-05 11:06:22 +08:00
|
|
|
Values config;
|
|
|
|
Pose2 pose1 = Pose2(0.,0.,0.);
|
|
|
|
config.insert(X(1), pose1);
|
|
|
|
config.insert(X(2), Pose2(1.5,0.,0.));
|
2012-09-04 02:01:24 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
NonlinearFactorGraph graph;
|
2023-02-06 16:40:32 +08:00
|
|
|
graph.emplace_shared<NonlinearEquality<Pose2>>(X(1), pose1);
|
|
|
|
graph.emplace_shared<BetweenFactor<Pose2>>(X(1),X(2), Pose2(1.,0.,0.), noiseModel::Isotropic::Sigma(3, 1));
|
2012-09-04 02:01:24 +08:00
|
|
|
|
2023-01-18 06:05:12 +08:00
|
|
|
std::shared_ptr<GaussianFactorGraph> fg = graph.linearize(config);
|
2012-09-04 02:01:24 +08:00
|
|
|
|
2013-08-06 21:44:22 +08:00
|
|
|
VectorValues zeros = config.zeroVectors();
|
2012-09-04 02:01:24 +08:00
|
|
|
|
2012-09-05 11:06:22 +08:00
|
|
|
ConjugateGradientParameters parameters;
|
2024-10-16 11:43:52 +08:00
|
|
|
parameters.epsilon_abs = 1e-3;
|
|
|
|
parameters.epsilon_rel = 1e-5;
|
|
|
|
parameters.maxIterations = 100;
|
2013-08-06 06:31:44 +08:00
|
|
|
VectorValues actual = conjugateGradientDescent(*fg, zeros, parameters);
|
2012-09-05 11:06:22 +08:00
|
|
|
|
2013-08-06 06:31:44 +08:00
|
|
|
VectorValues expected;
|
2016-04-16 04:54:46 +08:00
|
|
|
expected.insert(X(1), Z_3x1);
|
2014-11-24 02:22:25 +08:00
|
|
|
expected.insert(X(2), Vector3(-0.5,0.,0.));
|
2012-09-05 11:06:22 +08:00
|
|
|
CHECK(assert_equal(expected, actual));
|
|
|
|
}
|
2012-09-04 02:01:24 +08:00
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
TEST( Iterative, conjugateGradientDescent_soft_constraint )
|
|
|
|
{
|
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.));
|
2012-09-04 02:01:24 +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));
|
2023-02-06 16:40:32 +08:00
|
|
|
graph.emplace_shared<BetweenFactor<Pose2>>(X(1),X(2), Pose2(1.,0.,0.), noiseModel::Isotropic::Sigma(3, 1));
|
2012-09-05 11:06:22 +08:00
|
|
|
|
2023-01-18 06:05:12 +08:00
|
|
|
std::shared_ptr<GaussianFactorGraph> fg = graph.linearize(config);
|
2012-09-05 11:06:22 +08:00
|
|
|
|
2013-08-06 21:44:22 +08:00
|
|
|
VectorValues zeros = config.zeroVectors();
|
2012-09-05 11:06:22 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
ConjugateGradientParameters parameters;
|
2024-10-16 11:43:52 +08:00
|
|
|
parameters.epsilon_abs = 1e-3;
|
|
|
|
parameters.epsilon_rel = 1e-5;
|
|
|
|
parameters.maxIterations = 100;
|
2013-08-06 06:31:44 +08:00
|
|
|
VectorValues actual = conjugateGradientDescent(*fg, zeros, parameters);
|
2012-09-05 11:06:22 +08:00
|
|
|
|
2013-08-06 06:31:44 +08:00
|
|
|
VectorValues expected;
|
2016-04-16 04:54:46 +08:00
|
|
|
expected.insert(X(1), Z_3x1);
|
2014-11-24 02:22:25 +08:00
|
|
|
expected.insert(X(2), Vector3(-0.5,0.,0.));
|
2012-10-02 22:40:07 +08:00
|
|
|
CHECK(assert_equal(expected, actual));
|
2012-09-04 02:01:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
int main() {
|
2012-10-02 22:40:07 +08:00
|
|
|
TestResult tr;
|
|
|
|
return TestRegistry::runAllTests(tr);
|
2012-09-04 02:01:24 +08:00
|
|
|
}
|
|
|
|
/* ************************************************************************* */
|