Remove a whole lot of copy/paste

release/4.3a0
dellaert 2015-02-23 20:43:31 +01:00
parent f21ba05679
commit a60e13dd09
1 changed files with 256 additions and 284 deletions

View File

@ -18,10 +18,7 @@
* @date Sept 2013
*/
//#include "BundlerDefinitions.h"
#include <gtsam/slam/SmartProjectionCameraFactor.h>
//#include "../SmartFactorsTestProblems.h"
//#include "../LevenbergMarquardtOptimizerCERES.h"
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/slam/PoseTranslationPrior.h>
@ -39,17 +36,11 @@ using namespace std;
using namespace boost::assign;
using namespace gtsam;
typedef PinholeCamera<Cal3Bundler> Camera;
static bool isDebugTest = false;
// make a realistic calibration matrix
static double fov = 60; // degrees
static size_t w=640,h=480;
static Cal3_S2::shared_ptr K(new Cal3_S2(fov,w,h));
static Cal3_S2::shared_ptr K2(new Cal3_S2(1500, 1200, 0, 640, 480));
static boost::shared_ptr<Cal3Bundler> Kbundler(new Cal3Bundler(500, 1e-3, 1e-3, 0, 0));
static size_t w = 640, h = 480;
static double rankTol = 1.0;
static double linThreshold = -1.0;
@ -61,20 +52,20 @@ static SharedNoiseModel model(noiseModel::Unit::Create(2));
using symbol_shorthand::X;
using symbol_shorthand::L;
// tests data
Key x1 = 1;
static Key x1(1);
Symbol l1('l', 1), l2('l', 2), l3('l', 3);
Key c1 = 1, c2 = 2, c3 = 3;
static Key poseKey1(x1);
static Point2 measurement1(323.0, 240.0);
static Pose3 body_P_sensor1(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2), Point3(0.25, -0.10, 1.0));
// First camera pose, looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1));
// Second camera 1 meter to the right of first camera
Pose3 pose_right = level_pose * Pose3(Rot3(), Point3(1, 0, 0));
// Third camera 1 meter above the first camera
Pose3 pose_up = level_pose * Pose3(Rot3(), Point3(0, -1, 0));
typedef PinholeCamera<Cal3_S2> CameraCal3_S2;
typedef SmartProjectionCameraFactor<Cal3_S2> SmartFactor;
typedef SmartProjectionCameraFactor<Cal3Bundler> SmartFactorBundler;
typedef GeneralSFMFactor<Camera, Point3> SFMFactor;
static Point2 measurement1(323.0, 240.0);
static Pose3 body_P_sensor1(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2),
Point3(0.25, -0.10, 1.0));
template<class CALIBRATION>
PinholeCamera<CALIBRATION> perturbCameraPose(
@ -95,7 +86,8 @@ PinholeCamera<CALIBRATION> perturbCameraPoseAndCalibration(
Pose3 cameraPose = camera.pose();
Pose3 perturbedCameraPose = cameraPose.compose(noise_pose);
typename gtsam::traits<CALIBRATION>::TangentVector d;
d.setRandom(); d*=0.1;
d.setRandom();
d *= 0.1;
CALIBRATION perturbedCalibration = camera.calibration().retract(d);
return PinholeCamera<CALIBRATION>(perturbedCameraPose, perturbedCalibration);
}
@ -114,70 +106,83 @@ void projectToMultipleCameras(const PinholeCamera<CALIBRATION>& cam1,
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, perturbCameraPose) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
CameraCal3_S2 level_camera(level_pose, *K2);
Pose3 noise_pose = Pose3(Rot3::ypr(-M_PI/10, 0., -M_PI/10), Point3(0.5,0.1,0.3));
Pose3 perturbed_level_pose = level_pose.compose(noise_pose);
CameraCal3_S2 actualCamera(perturbed_level_pose, *K2);
// default Cal3_S2 cameras
namespace vanilla {
typedef PinholeCamera<Cal3_S2> Camera;
static Cal3_S2 K(fov, w, h);
static Cal3_S2 K2(1500, 1200, 0, 640, 480);
Camera level_camera(level_pose, K2);
Camera level_camera_right(pose_right, K2);
Camera cam1(level_pose, K2);
Camera cam2(pose_right, K2);
Camera cam3(pose_up, K2);
typedef GeneralSFMFactor<Camera, Point3> SFMFactor;
typedef SmartProjectionCameraFactor<Cal3_S2> SmartFactor;
}
CameraCal3_S2 expectedCamera = perturbCameraPose(level_camera);
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, perturbCameraPose) {
using namespace vanilla;
Pose3 noise_pose = Pose3(Rot3::ypr(-M_PI / 10, 0., -M_PI / 10),
Point3(0.5, 0.1, 0.3));
Pose3 perturbed_level_pose = level_pose.compose(noise_pose);
Camera actualCamera(perturbed_level_pose, K2);
Camera expectedCamera = perturbCameraPose(level_camera);
CHECK(assert_equal(expectedCamera, actualCamera));
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, Constructor) {
using namespace vanilla;
SmartFactor::shared_ptr factor1(new SmartFactor());
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, Constructor2) {
using namespace vanilla;
SmartFactor factor1(rankTol, linThreshold);
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, Constructor3) {
using namespace vanilla;
SmartFactor::shared_ptr factor1(new SmartFactor());
factor1->add(measurement1, poseKey1, model);
factor1->add(measurement1, x1, model);
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, Constructor4) {
using namespace vanilla;
SmartFactor factor1(rankTol, linThreshold);
factor1.add(measurement1, poseKey1, model);
factor1.add(measurement1, x1, model);
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, ConstructorWithTransform) {
using namespace vanilla;
bool manageDegeneracy = true;
bool isImplicit = false;
bool enableEPI = false;
SmartFactor factor1(rankTol, linThreshold, manageDegeneracy, isImplicit, enableEPI, body_P_sensor1);
factor1.add(measurement1, poseKey1, model);
SmartFactor factor1(rankTol, linThreshold, manageDegeneracy, isImplicit,
enableEPI, body_P_sensor1);
factor1.add(measurement1, x1, model);
}
/* ************************************************************************* */
TEST( SmartProjectionCameraFactor, Equals ) {
using namespace vanilla;
SmartFactor::shared_ptr factor1(new SmartFactor());
factor1->add(measurement1, poseKey1, model);
factor1->add(measurement1, x1, model);
SmartFactor::shared_ptr factor2(new SmartFactor());
factor2->add(measurement1, poseKey1, model);
//CHECK(assert_equal(*factor1, *factor2));
factor2->add(measurement1, x1, model);
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, noiseless ){
TEST( SmartProjectionCameraFactor, noiseless ) {
// cout << " ************************ SmartProjectionCameraFactor: noisy ****************************" << endl;
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
CameraCal3_S2 level_camera(level_pose, *K2);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
CameraCal3_S2 level_camera_right(level_pose_right, *K2);
using namespace vanilla;
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
@ -194,90 +199,41 @@ TEST( SmartProjectionCameraFactor, noiseless ){
factor1->add(level_uv, c1, model);
factor1->add(level_uv_right, c2, model);
double actualError = factor1->error(values);
double expectedError = 0.0;
DOUBLES_EQUAL(expectedError, actualError, 1e-7);
DOUBLES_EQUAL(expectedError, factor1->error(values), 1e-7);
CHECK(assert_equal(zero(4), factor1->reprojectionError(values), 1e-7));
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, noiselessBundler ){
TEST( SmartProjectionCameraFactor, noisy ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera level_camera(level_pose, *Kbundler);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
Camera level_camera_right(level_pose_right, *Kbundler);
using namespace vanilla;
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
// 1. Project two landmarks into two cameras and triangulate
Point2 level_uv = level_camera.project(landmark);
Point2 level_uv_right = level_camera_right.project(landmark);
Values values;
values.insert(c1, level_camera);
values.insert(c2, level_camera_right);
SmartFactorBundler::shared_ptr factor1(new SmartFactorBundler());
factor1->add(level_uv, c1, model);
factor1->add(level_uv_right, c2, model);
double actualError = factor1->error(values);
double expectedError = 0.0;
DOUBLES_EQUAL(expectedError, actualError, 1e-3);
Point3 oldPoint; // this takes the point stored in the factor (we are not interested in this)
if(factor1->point())
oldPoint = *(factor1->point());
Point3 expectedPoint;
if(factor1->point(values))
expectedPoint = *(factor1->point(values));
EXPECT(assert_equal(expectedPoint,landmark, 1e-3));
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, noisy ){
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
CameraCal3_S2 level_camera(level_pose, *K2);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
CameraCal3_S2 level_camera_right(level_pose_right, *K2);
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
// 1. Project two landmarks into two cameras and triangulate
Point2 pixelError(0.2,0.2);
Point2 pixelError(0.2, 0.2);
Point2 level_uv = level_camera.project(landmark) + pixelError;
Point2 level_uv_right = level_camera_right.project(landmark);
Values values;
values.insert(c1, level_camera);
CameraCal3_S2 perturbed_level_camera_right = perturbCameraPose(level_camera_right);
Camera perturbed_level_camera_right = perturbCameraPose(level_camera_right);
values.insert(c2, perturbed_level_camera_right);
SmartFactor::shared_ptr factor1(new SmartFactor());
factor1->add(level_uv, c1, model);
factor1->add(level_uv_right, c2, model);
double actualError1= factor1->error(values);
double actualError1 = factor1->error(values);
SmartFactor::shared_ptr factor2(new SmartFactor());
vector<Point2> measurements;
measurements.push_back(level_uv);
measurements.push_back(level_uv_right);
vector< SharedNoiseModel > noises;
vector<SharedNoiseModel> noises;
noises.push_back(model);
noises.push_back(model);
@ -287,26 +243,15 @@ TEST( SmartProjectionCameraFactor, noisy ){
factor2->add(measurements, views, noises);
double actualError2= factor2->error(values);
double actualError2 = factor2->error(values);
DOUBLES_EQUAL(actualError1, actualError2, 1e-7);
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, perturbPoseAndOptimize ){
TEST( SmartProjectionCameraFactor, perturbPoseAndOptimize ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 pose1 = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
CameraCal3_S2 cam1(pose1, *K2);
// create second camera 1 meter to the right of first camera
Pose3 pose2 = pose1 * Pose3(Rot3(), Point3(1,0,0));
CameraCal3_S2 cam2(pose2, *K2);
// create third camera 1 meter above the first camera
Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0,-1,0));
CameraCal3_S2 cam3(pose3, *K2);
using namespace vanilla;
// three landmarks ~5 meters infront of camera
Point3 landmark1(5, 0.5, 1.2);
@ -334,24 +279,27 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimize ){
SmartFactor::shared_ptr smartFactor3(new SmartFactor());
smartFactor3->add(measurements_cam3, views, model);
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6+5, 1e-5);
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6 + 5, 1e-5);
NonlinearFactorGraph graph;
graph.push_back(smartFactor1);
graph.push_back(smartFactor2);
graph.push_back(smartFactor3);
graph.push_back(PriorFactor<CameraCal3_S2>(c1, cam1, noisePrior));
graph.push_back(PriorFactor<CameraCal3_S2>(c2, cam2, noisePrior));
graph.push_back(PriorFactor<Camera>(c1, cam1, noisePrior));
graph.push_back(PriorFactor<Camera>(c2, cam2, noisePrior));
Values values;
values.insert(c1, cam1);
values.insert(c2, cam2);
values.insert(c3, perturbCameraPose(cam3));
if(isDebugTest) values.at<CameraCal3_S2>(c3).print("Smart: Pose3 before optimization: ");
if (isDebugTest)
values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
LevenbergMarquardtParams params;
if(isDebugTest) params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if(isDebugTest) params.verbosity = NonlinearOptimizerParams::ERROR;
if (isDebugTest)
params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if (isDebugTest)
params.verbosity = NonlinearOptimizerParams::ERROR;
Values result;
gttic_(SmartProjectionCameraFactor);
@ -363,28 +311,21 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimize ){
// GaussianFactorGraph::shared_ptr GFG = graph.linearize(values);
// VectorValues delta = GFG->optimize();
if(isDebugTest) result.at<CameraCal3_S2>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1,result.at<CameraCal3_S2>(c1)));
EXPECT(assert_equal(cam2,result.at<CameraCal3_S2>(c2)));
EXPECT(assert_equal(result.at<CameraCal3_S2>(c3).pose(), cam3.pose(), 1e-4));
EXPECT(assert_equal(result.at<CameraCal3_S2>(c3).calibration(), cam3.calibration(), 2));
if(isDebugTest) tictoc_print_();
if (isDebugTest)
result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1, result.at<Camera>(c1)));
EXPECT(assert_equal(cam2, result.at<Camera>(c2)));
EXPECT(assert_equal(result.at<Camera>(c3).pose(), cam3.pose(), 1e-4));
EXPECT(
assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 2));
if (isDebugTest)
tictoc_print_();
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ){
TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 pose1 = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
CameraCal3_S2 cam1(pose1, *K2);
// create second camera 1 meter to the right of first camera
Pose3 pose2 = pose1 * Pose3(Rot3(), Point3(1,0,0));
CameraCal3_S2 cam2(pose2, *K2);
// create third camera 1 meter above the first camera
Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0,-1,0));
CameraCal3_S2 cam3(pose3, *K2);
using namespace vanilla;
// three landmarks ~5 meters infront of camera
Point3 landmark1(5, 0.5, 1.2);
@ -403,9 +344,9 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ){
views.push_back(c3);
SfM_Track track1;
for(size_t i=0;i<3;++i){
for (size_t i = 0; i < 3; ++i) {
SfM_Measurement measures;
measures.first = i+1;// cameras are from 1 to 3
measures.first = i + 1; // cameras are from 1 to 3
measures.second = measurements_cam1.at(i);
track1.measurements.push_back(measures);
}
@ -413,9 +354,9 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ){
smartFactor1->add(track1, model);
SfM_Track track2;
for(size_t i=0;i<3;++i){
for (size_t i = 0; i < 3; ++i) {
SfM_Measurement measures;
measures.first = i+1;// cameras are from 1 to 3
measures.first = i + 1; // cameras are from 1 to 3
measures.second = measurements_cam2.at(i);
track2.measurements.push_back(measures);
}
@ -425,24 +366,27 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ){
SmartFactor::shared_ptr smartFactor3(new SmartFactor());
smartFactor3->add(measurements_cam3, views, model);
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6+5, 1e-5);
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6 + 5, 1e-5);
NonlinearFactorGraph graph;
graph.push_back(smartFactor1);
graph.push_back(smartFactor2);
graph.push_back(smartFactor3);
graph.push_back(PriorFactor<CameraCal3_S2>(c1, cam1, noisePrior));
graph.push_back(PriorFactor<CameraCal3_S2>(c2, cam2, noisePrior));
graph.push_back(PriorFactor<Camera>(c1, cam1, noisePrior));
graph.push_back(PriorFactor<Camera>(c2, cam2, noisePrior));
Values values;
values.insert(c1, cam1);
values.insert(c2, cam2);
values.insert(c3, perturbCameraPose(cam3));
if(isDebugTest) values.at<CameraCal3_S2>(c3).print("Smart: Pose3 before optimization: ");
if (isDebugTest)
values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
LevenbergMarquardtParams params;
if(isDebugTest) params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if(isDebugTest) params.verbosity = NonlinearOptimizerParams::ERROR;
if (isDebugTest)
params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if (isDebugTest)
params.verbosity = NonlinearOptimizerParams::ERROR;
Values result;
gttic_(SmartProjectionCameraFactor);
@ -454,28 +398,21 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ){
// GaussianFactorGraph::shared_ptr GFG = graph.linearize(values);
// VectorValues delta = GFG->optimize();
if(isDebugTest) result.at<CameraCal3_S2>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1,result.at<CameraCal3_S2>(c1)));
EXPECT(assert_equal(cam2,result.at<CameraCal3_S2>(c2)));
EXPECT(assert_equal(result.at<CameraCal3_S2>(c3).pose(), cam3.pose(), 1e-4));
EXPECT(assert_equal(result.at<CameraCal3_S2>(c3).calibration(), cam3.calibration(), 2));
if(isDebugTest) tictoc_print_();
if (isDebugTest)
result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1, result.at<Camera>(c1)));
EXPECT(assert_equal(cam2, result.at<Camera>(c2)));
EXPECT(assert_equal(result.at<Camera>(c3).pose(), cam3.pose(), 1e-4));
EXPECT(
assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 2));
if (isDebugTest)
tictoc_print_();
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, perturbCamerasAndOptimize ){
TEST( SmartProjectionCameraFactor, perturbCamerasAndOptimize ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 pose1 = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
CameraCal3_S2 cam1(pose1, *K2);
// create second camera 1 meter to the right of first camera
Pose3 pose2 = pose1 * Pose3(Rot3(), Point3(1,0,0));
CameraCal3_S2 cam2(pose2, *K2);
// create third camera 1 meter above the first camera
Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0,-1,0));
CameraCal3_S2 cam3(pose3, *K2);
using namespace vanilla;
// three landmarks ~5 meters infront of camera
Point3 landmark1(5, 0.5, 1.2);
@ -485,7 +422,7 @@ TEST( SmartProjectionCameraFactor, perturbCamerasAndOptimize ){
Point3 landmark5(10, -0.5, 1.2);
vector<Point2> measurements_cam1, measurements_cam2, measurements_cam3,
measurements_cam4, measurements_cam5;
measurements_cam4, measurements_cam5;
// 1. Project three landmarks into three cameras and triangulate
projectToMultipleCameras(cam1, cam2, cam3, landmark1, measurements_cam1);
@ -514,7 +451,7 @@ TEST( SmartProjectionCameraFactor, perturbCamerasAndOptimize ){
SmartFactor::shared_ptr smartFactor5(new SmartFactor());
smartFactor5->add(measurements_cam5, views, model);
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6+5, 1e-5);
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6 + 5, 1e-5);
NonlinearFactorGraph graph;
graph.push_back(smartFactor1);
@ -522,21 +459,24 @@ TEST( SmartProjectionCameraFactor, perturbCamerasAndOptimize ){
graph.push_back(smartFactor3);
graph.push_back(smartFactor4);
graph.push_back(smartFactor5);
graph.push_back(PriorFactor<CameraCal3_S2>(c1, cam1, noisePrior));
graph.push_back(PriorFactor<CameraCal3_S2>(c2, cam2, noisePrior));
graph.push_back(PriorFactor<Camera>(c1, cam1, noisePrior));
graph.push_back(PriorFactor<Camera>(c2, cam2, noisePrior));
Values values;
values.insert(c1, cam1);
values.insert(c2, cam2);
values.insert(c3, perturbCameraPoseAndCalibration(cam3));
if(isDebugTest) values.at<CameraCal3_S2>(c3).print("Smart: Pose3 before optimization: ");
if (isDebugTest)
values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
LevenbergMarquardtParams params;
params.relativeErrorTol = 1e-8;
params.absoluteErrorTol = 0;
params.maxIterations = 20;
if(isDebugTest) params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if(isDebugTest) params.verbosity = NonlinearOptimizerParams::ERROR;
if (isDebugTest)
params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if (isDebugTest)
params.verbosity = NonlinearOptimizerParams::ERROR;
Values result;
gttic_(SmartProjectionCameraFactor);
@ -548,28 +488,36 @@ TEST( SmartProjectionCameraFactor, perturbCamerasAndOptimize ){
// GaussianFactorGraph::shared_ptr GFG = graph.linearize(values);
// VectorValues delta = GFG->optimize();
if(isDebugTest) result.at<CameraCal3_S2>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1,result.at<CameraCal3_S2>(c1)));
EXPECT(assert_equal(cam2,result.at<CameraCal3_S2>(c2)));
EXPECT(assert_equal(result.at<CameraCal3_S2>(c3).pose(), cam3.pose(), 1e-1));
EXPECT(assert_equal(result.at<CameraCal3_S2>(c3).calibration(), cam3.calibration(), 20));
if(isDebugTest) tictoc_print_();
if (isDebugTest)
result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1, result.at<Camera>(c1)));
EXPECT(assert_equal(cam2, result.at<Camera>(c2)));
EXPECT(assert_equal(result.at<Camera>(c3).pose(), cam3.pose(), 1e-1));
EXPECT(
assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 20));
if (isDebugTest)
tictoc_print_();
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, Cal3Bundler ){
// Cal3Bundler cameras
namespace bundler {
typedef PinholeCamera<Cal3Bundler> Camera;
static Cal3Bundler K(500, 1e-3, 1e-3, 0, 0);
Camera level_camera(level_pose, K);
Camera level_camera_right(pose_right, K);
Pose3 pose1 = level_pose;
Camera cam1(level_pose, K);
Camera cam2(pose_right, K);
Camera cam3(pose_up, K);
typedef GeneralSFMFactor<Camera, Point3> SFMFactor;
typedef SmartProjectionCameraFactor<Cal3Bundler> SmartFactorBundler;
}
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 pose1 = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera cam1(pose1, *Kbundler);
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, Cal3Bundler ) {
// create second camera 1 meter to the right of first camera
Pose3 pose2 = pose1 * Pose3(Rot3(), Point3(1,0,0));
Camera cam2(pose2, *Kbundler);
// create third camera 1 meter above the first camera
Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0,-1,0));
Camera cam3(pose3, *Kbundler);
using namespace bundler;
// three landmarks ~5 meters infront of camera
Point3 landmark1(5, 0.5, 1.2);
@ -579,7 +527,7 @@ TEST( SmartProjectionCameraFactor, Cal3Bundler ){
Point3 landmark5(10, -0.5, 1.2);
vector<Point2> measurements_cam1, measurements_cam2, measurements_cam3,
measurements_cam4, measurements_cam5;
measurements_cam4, measurements_cam5;
// 1. Project three landmarks into three cameras and triangulate
projectToMultipleCameras(cam1, cam2, cam3, landmark1, measurements_cam1);
@ -622,14 +570,17 @@ TEST( SmartProjectionCameraFactor, Cal3Bundler ){
values.insert(c2, cam2);
// initialize third pose with some noise, we expect it to move back to original pose3
values.insert(c3, perturbCameraPose(cam3));
if(isDebugTest) values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
if (isDebugTest)
values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
LevenbergMarquardtParams params;
params.relativeErrorTol = 1e-8;
params.absoluteErrorTol = 0;
params.maxIterations = 20;
if(isDebugTest) params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if(isDebugTest) params.verbosity = NonlinearOptimizerParams::ERROR;
if (isDebugTest)
params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if (isDebugTest)
params.verbosity = NonlinearOptimizerParams::ERROR;
Values result;
gttic_(SmartProjectionCameraFactor);
@ -638,28 +589,21 @@ TEST( SmartProjectionCameraFactor, Cal3Bundler ){
gttoc_(SmartProjectionCameraFactor);
tictoc_finishedIteration_();
if(isDebugTest) result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1,result.at<Camera>(c1), 1e-4));
EXPECT(assert_equal(cam2,result.at<Camera>(c2), 1e-4));
if (isDebugTest)
result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1, result.at<Camera>(c1), 1e-4));
EXPECT(assert_equal(cam2, result.at<Camera>(c2), 1e-4));
EXPECT(assert_equal(result.at<Camera>(c3).pose(), cam3.pose(), 1e-1));
EXPECT(assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 1));
if(isDebugTest) tictoc_print_();
EXPECT(
assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 1));
if (isDebugTest)
tictoc_print_();
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, Cal3Bundler2 ){
TEST( SmartProjectionCameraFactor, Cal3Bundler2 ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 pose1 = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera cam1(pose1, *Kbundler);
// create second camera 1 meter to the right of first camera
Pose3 pose2 = pose1 * Pose3(Rot3(), Point3(1,0,0));
Camera cam2(pose2, *Kbundler);
// create third camera 1 meter above the first camera
Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0,-1,0));
Camera cam3(pose3, *Kbundler);
using namespace bundler;
// three landmarks ~5 meters infront of camera
Point3 landmark1(5, 0.5, 1.2);
@ -669,7 +613,7 @@ TEST( SmartProjectionCameraFactor, Cal3Bundler2 ){
Point3 landmark5(10, -0.5, 1.2);
vector<Point2> measurements_cam1, measurements_cam2, measurements_cam3,
measurements_cam4, measurements_cam5;
measurements_cam4, measurements_cam5;
// 1. Project three landmarks into three cameras and triangulate
projectToMultipleCameras(cam1, cam2, cam3, landmark1, measurements_cam1);
@ -712,14 +656,17 @@ TEST( SmartProjectionCameraFactor, Cal3Bundler2 ){
values.insert(c2, cam2);
// initialize third pose with some noise, we expect it to move back to original pose3
values.insert(c3, perturbCameraPoseAndCalibration(cam3));
if(isDebugTest) values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
if (isDebugTest)
values.at<Camera>(c3).print("Smart: Pose3 before optimization: ");
LevenbergMarquardtParams params;
params.relativeErrorTol = 1e-8;
params.absoluteErrorTol = 0;
params.maxIterations = 20;
if(isDebugTest) params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if(isDebugTest) params.verbosity = NonlinearOptimizerParams::ERROR;
if (isDebugTest)
params.verbosityLM = LevenbergMarquardtParams::TRYLAMBDA;
if (isDebugTest)
params.verbosity = NonlinearOptimizerParams::ERROR;
Values result;
gttic_(SmartProjectionCameraFactor);
@ -728,25 +675,56 @@ TEST( SmartProjectionCameraFactor, Cal3Bundler2 ){
gttoc_(SmartProjectionCameraFactor);
tictoc_finishedIteration_();
if(isDebugTest) result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1,result.at<Camera>(c1), 1e-4));
EXPECT(assert_equal(cam2,result.at<Camera>(c2), 1e-4));
if (isDebugTest)
result.at<Camera>(c3).print("Smart: Pose3 after optimization: ");
EXPECT(assert_equal(cam1, result.at<Camera>(c1), 1e-4));
EXPECT(assert_equal(cam2, result.at<Camera>(c2), 1e-4));
EXPECT(assert_equal(result.at<Camera>(c3).pose(), cam3.pose(), 1e-1));
EXPECT(assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 2));
if(isDebugTest) tictoc_print_();
EXPECT(
assert_equal(result.at<Camera>(c3).calibration(), cam3.calibration(), 2));
if (isDebugTest)
tictoc_print_();
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor ){
TEST( SmartProjectionCameraFactor, noiselessBundler ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera level_camera(level_pose, *Kbundler);
using namespace bundler;
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
Camera level_camera_right(level_pose_right, *Kbundler);
// 1. Project two landmarks into two cameras and triangulate
Point2 level_uv = level_camera.project(landmark);
Point2 level_uv_right = level_camera_right.project(landmark);
Values values;
values.insert(c1, level_camera);
values.insert(c2, level_camera_right);
SmartFactorBundler::shared_ptr factor1(new SmartFactorBundler());
factor1->add(level_uv, c1, model);
factor1->add(level_uv_right, c2, model);
double actualError = factor1->error(values);
double expectedError = 0.0;
DOUBLES_EQUAL(expectedError, actualError, 1e-3);
Point3 oldPoint; // this takes the point stored in the factor (we are not interested in this)
if (factor1->point())
oldPoint = *(factor1->point());
Point3 expectedPoint;
if (factor1->point(values))
expectedPoint = *(factor1->point(values));
EXPECT(assert_equal(expectedPoint, landmark, 1e-3));
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor ) {
using namespace bundler;
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
@ -766,7 +744,7 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor ){
double expectedError = factor1->error(values);
double expectedErrorGraph = smartGraph.error(values);
Point3 expectedPoint;
if(factor1->point())
if (factor1->point())
expectedPoint = *(factor1->point());
// cout << "expectedPoint " << expectedPoint.vector() << endl;
@ -779,9 +757,10 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor ){
generalGraph.push_back(sfm1);
generalGraph.push_back(sfm2);
values.insert(l1, expectedPoint); // note: we get rid of possible errors in the triangulation
Vector e1 = sfm1.evaluateError(values.at< Camera >(c1), values.at< Point3 >(l1));
Vector e2 = sfm2.evaluateError(values.at< Camera >(c2), values.at< Point3 >(l1));
double actualError = 0.5 * (norm_2(e1)*norm_2(e1) + norm_2(e2)*norm_2(e2));
Vector e1 = sfm1.evaluateError(values.at<Camera>(c1), values.at<Point3>(l1));
Vector e2 = sfm2.evaluateError(values.at<Camera>(c2), values.at<Point3>(l1));
double actualError = 0.5
* (norm_2(e1) * norm_2(e1) + norm_2(e2) * norm_2(e2));
double actualErrorGraph = generalGraph.error(values);
DOUBLES_EQUAL(expectedErrorGraph, actualErrorGraph, 1e-7);
@ -791,14 +770,9 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor ){
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor1 ){
TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor1 ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera level_camera(level_pose, *Kbundler);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
Camera level_camera_right(level_pose_right, *Kbundler);
using namespace bundler;
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
// 1. Project two landmarks into two cameras and triangulate
@ -817,7 +791,7 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor1 ){
Matrix expectedHessian = smartGraph.linearize(values)->hessian().first;
Vector expectedInfoVector = smartGraph.linearize(values)->hessian().second;
Point3 expectedPoint;
if(factor1->point())
if (factor1->point())
expectedPoint = *(factor1->point());
// COMMENTS:
@ -831,25 +805,23 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor1 ){
values.insert(l1, expectedPoint); // note: we get rid of possible errors in the triangulation
Matrix actualFullHessian = generalGraph.linearize(values)->hessian().first;
Matrix actualFullInfoVector = generalGraph.linearize(values)->hessian().second;
Matrix actualHessian = actualFullHessian.block(0,0,18,18) -
actualFullHessian.block(0,18,18,3) * (actualFullHessian.block(18,18,3,3)).inverse() * actualFullHessian.block(18,0,3,18);
Vector actualInfoVector = actualFullInfoVector.block(0,0,18,1) -
actualFullHessian.block(0,18,18,3) * (actualFullHessian.block(18,18,3,3)).inverse() * actualFullInfoVector.block(18,0,3,1);
Matrix actualHessian = actualFullHessian.block(0, 0, 18, 18)
- actualFullHessian.block(0, 18, 18, 3)
* (actualFullHessian.block(18, 18, 3, 3)).inverse()
* actualFullHessian.block(18, 0, 3, 18);
Vector actualInfoVector = actualFullInfoVector.block(0, 0, 18, 1)
- actualFullHessian.block(0, 18, 18, 3)
* (actualFullHessian.block(18, 18, 3, 3)).inverse()
* actualFullInfoVector.block(18, 0, 3, 1);
EXPECT(assert_equal(expectedHessian,actualHessian, 1e-7));
EXPECT(assert_equal(expectedInfoVector,actualInfoVector, 1e-7));
EXPECT(assert_equal(expectedHessian, actualHessian, 1e-7));
EXPECT(assert_equal(expectedInfoVector, actualInfoVector, 1e-7));
}
/* *************************************************************************/
// Have to think about how to compare multiplyHessianAdd in generalSfMFactor and smartFactors
//TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor2 ){
//
// // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
// Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
// cameraObjectBundler level_camera(level_pose, *Kbundler);
// // create second camera 1 meter to the right of first camera
// Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
// cameraObjectBundler level_camera_right(level_pose_right, *Kbundler);
// // landmark ~5 meters infront of camera
// Point3 landmark(5, 0.5, 1.2);
// // 1. Project two landmarks into two cameras
@ -901,16 +873,10 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor1 ){
//
// EXPECT(assert_equal(yActual,yExpected, 1e-7));
//}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, computeImplicitJacobian ){
TEST( SmartProjectionCameraFactor, computeImplicitJacobian ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera level_camera(level_pose, *Kbundler);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
Camera level_camera_right(level_pose_right, *Kbundler);
using namespace bundler;
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
// 1. Project two landmarks into two cameras and triangulate
@ -927,13 +893,13 @@ TEST( SmartProjectionCameraFactor, computeImplicitJacobian ){
Matrix expectedF, expectedE;
Vector expectedb;
CameraSet< Camera > cameras;
CameraSet<Camera> cameras;
cameras.push_back(level_camera);
cameras.push_back(level_camera_right);
factor1->error(values); // this is important to have a triangulation of the point
Point3 expectedPoint;
if(factor1->point())
if (factor1->point())
expectedPoint = *(factor1->point());
factor1->computeJacobians(expectedF, expectedE, expectedb, cameras);
@ -944,21 +910,17 @@ TEST( SmartProjectionCameraFactor, computeImplicitJacobian ){
generalGraph.push_back(sfm2);
values.insert(l1, expectedPoint); // note: we get rid of possible errors in the triangulation
Matrix actualFullHessian = generalGraph.linearize(values)->hessian().first;
Matrix actualVinv = (actualFullHessian.block(18,18,3,3)).inverse();
Matrix actualVinv = (actualFullHessian.block(18, 18, 3, 3)).inverse();
Matrix3 expectedVinv = factor1->PointCov(expectedE);
EXPECT(assert_equal(expectedVinv,actualVinv, 1e-7));
EXPECT(assert_equal(expectedVinv, actualVinv, 1e-7));
}
/* *************************************************************************/
TEST( SmartProjectionCameraFactor, implicitJacobianFactor ){
TEST( SmartProjectionCameraFactor, implicitJacobianFactor ) {
using namespace bundler;
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 level_pose = Pose3(Rot3::ypr(-M_PI/2, 0., -M_PI/2), Point3(0,0,1));
Camera level_camera(level_pose, *Kbundler);
// create second camera 1 meter to the right of first camera
Pose3 level_pose_right = level_pose * Pose3(Rot3(), Point3(1,0,0));
Camera level_camera_right(level_pose_right, *Kbundler);
// landmark ~5 meters infront of camera
Point3 landmark(5, 0.5, 1.2);
// 1. Project two landmarks into two cameras and triangulate
@ -975,35 +937,45 @@ TEST( SmartProjectionCameraFactor, implicitJacobianFactor ){
bool isImplicit = false;
// Hessian version
SmartFactorBundler::shared_ptr explicitFactor(new SmartFactorBundler(rankTol,linThreshold, manageDegeneracy, useEPI, isImplicit));
SmartFactorBundler::shared_ptr explicitFactor(
new SmartFactorBundler(rankTol, linThreshold, manageDegeneracy, useEPI,
isImplicit));
explicitFactor->add(level_uv, c1, model);
explicitFactor->add(level_uv_right, c2, model);
GaussianFactor::shared_ptr gaussianHessianFactor = explicitFactor->linearize(values);
HessianFactor& hessianFactor = dynamic_cast<HessianFactor&>(*gaussianHessianFactor);
GaussianFactor::shared_ptr gaussianHessianFactor = explicitFactor->linearize(
values);
HessianFactor& hessianFactor =
dynamic_cast<HessianFactor&>(*gaussianHessianFactor);
// Implicit Schur version
isImplicit = true;
SmartFactorBundler::shared_ptr implicitFactor(new SmartFactorBundler(rankTol,linThreshold, manageDegeneracy, useEPI, isImplicit));
SmartFactorBundler::shared_ptr implicitFactor(
new SmartFactorBundler(rankTol, linThreshold, manageDegeneracy, useEPI,
isImplicit));
implicitFactor->add(level_uv, c1, model);
implicitFactor->add(level_uv_right, c2, model);
GaussianFactor::shared_ptr gaussianImplicitSchurFactor = implicitFactor->linearize(values);
GaussianFactor::shared_ptr gaussianImplicitSchurFactor =
implicitFactor->linearize(values);
typedef RegularImplicitSchurFactor<9> Implicit9;
Implicit9& implicitSchurFactor = dynamic_cast<Implicit9&>(*gaussianImplicitSchurFactor);
Implicit9& implicitSchurFactor =
dynamic_cast<Implicit9&>(*gaussianImplicitSchurFactor);
VectorValues x = map_list_of
(c1, (Vector(9) << 1,2,3,4,5,6,7,8,9).finished())
(c2, (Vector(9) << 11,12,13,14,15,16,17,18,19).finished());
VectorValues x = map_list_of(c1,
(Vector(9) << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished())(c2,
(Vector(9) << 11, 12, 13, 14, 15, 16, 17, 18, 19).finished());
VectorValues yExpected, yActual;
double alpha = 1.0;
hessianFactor.multiplyHessianAdd(alpha, x, yActual);
implicitSchurFactor.multiplyHessianAdd(alpha, x, yExpected);
EXPECT(assert_equal(yActual,yExpected, 1e-7));
EXPECT(assert_equal(yActual, yExpected, 1e-7));
}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */