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

fix(detected_object_validation): add 3d pointcloud based validator #5327

Conversation

badai-nguyen
Copy link
Contributor

@badai-nguyen badai-nguyen commented Oct 17, 2023

Description

  • Currently obstacle_pointcloud_based_validator projects pointcloud into xy_plane and check the number of points within object footprint.
  • In some cases like the centerpoint misdetects tree bushes as car, then the high position points of the tree migh be included which cause a wrong validation.
  • This PR will add an option to validate obstacle pointcloud base on 3d shape of detected objects.
frequently misdetection case tree leaves are also projected and treated as validation points
yellow: obstacle points, green points: neighbor, pink: within polygon; green bbox: validated object
image image

Related link

TIER IV INTERNAL LINK

Tests performed

Tested by logging_simulator

  • green points: neighbor points
  • pink points: points within object shape
  • orange bbox: non-validated centerpoint result
    Screenshot from 2023-10-17 10-39-58

CPU usage comparison: there was not significant change in cpu usage of obstacle-pointcloud-based-validator-node

2d validation 3d validation
obstacle-pointcloud-based-validator-node-2d_CPU-Percent obstacle-pointcloud-based-validator-node-3d_CPU-Percent

Not applicable.

Effects on system behavior

Not applicable.

Pre-review checklist for the PR author

The PR author must check the checkboxes below when creating the PR.

In-review checklist for the PR reviewers

The PR reviewers must check the checkboxes below before approval.

Post-review checklist for the PR author

The PR author must check the checkboxes below before merging.

  • There are no open discussions or they are tracked via tickets.

After all checkboxes are checked, anyone who has write access can merge the PR.

Summary by CodeRabbit

  • New Feature: Added support for 3D shape-based validation of obstacle point clouds in the ObstaclePointCloudBasedValidator class.
  • New Feature: Introduced a new method addNeighborPointcloud to the Debugger class, allowing users to add neighbor point clouds.
  • New Feature: Added a parameter to the launch file (obstacle_pointcloud_based_validator.launch.xml) to choose between 2D and 3D validation methods.
  • Documentation: Updated documentation for the ObstaclePointCloudBasedValidator class to reflect the changes and provide usage instructions.

@badai-nguyen badai-nguyen requested a review from yukke42 October 17, 2023 02:35
@github-actions github-actions bot added the component:perception Advanced sensor data processing and environment understanding. (auto-assigned) label Oct 17, 2023
@badai-nguyen badai-nguyen force-pushed the fix/add_3d_point_based_validator branch from 6a8448b to d5b7bed Compare October 17, 2023 02:45
@badai-nguyen badai-nguyen marked this pull request as ready for review October 17, 2023 05:10
@yukkysaito
Copy link
Contributor

I'll review this 👍

Comment on lines 114 to 190
void ObstaclePointCloudBasedValidator::on3dObjectsAndObstaclePointCloud(
const autoware_auto_perception_msgs::msg::DetectedObjects::ConstSharedPtr & input_objects,
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & input_obstacle_pointcloud)
{
autoware_auto_perception_msgs::msg::DetectedObjects output, removed_objects;
output.header = input_objects->header;
removed_objects.header = input_objects->header;

// Transform to pointcloud frame
autoware_auto_perception_msgs::msg::DetectedObjects transformed_objects;
if (!object_recognition_utils::transformObjects(
*input_objects, input_obstacle_pointcloud->header.frame_id, tf_buffer_,
transformed_objects)) {
return;
}

// Convert to PCL
pcl::PointCloud<pcl::PointXYZ>::Ptr obstacle_pointcloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*input_obstacle_pointcloud, *obstacle_pointcloud);
if (obstacle_pointcloud->empty()) {
return;
}

// Create Kd-tree to search neighbor pointcloud to reduce cost
pcl::search::Search<pcl::PointXYZ>::Ptr kdtree =
pcl::make_shared<pcl::search::KdTree<pcl::PointXYZ>>(false);
kdtree->setInputCloud(obstacle_pointcloud);
for (size_t i = 0; i < transformed_objects.objects.size(); ++i) {
const auto & transformed_object = transformed_objects.objects.at(i);
const auto object_label_id = transformed_object.classification.front().label;
const auto & object = input_objects->objects.at(i);
const auto & transformed_object_position =
transformed_object.kinematics.pose_with_covariance.pose.position;
const auto search_radius = getMaxRadius3D(transformed_object);
if (!search_radius) {
output.objects.push_back(object);
continue;
}
// Search neighbor pointcloud to reduce cost
pcl::PointCloud<pcl::PointXYZ>::Ptr neighbor_pointcloud(new pcl::PointCloud<pcl::PointXYZ>);
std::vector<int> indices;
std::vector<float> distances;
pcl::PointXYZ trans_obj_position_pcl;
trans_obj_position_pcl.x = transformed_object_position.x;
trans_obj_position_pcl.y = transformed_object_position.y;
trans_obj_position_pcl.z = transformed_object_position.z;
kdtree->radiusSearch(trans_obj_position_pcl, search_radius.value(), indices, distances);
for (const auto & index : indices) {
neighbor_pointcloud->push_back(obstacle_pointcloud->at(index));
}

if (debugger_) debugger_->addNeighborPointcloud(neighbor_pointcloud);
// Filter object that have few pointcloud in them
const auto num = getPointCloudNumWithinShape(transformed_object, neighbor_pointcloud);
const auto object_distance =
std::hypot(transformed_object_position.x, transformed_object_position.y);
size_t min_pointcloud_num = std::clamp(
static_cast<size_t>(
points_num_threshold_param_.min_points_and_distance_ratio.at(object_label_id) /
object_distance +
0.5f),
static_cast<size_t>(points_num_threshold_param_.min_points_num.at(object_label_id)),
static_cast<size_t>(points_num_threshold_param_.max_points_num.at(object_label_id)));
if (num) {
(min_pointcloud_num <= num.value()) ? output.objects.push_back(object)
: removed_objects.objects.push_back(object);
} else {
output.objects.push_back(object);
}
}
objects_pub_->publish(output);
if (debugger_) {
debugger_->publishRemovedObjects(removed_objects);
debugger_->publishNeighborPointcloud(input_obstacle_pointcloud->header);
debugger_->publishPointcloudWithinPolygon(input_obstacle_pointcloud->header);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Since most of them are the same as callback functions of XY-plane, callback functions may be common.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yukkysaito thank you for your comment. I changed at e3cbf6c

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm sorry, I didn't communicate it well.
It was a little different from my image.

Most parts of the callback function are the same for 2D and 3D, so I would be happy if you could abstract and absorb only the parts that make a difference in the interface (using template, function pointer, etc.). If it is difficult, it might be better to have separate callbacks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yukkysaito I am sorry for late response. Currently, I did not find the efficient way to refactor as your comment yet, so I would like revert to the separate callbacks way first. I will consider to refactor this ASAP in another PR.

Comment on lines 172 to 173
points_num_threshold_param_.min_points_and_distance_ratio.at(object_label_id) /
object_distance +
Copy link
Contributor

Choose a reason for hiding this comment

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

The formula here is correct in 2D, but incorrect in 3D.
I don't think it will be a big problem with the 2D formula since it is after height crop, but you should leave it in the comments just in case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yukkysaito
IMO:

  • Since this is to adapt validation threshold as pointcloud density decreasing as far distance so the formular should be common for 2D and 3D. The min_points_num and max_points_num might be better changing for 2D and 3D.
  • The big difference happens when vehicle is in front of a up/down slope and the LiDAR resolution are largely changed in vertical axis.
  • As you mentioned, since we have height crop so I will leave it as is.

Copy link
Contributor

Choose a reason for hiding this comment

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

@badai-nguyen I agree.
Could you please leave a light comment in the code? 🙏

@github-actions
Copy link

github-actions bot commented Oct 17, 2023

Image description CodeRabbit

Walkthrough

The changes introduce support for 3D shape-based validation of obstacle point clouds in the ObstaclePointCloudBasedValidator class. A new method addNeighborPointcloud is added to the Debugger class. Additionally, a new parameter called "using_2d_validator" is added to the launch file, allowing users to choose between the existing 2D validation method and the new 3D validation method.

Changes

File Summary
perception/detected_object_validation/include/obstacle_pointcloud_based_validator/debugger.hpp Adds a new method addNeighborPointcloud to the Debugger class that adds each point in the input cloud to the neighbor_pointcloud_ member variable.
perception/detected_object_validation/include/obstacle_pointcloud_based_validator/obstacle_pointcloud_based_validator.hpp Modifies existing functions and adds a new function on3dObjectsAndObstaclePointCloud to the ObstaclePointCloudBasedValidator class. Introduces a new member variable using_2d_validator_.
perception/detected_object_validation/launch/obstacle_pointcloud_based_validator.launch.xml Adds a new parameter "using_2d_validator" with a default value of "true" to the launch file, allowing users to choose between the 2D and 3D validation methods.

🐇📝 Here come the changes,
3D validation, expanding ranges.
Debugger gets a new method,
Adding points to neighbor's bed.
Launch file gains a parameter,
Choose 2D or 3D, it's your prerogative, remember!


Uplevel your code reviews with CodeRabbit Pro

CodeRabbit Pro

If you like this project, please support us by purchasing the Pro version. The Pro version has advanced context, superior noise reduction and several proprietary improvements compared to the open source version. Moreover, CodeRabbit Pro is free for open source projects.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Image description CodeRabbit

Commits Files that changed from the base of the PR and between 738c376 and d5b7bed commits.
Files selected (4)
  • perception/detected_object_validation/include/obstacle_pointcloud_based_validator/debugger.hpp (1)
  • perception/detected_object_validation/include/obstacle_pointcloud_based_validator/obstacle_pointcloud_based_validator.hpp (1)
  • perception/detected_object_validation/launch/obstacle_pointcloud_based_validator.launch.xml (1)
  • perception/detected_object_validation/src/obstacle_pointcloud_based_validator.cpp (6)
Files not summarized due to errors (1)
  • perception/detected_object_validation/src/obstacle_pointcloud_based_validator.cpp (diff tokens exceeds limit)
Files skipped from review due to trivial changes (2)
  • perception/detected_object_validation/launch/obstacle_pointcloud_based_validator.launch.xml
  • perception/detected_object_validation/src/obstacle_pointcloud_based_validator.cpp (diff too large)
Review comments generated (2)
  • Review: 2
  • LGTM: 0

Tips

Chat with Image description CodeRabbit Bot (@coderabbitai)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @coderabbitai in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @coderabbitai: ignore anywhere in the PR description to pause further reviews from the bot.

Comment on lines 79 to 84
void addNeighborPointcloud(const pcl::PointCloud<pcl::PointXYZ>::Ptr & input)
{
for (const auto & point : *input) {
neighbor_pointcloud_->push_back(point);
}
}

Choose a reason for hiding this comment

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

Image description CodeRabbit

The addNeighborPointcloud method in the Debugger class is added to add points from an input point cloud to the neighbor_pointcloud_ member variable. However, there are a couple of improvements that can be made:

  1. It would be more efficient to reserve space for the new points in the neighbor_pointcloud_ before adding them. This can be done using the reserve method to avoid unnecessary reallocations.

  2. It's important to check if the input pointer is valid before accessing its contents. This can be done by adding a null check before the loop.

Here's the updated code:

void addNeighborPointcloud(const pcl::PointCloud<pcl::PointXYZ>::Ptr& input)
{
  if (input)
  {
    neighbor_pointcloud_->reserve(neighbor_pointcloud_->size() + input->size());
    for (const auto& point : *input)
    {
      neighbor_pointcloud_->push_back(point);
    }
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

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

@badai-nguyen I think the point is a decent one and we might as well reflect it.

Signed-off-by: badai-nguyen <[email protected]>
Signed-off-by: badai-nguyen <[email protected]>
This reverts commit e3cbf6c.
@github-actions github-actions bot added the type:documentation Creating or refining documentation. (auto-assigned) label Oct 30, 2023
@badai-nguyen badai-nguyen force-pushed the fix/add_3d_point_based_validator branch from 4b6acb9 to 7ad22a7 Compare October 31, 2023 00:42
@badai-nguyen badai-nguyen added the run:build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci) label Nov 13, 2023
Copy link

codecov bot commented Nov 13, 2023

Codecov Report

Attention: 151 lines in your changes are missing coverage. Please review.

Comparison is base (83821d4) 14.78% compared to head (be15671) 14.77%.
Report is 252 commits behind head on main.

Files Patch % Lines
...dation/src/obstacle_pointcloud_based_validator.cpp 0.00% 142 Missing ⚠️
...e/obstacle_pointcloud_based_validator/debugger.hpp 0.00% 5 Missing ⚠️
..._validator/obstacle_pointcloud_based_validator.hpp 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5327      +/-   ##
==========================================
- Coverage   14.78%   14.77%   -0.02%     
==========================================
  Files        1644     1645       +1     
  Lines      113941   114060     +119     
  Branches    35160    35160              
==========================================
  Hits        16849    16849              
- Misses      78136    78255     +119     
  Partials    18956    18956              
Flag Coverage Δ *Carryforward flag
differential 0.00% <0.00%> (?)
total 14.79% <ø> (+<0.01%) ⬆️ Carriedforward from 731e768

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@badai-nguyen
Copy link
Contributor Author

badai-nguyen commented Nov 14, 2023

@yukkysaito I refactored and changed to a single bind function at 731e768. Could you review this PR again?

Copy link
Contributor

@yukkysaito yukkysaito left a comment

Choose a reason for hiding this comment

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

LGTM

Signed-off-by: badai-nguyen <[email protected]>
@badai-nguyen badai-nguyen enabled auto-merge (squash) November 15, 2023 14:29
@badai-nguyen badai-nguyen merged commit a76d360 into autowarefoundation:main Nov 15, 2023
18 of 19 checks passed
takayuki5168 pushed a commit to tier4/autoware.universe that referenced this pull request Nov 22, 2023
…utowarefoundation#5327)

* fix: add 3d validation bind function

Signed-off-by: badai-nguyen <[email protected]>

* fix: check validation point within shape

Signed-off-by: badai-nguyen <[email protected]>

* fix: add 2d validator option param

Signed-off-by: badai-nguyen <[email protected]>

* chore: refactor

Signed-off-by: badai-nguyen <[email protected]>

* chore: refactor

Signed-off-by: badai-nguyen <[email protected]>

* Revert "chore: refactor"

This reverts commit e3cbf6c.

* chore: update docs and param file

Signed-off-by: badai-nguyen <[email protected]>

* refactor: change to abstract class

Signed-off-by: badai-nguyen <[email protected]>

* chore: add maintainer

Signed-off-by: badai-nguyen <[email protected]>

---------

Signed-off-by: badai-nguyen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:perception Advanced sensor data processing and environment understanding. (auto-assigned) run:build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci) type:documentation Creating or refining documentation. (auto-assigned)
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

2 participants