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