26 using namespace Eigen;
    31 ConsistencyTest::ConsistencyTest(
PbMap &PBM_source, 
PbMap &PBM_target) :
    32     PBMSource(PBM_source),
    38   double sum_depth_errors2 = 0;
    47   double avError2 = sum_depth_errors2 / sum_areas;
    48   return sqrt(avError2);
    57     cout << 
"Insuficient matched planes " << 
matched_planes.size() << endl;
    58     return Eigen::Matrix4f::Identity();
    62   Matrix3f normalCovariances = Matrix3f::Zero();
    63   normalCovariances(0,0) = 1;  
    67   JacobiSVD<MatrixXf> svd(normalCovariances, ComputeThinU | ComputeThinV);
    68   Matrix3f Rotation = svd.matrixV() * svd.matrixU().transpose();
    71   bool bPlanar_cond = 
false;
    78       if(fabs(planar_conditioning(0)) > 0.33)
    87     return Eigen::Matrix4f::Identity();
    90   double det = Rotation.determinant();
    94     aux << 1, 0, 0, 0, 1, 0, 0, 0, 
det;
    95     Rotation = svd.matrixV() * aux * svd.matrixU().transpose();
   115   Vector3f translation;
   116   Matrix3f hessian = Matrix3f::Zero();
   117   Vector3f gradient = Vector3f::Zero();
   118   float accum_error2 = 0.0;
   124     accum_error2 += trans_error * trans_error;
   130   translation = -hessian.inverse() * gradient;
   145   Eigen::Matrix4f rigidTransf;
   146   rigidTransf.block(0,0,3,3) = Rotation;
   147   rigidTransf.block(0,3,3,1) = translation;
   148   rigidTransf.row(3) << 0,0,0,1;
   157     cout << 
"Insuficient matched planes " << 
matched_planes.size() << endl;
   158     return Eigen::Matrix4f::Identity();
   162   Matrix3f normalCovariances = Matrix3f::Zero();
   169   for(
unsigned r=0; 
r<3; 
r++)
   170     for(
unsigned c=0; 
c<3; 
c++)
   171       normalCovariances(0,0) += normalCovariances(
r,
c);
   173   JacobiSVD<MatrixXf> svd(normalCovariances, ComputeThinU | ComputeThinV);
   174   Matrix3f Rotation = svd.matrixV() * svd.matrixU().transpose();
   177   bool bPlanar_cond = 
false;
   184       if(fabs(planar_conditioning(0)) > 0.33)
   193     return Eigen::Matrix4f::Identity();
   196   double det = Rotation.determinant();
   200     aux << 1, 0, 0, 0, 1, 0, 0, 0, 
det;
   201     Rotation = svd.matrixV() * aux * svd.matrixU().transpose();
   216   Vector3f translation;
   217   Matrix3f hessian = Matrix3f::Zero();
   218   Vector3f gradient = Vector3f::Zero();
   233   for(
unsigned r=0; 
r<3; 
r++)
   234     for(
unsigned c=0; 
c<3; 
c++)
   235       hessian(0,0) += hessian(
r,
c);
   237   translation = -hessian.inverse() * gradient;
   252   Eigen::Matrix4f rigidTransf;
   253   rigidTransf.block(0,0,3,3) = Rotation;
   254   rigidTransf.block(0,3,3,1) = translation;
   255   rigidTransf.row(3) << 0,0,0,1;
   260                                                  Eigen::Matrix4f &rigidTransf,
   261                                                  Eigen::Matrix<float,6,6> &covarianceM)
   265     cout << 
"Insuficient matched planes " << 
matched_planes.size() << endl;
   273   JacobiSVD<MatrixXf> svd_cond(normalVectors, ComputeThinU | ComputeThinV);
   275   if(svd_cond.singularValues()[0] / svd_cond.singularValues()[1] > 10)
   279   Matrix3f normalCovariances = Matrix3f::Zero();
   285   for(
unsigned r=0; 
r<3; 
r++)
   286     for(
unsigned c=0; 
c<3; 
c++)
   287       normalCovariances(0,0) += fabs(normalCovariances(
r,
c));
   289   JacobiSVD<MatrixXf> svd(normalCovariances, ComputeThinU | ComputeThinV);
   291   Matrix3f Rotation = svd.matrixV() * svd.matrixU().transpose();
   292   double det = Rotation.determinant();
   296     aux << 1, 0, 0, 0, 1, 0, 0, 0, 
det;
   297     Rotation = svd.matrixV() * aux * svd.matrixU().transpose();
   301   Vector3f translation;
   302   Matrix3f hessian = Matrix3f::Zero();
   303   Vector3f gradient = Vector3f::Zero();
   313   for(
unsigned r=0; 
r<3; 
r++)
   314     for(
unsigned c=0; 
c<3; 
c++)
   315       hessian(0,0) += fabs(hessian(
r,
c));
   317   translation = -hessian.inverse() * gradient;
   321   rigidTransf.block(0,0,3,3) = Rotation;
   322   rigidTransf.block(0,3,3,1) = translation;
   323   rigidTransf.row(3) << 0,0,0,1;
   326   covarianceM.block(0,0,3,3) = hessian; 
   327   covarianceM.block(3,3,3,3) = normalCovariances; 
   335   Matrix3f normalCovariances = Matrix3f::Zero();
   338   normalCovariances(1,1) += 100; 
   340   JacobiSVD<MatrixXf> svd(normalCovariances, ComputeThinU | ComputeThinV);
   341   Matrix3f Rotation = svd.matrixU() * svd.matrixV().transpose();
   343   if(Rotation.determinant() < 0)
   345     Rotation = -Rotation;
   348   Vector3f translation;
   349   Vector3f center_data = Vector3f::Zero(), center_model = Vector3f::Zero();
   350   Vector3f centerFull_data = Vector3f::Zero(), centerFull_model = Vector3f::Zero();
   351   unsigned numFull = 0, numNonStruct = 0;
   369     translation = (-centerFull_model + Rotation * centerFull_data) / numFull;
   373     translation = (-center_model + Rotation * center_data) / numNonStruct;
   379   Eigen::Matrix4f rigidTransf;
   380   rigidTransf.block(0,0,3,3) = Rotation;
   381   rigidTransf.block(0,3,3,1) = translation;
   382   rigidTransf.row(3) << 0,0,0,1;
   396     cout << 
"INITIALIZATION POSE \n" << rigidTransf << endl;
   397     cout << 
"Alignment error " << alignmentError << endl;
   401   double improveRate = 0;
   402   while( nIter < 10 && improveRate < 0.999 )
   405     Vector3f ptInModelRef;
   406     Eigen::Matrix<float,6,1> v6JacDepthPlane;
   407     Eigen::Matrix<float,6,1> v6Error = Eigen::Matrix<float,6,1>::Zero();
   408     Eigen::Matrix<float,6,6> m6Hessian = Eigen::Matrix<float,6,6>::Zero();
   419       m6Hessian += v6JacDepthPlane * v6JacDepthPlane.transpose();
   420       v6Error += v6JacDepthPlane * depthError;
   423     Eigen::Matrix<float,6,1> updatedSE3 = (m6Hessian.inverse() * v6Error).
transpose();
   425     _updatedSE3(0) = updatedSE3(0);
   426     _updatedSE3(1) = updatedSE3(1);
   427     _updatedSE3(2) = updatedSE3(2);
   428     _updatedSE3(3) = updatedSE3(3);
   429     _updatedSE3(4) = updatedSE3(4);
   430     _updatedSE3(5) = updatedSE3(5);
   432     Eigen::Matrix4f updatePose;
   433     updatePose << CMatUpdate(0,0), CMatUpdate(0,1), CMatUpdate(0,2), CMatUpdate(0,3),
   434                   CMatUpdate(1,0), CMatUpdate(1,1), CMatUpdate(1,2), CMatUpdate(1,3),
   435                   CMatUpdate(2,0), CMatUpdate(2,1), CMatUpdate(2,2), CMatUpdate(2,3),
   437     Eigen::Matrix4f tempPose = 
compose(updatePose, rigidTransf);
   440     cout << 
"New alignment error " << newError << endl;
   443     if(newError < alignmentError)
   445       improveRate = newError / alignmentError;
   446       alignmentError = newError;
   447       rigidTransf = tempPose;
   452         cout << 
"Not converging in iteration " << nIter << endl;
   461     cout << 
"Consistency test converged after " << nIter << endl;
   471   assert(
size(matched_planes,1) == 8 && 
size(matched_planes,2) == 3);
   474   Matrix3f normalCovariances = Matrix3f::Zero();
   475   normalCovariances(0,0) = 1;
   476   for(
unsigned i=0; i<3; i++)
   478     Vector3f n_i = Vector3f(matched_planes(0,i), matched_planes(1,i), matched_planes(2,i));
   479     Vector3f n_ii = Vector3f(matched_planes(4,i), matched_planes(5,i), matched_planes(6,i));
   480     normalCovariances += n_i * n_ii.transpose();
   484   JacobiSVD<MatrixXf> svd(normalCovariances, ComputeThinU | ComputeThinV);
   485   Matrix3f Rotation = svd.matrixV() * svd.matrixU().transpose();
   494   double det = Rotation.determinant();
   498     aux << 1, 0, 0, 0, 1, 0, 0, 0, 
det;
   499     Rotation = svd.matrixV() * aux * svd.matrixU().transpose();
   504   Vector3f translation;
   505   Matrix3f hessian = Matrix3f::Zero();
   506   Vector3f gradient = Vector3f::Zero();
   508   for(
unsigned i=0; i<3; i++)
   510     float trans_error = (matched_planes(3,i) - matched_planes(7,i)); 
   513     Vector3f n_i = Vector3f(matched_planes(0,i), matched_planes(1,i), matched_planes(2,i));
   514     hessian += n_i * n_i.transpose();
   515     gradient += n_i * trans_error;
   517   translation = -hessian.inverse() * gradient;
   527   rigidTransf(0,0) = Rotation(0,0);
   528   rigidTransf(0,1) = Rotation(0,1);
   529   rigidTransf(0,2) = Rotation(0,2);
   530   rigidTransf(1,0) = Rotation(1,0);
   531   rigidTransf(1,1) = Rotation(1,1);
   532   rigidTransf(1,2) = Rotation(1,2);
   533   rigidTransf(2,0) = Rotation(2,0);
   534   rigidTransf(2,1) = Rotation(2,1);
   535   rigidTransf(2,2) = Rotation(2,2);
   536   rigidTransf(0,3) = translation(0);
   537   rigidTransf(1,3) = translation(1);
   538   rigidTransf(2,3) = translation(2);
   539   rigidTransf(3,0) = 0;
   540   rigidTransf(3,1) = 0;
   541   rigidTransf(3,2) = 0;
   542   rigidTransf(3,3) = 1;
   551         vector< CMatrixDouble > &fitModels )
   562     for(
unsigned i=0; i<3; i++)
   563       corresp.col(i) = planeCorresp.col(useIndices[i]);
   579         const vector< CMatrixDouble > & testModels,
   580         const double distanceThreshold,
   581         unsigned int & out_bestModelIndex,
   584   ASSERT_( testModels.size()==1 )
   585   out_bestModelIndex = 0;
   588   Eigen::Matrix3f Rotation; Rotation << M(0,0), M(0,1), M(0,2), M(1,0), M(1,1), M(1,2), M(2,0), M(2,1), M(2,2);
   589   Eigen::Vector3f translation; translation << M(0,3), M(1,3), M(2,3);
   593   const size_t N = 
size(planeCorresp,2);
   594   out_inlierIndices.clear();
   595   out_inlierIndices.reserve(100);
   596   for (
size_t i=0;i<N;i++)
   598     const Eigen::Vector3f n_i = Eigen::Vector3f(planeCorresp(0,i), planeCorresp(1,i), planeCorresp(2,i));
   599     const Eigen::Vector3f n_ii = Rotation * Eigen::Vector3f(planeCorresp(4,i), planeCorresp(5,i), planeCorresp(6,i));
   600     const float d_error = fabs((planeCorresp(7,i) - translation.dot(n_i)) - planeCorresp(3,i));
   601     const float angle_error = (n_i .cross (n_ii )).
norm();
   603     if (d_error < distanceThreshold)
   604      if (angle_error < distanceThreshold) 
   605       out_inlierIndices.push_back(i);
   615   ASSERT_( useIndices.size()==3 )
   617   const Eigen::Vector3f n_1 = Eigen::Vector3f(planeCorresp(0,useIndices[0]), planeCorresp(1,useIndices[0]), planeCorresp(2,useIndices[0]));
   618   const Eigen::Vector3f n_2 = Eigen::Vector3f(planeCorresp(0,useIndices[1]), planeCorresp(1,useIndices[1]), planeCorresp(2,useIndices[1]));
   619   const Eigen::Vector3f n_3 = Eigen::Vector3f(planeCorresp(0,useIndices[2]), planeCorresp(1,useIndices[2]), planeCorresp(2,useIndices[2]));
   622   if( fabs(n_1. dot( n_2. 
cross(n_3) ) ) < 0.9 )
   639     cout << 
"Insuficient matched planes " << 
matched_planes.size() << endl;
   640     return Eigen::Matrix4f::Identity();
   663   ransac_executer.
execute(planeCorresp,
   677   cout << 
"Size planeCorresp: " << 
size(planeCorresp,2) << endl;
   678   cout << 
"RANSAC finished: " << inliers.size() << 
" inliers: " << inliers << 
" . \nBest model: \n" << best_model << endl;
   681   Eigen::Matrix4f rigidTransf; rigidTransf << best_model(0,0), best_model(0,1), best_model(0,2), best_model(0,3), best_model(1,0), best_model(1,1), best_model(1,2), best_model(1,3), best_model(2,0), best_model(2,1), best_model(2,2), best_model(2,3), 0, 0, 0, 1;
 EIGEN_STRONG_INLINE Scalar det() const
 
Eigen::Matrix4f estimatePose(std::map< unsigned, unsigned > &matched_planes)
 
bool execute(const CMatrixTemplateNumeric< NUMTYPE > &data, TRansacFitFunctor fit_func, TRansacDistanceFunctor dist_func, TRansacDegenerateFunctor degen_func, const double distanceThreshold, const unsigned int minimumSizeSamplesToFit, mrpt::vector_size_t &out_best_inliers, CMatrixTemplateNumeric< NUMTYPE > &out_best_model, const double prob_good_sample=0.999, const size_t maxIter=2000) const
An implementation of the RANSAC algorithm for robust fitting of models to data. 
 
void ransacPlaneAlignment_fit(const CMatrixDouble &planeCorresp, const mrpt::vector_size_t &useIndices, vector< CMatrixDouble > &fitModels)
 
CArrayNumeric is an array for numeric types supporting several mathematical operations (actually...
 
Eigen::Matrix4f estimatePoseRANSAC(std::map< unsigned, unsigned > &matched_planes)
 
A numeric matrix of compile-time fixed size. 
 
This base provides a set of functions for maths stuff. 
 
bool ransac3Dplane_degenerate(const CMatrixDouble &planeCorresp, const mrpt::vector_size_t &useIndices)
Return "true" if the selected points are a degenerate (invalid) case. 
 
Eigen::Matrix< dataType, 3, 1 > compose(Eigen::Matrix< dataType, 4, 4 > &pose, Eigen::Matrix< dataType, 3, 1 > &point)
 
Eigen::Matrix4f initPose2D(std::map< unsigned, unsigned > &matched_planes)
 
float cross(const mPointHull &O, const mPointHull &A, const mPointHull &B)
 
CMatrixDouble getAlignment(const CMatrixDouble &matched_planes)
 
GLsizei GLboolean transpose
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
double calcAlignmentError(std::map< unsigned, unsigned > &matched_planes, Eigen::Matrix4f &rigidTransf)
! Get diamond of points around the center. 
 
GLdouble GLdouble GLdouble r
 
Eigen::Matrix4f initPose(std::map< unsigned, unsigned > &matched_planes)
 
A matrix of dynamic size. 
 
std::vector< size_t > vector_size_t
 
std::map< unsigned, unsigned > matched_planes
 
void ransac3Dplane_distance(const CMatrixDouble &planeCorresp, const vector< CMatrixDouble > &testModels, const double distanceThreshold, unsigned int &out_bestModelIndex, mrpt::vector_size_t &out_inlierIndices)
 
std::vector< Plane > vPlanes
 
A generic RANSAC implementation with models as matrices. 
 
static CPose3D exp(const mrpt::math::CArrayNumeric< double, 6 > &vect, bool pseudo_exponential=false)
Exponentiate a Vector in the SE(3) Lie Algebra to generate a new CPose3D (static method). 
 
A class used to store a Plane-based Map (PbMap). 
 
void getHomogeneousMatrix(mrpt::math::CMatrixDouble44 &out_HM) const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
 
CONTAINER::Scalar norm(const CONTAINER &v)
 
bool estimatePoseWithCovariance(std::map< unsigned, unsigned > &matched_planes, Eigen::Matrix4f &rigidTransf, Eigen::Matrix< float, 6, 6 > &covarianceM)
 
std::vector< size_t > vector_size_t
 
Eigen::Matrix4f getRTwithModel(std::map< unsigned, unsigned > &matched_planes)