Skip to content

Commit aa613d4

Browse files
committed
feat(euclidean_cluster): add diagnostics warning when cluster skipped due to excessive points from large objects
1 parent e69b61d commit aa613d4

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

perception/autoware_euclidean_cluster/include/autoware/euclidean_cluster/voxel_grid_based_euclidean_cluster.hpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
// limitations under the License.
1414

1515
#pragma once
16-
1716
#include "autoware/euclidean_cluster/euclidean_cluster_interface.hpp"
1817
#include "autoware/euclidean_cluster/utils.hpp"
18+
#include <autoware_utils/ros/diagnostics_interface.hpp>
19+
#include <rclcpp/node.hpp>
1920

2021
#include <pcl/filters/voxel_grid.h>
2122
#include <pcl/point_types.h>
@@ -44,12 +45,20 @@ class VoxelGridBasedEuclideanCluster : public EuclideanClusterInterface
4445
{
4546
min_points_number_per_voxel_ = min_points_number_per_voxel;
4647
}
47-
48+
void setDiagnosticsInterface(autoware_utils::DiagnosticsInterface* diag_ptr)
49+
{
50+
diagnostics_interface_ptr_ = diag_ptr;
51+
}
4852
private:
4953
pcl::VoxelGrid<pcl::PointXYZ> voxel_grid_;
5054
float tolerance_;
5155
float voxel_leaf_size_;
5256
int min_points_number_per_voxel_;
57+
58+
void publishDiagnosticsSummary(
59+
const std::vector<std::string> & warnings,
60+
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & pointcloud_msg);
61+
autoware_utils::DiagnosticsInterface* diagnostics_interface_ptr_{nullptr};
5362
};
5463

5564
} // namespace autoware::euclidean_cluster

perception/autoware_euclidean_cluster/lib/voxel_grid_based_euclidean_cluster.cpp

+48-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include "autoware/euclidean_cluster/voxel_grid_based_euclidean_cluster.hpp"
16+
#include <rclcpp/node.hpp>
1617

1718
#include <pcl/kdtree/kdtree.h>
1819
#include <pcl/segmentation/extract_clusters.h>
@@ -41,6 +42,35 @@ VoxelGridBasedEuclideanCluster::VoxelGridBasedEuclideanCluster(
4142
min_points_number_per_voxel_(min_points_number_per_voxel)
4243
{
4344
}
45+
46+
// After processing all clusters, publish a summary of diagnostics.
47+
void VoxelGridBasedEuclideanCluster::publishDiagnosticsSummary(
48+
const std::vector<std::string> & warnings,
49+
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & pointcloud_msg)
50+
{
51+
if (!diagnostics_interface_ptr_) {
52+
return;
53+
}
54+
diagnostics_interface_ptr_->clear();
55+
56+
std::stringstream summary;
57+
if (!warnings.empty()) {
58+
summary << warnings.size() << " clusters skipped because cluster size exceeds the maximum allowed "
59+
<< max_cluster_size_ << " \n";
60+
for (const auto & warn : warnings) {
61+
summary << " - " << warn << "\n";
62+
}
63+
diagnostics_interface_ptr_->add_key_value("is_cluster_data_size_within_range", false);
64+
} else {
65+
diagnostics_interface_ptr_->add_key_value("is_cluster_data_size_within_range", true);
66+
}
67+
diagnostics_interface_ptr_->update_level_and_message(
68+
warnings.empty() ? diagnostic_msgs::msg::DiagnosticStatus::OK : diagnostic_msgs::msg::DiagnosticStatus::WARN,
69+
summary.str());
70+
diagnostics_interface_ptr_->publish(pointcloud_msg->header.stamp);
71+
}
72+
73+
4474
// TODO(badai-nguyen): remove this function when field copying also implemented for
4575
// euclidean_cluster.cpp
4676
bool VoxelGridBasedEuclideanCluster::cluster(
@@ -136,12 +166,25 @@ bool VoxelGridBasedEuclideanCluster::cluster(
136166

137167
// build output and check cluster size
138168
{
169+
// At the start, create a container to collect warnings.
170+
std::vector<std::string> warning_messages;
139171
for (size_t i = 0; i < temporary_clusters.size(); ++i) {
140172
auto & i_cluster_data_size = clusters_data_size.at(i);
141-
if (!(min_cluster_size_ <= static_cast<int>(i_cluster_data_size / point_step) &&
142-
static_cast<int>(i_cluster_data_size / point_step) <= max_cluster_size_)) {
173+
int cluster_size = static_cast<int>(i_cluster_data_size / point_step);
174+
if (cluster_size < min_cluster_size_) {
175+
// Cluster size is below the minimum threshold; skip without messaging.
176+
continue;
177+
}
178+
if (cluster_size > max_cluster_size_ /10) {
179+
// Cluster size exceeds the maximum threshold; log a warning.
180+
warning_messages.push_back(" Cluster " + std::to_string(i) + " (" + std::to_string(cluster_size) + ").");
143181
continue;
144182
}
183+
184+
// if (!(min_cluster_size_ <= static_cast<int>(i_cluster_data_size / point_step) &&
185+
// static_cast<int>(i_cluster_data_size / point_step) <= max_cluster_size_)) {
186+
// continue;
187+
// }
145188
const auto & cluster = temporary_clusters.at(i);
146189
tier4_perception_msgs::msg::DetectedObjectWithFeature feature_object;
147190
feature_object.feature.cluster = cluster;
@@ -164,6 +207,9 @@ bool VoxelGridBasedEuclideanCluster::cluster(
164207
objects.feature_objects.push_back(feature_object);
165208
}
166209
objects.header = pointcloud_msg->header;
210+
211+
publishDiagnosticsSummary(warning_messages, pointcloud_msg);
212+
167213
}
168214

169215
return true;

perception/autoware_euclidean_cluster/src/voxel_grid_based_euclidean_cluster_node.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@ VoxelGridBasedEuclideanClusterNode::VoxelGridBasedEuclideanClusterNode(
3131
const float tolerance = this->declare_parameter("tolerance", 1.0);
3232
const float voxel_leaf_size = this->declare_parameter("voxel_leaf_size", 0.5);
3333
const int min_points_number_per_voxel = this->declare_parameter("min_points_number_per_voxel", 3);
34+
3435
cluster_ = std::make_shared<VoxelGridBasedEuclideanCluster>(
3536
use_height, min_cluster_size, max_cluster_size, tolerance, voxel_leaf_size,
3637
min_points_number_per_voxel);
37-
38+
// Pass the diagnostics interface pointer from the node to the cluster
39+
diagnostics_interface_ptr_ = std::make_unique<autoware_utils::DiagnosticsInterface>(this, "euclidean_cluster");
40+
cluster_->setDiagnosticsInterface(diagnostics_interface_ptr_.get());
41+
3842
using std::placeholders::_1;
3943
pointcloud_sub_ = this->create_subscription<sensor_msgs::msg::PointCloud2>(
4044
"input", rclcpp::SensorDataQoS().keep_last(1),
@@ -48,6 +52,8 @@ VoxelGridBasedEuclideanClusterNode::VoxelGridBasedEuclideanClusterNode(
4852
std::make_unique<autoware_utils::DebugPublisher>(this, "voxel_grid_based_euclidean_cluster");
4953
stop_watch_ptr_->tic("cyclic_time");
5054
stop_watch_ptr_->tic("processing_time");
55+
56+
5157
}
5258

5359
void VoxelGridBasedEuclideanClusterNode::onPointCloud(

perception/autoware_euclidean_cluster/src/voxel_grid_based_euclidean_cluster_node.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
#include <autoware_utils/ros/debug_publisher.hpp>
2020
#include <autoware_utils/system/stop_watch.hpp>
21-
#include <rclcpp/rclcpp.hpp>
21+
#include <autoware_utils/ros/diagnostics_interface.hpp>
2222

2323
#include <geometry_msgs/msg/pose_stamped.hpp>
2424
#include <sensor_msgs/msg/point_cloud2.hpp>
@@ -43,6 +43,9 @@ class VoxelGridBasedEuclideanClusterNode : public rclcpp::Node
4343
std::shared_ptr<VoxelGridBasedEuclideanCluster> cluster_;
4444
std::unique_ptr<autoware_utils::StopWatch<std::chrono::milliseconds>> stop_watch_ptr_;
4545
std::unique_ptr<autoware_utils::DebugPublisher> debug_publisher_;
46+
47+
std::unique_ptr<autoware_utils::DiagnosticsInterface> diagnostics_interface_ptr_;
48+
4649
};
4750

4851
} // namespace autoware::euclidean_cluster

0 commit comments

Comments
 (0)