mp2p_icp/src/ICP.cpp
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  * A repertory of multi primitive-to-primitive (MP2P) ICP algorithms in C++
3  * Copyright (C) 2018-2024 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
13 #include <mp2p_icp/ICP.h>
14 #include <mp2p_icp/covariance.h>
15 #include <mrpt/core/exceptions.h>
16 #include <mrpt/core/lock_helper.h>
17 #include <mrpt/poses/Lie/SE.h>
18 #include <mrpt/system/filesystem.h>
19 #include <mrpt/tfest/se3.h>
20 
21 #include <regex>
22 
23 IMPLEMENTS_MRPT_OBJECT(ICP, mrpt::rtti::CObject, mp2p_icp)
24 
25 using namespace mp2p_icp;
26 
28  const metric_map_t& pcLocal, const metric_map_t& pcGlobal,
29  const mrpt::math::TPose3D& initialGuessLocalWrtGlobal, const Parameters& p, Results& result,
30  const std::optional<mrpt::poses::CPose3DPDFGaussianInf>& prior,
31  const mrpt::optional_ref<LogRecord>& outputDebugInfo)
32 {
33  using namespace std::string_literals;
34 
35  MRPT_START
36 
37  mrpt::system::CTimeLoggerEntry tle(profiler_, "align");
38 
39  // ----------------------------
40  // Initial sanity checks
41  // ----------------------------
42  ASSERT_(!matchers_.empty());
43  ASSERT_(!solvers_.empty());
44  ASSERT_(!quality_evaluators_.empty());
45 
46  ASSERT_(!pcGlobal.empty());
47  ASSERT_(!pcLocal.empty());
48 
49  // ----------------------------
50  // Preparation
51  // ----------------------------
52  mrpt::system::CTimeLoggerEntry tle1(profiler_, "align.1_prepare");
53  // Reset output:
54  result = Results();
55 
56  // Prepare output debug records:
57  std::optional<LogRecord> currentLog;
58 
59  const bool generateDebugRecord = outputDebugInfo.has_value() || p.generateDebugFiles;
60 
61  if (generateDebugRecord)
62  {
63  currentLog.emplace();
64  currentLog->pcGlobal = pcGlobal.get_shared_from_this_or_clone();
65  currentLog->pcLocal = pcLocal.get_shared_from_this_or_clone();
66  currentLog->initialGuessLocalWrtGlobal = initialGuessLocalWrtGlobal;
67  currentLog->icpParameters = p;
68  }
69 
70  tle1.stop();
71 
72  // ------------------------------------------------------
73  // Add our own parameters to the user's one, or just
74  // define a new one if none is provided.
75  // ------------------------------------------------------
76  std::set<ParameterSource*> activeParamSouces;
77 
78  auto lambdaAddOwnParams = [&](Parameterizable& obj)
79  {
80  ParameterSource* ps = obj.attachedSource();
81  if (!ps)
82  {
83  obj.attachToParameterSource(ownParamSource_);
84  ps = &ownParamSource_;
85  }
86  ps->updateVariable("ICP_ITERATION", result.nIterations);
87  activeParamSouces.insert(ps);
88  };
89  auto lambdaRealizeParamSources = [&]()
90  {
91  for (auto& ps : activeParamSouces) ps->realize();
92  };
93 
94  // ------------------------------------------------------
95  // Main ICP loop
96  // ------------------------------------------------------
97  mrpt::system::CTimeLoggerEntry tle2(profiler_, "align.2_create_state");
98 
99  ICP_State state(pcGlobal, pcLocal);
100  if (currentLog) state.log = &currentLog.value();
101 
102  tle2.stop();
103 
104  const auto initGuess = mrpt::poses::CPose3D(initialGuessLocalWrtGlobal);
105 
106  state.currentSolution.optimalPose = initGuess;
107 
108  mrpt::poses::CPose3D prev_solution = state.currentSolution.optimalPose;
109  std::optional<mrpt::poses::CPose3D> prev2_solution; // 2 steps ago
110  std::optional<mrpt::poses::CPose3D> lastCorrection;
111  SolverContext sc;
112  sc.prior = prior;
113 
114  for (result.nIterations = 0; result.nIterations < p.maxIterations; result.nIterations++)
115  {
116  mrpt::system::CTimeLoggerEntry tle3(profiler_, "align.3_iter");
117 
118  // Update iteration count, both in direct C++ structure...
119  state.currentIteration = result.nIterations;
120 
121  // ...and via programmable formulas:
122  for (auto& obj : matchers_) lambdaAddOwnParams(*obj);
123  for (auto& obj : solvers_) lambdaAddOwnParams(*obj);
124  for (auto& [obj, _] : quality_evaluators_) lambdaAddOwnParams(*obj);
125  lambdaRealizeParamSources();
126 
127  // Matchings
128  // ---------------------------------------
129  MatchContext mc;
130  mc.icpIteration = state.currentIteration;
131 
132  mrpt::system::CTimeLoggerEntry tle4(profiler_, "align.3.1_matchers");
133 
135  matchers_, state.pcGlobal, state.pcLocal, state.currentSolution.optimalPose, mc);
136 
137  tle4.stop();
138 
139  if (state.currentPairings.empty())
140  {
143  {
144  printf(
145  "[ICP] Iter=%3u No pairings!\n",
146  static_cast<unsigned int>(state.currentIteration));
147  }
148  break;
149  }
150 
151  // Optimal relative pose:
152  // ---------------------------------------
153  mrpt::system::CTimeLoggerEntry tle5(profiler_, "align.3.2_solvers");
154 
155  sc.icpIteration = state.currentIteration;
158  sc.lastIcpStepIncrement = lastCorrection;
159 
160  // Compute the optimal pose:
161  const bool solvedOk =
163 
164  tle5.stop();
165 
166  if (!solvedOk)
167  {
170  {
171  printf(
172  "[ICP] Iter=%3u Solver returned false\n",
173  static_cast<unsigned int>(state.currentIteration));
174  }
175  break;
176  }
177 
178  // Updated solution is already in "state.currentSolution".
179  mrpt::system::CTimeLoggerEntry tle6(profiler_, "align.3.3_end_criterions");
180 
181  // Termination criterion: small delta:
182  auto lambdaCalcIncrs =
183  [](const mrpt::poses::CPose3D& deltaSol) -> std::tuple<double, double>
184  {
185  const mrpt::math::CVectorFixed<double, 6> dSol = mrpt::poses::Lie::SE<3>::log(deltaSol);
186  const double delta_xyz = dSol.blockCopy<3, 1>(0, 0).norm();
187  const double delta_rot = dSol.blockCopy<3, 1>(3, 0).norm();
188  return {delta_xyz, delta_rot};
189  };
190 
191  // Keep the minimum step between the current increment, and the
192  // increment from current solution to two timesteps ago. This is to
193  // detect bistable, oscillating solutions.
194  const auto deltaSol = state.currentSolution.optimalPose - prev_solution;
195  lastCorrection = deltaSol; // save for the next solver context
196 
197  auto [delta_xyz, delta_rot] = lambdaCalcIncrs(deltaSol);
198 
199  if (prev2_solution.has_value())
200  {
201  auto [delta_xyz2, delta_rot2] =
202  lambdaCalcIncrs(state.currentSolution.optimalPose - *prev2_solution);
203 
204  mrpt::keep_min(delta_xyz, delta_xyz2);
205  mrpt::keep_min(delta_rot, delta_rot2);
206  }
207 
209  {
210  printf(
211  "[ICP] Iter=%3u Δt=%9.02e, ΔR=%6.03f deg, "
212  "(xyzypr)=%s pairs=%s\n",
213  static_cast<unsigned int>(state.currentIteration), std::abs(delta_xyz),
214  mrpt::RAD2DEG(std::abs(delta_rot)),
215  state.currentSolution.optimalPose.asString().c_str(),
216  state.currentPairings.contents_summary().c_str());
217  }
218 
219  const bool stalled =
220  (std::abs(delta_xyz) < p.minAbsStep_trans && std::abs(delta_rot) < p.minAbsStep_rot);
221 
222  // store partial solutions for logging/debuging?
223  if (p.saveIterationDetails &&
224  (p.decimationIterationDetails == 0 ||
225  state.currentIteration % p.decimationIterationDetails == 0 || stalled))
226  {
227  if (!currentLog->iterationsDetails.has_value()) currentLog->iterationsDetails.emplace();
228 
229  auto& id = currentLog->iterationsDetails.value()[state.currentIteration];
230  id.optimalPose = state.currentSolution.optimalPose;
231  id.pairings = state.currentPairings;
232  }
233 
234  // End criteria?
235  if (stalled)
236  {
238 
240  {
241  printf(
242  "[ICP] Iter=%3u Solver stalled.\n",
243  static_cast<unsigned int>(state.currentIteration));
244  }
245 
246  break;
247  }
248 
249  // Quality checkpoints to abort ICP iterations as useless?
250  if (auto itQ = p.quality_checkpoints.find(state.currentIteration);
251  itQ != p.quality_checkpoints.end())
252  {
253  const double minQuality = itQ->second;
254 
255  for (auto& e : quality_evaluators_) lambdaAddOwnParams(*e.obj);
256  lambdaRealizeParamSources();
257 
258  const double quality = evaluate_quality(
259  quality_evaluators_, pcGlobal, pcLocal, state.currentSolution.optimalPose,
260  state.currentPairings);
261 
262  if (quality < minQuality)
263  {
266  {
267  printf(
268  "[ICP] Iter=%3u quality checkpoint did not pass: %f < "
269  "%f\n",
270  static_cast<unsigned int>(state.currentIteration), quality, minQuality);
271  }
272  break; // abort ICP
273  }
274  }
275 
276  // Process user hooks:
277  if (iteration_hook_)
278  {
281  hi.currentPairings = &state.currentPairings;
282  hi.currentSolution = &state.currentSolution;
283  hi.pcGlobal = &state.pcGlobal;
284  hi.pcLocal = &state.pcLocal;
285 
286  const auto ho = iteration_hook_(hi);
287 
288  if (ho.request_stop)
289  {
290  // abort ICP
292  break;
293  }
294  }
295 
296  // roll values back:
297  prev2_solution = prev_solution;
298  prev_solution = state.currentSolution.optimalPose;
299  }
300 
301  // ----------------------------
302  // Fill in "result"
303  // ----------------------------
304  if (result.nIterations >= p.maxIterations)
306 
307  // Quality:
308  mrpt::system::CTimeLoggerEntry tle7(profiler_, "align.4_quality");
309 
310  for (auto& e : quality_evaluators_) lambdaAddOwnParams(*e.obj);
311  lambdaRealizeParamSources();
312 
313  result.quality = evaluate_quality(
314  quality_evaluators_, pcGlobal, pcLocal, state.currentSolution.optimalPose,
315  state.currentPairings);
316 
317  tle7.stop();
318 
319  // Store output:
320  result.optimal_tf.mean = state.currentSolution.optimalPose;
322  result.finalPairings = std::move(state.currentPairings);
323 
324  // Covariance:
326 
327  result.optimal_tf.cov =
328  mp2p_icp::covariance(result.finalPairings, result.optimal_tf.mean, covParams);
329 
330  // ----------------------------
331  // Log records
332  // ----------------------------
333  mrpt::system::CTimeLoggerEntry tle8(profiler_, "align.5_save_log");
334 
335  if (currentLog)
336  {
337  // Store results into log struct:
338  currentLog->icpResult = result;
339 
340  // Store dynamic variables:
341  if (!matchers().empty())
342  {
343  currentLog->dynamicVariables =
344  matchers().begin()->get()->attachedSource()->getVariableValues();
345  }
346 
347  currentLog->icpResult = result;
348 
349  // Save log to disk (if enabled), applying filters beforehand:
351  {
352  auto pc = mp2p_icp::metric_map_t::Create();
353  *pc = *currentLog->pcLocal;
355  currentLog->pcLocal = pc;
356  }
358  {
359  auto pc = mp2p_icp::metric_map_t::Create();
360  *pc = *currentLog->pcGlobal;
362  currentLog->pcGlobal = pc;
363  }
364 
365  save_log_file(*currentLog, p);
366 
367  // return log info:
368  if (outputDebugInfo.has_value())
369  outputDebugInfo.value().get() = std::move(currentLog.value());
370  }
371 
372  MRPT_END
373 }
374 
375 void ICP::save_log_file(const LogRecord& log, const Parameters& p)
376 {
377  using namespace std::string_literals;
378 
379  if (!p.generateDebugFiles) return;
380 
381  // global log file record counter:
382  static unsigned int logFileCounter = 0;
383  static std::mutex counterMtx;
384  unsigned int RECORD_UNIQUE_ID;
385  {
386  auto lck = mrpt::lockHelper(counterMtx);
387 
388  RECORD_UNIQUE_ID = logFileCounter++;
389 
390  if (p.decimationDebugFiles > 1 && (RECORD_UNIQUE_ID % p.decimationDebugFiles) != 0)
391  return; // skip due to decimation
392  }
393 
395 
396  {
397  const std::string expr = "\\$UNIQUE_ID";
398  const auto value = mrpt::format("%05u", RECORD_UNIQUE_ID);
399  filename = std::regex_replace(filename, std::regex(expr), value);
400  }
401 
402  {
403  const std::string expr = "\\$GLOBAL_ID";
404  const auto value = mrpt::format(
405  "%05u",
406  static_cast<unsigned int>(
407  (log.pcGlobal && log.pcGlobal->id.has_value()) ? log.pcGlobal->id.value() : 0));
408  filename = std::regex_replace(filename, std::regex(expr), value);
409  }
410 
411  {
412  const std::string expr = "\\$GLOBAL_LABEL";
413  const auto value =
414  (log.pcGlobal && log.pcGlobal->label.has_value()) ? log.pcGlobal->label.value() : ""s;
415  filename = std::regex_replace(filename, std::regex(expr), value);
416  }
417  {
418  const std::string expr = "\\$LOCAL_ID";
419  const auto value = mrpt::format(
420  "%05u",
421  static_cast<unsigned int>(
422  (log.pcLocal && log.pcLocal->id.has_value()) ? log.pcLocal->id.value() : 0));
423  filename = std::regex_replace(filename, std::regex(expr), value);
424  }
425 
426  {
427  const std::string expr = "\\$LOCAL_LABEL";
428  const auto value =
429  (log.pcLocal && log.pcLocal->label.has_value()) ? log.pcLocal->label.value() : ""s;
430  filename = std::regex_replace(filename, std::regex(expr), value);
431  }
432 
433  // make sure directory exist:
434  const auto baseDir = mrpt::system::extractFileDirectory(filename);
435  if (!mrpt::system::directoryExists(baseDir))
436  {
437  const bool ok = mrpt::system::createDirectory(baseDir);
438  if (!ok)
439  {
440  std::cerr << "[ICP::save_log_file] Could not create directory to "
441  "save icp log file: '"
442  << baseDir << "'" << std::endl;
443  }
444  else
445  {
446  std::cerr << "[ICP::save_log_file] Created output directory for logs: '" << baseDir
447  << "'" << std::endl;
448  }
449  }
450 
451  // Save it:
452  const bool saveOk = log.save_to_file(filename);
453  if (!saveOk)
454  {
455  std::cerr << "[ICP::save_log_file] Could not save icp log file to '" << filename << "'"
456  << std::endl;
457  }
458 }
459 
461  const solver_list_t& solvers, const Pairings& pairings, OptimalTF_Result& out,
462  const SolverContext& sc)
463 {
464  for (const auto& solver : solvers)
465  {
466  ASSERT_(solver);
467  if (solver->optimal_pose(pairings, out, sc)) return true;
468  }
469  return false;
470 }
471 
472 void ICP::initialize_solvers(const mrpt::containers::yaml& params)
473 {
474  initialize_solvers(params, solvers_);
475 }
476 
477 void ICP::initialize_solvers(const mrpt::containers::yaml& params, ICP::solver_list_t& lst)
478 {
479  lst.clear();
480 
481  ASSERT_(params.isSequence());
482  for (const auto& entry : params.asSequence())
483  {
484  const auto& e = entry.asMap();
485  // disabled?
486  if (e.count("enabled") && e.at("enabled").as<bool>() == false) continue;
487 
488  const auto sClass = e.at("class").as<std::string>();
489  auto o = mrpt::rtti::classFactory(sClass);
490  ASSERT_(o);
491 
492  auto m = std::dynamic_pointer_cast<Solver>(o);
493  ASSERTMSG_(
494  m, mrpt::format("`%s` class seems not to be derived from Solver", sClass.c_str()));
495 
496  m->initialize(e.at("params"));
497  lst.push_back(m);
498  }
499 }
500 
501 void ICP::initialize_matchers(const mrpt::containers::yaml& params)
502 {
504 }
505 
506 void ICP::initialize_matchers(const mrpt::containers::yaml& params, matcher_list_t& lst)
507 {
508  lst.clear();
509 
510  ASSERT_(params.isSequence());
511  for (const auto& entry : params.asSequence())
512  {
513  const auto& e = entry.asMap();
514  // disabled?
515  if (e.count("enabled") && e.at("enabled").as<bool>() == false) continue;
516 
517  const auto sClass = e.at("class").as<std::string>();
518  auto o = mrpt::rtti::classFactory(sClass);
519  ASSERT_(o);
520 
521  auto m = std::dynamic_pointer_cast<Matcher>(o);
522  ASSERTMSG_(
523  m, mrpt::format("`%s` class seems not to be derived from Matcher", sClass.c_str()));
524 
525  m->initialize(e.at("params"));
526  lst.push_back(m);
527  }
528 }
529 
531  const mrpt::containers::yaml& params, ICP::quality_eval_list_t& lst)
532 {
533  lst.clear();
534 
535  ASSERT_(params.isSequence());
536  const auto numEntries = params.asSequence().size();
537 
538  for (const auto& entry : params.asSequence())
539  {
540  const auto& e = entry.asMap();
541  // disabled?
542  if (e.count("enabled") && e.at("enabled").as<bool>() == false) continue;
543 
544  const auto sClass = e.at("class").as<std::string>();
545  auto o = mrpt::rtti::classFactory(sClass);
546  ASSERT_(o);
547 
548  auto m = std::dynamic_pointer_cast<QualityEvaluator>(o);
549  ASSERTMSG_(
550  m, mrpt::format(
551  "`%s` class seems not to be derived from QualityEvaluator", sClass.c_str()));
552 
553  m->initialize(e.at("params"));
554 
555  double weight = 1.0;
556  if (numEntries > 0 && e.count("weight") > 0) weight = e.at("weight").as<double>();
557  lst.emplace_back(m, weight);
558  }
559 }
560 
561 void ICP::initialize_quality_evaluators(const mrpt::containers::yaml& params)
562 {
564 }
565 
567  const quality_eval_list_t& evaluators, const metric_map_t& pcGlobal,
568  const metric_map_t& pcLocal, const mrpt::poses::CPose3D& localPose,
569  const Pairings& finalPairings)
570 {
571  ASSERT_(!evaluators.empty());
572 
573  double sumW = .0, sumEvals = .0;
574  for (const auto& e : evaluators)
575  {
576  const double w = e.relativeWeight;
577  ASSERT_GT_(w, 0);
578  const auto evalResult = e.obj->evaluate(pcGlobal, pcLocal, localPose, finalPairings);
579 
580  if (evalResult.hard_discard) return 0; // hard limit
581 
582  sumEvals += w * evalResult.quality;
583  sumW += w;
584  }
585  ASSERT_(sumW > 0);
586 
587  return sumEvals / sumW;
588 }
mp2p_icp::ICP::ICP_State::log
LogRecord * log
Definition: ICP.h:244
mp2p_icp::Results::terminationReason
IterTermReason terminationReason
Definition: Results.h:33
mp2p_icp::Parameters::functor_before_logging_local
std::function< void(mp2p_icp::metric_map_t &)> functor_before_logging_local
Definition: Parameters.h:85
mp2p_icp::OptimalTF_Result::optimalPose
mrpt::poses::CPose3D optimalPose
Definition: OptimalTF_Result.h:26
mp2p_icp::ICP::quality_eval_list_t
std::vector< QualityEvaluatorEntry > quality_eval_list_t
Definition: ICP.h:144
mp2p_icp::Pairings::contents_summary
virtual std::string contents_summary() const
Definition: Pairings.cpp:151
mp2p_icp::IterTermReason::Stalled
@ Stalled
ICP.h
Generic ICP algorithm container.
mp2p_icp
Definition: covariance.h:17
mp2p_icp::metric_map_t::empty
virtual bool empty() const
Definition: metricmap.cpp:364
mp2p_icp::ICP::IterationHook_Input::pcGlobal
const metric_map_t * pcGlobal
Definition: ICP.h:201
mp2p_icp::ICP::IterationHook_Input::pcLocal
const metric_map_t * pcLocal
Definition: ICP.h:202
mp2p_icp::Parameters::saveIterationDetails
bool saveIterationDetails
Definition: Parameters.h:64
mp2p_icp::ParameterSource
Definition: Parameterizable.h:42
mp2p_icp::ICP::profiler_
mrpt::system::CTimeLogger profiler_
Definition: ICP.h:228
mp2p_icp::ICP::evaluate_quality
static double evaluate_quality(const quality_eval_list_t &evaluators, const metric_map_t &pcGlobal, const metric_map_t &pcLocal, const mrpt::poses::CPose3D &localPose, const Pairings &finalPairings)
Definition: mp2p_icp/src/ICP.cpp:566
mp2p_icp::Parameters::minAbsStep_trans
double minAbsStep_trans
Definition: Parameters.h:39
mp2p_icp::ICP::IterationHook_Input::currentIteration
uint32_t currentIteration
Definition: ICP.h:205
s
XmlRpcServer s
mp2p_icp::ICP::IterationHook_Input::currentPairings
const Pairings * currentPairings
Definition: ICP.h:203
mp2p_icp::CovarianceParameters
Definition: covariance.h:19
mp2p_icp::metric_map_t::get_shared_from_this_or_clone
Ptr get_shared_from_this_or_clone()
Definition: metricmap.cpp:580
mp2p_icp::Parameters::functor_before_logging_global
std::function< void(mp2p_icp::metric_map_t &)> functor_before_logging_global
Definition: Parameters.h:86
mp2p_icp::Pairings
Definition: Pairings.h:76
mp2p_icp::ICP::ownParamSource_
ParameterSource ownParamSource_
Definition: ICP.h:248
mp2p_icp::Pairings::empty
virtual bool empty() const
Definition: Pairings.h:109
mp2p_icp::ICP::quality_evaluators_
quality_eval_list_t quality_evaluators_
Definition: ICP.h:224
mp2p_icp::OptimalTF_Result::optimalScale
double optimalScale
Definition: OptimalTF_Result.h:27
mp2p_icp::LogRecord
Definition: LogRecord.h:30
mp2p_icp::SolverContext
Definition: Solver.h:36
mp2p_icp::Results::optimal_tf
mrpt::poses::CPose3DPDFGaussian optimal_tf
Definition: Results.h:25
mp2p_icp::ICP::ICP_State::currentSolution
OptimalTF_Result currentSolution
Definition: ICP.h:242
mp2p_icp::OptimalTF_Result
Definition: OptimalTF_Result.h:24
mp2p_icp::Parameters::generateDebugFiles
bool generateDebugFiles
Definition: Parameters.h:58
mp2p_icp::ICP::solvers_
solver_list_t solvers_
Definition: ICP.h:222
ok
ROSCPP_DECL bool ok()
mp2p_icp::Results::finalPairings
Pairings finalPairings
Definition: Results.h:41
mp2p_icp::ICP::initialize_solvers
void initialize_solvers(const mrpt::containers::yaml &params)
Definition: mp2p_icp/src/ICP.cpp:472
mp2p_icp::SolverContext::guessRelativePose
std::optional< mrpt::poses::CPose3D > guessRelativePose
Definition: Solver.h:40
mp2p_icp::Parameters::debugFileNameFormat
std::string debugFileNameFormat
Definition: Parameters.h:78
mp2p_icp::ICP::ICP_State::pcGlobal
const metric_map_t & pcGlobal
Definition: ICP.h:239
testing::internal::string
::std::string string
Definition: gtest.h:1979
mp2p_icp::ICP::solver_list_t
std::vector< mp2p_icp::Solver::Ptr > solver_list_t
Definition: ICP.h:68
mp2p_icp::Results::nIterations
size_t nIterations
Definition: Results.h:31
mp2p_icp::ICP::IterationHook_Input::currentSolution
const OptimalTF_Result * currentSolution
Definition: ICP.h:204
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(FilterDecimateVoxelsQuadratic, mp2p_icp_filters::FilterBase, mp2p_icp_filters) using namespace mp2p_icp_filters
mp2p_icp::ICP
Definition: ICP.h:51
mp2p_icp::IterTermReason::MaxIterations
@ MaxIterations
mp2p_icp::LogRecord::save_to_file
bool save_to_file(const std::string &fileName) const
Definition: LogRecord.cpp:79
mp2p_icp::Parameters::maxIterations
uint32_t maxIterations
Definition: Parameters.h:34
mp2p_icp::covariance
mrpt::math::CMatrixDouble66 covariance(const Pairings &finalPairings, const mrpt::poses::CPose3D &finalAlignSolution, const CovarianceParameters &p)
Definition: covariance.cpp:22
mp2p_icp::Results::optimalScale
double optimalScale
Definition: Results.h:28
mp2p_icp::IterTermReason::HookRequest
@ HookRequest
mp2p_icp::SolverContext::icpIteration
std::optional< uint32_t > icpIteration
Definition: Solver.h:54
kitti-batch-convert.out
string out
Definition: kitti-batch-convert.py:7
mp2p_icp::SolverContext::lastIcpStepIncrement
std::optional< mrpt::poses::CPose3D > lastIcpStepIncrement
Definition: Solver.h:42
mp2p_icp::Parameters::decimationDebugFiles
uint32_t decimationDebugFiles
Definition: Parameters.h:75
mp2p_icp::ICP::solvers
const solver_list_t & solvers() const
Definition: ICP.h:93
mp2p_icp::ParameterSource::updateVariable
void updateVariable(const std::string &variable, double value)
Definition: Parameterizable.h:51
mp2p_icp::ICP::initialize_matchers
void initialize_matchers(const mrpt::containers::yaml &params)
Definition: mp2p_icp/src/ICP.cpp:501
mp2p_icp::Parameterizable
Definition: Parameterizable.h:77
mp2p_icp::MatchContext
Definition: Matcher.h:29
mp2p_icp::SolverContext::prior
std::optional< mrpt::poses::CPose3DPDFGaussianInf > prior
Definition: Solver.h:49
mp2p_icp::ICP::ICP_State
Definition: ICP.h:232
mp2p_icp::ICP::matchers
const matcher_list_t & matchers() const
Definition: ICP.h:126
mp2p_icp::Parameters::decimationIterationDetails
uint32_t decimationIterationDetails
Definition: Parameters.h:70
mp2p_icp::Parameters::minAbsStep_rot
double minAbsStep_rot
Definition: Parameters.h:44
covariance.h
Covariance estimation methods for ICP results.
mp2p_icp::ICP::align
virtual void align(const metric_map_t &pcLocal, const metric_map_t &pcGlobal, const mrpt::math::TPose3D &initialGuessLocalWrtGlobal, const Parameters &p, Results &result, const std::optional< mrpt::poses::CPose3DPDFGaussianInf > &prior=std::nullopt, const mrpt::optional_ref< LogRecord > &outputDebugInfo=std::nullopt)
Definition: mp2p_icp/src/ICP.cpp:27
mp2p_icp::Parameters::quality_checkpoints
std::map< uint32_t, double > quality_checkpoints
Definition: Parameters.h:92
mp2p_icp::LogRecord::pcGlobal
metric_map_t::ConstPtr pcGlobal
Definition: LogRecord.h:42
mp2p_icp::IterTermReason::SolverError
@ SolverError
mp2p_icp::IterTermReason::NoPairings
@ NoPairings
mp2p_icp::run_matchers
Pairings run_matchers(const matcher_list_t &matchers, const metric_map_t &pcGlobal, const metric_map_t &pcLocal, const mrpt::poses::CPose3D &local_wrt_global, const MatchContext &mc, const mrpt::optional_ref< MatchState > &userProvidedMS=std::nullopt)
Definition: mp2p_icp/src/Matcher.cpp:38
mp2p_icp::ICP::ICP_State::currentPairings
Pairings currentPairings
Definition: ICP.h:241
mp2p_icp::metric_map_t
Generic container of pointcloud(s), extracted features and other maps.
Definition: metricmap.h:55
mp2p_icp::Parameters::debugPrintIterationProgress
bool debugPrintIterationProgress
Definition: Parameters.h:88
mp2p_icp::ICP::iteration_hook_
iteration_hook_t iteration_hook_
Definition: ICP.h:226
mp2p_icp::IterTermReason::QualityCheckpointFailed
@ QualityCheckpointFailed
mp2p_icp::LogRecord::pcLocal
metric_map_t::ConstPtr pcLocal
Definition: LogRecord.h:42
mp2p_icp::Results
Definition: Results.h:21
mp2p_icp::ICP::run_solvers
static bool run_solvers(const solver_list_t &solvers, const Pairings &pairings, OptimalTF_Result &out, const SolverContext &sc={})
Definition: mp2p_icp/src/ICP.cpp:460
mp2p_icp::Parameters
Definition: Parameters.h:26
mp2p_icp::ICP::ICP_State::pcLocal
const metric_map_t & pcLocal
Definition: ICP.h:240
mp2p_icp::ICP::IterationHook_Input
Definition: ICP.h:197
mp2p_icp::SolverContext::currentCorrectionFromInitialGuess
std::optional< mrpt::poses::CPose3D > currentCorrectionFromInitialGuess
Definition: Solver.h:41
mp2p_icp::ICP::initialize_quality_evaluators
void initialize_quality_evaluators(const mrpt::containers::yaml &params)
Definition: mp2p_icp/src/ICP.cpp:561
mp2p_icp::matcher_list_t
std::vector< mp2p_icp::Matcher::Ptr > matcher_list_t
Definition: Matcher.h:108
mp2p_icp::ICP::ICP_State::currentIteration
uint32_t currentIteration
Definition: ICP.h:243
kitti-batch-convert.filename
filename
Definition: kitti-batch-convert.py:6
mp2p_icp::ICP::save_log_file
static void save_log_file(const LogRecord &log, const Parameters &p)
Definition: mp2p_icp/src/ICP.cpp:375
mp2p_icp::ICP::matchers_
matcher_list_t matchers_
Definition: ICP.h:223
mp2p_icp::Results::quality
double quality
Definition: Results.h:38
mp2p_icp::MatchContext::icpIteration
uint32_t icpIteration
The ICP iteration number we are in:
Definition: Matcher.h:34


mp2p_icp
Author(s):
autogenerated on Mon May 26 2025 02:45:49