FilterEdgesPlanes.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-2021 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
14 #include <mrpt/containers/yaml.h>
15 #include <mrpt/maps/CSimplePointsMap.h>
16 #include <mrpt/math/ops_containers.h> // dotProduct
17 #include <mrpt/obs/CObservation2DRangeScan.h>
18 
21 
22 using namespace mp2p_icp_filters;
23 
25  const mrpt::containers::yaml& c)
26 {
27  MCP_LOAD_OPT(c, input_pointcloud_layer);
28 
29  MCP_LOAD_REQ(c, voxel_filter_resolution);
30  MCP_LOAD_REQ(c, voxel_filter_decimation);
31  MCP_LOAD_REQ(c, full_pointcloud_decimation);
32  MCP_LOAD_REQ(c, voxel_filter_max_e2_e0);
33  MCP_LOAD_REQ(c, voxel_filter_max_e1_e0);
34  MCP_LOAD_REQ(c, voxel_filter_min_e2_e0);
35  MCP_LOAD_REQ(c, voxel_filter_min_e1_e0);
36  MCP_LOAD_OPT(c, voxel_filter_min_e1);
37 
38  MCP_LOAD_OPT(c, init_extension_min_x);
39  MCP_LOAD_OPT(c, init_extension_min_y);
40  MCP_LOAD_OPT(c, init_extension_min_z);
41  MCP_LOAD_OPT(c, init_extension_max_x);
42  MCP_LOAD_OPT(c, init_extension_max_y);
43  MCP_LOAD_OPT(c, init_extension_max_z);
44 }
45 
47 
48 void FilterEdgesPlanes::initialize(const mrpt::containers::yaml& c)
49 {
50  MRPT_START
51 
52  MRPT_LOG_DEBUG_STREAM("Loading these params:\n" << c);
54 
61 
62  MRPT_END
63 }
64 
66 {
67  MRPT_START
68 
69  // In:
70  const auto& pcPtr = inOut.point_layer(params_.input_pointcloud_layer);
71  ASSERTMSG_(
72  pcPtr, mrpt::format(
73  "Input point cloud layer '%s' was not found.",
75 
76  const auto& pc = *pcPtr;
77 
78  // Out:
79  auto pc_edges = mrpt::maps::CSimplePointsMap::Create();
80  auto pc_planes = mrpt::maps::CSimplePointsMap::Create();
81  auto pc_full_decim = mrpt::maps::CSimplePointsMap::Create();
82  auto pc_plane_centroids = mrpt::maps::CSimplePointsMap::Create();
83 
84  inOut.layers["edge_points"] = pc_edges;
85  inOut.layers["plane_points"] = pc_planes;
86  inOut.layers["full_decim"] = pc_full_decim;
87  inOut.layers["plane_centroids"] = pc_plane_centroids;
88 
89  pc_edges->reserve(pc.size() / 10);
90  pc_planes->reserve(pc.size() / 10);
91  pc_full_decim->reserve(pc.size() / 10);
92  pc_plane_centroids->reserve(pc.size() / 1000);
93 
96 
97  const auto& xs = pc.getPointsBufferRef_x();
98  const auto& ys = pc.getPointsBufferRef_y();
99  const auto& zs = pc.getPointsBufferRef_z();
100 
101  const float max_e20 = params_.voxel_filter_max_e2_e0;
102  const float max_e10 = params_.voxel_filter_max_e1_e0;
103  const float min_e20 = params_.voxel_filter_min_e2_e0;
104  const float min_e10 = params_.voxel_filter_min_e1_e0;
105  const float min_e1 = params_.voxel_filter_min_e1;
106 
107  std::size_t nEdgeVoxels = 0, nPlaneVoxels = 0, nTotalVoxels = 0;
108  for (const auto& vxl_pts : filter_grid_.pts_voxels)
109  {
110  if (!vxl_pts.indices.empty()) nTotalVoxels++;
111  if (vxl_pts.indices.size() < 5) continue;
112 
113  // Analyze the voxel contents:
114  mrpt::math::TPoint3Df mean{0, 0, 0};
115  const float inv_n = (1.0f / vxl_pts.indices.size());
116  for (size_t i = 0; i < vxl_pts.indices.size(); i++)
117  {
118  const auto pt_idx = vxl_pts.indices[i];
119  mean.x += xs[pt_idx];
120  mean.y += ys[pt_idx];
121  mean.z += zs[pt_idx];
122  }
123  mean.x *= inv_n;
124  mean.y *= inv_n;
125  mean.z *= inv_n;
126 
127  mrpt::math::CMatrixFixed<double, 3, 3> mat_a;
128  mat_a.setZero();
129  for (size_t i = 0; i < vxl_pts.indices.size(); i++)
130  {
131  const auto pt_idx = vxl_pts.indices[i];
132  const mrpt::math::TPoint3Df a(
133  xs[pt_idx] - mean.x, ys[pt_idx] - mean.y, zs[pt_idx] - mean.z);
134  mat_a(0, 0) += a.x * a.x;
135  mat_a(1, 0) += a.x * a.y;
136  mat_a(2, 0) += a.x * a.z;
137  mat_a(1, 1) += a.y * a.y;
138  mat_a(2, 1) += a.y * a.z;
139  mat_a(2, 2) += a.z * a.z;
140  }
141  mat_a *= inv_n;
142 
143  // Find eigenvalues & eigenvectors:
144  // This only looks at the lower-triangular part of the cov matrix.
145  mrpt::math::CMatrixFixed<double, 3, 3> eig_vectors;
146  std::vector<double> eig_vals;
147  mat_a.eig_symmetric(eig_vectors, eig_vals);
148 
149  const float e0 = eig_vals[0], e1 = eig_vals[1], e2 = eig_vals[2];
150 
151  mrpt::maps::CPointsMap* dest = nullptr;
152  if (e2 < max_e20 * e0 && e1 < max_e10 * e0)
153  {
154  // Classified as EDGE
155  // ------------------------
156  nEdgeVoxels++;
157  dest = pc_edges.get();
158  }
159  else if (e2 > min_e20 * e0 && e1 > min_e10 * e0 && e1 > min_e1)
160  {
161  // Classified as PLANE
162  // ------------------------
163  nPlaneVoxels++;
164 
165  // Define a plane from its centroid + a normal:
166  const auto pl_c = mrpt::math::TPoint3D(mean);
167 
168  // Normal = largest eigenvector:
169  const auto ev0 =
170  eig_vectors.extractColumn<mrpt::math::TVector3D>(0);
171  auto pl_n = mrpt::math::TVector3D(ev0.x, ev0.y, ev0.z);
172 
173  // Normal direction criterion: make it to face towards the vehicle.
174  // We can use the dot product to find it out, since pointclouds are
175  // given in vehicle-frame coordinates.
176  {
177  // Unit vector: vehicle -> plane centroid:
178  ASSERT_GT_(pl_c.norm(), 1e-3);
179  const auto u = pl_c * (1.0 / pl_c.norm());
180  const auto dot_prod =
181  mrpt::math::dotProduct<3, double>(u, pl_n);
182 
183  // It should be <0 if the normal is pointing to the vehicle.
184  // Otherwise, reverse the normal.
185  if (dot_prod > 0) pl_n = -pl_n;
186  }
187 
188  // Add plane & centroid:
189  const auto pl = mrpt::math::TPlane3D(pl_c, pl_n);
190  inOut.planes.emplace_back(pl, pl_c);
191 
192  // Also: add the centroid to this special layer:
193  pc_plane_centroids->insertPointFast(pl_c.x, pl_c.y, pl_c.z);
194 
195  // Filter out horizontal planes, since their uneven density
196  // makes ICP fail to converge.
197  // A plane on the ground has its 0'th eigenvector like [0 0 1]
198  if (std::abs(ev0.z) < 0.9f) { dest = pc_planes.get(); }
199  }
200  if (dest != nullptr)
201  {
202  for (size_t i = 0; i < vxl_pts.indices.size();
204  {
205  const auto pt_idx = vxl_pts.indices[i];
206  dest->insertPointFast(xs[pt_idx], ys[pt_idx], zs[pt_idx]);
207  }
208  }
209  // full_pointcloud_decimation=0 means dont use this layer
211  {
212  for (size_t i = 0; i < vxl_pts.indices.size();
214  {
215  const auto pt_idx = vxl_pts.indices[i];
216  pc_full_decim->insertPointFast(
217  xs[pt_idx], ys[pt_idx], zs[pt_idx]);
218  }
219  }
220  }
221  MRPT_LOG_DEBUG_STREAM(
222  "[VoxelGridFilter] Voxel counts: total=" << nTotalVoxels
223  << " edges=" << nEdgeVoxels
224  << " planes=" << nPlaneVoxels);
225 
226  MRPT_END
227 }
mp2p_icp_filters::FilterEdgesPlanes::filter_grid_
PointCloudToVoxelGrid filter_grid_
Definition: FilterEdgesPlanes.h:73
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_min_e2_e0
float voxel_filter_min_e2_e0
Definition: FilterEdgesPlanes.h:57
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_min_e1_e0
float voxel_filter_min_e1_e0
Definition: FilterEdgesPlanes.h:58
mp2p_icp_filters::FilterEdgesPlanes::Parameters::load_from_yaml
void load_from_yaml(const mrpt::containers::yaml &c)
Definition: FilterEdgesPlanes.cpp:24
mp2p_icp_filters::FilterEdgesPlanes::Parameters::init_extension_min_z
float init_extension_min_z
Definition: FilterEdgesPlanes.h:63
mp2p_icp_filters::FilterEdgesPlanes::filter
void filter(mp2p_icp::metric_map_t &inOut) const override
Definition: FilterEdgesPlanes.cpp:65
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_min_e1
float voxel_filter_min_e1
Definition: FilterEdgesPlanes.h:59
mp2p_icp_filters::FilterEdgesPlanes::Parameters::input_pointcloud_layer
std::string input_pointcloud_layer
Definition: FilterEdgesPlanes.h:46
mp2p_icp_filters::FilterEdgesPlanes::Parameters::init_extension_max_x
float init_extension_max_x
Definition: FilterEdgesPlanes.h:64
mp2p_icp_filters::FilterEdgesPlanes::FilterEdgesPlanes
FilterEdgesPlanes()
mp2p_icp_filters::FilterEdgesPlanes::Parameters::init_extension_max_y
float init_extension_max_y
Definition: FilterEdgesPlanes.h:65
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_decimation
unsigned int voxel_filter_decimation
Definition: FilterEdgesPlanes.h:54
mp2p_icp_filters::FilterEdgesPlanes::Parameters::full_pointcloud_decimation
unsigned int full_pointcloud_decimation
Definition: FilterEdgesPlanes.h:49
mp2p_icp::metric_map_t::planes
std::vector< plane_patch_t > planes
Definition: metricmap.h:80
mp2p_icp_filters::FilterBase
Definition: FilterBase.h:37
mp2p_icp_filters::FilterEdgesPlanes::params_
Parameters params_
Definition: FilterEdgesPlanes.h:70
mp2p_icp::metric_map_t::point_layer
mrpt::maps::CPointsMap::Ptr point_layer(const layer_name_t &name) const
Definition: metricmap.cpp:483
mp2p_icp_filters::FilterEdgesPlanes::Parameters::init_extension_min_y
float init_extension_min_y
Definition: FilterEdgesPlanes.h:62
mp2p_icp_filters::PointCloudToVoxelGrid::resize
void resize(const mrpt::math::TPoint3D &min_corner, const mrpt::math::TPoint3D &max_corner, const float voxel_size)
Definition: PointCloudToVoxelGrid.cpp:22
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_resolution
double voxel_filter_resolution
Definition: FilterEdgesPlanes.h:52
mp2p_icp_filters::FilterEdgesPlanes::initialize
void initialize(const mrpt::containers::yaml &c) override
Definition: FilterEdgesPlanes.cpp:48
mp2p_icp_filters::PointCloudToVoxelGrid::clear
void clear()
Definition: PointCloudToVoxelGrid.cpp:84
mp2p_icp_filters::PointCloudToVoxelGrid::processPointCloud
void processPointCloud(const mrpt::maps::CPointsMap &p)
Definition: PointCloudToVoxelGrid.cpp:39
mp2p_icp_filters::FilterEdgesPlanes::Parameters::init_extension_max_z
float init_extension_max_z
Definition: FilterEdgesPlanes.h:66
mp2p_icp_filters::FilterEdgesPlanes::Parameters::init_extension_min_x
float init_extension_min_x
Definition: FilterEdgesPlanes.h:61
mp2p_icp::metric_map_t
Generic container of pointcloud(s), extracted features and other maps.
Definition: metricmap.h:47
mp2p_icp_filters::PointCloudToVoxelGrid::pts_voxels
grid_t pts_voxels
Definition: PointCloudToVoxelGrid.h:64
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(FilterEdgesPlanes, mp2p_icp_filters::FilterBase, mp2p_icp_filters) using namespace mp2p_icp_filters
mp2p_icp::metric_map_t::layers
std::map< layer_name_t, mrpt::maps::CMetricMap::Ptr > layers
Definition: metricmap.h:74
mp2p_icp_filters
Definition: FilterBase.h:25
FilterEdgesPlanes.h
Classify pointcloud voxels into planes / "edges".
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_max_e1_e0
float voxel_filter_max_e1_e0
Definition: FilterEdgesPlanes.h:56
mp2p_icp_filters::FilterEdgesPlanes::Parameters::voxel_filter_max_e2_e0
float voxel_filter_max_e2_e0
Definition: FilterEdgesPlanes.h:55


mrpt_local_obstacles
Author(s): Jose-Luis Blanco-Claraco
autogenerated on Mon Aug 14 2023 02:09:02