@@ -51,6 +51,9 @@ namespace jsk_pcl_ros
51
51
{
52
52
DiagnosticNodelet::onInit ();
53
53
pub_ = advertise<sensor_msgs::PointCloud2>(*pnh_, " output" , 1 );
54
+ pnh_->param (" use_cluster_point_indices" , use_cpi_, false );
55
+ pnh_->param (" approximate_sync" , use_async_, false );
56
+ pnh_->param (" queue_size" , queue_size_, 100 );
54
57
55
58
srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
56
59
dynamic_reconfigure::Server<Config>::CallbackType f =
@@ -62,7 +65,31 @@ namespace jsk_pcl_ros
62
65
63
66
void OrganizedStatisticalOutlierRemoval::subscribe ()
64
67
{
65
- sub_ = pnh_->subscribe (" input" , 1 , &OrganizedStatisticalOutlierRemoval::filter, this );
68
+ if (use_cpi_)
69
+ {
70
+ sub_cloud_.subscribe (*pnh_, " input" , 1 );
71
+ sub_cpi_.subscribe (*pnh_, " input/cluster_indices" , 1 );
72
+ if (use_async_)
73
+ {
74
+ async_ = boost::make_shared<message_filters::Synchronizer<ApproximateSyncPolicy> >(queue_size_);
75
+ async_->connectInput (sub_cloud_, sub_cpi_);
76
+ async_->registerCallback (
77
+ boost::bind (
78
+ &OrganizedStatisticalOutlierRemoval::filterCloudWithClusterPointIndices, this , _1, _2));
79
+ }
80
+ else
81
+ {
82
+ sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(queue_size_);
83
+ sync_->connectInput (sub_cloud_, sub_cpi_);
84
+ sync_->registerCallback (
85
+ boost::bind (
86
+ &OrganizedStatisticalOutlierRemoval::filterCloudWithClusterPointIndices, this , _1, _2));
87
+ }
88
+ }
89
+ else
90
+ {
91
+ sub_ = pnh_->subscribe (" input" , 1 , &OrganizedStatisticalOutlierRemoval::filterCloud, this );
92
+ }
66
93
}
67
94
68
95
void OrganizedStatisticalOutlierRemoval::unsubscribe ()
@@ -79,26 +106,16 @@ namespace jsk_pcl_ros
79
106
std_mul_ = config.stddev ;
80
107
}
81
108
82
- void OrganizedStatisticalOutlierRemoval::filter (const sensor_msgs::PointCloud2::ConstPtr& msg)
109
+ void OrganizedStatisticalOutlierRemoval::filter (
110
+ pcl::PointCloud<PointT>::Ptr cloud,
111
+ pcl::PointCloud<PointT>::Ptr cloud_filtered,
112
+ bool keep_organized)
83
113
{
84
- boost::mutex::scoped_lock lock (mutex_);
85
- vital_checker_->poke ();
86
- sensor_msgs::PointCloud2 output;
87
-
88
- if (keep_organized_&& msg->is_dense ) {
89
- NODELET_ERROR (" keep_organized parameter is true, but input pointcloud is not organized." );
90
- }
91
- bool keep_organized = keep_organized_ && !msg->is_dense ;
92
-
93
114
#if PCL_VERSION_COMPARE (<, 1, 9, 0)
94
115
if (keep_organized) {
95
- // Send the input dataset to the spatial locator
96
- pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
97
- pcl::fromROSMsg (*msg, *cloud);
98
-
99
116
// Initialize the spatial locator
100
- pcl::search::Search<pcl::PointXYZ >::Ptr tree;
101
- tree.reset (new pcl::search::OrganizedNeighbor<pcl::PointXYZ > ());
117
+ pcl::search::Search<PointT >::Ptr tree;
118
+ tree.reset (new pcl::search::OrganizedNeighbor<PointT > ());
102
119
tree->setInputCloud (cloud);
103
120
104
121
// Allocate enough space to hold the results
@@ -147,74 +164,165 @@ namespace jsk_pcl_ros
147
164
148
165
double distance_threshold = mean + std_mul_ * stddev; // a distance that is bigger than this signals an outlier
149
166
150
- // Copy the common fields
151
- output.is_bigendian = msg->is_bigendian ;
152
- output.fields = msg->fields ;
153
- output.point_step = msg->point_step ;
154
- output.data .resize (msg->data .size ());
167
+ pcl::PCLPointCloud2::Ptr pcl_cloud (new pcl::PCLPointCloud2);
168
+ pcl::PCLPointCloud2::Ptr pcl_cloud_filtered (new pcl::PCLPointCloud2);
169
+ pcl::toPCLPointCloud2 (*cloud, *pcl_cloud);
170
+ pcl_cloud_filtered->is_bigendian = pcl_cloud->is_bigendian ;
171
+ pcl_cloud_filtered->fields = pcl_cloud->fields ;
172
+ pcl_cloud_filtered->point_step = pcl_cloud->point_step ;
173
+ pcl_cloud_filtered->data .resize (pcl_cloud->data .size ());
174
+ pcl_cloud_filtered->width = pcl_cloud->width ;
175
+ pcl_cloud_filtered->height = pcl_cloud->height ;
176
+ pcl_cloud_filtered->row_step = pcl_cloud_filtered->point_step * pcl_cloud_filtered->width ;
155
177
156
178
// Build a new cloud by neglecting outliers
157
179
int nr_p = 0 ;
158
- int nr_removed_p = 0 ;
159
- bool remove_point = false ;
160
180
for (int cp = 0 ; cp < static_cast <int > (indices.size ()); ++cp)
161
181
{
182
+ bool remove_point = false ;
162
183
if (negative_)
163
184
remove_point = (distances[cp] <= distance_threshold);
164
185
else
165
186
remove_point = (distances[cp] > distance_threshold);
166
187
if (remove_point)
167
188
{
168
189
/* Set the current point to NaN. */
169
- *(reinterpret_cast <float *>(&output.data [nr_p * output.point_step ])+0 ) = std::numeric_limits<float >::quiet_NaN ();
170
- *(reinterpret_cast <float *>(&output.data [nr_p * output.point_step ])+1 ) = std::numeric_limits<float >::quiet_NaN ();
171
- *(reinterpret_cast <float *>(&output.data [nr_p * output.point_step ])+2 ) = std::numeric_limits<float >::quiet_NaN ();
172
- nr_p++;
190
+ *(reinterpret_cast <float *>(&pcl_cloud_filtered->data [nr_p * pcl_cloud_filtered->point_step ])+0 ) = std::numeric_limits<float >::quiet_NaN ();
191
+ *(reinterpret_cast <float *>(&pcl_cloud_filtered->data [nr_p * pcl_cloud_filtered->point_step ])+1 ) = std::numeric_limits<float >::quiet_NaN ();
192
+ *(reinterpret_cast <float *>(&pcl_cloud_filtered->data [nr_p * pcl_cloud_filtered->point_step ])+2 ) = std::numeric_limits<float >::quiet_NaN ();
173
193
}
174
194
else
175
195
{
176
- memcpy (&output.data [nr_p * output.point_step ],
177
- &msg->data [indices[cp] * output.point_step ],
178
- output.point_step );
179
- nr_p++;
196
+ memcpy (&pcl_cloud_filtered->data [nr_p * pcl_cloud_filtered->point_step ],
197
+ &pcl_cloud->data [indices[cp] * pcl_cloud_filtered->point_step ],
198
+ pcl_cloud_filtered->point_step );
180
199
}
200
+ nr_p++;
181
201
}
182
- output.width = msg->width ;
183
- output.height = msg->height ;
184
- output.row_step = output.point_step * output.width ;
202
+ pcl::fromPCLPointCloud2 (*pcl_cloud_filtered, *cloud_filtered);
185
203
}
186
204
else
187
205
{
188
- pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
189
- pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);
190
- pcl::fromROSMsg (*msg, *cloud);
191
206
pcl::StatisticalOutlierRemoval<PointT> sor;
192
207
sor.setInputCloud (cloud);
193
208
sor.setMeanK (mean_k_);
194
209
sor.setStddevMulThresh (std_mul_);
195
210
sor.setNegative (negative_);
196
211
sor.filter (*cloud_filtered);
197
- pcl::toROSMsg (*cloud_filtered, output);
198
212
}
199
- output.header = msg->header ;
200
- output.is_dense = !keep_organized;
201
- pub_.publish (output);
202
213
#else
203
- pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
204
- pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);
205
- pcl::fromROSMsg (*msg, *cloud);
206
214
pcl::StatisticalOutlierRemoval<PointT> sor;
207
215
sor.setInputCloud (cloud);
208
216
sor.setMeanK (mean_k_);
209
217
sor.setStddevMulThresh (std_mul_);
210
218
sor.setNegative (negative_);
211
219
sor.setKeepOrganized (keep_organized);
212
220
sor.filter (*cloud_filtered);
221
+ #endif
222
+ }
223
+
224
+ void OrganizedStatisticalOutlierRemoval::filterCloud (const sensor_msgs::PointCloud2::ConstPtr& msg)
225
+ {
226
+ boost::mutex::scoped_lock lock (mutex_);
227
+ vital_checker_->poke ();
228
+ sensor_msgs::PointCloud2 output;
229
+
230
+ if (keep_organized_&& msg->is_dense ) {
231
+ NODELET_ERROR (" keep_organized parameter is true, but input pointcloud is not organized." );
232
+ }
233
+ bool keep_organized = keep_organized_ && !msg->is_dense ;
234
+ pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
235
+ pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);
236
+ pcl::fromROSMsg (*msg, *cloud);
237
+
238
+ // filter
239
+ OrganizedStatisticalOutlierRemoval::filter (cloud, cloud_filtered, keep_organized);
240
+
213
241
pcl::toROSMsg (*cloud_filtered, output);
242
+ #if PCL_VERSION_COMPARE (<, 1, 9, 0)
243
+ if (keep_organized) {
244
+ // Copy the common fields
245
+ output.is_bigendian = msg->is_bigendian ;
246
+ output.fields = msg->fields ;
247
+ output.point_step = msg->point_step ;
248
+ output.data .resize (msg->data .size ());
249
+ output.width = msg->width ;
250
+ output.height = msg->height ;
251
+ output.row_step = msg->point_step * msg->width ;
252
+ }
253
+ #endif
214
254
output.header = msg->header ;
215
255
output.is_dense = !keep_organized;
216
256
pub_.publish (output);
257
+ diagnostic_updater_->update ();
258
+ }
259
+
260
+ void OrganizedStatisticalOutlierRemoval::filterCloudWithClusterPointIndices (
261
+ const sensor_msgs::PointCloud2::ConstPtr& msg,
262
+ const jsk_recognition_msgs::ClusterPointIndices::ConstPtr& cpi_msg)
263
+ {
264
+ boost::mutex::scoped_lock lock (mutex_);
265
+ vital_checker_->poke ();
266
+ sensor_msgs::PointCloud2 output;
267
+
268
+ if (keep_organized_&& msg->is_dense ) {
269
+ NODELET_ERROR (" keep_organized parameter is true, but input pointcloud is not organized." );
270
+ }
271
+ bool keep_organized = keep_organized_ && !msg->is_dense ;
272
+ pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
273
+ pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);
274
+ pcl::fromROSMsg (*msg, *cloud);
275
+ cloud_filtered->points .resize (cloud->points .size ());
276
+ PointT nan_point;
277
+ nan_point.x = nan_point.y = nan_point.z = std::numeric_limits<float >::quiet_NaN ();
278
+ std::fill (cloud_filtered->points .begin (), cloud_filtered->points .end (), nan_point);
279
+
280
+ pcl::ExtractIndices<PointT> ex;
281
+ ex.setInputCloud (cloud);
282
+ ex.setKeepOrganized (keep_organized);
283
+ ex.setNegative (false );
284
+
285
+ for (size_t i = 0 ; i < cpi_msg->cluster_indices .size (); i++)
286
+ {
287
+ pcl::IndicesPtr indices;
288
+ pcl::PointCloud<PointT>::Ptr cluster_cloud (new pcl::PointCloud<PointT>);
289
+ pcl::PointCloud<PointT>::Ptr cluster_cloud_filtered (new pcl::PointCloud<PointT>);
290
+ indices.reset (new std::vector<int > (cpi_msg->cluster_indices [i].indices ));
291
+ ex.setIndices (indices);
292
+ ex.filter (*cluster_cloud);
293
+ OrganizedStatisticalOutlierRemoval::filter (cluster_cloud, cluster_cloud_filtered, keep_organized);
294
+ for (size_t j = 0 ; j < indices->size (); j++)
295
+ {
296
+ int ind = (*indices)[j];
297
+ if (!std::isnan (cluster_cloud_filtered->points [ind].x ) &&
298
+ !std::isnan (cluster_cloud_filtered->points [ind].y ) &&
299
+ !std::isnan (cluster_cloud_filtered->points [ind].z ))
300
+ {
301
+ cloud_filtered->points [ind].x = cluster_cloud_filtered->points [ind].x ;
302
+ cloud_filtered->points [ind].y = cluster_cloud_filtered->points [ind].y ;
303
+ cloud_filtered->points [ind].z = cluster_cloud_filtered->points [ind].z ;
304
+ cloud_filtered->points [ind].rgb = cluster_cloud_filtered->points [ind].rgb ;
305
+ }
306
+ }
307
+
308
+ }
309
+
310
+ pcl::toROSMsg (*cloud_filtered, output);
311
+ #if PCL_VERSION_COMPARE (<, 1, 9, 0)
312
+ if (keep_organized) {
313
+ // Copy the common fields
314
+ output.is_bigendian = msg->is_bigendian ;
315
+ output.fields = msg->fields ;
316
+ output.point_step = msg->point_step ;
317
+ output.data .resize (msg->data .size ());
318
+ output.width = msg->width ;
319
+ output.height = msg->height ;
320
+ output.row_step = output.point_step * output.width ;
321
+ }
217
322
#endif
323
+ output.header = msg->header ;
324
+ output.is_dense = !keep_organized;
325
+ pub_.publish (output);
218
326
diagnostic_updater_->update ();
219
327
}
220
328
0 commit comments