Skip to content

Commit c18f321

Browse files
feat(autoware_crop_box_filter): porting autoware_crop_box_filter, autoware_crop_box_filter, add readme: v0.1
Signed-off-by: liuXinGangChina <lxg19892021@gmail.com>
1 parent 3a62c18 commit c18f321

File tree

3 files changed

+111
-38
lines changed

3 files changed

+111
-38
lines changed
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# autoware_crop_box_filter
2+
3+
## Overview
4+
5+
The `autoware_crop_box_filter` is a package that crops the input pointcloud to a specified bounding box. This is useful for reducing the computational load and improving the performance of the system.
6+
7+
## Design
8+
9+
The `autoware_crop_box_filter` is implemented as a autoware core node that subscribes to the input pointcloud, and publishes the filtered pointcloud. The bounding box is specified using the `min_point` and `max_point` parameters.
10+
11+
## Inputs / Outputs
12+
13+
### Input
14+
15+
| Name | Type | Description |
16+
| ----------------- | ------------------------------- | ----------------- |
17+
| `~/input/points` | `sensor_msgs::msg::PointCloud2` | reference points |
18+
19+
### Output
20+
21+
| Name | Type | Description |
22+
| ----------------- | ------------------------------- | --------------- |
23+
| `~/output/points` | `sensor_msgs::msg::PointCloud2` | filtered points |
24+
| `~/crop_box_polygon` | `geometry_msgs::msg::PolygonStamped` | bounding box polygon |
25+
26+
## Parameters
27+
28+
### Launch file Parameters
29+
30+
| Name | Type | Default Value | Description |
31+
| ------------------ | ------ | ------------- | ------------------------------------- |
32+
| `input_frame` | string | " " | the frame id in which filtering is performed |
33+
| `output_frame` | string | " " | output frame id of the filtered points |
34+
| `input_pointcloud_frame` | string | " " | frame id of input pointcloud |
35+
| `max_queue_size` | int | 5 | max buffer size of input/output topics |
36+
| `crop_box_filter_param_file` | string | " " | path to the parameter file for the node |
37+
38+
39+
### Node Parameters
40+
41+
| Name | Type | Default Value | Description |
42+
| ------------------ | ------ | ------------- | ------------------------------------- |
43+
| `min_x` | double | -5.0 | minimum x value of the crop box |
44+
| `min_y` | double | -5.0 | minimum y value of the crop box |
45+
| `min_z` | double | -5.0 | minimum z value of the crop box |
46+
| `max_x` | double | 5.0 | maximum x value of the crop box |
47+
| `max_y` | double | 5.0 | maximum y value of the crop box |
48+
| `max_z` | double | 5.0 | maximum z value of the crop box |
49+
| `negative` | bool | true | if true, points inside the box are removed, otherwise points outside the box are removed |
50+
51+
## Usage
52+
53+
### 1.publish static tf from input pointcloud to target frame that is used for filtering
54+
55+
```cpp
56+
ros2 run tf2_ros static_transform_publisher 2.0 3.2 1.3 0 0 0 1 velodyne_top_base_link base_link
57+
```
58+
59+
### 2.launch node
60+
61+
```cpp
62+
ros2 launch autoware_crop_box_filter crop_box_filter_node.launch.xml
63+
```
64+
65+
### 3. launch rviz2 and AWSIM

sensing/autoware_crop_box_filter/include/autoware/crop_box_filter/crop_box_filter_node.hpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright(c) 2025 AutoCore Technology (Nanjing) Co., Ltd. All rights reserved.
2-
2+
//
33
// Copyright 2020 Tier IV, Inc.
44
//
55
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -57,6 +57,7 @@
5757

5858
#include <geometry_msgs/msg/polygon_stamped.hpp>
5959
#include <sensor_msgs/msg/point_cloud2.hpp>
60+
#include <sensor_msgs/point_cloud2_iterator.hpp>
6061

6162
#include <autoware_utils/ros/debug_publisher.hpp>
6263
#include <autoware_utils/ros/managed_transform_buffer.hpp>
@@ -65,7 +66,10 @@
6566

6667
#include <autoware/point_types/types.hpp>
6768

69+
#include <memory>
6870
#include <vector>
71+
#include <string>
72+
#include <utility>
6973

7074
namespace autoware::crop_box_filter
7175
{
@@ -81,7 +85,7 @@ using PointCloudConstPtr = PointCloud::ConstPtr;
8185

8286
private:
8387

84-
// member variable declearation & definitions *************************************
88+
// member variable declaration & definitions *************************************
8589

8690
/** \brief The managed transform buffer. */
8791
std::unique_ptr<autoware_utils::ManagedTransformBuffer> managed_tf_buffer_{nullptr};
@@ -123,7 +127,7 @@ using PointCloudConstPtr = PointCloud::ConstPtr;
123127
/** \brief Parameter service callback result : needed to be hold */
124128
OnSetParametersCallbackHandle::SharedPtr set_param_res_;
125129

126-
// publiser and subscriber declaration *********************
130+
// publisher and subscriber declaration *********************
127131

128132
/** \brief The input PointCloud2 subscriber. */
129133
rclcpp::Subscription<PointCloud2>::SharedPtr sub_input_;

sensing/autoware_crop_box_filter/src/crop_box_filter_node.cpp

+39-35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright(c) 2025 AutoCore Technology (Nanjing) Co., Ltd. All rights reserved.
2-
2+
//
33
// Copyright 2024 TIER IV, Inc.
44
//
55
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -52,11 +52,10 @@
5252
*/
5353

5454
#include "autoware/crop_box_filter/crop_box_filter_node.hpp"
55-
56-
#include <sensor_msgs/point_cloud2_iterator.hpp>
57-
5855
#include <memory>
5956
#include <vector>
57+
#include <string>
58+
#include <utility>
6059

6160
namespace autoware::crop_box_filter
6261
{
@@ -191,32 +190,7 @@ CropBoxFilter::CropBoxFilter(const rclcpp::NodeOptions & node_options)
191190

192191
void CropBoxFilter::pointcloud_callback(const PointCloud2ConstPtr cloud)
193192
{
194-
// chechk if the pointcloud is valid
195-
if (
196-
!is_data_layout_compatible_with_point_xyzircaedt(*cloud) &&
197-
!is_data_layout_compatible_with_point_xyzirc(*cloud))
198-
{
199-
RCLCPP_ERROR(
200-
get_logger(),
201-
"The pointcloud layout is not compatible with PointXYZIRCAEDT or PointXYZIRC. Aborting");
202-
203-
if (is_data_layout_compatible_with_point_xyziradrt(*cloud)) {
204-
RCLCPP_ERROR(
205-
get_logger(),
206-
"The pointcloud layout is compatible with PointXYZIRADRT. You may be using legacy "
207-
"code/data");
208-
}
209-
210-
if (is_data_layout_compatible_with_point_xyzi(*cloud)) {
211-
RCLCPP_ERROR(
212-
get_logger(),
213-
"The pointcloud layout is compatible with PointXYZI. You may be using legacy "
214-
"code/data");
215-
}
216-
217-
return;
218-
}
219-
193+
// check whether the pointcloud is valid
220194
if (!is_valid(cloud)) {
221195
RCLCPP_ERROR(this->get_logger(), "[input_pointcloud_callback] Invalid input pointcloud!");
222196
return;
@@ -249,27 +223,30 @@ void CropBoxFilter::pointcloud_callback(const PointCloud2ConstPtr cloud)
249223
for (size_t global_offset = 0; global_offset + cloud->point_step <= cloud->data.size();
250224
global_offset += cloud->point_step)
251225
{
226+
// extract point data from point cloud data buffer
252227
Eigen::Vector4f point;
253-
Eigen::Vector4f point_preprocessed;
228+
254229
std::memcpy(&point[0], &cloud->data[global_offset + x_offset], sizeof(float));
255230
std::memcpy(&point[1], &cloud->data[global_offset + y_offset], sizeof(float));
256231
std::memcpy(&point[2], &cloud->data[global_offset + z_offset], sizeof(float));
257232
point[3] = 1;
258-
point_preprocessed[3] = 1;
259233

260234
if (!std::isfinite(point[0]) || !std::isfinite(point[1]) || !std::isfinite(point[2])) {
261235
skipped_count++;
262236
continue;
263237
}
264238

239+
// preprocess point for filtering
240+
Eigen::Vector4f point_preprocessed = point;
241+
265242
// apply pre-transform if needed
266243
if (need_preprocess_transform_) {
267244
point_preprocessed = eigen_transform_preprocess_ * point;
268245
}
269246

270-
bool point_is_inside = point[2] > param_.min_z && point[2] < param_.max_z &&
271-
point[1] > param_.min_y && point[1] < param_.max_y &&
272-
point[0] > param_.min_x && point[0] < param_.max_x;
247+
bool point_is_inside = point_preprocessed[2] > param_.min_z && point_preprocessed[2] < param_.max_z &&
248+
point_preprocessed[1] > param_.min_y && point_preprocessed[1] < param_.max_y &&
249+
point_preprocessed[0] > param_.min_x && point_preprocessed[0] < param_.max_x;
273250
if ((!param_.negative && point_is_inside) || (param_.negative && !point_is_inside)) {
274251

275252
// apply post-transform if needed
@@ -627,6 +604,33 @@ bool CropBoxFilter::is_data_layout_compatible_with_point_xyzircaedt(const PointC
627604

628605
bool CropBoxFilter::is_valid( const PointCloud2ConstPtr & cloud)
629606
{
607+
// firstly check the fields of the point cloud
608+
if (
609+
!is_data_layout_compatible_with_point_xyzircaedt(*cloud) &&
610+
!is_data_layout_compatible_with_point_xyzirc(*cloud))
611+
{
612+
RCLCPP_ERROR(
613+
get_logger(),
614+
"The pointcloud layout is not compatible with PointXYZIRCAEDT or PointXYZIRC. Aborting");
615+
616+
if (is_data_layout_compatible_with_point_xyziradrt(*cloud)) {
617+
RCLCPP_ERROR(
618+
get_logger(),
619+
"The pointcloud layout is compatible with PointXYZIRADRT. You may be using legacy "
620+
"code/data");
621+
}
622+
623+
if (is_data_layout_compatible_with_point_xyzi(*cloud)) {
624+
RCLCPP_ERROR(
625+
get_logger(),
626+
"The pointcloud layout is compatible with PointXYZI. You may be using legacy "
627+
"code/data");
628+
}
629+
630+
return false;
631+
}
632+
633+
// secondly, verify the total size of the point cloud
630634
if (cloud->width * cloud->height * cloud->point_step != cloud->data.size()) {
631635
RCLCPP_WARN(
632636
this->get_logger(),

0 commit comments

Comments
 (0)