gtsam/cpp/testNonlinearFactorGraph.cpp

171 lines
4.8 KiB
C++

/**
* @file testNonlinearFactorGraph.cpp
* @brief Unit tests for Non-Linear Factor Graph
* @brief testNonlinearFactorGraph
* @author Carlos Nieto
* @author Christian Potthast
*/
/*STL/C++*/
#include <iostream>
using namespace std;
#include <CppUnitLite/TestHarness.h>
#include "Matrix.h"
#include "smallExample.h"
using namespace gtsam;
/* ************************************************************************* */
TEST( NonlinearFactorGraph, equals ){
NonlinearFactorGraph fg = createNonlinearFactorGraph();
NonlinearFactorGraph fg2 = createNonlinearFactorGraph();
CHECK( fg.equals(fg2) );
}
/* ************************************************************************* */
TEST( NonlinearFactorGraph, error )
{
NonlinearFactorGraph fg = createNonlinearFactorGraph();
FGConfig c1 = createConfig();
double actual1 = fg.error(c1);
DOUBLES_EQUAL( 0.0, actual1, 1e-9 );
FGConfig c2 = createNoisyConfig();
double actual2 = fg.error(c2);
DOUBLES_EQUAL( 5.625, actual2, 1e-9 );
}
/* ************************************************************************* */
TEST( NonlinearFactorGraph, probPrime )
{
NonlinearFactorGraph fg = createNonlinearFactorGraph();
FGConfig cfg = createConfig();
// evaluate the probability of the factor graph
double actual = fg.probPrime(cfg);
double expected = 1.0;
DOUBLES_EQUAL(expected,actual,0);
}
/* ************************************************************************* */
TEST( NonlinearFactorGraph, linearize )
{
NonlinearFactorGraph fg = createNonlinearFactorGraph();
FGConfig initial = createNoisyConfig();
LinearFactorGraph linearized = fg.linearize(initial);
LinearFactorGraph expected = createLinearFactorGraph();
CHECK(expected.equals(linearized));
}
/* ************************************************************************* */
TEST( NonlinearFactorGraph, iterate )
{
NonlinearFactorGraph fg = createNonlinearFactorGraph();
FGConfig initial = createNoisyConfig();
// Expected configuration is the difference between the noisy config
// and the ground-truth config. One step only because it's linear !
FGConfig expected;
Vector dl1(2); dl1(0)=-0.1; dl1(1)= 0.1; expected.insert("l1",dl1);
Vector dx1(2); dx1(0)=-0.1; dx1(1)=-0.1; expected.insert("x1",dx1);
Vector dx2(2); dx2(0)= 0.1; dx2(1)=-0.2; expected.insert("x2",dx2);
// Check one ordering
Ordering ord1;
ord1.push_back("x2");
ord1.push_back("l1");
ord1.push_back("x1");
FGConfig actual1 = fg.iterate(initial, ord1);
CHECK(actual1.equals(expected));
// Check another
Ordering ord2;
ord2.push_back("x1");
ord2.push_back("x2");
ord2.push_back("l1");
FGConfig actual2 = fg.iterate(initial, ord2);
CHECK(actual2.equals(expected));
// And yet another...
Ordering ord3;
ord3.push_back("l1");
ord3.push_back("x1");
ord3.push_back("x2");
FGConfig actual3 = fg.iterate(initial, ord3);
CHECK(actual3.equals(expected));
}
/* ************************************************************************* */
TEST( NonlinearFactorGraph, optimize ) {
NonlinearFactorGraph fg = createReallyNonlinearFactorGraph();
// test error at minimum
Vector xstar = Vector_(1,0.0);
FGConfig cstar;
cstar.insert("x",xstar);
DOUBLES_EQUAL(0.0,fg.error(cstar),0.0);
// test error at initial = [(1-cos(3))^2 + (sin(3))^2]*50 =
Vector x0 = Vector_(1,3.0);
FGConfig c0;
c0.insert("x",x0);
DOUBLES_EQUAL(199.0,fg.error(c0),1e-3);
// optimize parameters
Ordering ord;
ord.push_back("x");
double relativeErrorTreshold = 1e-5;
double absoluteErrorTreshold = 1e-5;
// Gauss-Newton
FGConfig actual = c0;
fg.optimize(actual,ord,relativeErrorTreshold,absoluteErrorTreshold);
CHECK(actual.equals(cstar));
// Levenberg-Marquardt
FGConfig actual2 = c0;
double lambda0 = 1000, lambdaFactor = 10;
fg.optimizeLM(actual2,ord,relativeErrorTreshold,absoluteErrorTreshold,0,lambda0,lambdaFactor);
CHECK(actual2.equals(cstar));
}
/* ************************************************************************* */
TEST( NonlinearFactorGraph, iterateLM ) {
// really non-linear factor graph
NonlinearFactorGraph fg = createReallyNonlinearFactorGraph();
// config far from minimum
Vector x0 = Vector_(1,3.0);
FGConfig config;
config.insert("x",x0);
// ordering
Ordering ord;
ord.push_back("x");
// normal iterate
int verbosity = 0;
FGConfig actual1 = config;
fg.iterate(actual1,ord,verbosity);
// LM iterate with lambda 0 should be the same
FGConfig actual2 = config;
double lambda0 = 0, lambdaFactor = 10;
double currentError = fg.error(actual2);
fg.iterateLM(actual2, currentError, lambda0, lambdaFactor, ord, verbosity);
CHECK(actual1.equals(actual2));
}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */