16 #include <mrpt/core/exceptions.h>
17 #include <mrpt/maps/CPointsMap.h>
18 #include <mrpt/poses/Lie/SE.h>
19 #include <mrpt/tfest/se3.h>
24 #if defined(MP2P_HAS_LIBPOINTMATCHER)
37 #if defined(MP2P_HAS_LIBPOINTMATCHER)
44 #if defined(MP2P_HAS_LIBPOINTMATCHER)
50 for (
const auto& ly : pc.
layers)
56 const auto xs = pts->getPointsBufferRef_x();
57 const auto ys = pts->getPointsBufferRef_y();
58 const auto zs = pts->getPointsBufferRef_z();
59 for (
size_t i = 0; i < xs.size(); i++)
60 ss << mrpt::format(
"%f %f %f\n", xs[i], ys[i], zs[i]);
68 const mrpt::containers::yaml& params)
71 params.printAsYAML(ss);
78 [[maybe_unused]]
const mrpt::math::TPose3D& initialGuessLocalWrtGlobal,
80 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3DPDFGaussianInf>&
82 [[maybe_unused]]
const mrpt::optional_ref<LogRecord>& outputDebugInfo)
84 using namespace std::string_literals;
87 #if defined(MP2P_HAS_LIBPOINTMATCHER)
89 ASSERT_EQUAL_(pcLocal.layers.size(), pcGlobal.layers.size());
90 ASSERT_(!pcLocal.empty() && !pcGlobal.empty());
94 "You must call initialize_derived() first, or initialize from a YAML "
95 "file with a `derived` section with the LibPointMathcer-specific "
102 mrpt::poses::CPose3D(initialGuessLocalWrtGlobal);
109 std::optional<LogRecord> currentLog;
111 const bool generateDebugRecord =
112 outputDebugInfo.has_value() || p.generateDebugFiles;
114 if (generateDebugRecord)
116 currentLog.emplace();
117 currentLog->pcGlobal = pcGlobal.get_shared_from_this_or_clone();
118 currentLog->pcLocal = pcLocal.get_shared_from_this_or_clone();
119 currentLog->initialGuessLocalWrtGlobal = initialGuessLocalWrtGlobal;
120 currentLog->icpParameters = p;
124 ASSERT_(pcLocal.size() > 0);
125 ASSERT_(pcGlobal.size() > 0);
128 using DP = PM::DataPoints;
131 const DP ptsLocal = pointsToPM(pcLocal);
132 const DP ptsGlobal = pointsToPM(pcGlobal);
142 std::stringstream ss;
145 icp.loadFromYaml(ss);
149 ASSERT_EQUAL_(cloudDimension, 3U);
153 initialGuessLocalWrtGlobal.getHomogeneousMatrix().asEigen();
160 "Initial transformation is not rigid, SE(3) identity will be used");
161 initTransfo = PM::TransformationParameters::Identity(
162 cloudDimension + 1, cloudDimension + 1);
165 const DP ptsLocalTf = rigidTrans.
compute(ptsLocal, initTransfo);
171 T = icp(ptsLocalTf, ptsGlobal);
176 mrpt::poses::CPose3D(initialGuessLocalWrtGlobal) +
177 mrpt::poses::CPose3D(mrpt::math::CMatrixDouble44(T));
181 catch (
const PM::ConvergenceError&)
188 if (!icp.transformationCheckers.empty())
190 icp.transformationCheckers.at(0)->getConditionVariables()[0];
192 result.nIterations = 1;
200 result.optimalScale = 1.0;
206 result.finalPairings, result.optimal_tf.mean, covParams);
212 if (currentLog) currentLog->icpResult = result;
218 if (currentLog && outputDebugInfo.has_value())
219 outputDebugInfo.value().get() = std::move(currentLog.value());
222 THROW_EXCEPTION(
"This method requires MP2P built against libpointmatcher");