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)