33 std::vector<bool> &alreadySelectedThis,
34 std::vector<bool> &alreadySelectedOther
35 #ifdef AVOID_MULTIPLE_CORRESPONDENCES
36 ,
const std::vector<vector_int> &listDuplicatedLandmarksThis
40 ASSERTDEB_(
c.this_idx < alreadySelectedThis.size() );
41 ASSERTDEB_(
c.other_idx < alreadySelectedOther.size() );
43 #ifndef AVOID_MULTIPLE_CORRESPONDENCES 44 alreadySelectedThis[
c.this_idx ]=
true;
45 alreadySelectedOther[
c.other_idx ] =
true;
47 for (
vector_int::iterator it1 = listDuplicatedLandmarksThis[
c.this_idx].begin();it1!=listDuplicatedLandmarksThis[
c.this_idx].end();it1++)
48 alreadySelectedThis[ *it1 ] =
true;
49 for (
vector_int::iterator it2 = listDuplicatedLandmarksOther[
c.other_idx].begin();it2!=listDuplicatedLandmarksOther[
c.other_idx].end();it2++)
50 alreadySelectedOther[ *it2 ] =
true;
86 const size_t nCorrs = in_correspondences.size();
94 if( nCorrs <
params.ransac_minSetSize )
104 timlog.
enter(
"ransac.find_max*");
107 unsigned int maxThis=0, maxOther=0;
110 maxThis = max(maxThis , matchIt->this_idx );
111 maxOther= max(maxOther, matchIt->other_idx );
114 timlog.
leave(
"ransac.find_max*");
119 timlog.
enter(
"ransac.count_unique_corrs");
123 std::vector<bool> hasCorrThis(maxThis+1,
false);
124 std::vector<bool> hasCorrOther(maxOther+1,
false);
125 unsigned int howManyDifCorrs = 0;
128 if (!hasCorrThis[matchIt->this_idx] &&
129 !hasCorrOther[matchIt->other_idx] )
131 hasCorrThis[matchIt->this_idx] =
true;
132 hasCorrOther[matchIt->other_idx] =
true;
137 timlog.
leave(
"ransac.count_unique_corrs");
144 if ( howManyDifCorrs <
params.ransac_minSetSize )
153 #ifdef AVOID_MULTIPLE_CORRESPONDENCES 158 std::vector<vector_int> listDuplicatedLandmarksThis(maxThis+1);
160 for (k=0;k<nCorrs-1;k++)
163 for (
unsigned j=k;j<nCorrs-1;j++)
165 if ( in_correspondences[k].this_x == in_correspondences[j].this_x &&
166 in_correspondences[k].this_y == in_correspondences[j].this_y &&
167 in_correspondences[k].this_z == in_correspondences[j].this_z )
168 duplis.push_back(in_correspondences[j].this_idx);
170 listDuplicatedLandmarksThis[in_correspondences[k].this_idx] = duplis;
173 std::vector<vector_int> listDuplicatedLandmarksOther(maxOther+1);
174 for (k=0;k<nCorrs-1;k++)
177 for (
unsigned j=k;j<nCorrs-1;j++)
179 if ( in_correspondences[k].other_x == in_correspondences[j].other_x &&
180 in_correspondences[k].other_y == in_correspondences[j].other_y &&
181 in_correspondences[k].other_z == in_correspondences[j].other_z )
182 duplis.push_back(in_correspondences[j].other_idx);
184 listDuplicatedLandmarksOther[in_correspondences[k].other_idx] = duplis;
188 std::deque<TMatchingPairList> alreadyAddedSubSets;
193 const double ransac_consistency_test_chi2_quantile = 0.99;
194 const double chi2_thres_dim1 =
mrpt::math::chi2inv(ransac_consistency_test_chi2_quantile, 1);
199 size_t largest_consensus_yet = 0;
200 double largestSubSet_RMSE = std::numeric_limits<double>::max();
203 const bool use_dynamic_iter_number = results.
ransac_iters==0;
204 if (use_dynamic_iter_number)
211 std::vector<bool> alreadySelectedThis, alreadySelectedOther;
213 if (!
params.ransac_algorithmForLandmarks)
215 alreadySelectedThis.assign(maxThis+1,
false);
216 alreadySelectedOther.assign(maxOther+1,
false);
221 std::vector<size_t> corrsIdxs(nCorrs), corrsIdxsPermutation;
222 for (
size_t i=0;i<nCorrs;i++) corrsIdxs[i]= i;
225 for (iter_idx = 0;iter_idx<results.
ransac_iters; iter_idx++)
232 timlog.
enter(
"ransac.permute");
237 timlog.
leave(
"ransac.permute");
243 if (
params.ransac_algorithmForLandmarks)
246 timlog.
enter(
"ransac.reset_selection_marks");
248 alreadySelectedThis.assign(maxThis+1,
false);
249 alreadySelectedOther.assign(maxOther+1,
false);
251 timlog.
leave(
"ransac.reset_selection_marks");
262 timlog.
enter(
"ransac.inner_loops");
264 for (
unsigned int j=0;j<nCorrs && subSet.size()<
params.ransac_maxSetSize;j++)
266 const size_t idx = corrsIdxsPermutation[j];
271 if (alreadySelectedThis [corr_j.
this_idx] || alreadySelectedOther[corr_j.
other_idx])
275 if (
params.user_individual_compat_callback)
280 if (! (*
params.user_individual_compat_callback)(pm,
params.user_individual_compat_callback_userdata))
289 subSet.push_back( corr_j );
290 markAsPicked(corr_j, alreadySelectedThis,alreadySelectedOther);
292 if (subSet.size()==2)
300 subSet[0].this_x, subSet[0].this_y,
301 subSet[1].this_x, subSet[1].this_y );
304 subSet[0].other_x, subSet[0].other_y,
305 subSet[1].other_x, subSet[1].other_y );
309 const double corrs_dist_chi2 =
313 bool is_acceptable = (corrs_dist_chi2 < chi2_thres_dim1 );
330 subSet.erase( subSet.begin() + (subSet.size() -1) );
335 markAsPicked(corr_j, alreadySelectedThis,alreadySelectedOther);
342 timlog.
enter(
"ransac.test_consistency");
358 const bool passTest = maha_dist <
params.ransac_mahalanobisDistanceThreshold;
363 subSet.push_back( corr_j );
364 markAsPicked(corr_j, alreadySelectedThis,alreadySelectedOther);
369 timlog.
leave(
"ransac.test_consistency");
375 timlog.
leave(
"ransac.inner_loops");
379 const bool has_to_eval_RMSE = (subSet.size()>=
params.ransac_minSetSize);
382 double this_subset_RMSE = 0;
383 if (has_to_eval_RMSE)
394 for (
size_t k=0;k<subSet.size();k++)
398 subSet[k].other_x, subSet[k].other_y,
401 this_subset_RMSE += mrpt::math::distanceSqrBetweenPoints<double>( subSet[k].this_x,subSet[k].this_y, gx,gy );
403 this_subset_RMSE /= std::max( static_cast<size_t>(1), subSet.size() );
407 this_subset_RMSE = std::numeric_limits<double>::max();
412 if (subSet.size()>=
params.ransac_minSetSize)
419 if (!
params.ransac_fuseByCorrsMatch)
427 if ( diffXY <
params.ransac_fuseMaxDiffXY && diffPhi <
params.ransac_fuseMaxDiffPhi )
443 for (
size_t i=0;i<alreadyAddedSubSets.size();i++)
445 if ( subSet == alreadyAddedSubSets[i] )
456 if (
params.ransac_algorithmForLandmarks)
463 alreadyAddedSubSets.push_back( subSet );
466 if (
params.ransac_algorithmForLandmarks)
467 newSOGMode.
log_w = 0;
468 else newSOGMode.
log_w = log(static_cast<double>(subSet.size()));
470 newSOGMode.
mean = referenceEstimation.
mean;
471 newSOGMode.
cov = referenceEstimation.
cov;
478 const size_t ninliers = subSet.size();
479 if (largest_consensus_yet<ninliers )
481 largest_consensus_yet = ninliers;
484 if (use_dynamic_iter_number)
488 const double fracinliers = ninliers/
static_cast<double>(howManyDifCorrs);
489 double pNoOutliers = 1 - pow(fracinliers,static_cast<double>(2.0 ));
491 pNoOutliers = std::max( std::numeric_limits<double>::epsilon(), pNoOutliers);
492 pNoOutliers =
std::min(1.0 - std::numeric_limits<double>::epsilon() , pNoOutliers);
499 cout <<
"[tfest::RANSAC] Iter #" << iter_idx <<
":est. # iters=" << results.
ransac_iters <<
" pNoOutliers=" << pNoOutliers <<
" #inliers: " << ninliers << endl;
505 if (subSet.size()>=
params.ransac_minSetSize && this_subset_RMSE<largestSubSet_RMSE )
508 cout <<
"[tfest::RANSAC] Iter #" << iter_idx <<
" Better subset: " << subSet.size() <<
" inliers, RMSE=" << this_subset_RMSE << endl;
511 largestSubSet_RMSE = this_subset_RMSE;
515 if (subSet.size()>=
params.ransac_minSetSize &&
516 this_subset_RMSE<MAX_RMSE_TO_END)
522 timlog.
leave(
"ransac.iter");
527 cout <<
"[tfest::RANSAC] Finished after " << iter_idx <<
" iterations.\n";
536 printf(
"nCorrs=%u\n",static_cast<unsigned int>(nCorrs)); \
537 printf(
"Saving '_debug_in_correspondences.txt'..."); \
538 in_correspondences.dumpToFile(
"_debug_in_correspondences.txt"); \
540 printf(
"Saving '_debug_results.transformation.txt'..."); \
541 results.transformation.saveToTextFile(
"_debug_results.transformation.txt"); \
A namespace of pseudo-random numbers genrators of diferent distributions.
void normalizeWeights()
Normalize the weights in m_modes such as the maximum log-weight is 0.
void permuteVector(const VEC &in_vector, VEC &out_result)
Returns a random permutation of a vector: all the elements of the input vector are in the output but ...
void clear()
Clear the list of modes.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
CPose2D mean
The mean value.
const float normalizationStd
The struct for each mode:
double distanceTo(const CPoseOrPoint< OTHERCLASS > &b) const
Returns the Euclidean distance to another pose/point:
#define MRPT_END_WITH_CLEAN_UP(stuff)
A gaussian distribution for 2D points.
void markAsPicked(const TMatchingPair &c, std::vector< bool > &alreadySelectedThis, std::vector< bool > &alreadySelectedOther)
Parameters for se2_l2_robust().
mrpt::utils::TMatchingPairList largestSubSet
the largest consensus sub-set
BASE_IMPEXP CRandomGenerator randomGenerator
A static instance of a CRandomGenerator class, for use in single-thread applications.
const TGaussianMode & get(size_t i) const
Access to individual beacons.
bool TFEST_IMPEXP se2_l2_robust(const mrpt::utils::TMatchingPairList &in_correspondences, const double in_normalizationStd, const TSE2RobustParams &in_ransac_params, TSE2RobustResult &out_results)
Robust least-squares (L2 norm) solution to finding the optimal SE(2) (x,y,yaw) between two reference ...
const Scalar * const_iterator
void push_back(const TGaussianMode &m)
Inserts a copy of the given mode into the SOG.
void composePoint(const mrpt::math::TPoint2D &l, CPoint2DPDFGaussian &g) const
Returns the PDF of the 2D point with "q"=this pose and "l" a point without uncertainty.
void composePoint(double lx, double ly, double &gx, double &gy) const
An alternative, slightly more efficient way of doing with G and L being 2D points and P this 2D pose...
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
T square(const T x)
Inline function for the square of a number.
This base provides a set of functions for maths stuff.
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
mrpt::math::CMatrixDouble33 cov
double mahalanobisDistanceToPoint(const double x, const double y) const
Returns the Mahalanobis distance from this PDF to some point.
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
unsigned int ransac_iters
Number of actual iterations executed.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
double BASE_IMPEXP chi2inv(double P, unsigned int dim=1)
The "quantile" of the Chi-Square distribution, for dimension "dim" and probability 0<P<1 (the inverse...
A safe way to call enter() and leave() of a mrpt::utils::CTimeLogger upon construction and destructio...
const double & phi() const
Get the phi angle of the 2D pose (in radians)
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
double leave(const char *func_name)
End of a named section.
mrpt::poses::CPosePDFSOG transformation
The output as a set of transformations (sum of Gaussians)
std::vector< int32_t > vector_int
size_t size() const
Return the number of Gaussian modes.
T distanceBetweenPoints(const T x1, const T y1, const T x2, const T y2)
Returns the distance between 2 points in 2D.
bool TFEST_IMPEXP se2_l2(const mrpt::utils::TMatchingPairList &in_correspondences, mrpt::math::TPose2D &out_transformation, mrpt::math::CMatrixDouble33 *out_estimateCovariance=NULL)
Least-squares (L2 norm) solution to finding the optimal SE(2) (x,y,yaw) between two reference frames...
void enter(const char *func_name)
Start of a named section.
double log_w
The log-weight.
Functions for estimating the optimal transformation between two frames of references given measuremen...
GLenum const GLfloat * params
For each individual-compatibility (IC) test, the indices of the candidate match between elements in b...
Output placeholder for se2_l2_robust()
A structure for holding correspondences between two sets of points or points-like entities in 2D or 3...