Go to the documentation of this file.00001
00002
00003
00004 #include <laser_geometry/laser_geometry.h>
00005 #include <nifti_pcl_common/point_types.h>
00006 #include <nodelet/nodelet.h>
00007 #include <sensor_msgs/LaserScan.h>
00008 #include <pcl/common/io.h>
00009 #include <pcl/common/impl/io.hpp>
00010 #include <pcl/point_cloud.h>
00011 #include <pcl/point_types.h>
00012 #include <pcl_ros/point_cloud.h>
00013 #include <pluginlib/class_list_macros.h>
00014 #include <ros/ros.h>
00015 #include <tf/transform_listener.h>
00016
00017 namespace point_cloud_color {
00018
00019 typedef nifti_pcl_common::LaserPoint PointOut;
00020
00021 class ScanToPointCloud: public nodelet::Nodelet {
00022 public:
00023 ScanToPointCloud();
00024 virtual ~ScanToPointCloud();
00025 void onInit();
00026 void scanCallback(const sensor_msgs::LaserScan::ConstPtr &scanMsg);
00027 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00028 private:
00029 std::string targetFrame;
00030 double waitForTransform;
00031 int scanQueue;
00032 int pointCloudQueue;
00033 tf::TransformListener transformListener;
00034 ros::Subscriber scanSubscriber;
00035 laser_geometry::LaserProjection projector;
00036 ros::Publisher pointCloudPublisher;
00037 };
00038
00039 ScanToPointCloud::ScanToPointCloud() : targetFrame(""), waitForTransform(0.5), scanQueue(10), pointCloudQueue(10), transformListener() {
00040 }
00041
00042 ScanToPointCloud::~ScanToPointCloud() {
00043 }
00044
00045 void ScanToPointCloud::onInit() {
00046 NODELET_INFO("ScanToPointCloud::onInit: Initializing...");
00047
00048 #ifdef USE_MT_NODE_HANDLE
00049 ros::NodeHandle &nh = getMTNodeHandle();
00050 ros::NodeHandle &pnh = getMTPrivateNodeHandle();
00051 #else
00052 ros::NodeHandle &nh = getNodeHandle();
00053 ros::NodeHandle &pnh = getPrivateNodeHandle();
00054 #endif
00055
00056
00057 pnh.param("target_frame", targetFrame, targetFrame);
00058 NODELET_INFO("ScanToPointCloud::onInit: Using target frame %s.", targetFrame.data());
00059 pnh.param("wait_for_transform", waitForTransform, waitForTransform);
00060 NODELET_INFO("ScanToPointCloud::onInit: Maximum time to wait for transform %.2f s.", waitForTransform);
00061 pnh.param("scan_queue", scanQueue, scanQueue);
00062 NODELET_INFO("ScanToPointCloud::onInit: Scan queue size %i.", scanQueue);
00063 pnh.param("point_cloud_queue", pointCloudQueue, pointCloudQueue);
00064 NODELET_INFO("ScanToPointCloud::onInit: Point cloud queue size %i.", pointCloudQueue);
00065
00066
00067 std::string scanTopic = nh.resolveName("scan", true);
00068 NODELET_INFO("ScanToPointCloud::onInit: Subscribing scan %s.", scanTopic.data());
00069 scanSubscriber = nh.subscribe<sensor_msgs::LaserScan>(scanTopic, scanQueue, &ScanToPointCloud::scanCallback, this);
00070
00071
00072 std::string pclTopic = nh.resolveName("scan_point_cloud", true);
00073 NODELET_INFO("ScanToPointCloud::onInit: Advertising point cloud %s.", pclTopic.data());
00074 pointCloudPublisher = nh.advertise<pcl::PointCloud<nifti_pcl_common::LaserPoint> >(pclTopic, pointCloudQueue, false);
00075 }
00076
00077 void ScanToPointCloud::scanCallback(const sensor_msgs::LaserScan::ConstPtr &scanPtr) {
00078 ros::Time t1 = ros::Time::now();
00079 NODELET_DEBUG("ScanToPointCloud::scanCallback: Point cloud received (%lu points).", scanPtr->ranges.size());
00080 std::string frame = targetFrame.size() > 0 ? targetFrame : scanPtr->header.frame_id;
00081 if (!transformListener.waitForTransform(frame, scanPtr->header.frame_id, scanPtr->header.stamp + ros::Duration(scanPtr->scan_time), ros::Duration(waitForTransform))) {
00082 NODELET_WARN("ScanToPointCloud::scanCallback: Cannot transform from %s to %s at %.2f s.", scanPtr->header.frame_id.data(), frame.data(), scanPtr->header.stamp.toSec());
00083 return;
00084 }
00085 sensor_msgs::PointCloud2 pclMsg;
00086 try {
00087
00088 int channelOptions = laser_geometry::channel_option::Intensity
00089 | laser_geometry::channel_option::Index
00090 | laser_geometry::channel_option::Timestamp
00091 | laser_geometry::channel_option::Viewpoint;
00092 projector.transformLaserScanToPointCloud(frame, *scanPtr, pclMsg, transformListener, -1.0, channelOptions);
00093 pcl::PointCloud<nifti_pcl_common::LaserProjectionPoint> pclProj;
00094 pcl::fromROSMsg(pclMsg, pclProj);
00095
00096 pcl::PointCloud<nifti_pcl_common::LaserPoint> pclOut;
00097 pcl::copyPointCloud(pclProj, pclOut);
00098 for (size_t i = 0; i < pclProj.points.size(); ++i) {
00099 ros::Time pointStamp = pclProj.header.stamp + ros::Duration(pclProj.points[i].stamps);
00100 pclOut.points[i].sec = pointStamp.sec;
00101 pclOut.points[i].nsec = pointStamp.nsec;
00102 }
00103 pointCloudPublisher.publish(pclOut);
00104 NODELET_DEBUG("ScanToPointCloud::scanCallback: Converting scan to point cloud: %.3f s.", (ros::Time::now() - t1).toSec());
00105
00106 } catch(tf::TransformException& ex) {
00107 ROS_ERROR("ScanToPointCloud::scanCallback: Transform exception: %s.", ex.what());
00108 return;
00109 }
00110 }
00111
00112 }
00113
00114 PLUGINLIB_DECLARE_CLASS(point_cloud_color, scan_to_point_cloud, point_cloud_color::ScanToPointCloud, nodelet::Nodelet)