2 tests to go

release/4.3a0
lcarlone 2021-03-28 20:03:02 -04:00
parent b10a9d245b
commit 2c1b780a4f
2 changed files with 104 additions and 81 deletions

View File

@ -157,11 +157,10 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
Matrix& E, Vector& b, const Values& values) const { Matrix& E, Vector& b, const Values& values) const {
if (!result_) { if (!result_) {
throw ("computeJacobiansWithTriangulatedPoint"); throw ("computeJacobiansWithTriangulatedPoint");
} else { } else { // valid result: compute jacobians
size_t numViews = measured_.size(); size_t numViews = measured_.size();
E = Matrix::Zero(3*numViews,3); // a StereoPoint2 for each view E = Matrix::Zero(3*numViews,3); // a StereoPoint2 for each view
b = Vector::Zero(3*numViews); // a StereoPoint2 for each view b = Vector::Zero(3*numViews); // a StereoPoint2 for each view
// valid result: compute jacobians
Matrix dPoseCam_dPoseBody,dPoseCam_dPoseExt, dProject_dPoseCam,Ei; Matrix dPoseCam_dPoseBody,dPoseCam_dPoseExt, dProject_dPoseCam,Ei;
for (size_t i = 0; i < numViews; i++) { // for each camera/measurement for (size_t i = 0; i < numViews; i++) { // for each camera/measurement
@ -184,6 +183,8 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
b.segment<ZDim>(row) = - reprojectionError.vector(); b.segment<ZDim>(row) = - reprojectionError.vector();
E.block<3,3>(row,0) = Ei; E.block<3,3>(row,0) = Ei;
} }
// correct for monocular measurements, where the right pixel measurement is nan
//Base::CorrectForMissingMeasurements(measured_, cameras, b, Fs, E);
} }
} }
@ -203,9 +204,10 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
throw std::runtime_error("SmartStereoProjectionHessianFactor: this->" throw std::runtime_error("SmartStereoProjectionHessianFactor: this->"
"measured_.size() inconsistent with input"); "measured_.size() inconsistent with input");
std::cout << "triangulate" << std::endl;
triangulateSafe(cameras(values)); triangulateSafe(cameras(values));
if (params_.degeneracyMode == ZERO_ON_DEGENERACY && !result_) { if (!result_) {
std::cout << "degenerate" << std::endl; std::cout << "degenerate" << std::endl;
// failed: return"empty" Hessian // failed: return"empty" Hessian
for(Matrix& m: Gs) for(Matrix& m: Gs)
@ -216,6 +218,7 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
Gs, gs, 0.0); Gs, gs, 0.0);
} }
std::cout << "params_.degeneracyMode" << params_.degeneracyMode << std::endl;
// Jacobian could be 3D Point3 OR 2D Unit3, difference is E.cols(). // Jacobian could be 3D Point3 OR 2D Unit3, difference is E.cols().
FBlocks Fs; FBlocks Fs;
Matrix F, E; Matrix F, E;
@ -263,7 +266,7 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
keyToSlotMap[keys_[k]] = k; keyToSlotMap[keys_[k]] = k;
} }
// std::cout << "linearize" << std::endl; std::cout << "linearize" << std::endl;
// for(size_t i=0; i<nrUniqueKeys;i++){ // for(size_t i=0; i<nrUniqueKeys;i++){
// std::cout <<"key: " << DefaultKeyFormatter(keys_[i]); // std::cout <<"key: " << DefaultKeyFormatter(keys_[i]);
// std::cout <<" key slot: " << keyToSlotMap[keys_[i]] << std::endl; // std::cout <<" key slot: " << keyToSlotMap[keys_[i]] << std::endl;
@ -273,24 +276,6 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
// std::cout <<" key slot: " << keyToSlotMap[nonuniqueKeys[i]] << std::endl; // std::cout <<" key slot: " << keyToSlotMap[nonuniqueKeys[i]] << std::endl;
// } // }
/////////////////////////////////////////////////////////////////
// PROTOTYPING
size_t numMeasurements = measured_.size();
Matrix F = Matrix::Zero(3*numMeasurements, 6 * nrUniqueKeys);
for(size_t k=0; k<numMeasurements; k++){
Key key_body = w_P_body_keys_.at(k);
Key key_cal = body_P_cam_keys_.at(k);
F.block<3,6>( 3*k , 6*keyToSlotMap[key_body] ) = Fs[k].block<3,6>(0,0);
F.block<3,6>( 3*k , 6*keyToSlotMap[key_cal] ) = Fs[k].block<3,6>(0,6);
}
Matrix augH = Matrix::Zero(6*nrUniqueKeys+1,6*nrUniqueKeys+1);
augH.block(0,0,6*nrUniqueKeys,6*nrUniqueKeys) = F.transpose() * F - F.transpose() * E * P * E.transpose() * F;
Matrix infoVec = F.transpose() * b - F.transpose() * E * P * E.transpose() * b;
augH.block(0,6*nrUniqueKeys,6*nrUniqueKeys,1) = infoVec;
augH.block(6*nrUniqueKeys,0,1,6*nrUniqueKeys) = infoVec.transpose();
augH(6*nrUniqueKeys,6*nrUniqueKeys) = b.squaredNorm();
/////////////////////////////////////////////////////////////////
// initialize matrix to zero // initialize matrix to zero
augmentedHessianUniqueKeys = SymmetricBlockMatrix(dims, Matrix::Zero(6*nrUniqueKeys+1,6*nrUniqueKeys+1)); augmentedHessianUniqueKeys = SymmetricBlockMatrix(dims, Matrix::Zero(6*nrUniqueKeys+1,6*nrUniqueKeys+1));
@ -317,7 +302,7 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
augmentedHessian.aboveDiagonalBlock(i,j).transpose()); augmentedHessian.aboveDiagonalBlock(i,j).transpose());
} }
} }
else{ else{ //TODO: remove else
augmentedHessianUniqueKeys.updateOffDiagonalBlock( keyToSlotMap[key_i] , keyToSlotMap[key_j], augmentedHessianUniqueKeys.updateOffDiagonalBlock( keyToSlotMap[key_i] , keyToSlotMap[key_j],
augmentedHessian.aboveDiagonalBlock(j,i).transpose()); augmentedHessian.aboveDiagonalBlock(j,i).transpose());
} }
@ -327,12 +312,6 @@ class SmartStereoProjectionFactorPP : public SmartStereoProjectionFactor {
//std::cout << "Matrix \n " << Matrix(augmentedHessianUniqueKeys.selfadjointView()) <<std::endl; //std::cout << "Matrix \n " << Matrix(augmentedHessianUniqueKeys.selfadjointView()) <<std::endl;
//std::cout << "sq norm " << b.squaredNorm() << std::endl; //std::cout << "sq norm " << b.squaredNorm() << std::endl;
std::cout << "norm diff: \n"<< Matrix(augH - Matrix(augmentedHessianUniqueKeys.selfadjointView())).lpNorm<Eigen::Infinity>() << std::endl;
//
//
// std::cout << "TEST MATRIX:" << std::endl;
// augmentedHessianUniqueKeys = SymmetricBlockMatrix(dims, augH);
} }
return boost::make_shared<RegularHessianFactor<DimPose> >(keys_, augmentedHessianUniqueKeys); return boost::make_shared<RegularHessianFactor<DimPose> >(keys_, augmentedHessianUniqueKeys);

View File

@ -156,7 +156,7 @@ TEST( SmartStereoProjectionFactorPP, Equals ) {
} }
/* *************************************************************************/ /* *************************************************************************/
TEST_UNSAFE( SmartStereoProjectionFactorPP, noiseless ) { TEST_UNSAFE( SmartStereoProjectionFactorPP, noiseless_error_identityExtrinsics ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2),
Point3(0, 0, 1)); Point3(0, 0, 1));
@ -193,7 +193,7 @@ TEST_UNSAFE( SmartStereoProjectionFactorPP, noiseless ) {
} }
/* *************************************************************************/ /* *************************************************************************/
TEST_UNSAFE( SmartStereoProjectionFactorPP, noiselessNonidenticalExtrinsics ) { TEST_UNSAFE( SmartStereoProjectionFactorPP, noiseless_error_multipleExtrinsics ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2),
Point3(0, 0, 1)); Point3(0, 0, 1));
@ -237,7 +237,7 @@ TEST_UNSAFE( SmartStereoProjectionFactorPP, noiselessNonidenticalExtrinsics ) {
} }
/* *************************************************************************/ /* *************************************************************************/
TEST( SmartProjectionPoseFactor, noiselessWithMissingMeasurements ) { TEST( SmartProjectionPoseFactor, noiseless_error_multipleExtrinsics_missingMeasurements ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2),
@ -302,7 +302,7 @@ TEST( SmartProjectionPoseFactor, noiselessWithMissingMeasurements ) {
} }
/* *************************************************************************/ /* *************************************************************************/
TEST( SmartStereoProjectionFactorPP, noisy ) { TEST( SmartStereoProjectionFactorPP, noisy_error_multipleExtrinsics ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2),
Point3(0, 0, 1)); Point3(0, 0, 1));
@ -368,7 +368,7 @@ TEST( SmartStereoProjectionFactorPP, noisy ) {
} }
/* *************************************************************************/ /* *************************************************************************/
TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_optimization ) { TEST( SmartStereoProjectionFactorPP, 3poses_optimization_multipleExtrinsics ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1)); Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1));
@ -531,7 +531,7 @@ TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_optimization
} }
/* *************************************************************************/ /* *************************************************************************/
TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_error_sameExtrinsicKey ) { TEST( SmartStereoProjectionFactorPP, 3poses_error_sameExtrinsicKey ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1)); Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1));
@ -610,7 +610,7 @@ TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_error_sameEx
} }
/* *************************************************************************/ /* *************************************************************************/
TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_error_sameExtrinsicKey_error_noisy ) { TEST( SmartStereoProjectionFactorPP, 3poses_noisy_error_sameExtrinsicKey ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1)); Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1));
@ -741,12 +741,12 @@ TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_error_sameEx
initialError_actual = graph.error(values); initialError_actual = graph.error(values);
} }
std::cout << " initialError_expected " << initialError_expected << std::endl; //std::cout << " initialError_expected " << initialError_expected << std::endl;
EXPECT_DOUBLES_EQUAL(initialError_expected, initialError_actual, 1e-7); EXPECT_DOUBLES_EQUAL(initialError_expected, initialError_actual, 1e-7);
} }
/* *************************************************************************/ /* *************************************************************************/
TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_optimization_sameExtrinsicKey ) { TEST( SmartStereoProjectionFactorPP, 3poses_optimization_sameExtrinsicKey ) {
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // create first camera. Looking along X-axis, 1 meter above ground plane (x-y)
Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1)); Pose3 w_Pose_cam1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1));
@ -825,9 +825,27 @@ TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_optimization
double initialErrorSmart = graph.error(values); double initialErrorSmart = graph.error(values);
EXPECT_DOUBLES_EQUAL(31986.961831653316, initialErrorSmart, 1e-5); // initial guess is noisy, so nonzero error EXPECT_DOUBLES_EQUAL(31986.961831653316, initialErrorSmart, 1e-5); // initial guess is noisy, so nonzero error
std::cout << " 1: " << smartFactor1->error(values) <<std::endl; /////////////////////////////////////////////////////////////////
std::cout << " 2: " << smartFactor2->error(values) <<std::endl; // What the factor is doing is the following Schur complement math (this matches augmentedHessianPP in code):
std::cout << " 3: " << smartFactor3->error(values) <<std::endl; // size_t numMeasurements = measured_.size();
// Matrix F = Matrix::Zero(3*numMeasurements, 6 * nrUniqueKeys);
// for(size_t k=0; k<numMeasurements; k++){
// Key key_body = w_P_body_keys_.at(k);
// Key key_cal = body_P_cam_keys_.at(k);
// F.block<3,6>( 3*k , 6*keyToSlotMap[key_body] ) = Fs[k].block<3,6>(0,0);
// F.block<3,6>( 3*k , 6*keyToSlotMap[key_cal] ) = Fs[k].block<3,6>(0,6);
// }
// Matrix augH = Matrix::Zero(6*nrUniqueKeys+1,6*nrUniqueKeys+1);
// augH.block(0,0,6*nrUniqueKeys,6*nrUniqueKeys) = F.transpose() * F - F.transpose() * E * P * E.transpose() * F;
// Matrix infoVec = F.transpose() * b - F.transpose() * E * P * E.transpose() * b;
// augH.block(0,6*nrUniqueKeys,6*nrUniqueKeys,1) = infoVec;
// augH.block(6*nrUniqueKeys,0,1,6*nrUniqueKeys) = infoVec.transpose();
// augH(6*nrUniqueKeys,6*nrUniqueKeys) = b.squaredNorm();
// // The following is close to zero:
// std::cout << "norm diff: \n"<< Matrix(augH - Matrix(augmentedHessianUniqueKeys.selfadjointView())).lpNorm<Eigen::Infinity>() << std::endl;
// std::cout << "TEST MATRIX:" << std::endl;
// augmentedHessianUniqueKeys = SymmetricBlockMatrix(dims, augH);
/////////////////////////////////////////////////////////////////
Values result; Values result;
gttic_(SmartStereoProjectionFactorPP); gttic_(SmartStereoProjectionFactorPP);
@ -845,7 +863,7 @@ TEST( SmartStereoProjectionFactorPP, 3poses_smart_projection_factor_optimization
} }
/* ************************************************************************* /* *************************************************************************
TEST( SmartStereoProjectionFactorPP, body_P_sensor_monocular ){ TEST( SmartStereoProjectionFactorPP, monocular_multipleExtrinsicKeys ){
// make a realistic calibration matrix // make a realistic calibration matrix
double fov = 60; // degrees double fov = 60; // degrees
size_t w=640,h=480; size_t w=640,h=480;
@ -881,12 +899,6 @@ TEST( SmartStereoProjectionFactorPP, body_P_sensor_monocular ){
projectToMultipleCameras(cam1, cam2, cam3, landmark2, measurements_cam2); projectToMultipleCameras(cam1, cam2, cam3, landmark2, measurements_cam2);
projectToMultipleCameras(cam1, cam2, cam3, landmark3, measurements_cam3); projectToMultipleCameras(cam1, cam2, cam3, landmark3, measurements_cam3);
// Create smart factors
KeyVector views;
views.push_back(x1);
views.push_back(x2);
views.push_back(x3);
// convert measurement to (degenerate) stereoPoint2 (with right pixel being NaN) // convert measurement to (degenerate) stereoPoint2 (with right pixel being NaN)
vector<StereoPoint2> measurements_cam1_stereo, measurements_cam2_stereo, measurements_cam3_stereo; vector<StereoPoint2> measurements_cam1_stereo, measurements_cam2_stereo, measurements_cam3_stereo;
for(size_t k=0; k<measurements_cam1.size();k++) for(size_t k=0; k<measurements_cam1.size();k++)
@ -898,64 +910,81 @@ TEST( SmartStereoProjectionFactorPP, body_P_sensor_monocular ){
for(size_t k=0; k<measurements_cam3.size();k++) for(size_t k=0; k<measurements_cam3.size();k++)
measurements_cam3_stereo.push_back(StereoPoint2(measurements_cam3[k].x() , missing_uR , measurements_cam3[k].y())); measurements_cam3_stereo.push_back(StereoPoint2(measurements_cam3[k].x() , missing_uR , measurements_cam3[k].y()));
SmartStereoProjectionParams params; KeyVector poseKeys;
params.setRankTolerance(1.0); poseKeys.push_back(x1);
params.setDegeneracyMode(gtsam::IGNORE_DEGENERACY); poseKeys.push_back(x2);
params.setEnableEPI(false); poseKeys.push_back(x3);
Symbol body_P_cam_key('P', 0);
KeyVector extrinsicKeys;
extrinsicKeys.push_back(body_P_cam_key);
extrinsicKeys.push_back(body_P_cam_key);
extrinsicKeys.push_back(body_P_cam_key);
SmartStereoProjectionParams smart_params;
smart_params.setRankTolerance(1.0);
smart_params.setDegeneracyMode(gtsam::IGNORE_DEGENERACY);
smart_params.setEnableEPI(false);
Cal3_S2Stereo::shared_ptr Kmono(new Cal3_S2Stereo(fov,w,h,b)); Cal3_S2Stereo::shared_ptr Kmono(new Cal3_S2Stereo(fov,w,h,b));
SmartStereoProjectionFactorPP smartFactor1(model, params, sensor_to_body);
smartFactor1.add(measurements_cam1_stereo, views, Kmono);
SmartStereoProjectionFactorPP smartFactor2(model, params, sensor_to_body); SmartStereoProjectionFactorPP smartFactor1(model, smart_params);
smartFactor2.add(measurements_cam2_stereo, views, Kmono); smartFactor1.add(measurements_cam1_stereo, poseKeys, extrinsicKeys, Kmono);
SmartStereoProjectionFactorPP smartFactor3(model, params, sensor_to_body); SmartStereoProjectionFactorPP smartFactor2(model, smart_params);
smartFactor3.add(measurements_cam3_stereo, views, Kmono); smartFactor2.add(measurements_cam2_stereo, poseKeys, extrinsicKeys, Kmono);
SmartStereoProjectionFactorPP smartFactor3(model, smart_params);
smartFactor3.add(measurements_cam3_stereo, poseKeys, extrinsicKeys, Kmono);
// Graph
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6, 0.10); const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6, 0.10);
// Put all factors in factor graph, adding priors
NonlinearFactorGraph graph; NonlinearFactorGraph graph;
graph.push_back(smartFactor1); graph.push_back(smartFactor1);
graph.push_back(smartFactor2); graph.push_back(smartFactor2);
graph.push_back(smartFactor3); graph.push_back(smartFactor3);
graph.addPrior(x1, bodyPose1, noisePrior); graph.addPrior(x1, bodyPose1, noisePrior);
graph.addPrior(x2, bodyPose2, noisePrior); graph.addPrior(x2, bodyPose2, noisePrior);
graph.addPrior(x3, bodyPose3, noisePrior);
// we might need some prior on the calibration too
// graph.addPrior(body_P_cam_key, body_Pose_cam, noisePrior); // no need! the measurements will fix this!
// Check errors at ground truth poses // Check errors at ground truth poses
Values gtValues; Values gtValues;
gtValues.insert(x1, bodyPose1); gtValues.insert(x1, bodyPose1);
gtValues.insert(x2, bodyPose2); gtValues.insert(x2, bodyPose2);
gtValues.insert(x3, bodyPose3); gtValues.insert(x3, bodyPose3);
gtValues.insert(body_P_cam_key, sensor_to_body);
double actualError = graph.error(gtValues); double actualError = graph.error(gtValues);
double expectedError = 0.0; double expectedError = 0.0;
DOUBLES_EQUAL(expectedError, actualError, 1e-7) DOUBLES_EQUAL(expectedError, actualError, 1e-7)
Pose3 noise_pose = Pose3(Rot3::Ypr(-M_PI/100, 0., -M_PI/100), gtsam::Point3(0.1,0.1,0.1)); // noisy values
Values values; Values values;
Pose3 noise_pose = Pose3(Rot3::Ypr(-M_PI / 100, 0., -M_PI / 100), Point3(0.01, 0.01, 0.01)); // smaller noise
values.insert(x1, bodyPose1); values.insert(x1, bodyPose1);
values.insert(x2, bodyPose2); values.insert(x2, bodyPose2);
// initialize third pose with some noise, we expect it to move back to original pose3 values.insert(x3, bodyPose3);
values.insert(x3, bodyPose3*noise_pose); values.insert(body_P_cam_key, sensor_to_body*noise_pose);
// cost is large before optimization
double initialErrorSmart = graph.error(values);
EXPECT_DOUBLES_EQUAL(2379.0012816261642, initialErrorSmart, 1e-5); // freeze value
LevenbergMarquardtParams lmParams;
Values result; Values result;
LevenbergMarquardtOptimizer optimizer(graph, values, lmParams); gttic_(SmartStereoProjectionFactorPP);
LevenbergMarquardtOptimizer optimizer(graph, values, lm_params);
result = optimizer.optimize(); result = optimizer.optimize();
EXPECT(assert_equal(bodyPose3,result.at<Pose3>(x3))); gttoc_(SmartStereoProjectionFactorPP);
tictoc_finishedIteration_();
EXPECT_DOUBLES_EQUAL(0, graph.error(result), 1e-5);
EXPECT(assert_equal(sensor_to_body,result.at<Pose3>(body_P_cam_key)));
} }
/* ************************************************************************* /* *************************************************************************/
TEST( SmartStereoProjectionFactorPP, landmarkDistance ) { TEST( SmartStereoProjectionFactorPP, landmarkDistance ) {
// double excludeLandmarksFutherThanDist = 2;
KeyVector views;
views.push_back(x1);
views.push_back(x2);
views.push_back(x3);
// create first camera. Looking along X-axis, 1 meter above ground plane (x-y) // 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)); Pose3 pose1 = Pose3(Rot3::Ypr(-M_PI / 2, 0., -M_PI / 2), Point3(0, 0, 1));
StereoCamera cam1(pose1, K); StereoCamera cam1(pose1, K);
@ -966,6 +995,17 @@ TEST( SmartStereoProjectionFactorPP, landmarkDistance ) {
Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0, -1, 0)); Pose3 pose3 = pose1 * Pose3(Rot3(), Point3(0, -1, 0));
StereoCamera cam3(pose3, K); StereoCamera cam3(pose3, K);
KeyVector views;
views.push_back(x1);
views.push_back(x2);
views.push_back(x3);
Symbol body_P_cam_key('P', 0);
KeyVector extrinsicKeys;
extrinsicKeys.push_back(body_P_cam_key);
extrinsicKeys.push_back(body_P_cam_key);
extrinsicKeys.push_back(body_P_cam_key);
// three landmarks ~5 meters infront of camera // three landmarks ~5 meters infront of camera
Point3 landmark1(5, 0.5, 1.2); Point3 landmark1(5, 0.5, 1.2);
Point3 landmark2(5, -0.5, 1.2); Point3 landmark2(5, -0.5, 1.2);
@ -980,26 +1020,27 @@ TEST( SmartStereoProjectionFactorPP, landmarkDistance ) {
cam2, cam3, landmark3); cam2, cam3, landmark3);
SmartStereoProjectionParams params; SmartStereoProjectionParams params;
params.setLinearizationMode(JACOBIAN_SVD); params.setLinearizationMode(HESSIAN);
params.setLandmarkDistanceThreshold(2); params.setLandmarkDistanceThreshold(2);
SmartStereoProjectionFactorPP::shared_ptr smartFactor1(new SmartStereoProjectionFactorPP(model, params)); SmartStereoProjectionFactorPP::shared_ptr smartFactor1(new SmartStereoProjectionFactorPP(model, params));
smartFactor1->add(measurements_cam1, views, K); smartFactor1->add(measurements_cam1, views, extrinsicKeys, K);
SmartStereoProjectionFactorPP::shared_ptr smartFactor2(new SmartStereoProjectionFactorPP(model, params)); SmartStereoProjectionFactorPP::shared_ptr smartFactor2(new SmartStereoProjectionFactorPP(model, params));
smartFactor2->add(measurements_cam2, views, K); smartFactor2->add(measurements_cam2, views, extrinsicKeys, K);
SmartStereoProjectionFactorPP::shared_ptr smartFactor3(new SmartStereoProjectionFactorPP(model, params)); SmartStereoProjectionFactorPP::shared_ptr smartFactor3(new SmartStereoProjectionFactorPP(model, params));
smartFactor3->add(measurements_cam3, views, K); smartFactor3->add(measurements_cam3, views, extrinsicKeys, K);
// create graph
const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6, 0.10); const SharedDiagonal noisePrior = noiseModel::Isotropic::Sigma(6, 0.10);
NonlinearFactorGraph graph; NonlinearFactorGraph graph;
graph.push_back(smartFactor1); graph.push_back(smartFactor1);
graph.push_back(smartFactor2); graph.push_back(smartFactor2);
graph.push_back(smartFactor3); graph.push_back(smartFactor3);
graph.addPrior(x1, pose1, noisePrior); graph.addPrior(x1, pose1, noisePrior);
graph.addPrior(x2, pose2, noisePrior); graph.addPrior(x2, pose2, noisePrior);
graph.addPrior(body_P_cam_key, Pose3::identity(), noisePrior);
// Pose3 noise_pose = Pose3(Rot3::Ypr(-M_PI/10, 0., -M_PI/10), Point3(0.5,0.1,0.3)); // noise from regular projection factor test below // Pose3 noise_pose = Pose3(Rot3::Ypr(-M_PI/10, 0., -M_PI/10), Point3(0.5,0.1,0.3)); // noise from regular projection factor test below
Pose3 noise_pose = Pose3(Rot3::Ypr(-M_PI / 100, 0., -M_PI / 100), Pose3 noise_pose = Pose3(Rot3::Ypr(-M_PI / 100, 0., -M_PI / 100),
@ -1008,12 +1049,15 @@ TEST( SmartStereoProjectionFactorPP, landmarkDistance ) {
values.insert(x1, pose1); values.insert(x1, pose1);
values.insert(x2, pose2); values.insert(x2, pose2);
values.insert(x3, pose3 * noise_pose); values.insert(x3, pose3 * noise_pose);
values.insert(body_P_cam_key, Pose3::identity());
// All factors are disabled and pose should remain where it is std::cout << "optimization " << std::endl;
// All smart factors are disabled and pose should remain where it is
Values result; Values result;
LevenbergMarquardtOptimizer optimizer(graph, values, lm_params); LevenbergMarquardtOptimizer optimizer(graph, values, lm_params);
result = optimizer.optimize(); result = optimizer.optimize();
EXPECT(assert_equal(values.at<Pose3>(x3), result.at<Pose3>(x3))); EXPECT(assert_equal(values.at<Pose3>(x3), result.at<Pose3>(x3), 1e-5));
EXPECT_DOUBLES_EQUAL(graph.error(values), graph.error(result), 1e-5);
} }
/* ************************************************************************* /* *************************************************************************