14
14
15
15
#include " pointcloud_preprocessor/outlier_filter/ring_outlier_filter_nodelet.hpp"
16
16
17
+ #include " autoware_auto_geometry/common_3d.hpp"
18
+
17
19
#include < sensor_msgs/point_cloud2_iterator.hpp>
18
20
19
21
#include < algorithm>
@@ -29,6 +31,8 @@ RingOutlierFilterComponent::RingOutlierFilterComponent(const rclcpp::NodeOptions
29
31
using tier4_autoware_utils::StopWatch;
30
32
stop_watch_ptr_ = std::make_unique<StopWatch<std::chrono::milliseconds>>();
31
33
debug_publisher_ = std::make_unique<DebugPublisher>(this , " ring_outlier_filter" );
34
+ excluded_points_publisher_ =
35
+ this ->create_publisher <sensor_msgs::msg::PointCloud2>(" debug/ring_outlier_filter" , 1 );
32
36
stop_watch_ptr_->tic (" cyclic_time" );
33
37
stop_watch_ptr_->tic (" processing_time" );
34
38
}
@@ -42,6 +46,8 @@ RingOutlierFilterComponent::RingOutlierFilterComponent(const rclcpp::NodeOptions
42
46
max_rings_num_ = static_cast <uint16_t >(declare_parameter (" max_rings_num" , 128 ));
43
47
max_points_num_per_ring_ =
44
48
static_cast <size_t >(declare_parameter (" max_points_num_per_ring" , 4000 ));
49
+ publish_excluded_points_ =
50
+ static_cast <bool >(declare_parameter (" publish_excluded_points" , false ));
45
51
}
46
52
47
53
using std::placeholders::_1;
@@ -196,6 +202,17 @@ void RingOutlierFilterComponent::faster_filter(
196
202
sensor_msgs::msg::PointField::FLOAT32, " z" , 1 , sensor_msgs::msg::PointField::FLOAT32,
197
203
" intensity" , 1 , sensor_msgs::msg::PointField::FLOAT32);
198
204
205
+ if (publish_excluded_points_) {
206
+ auto excluded_points = extractExcludedPoints (*input, output, 0.01 );
207
+ // set fields
208
+ sensor_msgs::PointCloud2Modifier excluded_pcd_modifier (excluded_points);
209
+ excluded_pcd_modifier.setPointCloud2Fields (
210
+ num_fields, " x" , 1 , sensor_msgs::msg::PointField::FLOAT32, " y" , 1 ,
211
+ sensor_msgs::msg::PointField::FLOAT32, " z" , 1 , sensor_msgs::msg::PointField::FLOAT32,
212
+ " intensity" , 1 , sensor_msgs::msg::PointField::FLOAT32);
213
+ excluded_points_publisher_->publish (excluded_points);
214
+ }
215
+
199
216
// add processing time for debug
200
217
if (debug_publisher_) {
201
218
const double cyclic_time_ms = stop_watch_ptr_->toc (" cyclic_time" , true );
@@ -241,13 +258,67 @@ rcl_interfaces::msg::SetParametersResult RingOutlierFilterComponent::paramCallba
241
258
if (get_param (p, " num_points_threshold" , num_points_threshold_)) {
242
259
RCLCPP_DEBUG (get_logger (), " Setting new num_points_threshold to: %d." , num_points_threshold_);
243
260
}
261
+ if (get_param (p, " publish_excluded_points" , publish_excluded_points_)) {
262
+ RCLCPP_DEBUG (
263
+ get_logger (), " Setting new publish_excluded_points to: %d." , publish_excluded_points_);
264
+ }
244
265
245
266
rcl_interfaces::msg::SetParametersResult result;
246
267
result.successful = true ;
247
268
result.reason = " success" ;
248
269
249
270
return result;
250
271
}
272
+
273
+ sensor_msgs::msg::PointCloud2 RingOutlierFilterComponent::extractExcludedPoints (
274
+ const sensor_msgs::msg::PointCloud2 & input, const sensor_msgs::msg::PointCloud2 & output,
275
+ float epsilon)
276
+ {
277
+ // Convert ROS PointCloud2 message to PCL point cloud for easier manipulation
278
+ pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud (new pcl::PointCloud<pcl::PointXYZ>);
279
+ pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud (new pcl::PointCloud<pcl::PointXYZ>);
280
+ pcl::fromROSMsg (input, *input_cloud);
281
+ pcl::fromROSMsg (output, *output_cloud);
282
+
283
+ pcl::PointCloud<pcl::PointXYZ>::Ptr excluded_points (new pcl::PointCloud<pcl::PointXYZ>);
284
+
285
+ for (const auto & input_point : *input_cloud) {
286
+ bool is_excluded = true ;
287
+
288
+ for (const auto & output_point : *output_cloud) {
289
+ float distance = autoware::common::geometry::distance_3d (input_point, output_point);
290
+
291
+ // If the distance is less than the threshold (epsilon), the point is not excluded
292
+ if (distance < epsilon) {
293
+ is_excluded = false ;
294
+ break ;
295
+ }
296
+ }
297
+
298
+ // If the point is still marked as excluded after all comparisons, add it to the excluded
299
+ // pointcloud
300
+ if (is_excluded) {
301
+ excluded_points->push_back (input_point);
302
+ }
303
+ }
304
+
305
+ sensor_msgs::msg::PointCloud2 excluded_points_msg;
306
+ pcl::toROSMsg (*excluded_points, excluded_points_msg);
307
+
308
+ // Set the metadata for the excluded points message based on the input cloud
309
+ excluded_points_msg.height = 1 ;
310
+ excluded_points_msg.width =
311
+ static_cast <uint32_t >(output.data .size () / output.height / output.point_step );
312
+ excluded_points_msg.row_step = static_cast <uint32_t >(output.data .size () / output.height );
313
+ excluded_points_msg.is_bigendian = input.is_bigendian ;
314
+ excluded_points_msg.is_dense = input.is_dense ;
315
+ excluded_points_msg.header = input.header ;
316
+ excluded_points_msg.header .frame_id =
317
+ !tf_input_frame_.empty () ? tf_input_frame_ : tf_input_orig_frame_;
318
+
319
+ return excluded_points_msg;
320
+ }
321
+
251
322
} // namespace pointcloud_preprocessor
252
323
253
324
#include < rclcpp_components/register_node_macro.hpp>
0 commit comments