Matcher_Point2Plane.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  * ------------------------------------------------------------------------- */
15 #include <mrpt/core/exceptions.h>
16 #include <mrpt/core/round.h>
17 #include <mrpt/version.h>
18 
20 
21 using namespace mp2p_icp;
22 
24 {
25  mrpt::system::COutputLogger::setLoggerName("Matcher_Point2Plane");
26 }
27 
28 void Matcher_Point2Plane::initialize(const mrpt::containers::yaml& params)
29 {
31 
34  MCP_LOAD_REQ(params, knn);
36  MCP_LOAD_REQ(params, minimumPlanePoints);
37  ASSERT_GE_(minimumPlanePoints, 3UL);
38 
39  MCP_LOAD_OPT(params, localPointMustFitPlaneToo);
40  MCP_LOAD_OPT(params, localToGlobalPlaneMinAbsCosine);
41 }
42 
43 // Filter the list of neighbors by maximum distance threshold:
44 static void filterListByMaxDist(
45  std::vector<size_t>& kddIdxs, std::vector<float>& kddSqrDist,
46  const float maxDistForCorrespondenceSquared)
47 {
48  // Faster common case: all points are valid:
49  if (!kddSqrDist.empty() &&
50  kddSqrDist.back() < maxDistForCorrespondenceSquared)
51  {
52  // Nothing to do: all knn points are within the range.
53  }
54  else
55  {
56  for (size_t j = 0; j < kddSqrDist.size(); j++)
57  {
58  if (kddSqrDist[j] > maxDistForCorrespondenceSquared)
59  {
60  kddIdxs.resize(j);
61  kddSqrDist.resize(j);
62  break;
63  }
64  }
65  }
66 }
67 
69  const mrpt::maps::CMetricMap& pcGlobalMap,
70  const mrpt::maps::CPointsMap& pcLocal,
71  const mrpt::poses::CPose3D& localPose, MatchState& ms,
72  [[maybe_unused]] const layer_name_t& globalName,
73  const layer_name_t& localName, Pairings& out) const
74 {
75  MRPT_START
76 
78 
79  const mrpt::maps::NearestNeighborsCapable& nnGlobal =
80  *mp2p_icp::MapToNN(pcGlobalMap, true /*throw if cannot convert*/);
81 
82  out.potential_pairings += pcLocal.size();
83 
84  // Empty maps? Nothing to do
85  if (pcGlobalMap.isEmpty() || pcLocal.empty()) return;
86 
88  pcLocal, localPose, maxLocalPointsPerLayer_, localPointsSampleSeed_);
89 
90  // Try to do matching only if the bounding boxes have some overlap:
91  if (!pcGlobalMap.boundingBox().intersection(
92  {tl.localMin, tl.localMax},
94  return;
95 
96  // Prepare output: no correspondences initially:
97  out.paired_pt2pl.reserve(out.paired_pt2pl.size() + pcLocal.size() / 10);
98 
99  // Loop for each point in local map:
100  // --------------------------------------------------
101  const float maxDistForCorrespondenceSquared = mrpt::square(searchRadius);
102 
103  const auto& lxs = pcLocal.getPointsBufferRef_x();
104  const auto& lys = pcLocal.getPointsBufferRef_y();
105  const auto& lzs = pcLocal.getPointsBufferRef_z();
106 
107  std::vector<float> kddSqrDist, kddSqrDistLocal;
108  std::vector<size_t> kddIdxs, kddIdxsLocal;
109  std::vector<mrpt::math::TPoint3Df> kddPts, kddPtsLocal;
110  std::vector<float> kddXs, kddYs, kddZs;
111 
112  for (size_t i = 0; i < tl.x_locals.size(); i++)
113  {
114  const size_t localIdx = tl.idxs.has_value() ? (*tl.idxs)[i] : i;
115 
117  ms.localPairedBitField.point_layers.at(localName)[localIdx])
118  continue; // skip, already paired.
119 
120  // Don't discard **global** map points if already used by another
121  // matcher, since the assumption of "plane" features implies that
122  // many local points may match the *same* "global plane", so it's ok
123  // to have multiple-local-to-one-global pairings.
124 
125  // For speed-up:
126  const float lx = tl.x_locals[i], ly = tl.y_locals[i],
127  lz = tl.z_locals[i];
128 
129  // Use a KD-tree to look for the nearnest neighbor(s) of
130  // (x_local, y_local, z_local) in the global map.
131  nnGlobal.nn_multiple_search(
132  {lx, ly, lz}, // Look closest to this guy
133  knn, kddPts, kddSqrDist, kddIdxs);
134 
135  // Filter the list of neighbors by maximum distance threshold:
137  kddIdxs, kddSqrDist, maxDistForCorrespondenceSquared);
138 
139  // minimum: 3 points to be able to fit a plane
140  if (kddIdxs.size() < minimumPlanePoints) continue;
141 
142  mp2p_icp::vector_of_points_to_xyz(kddPts, kddXs, kddYs, kddZs);
143 
145  kddXs.data(), kddYs.data(), kddZs.data(), std::nullopt,
146  kddPts.size());
147 
148  // Do these points look like a plane?
149 #if 0
150  std::cout << "eig values: " << eig.eigVals[0] << " " << eig.eigVals[1]
151  << " " << eig.eigVals[2]
152  << " eigvec0: " << eig.eigVectors[0].asString() << "\n"
153  << " eigvec1: " << eig.eigVectors[1].asString() << "\n"
154  << " eigvec2: " << eig.eigVectors[2].asString() << "\n";
155 #endif
156 
157  // e0/e2 must be < planeEigenThreshold:
158  if (eig.eigVals[0] > planeEigenThreshold * eig.eigVals[2]) continue;
159 
160  const auto& normal = eig.eigVectors[0];
161  const mrpt::math::TPoint3D planeCentroid = {
162  eig.meanCov.mean.x(), eig.meanCov.mean.y(), eig.meanCov.mean.z()};
163 
164  const auto thePlane = mrpt::math::TPlane(planeCentroid, normal);
165  const double ptPlaneDist = std::abs(thePlane.distance({lx, ly, lz}));
166 
167  if (ptPlaneDist > distanceThreshold) continue; // plane is too distant
168 
169  // Next, check plane-to-plane angle:
171  {
172  pcLocal.kdTreeNClosestPoint3DIdx(
173  // Look closest to this guy
174  lxs[localIdx], lys[localIdx], lzs[localIdx],
175  // This max number of matches
176  knn, kddIdxsLocal, kddSqrDistLocal);
177 
179  kddIdxsLocal, kddSqrDistLocal, maxDistForCorrespondenceSquared);
180 
181  // minimum: 3 points to be able to fit a plane
182  if (kddIdxsLocal.size() < minimumPlanePoints) continue;
183 
185  tl.x_locals.data(), tl.y_locals.data(), tl.z_locals.data(),
186  kddIdxsLocal);
187 
188  // Do these points look like a plane?
189  // e0/e2 must be < planeEigenThreshold:
190  if (eigLocal.eigVals[0] > planeEigenThreshold * eigLocal.eigVals[2])
191  continue;
192 
193  const auto& normalLocal = eigLocal.eigVectors[0];
194 
195  const float dotProd = normalLocal.x * normal.x +
196  normalLocal.y * normal.y +
197  normalLocal.z * normal.z;
198 
199  // Angle too large?
200  if (std::abs(dotProd) < localToGlobalPlaneMinAbsCosine) continue;
201  }
202 
203  // OK, all conditions pass: add the new pairing:
204  auto& p = out.paired_pt2pl.emplace_back();
205  p.pt_local = {lxs[localIdx], lys[localIdx], lzs[localIdx]};
206  p.pl_global.centroid = planeCentroid;
207 
208  p.pl_global.plane = thePlane;
209 
210  // Mark local point as already paired:
211  ms.localPairedBitField.point_layers[localName].mark_as_set(localIdx);
212 
213  } // For each local point
214 
215  MRPT_END
216 }
mp2p_icp::Matcher_Point2Plane::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Point2Plane.cpp:28
mp2p_icp::Parameterizable::checkAllParametersAreRealized
void checkAllParametersAreRealized() const
Definition: Parameterizable.cpp:138
mp2p_icp
Definition: covariance.h:17
mp2p_icp::Matcher_Point2Plane
Definition: Matcher_Point2Plane.h:30
mp2p_icp::Matcher_Points_Base::bounding_box_intersection_check_epsilon_
double bounding_box_intersection_check_epsilon_
Definition: Matcher_Points_Base.h:63
mp2p_icp::Matcher_Point2Plane::localPointMustFitPlaneToo
bool localPointMustFitPlaneToo
Definition: Matcher_Point2Plane.h:63
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud
Definition: Matcher_Points_Base.h:90
mp2p_icp::Matcher
Definition: Matcher.h:72
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::y_locals
mrpt::aligned_std_vector< float > y_locals
Definition: Matcher_Points_Base.h:100
mp2p_icp::Pairings
Definition: Pairings.h:94
mp2p_icp::layer_name_t
std::string layer_name_t
Definition: layer_name_t.h:22
mp2p_icp::Matcher_Points_Base::allowMatchAlreadyMatchedPoints_
bool allowMatchAlreadyMatchedPoints_
Definition: Matcher_Points_Base.h:52
mp2p_icp::Matcher_Point2Plane::localToGlobalPlaneMinAbsCosine
double localToGlobalPlaneMinAbsCosine
Definition: Matcher_Point2Plane.h:64
DECLARE_PARAMETER_REQ
#define DECLARE_PARAMETER_REQ(__yaml, __variable)
Definition: Parameterizable.h:175
mp2p_icp::estimate_points_eigen
PointCloudEigen estimate_points_eigen(const float *xs, const float *ys, const float *zs, mrpt::optional_ref< const std::vector< size_t >> indices, std::optional< size_t > totalCount=std::nullopt)
Definition: estimate_points_eigen.cpp:19
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::idxs
std::optional< std::vector< std::size_t > > idxs
Definition: Matcher_Points_Base.h:97
mp2p_icp::Matcher_Points_Base::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Points_Base.cpp:120
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::z_locals
mrpt::aligned_std_vector< float > z_locals
Definition: Matcher_Points_Base.h:100
mp2p_icp::MatchState
Definition: Matcher.h:36
kitti-batch-convert.out
string out
Definition: kitti-batch-convert.py:7
mp2p_icp::Matcher_Point2Plane::minimumPlanePoints
uint32_t minimumPlanePoints
Definition: Matcher_Point2Plane.h:61
mp2p_icp::Matcher_Point2Plane::knn
uint32_t knn
Definition: Matcher_Point2Plane.h:60
mp2p_icp::Matcher_Points_Base::localPointsSampleSeed_
uint64_t localPointsSampleSeed_
Definition: Matcher_Points_Base.h:48
mp2p_icp::Matcher_Point2Plane::implMatchOneLayer
void implMatchOneLayer(const mrpt::maps::CMetricMap &pcGlobal, const mrpt::maps::CPointsMap &pcLocal, const mrpt::poses::CPose3D &localPose, MatchState &ms, const layer_name_t &globalName, const layer_name_t &localName, Pairings &out) const override
Definition: Matcher_Point2Plane.cpp:68
mp2p_icp::PointCloudEigen::eigVectors
std::array< mrpt::math::TVector3D, 3 > eigVectors
Definition: estimate_points_eigen.h:35
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(QualityEvaluator_RangeImageSimilarity, QualityEvaluator, mp2p_icp) using namespace mp2p_icp
mp2p_icp::Matcher_Point2Plane::Matcher_Point2Plane
Matcher_Point2Plane()
Definition: Matcher_Point2Plane.cpp:23
mp2p_icp::pointcloud_bitfield_t::point_layers
std::map< layer_name_t, DenseOrSparseBitField > point_layers
Definition: pointcloud_bitfield.h:82
mp2p_icp::Matcher_Point2Plane::searchRadius
double searchRadius
Definition: Matcher_Point2Plane.h:59
mp2p_icp::Matcher_Point2Plane::planeEigenThreshold
double planeEigenThreshold
Definition: Matcher_Point2Plane.h:62
mp2p_icp::vector_of_points_to_xyz
void vector_of_points_to_xyz(const std::vector< mrpt::math::TPoint3Df > &pts, std::vector< float > &xs, std::vector< float > &ys, std::vector< float > &zs)
Definition: estimate_points_eigen.cpp:116
mp2p_icp::PointCloudEigen
Output of estimate_points_eigen()
Definition: estimate_points_eigen.h:32
mp2p_icp::PointCloudEigen::meanCov
mrpt::poses::CPointPDFGaussian meanCov
Definition: estimate_points_eigen.h:34
mp2p_icp::Matcher_Points_Base::maxLocalPointsPerLayer_
uint64_t maxLocalPointsPerLayer_
Definition: Matcher_Points_Base.h:47
mp2p_icp::MatchState::localPairedBitField
pointcloud_bitfield_t localPairedBitField
Definition: Matcher.h:46
mp2p_icp::MapToNN
const mrpt::maps::NearestNeighborsCapable * MapToNN(const mrpt::maps::CMetricMap &map, bool throwIfNotImplemented)
Definition: metricmap.cpp:690
mp2p_icp::PointCloudEigen::eigVals
std::array< double, 3 > eigVals
Definition: estimate_points_eigen.h:37
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::x_locals
mrpt::aligned_std_vector< float > x_locals
Definition: Matcher_Points_Base.h:100
filterListByMaxDist
static void filterListByMaxDist(std::vector< size_t > &kddIdxs, std::vector< float > &kddSqrDist, const float maxDistForCorrespondenceSquared)
Definition: Matcher_Point2Plane.cpp:44
estimate_points_eigen.h
Calculate eigenvectors and eigenvalues from a set of points.
mp2p_icp::Matcher_Points_Base::transform_local_to_global
static TransformedLocalPointCloud transform_local_to_global(const mrpt::maps::CPointsMap &pcLocal, const mrpt::poses::CPose3D &localPose, const std::size_t maxLocalPoints=0, const uint64_t localPointsSampleSeed=0)
Definition: Matcher_Points_Base.cpp:174
Matcher_Point2Plane.h
Pointcloud matcher: point to plane-fit of nearby points.
mp2p_icp::Matcher_Point2Plane::distanceThreshold
double distanceThreshold
Definition: Matcher_Point2Plane.h:58


mp2p_icp
Author(s): Jose-Luis Blanco-Claraco
autogenerated on Tue Jul 2 2024 02:47:25