get_cloud_and_image.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 #include "sick_laser/motor.h"
00034 #include "sick_laser/capture_image.h"
00035 
00036 #include <ros/ros.h>
00037 #include <sensor_msgs/LaserScan.h>
00038 #include <sensor_msgs/PointCloud.h>
00039 #include <pcl/io/pcd_io.h>
00040 #include <pcl/point_types.h>
00041 
00042 #include <stdio.h>
00043 #include <vector>
00044 #include <fstream>
00045 
00046 using namespace std;
00047 //global values
00048 float g_speed = 0.0;
00049 bool g_is_motor_move = false;
00050 float g_motor_deg = 0.0;
00051 char *g_motor_dir;
00052 
00053 class SickLaser
00054 {
00055 public:
00056   SickLaser ();
00057   ~SickLaser ();
00058 public:
00059   bool laserIsSaveDataAsPCD (char *p_is_save);
00060   void laserGetMotorMoveTime (double f_time);
00061   void laserGetDataCallBack (const sensor_msgs::LaserScan::ConstPtr & laser);
00062   void laserGetScanDegree (float f_degree);
00063 public:
00064   CameraCapture m_camera_;
00065 private:
00066   ros::NodeHandle nh_;
00067   ros::Subscriber sub_;
00068 
00069   vector < double > one_frame_vec_;    //每一帧的vector,此处给出大小,开辟内存空间
00070   vector < vector < double > > data_vec_;       //原始点云vector,此处给出大小,开辟内存空间
00071   vector < double > timestamp_vec_;    //save the angle between two laser lines
00072 
00073   bool b_is_save_as_pcd_;
00074   ros::Time time_start_;
00075   static float n_count_;
00076   float first_scan_degree_;
00077   double motor_move_time_;
00078   int n_image_count_;
00079   bool is_captured_;
00080 };
00081 
00082 float SickLaser::n_count_ = 0.0;        //the number of frame that the laser has scaned
00083 
00084 SickLaser::SickLaser ()
00085 {
00086   sub_ = nh_.subscribe ("/scan", 1000, &SickLaser::laserGetDataCallBack, this); //create a subscriber
00087 
00088   one_frame_vec_.reserve (361); //save one frame data
00089   data_vec_.reserve (2000);     //save point cloud 
00090   timestamp_vec_.reserve (2000);
00091   b_is_save_as_pcd_ = true;     //whether the point cloud is saved as PCD file. 
00092   time_start_ = ros::Time::now ();
00093   first_scan_degree_ = 0.0;
00094   motor_move_time_ = 0.0;
00095   n_image_count_ = 1;
00096   is_captured_ = false;
00097 
00098   m_camera_.camPrintBuildInfo ();
00099   m_camera_.camConnect ();
00100 }
00101 
00102 SickLaser::~SickLaser ()
00103 {
00104 }
00105 
00106 bool SickLaser::laserIsSaveDataAsPCD (char *p_is_save)
00107 {
00108   if (!strcmp (p_is_save, "y"))
00109   {
00110     b_is_save_as_pcd_ = true;
00111   }
00112   else
00113     b_is_save_as_pcd_ = false;
00114 
00115   return b_is_save_as_pcd_;
00116 }
00117 
00118 void SickLaser::laserGetMotorMoveTime (double f_time)   //get the time stamp
00119 {
00120   motor_move_time_ = f_time + 0.2;
00121   //motor_move_time_ = f_time;
00122 }
00123 
00124 void SickLaser::laserGetScanDegree (float f_degree)
00125 {
00126   first_scan_degree_ = f_degree / 180.0 * 3.1415;
00127 }
00128 
00129 void SickLaser::laserGetDataCallBack (const sensor_msgs::LaserScan::ConstPtr & laser)
00130 {
00131   if (g_is_motor_move)
00132   {
00133     double duration = ros::Time::now ().toSec () - motor_move_time_;    //here
00134     if (duration * g_speed < g_motor_deg)
00135     {
00136       if (((duration * g_speed - n_image_count_ * 45.0) < 0.5) && (!is_captured_))
00137       {
00138         m_camera_.camImageCapture (n_image_count_);
00139         n_image_count_++;
00140         is_captured_ = true;
00141       }
00142       for (int i = 0; i < 361; ++i)
00143       {
00144         one_frame_vec_.push_back (laser->ranges[i]);
00145       }
00146       data_vec_.push_back (one_frame_vec_);
00147       timestamp_vec_.push_back (laser->header.stamp.toSec ());
00148       one_frame_vec_.clear ();
00149       n_count_++;
00150       //ROS_INFO("n_count_ = %f\n",n_count_ );
00151 
00152       if (duration * g_speed - (n_image_count_ - 1) * 45.0 > 10.0)
00153       {
00154         is_captured_ = false;
00155       }
00156     }
00157     else
00158     {
00159       m_camera_.camStopCapture ();
00160       float scandegree = duration * g_speed;
00161       ROS_INFO ("scan %f frame ", n_count_);
00162       ROS_INFO ("scan degree is: %f", scandegree);
00163       g_is_motor_move = false;
00164 
00165       float angleResolution = laser->angle_increment;   //  resolution of laser
00166       //float anglePerFrame = duration.toSec()*g_speed/(n_count_-1)/180*3.14159;// degree between two frames,unit:rad
00167       //save the timestamp
00168       ofstream m_of1 ("lasertimestamp.txt");
00169       ofstream m_of2 ("motortimestamp.txt");
00170       char buf[50];
00171       if (m_of1.is_open ())
00172       {
00173         for (int i = 0; i < (int) timestamp_vec_.size (); i++)
00174         {
00175           bzero (buf, sizeof (buf));
00176           sprintf (buf, "%lf", timestamp_vec_[i]);
00177           m_of1 << buf << "\n";
00178         }
00179         m_of1.close ();
00180       }
00181       else
00182       {
00183         ROS_INFO ("open the file lasertimestamp.txt fail");
00184         return;
00185       }
00186       if (m_of2.is_open ())
00187       {
00188         sprintf (buf, "%lf", motor_move_time_ - 0.2);
00189         m_of2 << buf << "\n";
00190         m_of2.close ();
00191       }
00192       else
00193       {
00194         ROS_INFO ("open the file motortimestamp.txt fail");
00195         return;
00196       }
00197 
00198       vector < double >vecAnglePerFrame;
00199       vecAnglePerFrame.resize (timestamp_vec_.size ());
00200       for (int i = 0; i < (int) timestamp_vec_.size (); i++)
00201       {
00202         vecAnglePerFrame[i] = (timestamp_vec_[i] - motor_move_time_) * g_speed / 180 * 3.14159;
00203       }
00204 
00205       int iCloudWidth = 361;    //width of point cloud =  the points number of one frame
00206       int iCloudHeight = n_count_;      //height of point cloud = the number of frames
00207 
00208       if (b_is_save_as_pcd_)    //save the point cloud as PCD file
00209       {
00210         ROS_INFO ("save as a PCD file \n");
00211         pcl::PointCloud < pcl::PointXYZ > cloudScan;
00212         cloudScan.width = iCloudWidth;
00213         cloudScan.height = iCloudHeight;
00214         cloudScan.is_dense = false;
00215         cloudScan.points.resize (cloudScan.width * cloudScan.height);
00216 
00217         if (strcmp (g_motor_dir, "0") == 0)
00218         {
00219           for (int i = 0; i < iCloudHeight; i++)        //caculate the 3D x,y,z coordinates
00220             for (int j = 0; j < iCloudWidth; j++)
00221             {
00222               cloudScan.points[i * iCloudWidth + j].x =
00223                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ - vecAnglePerFrame[i]);
00224               cloudScan.points[i * iCloudWidth + j].y =
00225                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ - vecAnglePerFrame[i]);
00226               cloudScan.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00227             }
00228         }
00229         else if (strcmp (g_motor_dir, "1") == 0)
00230         {
00231           for (int i = 0; i < iCloudHeight; i++)
00232             for (int j = 0; j < iCloudWidth; j++)
00233             {
00234               cloudScan.points[i * iCloudWidth + j].x =
00235                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ + vecAnglePerFrame[i]);
00236               cloudScan.points[i * iCloudWidth + j].y =
00237                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ + vecAnglePerFrame[i]);
00238               cloudScan.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00239             }
00240         }
00241         pcl::io::savePCDFileASCII ("laserdata.pcd", cloudScan);
00242 
00243         ROS_INFO ("save end");
00244       }
00245       else
00246       {
00247         ros::NodeHandle nhCloud;
00248         ros::Publisher cloud_pub = nhCloud.advertise < sensor_msgs::PointCloud > ("cloud", 50); //create a publisher
00249 
00250         int iCloudWidth = 361;
00251         int iCloudHeight = n_count_;
00252 
00253         sensor_msgs::PointCloud cloud;
00254         cloud.header.stamp = ros::Time::now ();
00255         cloud.header.frame_id = "sensor_frame";
00256 
00257         cloud.points.resize (iCloudWidth * iCloudHeight);
00258 
00259         cloud.channels.resize (1);
00260         cloud.channels[0].name = "intensities";
00261 
00262         if (strcmp (g_motor_dir, "0") == 0)
00263         {
00264           for (int i = 0; i < iCloudHeight; i++)
00265             for (int j = 0; j < iCloudWidth; j++)
00266             {
00267               cloud.points[i * iCloudWidth + j].x =
00268                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ - vecAnglePerFrame[i]);
00269               cloud.points[i * iCloudWidth + j].y =
00270                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ - vecAnglePerFrame[i]);
00271               cloud.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00272             }
00273         }
00274         else if (strcmp (g_motor_dir, "1") == 0)
00275         {
00276           for (int i = 0; i < iCloudHeight; i++)
00277             for (int j = 0; j < iCloudWidth; j++)
00278             {
00279               cloud.points[i * iCloudWidth + j].x =
00280                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * cos (first_scan_degree_ + vecAnglePerFrame[i]);
00281               cloud.points[i * iCloudWidth + j].y =
00282                 data_vec_[i][j] * sin (0.0 + j * angleResolution) * sin (first_scan_degree_ + vecAnglePerFrame[i]);
00283               cloud.points[i * iCloudWidth + j].z = data_vec_[i][j] * cos (0.0 + j * angleResolution);
00284             }
00285         }
00286         sleep (3);
00287         cloud_pub.publish (cloud);
00288       }
00289       sleep (1);
00290       
00291       return;
00292     }
00293   }
00294 
00295 }
00296 
00297 int main (int argc, char **argv)
00298 {
00299   ros::init (argc, argv, "getdata");
00300 
00301   int port = atoi (argv[1]);    //'1'->port1, '2'->port2
00302   g_motor_dir = argv[2];        //motor direction
00303   int motor_fre = atoi (argv[3]);       //motor frequency
00304   g_motor_deg = atoi (argv[4]) * 1.0;   //degree to move
00305   float firstdegree = atoi (argv[5]) * 1.0;
00306   char *cIsSaveAsPCD = argv[6]; //whethere saved as PCD file
00307 
00308   ROS_INFO ("port is %d", port);
00309   ROS_INFO ("direction is %s", g_motor_dir);
00310   ROS_INFO ("frequency is %d", motor_fre);
00311   ROS_INFO ("degree is %f", g_motor_deg);
00312 
00313   g_speed = motor_fre * STEP_DIS * SUBDIVISION / 180;   //g_speed of motor,unit:degree/second
00314 
00315   Motor myMotor (port, g_motor_dir, motor_fre, g_motor_deg);
00316 
00317   SickLaser laser;
00318   laser.laserIsSaveDataAsPCD (cIsSaveAsPCD);
00319   laser.laserGetScanDegree (firstdegree);
00320   laser.m_camera_.camImageCapture (0);
00321 
00322   double ts = myMotor.motorMove ();
00323   ROS_INFO ("Motor move at %lf", ts);
00324   laser.laserGetMotorMoveTime (ts);
00325   g_is_motor_move = true;
00326 
00327   ros::spin ();
00328 
00329   return 0;
00330 }


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