32 #include <pcl/point_cloud.h>    33 #include <pcl/point_types.h>    35 #include <pcl/io/pcd_io.h>    36 #include <pcl/filters/voxel_grid.h>    37 #include <pcl/filters/radius_outlier_removal.h>    43 #include <nav_msgs/Odometry.h>    44 #include <sensor_msgs/PointCloud2.h>    51 #include <rtabmap_ros/OdomInfo.h>    54 #include <rtabmap/core/Version.h>   113                 bool subscribeOdomInfo = 
false;
   115                 pnh.
param(
"queue_size", queueSize, queueSize);
   131                 pnh.
param(
"subscribe_odom_info", subscribeOdomInfo, subscribeOdomInfo);
   149                 ROS_INFO(
"%s: remove_z=%s", 
getName().c_str(), 
removeZ_?
"true":
"false");
   153                         ROS_ERROR(
"point_cloud_assembler: max_cloud or assembling_time parameters should be set!");
   159                 std::string subscribedTopicsMsg;
   163                         subscribedTopicsMsg = 
uFormat(
"\n%s subscribed to %s",
   167                 else if(subscribeOdomInfo)
   174                         subscribedTopicsMsg = 
uFormat(
"\n%s subscribed to (exact sync):\n   %s,\n   %s",
   176                                                                 syncCloudSub_.getTopic().c_str(),
   177                                                                 syncOdomSub_.getTopic().c_str(),
   188                         subscribedTopicsMsg = 
uFormat(
"\n%s subscribed to (exact sync):\n   %s,\n   %s",
   190                                                                 syncCloudSub_.getTopic().c_str(),
   202                         const sensor_msgs::PointCloud2ConstPtr & cloudMsg,
   203                         const nav_msgs::OdometryConstPtr & odomMsg)
   214                         NODELET_WARN(
"Reseting point cloud assembler as null odometry has been received.");
   220                         const sensor_msgs::PointCloud2ConstPtr & cloudMsg,
   221                         const nav_msgs::OdometryConstPtr & odomMsg,
   222                         const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg)
   228                         if(odomInfoMsg->keyFrameAdded)
   240                         NODELET_WARN(
"Reseting point cloud assembler as null odometry has been received.");
   245         sensor_msgs::PointCloud2 
removeField(
const sensor_msgs::PointCloud2 & input, 
const std::string & field)
   247                 sensor_msgs::PointCloud2 output;
   249                 std::vector<int> inputFieldIndex;
   250                 for(
size_t i=0; i<input.fields.size(); ++i)
   252                         if(input.fields[i].name.compare(field) == 0)
   258                                 sensor_msgs::PointField outputField = input.fields[i];
   259                                 outputField.offset = 
offset;
   260                                 offset += outputField.count * sizeOfPointField(outputField.datatype);
   261                                 output.fields.push_back(outputField);
   262                                 inputFieldIndex.push_back(i);
   265                 output.header = input.header;
   266                 output.height = input.height;
   267                 output.width = input.width;
   268                 output.is_bigendian = input.is_bigendian;
   269                 output.is_dense = input.is_dense;
   270                 output.point_step = 
offset;
   271                 output.row_step = output.width * output.point_step;
   272                 output.data.resize(output.height*output.row_step);
   273                 int total = output.height*output.width;
   274                 for(
int i=0; i<total; ++i)
   277                         int oi = i*output.point_step;
   278                         int pi = i*input.point_step;
   279                         for(
size_t j=0;j<output.fields.size(); ++j)
   281                                 memcpy(&output.data[oi + output.fields[j].offset],
   282                                            &input.data[pi + input.fields[inputFieldIndex[j]].offset],
   283                                            output.fields[j].count * sizeOfPointField(output.fields[j].datatype));
   293                         UASSERT_MSG(cloudMsg->data.size() == cloudMsg->row_step*cloudMsg->height,
   294                                         uFormat(
"data=%d row_step=%d height=%d", cloudMsg->data.size(), cloudMsg->row_step, cloudMsg->height).c_str());
   296                         if(skipClouds_<=0 || cloudsSkipped_ >= 
skipClouds_)
   302                                                 cloudMsg->header.frame_id, 
   303                                                 cloudMsg->header.stamp,
   309                                         ROS_ERROR(
"Cloud not transform all clouds! Resetting...");
   314                                 bool isMoving = 
true;
   329                                 pcl::PCLPointCloud2::Ptr newCloud(
new pcl::PCLPointCloud2);
   335 #if PCL_VERSION_COMPARE(>=, 1, 10, 0)   341                                         newCloud->header.stamp = 
stamp;
   345                                         sensor_msgs::PointCloud2 output;
   350                                 if(!newCloud->is_dense)
   358 #if PCL_VERSION_COMPARE(>=, 1, 10, 0)   359                                 bool reachedMaxSize =
   364                                 bool reachedMaxSize =
   372                                         pcl::PCLPointCloud2Ptr assembled(
new pcl::PCLPointCloud2);
   373                                         for(std::list<pcl::PCLPointCloud2::Ptr>::iterator iter=
clouds_.begin(); iter!=
clouds_.end(); ++iter)
   375                                                 if(assembled->data.empty())
   377                                                         *assembled = *(*iter);
   381                                                         pcl::PCLPointCloud2Ptr assembledTmp(
new pcl::PCLPointCloud2);
   382 #if PCL_VERSION_COMPARE(>=, 1, 10, 0)   383                                                         pcl::concatenate(*assembled, *(*iter), *assembledTmp);
   388                                                         assembledTmp->row_step = assembled->row_step + (*iter)->row_step;
   389                                                         assembled = assembledTmp;
   393                                         sensor_msgs::PointCloud2 rosCloud;
   397                                                 int x_idx=-1, y_idx=-1, z_idx=-1;
   398                                                 for (std::size_t 
d = 0; 
d < assembled->fields.size (); ++
d)
   400                                                         if (assembled->fields[
d].name.compare(
"x")==0)
   402                                                         if (assembled->fields[
d].name.compare(
"y")==0)
   404                                                         if (assembled->fields[
d].name.compare(
"z")==0)
   407                                                 bool overflow = 
false;
   408                                                 if(x_idx>=0 && y_idx>=0 && z_idx>=0) {
   409                                                         Eigen::Vector4f min_p, max_p;
   410                                                         pcl::getMinMax3D(assembled, x_idx, y_idx, z_idx, min_p, max_p);
   425 #if PCL_VERSION_COMPARE(>=, 1, 10, 0)   431                                                         assembled->header.stamp = 
stamp;
   435                                                         pcl::VoxelGrid<pcl::PCLPointCloud2> filter;
   437                                                         filter.setInputCloud(assembled);
   438                                                         pcl::PCLPointCloud2Ptr output(
new pcl::PCLPointCloud2);
   439                                                         filter.filter(*output);
   445                                                 pcl::RadiusOutlierRemoval<pcl::PCLPointCloud2> filter;
   448                                                 filter.setInputCloud(assembled);
   449                                                 pcl::PCLPointCloud2Ptr output(
new pcl::PCLPointCloud2);
   450                                                 filter.filter(*output);
   462                                                                 cloudMsg->header.stamp,
   467                                                         ROS_ERROR(
"Cloud not transform back assembled clouds in target frame \"%s\"! Resetting...", 
frameId_.c_str());
   479                                         rosCloud.header = cloudMsg->header;
   482                                                 rosCloud.header.frame_id = 
frameId_;
   530                                 ROS_WARN(
"%s: Did not receive data since 5 seconds! Make sure the input topics are "   531                                                 "published (\"$ rostopic hz my_topic\") and the timestamps in their "   532                                                 "header are set. %s",
   534                                                 subscribedTopicsMsg.c_str());
 message_filters::Synchronizer< syncInfoPolicy > * exactInfoSync_
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
tf::TransformListener tfListener_
std::string uFormat(const char *fmt,...)
std::string getTopic() const
sensor_msgs::PointCloud2 removeField(const sensor_msgs::PointCloud2 &input, const std::string &field)
#define NODELET_WARN(...)
std::string getTopic() const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
message_filters::Subscriber< nav_msgs::Odometry > syncOdomSub_
void callbackCloud(const sensor_msgs::PointCloud2ConstPtr &cloudMsg)
ros::NodeHandle & getNodeHandle() const
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP removeNaNFromPointCloud(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud)
pcl::PCLPointCloud2::Ptr RTABMAP_EXP laserScanToPointCloud2(const LaserScan &laserScan, const Transform &transform=Transform())
double waitForTransformDuration_
rtabmap::Transform transformFromPoseMsg(const geometry_msgs::Pose &msg, bool ignoreRotationIfNotSet=false)
ros::NodeHandle & getPrivateNodeHandle() const
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
boost::thread * warningThread_
geometry_msgs::TransformStamped t
rtabmap::Transform getTransform(const std::string &fromFrameId, const std::string &toFrameId, const ros::Time &stamp, tf::TransformListener &listener, double waitForTransform)
std::list< pcl::PCLPointCloud2::Ptr > clouds_
const std::string & getName() const
void callbackCloudOdom(const sensor_msgs::PointCloud2ConstPtr &cloudMsg, const nav_msgs::OdometryConstPtr &odomMsg)
LaserScan RTABMAP_EXP commonFiltering(const LaserScan &scan, int downsamplingStep, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalK=0, float normalRadius=0.0f, float groundNormalsUp=0.0f)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
void warningLoop(const std::string &subscribedTopicsMsg)
#define UASSERT_MSG(condition, msg_str)
GLM_FUNC_DECL genType pi()
message_filters::Subscriber< sensor_msgs::PointCloud2 > syncCloudSub_
LaserScan laserScanFromPointCloud(const PointCloud2T &cloud, bool filterNaNs, bool is2D, const Transform &transform)
void toPCL(const ros::Time &stamp, std::uint64_t &pcl_stamp)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
message_filters::sync_policies::ExactTime< sensor_msgs::PointCloud2, nav_msgs::Odometry, rtabmap_ros::OdomInfo > syncInfoPolicy
virtual ~PointCloudAssembler()
message_filters::sync_policies::ExactTime< sensor_msgs::PointCloud2, nav_msgs::Odometry > syncPolicy
bool concatenatePointCloud(const sensor_msgs::PointCloud2 &cloud1, const sensor_msgs::PointCloud2 &cloud2, sensor_msgs::PointCloud2 &cloud_out)
message_filters::Subscriber< rtabmap_ros::OdomInfo > syncOdomInfoSub_
#define NODELET_INFO(...)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const tf::Transform &transform)
ros::Subscriber cloudSub_
void callbackCloudOdomInfo(const sensor_msgs::PointCloud2ConstPtr &cloudMsg, const nav_msgs::OdometryConstPtr &odomMsg, const rtabmap_ros::OdomInfoConstPtr &odomInfoMsg)
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
rtabmap::Transform previousPose_
message_filters::Synchronizer< syncPolicy > * exactSync_
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::CoreWrapper, nodelet::Nodelet)
void moveFromPCL(pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
uint32_t getNumSubscribers() const
std::string fixedFrameId_