Matcher_Point2Line.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_Point2Line");
26 }
27 
28 void Matcher_Point2Line::initialize(const mrpt::containers::yaml& params)
29 {
31 
32  MCP_LOAD_REQ(params, distanceThreshold);
33  MCP_LOAD_REQ(params, knn);
34  MCP_LOAD_REQ(params, lineEigenThreshold);
35  MCP_LOAD_REQ(params, minimumLinePoints);
36  ASSERT_GE_(minimumLinePoints, 2UL);
37 }
38 
40  const mrpt::maps::CMetricMap& pcGlobalMap, const mrpt::maps::CPointsMap& pcLocal,
41  const mrpt::poses::CPose3D& localPose, MatchState& ms,
42  [[maybe_unused]] const layer_name_t& globalName, const layer_name_t& localName,
43  Pairings& out) const
44 {
45  MRPT_START
46 
47  const mrpt::maps::NearestNeighborsCapable& nnGlobal =
48  *mp2p_icp::MapToNN(pcGlobalMap, true /*throw if cannot convert*/);
49 
50  out.potential_pairings += pcLocal.size();
51 
52  // Empty maps? Nothing to do
53  if (pcGlobalMap.isEmpty() || pcLocal.empty()) return;
54 
56  pcLocal, localPose, maxLocalPointsPerLayer_, localPointsSampleSeed_);
57 
58  // Try to do matching only if the bounding boxes have some overlap:
59  if (!pcGlobalMap.boundingBox().intersection(
60  {tl.localMin, tl.localMax},
62  return;
63 
64  // Prepare output: no correspondences initially:
65  out.paired_pt2pl.reserve(out.paired_pt2pl.size() + pcLocal.size() / 10);
66 
67  // Loop for each point in local map:
68  // --------------------------------------------------
69  const float maxDistForCorrespondenceSquared = mrpt::square(distanceThreshold);
70 
71  const auto& lxs = pcLocal.getPointsBufferRef_x();
72  const auto& lys = pcLocal.getPointsBufferRef_y();
73  const auto& lzs = pcLocal.getPointsBufferRef_z();
74 
75  std::vector<float> kddSqrDist;
76  std::vector<uint64_t> kddIdxs;
77  std::vector<mrpt::math::TPoint3Df> kddPts;
78  std::vector<float> kddXs, kddYs, kddZs;
79 
80  for (size_t i = 0; i < tl.x_locals.size(); i++)
81  {
82  const size_t localIdx = tl.idxs.has_value() ? (*tl.idxs)[i] : i;
83 
85  ms.localPairedBitField.point_layers.at(localName)[localIdx])
86  continue; // skip, already paired.
87 
88  // Don't discard **global** map points if already used by another
89  // matcher, since the assumption of "line" features implies that
90  // many local points may match the *same* "global line", so it's ok
91  // to have multiple-local-to-one-global pairings.
92 
93  // For speed-up:
94  const float lx = tl.x_locals[i], ly = tl.y_locals[i], lz = tl.z_locals[i];
95 
96  // Use a KD-tree to look for the nearnest neighbor(s) of
97  // (x_local, y_local, z_local) in the global map.
98  nnGlobal.nn_multiple_search(
99  {lx, ly, lz}, // Look closest to this guy
100  knn, kddPts, kddSqrDist, kddIdxs);
101 
102  // Filter the list of neighbors by maximum distance threshold:
103 
104  // Faster common case: all points are valid:
105  if (!kddSqrDist.empty() && kddSqrDist.back() < maxDistForCorrespondenceSquared)
106  {
107  // Nothing to do: all knn points are within the range.
108  }
109  else
110  {
111  for (size_t j = 0; j < kddSqrDist.size(); j++)
112  {
113  if (kddSqrDist[j] > maxDistForCorrespondenceSquared)
114  {
115  kddIdxs.resize(j);
116  kddSqrDist.resize(j);
117  break;
118  }
119  }
120  }
121 
122  // minimum: 2 points to be able to fit a line
123  if (kddIdxs.size() < minimumLinePoints) continue;
124 
125  mp2p_icp::vector_of_points_to_xyz(kddPts, kddXs, kddYs, kddZs);
126 
128  kddXs.data(), kddYs.data(), kddZs.data(), std::nullopt, kddPts.size());
129 
130  // Do these points look like a line?
131 #if 0
132  std::cout << "eig values: " << eig.eigVals[0] << " " << eig.eigVals[1]
133  << " " << eig.eigVals[2]
134  << " eigvec0: " << eig.eigVectors[0].asString() << "\n"
135  << " eigvec1: " << eig.eigVectors[1].asString() << "\n"
136  << " eigvec2: " << eig.eigVectors[2].asString() << "\n";
137 #endif
138 
139  // e0/e{1,2} must be < lineEigenThreshold:
140  if (eig.eigVals[0] > lineEigenThreshold * eig.eigVals[2]) continue;
141  if (eig.eigVals[1] > lineEigenThreshold * eig.eigVals[2]) continue;
142 
143  auto& p = out.paired_pt2ln.emplace_back();
144  p.pt_local = {lxs[localIdx], lys[localIdx], lzs[localIdx]};
145 
146  const auto& normal = eig.eigVectors[2];
147  p.ln_global.pBase = {eig.meanCov.mean.x(), eig.meanCov.mean.y(), eig.meanCov.mean.z()};
148  p.ln_global.director = normal.unitarize();
149 
150  // Mark local point as already paired:
151  ms.localPairedBitField.point_layers[localName].mark_as_set(localIdx);
152 
153  } // For each local point
154 
155  MRPT_END
156 }
mp2p_icp
Definition: covariance.h:17
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_Points_Base::TransformedLocalPointCloud
Definition: Matcher_Points_Base.h:90
mp2p_icp::Matcher
Definition: Matcher.h:73
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:76
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::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_Point2Line::distanceThreshold
double distanceThreshold
Definition: Matcher_Point2Line.h:52
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::idxs
std::optional< std::vector< std::size_t > > idxs
Definition: Matcher_Points_Base.h:97
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(FilterDecimateVoxelsQuadratic, mp2p_icp_filters::FilterBase, mp2p_icp_filters) using namespace mp2p_icp_filters
Matcher_Point2Line.h
Pointcloud matcher: point to line-fit of nearby points.
mp2p_icp::Matcher_Points_Base::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Points_Base.cpp:114
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:37
kitti-batch-convert.out
string out
Definition: kitti-batch-convert.py:7
mp2p_icp::Matcher_Point2Line::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: Matcher_Point2Line.cpp:28
mp2p_icp::Matcher_Points_Base::localPointsSampleSeed_
uint64_t localPointsSampleSeed_
Definition: Matcher_Points_Base.h:48
mp2p_icp::Matcher_Point2Line::Matcher_Point2Line
Matcher_Point2Line()
Definition: Matcher_Point2Line.cpp:23
mp2p_icp::PointCloudEigen::eigVectors
std::array< mrpt::math::TVector3D, 3 > eigVectors
Definition: estimate_points_eigen.h:35
mp2p_icp::Matcher_Point2Line::knn
uint32_t knn
Definition: Matcher_Point2Line.h:53
mp2p_icp::pointcloud_bitfield_t::point_layers
std::map< layer_name_t, DenseOrSparseBitField > point_layers
Definition: pointcloud_bitfield.h:82
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:117
mp2p_icp::Matcher_Point2Line::lineEigenThreshold
double lineEigenThreshold
Definition: Matcher_Point2Line.h:55
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:47
mp2p_icp::MapToNN
const mrpt::maps::NearestNeighborsCapable * MapToNN(const mrpt::maps::CMetricMap &map, bool throwIfNotImplemented)
Definition: metricmap.cpp:658
mp2p_icp::Matcher_Point2Line::minimumLinePoints
uint32_t minimumLinePoints
Definition: Matcher_Point2Line.h:54
mp2p_icp::PointCloudEigen::eigVals
std::array< double, 3 > eigVals
sorted in ascending order
Definition: estimate_points_eigen.h:36
mp2p_icp::Matcher_Point2Line::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_Point2Line.cpp:39
mp2p_icp::Matcher_Points_Base::TransformedLocalPointCloud::x_locals
mrpt::aligned_std_vector< float > x_locals
Definition: Matcher_Points_Base.h:100
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:163
mp2p_icp::Matcher_Point2Line
Definition: Matcher_Point2Line.h:30


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