vision_to_laser.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 "ros/ros.h"
00034 #include "sensor_msgs/LaserScan.h"
00035 #include <sensor_msgs/PointCloud.h>
00036 #include <pcl/io/pcd_io.h>
00037 #include <pcl/point_types.h>
00038 
00039 #include <opencv/highgui.h>
00040 #include <opencv/cv.h>
00041 
00042 #include "laser_points_colouration/point3d.h"
00043 #include "laser_points_colouration/point_color.h"
00044 
00045 #include <vector>
00046 #include <fstream>
00047 #include <cmath>
00048 
00049 #define nWidth 1280
00050 #define nHeight 960
00051 
00052 class VisionToLaser
00053 {
00054 public:
00055   VisionToLaser ();
00056   ~VisionToLaser ();
00057 public:
00058   void loadParameters ();       //load the parameters
00059   void loadLaserPoints (char *_filename);       //load laser data
00060   void loadVisionImage ();      //load vision data
00061   void visionToLaser ();        //colored the laser points
00062   bool saveData ();             //save the colored data
00063   void getSceneNum (int scene_num_);    //get the scene number
00064   void getImageMovedDegree ();  //get the degree which image is captured at
00065 private:
00066     ros::NodeHandle nh_;
00067 private:                       //some matrices and vectors
00068   CvMat * intrinsic_M_;
00069   CvMat *rotation_M_;
00070   CvMat *translate_V_;
00071   CvMat *target_V_;
00072   CvMat *far_left_point_;
00073   CvMat *far_right_point_;
00074 
00075   float left_bound_;            //bounder of points
00076   float right_bound_;
00077   float upper_bound_;
00078   float lower_bound_;
00079   float front_bound_;
00080   float back_bound_;
00081 
00082   std::vector < std::vector < CPoint3d > >laser_data_vec_;
00083   std::vector < std::vector < CPoint3d > >laser_data_raw_vec_;
00084   std::vector < std::vector < CPointColor > >data_color_vec_;
00085   IplImage *image[8];
00086 
00087   double image_moved_degree_[8];
00088 
00089   int n_scene_num_;
00090 };
00091 
00092 VisionToLaser::VisionToLaser ()
00093 {
00094   intrinsic_M_ = cvCreateMat (3, 3, CV_32FC1);
00095   rotation_M_ = cvCreateMat (3, 3, CV_32FC1);
00096   translate_V_ = cvCreateMat (3, 1, CV_32FC1);
00097   target_V_ = cvCreateMat (3, 1, CV_32FC1);
00098 
00099   far_left_point_ = cvCreateMat (3, 1, CV_32FC1);
00100   far_right_point_ = cvCreateMat (3, 1, CV_32FC1);
00101 
00102   left_bound_ = 0.0;
00103   right_bound_ = 0.0;
00104   upper_bound_ = 0.0;
00105   lower_bound_ = 0.0;
00106   front_bound_ = 0.0;
00107   back_bound_ = 0.0;
00108 
00109   laser_data_vec_.reserve (2000);
00110   data_color_vec_.resize (2000);
00111   laser_data_raw_vec_.reserve (2000);
00112 
00113   for (int i = 0; i < 8; i++)
00114   {
00115     image[i] = NULL;
00116   }
00117 
00118   n_scene_num_ = 0;
00119 }
00120 
00121 VisionToLaser::~VisionToLaser ()
00122 {
00123   cvReleaseMat (&intrinsic_M_);
00124   cvReleaseMat (&rotation_M_);
00125   cvReleaseMat (&translate_V_);
00126   cvReleaseMat (&target_V_);
00127   cvReleaseMat (&far_left_point_);
00128   cvReleaseMat (&far_right_point_);
00129 }
00130 
00131 void VisionToLaser::loadParameters ()
00132 {
00133   intrinsic_M_ = (CvMat *) cvLoad ("Intrinsics.xml");   //load intrinsics , translation and rotation matrix
00134   translate_V_ = (CvMat *) cvLoad ("translation.xml");
00135   rotation_M_ = (CvMat *) cvLoad ("rotation.xml");
00136 
00137   left_bound_ = 50.0;
00138   right_bound_ = -50.0;
00139   upper_bound_ = 50.0;
00140   lower_bound_ = -50.0;
00141   front_bound_ = 0.5;
00142   back_bound_ = 50.0;
00143 
00144 }
00145 
00146 void VisionToLaser::loadLaserPoints (char *_filename)
00147 {
00148   pcl::PointCloud < pcl::PointXYZ >::Ptr cloud (new pcl::PointCloud < pcl::PointXYZ >);
00149 
00150   if (pcl::io::loadPCDFile < pcl::PointXYZ > (_filename, *cloud) == -1) //load the pcd file
00151   {
00152     PCL_ERROR ("Couldn't read file \n");
00153     return;
00154   }
00155   else
00156     printf ("points number = %d\n", cloud->width * cloud->height);
00157 
00158   std::vector < CPoint3d > vec_laserdata;
00159   vec_laserdata.reserve (361);
00160   CPoint3d p;
00161   for (unsigned int j = 0; j < cloud->points.size () / 361; j++)
00162   {
00163     for (unsigned int i = 0; i < 361; i++)
00164     {
00165       p.x = cloud->points[j * 361 + i].x;
00166       p.y = cloud->points[j * 361 + i].y;
00167       p.z = cloud->points[j * 361 + i].z;
00168       vec_laserdata.push_back (p);
00169     }
00170     laser_data_raw_vec_.push_back (vec_laserdata);
00171     vec_laserdata.clear ();
00172   }
00173   ROS_INFO ("Read the laser data successfully!");
00174 }
00175 
00176 void VisionToLaser::loadVisionImage ()
00177 {
00178   char _imagename[50];
00179   for (int _imagenum = 0; _imagenum < 8; _imagenum++)   //load the images
00180   {
00181     bzero (_imagename, sizeof (_imagename));
00182     sprintf (_imagename, "image%d.bmp", _imagenum + 1);
00183     image[_imagenum] = cvLoadImage (_imagename, CV_LOAD_IMAGE_COLOR);
00184   }
00185 }
00186 
00187 void VisionToLaser::getSceneNum (int scene_num_)
00188 {
00189   n_scene_num_ = scene_num_;
00190 }
00191 
00192 void VisionToLaser::getImageMovedDegree ()
00193 {
00194   std::ifstream mr_imgtime ("imagetimestamp.txt");      //get the degree from timestamps
00195   double imgtime[9];
00196   std::ifstream mr_motortime ("motortimestamp.txt");
00197   double motortime;
00198   if (mr_imgtime.is_open ())
00199   {
00200     ROS_INFO ("Start read the image timestamp!");
00201     for (int i = 0; i < 9; i++)
00202     {
00203       mr_imgtime >> imgtime[i];
00204     }
00205   }
00206   else
00207   {
00208     ROS_INFO ("Read the image timestamp fail");
00209     
00210     return;
00211   }
00212   mr_imgtime.close ();
00213   if (mr_motortime.is_open ())
00214   {
00215     ROS_INFO ("Start read the motor timestamp!");
00216     mr_motortime >> motortime;
00217   }
00218   else
00219   {
00220     ROS_INFO ("Read the motor timestamp fail");
00221     
00222     return;
00223   }
00224   mr_motortime.close ();
00225   image_moved_degree_[0] = 0.0; //calculate the degree which images are get at                      
00226   for (int j = 1; j < 8; j++)
00227   {
00228     image_moved_degree_[j] = (imgtime[j + 1] - motortime - 0.2) * 9.0 / 180.0 * 3.1415;
00229   }
00230 }
00231 
00232 void VisionToLaser::visionToLaser ()
00233 {
00234   size_t laserHeight = laser_data_raw_vec_.size ();
00235   size_t laserWidth = 361;
00236   data_color_vec_.resize (laserHeight);
00237   for (size_t j = 0; j < laserHeight; j++)
00238     data_color_vec_[j].resize (laserWidth);
00239 
00240   size_t totalPointsNum = laserHeight * laserWidth;
00241   CvMat *regionPoints = cvCreateMat ((int) totalPointsNum, 3, CV_32FC1);
00242   CvMat *pointIndex = cvCreateMat ((int) totalPointsNum, 1, CV_32SC1);
00243 
00244   float *regionPtr = NULL;      //regionPoints->data.fl;
00245   int *pointIndexPtr = NULL;    //pointIndex->data.i;
00246 
00247   float x, y, z;
00248   size_t counter;
00249   size_t regionPointsNum;
00250 
00251   unsigned char *img_data;
00252   int img_step = 0;
00253   int img_channels = 0;
00254 
00255   int inRangeX;
00256   int inRangeY;
00257   size_t reducedPointsNum = 0;
00258 
00259   size_t laser_Index = 0;
00260   // read in the laser points as cvMat
00261   std::vector < CPoint3d > vec_data;
00262   vec_data.reserve (361);
00263   CPoint3d p;
00264   for (int scenecount = 0; scenecount < 8; scenecount++)
00265   {
00266     for (int j = 0; j < (int) laser_data_raw_vec_.size (); j++)
00267     {
00268       for (int i = 0; i < 361; i++)
00269       {
00270         float x = laser_data_raw_vec_[j][i].x;
00271         float y = laser_data_raw_vec_[j][i].y;
00272         float z = laser_data_raw_vec_[j][i].z;
00273 
00274         p.x = x * cos (image_moved_degree_[scenecount]) - y * sin (image_moved_degree_[scenecount]);
00275         p.y = x * sin (image_moved_degree_[scenecount]) + y * cos (image_moved_degree_[scenecount]);
00276         p.z = z;
00277 
00278         vec_data.push_back (p);
00279       }
00280       laser_data_vec_.push_back (vec_data);
00281       vec_data.clear ();
00282     }
00283 
00284     regionPtr = regionPoints->data.fl;
00285     pointIndexPtr = pointIndex->data.i;
00286 
00287     counter = 0;
00288     regionPointsNum = 0;
00289     while (counter < totalPointsNum)    //judge whether these points are inside the boundary 
00290     {
00291       x = laser_data_vec_[counter / laserWidth][counter % laserWidth].x;
00292       y = laser_data_vec_[counter / laserWidth][counter % laserWidth].y;
00293       z = laser_data_vec_[counter / laserWidth][counter % laserWidth].z;
00294       counter++;
00295       if (y > left_bound_ || y < right_bound_)
00296       {
00297         continue;
00298       }
00299       else if (z > upper_bound_ || z < lower_bound_)
00300       {
00301         continue;
00302       }
00303       else if (x > back_bound_ || x < front_bound_)
00304       {
00305         continue;
00306       }
00307       else
00308       {
00309         regionPtr[regionPointsNum * 3 + 0] = x;
00310         regionPtr[regionPointsNum * 3 + 1] = y;
00311         regionPtr[regionPointsNum * 3 + 2] = z;
00312         pointIndexPtr[regionPointsNum] = (int) (counter - 1);
00313         regionPointsNum++;
00314       }
00315 
00316     }
00317     ROS_INFO ("regionPointsNum = %d", regionPointsNum);
00318     img_data = (unsigned char *) image[scenecount]->imageData;
00319     img_step = image[scenecount]->widthStep;
00320     img_channels = image[scenecount]->nChannels;
00321 
00322     reducedPointsNum = 0;
00323     counter = 0;
00324     laser_Index = 0;
00325 
00326     while (counter < regionPointsNum)
00327     {
00328       target_V_->data.fl[0] = x = regionPtr[counter * 3];
00329       target_V_->data.fl[1] = y = regionPtr[counter * 3 + 1];
00330       target_V_->data.fl[2] = z = regionPtr[counter * 3 + 2];
00331       counter++;
00332       // project the laser points to iamge coordinates
00333       cvGEMM (rotation_M_, target_V_, 1.0, translate_V_, 1.0, target_V_, 0);
00334       cvGEMM (intrinsic_M_, target_V_, 1.0, NULL, 0.0, target_V_, 0);
00335       // judge if the projected points are in the range 1280*960  
00336       inRangeX = int (target_V_->data.fl[0] / target_V_->data.fl[2] + 0.5);
00337       if (inRangeX < 0 || inRangeX >= nWidth)
00338       {
00339         continue;
00340       }
00341       inRangeY = int (target_V_->data.fl[1] / target_V_->data.fl[2] + 0.5);
00342       if (inRangeY < 0 || inRangeY >= nHeight)
00343       {
00344         continue;
00345       }
00346 
00347       laser_Index = pointIndexPtr[counter - 1];
00348       /*if (data_color_vec_[laser_Index/laserWidth][laser_Index%laserWidth].bIsColored == false)
00349          {
00350          data_color_vec_[laser_Index/laserWidth][laser_Index%laserWidth].r =
00351          img_data[inRangeY*img_step+inRangeX*img_channels+2]/255.0;
00352          data_color_vec_[laser_Index/laserWidth][laser_Index%laserWidth].g =
00353          img_data[inRangeY*img_step+inRangeX*img_channels+1]/255.0;
00354          data_color_vec_[laser_Index/laserWidth][laser_Index%laserWidth].b =
00355          img_data[inRangeY*img_step+inRangeX*img_channels]/255.0;
00356          data_color_vec_[laser_Index/laserWidth][laser_Index%laserWidth].bIsColored = true;
00357          reducedPointsNum++;
00358          } */
00359       //colored the laser points with image
00360       data_color_vec_[laser_Index / laserWidth][laser_Index % laserWidth].r =
00361         img_data[inRangeY * img_step + inRangeX * img_channels + 2] / 255.0;
00362       data_color_vec_[laser_Index / laserWidth][laser_Index % laserWidth].g =
00363         img_data[inRangeY * img_step + inRangeX * img_channels + 1] / 255.0;
00364       data_color_vec_[laser_Index / laserWidth][laser_Index % laserWidth].b =
00365         img_data[inRangeY * img_step + inRangeX * img_channels] / 255.0;
00366       data_color_vec_[laser_Index / laserWidth][laser_Index % laserWidth].bIsColored = true;
00367       reducedPointsNum++;
00368     }
00369     ROS_INFO ("This is the %d scenes", scenecount);
00370     laser_data_vec_.clear ();
00371   }
00372 
00373   cvReleaseMat (&regionPoints);
00374   cvReleaseMat (&pointIndex);
00375 }
00376 
00377 bool VisionToLaser::saveData () //save colored points
00378 {
00379   std::ofstream m_w ("colordata.txt");
00380   if (!m_w.is_open ())
00381   {
00382     ROS_INFO ("Open the file colordata.txt fail\n");
00383     
00384     return false;
00385   }
00386   else
00387   {
00388     ROS_INFO ("Open the file ok,and write the colored points to this file!");
00389     for (int j = 0; j < (int) laser_data_raw_vec_.size (); j++)
00390       for (int i = 0; i < 361; i++)
00391       {
00392         m_w << laser_data_raw_vec_[j][i].x << "  " << laser_data_raw_vec_[j][i].y << "  " << laser_data_raw_vec_[j][i].
00393           z << "  " << data_color_vec_[j][i].r << "  " << data_color_vec_[j][i].g << "  " << data_color_vec_[j][i].
00394           b << "  " << data_color_vec_[j][i].bIsColored << "\n";
00395       }
00396     m_w.close ();
00397     
00398     return true;
00399   }
00400 }
00401 
00402 int main (int argc, char **argv)
00403 {
00404   char *pointcloud_name = argv[1];      //please put in the pcd file name
00405 
00406   ros::init (argc, argv, "colouration");
00407 
00408   VisionToLaser m_vtl;
00409 
00410   m_vtl.loadParameters ();
00411   m_vtl.loadLaserPoints (pointcloud_name);
00412   m_vtl.getImageMovedDegree ();
00413 
00414   m_vtl.loadVisionImage ();
00415   m_vtl.visionToLaser ();
00416 
00417   bool isSaved = m_vtl.saveData ();
00418   if (isSaved)
00419   {
00420     ROS_INFO ("Save the colored data successfully!");
00421   }
00422   else
00423   {
00424     ROS_INFO ("Save the colored data fail!");
00425     
00426     return -1;
00427   }
00428 
00429   return 0;
00430 }


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