Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(euclidean_cluster): add diagnostics warning when cluster skipped #10278

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
// limitations under the License.

#pragma once

#include "autoware/euclidean_cluster/euclidean_cluster_interface.hpp"
#include "autoware/euclidean_cluster/utils.hpp"

#include <autoware_utils/ros/diagnostics_interface.hpp>
#include <rclcpp/node.hpp>

#include <pcl/filters/voxel_grid.h>
#include <pcl/point_types.h>

Expand Down Expand Up @@ -44,12 +46,21 @@ class VoxelGridBasedEuclideanCluster : public EuclideanClusterInterface
{
min_points_number_per_voxel_ = min_points_number_per_voxel;
}
void setDiagnosticsInterface(autoware_utils::DiagnosticsInterface * diag_ptr)
{
diagnostics_interface_ptr_ = diag_ptr;
}

private:
pcl::VoxelGrid<pcl::PointXYZ> voxel_grid_;
float tolerance_;
float voxel_leaf_size_;
int min_points_number_per_voxel_;

void publishDiagnosticsSummary(
const std::vector<std::string> & warnings,
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & pointcloud_msg);
autoware_utils::DiagnosticsInterface * diagnostics_interface_ptr_{nullptr};
};

} // namespace autoware::euclidean_cluster
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include "autoware/euclidean_cluster/voxel_grid_based_euclidean_cluster.hpp"

#include <rclcpp/node.hpp>

#include <pcl/kdtree/kdtree.h>
#include <pcl/segmentation/extract_clusters.h>

Expand Down Expand Up @@ -41,6 +43,36 @@
min_points_number_per_voxel_(min_points_number_per_voxel)
{
}

// After processing all clusters, publish a summary of diagnostics.
void VoxelGridBasedEuclideanCluster::publishDiagnosticsSummary(
const std::vector<std::string> & warnings,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const std::vector<std::string> & warnings,
const std::vector<std::string> & diagnostics_messages,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is two option

  1. If the cluster size is the only diagnostics and other diagnostics will not be added in the future, it shall be named diagnostics_cluster_max_size or something similar.
  2. There is any chance to add different type of diagnostics, pair with an index to distinguish diag type, and it will named diagnostics_messages

const sensor_msgs::msg::PointCloud2::ConstSharedPtr & pointcloud_msg)
{
if (!diagnostics_interface_ptr_) {
return;
}
diagnostics_interface_ptr_->clear();

std::stringstream summary;
if (!warnings.empty()) {
summary << warnings.size()
<< " clusters skipped because cluster size exceeds the maximum allowed "
<< max_cluster_size_ << " \n";
for (const auto & warn : warnings) {
summary << " - " << warn << "\n";
}
diagnostics_interface_ptr_->add_key_value("is_cluster_data_size_within_range", false);
} else {
diagnostics_interface_ptr_->add_key_value("is_cluster_data_size_within_range", true);
}
diagnostics_interface_ptr_->update_level_and_message(
warnings.empty() ? static_cast<int8_t>(diagnostic_msgs::msg::DiagnosticStatus::OK)
: static_cast<int8_t>(diagnostic_msgs::msg::DiagnosticStatus::WARN),
summary.str());
diagnostics_interface_ptr_->publish(pointcloud_msg->header.stamp);
}

// TODO(badai-nguyen): remove this function when field copying also implemented for
// euclidean_cluster.cpp
bool VoxelGridBasedEuclideanCluster::cluster(
Expand Down Expand Up @@ -136,34 +168,45 @@

// build output and check cluster size
{
// At the start, create a container to collect warnings.
std::vector<std::string> warning_messages;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning_messages could be diagnostics level not only WARN but ERROR.
Therefore I would like to suggest

Suggested change
std::vector<std::string> warning_messages;
std::vector<std::string> diagnostics_messages;

for (size_t i = 0; i < temporary_clusters.size(); ++i) {
auto & i_cluster_data_size = clusters_data_size.at(i);
if (!(min_cluster_size_ <= static_cast<int>(i_cluster_data_size / point_step) &&
static_cast<int>(i_cluster_data_size / point_step) <= max_cluster_size_)) {
int cluster_size = static_cast<int>(i_cluster_data_size / point_step);
if (cluster_size < min_cluster_size_) {
// Cluster size is below the minimum threshold; skip without messaging.
continue;
}
if (cluster_size > max_cluster_size_) {
// Cluster size exceeds the maximum threshold; log a warning.
warning_messages.push_back(
" Cluster " + std::to_string(i) + " (" + std::to_string(cluster_size) + ").");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
warning_messages.push_back(
" Cluster " + std::to_string(i) + " (" + std::to_string(cluster_size) + ").");
warning_messages.push_back(
" Cluster " + std::to_string(i) + " (" + std::to_string(cluster_size) + " > "+ max_cluster_size_ +").");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indicate current maximum value to user.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The diagnostics messages are modified in the latest commit as the following reasons

  1. current cluster implementation will make the point number in skipped cluster just exactly the same as threshold+1, making the information of point number in a cluster redundant
  2. without cluster point number, cluster index becomes redundant
    so now output will only gives information of threshold and total number of skipped clusters

continue;
}
const auto & cluster = temporary_clusters.at(i);
tier4_perception_msgs::msg::DetectedObjectWithFeature feature_object;
feature_object.feature.cluster = cluster;
feature_object.feature.cluster.data.resize(i_cluster_data_size);
feature_object.feature.cluster.header = pointcloud_msg->header;
feature_object.feature.cluster.is_bigendian = pointcloud_msg->is_bigendian;
feature_object.feature.cluster.is_dense = pointcloud_msg->is_dense;
feature_object.feature.cluster.point_step = point_step;
feature_object.feature.cluster.row_step = i_cluster_data_size / pointcloud_msg->height;
feature_object.feature.cluster.width =
i_cluster_data_size / point_step / pointcloud_msg->height;

feature_object.object.kinematics.pose_with_covariance.pose.position =
getCentroid(feature_object.feature.cluster);
autoware_perception_msgs::msg::ObjectClassification classification;
classification.label = autoware_perception_msgs::msg::ObjectClassification::UNKNOWN;
classification.probability = 1.0f;
feature_object.object.classification.emplace_back(classification);

objects.feature_objects.push_back(feature_object);
}
objects.header = pointcloud_msg->header;

publishDiagnosticsSummary(warning_messages, pointcloud_msg);

Check warning on line 209 in perception/autoware_euclidean_cluster/lib/voxel_grid_based_euclidean_cluster.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

VoxelGridBasedEuclideanCluster::cluster increases in cyclomatic complexity from 13 to 14, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
}

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@ VoxelGridBasedEuclideanClusterNode::VoxelGridBasedEuclideanClusterNode(
const float tolerance = this->declare_parameter("tolerance", 1.0);
const float voxel_leaf_size = this->declare_parameter("voxel_leaf_size", 0.5);
const int min_points_number_per_voxel = this->declare_parameter("min_points_number_per_voxel", 3);

cluster_ = std::make_shared<VoxelGridBasedEuclideanCluster>(
use_height, min_cluster_size, max_cluster_size, tolerance, voxel_leaf_size,
min_points_number_per_voxel);
// Pass the diagnostics interface pointer from the node to the cluster
diagnostics_interface_ptr_ =
std::make_unique<autoware_utils::DiagnosticsInterface>(this, "euclidean_cluster");
cluster_->setDiagnosticsInterface(diagnostics_interface_ptr_.get());

using std::placeholders::_1;
pointcloud_sub_ = this->create_subscription<sensor_msgs::msg::PointCloud2>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#include "autoware/euclidean_cluster/voxel_grid_based_euclidean_cluster.hpp"

#include <autoware_utils/ros/debug_publisher.hpp>
#include <autoware_utils/ros/diagnostics_interface.hpp>
#include <autoware_utils/system/stop_watch.hpp>
#include <rclcpp/rclcpp.hpp>

#include <geometry_msgs/msg/pose_stamped.hpp>
#include <sensor_msgs/msg/point_cloud2.hpp>
Expand All @@ -43,6 +43,8 @@ class VoxelGridBasedEuclideanClusterNode : public rclcpp::Node
std::shared_ptr<VoxelGridBasedEuclideanCluster> cluster_;
std::unique_ptr<autoware_utils::StopWatch<std::chrono::milliseconds>> stop_watch_ptr_;
std::unique_ptr<autoware_utils::DebugPublisher> debug_publisher_;

std::unique_ptr<autoware_utils::DiagnosticsInterface> diagnostics_interface_ptr_;
};

} // namespace autoware::euclidean_cluster
Loading