33 std::vector<bool>& alreadySelectedOther
34 #ifdef AVOID_MULTIPLE_CORRESPONDENCES
36 const std::vector<std::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;
48 listDuplicatedLandmarksThis[
c.this_idx].begin();
49 it1 != listDuplicatedLandmarksThis[
c.this_idx].end(); it1++)
50 alreadySelectedThis[*it1] =
true;
52 listDuplicatedLandmarksOther[
c.other_idx].begin();
53 it2 != listDuplicatedLandmarksOther[
c.other_idx].end(); it2++)
54 alreadySelectedOther[*it2] =
true;
89 const size_t nCorrs = in_correspondences.size();
92 const double MAX_RMSE_TO_END =
99 if (nCorrs <
params.ransac_minSetSize)
102 results.transformation.clear();
108 timlog.enter(
"ransac.find_max*");
111 unsigned int maxThis = 0, maxOther = 0;
113 matchIt != in_correspondences.end(); ++matchIt)
115 maxThis = max(maxThis, matchIt->this_idx);
116 maxOther = max(maxOther, matchIt->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;
131 matchIt != in_correspondences.end(); ++matchIt)
133 if (!hasCorrThis[matchIt->this_idx] &&
134 !hasCorrOther[matchIt->other_idx])
136 hasCorrThis[matchIt->this_idx] =
true;
137 hasCorrOther[matchIt->other_idx] =
true;
142 timlog.leave(
"ransac.count_unique_corrs");
146 results.transformation.clear();
150 if (howManyDifCorrs <
params.ransac_minSetSize)
153 results.transformation.clear();
158 #ifdef AVOID_MULTIPLE_CORRESPONDENCES
165 std::vector<std::vector<int>> listDuplicatedLandmarksThis(maxThis + 1);
167 for (k = 0; k < nCorrs - 1; k++)
169 std::vector<int> duplis;
170 for (
unsigned j = k; j < nCorrs - 1; j++)
172 if (in_correspondences[k].this_x == in_correspondences[j].this_x &&
173 in_correspondences[k].this_y == in_correspondences[j].this_y &&
174 in_correspondences[k].this_z == in_correspondences[j].this_z)
175 duplis.push_back(in_correspondences[j].this_idx);
177 listDuplicatedLandmarksThis[in_correspondences[k].this_idx] = duplis;
180 std::vector<std::vector<int>> listDuplicatedLandmarksOther(maxOther + 1);
181 for (k = 0; k < nCorrs - 1; k++)
183 std::vector<int> duplis;
184 for (
unsigned j = k; j < nCorrs - 1; j++)
186 if (in_correspondences[k].other_x ==
187 in_correspondences[j].other_x &&
188 in_correspondences[k].other_y ==
189 in_correspondences[j].other_y &&
190 in_correspondences[k].other_z == in_correspondences[j].other_z)
191 duplis.push_back(in_correspondences[j].other_idx);
193 listDuplicatedLandmarksOther[in_correspondences[k].other_idx] = duplis;
197 std::deque<TMatchingPairList> alreadyAddedSubSets;
202 const double ransac_consistency_test_chi2_quantile = 0.99;
203 const double chi2_thres_dim1 =
209 size_t largest_consensus_yet = 0;
210 double largestSubSet_RMSE = std::numeric_limits<double>::max();
213 const bool use_dynamic_iter_number =
results.ransac_iters == 0;
214 if (use_dynamic_iter_number)
217 params.probability_find_good_model > 0 &&
218 params.probability_find_good_model < 1);
224 std::vector<bool> alreadySelectedThis, alreadySelectedOther;
226 if (!
params.ransac_algorithmForLandmarks)
228 alreadySelectedThis.assign(maxThis + 1,
false);
229 alreadySelectedOther.assign(maxOther + 1,
false);
235 std::vector<size_t> corrsIdxs(nCorrs), corrsIdxsPermutation;
236 for (
size_t i = 0; i < nCorrs; i++) corrsIdxs[i] = i;
239 for (iter_idx = 0; iter_idx <
results.ransac_iters;
243 CTimeLoggerEntry tle(timlog,
"ransac.iter");
247 timlog.enter(
"ransac.permute");
252 timlog.leave(
"ransac.permute");
258 if (
params.ransac_algorithmForLandmarks)
261 timlog.enter(
"ransac.reset_selection_marks");
263 alreadySelectedThis.assign(maxThis + 1,
false);
264 alreadySelectedOther.assign(maxOther + 1,
false);
266 timlog.leave(
"ransac.reset_selection_marks");
279 timlog.enter(
"ransac.inner_loops");
281 for (
unsigned int j = 0;
282 j < nCorrs && subSet.size() <
params.ransac_maxSetSize; j++)
284 const size_t idx = corrsIdxsPermutation[j];
289 if (alreadySelectedThis[corr_j.
this_idx] ||
294 if (
params.user_individual_compat_callback)
299 if (!
params.user_individual_compat_callback(pm))
303 if (subSet.size() < 2)
309 subSet.push_back(corr_j);
310 markAsPicked(corr_j, alreadySelectedThis, alreadySelectedOther);
312 if (subSet.size() == 2)
320 const double corrs_dist1 =
322 subSet[0].this_x, subSet[0].this_y,
323 subSet[1].this_x, subSet[1].this_y);
325 const double corrs_dist2 =
327 subSet[0].other_x, subSet[0].other_y,
328 subSet[1].other_x, subSet[1].other_y);
332 const double corrs_dist_chi2 =
337 bool is_acceptable = (corrs_dist_chi2 < chi2_thres_dim1);
350 (referenceEstimation.
cov(2, 2) <
358 subSet.erase(subSet.begin() + (subSet.size() - 1));
364 corr_j, alreadySelectedThis, alreadySelectedOther);
371 timlog.enter(
"ransac.test_consistency");
391 const bool passTest =
392 maha_dist <
params.ransac_mahalanobisDistanceThreshold;
397 subSet.push_back(corr_j);
399 corr_j, alreadySelectedThis, alreadySelectedOther);
404 timlog.leave(
"ransac.test_consistency");
410 timlog.leave(
"ransac.inner_loops");
413 const bool has_to_eval_RMSE =
414 (subSet.size() >=
params.ransac_minSetSize);
418 double this_subset_RMSE = 0;
419 if (has_to_eval_RMSE)
422 CTimeLoggerEntry tle(timlog,
"ransac.comp_rmse");
430 for (
size_t k = 0; k < subSet.size(); k++)
434 subSet[k].other_x, subSet[k].other_y, gx, gy);
437 mrpt::math::distanceSqrBetweenPoints<double>(
438 subSet[k].this_x, subSet[k].this_y, gx, gy);
440 this_subset_RMSE /= std::max(
static_cast<size_t>(1), subSet.size());
444 this_subset_RMSE = std::numeric_limits<double>::max();
450 if (subSet.size() >=
params.ransac_minSetSize)
459 if (!
params.ransac_fuseByCorrsMatch)
463 for (
size_t i = 0; i <
results.transformation.size(); i++)
466 results.transformation.get(i).mean.distanceTo(
467 referenceEstimation.
mean);
468 double diffPhi = fabs(
470 results.transformation.get(i).mean.phi() -
471 referenceEstimation.
mean.
phi()));
472 if (diffXY <
params.ransac_fuseMaxDiffXY &&
473 diffPhi <
params.ransac_fuseMaxDiffPhi)
491 for (
size_t i = 0; i < alreadyAddedSubSets.size(); i++)
493 if (subSet == alreadyAddedSubSets[i])
501 if (indexFound != -1)
504 if (
params.ransac_algorithmForLandmarks)
505 results.transformation.get(indexFound).log_w = log(
506 1 + exp(
results.transformation.get(indexFound).log_w));
508 results.transformation.get(indexFound).log_w =
510 exp(
results.transformation.get(indexFound).log_w));
515 alreadyAddedSubSets.push_back(subSet);
518 if (
params.ransac_algorithmForLandmarks)
519 newSOGMode.
log_w = 0;
521 newSOGMode.
log_w = log(
static_cast<double>(subSet.size()));
523 newSOGMode.
mean = referenceEstimation.
mean;
524 newSOGMode.
cov = referenceEstimation.
cov;
527 results.transformation.push_back(newSOGMode);
531 const size_t ninliers = subSet.size();
532 if (largest_consensus_yet < ninliers)
534 largest_consensus_yet = ninliers;
537 if (use_dynamic_iter_number)
542 const double fracinliers =
544 static_cast<double>(howManyDifCorrs);
546 1 - pow(fracinliers,
static_cast<double>(
549 pNoOutliers = std::max(
550 std::numeric_limits<double>::epsilon(),
553 1.0 - std::numeric_limits<double>::epsilon(),
557 log(1 -
params.probability_find_good_model) /
560 results.ransac_iters = std::max(
564 cout <<
"[tfest::RANSAC] Iter #" << iter_idx
565 <<
":est. # iters=" <<
results.ransac_iters
566 <<
" pNoOutliers=" << pNoOutliers
567 <<
" #inliers: " << ninliers << endl;
572 if (subSet.size() >=
params.ransac_minSetSize &&
573 this_subset_RMSE < largestSubSet_RMSE)
576 cout <<
"[tfest::RANSAC] Iter #" << iter_idx
577 <<
" Better subset: " << subSet.size()
578 <<
" inliers, RMSE=" << this_subset_RMSE << endl;
580 results.largestSubSet = subSet;
581 largestSubSet_RMSE = this_subset_RMSE;
585 if (subSet.size() >=
params.ransac_minSetSize &&
586 this_subset_RMSE < MAX_RMSE_TO_END)
592 timlog.leave(
"ransac.iter");
597 cout <<
"[tfest::RANSAC] Finished after " << iter_idx
601 results.transformation.normalizeWeights();
606 printf(
"nCorrs=%u\n",
static_cast<unsigned int>(nCorrs));
607 printf(
"Saving '_debug_in_correspondences.txt'...");
608 in_correspondences.
dumpToFile(
"_debug_in_correspondences.txt");
609 printf(
"Ok\n"); printf(
"Saving '_debug_results.transformation.txt'...");
610 results.transformation.saveToTextFile(
611 "_debug_results.transformation.txt");