33     const TMatchingPair& c, std::vector<bool>& alreadySelectedThis,
    34     std::vector<bool>& alreadySelectedOther
    35 #ifdef AVOID_MULTIPLE_CORRESPONDENCES
    37     const std::vector<std::vector<int>>& listDuplicatedLandmarksThis
    44 #ifndef AVOID_MULTIPLE_CORRESPONDENCES    45     alreadySelectedThis[c.
this_idx] = 
true;
    48     for (std::vector<int>::iterator it1 =
    49              listDuplicatedLandmarksThis[c.
this_idx].begin();
    50          it1 != listDuplicatedLandmarksThis[c.
this_idx].end(); it1++)
    51         alreadySelectedThis[*it1] = 
true;
    52     for (std::vector<int>::iterator it2 =
    53              listDuplicatedLandmarksOther[c.
other_idx].begin();
    54          it2 != listDuplicatedLandmarksOther[c.
other_idx].end(); it2++)
    55         alreadySelectedOther[*it2] = 
true;
    90     const size_t nCorrs = in_correspondences.size();
    93     const double MAX_RMSE_TO_END =
   100     if (nCorrs < 
params.ransac_minSetSize)
   103         results.transformation.clear();
   109     timlog.enter(
"ransac.find_max*");
   112     unsigned int maxThis = 0, maxOther = 0;
   113     for (
const auto& in_correspondence : in_correspondences)
   115         maxThis = max(maxThis, in_correspondence.this_idx);
   116         maxOther = max(maxOther, in_correspondence.other_idx);
   119     timlog.leave(
"ransac.find_max*");
   123     timlog.enter(
"ransac.count_unique_corrs");
   127     std::vector<bool> hasCorrThis(maxThis + 1, 
false);
   128     std::vector<bool> hasCorrOther(maxOther + 1, 
false);
   129     unsigned int howManyDifCorrs = 0;
   130     for (
const auto& in_correspondence : in_correspondences)
   132         if (!hasCorrThis[in_correspondence.this_idx] &&
   133             !hasCorrOther[in_correspondence.other_idx])
   135             hasCorrThis[in_correspondence.this_idx] = 
true;
   136             hasCorrOther[in_correspondence.other_idx] = 
true;
   141     timlog.leave(
"ransac.count_unique_corrs");
   145     results.transformation.clear();
   149     if (howManyDifCorrs < 
params.ransac_minSetSize)
   152         results.transformation.clear();
   157 #ifdef AVOID_MULTIPLE_CORRESPONDENCES   164     std::vector<std::vector<int>> listDuplicatedLandmarksThis(maxThis + 1);
   166     for (k = 0; k < nCorrs - 1; k++)
   168         std::vector<int> duplis;
   169         for (
unsigned j = k; j < nCorrs - 1; j++)
   171             if (in_correspondences[k].this_x == in_correspondences[j].this_x &&
   172                 in_correspondences[k].this_y == in_correspondences[j].this_y &&
   173                 in_correspondences[k].this_z == in_correspondences[j].this_z)
   174                 duplis.push_back(in_correspondences[j].this_idx);
   176         listDuplicatedLandmarksThis[in_correspondences[k].this_idx] = duplis;
   179     std::vector<std::vector<int>> listDuplicatedLandmarksOther(maxOther + 1);
   180     for (k = 0; k < nCorrs - 1; k++)
   182         std::vector<int> duplis;
   183         for (
unsigned j = k; j < nCorrs - 1; j++)
   185             if (in_correspondences[k].other_x ==
   186                     in_correspondences[j].other_x &&
   187                 in_correspondences[k].other_y ==
   188                     in_correspondences[j].other_y &&
   189                 in_correspondences[k].other_z == in_correspondences[j].other_z)
   190                 duplis.push_back(in_correspondences[j].other_idx);
   192         listDuplicatedLandmarksOther[in_correspondences[k].other_idx] = duplis;
   196     std::deque<TMatchingPairList> alreadyAddedSubSets;
   201     const double ransac_consistency_test_chi2_quantile = 0.99;
   202     const double chi2_thres_dim1 =
   208     size_t largest_consensus_yet = 0;  
   209     double largestSubSet_RMSE = std::numeric_limits<double>::max();
   212     const bool use_dynamic_iter_number = 
results.ransac_iters == 0;
   213     if (use_dynamic_iter_number)
   216             params.probability_find_good_model > 0 &&
   217             params.probability_find_good_model < 1);
   223     std::vector<bool> alreadySelectedThis, alreadySelectedOther;
   225     if (!
params.ransac_algorithmForLandmarks)
   227         alreadySelectedThis.assign(maxThis + 1, 
false);
   228         alreadySelectedOther.assign(maxOther + 1, 
false);
   234     std::vector<size_t> corrsIdxs(nCorrs), corrsIdxsPermutation;
   235     for (
size_t i = 0; i < nCorrs; i++) corrsIdxs[i] = i;
   238     for (iter_idx = 0; iter_idx < 
results.ransac_iters;
   242         CTimeLoggerEntry tle(timlog, 
"ransac.iter");
   246         timlog.enter(
"ransac.permute");
   251         timlog.leave(
"ransac.permute");
   257         if (
params.ransac_algorithmForLandmarks)
   260             timlog.enter(
"ransac.reset_selection_marks");
   262             alreadySelectedThis.assign(maxThis + 1, 
false);
   263             alreadySelectedOther.assign(maxOther + 1, 
false);
   265             timlog.leave(
"ransac.reset_selection_marks");
   278         timlog.enter(
"ransac.inner_loops");
   280         for (
unsigned int j = 0;
   281              j < nCorrs && subSet.size() < 
params.ransac_maxSetSize; j++)
   283             const size_t idx = corrsIdxsPermutation[j];
   288             if (alreadySelectedThis[corr_j.
this_idx] ||
   293             if (
params.user_individual_compat_callback)
   298                 if (!
params.user_individual_compat_callback(pm))
   302             if (subSet.size() < 2)
   308                 subSet.push_back(corr_j);
   309                 markAsPicked(corr_j, alreadySelectedThis, alreadySelectedOther);
   311                 if (subSet.size() == 2)
   319                     const double corrs_dist1 =
   321                             subSet[0].this_x, subSet[0].this_y,
   322                             subSet[1].this_x, subSet[1].this_y);
   324                     const double corrs_dist2 =
   326                             subSet[0].other_x, subSet[0].other_y,
   327                             subSet[1].other_x, subSet[1].other_y);
   331                     const double corrs_dist_chi2 =
   336                     bool is_acceptable = (corrs_dist_chi2 < chi2_thres_dim1);
   349                             (referenceEstimation.
cov(2, 2) <
   357                         subSet.erase(subSet.begin() + (subSet.size() - 1));
   363                             corr_j, alreadySelectedThis, alreadySelectedOther);
   370                 timlog.enter(
"ransac.test_consistency");
   390                 const bool passTest =
   391                     maha_dist < 
params.ransac_mahalanobisDistanceThreshold;
   396                     subSet.push_back(corr_j);
   398                         corr_j, alreadySelectedThis, alreadySelectedOther);
   403                 timlog.leave(
"ransac.test_consistency");
   409         timlog.leave(
"ransac.inner_loops");
   412         const bool has_to_eval_RMSE =
   413             (subSet.size() >= 
params.ransac_minSetSize);
   417         double this_subset_RMSE = 0;
   418         if (has_to_eval_RMSE)
   421             CTimeLoggerEntry tle(timlog, 
"ransac.comp_rmse");
   429             for (
size_t k = 0; k < subSet.size(); k++)
   433                     subSet[k].other_x, subSet[k].other_y, gx, gy);
   436                     mrpt::math::distanceSqrBetweenPoints<double>(
   437                         subSet[k].this_x, subSet[k].this_y, gx, gy);
   439             this_subset_RMSE /= std::max(static_cast<size_t>(1), subSet.size());
   443             this_subset_RMSE = std::numeric_limits<double>::max();
   449         if (subSet.size() >= 
params.ransac_minSetSize)
   458             if (!
params.ransac_fuseByCorrsMatch)
   462                 for (
size_t i = 0; i < 
results.transformation.size(); i++)
   465                         results.transformation.get(i).mean.distanceTo(
   466                             referenceEstimation.
mean);
   468                         results.transformation.get(i).mean.phi() -
   469                         referenceEstimation.
mean.
phi()));
   470                     if (diffXY < 
params.ransac_fuseMaxDiffXY &&
   471                         diffPhi < 
params.ransac_fuseMaxDiffPhi)
   489                 for (
size_t i = 0; i < alreadyAddedSubSets.size(); i++)
   491                     if (subSet == alreadyAddedSubSets[i])
   499             if (indexFound != -1)
   502                 if (
params.ransac_algorithmForLandmarks)
   503                     results.transformation.get(indexFound).log_w = log(
   504                         1 + exp(
results.transformation.get(indexFound).log_w));
   506                     results.transformation.get(indexFound).log_w =
   508                             exp(
results.transformation.get(indexFound).log_w));
   513                 alreadyAddedSubSets.push_back(subSet);
   516                 if (
params.ransac_algorithmForLandmarks)
   517                     newSOGMode.
log_w = 0;  
   519                     newSOGMode.
log_w = log(static_cast<double>(subSet.size()));
   521                 newSOGMode.
mean = referenceEstimation.
mean;
   522                 newSOGMode.
cov = referenceEstimation.
cov;
   525                 results.transformation.push_back(newSOGMode);
   529         const size_t ninliers = subSet.size();
   530         if (largest_consensus_yet < ninliers)
   532             largest_consensus_yet = ninliers;
   535             if (use_dynamic_iter_number)
   540                 const double fracinliers =
   542                     static_cast<double>(howManyDifCorrs);  
   544                     1 - pow(fracinliers, static_cast<double>(
   547                 pNoOutliers = std::max(
   548                     std::numeric_limits<double>::epsilon(),
   550                 pNoOutliers = std::min(
   551                     1.0 - std::numeric_limits<double>::epsilon(),
   555                     log(1 - 
params.probability_find_good_model) /
   558                 results.ransac_iters = std::max(
   562                     cout << 
"[tfest::RANSAC] Iter #" << iter_idx
   563                          << 
":est. # iters=" << 
results.ransac_iters
   564                          << 
" pNoOutliers=" << pNoOutliers
   565                          << 
" #inliers: " << ninliers << endl;
   570         if (subSet.size() >= 
params.ransac_minSetSize &&
   571             this_subset_RMSE < largestSubSet_RMSE)
   574                 cout << 
"[tfest::RANSAC] Iter #" << iter_idx
   575                      << 
" Better subset: " << subSet.size()
   576                      << 
" inliers, RMSE=" << this_subset_RMSE << endl;
   578             results.largestSubSet = subSet;
   579             largestSubSet_RMSE = this_subset_RMSE;
   583         if (subSet.size() >= 
params.ransac_minSetSize &&
   584             this_subset_RMSE < MAX_RMSE_TO_END)
   590         timlog.leave(
"ransac.iter");
   595         cout << 
"[tfest::RANSAC] Finished after " << iter_idx
   599     results.transformation.normalizeWeights();
   604         printf(
"nCorrs=%u\n", static_cast<unsigned int>(nCorrs));
   605         printf(
"Saving '_debug_in_correspondences.txt'...");
   606         in_correspondences.dumpToFile(
"_debug_in_correspondences.txt");
   607         printf(
"Ok\n"); printf(
"Saving '_debug_results.transformation.txt'...");
   608         results.transformation.saveToTextFile(
   609             "_debug_results.transformation.txt");
 A namespace of pseudo-random numbers generators of diferent distributions. 
 
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 ...
 
CPose2D mean
The mean value. 
 
const float normalizationStd
 
The struct for each mode: 
 
A gaussian distribution for 2D points. 
 
void markAsPicked(const TMatchingPair &c, std::vector< bool > &alreadySelectedThis, std::vector< bool > &alreadySelectedOther)
 
bool se2_l2(const mrpt::tfest::TMatchingPairList &in_correspondences, mrpt::math::TPose2D &out_transformation, mrpt::math::CMatrixDouble33 *out_estimateCovariance=nullptr)
Least-squares (L2 norm) solution to finding the optimal SE(2) (x,y,yaw) between two reference frames...
 
Parameters for se2_l2_robust(). 
 
mrpt::vision::TStereoCalibParams params
 
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. 
 
#define MRPT_END_WITH_CLEAN_UP(stuff)
 
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. 
 
#define ASSERT_(f)
Defines an assertion mechanism. 
 
This base provides a set of functions for maths stuff. 
 
bool se2_l2_robust(const mrpt::tfest::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 ...
 
map< string, CVectorDouble > results
 
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
 
mrpt::system::CTimeLogger CTimeLogger
 
double phi() const
Get the phi angle of the 2D pose (in radians) 
 
constexpr double DEG2RAD(const double x)
Degrees to radians. 
 
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...
 
A structure for holding correspondences between two sets of points or points-like entities in 2D or 3...
 
return_t square(const num_t x)
Inline function for the square of a number. 
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
double chi2inv(double P, unsigned int dim=1)
The "quantile" of the Chi-Square distribution, for dimension "dim" and probability 0<P<1 (the inverse...
 
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug. 
 
T distanceBetweenPoints(const T x1, const T y1, const T x2, const T y2)
Returns the distance between 2 points in 2D. 
 
bool verbose
Show progress messages to std::cout console (default=true) 
 
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications. 
 
double log_w
The log-weight. 
 
Functions for estimating the optimal transformation between two frames of references given measuremen...
 
For each individual-compatibility (IC) test, the indices of the candidate match between elements in b...
 
Output placeholder for se2_l2_robust() 
 
int round(const T value)
Returns the closer integer (int) to x.