get_point_cloud.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *  Software License Agreement (BSD License)
00003 *  Copyright (c) 2013, Intelligent Robotics Lab, DLUT.
00004 *  All rights reserved.
00005 *  Author:Zhao Cilang,Yan Fei,Zhuang Yan.
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *   * Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *   * Redistributions in binary form must reproduce the above
00013 *     copyright notice, this list of conditions and the following
00014 *     disclaimer in the documentation and/or other materials provided
00015 *     with the distribution.
00016 *   * Neither the name of the Intelligent Robotics Lab nor the names of its
00017 *     contributors may be used to endorse or promote products derived
00018 *     from this software without specific prior written permission.
00019 *
00020 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 *  POSSIBILITY OF SUCH DAMAGE.
00032 *********************************************************************/
00033 //=========================================================================
00034 //This software provide a solution to get point cloud and publish it.
00035 //We first get one frame laser data,and then caculate the 3D point cloud 
00036 //acording to the degree that the motor has moved.
00037 //=========================================================================
00038 #include "sick_laser/motor.h"
00039 
00040 #include <ros/ros.h>
00041 #include <sensor_msgs/LaserScan.h>
00042 #include <sensor_msgs/PointCloud.h>
00043 #include <pcl/io/pcd_io.h>
00044 #include <pcl/point_types.h>
00045 
00046 #include <vector>
00047 #include <fstream>
00048 
00049 using namespace std;
00050 //global values
00051 float g_speed = 0.0;
00052 bool g_is_move = false;
00053 float g_motor_deg = 0.0;
00054 char *g_motor_dir;
00055 
00056 class SickLaser
00057 {
00058 public:
00059   SickLaser ();
00060   ~SickLaser ();
00061 public:
00062   bool laserIsSaveDataAsPCD (char *c_is_save);
00063   void laserGetMotorMoveTime (double f_time);
00064   void laserGetDataCallBack (const sensor_msgs::LaserScan::ConstPtr & laser);
00065   void laserGetScanDegree (float f_degree);
00066 private:
00067     ros::NodeHandle nh_;
00068     ros::Subscriber sub_;
00069 
00070     vector < double >one_frame_vec_;    
00071     vector < vector < double > >data_vec_;       
00072     vector < double >timestamp_vec_;    //save the angle between two laser lines
00073 
00074   bool is_save_as_PCD_;
00075   ros::Time time_start_;
00076   static float f_count_;
00077   float first_scan_degree_;
00078   double motor_move_time_;
00079 };
00080 
00081 float SickLaser::f_count_ = 0.0;        //the number of frame that the laser has scaned
00082 
00083 SickLaser::SickLaser ()
00084 {
00085   sub_ = nh_.subscribe ("/scan", 1000, &SickLaser::laserGetDataCallBack, this); //create a subscriber
00086 
00087   one_frame_vec_.reserve (361); //save one frame data
00088   data_vec_.reserve (800);      //save point cloud 
00089   timestamp_vec_.reserve (800);
00090   is_save_as_PCD_ = true;       //whether the point cloud is saved as PCD file. 
00091   time_start_ = ros::Time::now ();
00092   first_scan_degree_ = 0.0;
00093   motor_move_time_ = 0.0;
00094 }
00095 
00096 SickLaser::~SickLaser ()
00097 {
00098 }
00099 
00100 bool SickLaser::laserIsSaveDataAsPCD (char *c_is_save)
00101 {
00102   if (!strcmp (c_is_save, "y"))
00103   {
00104     is_save_as_PCD_ = true;
00105   }
00106   else
00107     is_save_as_PCD_ = false;
00108 
00109   return is_save_as_PCD_;
00110 }
00111 
00112 void SickLaser::laserGetMotorMoveTime (double f_time)   //get the time stamp
00113 {
00114   motor_move_time_ = f_time + 0.2;
00115 }
00116 
00117 void SickLaser::laserGetScanDegree (float f_degree)
00118 {
00119   first_scan_degree_ = f_degree / 180.0 * 3.1415;
00120 }
00121 
00122 void SickLaser::laserGetDataCallBack (const sensor_msgs::LaserScan::ConstPtr & laser)
00123 {
00124   if (g_is_move)
00125   {
00126     double duration = ros::Time::now ().toSec () - motor_move_time_;    //here
00127     if (duration * g_speed < g_motor_deg)
00128     {
00129       for (int i = 0; i < 361; ++i)
00130       {
00131         one_frame_vec_.push_back (laser->ranges[i]);
00132       }
00133       data_vec_.push_back (one_frame_vec_);
00134       timestamp_vec_.push_back (laser->header.stamp.toSec ());
00135       one_frame_vec_.clear ();
00136       f_count_++;
00137       ROS_INFO ("f_count_ = %f", f_count_);
00138     }
00139     else
00140     {
00141       float scandegree = duration * g_speed;
00142       ROS_INFO ("scan %f frame ", f_count_);
00143       ROS_INFO ("scan degree is: %f", scandegree);
00144       g_is_move = false;
00145 
00146       float angleResolution = laser->angle_increment;   //  resolution of laser
00147       //float anglePerFrame = duration.toSec()*g_speed/(f_count_-1)/180*3.14159;// degree between two frames,unit:rad
00148       vector < double >vecAnglePerFrame;
00149       vecAnglePerFrame.resize (timestamp_vec_.size ());
00150       for (int i = 0; i < (int) timestamp_vec_.size (); i++)
00151       {
00152         vecAnglePerFrame[i] = (timestamp_vec_[i] - motor_move_time_) * g_speed / 180 * 3.14159;
00153       }
00154 
00155       int iCloudWidth = 361;    //width of point cloud =  the points number of one frame
00156       int iCloudHeight = f_count_;      //height of point cloud = the number of frames
00157 
00158       if (is_save_as_PCD_)      //save the point cloud as PCD file
00159       {
00160         ROS_INFO ("save as a PCD file ");
00161         pcl::PointCloud < pcl::PointXYZ > cloudScan;
00162         cloudScan.width = iCloudWidth;
00163         cloudScan.height = iCloudHeight;
00164         cloudScan.is_dense = false;
00165         cloudScan.points.resize (cloudScan.width * cloudScan.height);
00166 
00167         if (strcmp (g_motor_dir, "0") == 0)
00168         {
00169           for (int i = 0; i < iCloudHeight; i++)        //caculate the 3D x,y,z coordinates
00170             for (int j = 0; j < iCloudWidth; j++)
00171             {
00172               cloudScan.points[i * iCloudWidth + j].x =
00173                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ - vecAnglePerFrame[i]);
00174               cloudScan.points[i * iCloudWidth + j].y =
00175                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ - vecAnglePerFrame[i]);
00176               cloudScan.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00177             }
00178         }
00179         else if (strcmp (g_motor_dir, "1") == 0)
00180         {
00181           for (int i = 0; i < iCloudHeight; i++)
00182             for (int j = 0; j < iCloudWidth; j++)
00183             {
00184               cloudScan.points[i * iCloudWidth + j].x =
00185                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ + vecAnglePerFrame[i]);
00186               cloudScan.points[i * iCloudWidth + j].y =
00187                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ + vecAnglePerFrame[i]);
00188               cloudScan.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00189             }
00190         }
00191         pcl::io::savePCDFileASCII ("laser.pcd", cloudScan);
00192 
00193         ROS_INFO ("save end");
00194       }
00195       else
00196       {
00197         ros::NodeHandle nhCloud;
00198         ros::Publisher cloud_pub = nhCloud.advertise < sensor_msgs::PointCloud > ("cloud", 50); //create a publisher
00199 
00200         int iCloudWidth = 361;
00201         int iCloudHeight = f_count_;
00202 
00203         sensor_msgs::PointCloud cloud;
00204         cloud.header.stamp = ros::Time::now ();
00205         cloud.header.frame_id = "sensor_frame";
00206 
00207         cloud.points.resize (iCloudWidth * iCloudHeight);
00208 
00209         cloud.channels.resize (1);
00210         cloud.channels[0].name = "intensities";
00211 
00212         if (strcmp (g_motor_dir, "0") == 0)
00213         {
00214           for (int i = 0; i < iCloudHeight; i++)
00215             for (int j = 0; j < iCloudWidth; j++)
00216             {
00217               cloud.points[i * iCloudWidth + j].x =
00218                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ - vecAnglePerFrame[i]);
00219               cloud.points[i * iCloudWidth + j].y =
00220                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ - vecAnglePerFrame[i]);
00221               cloud.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00222             }
00223         }
00224         else if (strcmp (g_motor_dir, "1") == 0)
00225         {
00226           for (int i = 0; i < iCloudHeight; i++)
00227             for (int j = 0; j < iCloudWidth; j++)
00228             {
00229               cloud.points[i * iCloudWidth + j].x =
00230                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ + vecAnglePerFrame[i]);
00231               cloud.points[i * iCloudWidth + j].y =
00232                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ + vecAnglePerFrame[i]);
00233               cloud.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00234             }
00235         }
00236         sleep (3);
00237         cloud_pub.publish (cloud);
00238       }
00239       sleep (1);
00240       
00241       return;
00242     }
00243   }
00244 
00245 }
00246 
00247 int main (int argc, char **argv)
00248 {
00249   ros::init (argc, argv, "getdata");
00250 
00251   int port = atoi (argv[1]);    //'1'->port1, '2'->port2
00252   g_motor_dir = argv[2];        //motor direction
00253   int motor_fre = atoi (argv[3]);       //motor frequency
00254   g_motor_deg = atoi (argv[4]) * 1.0;   //degree to move
00255   float firstdegree = atoi (argv[5]) * 1.0;
00256   char *is_save_as_pcd = argv[6];       //whethere saved as PCD file
00257 
00258   ROS_INFO ("port is %d\n", port);
00259   ROS_INFO ("direction is %s\n", g_motor_dir);
00260   ROS_INFO ("frequency is %d\n", motor_fre);
00261   ROS_INFO ("degree is %f\n", g_motor_deg);
00262 
00263   g_speed = motor_fre * STEP_DIS * SUBDIVISION / 180;   //g_speed of motor,unit:degree/second
00264 
00265   Motor myMotor (port, g_motor_dir, motor_fre, g_motor_deg);
00266   SickLaser laser;
00267 
00268   laser.laserIsSaveDataAsPCD (is_save_as_pcd);
00269   laser.laserGetScanDegree (firstdegree);
00270   double ts = myMotor.motorMove ();
00271   laser.laserGetMotorMoveTime (ts);
00272   g_is_move = true;
00273 
00274   ros::spin ();
00275 
00276   return 0;
00277 }


sick_laser
Author(s): Zhao Cilang,Yan Fei,Zhuang Yan/zhuang@dlut.edu.cn
autogenerated on Sun Jan 5 2014 11:05:03