feat(crop_box_filter): simplify validation logic for input point cloud#875
Conversation
…ve redundant functions Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…ation logic Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…improve clarity Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…emoving redundant lambda function Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…stamp handling in validation logic Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…nt ownership Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
… xyz field and data size checks Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
|
Thank you for contributing to the Autoware project! 🚧 If your pull request is in progress, switch it to draft mode. Please ensure:
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #875 +/- ##
==========================================
+ Coverage 50.16% 50.34% +0.18%
==========================================
Files 356 358 +2
Lines 22892 22780 -112
Branches 10139 10120 -19
==========================================
- Hits 11483 11468 -15
+ Misses 10305 10205 -100
- Partials 1104 1107 +3
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
mojomex
left a comment
There was a problem hiding this comment.
I left some small nit-picky comments, but feel free to leave some un-addressed. Merge at your convenience.
| namespace autoware::crop_box_filter | ||
| { | ||
|
|
||
| static ValidationResult validate_xyz_fields(const PointCloud2ConstPtr & cloud) |
There was a problem hiding this comment.
(nit) More idiomatic would be to pass a const& PointCloud2 or const PointCloud2 * const since the function does not care about ownership.
|
|
||
| static ValidationResult validate_data_size(const PointCloud2ConstPtr & cloud) | ||
| { | ||
| if (cloud->width * cloud->height * cloud->point_step != cloud->data.size()) { |
There was a problem hiding this comment.
(optional / discussion) Not sure what PointCloud2 best practice is here. Technically, <= would be enough here. Foxglove still processes pointclouds where width*height*point_step < data.size() and shows a warning icon.
There was a problem hiding this comment.
Thanks for the insightful feedback.
As long as data.size() exceeds cloud->width * cloud->height * cloud->point_step, the crop box filter should process the data without any issues. Thus, I think it's reasonable to allow such point clouds.
Fixed in: 2c225e2
| { | ||
| if (cloud->width * cloud->height * cloud->point_step != cloud->data.size()) { | ||
| std::ostringstream oss; | ||
| oss << "Invalid PointCloud (data = " << cloud->data.size() << ", width = " << cloud->width |
There was a problem hiding this comment.
| oss << "Invalid PointCloud (data = " << cloud->data.size() << ", width = " << cloud->width | |
| oss << "Invalid PointCloud (data.size = " << cloud->data.size() << ", width = " << cloud->width |
There was a problem hiding this comment.
It looks more concrete.
addressed e48e8b9
| namespace autoware::crop_box_filter | ||
| { | ||
|
|
||
| struct ValidationResult |
There was a problem hiding this comment.
(nit) Not sure if tl is easily accessible in autoware_crop_box_filter, but parts of Autoware already use tl::expected<T, E> as a backport of std::expected from C++23, which is more idiomatic.
There was a problem hiding this comment.
Thank you for the suggestion.
I didn't know about tl::expected, so I'm glad to learn about it.
In this case, to keep the implementation simple, I would like to keep the current implementation. However, I will keep the concept of tl::expected in mind.
|
|
||
| int main(int argc, char ** argv) | ||
| { | ||
| rclcpp::init(0, nullptr); |
There was a problem hiding this comment.
rclcpp should not be needed here - message types work without rclcpp.
Once removed, the main function shouldn't be needed altogether since GTest usually auto-discovers tests.
There was a problem hiding this comment.
Thank you for pointing that out!
I totally overlooked it.
It's addressed in: be22678
Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
sasakisasaki
left a comment
There was a problem hiding this comment.
Reviewed. Readability is now much higher now. Thank you!
I left some minor comments 👍
| namespace autoware::crop_box_filter | ||
| { | ||
|
|
||
| static ValidationResult validate_xyz_fields(const PointCloud2ConstPtr & cloud) |
There was a problem hiding this comment.
For making the role explicit 👍
| static ValidationResult validate_xyz_fields(const PointCloud2ConstPtr & cloud) | |
| static ValidationResult contains_xyz_fields(const PointCloud2ConstPtr & cloud) |
There was a problem hiding this comment.
Since the return value is ValidationResult, not the bool expected from a function called contains_..., I'm not sure on this one 🤔
There was a problem hiding this comment.
Thank you for your comments!
In this case, validate_xyz_fields() checks if its fields have a data type of sensor_msgs::msg::PointField::FLOAT32. So I believe validate is more appropriate in this case.
|
|
||
| ValidationResult validate_pointcloud2(const PointCloud2ConstPtr & cloud) | ||
| { | ||
| const ValidationResult xyz_validation_result = validate_xyz_fields(cloud); |
There was a problem hiding this comment.
If above my proposal is accepted.
| const ValidationResult xyz_validation_result = validate_xyz_fields(cloud); | |
| const ValidationResult xyz_validation_result = contains_xyz_fields(cloud); |
| else if (field.name == "z") | ||
| has_z = true; | ||
| } |
There was a problem hiding this comment.
Although the number of loops is not huge
| else if (field.name == "z") | |
| has_z = true; | |
| } | |
| else if (field.name == "z") | |
| has_z = true; | |
| if (has_x && has_y && has_z) break; | |
| } |
There was a problem hiding this comment.
Thank you for suggestion!
It looks better in the perspective of this loop's objective.
Addressed in b1a37e9
…tCloud2 Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…g shared_ptr usage Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…er than comparison Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…elds in PointCloud2 Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
…filter.cpp Signed-off-by: Takahisa.Ishikawa <takahisa.ishikawa@tier4.jp>
Description
Simplify the validation criteria for input point clouds and extract the validation logic into
crop_box_filter.cpp.Background
The original
is_valid()method inCropBoxFilterchecked whether the inputPointCloud2matched specific Autoware point type layouts (e.g.,PointXYZIRCAEDT,PointXYZIRC). This was overly strict; the crop box filter only requiresx,y,zasFLOAT32fields and a consistent data size to function correctly.Changes
src/crop_box_filter.hpp/crop_box_filter.cpp: Newly added.validate_pointcloud2()logic.crop_box_filter_node.cpp: Removed ~230 lines.is_valid()and all fouris_data_layout_compatible_with_point_*()methods.pointcloud_callback()to callvalidate_pointcloud2().test/test_crop_box_filter.cpp: Added new unit tests forvalidate_pointcloud2().Related links
Parent Issue:
How was this PR tested?
colcon build --packages-select autoware_crop_box_filtersucceeded.test_crop_box_filter(new): 3/3 cases passed — accepts xyz-only, accepts XYZIRC, and rejects missing 'z'.test_crop_box_filter_node(existing): No regressions.Notes for reviewers
PointXYZIRC. The new code only requiresx,y,zasFLOAT32fields, which is the minimum the filter needs. This makes the node compatible with a broader range of point cloud types.crop_box_filter.hppfor now, but I plan to extract more crop box filter logic into it in a future pull request.Interface changes
None.