pmdcamera_driver_node.cpp
Go to the documentation of this file.
00001 #include "pmdcamera_driver_node.h"
00002 #include <boost/make_shared.hpp>
00003 #include "exceptions.h"
00004 
00005 PmdcameraDriverNode::PmdcameraDriverNode(ros::NodeHandle &nh) : iri_base_driver::IriBaseNodeDriver<PmdcameraDriver>(nh) {
00006 
00007   max_intensity_ = 50000.0;  // This value doesn't need to be fixed for calibration.(experimentally it didn't overpass 34539.2)
00008   max_amplitude_ = 50000.0;  // This value needs to be fixed for calibration.(experimentally it didn't overpass 48776.8)
00009   //TODO: Canviar la max_depth segons la frequencia de modulacio
00010   max_depth_ = 7.5;  // (experimentally it didn't overpass 7.49)
00011 
00012   int camera_type=0;
00013   private_node_handle_.param<int>("camera_type", camera_type, pmd_camera::camboard);
00014   std::string frame_id="/camboard_frame";
00015   private_node_handle_.param<std::string>("frame_id", frame_id, "/camboard_frame");
00016 
00017   int int_time=700;
00018   private_node_handle_.param<int>("integration_time", int_time, 700);
00019   int mod_freq=20000000;
00020   private_node_handle_.param<int>("modulation_freq", mod_freq, 20000000);
00021 
00022   if (camera_type==pmd_camera::camboard) {
00023     driver_.setCameraType(pmd_camera::camboard);
00024     ROS_INFO("Camera type CAMBOARD");
00025   } else  if (camera_type==pmd_camera::camcube) {
00026     driver_.setCameraType(pmd_camera::camcube);
00027     ROS_INFO("Camera type CAMCUBE");  
00028   } else {
00029     ROS_WARN("Camera type not recognized. Trying camboard...");  
00030   }
00031 
00032   driver_.setIntegrationTime(int_time);
00033   driver_.setModulationFrequency(mod_freq);
00034 
00035   // Obtain real camera width and height
00036   real_width_  = driver_.getWidth();  // 207
00037   real_height_ = driver_.getHeight(); // 204
00038 
00039   //CamBoard has some dead pixels and efective image size is 200x200
00040   ROS_INFO("Raw Image size %d %d", real_width_, real_height_);
00041 
00042   // Define working camera width and height
00043   width_  = 200;
00044   height_ = 200;
00045 
00046   // Init class attributes if necessary
00047   loop_rate_ = 50; //in [Hz]
00048 
00049   // Assemble the point cloud data
00050   if(camera_type==pmd_camera::camboard){
00051     pcl2_int_msg_.header.frame_id = std::string (frame_id);
00052     pcl2_amp_msg_.header.frame_id = std::string (frame_id);
00053     pcl2_range_msg_.header.frame_id = std::string (frame_id);
00054   } else if (camera_type==pmd_camera::camcube) {
00055     pcl2_int_msg_.header.frame_id = std::string (frame_id);
00056     pcl2_amp_msg_.header.frame_id = std::string (frame_id);
00057     pcl2_range_msg_.header.frame_id = std::string (frame_id);
00058   } else {
00059     ROS_WARN("Camera type not recognized. Trying again...");  
00060   }
00061 
00062   // PointCloud_int is XYZI
00063   pcl2_int_msg_.height         = height_;
00064   pcl2_int_msg_.width          = width_;
00065   pcl2_int_msg_.fields.resize (4);
00066   pcl2_int_msg_.fields[0].name = "x";
00067   pcl2_int_msg_.fields[1].name = "y";
00068   pcl2_int_msg_.fields[2].name = "z";
00069   pcl2_int_msg_.fields[3].name = "intensity";
00070   // PointCloud_amp is XYZI
00071   pcl2_amp_msg_.height         = height_;
00072   pcl2_amp_msg_.width          = width_;
00073   pcl2_amp_msg_.fields.resize (4);
00074   pcl2_amp_msg_.fields[0].name = "x";
00075   pcl2_amp_msg_.fields[1].name = "y";
00076   pcl2_amp_msg_.fields[2].name = "z";
00077   pcl2_amp_msg_.fields[3].name = "intensity";
00078   // PointCloud_range is PointWithRange
00079   pcl2_range_msg_.height         = height_;
00080   pcl2_range_msg_.width          = width_;
00081   pcl2_range_msg_.fields.resize (5);
00082   pcl2_range_msg_.fields[0].name = "x";
00083   pcl2_range_msg_.fields[1].name = "y";
00084   pcl2_range_msg_.fields[2].name = "z";
00085   pcl2_range_msg_.fields[3].name = "range";
00086   pcl2_range_msg_.fields[4].name = "intensity";
00087 
00088   // Set all the fields types accordingly
00089   int offset = 0;
00090   // pcl2_int and pcl2_amp
00091   for (size_t s = 0; s < pcl2_int_msg_.fields.size (); ++s, offset += 4)
00092   {
00093     pcl2_int_msg_.fields[s].offset   = offset;
00094     pcl2_int_msg_.fields[s].count    = 1;
00095     pcl2_int_msg_.fields[s].datatype = sensor_msgs::PointField::FLOAT32;
00096     pcl2_amp_msg_.fields[s].offset   = offset;
00097     pcl2_amp_msg_.fields[s].count    = 1;
00098     pcl2_amp_msg_.fields[s].datatype = sensor_msgs::PointField::FLOAT32;
00099   }
00100   pcl2_int_msg_.point_step = offset;
00101   pcl2_int_msg_.row_step   = pcl2_int_msg_.point_step * pcl2_int_msg_.width;
00102   pcl2_int_msg_.data.resize (pcl2_int_msg_.row_step   * pcl2_int_msg_.height);
00103   pcl2_int_msg_.is_dense   = true;
00104   pcl2_amp_msg_.point_step = offset;
00105   pcl2_amp_msg_.row_step   = pcl2_amp_msg_.point_step * pcl2_amp_msg_.width;
00106   pcl2_amp_msg_.data.resize (pcl2_amp_msg_.row_step   * pcl2_amp_msg_.height);
00107   pcl2_amp_msg_.is_dense   = true;
00108 
00109   offset = 0;
00110   // pcl2_range
00111   for (size_t s = 0; s < pcl2_range_msg_.fields.size (); ++s, offset += 4)
00112   {
00113     pcl2_range_msg_.fields[s].offset   = offset;
00114     pcl2_range_msg_.fields[s].count    = 1;
00115     pcl2_range_msg_.fields[s].datatype = sensor_msgs::PointField::FLOAT32;
00116   }
00117   pcl2_range_msg_.point_step = offset;
00118   pcl2_range_msg_.row_step   = pcl2_range_msg_.point_step * pcl2_range_msg_.width;
00119   pcl2_range_msg_.data.resize (pcl2_range_msg_.row_step   * pcl2_range_msg_.height);
00120   pcl2_range_msg_.is_dense   = true;
00121 
00122   // Assemble the intensity image data
00123   Image_flags_msg_.header.frame_id = pcl2_int_msg_.header.frame_id;
00124   Image_flags_msg_.height   = height_;
00125   Image_flags_msg_.width    = width_;
00126   Image_flags_msg_.encoding = sensor_msgs::image_encodings::MONO8;
00127   Image_flags_msg_.step     = width_;
00128   Image_flags_msg_.data.resize(width_ * height_);
00129 
00130   // Assemble the intensity image data
00131   Image_int_msg_.header.frame_id = pcl2_int_msg_.header.frame_id;
00132   Image_int_msg_.height   = height_;
00133   Image_int_msg_.width    = width_;
00134   Image_int_msg_.encoding = sensor_msgs::image_encodings::MONO8;
00135   Image_int_msg_.step     = width_ * sizeof(uint8_t);
00136   Image_int_msg_.data.resize(Image_int_msg_.step * height_);
00137 
00138   // Assemble the amplitude image data
00139   Image_amp_msg_.header.frame_id = pcl2_int_msg_.header.frame_id;
00140   Image_amp_msg_.height   = height_;
00141   Image_amp_msg_.width    = width_;
00142   Image_amp_msg_.encoding = sensor_msgs::image_encodings::MONO8;
00143   Image_amp_msg_.step     = width_ * sizeof(uint8_t);
00144   Image_amp_msg_.data.resize(Image_amp_msg_.step * height_);
00145 
00146   // Assemble the depth image data
00147   Image_depth_msg_.header.frame_id = pcl2_int_msg_.header.frame_id;
00148   Image_depth_msg_.height          = height_;
00149   Image_depth_msg_.width           = width_;
00150   Image_depth_msg_.encoding        = sensor_msgs::image_encodings::TYPE_32FC1;
00151   Image_depth_msg_.step            = width_ * sizeof(float);
00152   Image_depth_msg_.data.resize(Image_depth_msg_.step * height_);
00153 
00154   //@TODO: put the paths in a configuration file?
00155   //@TODO: podem fer servir public_handler o private_handler 
00156   // Read calibration parameters from disk
00157   switch (camera_type) {
00158     case pmd_camera::camboard:
00159       public_node_handle_.param ("camera_name", camera_name_, std::string("camboard"));
00160       public_node_handle_.param ("camera_info_url", camera_info_url_, std::string("file://")+ros::package::getPath(ROS_PACKAGE_NAME)+std::string("/info/camboard_calibration.yaml"));
00161       break;
00162     case pmd_camera::camcube:
00163       public_node_handle_.param ("camera_name", camera_name_, std::string("camcube"));
00164       public_node_handle_.param ("camera_info_url", camera_info_url_, std::string("file://")+ros::package::getPath(ROS_PACKAGE_NAME)+std::string("/info/camcube_calibration.yaml"));
00165       break;
00166     default:
00167       public_node_handle_.param ("camera_name", camera_name_, std::string("camera"));
00168       public_node_handle_.param ("camera_info_url", camera_info_url_, std::string("auto"));
00169       break;
00170   }
00171 
00172   camera_info_manager_ = new camera_info_manager::CameraInfoManager(public_node_handle_, camera_name_, camera_info_url_);
00173 
00174   image_transport::ImageTransport imt(public_node_handle_);  
00175 
00176   // [init publishers]
00177   image_raw_publisher_   = imt.advertiseCamera ("intensity/image_raw", 1); 
00178   image_amp_publisher_   = imt.advertiseCamera ("amplitude/image_raw", 1);
00179   image_depth_publisher_ = imt.advertiseCamera ("distance/image_raw", 1);
00180   image_flags_publisher_ = imt.advertiseCamera ("flags/image_raw", 1);
00181   pcl_int_raw_publisher_  = public_node_handle_.advertise<sensor_msgs::PointCloud2>("pointcloud/pcl_int_raw", 1);
00182   pcl_amp_raw_publisher_  = public_node_handle_.advertise<sensor_msgs::PointCloud2>("pointcloud/pcl_amp_raw", 1);
00183   pcl_range_raw_publisher_  = public_node_handle_.advertise<sensor_msgs::PointCloud2>("pointcloud/pcl_range_raw", 1);
00184 
00185   ROS_INFO ("publishers initialized");
00186 
00187   // [init subscribers]
00188 
00189   // [init services]
00190 
00191   // [init clients]
00192 
00193   // [init action servers]
00194 
00195   // [init action clients]
00196 }
00197 
00198 
00199   void 
00200 PmdcameraDriverNode::findMaxIntensity(const float* intensity)
00201 {
00202   if (max_intensity_ == 0)
00203     for (int v = 0; v < height_; ++v)
00204       for (int u = 0; u < width_; ++u) 
00205         if (max_intensity_ < intensity[v*(width_)+u])
00206           max_intensity_ = intensity[v*(width_)+u];
00207   //ROS_INFO("max_intensity %d",max_intensity_);
00208 }
00209 
00210 void PmdcameraDriverNode::findMaxAmplitude(const float* amplitude)
00211 {
00212   if (max_amplitude_ == 0)
00213     for (int v = 0; v < height_; ++v)
00214       for (int u = 0; u < width_; ++u) 
00215         if (max_amplitude_ < amplitude[v*(width_)+u])
00216           max_amplitude_ = amplitude[v*(width_)+u];
00217   //ROS_INFO("max_amplitude %d",max_amplitude_);
00218 }
00219 
00220 void PmdcameraDriverNode::findMaxDepth(const float* distance)
00221 {
00222   if (max_depth_ == 0)
00223     for (int v = 0; v < height_; ++v)
00224       for (int u = 0; u < width_; ++u) 
00225         if (max_depth_ < distance[v*(width_)+u])
00226           max_depth_ = distance[v*(width_)+u];
00227   //ROS_INFO("max_depth %d",max_depth_);
00228 }
00229 
00230 void PmdcameraDriverNode::assembleFlagsImage(float* flags)
00231 {
00232   for (int v = 0; v < height_; ++v)
00233   {
00234     for (int u = 0; u < width_; ++u) 
00235     {
00236       int index = v * width_ + u;
00237       Image_flags_msg_.data[index] = flags[index];
00238     }
00239   }
00240 }
00241 
00242 void PmdcameraDriverNode::assembleIntensityImage(float* intensity)
00243 {
00244     //we need to obtain the intensity if not done yet
00245     findMaxIntensity(intensity);
00246     if (max_intensity_ != 0)
00247     {
00248         for (unsigned index = 0; index < Image_int_msg_.height * Image_int_msg_.width; ++index){
00249             Image_int_msg_.data[index]=intensity[index]*255/max_intensity_;
00250         }
00251     }
00252 }
00253 
00254 void PmdcameraDriverNode::assembleAmplitudeImage(float* amplitude)
00255 {
00256     //we need to obtain the intensity if not done yet
00257     //  findMaxAmplitude(amplitude);
00258     if (max_amplitude_ != 0)
00259     {
00260         for (unsigned index = 0; index < Image_amp_msg_.height * Image_amp_msg_.width; ++index){
00261             Image_amp_msg_.data[index] = amplitude[index]*255/max_amplitude_;
00262         }
00263     }
00264 }
00265 
00266 void PmdcameraDriverNode::assembleDepthImage(float* distance)
00267 {
00268   //we need to obtain the intensity if not done yet
00269   //  max_depth_ = 0; //reset intensity as now we want depth
00270   //  findMaxDepth(distance);
00271   
00272     float* raw_data = reinterpret_cast<float*>(&distance[0]);
00273     float* depth_data = reinterpret_cast<float*>(&Image_depth_msg_.data[0]);
00274     for (unsigned index = 0; index < Image_depth_msg_.height * Image_depth_msg_.width; ++index){
00275         depth_data[index] = raw_data[index];
00276     }
00277 
00278 }
00279 
00280 void PmdcameraDriverNode::assemblePcl2Int(const float* const coord_3D, const float* const intensity) 
00281 {    
00282   //we need to obtain the intensity if not done yet
00283   findMaxIntensity(intensity);
00284   if (max_intensity_ == 0 ) max_intensity_=1;
00285   // float bad_point = std::numeric_limits<float>::quiet_NaN ();
00286   // Assemble an awesome sensor_msgs/PointCloud2 message
00287   for (int v = 0; v < height_; v++)
00288   {
00289     for (int u = 0; u < width_; u++) 
00290     {
00291       int index = v * width_ + u;
00292       int index1 = v * real_width_ + u;
00293       int index3 = (v * real_width_ + u)*3;
00294 
00295       float *pstep = (float*)&pcl2_int_msg_.data[(index) * pcl2_int_msg_.point_step];
00296       //flip vertically !!!
00297       pstep[0] = coord_3D[index3];
00298       pstep[1] = coord_3D[index3+1];
00299       pstep[2] = coord_3D[index3+2];
00300       pstep[3] = intensity[index1]*255/max_intensity_;
00301 
00302       //RGBValue intensity_rgb;
00303       //intensity_rgb.Red = intensity_rgb.Green = intensity_rgb.Blue = intensity[index1]*255/max_intensity_;
00304       //pstep[3] = intensity_rgb.float_value;
00305 
00306     }
00307   }
00308 }
00309 
00310 void PmdcameraDriverNode::assemblePcl2Amp(const float* const coord_3D, const float* const amplitude) 
00311 {    
00312   // float bad_point = std::numeric_limits<float>::quiet_NaN ();
00313   // Assemble an awesome sensor_msgs/PointCloud2 message
00314   for (int v = 0; v < height_; v++){
00315     for (int u = 0; u < width_; u++){
00316       int index = v * width_ + u;
00317       int index1 = v * real_width_ + u;
00318       int index3 = (v * real_width_ + u)*3;
00319 
00320       float *pstep = (float*)&pcl2_amp_msg_.data[(index) * pcl2_amp_msg_.point_step];
00321       //flip vertically !!!
00322       pstep[0] = coord_3D[index3];
00323       pstep[1] = coord_3D[index3+1];
00324       pstep[2] = coord_3D[index3+2];
00325       pstep[3] = amplitude[index1];
00326       
00327       //RGBValue amplitude_rgb;
00328       //amplitude_rgb.Red = amplitude_rgb.Green = amplitude_rgb.Blue = amplitude[index1];
00329       //pstep[3] = amplitude_rgb.float_value;
00330     }
00331   }
00332 }
00333 
00334 void PmdcameraDriverNode::assemblePcl2RangeImage(const float* const coord_3D, const float* const range, const float* const amp) 
00335 {    
00336   // float bad_point = std::numeric_limits<float>::quiet_NaN ();
00337   // Assemble an awesome sensor_msgs/PointCloud2 message
00338   for (int v = 0; v < height_; v++){
00339     for (int u = 0; u < width_; u++){
00340       int index = v * width_ + u;
00341       int index1 = v * real_width_ + u;
00342       int index3 = (v * real_width_ + u)*3;
00343 
00344       float *pstep = (float*)&pcl2_range_msg_.data[(index) * pcl2_range_msg_.point_step];
00345       //flip vertically !!!
00346       pstep[0] = coord_3D[index3];
00347       pstep[1] = coord_3D[index3+1];
00348       pstep[2] = coord_3D[index3+2];
00349       pstep[3] = range[index1];
00350       pstep[4] = amp[index1];
00351     }
00352   }
00353 }
00354 
00355 void PmdcameraDriverNode::mainNodeThread(void)
00356 {
00357   camera_info_ = camera_info_manager_->getCameraInfo ();
00358 
00359   //reset the intensity max value
00360   max_intensity_ = 0;
00361 
00362   //lock access to driver
00363   //  this->driver_.lock();
00364 
00365   // [fill msg Header if necessary]
00366   //<publisher_name>.header.frame_id = "<publisher_topic_name>";
00367   //<publisher_name>.header.stamp = ros::Time::now();
00368   PointCloud_msg_.header.frame_id = camera_info_.header.frame_id = pcl2_range_msg_.header.frame_id = pcl2_amp_msg_.header.frame_id = pcl2_int_msg_.header.frame_id;
00369   PointCloud_msg_.header.stamp = pcl2_range_msg_.header.stamp = pcl2_amp_msg_.header.stamp = pcl2_int_msg_.header.stamp = Image_int_msg_.header.stamp = Image_amp_msg_.header.stamp
00370     = Image_depth_msg_.header.stamp = camera_info_.header.stamp = ros::Time::now ();
00371 
00372   //TODO: blocking the reading part is enough  or all function should be under blockng?
00373   if ((pcl_range_raw_publisher_.getNumSubscribers () > 0) ||
00374       (pcl_amp_raw_publisher_.getNumSubscribers () > 0) ||
00375       (pcl_int_raw_publisher_.getNumSubscribers () > 0) ||
00376       (image_raw_publisher_.getNumSubscribers ()   > 0) ||
00377       (image_amp_publisher_.getNumSubscribers ()   > 0) ||
00378       (image_flags_publisher_.getNumSubscribers () > 0) ||
00379       (image_depth_publisher_.getNumSubscribers () > 0)) {
00380     try {
00381       driver_.lock();
00382       driver_.readData();
00383       //unlock access to driver if previously blocked
00384       driver_.unlock();
00385 
00386       // [fill msg structures]
00387 
00388       // [fill srv structure and make request to the server]
00389 
00390       // [fill action structure and make request to the action server]
00391 
00392       // [publish messages]
00393       if (pcl_range_raw_publisher_.getNumSubscribers () > 0) {
00394         bool is_dense = true;
00395         assemblePcl2RangeImage(driver_.get3DImage(is_dense), driver_.getRangeImage(), driver_.getAmplitudeImage());
00396         pcl2_range_msg_.is_dense = is_dense;
00397         pcl_range_raw_publisher_.publish(pcl2_range_msg_);
00398       }
00399 
00400       if (pcl_amp_raw_publisher_.getNumSubscribers () > 0) {
00401         bool is_dense = true;
00402         assemblePcl2Amp(driver_.get3DImage(is_dense), driver_.getAmplitudeImage());
00403         pcl2_amp_msg_.is_dense = is_dense;
00404         pcl_amp_raw_publisher_.publish(pcl2_amp_msg_);
00405       }
00406 
00407       if (pcl_int_raw_publisher_.getNumSubscribers () > 0) {
00408         bool is_dense = true;
00409         assemblePcl2Int(driver_.get3DImage(is_dense), driver_.getIntensityImage());
00410         pcl2_int_msg_.is_dense = is_dense;
00411         pcl_int_raw_publisher_.publish(pcl2_int_msg_);
00412       }
00413 
00414       if (image_flags_publisher_.getNumSubscribers () > 0) {
00415         assembleFlagsImage(driver_.getFlagsImage());
00416         //shared to easy the nodelet paradigm
00417         image_flags_publisher_.publish(boost::make_shared<const sensor_msgs::Image> (Image_int_msg_),boost::make_shared<const sensor_msgs::CameraInfo> (camera_info_));
00418       }
00419 
00420       if (image_raw_publisher_.getNumSubscribers () > 0) {
00421         assembleIntensityImage(driver_.getIntensityImage());
00422         //shared to easy the nodelet paradigm
00423         image_raw_publisher_.publish(boost::make_shared<const sensor_msgs::Image> (Image_int_msg_),boost::make_shared<const sensor_msgs::CameraInfo> (camera_info_));
00424       }
00425 
00426       if (image_amp_publisher_.getNumSubscribers () > 0)
00427       {
00428         assembleAmplitudeImage(driver_.getAmplitudeImage());
00429         //shared to easy the nodelet paradigm
00430         image_amp_publisher_.publish(boost::make_shared<const sensor_msgs::Image> (Image_amp_msg_),boost::make_shared<const sensor_msgs::CameraInfo> (camera_info_));
00431       }
00432 
00433       if (image_depth_publisher_.getNumSubscribers () > 0)
00434       {
00435         assembleDepthImage(driver_.getDepthImage());
00436         //shared to easy the nodelet paradigm
00437         image_depth_publisher_.publish(boost::make_shared<const sensor_msgs::Image> (Image_depth_msg_),boost::make_shared<const sensor_msgs::CameraInfo> (camera_info_));
00438       }
00439       //   ROS_INFO("new image");
00440     } catch(CException &e){
00441       driver_.unlock();
00442       ROS_INFO("Impossible to capture frame");
00443     }
00444     //unlock access to driver if previously blocked
00445     //  this->driver_.unlock();
00446   }
00447 }
00448 
00449 /*  [subscriber callbacks] */
00450 
00451 /*  [service callbacks] */
00452 
00453 /*  [action callbacks] */
00454 
00455 /*  [action requests] */
00456 
00457 void PmdcameraDriverNode::postNodeOpenHook(void)
00458 {
00459 }
00460 
00461 void PmdcameraDriverNode::addNodeDiagnostics(void)
00462 {
00463 }
00464 
00465 void PmdcameraDriverNode::addNodeOpenedTests(void)
00466 {
00467 }
00468 
00469 void PmdcameraDriverNode::addNodeStoppedTests(void)
00470 {
00471 }
00472 
00473 void PmdcameraDriverNode::addNodeRunningTests(void)
00474 {
00475 }
00476 
00477 void PmdcameraDriverNode::reconfigureNodeHook(int level)
00478 {
00479 }
00480 
00481 PmdcameraDriverNode::~PmdcameraDriverNode()
00482 {
00483   //[free dynamic memory]
00484   delete camera_info_manager_;
00485 }
00486 
00487 /* main function */
00488 int main(int argc,char *argv[])
00489 {
00490   return driver_base::main<PmdcameraDriverNode>(argc,argv,"pmdcamera_driver_node");
00491 }


iri_pmdcamera
Author(s): Guillem Alenya - IRI Robotics Lab
autogenerated on Fri Dec 6 2013 20:10:05