32 #include <pcl/point_cloud.h>
33 #include <pcl/point_types.h>
35 #include <pcl/io/pcd_io.h>
41 #include <sensor_msgs/PointCloud2.h>
103 int syncQueueSize = 5;
106 double approxSyncMaxInterval = 0.0;
107 pnh.
param(
"topic_queue_size", queueSize, queueSize);
110 pnh.
param(
"queue_size", syncQueueSize, syncQueueSize);
111 ROS_WARN(
"Parameter \"queue_size\" has been renamed "
112 "to \"sync_queue_size\" and will be removed "
113 "in future versions! The value (%d) is copied to "
114 "\"sync_queue_size\".", syncQueueSize);
118 pnh.
param(
"sync_queue_size", syncQueueSize, syncQueueSize);
122 pnh.
param(
"approx_sync", approx, approx);
123 pnh.
param(
"approx_sync_max_interval", approxSyncMaxInterval, approxSyncMaxInterval);
131 std::string subscribedTopicsMsg;
139 if(approxSyncMaxInterval > 0.0)
148 subscribedTopicsMsg =
uFormat(
"\n%s subscribed to (%s sync%s):\n %s,\n %s,\n %s,\n %s",
150 approx?
"approx":
"exact",
151 approx&&approxSyncMaxInterval!=0.0?
uFormat(
", max interval=%fs", approxSyncMaxInterval).
c_str():
"",
163 if(approxSyncMaxInterval > 0.0)
172 subscribedTopicsMsg =
uFormat(
"\n%s subscribed to (%s sync%s):\n %s,\n %s,\n %s",
174 approx?
"approx":
"exact",
175 approx&&approxSyncMaxInterval!=0.0?
uFormat(
", max interval=%fs", approxSyncMaxInterval).
c_str():
"",
185 if(approxSyncMaxInterval > 0.0)
194 subscribedTopicsMsg =
uFormat(
"\n%s subscribed to (%s sync%s):\n %s,\n %s",
196 approx?
"approx":
"exact",
197 approx&&approxSyncMaxInterval!=0.0?
uFormat(
", max interval=%fs", approxSyncMaxInterval).
c_str():
"",
209 const sensor_msgs::PointCloud2ConstPtr & cloudMsg_2,
210 const sensor_msgs::PointCloud2ConstPtr & cloudMsg_3,
211 const sensor_msgs::PointCloud2ConstPtr & cloudMsg_4)
213 std::vector<sensor_msgs::PointCloud2ConstPtr> clouds;
214 clouds.push_back(cloudMsg_1);
215 clouds.push_back(cloudMsg_2);
216 clouds.push_back(cloudMsg_3);
217 clouds.push_back(cloudMsg_4);
222 const sensor_msgs::PointCloud2ConstPtr & cloudMsg_2,
223 const sensor_msgs::PointCloud2ConstPtr & cloudMsg_3)
225 std::vector<sensor_msgs::PointCloud2ConstPtr> clouds;
226 clouds.push_back(cloudMsg_1);
227 clouds.push_back(cloudMsg_2);
228 clouds.push_back(cloudMsg_3);
233 const sensor_msgs::PointCloud2ConstPtr & cloudMsg_2)
235 std::vector<sensor_msgs::PointCloud2ConstPtr> clouds;
236 clouds.push_back(cloudMsg_1);
237 clouds.push_back(cloudMsg_2);
241 void combineClouds(
const std::vector<sensor_msgs::PointCloud2ConstPtr> & cloudMsgs)
247 pcl::PCLPointCloud2::Ptr output(
new pcl::PCLPointCloud2);
250 if(!
frameId.empty() &&
frameId.compare(cloudMsgs[0]->header.frame_id) != 0)
252 sensor_msgs::PointCloud2 tmp;
259 frameId = cloudMsgs[0]->header.frame_id;
265 bool hasField[4] = {
false};
266 for(
size_t i=0;
i<output->fields.size(); ++
i)
268 if(output->fields[
i].name.compare(
"x") == 0)
272 else if(output->fields[
i].name.compare(
"y") == 0)
276 else if(output->fields[
i].name.compare(
"z") == 0)
286 if(hasField[0] && hasField[1] && hasField[2] && !hasField[3])
292 pcl::PointCloud<pcl::PointXYZ> cloudxyz;
293 pcl::fromPCLPointCloud2(*output, cloudxyz);
294 pcl::toPCLPointCloud2(cloudxyz, *output);
298 for(
unsigned int i=1;
i<cloudMsgs.size(); ++
i)
302 cloudMsgs[0]->header.stamp != cloudMsgs[
i]->header.stamp)
308 cloudMsgs[0]->
header.stamp,
309 cloudMsgs[
i]->header.stamp,
314 pcl::PCLPointCloud2::Ptr cloud2(
new pcl::PCLPointCloud2);
315 if(
frameId.compare(cloudMsgs[
i]->header.frame_id) != 0)
317 sensor_msgs::PointCloud2 tmp;
319 if(!cloudDisplacement.
isNull())
321 sensor_msgs::PointCloud2 tmp2;
333 if(!cloudDisplacement.
isNull())
335 sensor_msgs::PointCloud2 tmp;
345 if(!cloud2->is_dense)
354 bool hasField[4] = {
false};
355 for(
size_t i=0;
i<cloud2->fields.size(); ++
i)
357 if(cloud2->fields[
i].name.compare(
"x") == 0)
361 else if(cloud2->fields[
i].name.compare(
"y") == 0)
365 else if(cloud2->fields[
i].name.compare(
"z") == 0)
375 if(hasField[0] && hasField[1] && hasField[2] && !hasField[3])
381 pcl::PointCloud<pcl::PointXYZ> cloudxyz;
382 pcl::fromPCLPointCloud2(*cloud2, cloudxyz);
383 pcl::toPCLPointCloud2(cloudxyz, *cloud2);
387 if(output->data.empty())
391 else if(!cloud2->data.empty())
394 if(output->fields.size() != cloud2->fields.size())
396 ROS_WARN(
"%s: Input topics don't have all the "
397 "same number of fields (cloud1=%d, cloud%d=%d), concatenation "
398 "may fails. You can enable \"xyz_output\" option "
399 "to convert all inputs to XYZ.",
401 (
int)output->fields.size(),
403 (
int)output->fields.size());
406 pcl::PCLPointCloud2::Ptr tmp_output(
new pcl::PCLPointCloud2);
407 #if PCL_VERSION_COMPARE(>=, 1, 10, 0)
408 pcl::concatenate(*output, *cloud2, *tmp_output);
413 tmp_output->row_step = tmp_output->width * tmp_output->point_step;
418 sensor_msgs::PointCloud2 rosCloud;
420 rosCloud.header.stamp = cloudMsgs[0]->header.stamp;
421 rosCloud.header.frame_id =
frameId;
426 void warningLoop(
const std::string & subscribedTopicsMsg,
bool approxSync)
434 ROS_WARN(
"%s: Did not receive data since 5 seconds! Make sure the input topics are "
435 "published (\"$ rostopic hz my_topic\") and the timestamps in their "
436 "header are set. %s%s",
438 approxSync?
"":
"Parameter \"approx_sync\" is false, which means that input "
439 "topics should have all the exact timestamp for the callback to be called.",
440 subscribedTopicsMsg.c_str());