14
14
15
15
#include " pointcloud_preprocessor/outlier_filter/ring_outlier_filter_nodelet.hpp"
16
16
17
- #include " autoware_auto_geometry/common_3d .hpp"
17
+ #include " autoware_point_types/types .hpp"
18
18
19
19
#include < sensor_msgs/point_cloud2_iterator.hpp>
20
20
21
- #include < pcl/search/pcl_search.h>
22
-
23
21
#include < algorithm>
24
22
#include < vector>
25
23
namespace pointcloud_preprocessor
26
24
{
25
+ using autoware_point_types::PointXYZIRADRT;
26
+
27
27
RingOutlierFilterComponent::RingOutlierFilterComponent (const rclcpp::NodeOptions & options)
28
28
: Filter(" RingOutlierFilter" , options)
29
29
{
@@ -35,6 +35,10 @@ RingOutlierFilterComponent::RingOutlierFilterComponent(const rclcpp::NodeOptions
35
35
debug_publisher_ = std::make_unique<DebugPublisher>(this , " ring_outlier_filter" );
36
36
outlier_pointcloud_publisher_ =
37
37
this ->create_publisher <PointCloud2>(" debug/ring_outlier_filter" , 1 );
38
+ image_pub_ =
39
+ image_transport::create_publisher (this , " ring_outlier_filter/debug/frequency_image" );
40
+ visibility_pub_ = create_publisher<tier4_debug_msgs::msg::Float32Stamped>(
41
+ " ring_outlier_filter/debug/visibility" , rclcpp::SensorDataQoS ());
38
42
stop_watch_ptr_->tic (" cyclic_time" );
39
43
stop_watch_ptr_->tic (" processing_time" );
40
44
}
@@ -50,6 +54,13 @@ RingOutlierFilterComponent::RingOutlierFilterComponent(const rclcpp::NodeOptions
50
54
static_cast <size_t >(declare_parameter (" max_points_num_per_ring" , 4000 ));
51
55
publish_outlier_pointcloud_ =
52
56
static_cast <bool >(declare_parameter (" publish_outlier_pointcloud" , false ));
57
+
58
+ min_azimuth_deg_ = static_cast <float >(declare_parameter (" min_azimuth_deg" , 0.0 ));
59
+ max_azimuth_deg_ = static_cast <float >(declare_parameter (" max_azimuth_deg" , 360.0 ));
60
+ max_distance_ = static_cast <float >(declare_parameter (" max_distance" , 12.0 ));
61
+ vertical_bins_ = static_cast <int >(declare_parameter (" vertical_bins" , 128 ));
62
+ horizontal_bins_ = static_cast <int >(declare_parameter (" horizontal_bins" , 36 ));
63
+ noise_threshold_ = static_cast <int >(declare_parameter (" noise_threshold" , 2 ));
53
64
}
54
65
55
66
using std::placeholders::_1;
@@ -73,13 +84,7 @@ void RingOutlierFilterComponent::faster_filter(
73
84
output.data .resize (output.point_step * input->width );
74
85
size_t output_size = 0 ;
75
86
76
- // Set up the noise points cloud, if noise points are to be published.
77
- PointCloud2 outlier_points;
78
- size_t outlier_points_size = 0 ;
79
- if (publish_outlier_pointcloud_) {
80
- outlier_points.point_step = sizeof (PointXYZI);
81
- outlier_points.data .resize (outlier_points.point_step * input->width );
82
- }
87
+ pcl::PointCloud<PointXYZIRADRT>::Ptr outlier_pcl (new pcl::PointCloud<PointXYZIRADRT>);
83
88
84
89
const auto ring_offset =
85
90
input->fields .at (static_cast <size_t >(autoware_point_types::PointIndex::Ring)).offset ;
@@ -89,6 +94,10 @@ void RingOutlierFilterComponent::faster_filter(
89
94
input->fields .at (static_cast <size_t >(autoware_point_types::PointIndex::Distance)).offset ;
90
95
const auto intensity_offset =
91
96
input->fields .at (static_cast <size_t >(autoware_point_types::PointIndex::Intensity)).offset ;
97
+ const auto return_type_offset =
98
+ input->fields .at (static_cast <size_t >(autoware_point_types::PointIndex::ReturnType)).offset ;
99
+ const auto time_stamp_offset =
100
+ input->fields .at (static_cast <size_t >(autoware_point_types::PointIndex::TimeStamp)).offset ;
92
101
93
102
std::vector<std::vector<size_t >> ring2indices;
94
103
ring2indices.reserve (max_rings_num_);
@@ -163,24 +172,32 @@ void RingOutlierFilterComponent::faster_filter(
163
172
}
164
173
} else if (publish_outlier_pointcloud_) {
165
174
for (int i = walk_first_idx; i <= walk_last_idx; i++) {
166
- auto outlier_ptr =
167
- reinterpret_cast <PointXYZI *>(&outlier_points.data [outlier_points_size]);
175
+ PointXYZIRADRT outlier_point;
168
176
auto input_ptr =
169
- reinterpret_cast <const PointXYZI *>(&input->data [indices[walk_first_idx]]);
177
+ reinterpret_cast <const PointXYZIRADRT *>(&input->data [indices[walk_first_idx]]);
170
178
if (transform_info.need_transform ) {
171
179
Eigen::Vector4f p (input_ptr->x , input_ptr->y , input_ptr->z , 1 );
172
180
p = transform_info.eigen_transform * p;
173
- outlier_ptr-> x = p[0 ];
174
- outlier_ptr-> y = p[1 ];
175
- outlier_ptr-> z = p[2 ];
181
+ outlier_point. x = p[0 ];
182
+ outlier_point. y = p[1 ];
183
+ outlier_point. z = p[2 ];
176
184
} else {
177
- *outlier_ptr = *input_ptr;
185
+ outlier_point = *input_ptr;
178
186
}
179
- const float & intensity = *reinterpret_cast <const float *>(
180
- &input->data [indices[walk_first_idx] + intensity_offset]);
181
- outlier_ptr->intensity = intensity;
182
187
183
- outlier_points_size += outlier_points.point_step ;
188
+ outlier_point.intensity = *reinterpret_cast <const float *>(
189
+ &input->data [indices[walk_first_idx] + intensity_offset]);
190
+ outlier_point.ring = *reinterpret_cast <const uint16_t *>(
191
+ &input->data [indices[walk_first_idx] + ring_offset]);
192
+ outlier_point.azimuth = *reinterpret_cast <const float *>(
193
+ &input->data [indices[walk_first_idx] + azimuth_offset]);
194
+ outlier_point.distance = *reinterpret_cast <const float *>(
195
+ &input->data [indices[walk_first_idx] + distance_offset]);
196
+ outlier_point.return_type = *reinterpret_cast <const uint8_t *>(
197
+ &input->data [indices[walk_first_idx] + return_type_offset]);
198
+ outlier_point.time_stamp = *reinterpret_cast <const float *>(
199
+ &input->data [indices[walk_first_idx] + time_stamp_offset]);
200
+ outlier_pcl->push_back (outlier_point);
184
201
}
185
202
}
186
203
@@ -213,30 +230,47 @@ void RingOutlierFilterComponent::faster_filter(
213
230
}
214
231
} else if (publish_outlier_pointcloud_) {
215
232
for (int i = walk_first_idx; i < walk_last_idx; i++) {
216
- auto outlier_ptr = reinterpret_cast <PointXYZI *>(&outlier_points.data [outlier_points_size]);
217
- auto input_ptr = reinterpret_cast <const PointXYZI *>(&input->data [indices[i]]);
233
+ PointXYZIRADRT outlier_point;
234
+
235
+ auto input_ptr = reinterpret_cast <const PointXYZIRADRT *>(&input->data [indices[i]]);
218
236
if (transform_info.need_transform ) {
219
237
Eigen::Vector4f p (input_ptr->x , input_ptr->y , input_ptr->z , 1 );
220
238
p = transform_info.eigen_transform * p;
221
- outlier_ptr-> x = p[0 ];
222
- outlier_ptr-> y = p[1 ];
223
- outlier_ptr-> z = p[2 ];
239
+ outlier_point. x = p[0 ];
240
+ outlier_point. y = p[1 ];
241
+ outlier_point. z = p[2 ];
224
242
} else {
225
- *outlier_ptr = *input_ptr;
243
+ outlier_point = *input_ptr;
226
244
}
227
- const float & intensity =
245
+ outlier_point. intensity =
228
246
*reinterpret_cast <const float *>(&input->data [indices[i] + intensity_offset]);
229
- outlier_ptr->intensity = intensity;
230
- outlier_points_size += outlier_points.point_step ;
247
+ outlier_point.ring =
248
+ *reinterpret_cast <const uint16_t *>(&input->data [indices[i] + ring_offset]);
249
+ outlier_point.azimuth =
250
+ *reinterpret_cast <const float *>(&input->data [indices[i] + azimuth_offset]);
251
+ outlier_point.distance =
252
+ *reinterpret_cast <const float *>(&input->data [indices[i] + distance_offset]);
253
+ outlier_point.return_type =
254
+ *reinterpret_cast <const uint8_t *>(&input->data [indices[i] + return_type_offset]);
255
+ outlier_point.time_stamp =
256
+ *reinterpret_cast <const float *>(&input->data [indices[i] + time_stamp_offset]);
257
+ outlier_pcl->push_back (outlier_point);
231
258
}
232
259
}
233
260
}
234
261
235
262
setUpPointCloudFormat (input, output, output_size, /* num_fields=*/ 4 );
236
263
237
264
if (publish_outlier_pointcloud_) {
238
- setUpPointCloudFormat (input, outlier_points, outlier_points_size, /* num_fields=*/ 4 );
239
- outlier_pointcloud_publisher_->publish (outlier_points);
265
+ PointCloud2 outlier;
266
+ pcl::toROSMsg (*outlier_pcl, outlier);
267
+ outlier.header = input->header ;
268
+ outlier_pointcloud_publisher_->publish (outlier);
269
+
270
+ tier4_debug_msgs::msg::Float32Stamped visibility_msg;
271
+ visibility_msg.data = calculateVisibilityScore (outlier);
272
+ visibility_msg.stamp = input->header .stamp ;
273
+ visibility_pub_->publish (visibility_msg);
240
274
}
241
275
242
276
// add processing time for debug
@@ -288,6 +322,12 @@ rcl_interfaces::msg::SetParametersResult RingOutlierFilterComponent::paramCallba
288
322
RCLCPP_DEBUG (
289
323
get_logger (), " Setting new publish_outlier_pointcloud to: %d." , publish_outlier_pointcloud_);
290
324
}
325
+ if (get_param (p, " vertical_bins" , vertical_bins_)) {
326
+ RCLCPP_DEBUG (get_logger (), " Setting new vertical_bins to: %d." , vertical_bins_);
327
+ }
328
+ if (get_param (p, " max_azimuth_diff" , max_azimuth_diff_)) {
329
+ RCLCPP_DEBUG (get_logger (), " Setting new max_azimuth_diff to: %f." , max_azimuth_diff_);
330
+ }
291
331
292
332
rcl_interfaces::msg::SetParametersResult result;
293
333
result.successful = true ;
@@ -319,6 +359,61 @@ void RingOutlierFilterComponent::setUpPointCloudFormat(
319
359
" intensity" , 1 , sensor_msgs::msg::PointField::FLOAT32);
320
360
}
321
361
362
+ float RingOutlierFilterComponent::calculateVisibilityScore (
363
+ const sensor_msgs::msg::PointCloud2 & input)
364
+ {
365
+ pcl::PointCloud<PointXYZIRADRT>::Ptr input_cloud (new pcl::PointCloud<PointXYZIRADRT>);
366
+ pcl::fromROSMsg (input, *input_cloud);
367
+
368
+ const uint32_t vertical_bins = vertical_bins_;
369
+ const uint32_t horizontal_bins = horizontal_bins_;
370
+ const float max_azimuth = max_azimuth_deg_ * 100.0 ;
371
+ const float min_azimuth = min_azimuth_deg_ * 100.0 ;
372
+
373
+ const uint32_t horizontal_resolution =
374
+ static_cast <uint32_t >((max_azimuth - min_azimuth) / horizontal_bins);
375
+
376
+ std::vector<pcl::PointCloud<PointXYZIRADRT>> ring_point_clouds (vertical_bins);
377
+ cv::Mat frequency_image (cv::Size (horizontal_bins, vertical_bins), CV_8UC1, cv::Scalar (0 ));
378
+
379
+ // Split points into rings
380
+ for (const auto & point : input_cloud->points ) {
381
+ ring_point_clouds.at (point.ring ).push_back (point);
382
+ }
383
+
384
+ // Calculate frequency for each bin in each ring
385
+ for (const auto & ring_points : ring_point_clouds) {
386
+ if (ring_points.empty ()) continue ;
387
+
388
+ const uint ring_id = ring_points.front ().ring ;
389
+ std::vector<int > frequency_in_ring (horizontal_bins, 0 );
390
+
391
+ for (const auto & point : ring_points.points ) {
392
+ if (point.azimuth < min_azimuth || point.azimuth >= max_azimuth) continue ;
393
+ if (point.distance >= max_distance_) continue ;
394
+
395
+ const uint bin_index =
396
+ static_cast <uint >((point.azimuth - min_azimuth) / horizontal_resolution);
397
+
398
+ frequency_in_ring[bin_index]++;
399
+ frequency_in_ring[bin_index] =
400
+ std::min (frequency_in_ring[bin_index], 255 ); // Ensure value is within uchar range
401
+
402
+ frequency_image.at <uchar>(ring_id, bin_index) =
403
+ static_cast <uchar>(frequency_in_ring[bin_index]);
404
+ }
405
+ }
406
+
407
+ cv::Mat binary_image;
408
+ cv::inRange (frequency_image, noise_threshold_, 255 , binary_image);
409
+
410
+ const int num_pixels = cv::countNonZero (frequency_image);
411
+ const float num_filled_pixels =
412
+ static_cast <float >(num_pixels) / static_cast <float >(vertical_bins * horizontal_bins);
413
+
414
+ return 1 .0f - num_filled_pixels;
415
+ }
416
+
322
417
} // namespace pointcloud_preprocessor
323
418
324
419
#include < rclcpp_components/register_node_macro.hpp>
0 commit comments