Skip to content

Commit 5640819

Browse files
publish excluded points for debug purpose
Signed-off-by: kyoichi-sugahara <kyoichi.sugahara@tier4.jp>
1 parent 0dbe52e commit 5640819

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

sensing/pointcloud_preprocessor/docs/ring-outlier-filter.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This implementation inherits `pointcloud_preprocessor::Filter` class, please ref
2929
| `num_points_threshold` | int | 4 | |
3030
| `max_rings_num` | uint_16 | 128 | |
3131
| `max_points_num_per_ring` | size_t | 4000 | Set this value large enough such that `HFoV / resolution < max_points_num_per_ring` |
32+
| `publish_excluded_points` | bool | false | Flag to publish excluded pointcloud |
3233

3334
## Assumptions / Known limits
3435

sensing/pointcloud_preprocessor/include/pointcloud_preprocessor/outlier_filter/ring_outlier_filter_nodelet.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <point_cloud_msg_wrapper/point_cloud_msg_wrapper.hpp>
2323

24+
#include <memory>
2425
#include <utility>
2526
#include <vector>
2627

@@ -42,11 +43,15 @@ class RingOutlierFilterComponent : public pointcloud_preprocessor::Filter
4243
const TransformInfo & transform_info);
4344

4445
private:
46+
/** \brief publisher of excluded pointcloud for debug reason. **/
47+
rclcpp::Publisher<sensor_msgs::msg::PointCloud2>::SharedPtr excluded_points_publisher_;
48+
4549
double distance_ratio_;
4650
double object_length_threshold_;
4751
int num_points_threshold_;
4852
uint16_t max_rings_num_;
4953
size_t max_points_num_per_ring_;
54+
bool publish_excluded_points_;
5055

5156
/** \brief Parameter service callback result : needed to be hold */
5257
OnSetParametersCallbackHandle::SharedPtr set_param_res_;
@@ -68,6 +73,8 @@ class RingOutlierFilterComponent : public pointcloud_preprocessor::Filter
6873

6974
return x * x + y * y + z * z >= object_length_threshold_ * object_length_threshold_;
7075
}
76+
PointCloud2 extractExcludedPoints(
77+
const PointCloud2 & input, const PointCloud2 & output, float epsilon);
7178

7279
public:
7380
PCL_MAKE_ALIGNED_OPERATOR_NEW

sensing/pointcloud_preprocessor/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<buildtool_depend>ament_cmake_auto</buildtool_depend>
1919
<buildtool_depend>autoware_cmake</buildtool_depend>
2020

21+
<depend>autoware_auto_geometry</depend>
2122
<depend>autoware_point_types</depend>
2223
<depend>cgal</depend>
2324
<depend>cv_bridge</depend>

sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp

+71
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include "pointcloud_preprocessor/outlier_filter/ring_outlier_filter_nodelet.hpp"
1616

17+
#include "autoware_auto_geometry/common_3d.hpp"
18+
1719
#include <sensor_msgs/point_cloud2_iterator.hpp>
1820

1921
#include <algorithm>
@@ -29,6 +31,8 @@ RingOutlierFilterComponent::RingOutlierFilterComponent(const rclcpp::NodeOptions
2931
using tier4_autoware_utils::StopWatch;
3032
stop_watch_ptr_ = std::make_unique<StopWatch<std::chrono::milliseconds>>();
3133
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);
3236
stop_watch_ptr_->tic("cyclic_time");
3337
stop_watch_ptr_->tic("processing_time");
3438
}
@@ -42,6 +46,8 @@ RingOutlierFilterComponent::RingOutlierFilterComponent(const rclcpp::NodeOptions
4246
max_rings_num_ = static_cast<uint16_t>(declare_parameter("max_rings_num", 128));
4347
max_points_num_per_ring_ =
4448
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));
4551
}
4652

4753
using std::placeholders::_1;
@@ -196,6 +202,17 @@ void RingOutlierFilterComponent::faster_filter(
196202
sensor_msgs::msg::PointField::FLOAT32, "z", 1, sensor_msgs::msg::PointField::FLOAT32,
197203
"intensity", 1, sensor_msgs::msg::PointField::FLOAT32);
198204

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+
199216
// add processing time for debug
200217
if (debug_publisher_) {
201218
const double cyclic_time_ms = stop_watch_ptr_->toc("cyclic_time", true);
@@ -241,13 +258,67 @@ rcl_interfaces::msg::SetParametersResult RingOutlierFilterComponent::paramCallba
241258
if (get_param(p, "num_points_threshold", num_points_threshold_)) {
242259
RCLCPP_DEBUG(get_logger(), "Setting new num_points_threshold to: %d.", num_points_threshold_);
243260
}
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+
}
244265

245266
rcl_interfaces::msg::SetParametersResult result;
246267
result.successful = true;
247268
result.reason = "success";
248269

249270
return result;
250271
}
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+
251322
} // namespace pointcloud_preprocessor
252323

253324
#include <rclcpp_components/register_node_macro.hpp>

0 commit comments

Comments
 (0)