Skip to content

Commit eeab1b2

Browse files
committed
fix: using empty padding field
Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp>
1 parent d7bd69f commit eeab1b2

File tree

2 files changed

+188
-60
lines changed

2 files changed

+188
-60
lines changed

perception/occupancy_grid_map_outlier_filter/include/occupancy_grid_map_outlier_filter/occupancy_grid_map_outlier_filter_nodelet.hpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ class RadiusSearch2dFilter
5656
const PclPointCloud & input, const Pose & pose, PclPointCloud & output,
5757
PclPointCloud & outlier);
5858
void filter(
59-
const PclPointCloud & high_conf_input, const PclPointCloud & low_conf_input, const Pose & pose,
60-
PclPointCloud & output, PclPointCloud & outlier);
59+
const PointCloud2 & high_conf_input, const PointCloud2 & low_conf_input, const Pose & pose,
60+
PointCloud2 & output, PointCloud2 & outlier);
6161

6262
private:
6363
float search_radius_;
@@ -79,22 +79,25 @@ class OccupancyGridMapOutlierFilterComponent : public rclcpp::Node
7979
const PointCloud2::ConstSharedPtr & input_pointcloud);
8080
void filterByOccupancyGridMap(
8181
const OccupancyGrid & occupancy_grid_map, const PointCloud2 & pointcloud,
82-
PclPointCloud & high_confidence, PclPointCloud & low_confidence, PclPointCloud & out_ogm);
82+
PointCloud2 & high_confidence, PointCloud2 & low_confidence, PointCloud2 & out_ogm);
8383
void splitPointCloudFrontBack(
8484
const PointCloud2::ConstSharedPtr & input_pc, PointCloud2 & front_pc, PointCloud2 & behind_pc);
85+
void initializerPointCloud2(const PointCloud2 & input, PointCloud2 & output);
86+
void finalizePointCloud2(const PointCloud2 & input, PointCloud2 & output);
87+
void concatPointCloud2(PointCloud2 & output, const PointCloud2 & input);
8588

8689
private:
8790
class Debugger
8891
{
8992
public:
9093
explicit Debugger(OccupancyGridMapOutlierFilterComponent & node);
91-
void publishOutlier(const PclPointCloud & input, const Header & header);
92-
void publishHighConfidence(const PclPointCloud & input, const Header & header);
93-
void publishLowConfidence(const PclPointCloud & input, const Header & header);
94+
void publishOutlier(const PointCloud2 & input, const Header & header);
95+
void publishHighConfidence(const PointCloud2 & input, const Header & header);
96+
void publishLowConfidence(const PointCloud2 & input, const Header & header);
9497

9598
private:
9699
void transformToBaseLink(
97-
const PclPointCloud & input, const Header & header, PointCloud2 & output);
100+
const PointCloud2 & input, const Header & header, PointCloud2 & output);
98101
rclcpp::Publisher<PointCloud2>::SharedPtr outlier_pointcloud_pub_;
99102
rclcpp::Publisher<PointCloud2>::SharedPtr low_confidence_pointcloud_pub_;
100103
rclcpp::Publisher<PointCloud2>::SharedPtr high_confidence_pointcloud_pub_;

perception/occupancy_grid_map_outlier_filter/src/occupancy_grid_map_outlier_filter_nodelet.cpp

+178-53
Original file line numberDiff line numberDiff line change
@@ -147,34 +147,45 @@ void RadiusSearch2dFilter::filter(
147147
}
148148

149149
void RadiusSearch2dFilter::filter(
150-
const PclPointCloud & high_conf_input, const PclPointCloud & low_conf_input, const Pose & pose,
151-
PclPointCloud & output, PclPointCloud & outlier)
150+
const PointCloud2 & high_conf_xyz_cloud, const PointCloud2 & low_conf_xyz_cloud,
151+
const Pose & pose, PointCloud2 & output, PointCloud2 & outlier)
152152
{
153-
const auto & high_conf_xyz_cloud = high_conf_input;
154-
const auto & low_conf_xyz_cloud = low_conf_input;
155153
// check the limit points number
156-
if (low_conf_xyz_cloud.points.size() > max_filter_points_nb_) {
154+
if (low_conf_xyz_cloud.width > max_filter_points_nb_) {
157155
RCLCPP_WARN(
158156
rclcpp::get_logger("OccupancyGridMapOutlierFilterComponent"),
159157
"Skip outlier filter since too much low_confidence pointcloud!");
160158
return;
161159
}
162-
160+
int x_offset = low_conf_xyz_cloud.fields[pcl::getFieldIndex(low_conf_xyz_cloud, "x")].offset;
161+
int y_offset = low_conf_xyz_cloud.fields[pcl::getFieldIndex(low_conf_xyz_cloud, "y")].offset;
162+
int point_step = low_conf_xyz_cloud.point_step;
163163
pcl::PointCloud<pcl::PointXY>::Ptr xy_cloud(new pcl::PointCloud<pcl::PointXY>);
164-
xy_cloud->points.resize(low_conf_xyz_cloud.points.size() + high_conf_xyz_cloud.points.size());
165-
for (size_t i = 0; i < low_conf_xyz_cloud.points.size(); ++i) {
166-
xy_cloud->points[i].x = low_conf_xyz_cloud.points[i].x;
167-
xy_cloud->points[i].y = low_conf_xyz_cloud.points[i].y;
164+
xy_cloud->points.resize(low_conf_xyz_cloud.width + high_conf_xyz_cloud.width);
165+
for (size_t i = 0; i < low_conf_xyz_cloud.width; ++i) {
166+
std::memcpy(
167+
&xy_cloud->points[i].x, &low_conf_xyz_cloud.data[i * point_step + x_offset], sizeof(float));
168+
std::memcpy(
169+
&xy_cloud->points[i].y, &low_conf_xyz_cloud.data[i * point_step + y_offset], sizeof(float));
168170
}
169-
for (size_t i = low_conf_xyz_cloud.points.size(); i < xy_cloud->points.size(); ++i) {
170-
xy_cloud->points[i].x = high_conf_xyz_cloud.points[i - low_conf_xyz_cloud.points.size()].x;
171-
xy_cloud->points[i].y = high_conf_xyz_cloud.points[i - low_conf_xyz_cloud.points.size()].y;
171+
172+
for (size_t i = low_conf_xyz_cloud.width; i < xy_cloud->points.size(); ++i) {
173+
size_t high_conf_xyz_cloud_index = i - low_conf_xyz_cloud.width;
174+
std::memcpy(
175+
&xy_cloud->points[i].x,
176+
&high_conf_xyz_cloud.data[high_conf_xyz_cloud_index * point_step + x_offset], sizeof(float));
177+
std::memcpy(
178+
&xy_cloud->points[i].y,
179+
&high_conf_xyz_cloud.data[high_conf_xyz_cloud_index * point_step + y_offset], sizeof(float));
172180
}
173181

174182
std::vector<int> k_indices(xy_cloud->points.size());
175183
std::vector<float> k_distances(xy_cloud->points.size());
176184
kd_tree_->setInputCloud(xy_cloud);
177-
for (size_t i = 0; i < low_conf_xyz_cloud.points.size(); ++i) {
185+
186+
size_t output_size = 0;
187+
size_t outlier_size = 0;
188+
for (size_t i = 0; i < low_conf_xyz_cloud.data.size() / low_conf_xyz_cloud.point_step; ++i) {
178189
const float distance =
179190
std::hypot(xy_cloud->points[i].x - pose.position.x, xy_cloud->points[i].y - pose.position.y);
180191
const int min_points_threshold = std::min(
@@ -184,11 +195,20 @@ void RadiusSearch2dFilter::filter(
184195
kd_tree_->radiusSearch(i, search_radius_, k_indices, k_distances, min_points_threshold);
185196

186197
if (min_points_threshold <= points_num) {
187-
output.points.push_back(low_conf_xyz_cloud.points.at(i));
198+
std::memcpy(
199+
&output.data[output_size], &low_conf_xyz_cloud.data[i * low_conf_xyz_cloud.point_step],
200+
low_conf_xyz_cloud.point_step);
201+
output_size += low_conf_xyz_cloud.point_step;
188202
} else {
189-
outlier.points.push_back(low_conf_xyz_cloud.points.at(i));
203+
std::memcpy(
204+
&outlier.data[outlier_size], &low_conf_xyz_cloud.data[i * low_conf_xyz_cloud.point_step],
205+
low_conf_xyz_cloud.point_step);
206+
outlier_size += low_conf_xyz_cloud.point_step;
190207
}
191208
}
209+
210+
output.data.resize(output_size);
211+
outlier.data.resize(outlier_size);
192212
}
193213

194214
OccupancyGridMapOutlierFilterComponent::OccupancyGridMapOutlierFilterComponent(
@@ -239,21 +259,50 @@ OccupancyGridMapOutlierFilterComponent::OccupancyGridMapOutlierFilterComponent(
239259
void OccupancyGridMapOutlierFilterComponent::splitPointCloudFrontBack(
240260
const PointCloud2::ConstSharedPtr & input_pc, PointCloud2 & front_pc, PointCloud2 & behind_pc)
241261
{
242-
PclPointCloud tmp_behind_pc;
243-
PclPointCloud tmp_front_pc;
244-
for (sensor_msgs::PointCloud2ConstIterator<float> x(*input_pc, "x"), y(*input_pc, "y"),
245-
z(*input_pc, "z"), intensity(*input_pc, "intensity");
246-
x != x.end(); ++x, ++y, ++z, ++intensity) {
247-
if (*x < 0.0) {
248-
tmp_behind_pc.push_back(pcl::PointXYZI(*x, *y, *z, *intensity));
262+
int x_offset = input_pc->fields[pcl::getFieldIndex(*input_pc, "x")].offset;
263+
int point_step = input_pc->point_step;
264+
265+
front_pc.data.resize(input_pc->data.size());
266+
behind_pc.data.resize(input_pc->data.size());
267+
front_pc.point_step = input_pc->point_step;
268+
behind_pc.point_step = input_pc->point_step;
269+
front_pc.fields = input_pc->fields;
270+
behind_pc.fields = input_pc->fields;
271+
front_pc.height = input_pc->height;
272+
behind_pc.height = input_pc->height;
273+
274+
size_t front_count = 0;
275+
size_t behind_count = 0;
276+
277+
for (size_t global_offset = 0; global_offset < input_pc->data.size();
278+
global_offset += point_step) {
279+
float x;
280+
std::memcpy(&x, &input_pc->data[global_offset + x_offset], sizeof(float));
281+
if (x < 0.0) {
282+
std::memcpy(
283+
&behind_pc.data[behind_count * point_step], &input_pc->data[global_offset],
284+
input_pc->point_step);
285+
behind_count++;
249286
} else {
250-
tmp_front_pc.push_back(pcl::PointXYZI(*x, *y, *z, *intensity));
287+
std::memcpy(
288+
&front_pc.data[front_count * point_step], &input_pc->data[global_offset],
289+
input_pc->point_step);
290+
front_count++;
251291
}
252292
}
253-
pcl::toROSMsg(tmp_front_pc, front_pc);
254-
pcl::toROSMsg(tmp_behind_pc, behind_pc);
293+
front_pc.data.resize(front_count * point_step);
294+
front_pc.width = front_count;
295+
front_pc.row_step = front_count * front_pc.point_step;
255296
front_pc.header = input_pc->header;
297+
front_pc.is_bigendian = input_pc->is_bigendian;
298+
front_pc.is_dense = input_pc->is_dense;
299+
300+
behind_pc.data.resize(behind_count * point_step);
301+
behind_pc.width = behind_count;
302+
behind_pc.row_step = behind_count * behind_pc.point_step;
256303
behind_pc.header = input_pc->header;
304+
behind_pc.is_bigendian = input_pc->is_bigendian;
305+
behind_pc.is_dense = input_pc->is_dense;
257306
}
258307
void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
259308
const OccupancyGrid::ConstSharedPtr & input_ogm, const PointCloud2::ConstSharedPtr & input_pc)
@@ -264,6 +313,10 @@ void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
264313
PointCloud2 input_front_pc{};
265314
PointCloud2 input_behind_pc{};
266315
PointCloud2 ogm_frame_input_behind_pc{};
316+
PointCloud2 ogm_frame_pc;
317+
PointCloud2 input_front_pc;
318+
PointCloud2 input_behind_pc;
319+
PointCloud2 ogm_frame_input_behind_pc;
267320
splitPointCloudFrontBack(input_pc, input_front_pc, input_behind_pc);
268321
if (
269322
!transformPointcloud(input_front_pc, *tf2_, input_ogm->header.frame_id, ogm_frame_pc) ||
@@ -272,33 +325,50 @@ void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
272325
return;
273326
}
274327
// Occupancy grid map based filter
275-
PclPointCloud high_confidence_pc{};
276-
PclPointCloud low_confidence_pc{};
277-
PclPointCloud out_ogm_pc{};
278-
PclPointCloud ogm_frame_behind_pc;
279-
pcl::fromROSMsg(ogm_frame_input_behind_pc, ogm_frame_behind_pc);
328+
PointCloud2 high_confidence_pc{};
329+
PointCloud2 low_confidence_pc{};
330+
PointCloud2 out_ogm_pc{};
331+
initializerPointCloud2(ogm_frame_pc, high_confidence_pc);
332+
initializerPointCloud2(ogm_frame_pc, low_confidence_pc);
333+
initializerPointCloud2(ogm_frame_pc, out_ogm_pc);
334+
// PclPointCloud ogm_frame_behind_pc;
335+
// pcl::fromROSMsg(ogm_frame_input_behind_pc, ogm_frame_behind_pc);
280336
filterByOccupancyGridMap(
281337
*input_ogm, ogm_frame_pc, high_confidence_pc, low_confidence_pc, out_ogm_pc);
282338
// Apply Radius search 2d filter for low confidence pointcloud
283-
PclPointCloud filtered_low_confidence_pc{};
284-
PclPointCloud outlier_pc{};
339+
PointCloud2 filtered_low_confidence_pc{};
340+
PointCloud2 outlier_pc{};
341+
initializerPointCloud2(low_confidence_pc, outlier_pc);
342+
initializerPointCloud2(low_confidence_pc, filtered_low_confidence_pc);
343+
PointCloud2 outlier_pc;
344+
outlier_pc.data.resize(low_confidence_pc.data.size());
345+
outlier_pc.point_step = low_confidence_pc.point_step;
346+
outlier_pc.fields = low_confidence_pc.fields;
347+
outlier_pc.height = 1;
285348
if (radius_search_2d_filter_ptr_) {
286349
auto pc_frame_pose_stamped = getPoseStamped(
287350
*tf2_, input_ogm->header.frame_id, input_pc->header.frame_id, input_ogm->header.stamp);
288351
radius_search_2d_filter_ptr_->filter(
289352
high_confidence_pc, low_confidence_pc, pc_frame_pose_stamped.pose, filtered_low_confidence_pc,
290353
outlier_pc);
291354
} else {
292-
outlier_pc = low_confidence_pc;
355+
std::memcpy(&outlier_pc.data[0], &low_confidence_pc.data[0], low_confidence_pc.data.size());
356+
outlier_pc.data.resize(low_confidence_pc.data.size());
293357
}
294358
// Concatenate high confidence pointcloud from occupancy grid map and non-outlier pointcloud
295-
PclPointCloud concat_pc =
296-
high_confidence_pc + filtered_low_confidence_pc + out_ogm_pc + ogm_frame_behind_pc;
359+
PointCloud2 ogm_frame_filtered_pc{};
360+
concatPointCloud2(ogm_frame_filtered_pc, high_confidence_pc);
361+
concatPointCloud2(ogm_frame_filtered_pc, filtered_low_confidence_pc);
362+
concatPointCloud2(ogm_frame_filtered_pc, out_ogm_pc);
363+
concatPointCloud2(ogm_frame_filtered_pc, ogm_frame_input_behind_pc);
364+
365+
finalizePointCloud2(ogm_frame_pc, ogm_frame_filtered_pc);
366+
finalizePointCloud2(ogm_frame_pc, filtered_low_confidence_pc);
367+
finalizePointCloud2(ogm_frame_pc, outlier_pc);
368+
finalizePointCloud2(ogm_frame_pc, high_confidence_pc);
297369
// Convert to ros msg
298370
{
299-
PointCloud2 ogm_frame_filtered_pc{};
300371
auto base_link_frame_filtered_pc_ptr = std::make_unique<PointCloud2>();
301-
pcl::toROSMsg(concat_pc, ogm_frame_filtered_pc);
302372
ogm_frame_filtered_pc.header = ogm_frame_pc.header;
303373
if (!transformPointcloud(
304374
ogm_frame_filtered_pc, *tf2_, base_link_frame_, *base_link_frame_filtered_pc_ptr)) {
@@ -323,24 +393,82 @@ void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
323393
}
324394
}
325395

396+
void OccupancyGridMapOutlierFilterComponent::initializerPointCloud2(
397+
const PointCloud2 & input, PointCloud2 & output)
398+
{
399+
output.header = input.header;
400+
output.point_step = input.point_step;
401+
output.fields = input.fields;
402+
output.height = input.height;
403+
output.is_bigendian = input.is_bigendian;
404+
output.is_dense = input.is_dense;
405+
output.data.resize(input.data.size());
406+
}
407+
408+
void OccupancyGridMapOutlierFilterComponent::finalizePointCloud2(
409+
const PointCloud2 & input, PointCloud2 & output)
410+
{
411+
output.header = input.header;
412+
output.point_step = input.point_step;
413+
output.fields = input.fields;
414+
output.height = input.height;
415+
output.is_bigendian = input.is_bigendian;
416+
output.is_dense = input.is_dense;
417+
output.width = output.data.size() / output.point_step / output.height;
418+
output.row_step = output.data.size() / output.height;
419+
}
420+
421+
void OccupancyGridMapOutlierFilterComponent::concatPointCloud2(
422+
PointCloud2 & output, const PointCloud2 & input)
423+
{
424+
size_t output_size = output.data.size();
425+
output.data.resize(output.data.size() + input.data.size());
426+
std::memcpy(&output.data[output_size], &input.data[0], input.data.size());
427+
}
326428
void OccupancyGridMapOutlierFilterComponent::filterByOccupancyGridMap(
327429
const OccupancyGrid & occupancy_grid_map, const PointCloud2 & pointcloud,
328-
PclPointCloud & high_confidence, PclPointCloud & low_confidence, PclPointCloud & out_ogm)
430+
PointCloud2 & high_confidence, PointCloud2 & low_confidence, PointCloud2 & out_ogm)
329431
{
330-
for (sensor_msgs::PointCloud2ConstIterator<float> x(pointcloud, "x"), y(pointcloud, "y"),
331-
z(pointcloud, "z"), intensity(pointcloud, "intensity");
332-
x != x.end(); ++x, ++y, ++z, ++intensity) {
333-
const auto cost = getCost(occupancy_grid_map, *x, *y);
432+
int x_offset = pointcloud.fields[pcl::getFieldIndex(pointcloud, "x")].offset;
433+
int y_offset = pointcloud.fields[pcl::getFieldIndex(pointcloud, "y")].offset;
434+
// int z_offset = pointcloud.fields[pcl::getFieldIndex(pointcloud, "z")].offset;
435+
// int intensity_offset = pointcloud.fields[pcl::getFieldIndex(pointcloud, "intensity")].offset;
436+
size_t high_confidence_size = 0;
437+
size_t low_confidence_size = 0;
438+
size_t out_ogm_size = 0;
439+
440+
for (size_t global_offset = 0; global_offset < pointcloud.data.size();
441+
global_offset += pointcloud.point_step) {
442+
float x;
443+
float y;
444+
std::memcpy(&x, &pointcloud.data[global_offset + x_offset], sizeof(float));
445+
std::memcpy(&y, &pointcloud.data[global_offset + y_offset], sizeof(float));
446+
447+
const auto cost = getCost(occupancy_grid_map, x, y);
334448
if (cost) {
335449
if (cost_threshold_ < *cost) {
336-
high_confidence.push_back(pcl::PointXYZI(*x, *y, *z, *intensity));
450+
std::memcpy(
451+
&high_confidence.data[high_confidence_size], &pointcloud.data[global_offset],
452+
pointcloud.point_step);
453+
high_confidence_size += pointcloud.point_step;
337454
} else {
338-
low_confidence.push_back(pcl::PointXYZI(*x, *y, *z, *intensity));
455+
std::memcpy(
456+
&low_confidence.data[low_confidence_size], &pointcloud.data[global_offset],
457+
pointcloud.point_step);
458+
low_confidence_size += pointcloud.point_step;
339459
}
340460
} else {
341-
out_ogm.push_back(pcl::PointXYZI(*x, *y, *z, *intensity));
461+
std::memcpy(
462+
&out_ogm.data[out_ogm_size], &pointcloud.data[global_offset], pointcloud.point_step);
463+
out_ogm_size += pointcloud.point_step;
342464
}
343465
}
466+
high_confidence.data.resize(high_confidence_size);
467+
low_confidence.data.resize(low_confidence_size);
468+
out_ogm.data.resize(out_ogm_size);
469+
finalizePointCloud2(pointcloud, high_confidence);
470+
finalizePointCloud2(pointcloud, low_confidence);
471+
finalizePointCloud2(pointcloud, out_ogm);
344472
}
345473

346474
OccupancyGridMapOutlierFilterComponent::Debugger::Debugger(
@@ -356,34 +484,31 @@ OccupancyGridMapOutlierFilterComponent::Debugger::Debugger(
356484
}
357485

358486
void OccupancyGridMapOutlierFilterComponent::Debugger::publishOutlier(
359-
const PclPointCloud & input, const Header & header)
487+
const PointCloud2 & input, const Header & header)
360488
{
361489
auto output_ptr = std::make_unique<PointCloud2>();
362490
transformToBaseLink(input, header, *output_ptr);
363491
outlier_pointcloud_pub_->publish(std::move(output_ptr));
364492
}
365493
void OccupancyGridMapOutlierFilterComponent::Debugger::publishHighConfidence(
366-
const PclPointCloud & input, const Header & header)
494+
const PointCloud2 & input, const Header & header)
367495
{
368496
auto output_ptr = std::make_unique<PointCloud2>();
369497
transformToBaseLink(input, header, *output_ptr);
370498
high_confidence_pointcloud_pub_->publish(std::move(output_ptr));
371499
}
372500

373501
void OccupancyGridMapOutlierFilterComponent::Debugger::publishLowConfidence(
374-
const PclPointCloud & input, const Header & header)
502+
const PointCloud2 & input, const Header & header)
375503
{
376504
auto output_ptr = std::make_unique<PointCloud2>();
377505
transformToBaseLink(input, header, *output_ptr);
378506
low_confidence_pointcloud_pub_->publish(std::move(output_ptr));
379507
}
380508

381509
void OccupancyGridMapOutlierFilterComponent::Debugger::transformToBaseLink(
382-
const PclPointCloud & pcl_input, const Header & header, PointCloud2 & output)
510+
const PointCloud2 & ros_input, [[maybe_unused]] const Header & header, PointCloud2 & output)
383511
{
384-
PointCloud2 ros_input{};
385-
pcl::toROSMsg(pcl_input, ros_input);
386-
ros_input.header = header;
387512
transformPointcloud(ros_input, *(node_.tf2_), node_.base_link_frame_, output);
388513
}
389514

0 commit comments

Comments
 (0)