@@ -147,34 +147,45 @@ void RadiusSearch2dFilter::filter(
147
147
}
148
148
149
149
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)
152
152
{
153
- const auto & high_conf_xyz_cloud = high_conf_input;
154
- const auto & low_conf_xyz_cloud = low_conf_input;
155
153
// 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_) {
157
155
RCLCPP_WARN (
158
156
rclcpp::get_logger (" OccupancyGridMapOutlierFilterComponent" ),
159
157
" Skip outlier filter since too much low_confidence pointcloud!" );
160
158
return ;
161
159
}
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 ;
163
163
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 ));
168
170
}
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 ));
172
180
}
173
181
174
182
std::vector<int > k_indices (xy_cloud->points .size ());
175
183
std::vector<float > k_distances (xy_cloud->points .size ());
176
184
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) {
178
189
const float distance =
179
190
std::hypot (xy_cloud->points [i].x - pose.position .x , xy_cloud->points [i].y - pose.position .y );
180
191
const int min_points_threshold = std::min (
@@ -184,11 +195,20 @@ void RadiusSearch2dFilter::filter(
184
195
kd_tree_->radiusSearch (i, search_radius_, k_indices, k_distances, min_points_threshold);
185
196
186
197
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 ;
188
202
} 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 ;
190
207
}
191
208
}
209
+
210
+ output.data .resize (output_size);
211
+ outlier.data .resize (outlier_size);
192
212
}
193
213
194
214
OccupancyGridMapOutlierFilterComponent::OccupancyGridMapOutlierFilterComponent (
@@ -239,21 +259,50 @@ OccupancyGridMapOutlierFilterComponent::OccupancyGridMapOutlierFilterComponent(
239
259
void OccupancyGridMapOutlierFilterComponent::splitPointCloudFrontBack (
240
260
const PointCloud2::ConstSharedPtr & input_pc, PointCloud2 & front_pc, PointCloud2 & behind_pc)
241
261
{
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++;
249
286
} 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++;
251
291
}
252
292
}
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 ;
255
296
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 ;
256
303
behind_pc.header = input_pc->header ;
304
+ behind_pc.is_bigendian = input_pc->is_bigendian ;
305
+ behind_pc.is_dense = input_pc->is_dense ;
257
306
}
258
307
void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2 (
259
308
const OccupancyGrid::ConstSharedPtr & input_ogm, const PointCloud2::ConstSharedPtr & input_pc)
@@ -264,6 +313,10 @@ void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
264
313
PointCloud2 input_front_pc{};
265
314
PointCloud2 input_behind_pc{};
266
315
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;
267
320
splitPointCloudFrontBack (input_pc, input_front_pc, input_behind_pc);
268
321
if (
269
322
!transformPointcloud (input_front_pc, *tf2_, input_ogm->header .frame_id , ogm_frame_pc) ||
@@ -272,33 +325,50 @@ void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
272
325
return ;
273
326
}
274
327
// 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);
280
336
filterByOccupancyGridMap (
281
337
*input_ogm, ogm_frame_pc, high_confidence_pc, low_confidence_pc, out_ogm_pc);
282
338
// 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 ;
285
348
if (radius_search_2d_filter_ptr_) {
286
349
auto pc_frame_pose_stamped = getPoseStamped (
287
350
*tf2_, input_ogm->header .frame_id , input_pc->header .frame_id , input_ogm->header .stamp );
288
351
radius_search_2d_filter_ptr_->filter (
289
352
high_confidence_pc, low_confidence_pc, pc_frame_pose_stamped.pose , filtered_low_confidence_pc,
290
353
outlier_pc);
291
354
} 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 ());
293
357
}
294
358
// 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);
297
369
// Convert to ros msg
298
370
{
299
- PointCloud2 ogm_frame_filtered_pc{};
300
371
auto base_link_frame_filtered_pc_ptr = std::make_unique<PointCloud2>();
301
- pcl::toROSMsg (concat_pc, ogm_frame_filtered_pc);
302
372
ogm_frame_filtered_pc.header = ogm_frame_pc.header ;
303
373
if (!transformPointcloud (
304
374
ogm_frame_filtered_pc, *tf2_, base_link_frame_, *base_link_frame_filtered_pc_ptr)) {
@@ -323,24 +393,82 @@ void OccupancyGridMapOutlierFilterComponent::onOccupancyGridMapAndPointCloud2(
323
393
}
324
394
}
325
395
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
+ }
326
428
void OccupancyGridMapOutlierFilterComponent::filterByOccupancyGridMap (
327
429
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)
329
431
{
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);
334
448
if (cost) {
335
449
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 ;
337
454
} 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 ;
339
459
}
340
460
} 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 ;
342
464
}
343
465
}
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);
344
472
}
345
473
346
474
OccupancyGridMapOutlierFilterComponent::Debugger::Debugger (
@@ -356,34 +484,31 @@ OccupancyGridMapOutlierFilterComponent::Debugger::Debugger(
356
484
}
357
485
358
486
void OccupancyGridMapOutlierFilterComponent::Debugger::publishOutlier (
359
- const PclPointCloud & input, const Header & header)
487
+ const PointCloud2 & input, const Header & header)
360
488
{
361
489
auto output_ptr = std::make_unique<PointCloud2>();
362
490
transformToBaseLink (input, header, *output_ptr);
363
491
outlier_pointcloud_pub_->publish (std::move (output_ptr));
364
492
}
365
493
void OccupancyGridMapOutlierFilterComponent::Debugger::publishHighConfidence (
366
- const PclPointCloud & input, const Header & header)
494
+ const PointCloud2 & input, const Header & header)
367
495
{
368
496
auto output_ptr = std::make_unique<PointCloud2>();
369
497
transformToBaseLink (input, header, *output_ptr);
370
498
high_confidence_pointcloud_pub_->publish (std::move (output_ptr));
371
499
}
372
500
373
501
void OccupancyGridMapOutlierFilterComponent::Debugger::publishLowConfidence (
374
- const PclPointCloud & input, const Header & header)
502
+ const PointCloud2 & input, const Header & header)
375
503
{
376
504
auto output_ptr = std::make_unique<PointCloud2>();
377
505
transformToBaseLink (input, header, *output_ptr);
378
506
low_confidence_pointcloud_pub_->publish (std::move (output_ptr));
379
507
}
380
508
381
509
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)
383
511
{
384
- PointCloud2 ros_input{};
385
- pcl::toROSMsg (pcl_input, ros_input);
386
- ros_input.header = header;
387
512
transformPointcloud (ros_input, *(node_.tf2_ ), node_.base_link_frame_ , output);
388
513
}
389
514
0 commit comments