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]);
70 params.printAsYAML(ss);
76 [[maybe_unused]]
const mrpt::math::TPose3D& initialGuessLocalWrtGlobal,
78 [[maybe_unused]]
const std::optional<mrpt::poses::CPose3DPDFGaussianInf>& prior,
79 [[maybe_unused]]
const mrpt::optional_ref<LogRecord>& outputDebugInfo)
81 using namespace std::string_literals;
84 #if defined(MP2P_HAS_LIBPOINTMATCHER)
86 ASSERT_EQUAL_(pcLocal.layers.size(), pcGlobal.layers.size());
87 ASSERT_(!pcLocal.empty() && !pcGlobal.empty());
91 "You must call initialize_derived() first, or initialize from a YAML "
92 "file with a `derived` section with the LibPointMathcer-specific "
105 std::optional<LogRecord> currentLog;
107 const bool generateDebugRecord = outputDebugInfo.has_value() || p.generateDebugFiles;
109 if (generateDebugRecord)
111 currentLog.emplace();
112 currentLog->pcGlobal = pcGlobal.get_shared_from_this_or_clone();
113 currentLog->pcLocal = pcLocal.get_shared_from_this_or_clone();
114 currentLog->initialGuessLocalWrtGlobal = initialGuessLocalWrtGlobal;
115 currentLog->icpParameters = p;
119 ASSERT_(pcLocal.size() > 0);
120 ASSERT_(pcGlobal.size() > 0);
123 using DP = PM::DataPoints;
126 const DP ptsLocal = pointsToPM(pcLocal);
127 const DP ptsGlobal = pointsToPM(pcGlobal);
137 std::stringstream ss;
140 icp.loadFromYaml(ss);
144 ASSERT_EQUAL_(cloudDimension, 3U);
148 initialGuessLocalWrtGlobal.getHomogeneousMatrix().asEigen();
154 MRPT_LOG_WARN(
"Initial transformation is not rigid, SE(3) identity will be used");
156 PM::TransformationParameters::Identity(cloudDimension + 1, cloudDimension + 1);
159 const DP ptsLocalTf = rigidTrans.
compute(ptsLocal, initTransfo);
165 T = icp(ptsLocalTf, ptsGlobal);
170 mrpt::poses::CPose3D(mrpt::math::CMatrixDouble44(T));
174 catch (
const PM::ConvergenceError&)
181 if (!icp.transformationCheckers.empty())
182 result.nIterations = icp.transformationCheckers.at(0)->getConditionVariables()[0];
184 result.nIterations = 1;
189 result.finalPairings);
192 result.optimalScale = 1.0;
197 result.optimal_tf.cov =
204 if (currentLog) currentLog->icpResult = result;
210 if (currentLog && outputDebugInfo.has_value())
211 outputDebugInfo.value().get() = std::move(currentLog.value());
214 THROW_EXCEPTION(
"This method requires MP2P built against libpointmatcher");