140 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
/* ----------------------------------------------------------------------------
 | 
						|
 | 
						|
 * 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
 | 
						|
 | 
						|
 * -------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 *  @file  testSmartRangeFactor.cpp
 | 
						|
 *  @brief Unit tests for SmartRangeFactor Class
 | 
						|
 *  @author Frank Dellaert
 | 
						|
 *  @date Nov 2013
 | 
						|
 */
 | 
						|
 | 
						|
#include <gtsam_unstable/slam/SmartRangeFactor.h>
 | 
						|
#include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
						|
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
 | 
						|
#include <gtsam/slam/PriorFactor.h>
 | 
						|
#include <CppUnitLite/TestHarness.h>
 | 
						|
 | 
						|
using namespace std;
 | 
						|
using namespace gtsam;
 | 
						|
 | 
						|
static const double sigma = 2.0;
 | 
						|
 | 
						|
// Test situation:
 | 
						|
static const Point2 p(0, 10);
 | 
						|
static const Pose2 pose1(0, 0, 0), pose2(5, 0, 0), pose3(5, 5, 0);
 | 
						|
static const double r1 = pose1.range(p), r2 = pose2.range(p), r3 = pose3.range(
 | 
						|
    p);
 | 
						|
 | 
						|
/* ************************************************************************* */
 | 
						|
 | 
						|
TEST( SmartRangeFactor, constructor ) {
 | 
						|
  SmartRangeFactor f1;
 | 
						|
  LONGS_EQUAL(0, f1.size())
 | 
						|
  SmartRangeFactor f2(sigma);
 | 
						|
  LONGS_EQUAL(0, f2.size())
 | 
						|
}
 | 
						|
/* ************************************************************************* */
 | 
						|
 | 
						|
TEST( SmartRangeFactor, addRange ) {
 | 
						|
  SmartRangeFactor f(sigma);
 | 
						|
  f.addRange(1, 10);
 | 
						|
  f.addRange(1, 12);
 | 
						|
  LONGS_EQUAL(2, f.size())
 | 
						|
}
 | 
						|
/* ************************************************************************* */
 | 
						|
 | 
						|
TEST( SmartRangeFactor, scenario ) {
 | 
						|
  DOUBLES_EQUAL(10, r1, 1e-9);
 | 
						|
  DOUBLES_EQUAL(sqrt(100.0+25.0), r2, 1e-9);
 | 
						|
  DOUBLES_EQUAL(sqrt(50.0), r3, 1e-9);
 | 
						|
}
 | 
						|
/* ************************************************************************* */
 | 
						|
 | 
						|
TEST( SmartRangeFactor, unwhitenedError ) {
 | 
						|
  Values values; // all correct
 | 
						|
  values.insert(1, pose1);
 | 
						|
  values.insert(2, pose2);
 | 
						|
  values.insert(3, pose3);
 | 
						|
 | 
						|
  SmartRangeFactor f(sigma);
 | 
						|
  f.addRange(1, r1);
 | 
						|
 | 
						|
  // Check Jacobian for n==1
 | 
						|
  vector<Matrix> H1(1);
 | 
						|
  f.unwhitenedError(values, H1); // with H now !
 | 
						|
  CHECK(assert_equal(zeros(3,1), H1.front()));
 | 
						|
 | 
						|
  // Whenever there are two ranges or less, error should be zero
 | 
						|
  Vector actual1 = f.unwhitenedError(values);
 | 
						|
  EXPECT(assert_equal((Vector(1) << 0.0), actual1));
 | 
						|
  f.addRange(2, r2);
 | 
						|
  Vector actual2 = f.unwhitenedError(values);
 | 
						|
  EXPECT(assert_equal((Vector(1) << 0.0), actual2));
 | 
						|
 | 
						|
  f.addRange(3, r3);
 | 
						|
  vector<Matrix> H(3);
 | 
						|
  Vector actual3 = f.unwhitenedError(values);
 | 
						|
  EXPECT_LONGS_EQUAL(3, f.keys().size());
 | 
						|
  EXPECT(assert_equal((Vector(1) << 0.0), actual3));
 | 
						|
 | 
						|
  // Check keys and Jacobian
 | 
						|
  Vector actual4 = f.unwhitenedError(values, H); // with H now !
 | 
						|
  EXPECT(assert_equal((Vector(1) << 0.0), actual4));
 | 
						|
  CHECK(assert_equal((Matrix(1, 3) << 0.0,-1.0,0.0), H.front()));
 | 
						|
  CHECK(assert_equal((Matrix(1, 3) << sqrt(2.0)/2,-sqrt(2.0)/2,0.0), H.back()));
 | 
						|
 | 
						|
  // Test clone
 | 
						|
  NonlinearFactor::shared_ptr clone = f.clone();
 | 
						|
  EXPECT_LONGS_EQUAL(3, clone->keys().size());
 | 
						|
}
 | 
						|
/* ************************************************************************* */
 | 
						|
 | 
						|
TEST( SmartRangeFactor, optimization ) {
 | 
						|
  SmartRangeFactor f(sigma);
 | 
						|
  f.addRange(1, r1);
 | 
						|
  f.addRange(2, r2);
 | 
						|
  f.addRange(3, r3);
 | 
						|
 | 
						|
  // Create initial value for optimization
 | 
						|
  Values initial;
 | 
						|
  initial.insert(1, pose1);
 | 
						|
  initial.insert(2, pose2);
 | 
						|
  initial.insert(3, Pose2(5, 6, 0)); // does not satisfy range measurement
 | 
						|
  Vector actual5 = f.unwhitenedError(initial);
 | 
						|
  EXPECT(assert_equal((Vector(1) << sqrt(25.0+16.0)-sqrt(50.0)), actual5));
 | 
						|
 | 
						|
  // Create Factor graph
 | 
						|
  NonlinearFactorGraph graph;
 | 
						|
  graph.push_back(f);
 | 
						|
  const noiseModel::Base::shared_ptr //
 | 
						|
  priorNoise = noiseModel::Diagonal::Sigmas(Vector3(1, 1, M_PI));
 | 
						|
  graph.push_back(PriorFactor<Pose2>(1, pose1, priorNoise));
 | 
						|
  graph.push_back(PriorFactor<Pose2>(2, pose2, priorNoise));
 | 
						|
 | 
						|
  // Try optimizing
 | 
						|
  LevenbergMarquardtParams params;
 | 
						|
  //  params.setVerbosity("ERROR");
 | 
						|
  LevenbergMarquardtOptimizer optimizer(graph, initial, params);
 | 
						|
  Values result = optimizer.optimize();
 | 
						|
  EXPECT(assert_equal(initial.at<Pose2>(1), result.at<Pose2>(1)));
 | 
						|
  EXPECT(assert_equal(initial.at<Pose2>(2), result.at<Pose2>(2)));
 | 
						|
  // only the third pose will be changed, converges on following:
 | 
						|
  EXPECT(assert_equal(Pose2(5.52159, 5.582727, 0), result.at<Pose2>(3),1e-5));
 | 
						|
}
 | 
						|
 | 
						|
/* ************************************************************************* */
 | 
						|
int main() {
 | 
						|
  TestResult tr;
 | 
						|
  return TestRegistry::runAllTests(tr);
 | 
						|
}
 | 
						|
/* ************************************************************************* */
 | 
						|
 |