astra_driver.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Willow Garage, Inc.
00003  * Copyright (c) 2016, Orbbec Ltd.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00015  *       contributors may be used to endorse or promote products derived from
00016  *       this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *      Author: Tim Liu (liuhua@orbbec.com)
00031  */
00032 
00033 #include "astra_camera/astra_driver.h"
00034 #include "astra_camera/astra_exception.h"
00035 #include "astra_camera/astra_device_type.h"
00036 
00037 #include <unistd.h>  
00038 #include <stdlib.h>  
00039 #include <stdio.h>  
00040 #include <sys/shm.h>  
00041 #include <sensor_msgs/image_encodings.h>
00042 #include <sensor_msgs/distortion_models.h>
00043 
00044 #include <boost/date_time/posix_time/posix_time.hpp>
00045 #include <boost/thread/thread.hpp>
00046 
00047 #define  MULTI_ASTRA 1
00048 namespace astra_wrapper
00049 {
00050 
00051 AstraDriver::AstraDriver(ros::NodeHandle& n, ros::NodeHandle& pnh) :
00052     nh_(n),
00053     pnh_(pnh),
00054     device_manager_(AstraDeviceManager::getSingelton()),
00055     config_init_(false),
00056     data_skip_ir_counter_(0),
00057     data_skip_color_counter_(0),
00058     data_skip_depth_counter_ (0),
00059     ir_subscribers_(false),
00060     color_subscribers_(false),
00061     depth_subscribers_(false),
00062     depth_raw_subscribers_(false),
00063     uvc_flip_(0)
00064 {
00065 
00066   genVideoModeTableMap();
00067 
00068   readConfigFromParameterServer();
00069 
00070 #if MULTI_ASTRA
00071         int bootOrder, devnums;
00072   if (!pnh.getParam("bootorder", bootOrder))
00073   {
00074     bootOrder = 0;
00075   }
00076   
00077   if (!pnh.getParam("devnums", devnums))
00078   {
00079     devnums = 1;
00080   }
00081 
00082         if( devnums>1 )
00083         {
00084                 int shmid;
00085                 char *shm = NULL;
00086                 char *tmp;
00087 
00088                 if(  bootOrder==1 )
00089                 {
00090                         if( (shmid = shmget((key_t)0401, 1, 0666|IPC_CREAT)) == -1 )   
00091                         { 
00092                                 ROS_ERROR("Create Share Memory Error:%s", strerror(errno));
00093                         }
00094                         shm = (char *)shmat(shmid, 0, 0);  
00095                         *shm = 1;
00096                         initDevice();
00097                         ROS_INFO("*********** device_id %s already open device************************ ", device_id_.c_str());
00098                         *shm = 2;
00099                 }
00100                 else    
00101                 {       
00102                         if( (shmid = shmget((key_t)0401, 1, 0666|IPC_CREAT)) == -1 )   
00103                         { 
00104                                 ROS_ERROR("Create Share Memory Error:%s", strerror(errno));
00105                         }
00106                         shm = (char *)shmat(shmid, 0, 0);
00107                         while( *shm!=bootOrder)
00108                         {
00109                                 boost::this_thread::sleep(boost::posix_time::milliseconds(10));
00110                         }
00111 
00112                          initDevice();
00113                          ROS_INFO("*********** device_id %s already open device************************ ", device_id_.c_str());
00114                         *shm = (bootOrder+1);
00115                 }
00116                 if(  bootOrder==devnums )
00117                 {
00118                         if(shmdt(shm) == -1)  
00119                         {  
00120                                 ROS_ERROR("shmdt failed\n");  
00121                         } 
00122                         if(shmctl(shmid, IPC_RMID, 0) == -1)  
00123                         {  
00124                                 ROS_ERROR("shmctl(IPC_RMID) failed\n");  
00125                         }
00126                  }
00127                  else
00128                  {
00129                         if(shmdt(shm) == -1)  
00130                         {  
00131                                 ROS_ERROR("shmdt failed\n");  
00132                         } 
00133                  }
00134          }
00135          else
00136          {
00137                 initDevice();
00138          }
00139 #else
00140   initDevice();
00141 
00142 #endif
00143   // Initialize dynamic reconfigure
00144   reconfigure_server_.reset(new ReconfigureServer(pnh_));
00145   reconfigure_server_->setCallback(boost::bind(&AstraDriver::configCb, this, _1, _2));
00146 
00147   while (!config_init_)
00148   {
00149     ROS_DEBUG("Waiting for dynamic reconfigure configuration.");
00150     boost::this_thread::sleep(boost::posix_time::milliseconds(100));
00151   }
00152   ROS_DEBUG("Dynamic reconfigure configuration received.");
00153 
00154   advertiseROSTopics();
00155 }
00156 
00157 void AstraDriver::advertiseROSTopics()
00158 {
00159 
00160   // Allow remapping namespaces rgb, ir, depth, depth_registered
00161   ros::NodeHandle color_nh(nh_, "rgb");
00162   image_transport::ImageTransport color_it(color_nh);
00163   ros::NodeHandle ir_nh(nh_, "ir");
00164   image_transport::ImageTransport ir_it(ir_nh);
00165   ros::NodeHandle depth_nh(nh_, "depth");
00166   image_transport::ImageTransport depth_it(depth_nh);
00167   ros::NodeHandle depth_raw_nh(nh_, "depth");
00168   image_transport::ImageTransport depth_raw_it(depth_raw_nh);
00169   ros::NodeHandle projector_nh(nh_, "projector");
00170   // Advertise all published topics
00171 
00172   // Prevent connection callbacks from executing until we've set all the publishers. Otherwise
00173   // connectCb() can fire while we're advertising (say) "depth/image_raw", but before we actually
00174   // assign to pub_depth_raw_. Then pub_depth_raw_.getNumSubscribers() returns 0, and we fail to start
00175   // the depth generator.
00176   boost::lock_guard<boost::mutex> lock(connect_mutex_);
00177 
00178   // Asus Xtion PRO does not have an RGB camera
00179   //ROS_WARN("-------------has color sensor is %d----------- ", device_->hasColorSensor());
00180   if (device_->hasColorSensor())
00181   {
00182     image_transport::SubscriberStatusCallback itssc = boost::bind(&AstraDriver::imageConnectCb, this);
00183     ros::SubscriberStatusCallback rssc = boost::bind(&AstraDriver::imageConnectCb, this);
00184     pub_color_ = color_it.advertiseCamera("image", 1, itssc, itssc, rssc, rssc);
00185   }
00186 
00187   if (device_->hasIRSensor())
00188   {
00189     image_transport::SubscriberStatusCallback itssc = boost::bind(&AstraDriver::imageConnectCb, this);
00190     ros::SubscriberStatusCallback rssc = boost::bind(&AstraDriver::imageConnectCb, this);
00191     pub_ir_ = ir_it.advertiseCamera("image", 1, itssc, itssc, rssc, rssc);
00192   }
00193 
00194   if (device_->hasDepthSensor())
00195   {
00196     image_transport::SubscriberStatusCallback itssc = boost::bind(&AstraDriver::depthConnectCb, this);
00197     ros::SubscriberStatusCallback rssc = boost::bind(&AstraDriver::depthConnectCb, this);
00198     pub_depth_raw_ = depth_it.advertiseCamera("image_raw", 1, itssc, itssc, rssc, rssc);
00199     pub_depth_ = depth_raw_it.advertiseCamera("image", 1, itssc, itssc, rssc, rssc);
00200     pub_projector_info_ = projector_nh.advertise<sensor_msgs::CameraInfo>("camera_info", 1, rssc, rssc);
00201   }
00202 
00204 
00205   // Pixel offset between depth and IR images.
00206   // By default assume offset of (5,4) from 9x7 correlation window.
00207   // NOTE: These are now (temporarily?) dynamically reconfigurable, to allow tweaking.
00208   //param_nh.param("depth_ir_offset_x", depth_ir_offset_x_, 5.0);
00209   //param_nh.param("depth_ir_offset_y", depth_ir_offset_y_, 4.0);
00210 
00211   // The camera names are set to [rgb|depth]_[serial#], e.g. depth_B00367707227042B.
00212   // camera_info_manager substitutes this for ${NAME} in the URL.
00213   std::string serial_number = device_->getStringID();
00214   std::string color_name, ir_name;
00215 
00216   color_name = "rgb_"   + serial_number;
00217   ir_name  = "depth_" + serial_number;
00218 
00219   // Load the saved calibrations, if they exist
00220   color_info_manager_ = boost::make_shared<camera_info_manager::CameraInfoManager>(color_nh, color_name, color_info_url_);
00221   ir_info_manager_  = boost::make_shared<camera_info_manager::CameraInfoManager>(ir_nh,  ir_name,  ir_info_url_);
00222 
00223   get_serial_server = nh_.advertiseService("get_serial", &AstraDriver::getSerialCb, this);
00224   get_device_type_server = nh_.advertiseService("get_device_type", &AstraDriver::getDeviceTypeCb, this);
00225   get_ir_gain_server = nh_.advertiseService("get_ir_gain", &AstraDriver::getIRGainCb, this);
00226   set_ir_gain_server = nh_.advertiseService("set_ir_gain", &AstraDriver::setIRGainCb, this);
00227   get_ir_exposure_server = nh_.advertiseService("get_ir_exposure", &AstraDriver::getIRExposureCb, this);
00228   set_ir_exposure_server = nh_.advertiseService("set_ir_exposure", &AstraDriver::setIRExposureCb, this);
00229   set_ir_flood_server = nh_.advertiseService("set_ir_flood", &AstraDriver::setIRFloodCb, this);
00230   set_laser_server = nh_.advertiseService("set_laser", &AstraDriver::setLaserCb, this);
00231   reset_ir_gain_server = nh_.advertiseService("reset_ir_gain", &AstraDriver::resetIRGainCb, this);
00232   reset_ir_exposure_server = nh_.advertiseService("reset_ir_exposure", &AstraDriver::resetIRExposureCb, this);
00233   get_camera_info = nh_.advertiseService("get_camera_info", &AstraDriver::getCameraInfoCb, this);
00234 }
00235 
00236 bool AstraDriver::getSerialCb(astra_camera::GetSerialRequest& req, astra_camera::GetSerialResponse& res)
00237 {
00238   res.serial = device_manager_->getSerial(device_->getUri());
00239   return true;
00240 }
00241 
00242 bool AstraDriver::getDeviceTypeCb(astra_camera::GetDeviceTypeRequest& req, astra_camera::GetDeviceTypeResponse& res)
00243 {
00244   res.device_type = std::string(device_->getDeviceType());
00245   return true;
00246 }
00247 
00248 bool AstraDriver::getIRGainCb(astra_camera::GetIRGainRequest& req, astra_camera::GetIRGainResponse& res)
00249 {
00250   res.gain = device_->getIRGain();
00251   return true;
00252 }
00253 
00254 bool AstraDriver::setIRGainCb(astra_camera::SetIRGainRequest& req, astra_camera::SetIRGainResponse& res)
00255 {
00256   device_->setIRGain(req.gain);
00257   return true;
00258 }
00259 
00260 bool AstraDriver::getIRExposureCb(astra_camera::GetIRExposureRequest& req, astra_camera::GetIRExposureResponse& res)
00261 {
00262   res.exposure = device_->getIRExposure();
00263   return true;
00264 }
00265 
00266 bool AstraDriver::setIRExposureCb(astra_camera::SetIRExposureRequest& req, astra_camera::SetIRExposureResponse& res)
00267 {
00268   device_->setIRExposure(req.exposure);
00269   return true;
00270 }
00271 
00272 bool AstraDriver::setLaserCb(astra_camera::SetLaserRequest& req, astra_camera::SetLaserResponse& res)
00273 {
00274   device_->setLaser(req.enable);
00275   return true;
00276 }
00277 
00278 bool AstraDriver::resetIRGainCb(astra_camera::ResetIRGainRequest& req, astra_camera::ResetIRGainResponse& res)
00279 {
00280   device_->setIRGain(0x8);
00281   return true;
00282 }
00283 
00284 bool AstraDriver::resetIRExposureCb(astra_camera::ResetIRExposureRequest& req, astra_camera::ResetIRExposureResponse& res)
00285 {
00286   device_->setIRExposure(0x419);
00287   return true;
00288 }
00289 
00290 bool AstraDriver::getCameraInfoCb(astra_camera::GetCameraInfoRequest& req, astra_camera::GetCameraInfoResponse& res)
00291 {
00292   res.info = convertAstraCameraInfo(device_->getCameraParams(), ros::Time::now());
00293   return true;
00294 }
00295 
00296 bool AstraDriver::setIRFloodCb(astra_camera::SetIRFloodRequest& req, astra_camera::SetIRFloodResponse& res)
00297 {
00298   device_->setIRFlood(req.enable);
00299   return true;
00300 }
00301 
00302 void AstraDriver::configCb(Config &config, uint32_t level)
00303 {
00304   if (device_->getDeviceTypeNo() == OB_STEREO_S_NO)
00305   {
00306     config.depth_mode = 13;
00307     config.ir_mode = 13;
00308   }
00309   else if (device_->getDeviceTypeNo() == OB_EMBEDDED_S_NO)
00310   {
00311     config.depth_mode = 13;
00312     config.ir_mode = 13;
00313     uvc_flip_ = 1;
00314   }
00315   bool stream_reset = false;
00316 
00317   rgb_preferred_ = config.rgb_preferred;
00318 
00319   if (config_init_ && old_config_.rgb_preferred != config.rgb_preferred)
00320     imageConnectCb();
00321 
00322   depth_ir_offset_x_ = config.depth_ir_offset_x;
00323   depth_ir_offset_y_ = config.depth_ir_offset_y;
00324   z_offset_mm_ = config.z_offset_mm;
00325   z_scaling_ = config.z_scaling;
00326 
00327   ir_time_offset_ = ros::Duration(config.ir_time_offset);
00328   color_time_offset_ = ros::Duration(config.color_time_offset);
00329   depth_time_offset_ = ros::Duration(config.depth_time_offset);
00330 
00331   if (lookupVideoModeFromDynConfig(config.ir_mode, ir_video_mode_)<0)
00332   {
00333     ROS_ERROR("Undefined IR video mode received from dynamic reconfigure");
00334     exit(-1);
00335   }
00336 
00337   if (lookupVideoModeFromDynConfig(config.color_mode, color_video_mode_)<0)
00338   {
00339     ROS_ERROR("Undefined color video mode received from dynamic reconfigure");
00340     exit(-1);
00341   }
00342 
00343   if (lookupVideoModeFromDynConfig(config.depth_mode, depth_video_mode_)<0)
00344   {
00345     ROS_ERROR("Undefined depth video mode received from dynamic reconfigure");
00346     exit(-1);
00347   }
00348 
00349   // assign pixel format
00350 
00351   ir_video_mode_.pixel_format_ = PIXEL_FORMAT_GRAY16;
00352   color_video_mode_.pixel_format_ = PIXEL_FORMAT_RGB888;
00353   depth_video_mode_.pixel_format_ = PIXEL_FORMAT_DEPTH_1_MM;
00354 
00355   color_depth_synchronization_ = config.color_depth_synchronization;
00356   depth_registration_ = config.depth_registration;
00357 
00358   auto_exposure_ = config.auto_exposure;
00359   auto_white_balance_ = config.auto_white_balance;
00360 
00361   use_device_time_ = config.use_device_time;
00362 
00363   data_skip_ = config.data_skip+1;
00364 
00365   applyConfigToOpenNIDevice();
00366 
00367   config_init_ = true;
00368 
00369   old_config_ = config;
00370 }
00371 
00372 void AstraDriver::setIRVideoMode(const AstraVideoMode& ir_video_mode)
00373 {
00374   if (device_->isIRVideoModeSupported(ir_video_mode))
00375   {
00376     if (ir_video_mode != device_->getIRVideoMode())
00377     {
00378       device_->setIRVideoMode(ir_video_mode);
00379     }
00380 
00381   }
00382   else
00383   {
00384     ROS_ERROR_STREAM("Unsupported IR video mode - " << ir_video_mode);
00385   }
00386 }
00387 void AstraDriver::setColorVideoMode(const AstraVideoMode& color_video_mode)
00388 {
00389   if (device_->isColorVideoModeSupported(color_video_mode))
00390   {
00391     if (color_video_mode != device_->getColorVideoMode())
00392     {
00393       device_->setColorVideoMode(color_video_mode);
00394     }
00395   }
00396   else
00397   {
00398     ROS_ERROR_STREAM("Unsupported color video mode - " << color_video_mode);
00399   }
00400 }
00401 void AstraDriver::setDepthVideoMode(const AstraVideoMode& depth_video_mode)
00402 {
00403   if (device_->isDepthVideoModeSupported(depth_video_mode))
00404   {
00405     if (depth_video_mode != device_->getDepthVideoMode())
00406     {
00407       device_->setDepthVideoMode(depth_video_mode);
00408     }
00409   }
00410   else
00411   {
00412     ROS_ERROR_STREAM("Unsupported depth video mode - " << depth_video_mode);
00413   }
00414 }
00415 
00416 void AstraDriver::applyConfigToOpenNIDevice()
00417 {
00418 
00419   data_skip_ir_counter_ = 0;
00420   data_skip_color_counter_= 0;
00421   data_skip_depth_counter_ = 0;
00422 
00423   setIRVideoMode(ir_video_mode_);
00424   if (device_->hasColorSensor())
00425   {
00426         setColorVideoMode(color_video_mode_);
00427   }
00428   setDepthVideoMode(depth_video_mode_);
00429 
00430   if (device_->isImageRegistrationModeSupported())
00431   {
00432     try
00433     {
00434       if (!config_init_ || (old_config_.depth_registration != depth_registration_))
00435         device_->setImageRegistrationMode(depth_registration_);
00436     }
00437     catch (const AstraException& exception)
00438     {
00439       ROS_ERROR("Could not set image registration. Reason: %s", exception.what());
00440     }
00441   }
00442 
00443   try
00444   {
00445     if (!config_init_ || (old_config_.color_depth_synchronization != color_depth_synchronization_))
00446       device_->setDepthColorSync(color_depth_synchronization_);
00447   }
00448   catch (const AstraException& exception)
00449   {
00450     ROS_ERROR("Could not set color depth synchronization. Reason: %s", exception.what());
00451   }
00452 
00453   try
00454   {
00455     if (!config_init_ || (old_config_.auto_exposure != auto_exposure_))
00456       device_->setAutoExposure(auto_exposure_);
00457   }
00458   catch (const AstraException& exception)
00459   {
00460     ROS_ERROR("Could not set auto exposure. Reason: %s", exception.what());
00461   }
00462 
00463   try
00464   {
00465     if (!config_init_ || (old_config_.auto_white_balance != auto_white_balance_))
00466       device_->setAutoWhiteBalance(auto_white_balance_);
00467   }
00468   catch (const AstraException& exception)
00469   {
00470     ROS_ERROR("Could not set auto white balance. Reason: %s", exception.what());
00471   }
00472 
00473   device_->setUseDeviceTimer(use_device_time_);
00474 
00475 }
00476 
00477 void AstraDriver::imageConnectCb()
00478 {
00479   boost::lock_guard<boost::mutex> lock(connect_mutex_);
00480 
00481   bool ir_started = device_->isIRStreamStarted();
00482   bool color_started = device_->isColorStreamStarted();
00483 
00484   ir_subscribers_ = pub_ir_.getNumSubscribers() > 0;
00485   color_subscribers_ = pub_color_.getNumSubscribers() > 0;
00486 
00487   if (color_subscribers_ && (!ir_subscribers_ || rgb_preferred_))
00488   {
00489     if (ir_subscribers_)
00490       ROS_ERROR("Cannot stream RGB and IR at the same time. Streaming RGB only.");
00491 
00492     if (ir_started)
00493     {
00494       ROS_INFO("Stopping IR stream.");
00495       device_->stopIRStream();
00496     }
00497 
00498     if (!color_started)
00499     {
00500       device_->setColorFrameCallback(boost::bind(&AstraDriver::newColorFrameCallback, this, _1));
00501 
00502       ROS_INFO("Starting color stream.");
00503       device_->startColorStream();
00504     }
00505   }
00506   else if (ir_subscribers_ && (!color_subscribers_ || !rgb_preferred_))
00507   {
00508 
00509     if (color_subscribers_)
00510       ROS_ERROR("Cannot stream RGB and IR at the same time. Streaming IR only.");
00511 
00512     if (color_started)
00513     {
00514       ROS_INFO("Stopping color stream.");
00515       device_->stopColorStream();
00516     }
00517 
00518     if (!ir_started)
00519     {
00520       device_->setIRFrameCallback(boost::bind(&AstraDriver::newIRFrameCallback, this, _1));
00521 
00522       ROS_INFO("Starting IR stream.");
00523       device_->startIRStream();
00524     }
00525   }
00526   else
00527   {
00528     if (color_started)
00529     {
00530       ROS_INFO("Stopping color stream.");
00531       device_->stopColorStream();
00532     }
00533     if (ir_started)
00534     {
00535       ROS_INFO("Stopping IR stream.");
00536       device_->stopIRStream();
00537     }
00538   }
00539 }
00540 
00541 void AstraDriver::depthConnectCb()
00542 {
00543   boost::lock_guard<boost::mutex> lock(connect_mutex_);
00544 
00545   depth_subscribers_ = pub_depth_.getNumSubscribers() > 0;
00546   depth_raw_subscribers_ = pub_depth_raw_.getNumSubscribers() > 0;
00547   projector_info_subscribers_ = pub_projector_info_.getNumSubscribers() > 0;
00548 
00549   bool need_depth = depth_subscribers_ || depth_raw_subscribers_;
00550 
00551   if (need_depth && !device_->isDepthStreamStarted())
00552   {
00553     device_->setDepthFrameCallback(boost::bind(&AstraDriver::newDepthFrameCallback, this, _1));
00554 
00555     ROS_INFO("Starting depth stream.");
00556     device_->startDepthStream();
00557   }
00558   else if (!need_depth && device_->isDepthStreamStarted())
00559   {
00560     ROS_INFO("Stopping depth stream.");
00561     device_->stopDepthStream();
00562   }
00563 }
00564 
00565 void AstraDriver::newIRFrameCallback(sensor_msgs::ImagePtr image)
00566 {
00567   if ((++data_skip_ir_counter_)%data_skip_==0)
00568   {
00569     data_skip_ir_counter_ = 0;
00570 
00571     if (ir_subscribers_)
00572     {
00573       image->header.frame_id = ir_frame_id_;
00574       image->header.stamp = image->header.stamp + ir_time_offset_;
00575 
00576       pub_ir_.publish(image, getIRCameraInfo(image->width, image->height, image->header.stamp));
00577     }
00578   }
00579 }
00580 
00581 void AstraDriver::newColorFrameCallback(sensor_msgs::ImagePtr image)
00582 {
00583   if ((++data_skip_color_counter_)%data_skip_==0)
00584   {
00585     data_skip_color_counter_ = 0;
00586 
00587     if (color_subscribers_)
00588     {
00589       image->header.frame_id = color_frame_id_;
00590       image->header.stamp = image->header.stamp + color_time_offset_;
00591 
00592       pub_color_.publish(image, getColorCameraInfo(image->width, image->height, image->header.stamp));
00593     }
00594   }
00595 }
00596 
00597 void AstraDriver::newDepthFrameCallback(sensor_msgs::ImagePtr image)
00598 {
00599   if ((++data_skip_depth_counter_)%data_skip_==0)
00600   {
00601 
00602     data_skip_depth_counter_ = 0;
00603 
00604     if (depth_raw_subscribers_||depth_subscribers_||projector_info_subscribers_)
00605     {
00606       image->header.stamp = image->header.stamp + depth_time_offset_;
00607 
00608       if (z_offset_mm_ != 0)
00609       {
00610         uint16_t* data = reinterpret_cast<uint16_t*>(&image->data[0]);
00611         for (unsigned int i = 0; i < image->width * image->height; ++i)
00612           if (data[i] != 0)
00613                 data[i] += z_offset_mm_;
00614       }
00615 
00616       if (fabs(z_scaling_ - 1.0) > 1e-6)
00617       {
00618         uint16_t* data = reinterpret_cast<uint16_t*>(&image->data[0]);
00619         for (unsigned int i = 0; i < image->width * image->height; ++i)
00620           if (data[i] != 0)
00621                 data[i] = static_cast<uint16_t>(data[i] * z_scaling_);
00622       }
00623 
00624       sensor_msgs::CameraInfoPtr cam_info;
00625 
00626       if (depth_registration_)
00627       {
00628         image->header.frame_id = color_frame_id_;
00629         cam_info = getColorCameraInfo(image->width, image->height, image->header.stamp);
00630       } else
00631       {
00632         image->header.frame_id = depth_frame_id_;
00633         cam_info = getDepthCameraInfo(image->width, image->height, image->header.stamp);
00634       }
00635 
00636       if (depth_raw_subscribers_)
00637       {
00638         pub_depth_raw_.publish(image, cam_info);
00639       }
00640 
00641       if (depth_subscribers_ )
00642       {
00643         sensor_msgs::ImageConstPtr floating_point_image = rawToFloatingPointConversion(image);
00644         pub_depth_.publish(floating_point_image, cam_info);
00645       }
00646 
00647       // Projector "info" probably only useful for working with disparity images
00648       if (projector_info_subscribers_)
00649       {
00650         pub_projector_info_.publish(getProjectorCameraInfo(image->width, image->height, image->header.stamp));
00651       }
00652     }
00653   }
00654 }
00655 
00656 sensor_msgs::CameraInfo AstraDriver::convertAstraCameraInfo(OBCameraParams p, ros::Time time) const
00657 {
00658   sensor_msgs::CameraInfo info;
00659   // info.width = width;
00660   // info.height = height;
00661   info.distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
00662   info.D.resize(5, 0.0);
00663   info.D[0] = p.r_k[0];
00664   info.D[1] = p.r_k[1];
00665   info.D[2] = p.r_k[3];
00666   info.D[3] = p.r_k[4];
00667   info.D[4] = p.r_k[2];
00668 
00669   info.K.assign(0.0);
00670   info.K[0] = p.r_intr_p[0];
00671   info.K[2] = p.r_intr_p[2];
00672   info.K[4] = p.r_intr_p[1];
00673   info.K[5] = p.r_intr_p[3];
00674   info.K[8] = 1.0;
00675 
00676   info.R.assign(0.0);
00677   for (int i = 0; i < 9; i++)
00678   {
00679     info.R[i] = p.r2l_r[i];
00680   }
00681 
00682   info.P.assign(0.0);
00683   info.P[0] = info.K[0];
00684   info.P[2] = info.K[2];
00685   info.P[3] = p.r2l_t[0];
00686   info.P[5] = info.K[4];
00687   info.P[6] = info.K[5];
00688   info.P[7] = p.r2l_t[1];
00689   info.P[10] = 1.0;
00690   info.P[11] = p.r2l_t[2];
00691   // Fill in header
00692   info.header.stamp    = time;
00693   info.header.frame_id = color_frame_id_;
00694   return info;
00695 }
00696 
00697 // Methods to get calibration parameters for the various cameras
00698 sensor_msgs::CameraInfoPtr AstraDriver::getDefaultCameraInfo(int width, int height, double f) const
00699 {
00700   sensor_msgs::CameraInfoPtr info = boost::make_shared<sensor_msgs::CameraInfo>();
00701 
00702   info->width  = width;
00703   info->height = height;
00704 
00705   // No distortion
00706   info->D.resize(5, 0.0);
00707   info->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
00708 
00709   // Simple camera matrix: square pixels (fx = fy), principal point at center
00710   info->K.assign(0.0);
00711   info->K[0] = info->K[4] = f;
00712   info->K[2] = (width / 2) - 0.5;
00713   // Aspect ratio for the camera center on Astra (and other devices?) is 4/3
00714   // This formula keeps the principal point the same in VGA and SXGA modes
00715   info->K[5] = (width * (3./8.)) - 0.5;
00716   info->K[8] = 1.0;
00717 
00718   // No separate rectified image plane, so R = I
00719   info->R.assign(0.0);
00720   info->R[0] = info->R[4] = info->R[8] = 1.0;
00721 
00722   // Then P=K(I|0) = (K|0)
00723   info->P.assign(0.0);
00724   info->P[0]  = info->P[5] = f; // fx, fy
00725   info->P[2]  = info->K[2];     // cx
00726   info->P[6]  = info->K[5];     // cy
00727   info->P[10] = 1.0;
00728 
00729   return info;
00730 }
00731 
00733 sensor_msgs::CameraInfoPtr AstraDriver::getColorCameraInfo(int width, int height, ros::Time time) const
00734 {
00735   sensor_msgs::CameraInfoPtr info;
00736 
00737   if (color_info_manager_->isCalibrated())
00738   {
00739     info = boost::make_shared<sensor_msgs::CameraInfo>(color_info_manager_->getCameraInfo());
00740     if ( info->width != width )
00741     {
00742       // Use uncalibrated values
00743       ROS_WARN_ONCE("Image resolution doesn't match calibration of the RGB camera. Using default parameters.");
00744       info = getDefaultCameraInfo(width, height, device_->getColorFocalLength(height));
00745     }
00746   }
00747   else
00748   {
00749     // If uncalibrated, fill in default values
00750     if (device_->getDeviceTypeNo() == OB_STEREO_S_NO || device_->getDeviceTypeNo() == OB_EMBEDDED_S_NO ||
00751         device_->getDeviceTypeNo() == OB_ASTRA_PRO_NO)
00752     {
00753       sensor_msgs::CameraInfo cinfo = convertAstraCameraInfo(device_->getCameraParams(), time);
00754       info = boost::make_shared<sensor_msgs::CameraInfo>(ir_info_manager_->getCameraInfo());
00755       info->D.resize(5, 0.0);
00756       info->K.assign(0.0);
00757       info->R.assign(0.0);
00758       info->P.assign(0.0);
00759       info->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
00760       info->width = width;
00761       info->height = height;
00762       for (int i = 0; i < 5; i++)
00763       {
00764         info->D[i] = cinfo.D[i];
00765       }
00766 
00767       for (int i = 0; i < 9; i++)
00768       {
00769         info->K[i] = cinfo.K[i];
00770         info->R[i] = cinfo.R[i];
00771       }
00772 
00773       for (int i = 0; i < 12; i++)
00774       {
00775         info->P[i] = cinfo.P[i];
00776       }
00777     }
00778     else
00779     {
00780       info = getDefaultCameraInfo(width, height, device_->getColorFocalLength(height));
00781     }
00782   }
00783 
00784   // Fill in header
00785   info->header.stamp    = time;
00786   info->header.frame_id = color_frame_id_;
00787 
00788   return info;
00789 }
00790 
00791 
00792 sensor_msgs::CameraInfoPtr AstraDriver::getIRCameraInfo(int width, int height, ros::Time time) const
00793 {
00794   sensor_msgs::CameraInfoPtr info;
00795 
00796   if (ir_info_manager_->isCalibrated())
00797   {
00798     info = boost::make_shared<sensor_msgs::CameraInfo>(ir_info_manager_->getCameraInfo());
00799     if ( info->width != width )
00800     {
00801       // Use uncalibrated values
00802       ROS_WARN_ONCE("Image resolution doesn't match calibration of the IR camera. Using default parameters.");
00803       info = getDefaultCameraInfo(width, height, device_->getIRFocalLength(height));
00804     }
00805   }
00806   else
00807   {
00808     // If uncalibrated, fill in default values
00809     info = getDefaultCameraInfo(width, height, device_->getDepthFocalLength(height));
00810     if (device_->getDeviceTypeNo() == OB_STEREO_S_NO || device_->getDeviceTypeNo() == OB_EMBEDDED_S_NO ||
00811         device_->getDeviceTypeNo() == OB_ASTRA_PRO_NO)
00812     {
00813       OBCameraParams p = device_->getCameraParams();
00814       info->D.resize(5, 0.0);
00815       info->D[0] = p.l_k[0];
00816       info->D[1] = p.l_k[1];
00817       info->D[2] = p.l_k[3];
00818       info->D[3] = p.l_k[4];
00819       info->D[4] = p.l_k[2];
00820 
00821       info->K.assign(0.0);
00822       info->K[0] = (1 - uvc_flip_)*p.r_intr_p[0] + (uvc_flip_)*(-p.r_intr_p[0]);
00823       info->K[2] = (1 - uvc_flip_)*p.r_intr_p[2] + (uvc_flip_)*(width - p.r_intr_p[2]);
00824       info->K[4] = p.l_intr_p[1];
00825       info->K[5] = p.l_intr_p[3];
00826       info->K[8] = 1.0;
00827 
00828       info->P.assign(0.0);
00829       info->P[0] = info->K[0];
00830       info->P[2] = info->K[2];
00831       info->P[5] = info->K[4];
00832       info->P[6] = info->K[5];
00833       info->P[10] = 1.0;
00834     }
00835   }
00836 
00837   // Fill in header
00838   info->header.stamp    = time;
00839   info->header.frame_id = depth_frame_id_;
00840 
00841   return info;
00842 }
00843 
00844 sensor_msgs::CameraInfoPtr AstraDriver::getDepthCameraInfo(int width, int height, ros::Time time) const
00845 {
00846   // The depth image has essentially the same intrinsics as the IR image, BUT the
00847   // principal point is offset by half the size of the hardware correlation window
00848   // (probably 9x9 or 9x7 in 640x480 mode). See http://www.ros.org/wiki/kinect_calibration/technical
00849 
00850   double scaling = (double)width / 640;
00851 
00852   sensor_msgs::CameraInfoPtr info = getIRCameraInfo(width, height, time);
00853   info->K[2] -= depth_ir_offset_x_*scaling; // cx
00854   info->K[5] -= depth_ir_offset_y_*scaling; // cy
00855   info->P[2] -= depth_ir_offset_x_*scaling; // cx
00856   info->P[6] -= depth_ir_offset_y_*scaling; // cy
00857 
00859   return info;
00860 }
00861 
00862 sensor_msgs::CameraInfoPtr AstraDriver::getProjectorCameraInfo(int width, int height, ros::Time time) const
00863 {
00864   // The projector info is simply the depth info with the baseline encoded in the P matrix.
00865   // It's only purpose is to be the "right" camera info to the depth camera's "left" for
00866   // processing disparity images.
00867   sensor_msgs::CameraInfoPtr info = getDepthCameraInfo(width, height, time);
00868   // Tx = -baseline * fx
00869   info->P[3] = -device_->getBaseline() * info->P[0];
00870   return info;
00871 }
00872 
00873 void AstraDriver::readConfigFromParameterServer()
00874 {
00875   if (!pnh_.getParam("device_id", device_id_))
00876   {
00877     ROS_WARN ("~device_id is not set! Using first device.");
00878     device_id_ = "#1";
00879   }
00880 
00881   // Camera TF frames
00882   pnh_.param("ir_frame_id", ir_frame_id_, std::string("/openni_ir_optical_frame"));
00883   pnh_.param("rgb_frame_id", color_frame_id_, std::string("/openni_rgb_optical_frame"));
00884   pnh_.param("depth_frame_id", depth_frame_id_, std::string("/openni_depth_optical_frame"));
00885 
00886   ROS_DEBUG("ir_frame_id = '%s' ", ir_frame_id_.c_str());
00887   ROS_DEBUG("rgb_frame_id = '%s' ", color_frame_id_.c_str());
00888   ROS_DEBUG("depth_frame_id = '%s' ", depth_frame_id_.c_str());
00889 
00890   pnh_.param("rgb_camera_info_url", color_info_url_, std::string());
00891   pnh_.param("depth_camera_info_url", ir_info_url_, std::string());
00892 
00893 }
00894 
00895 std::string AstraDriver::resolveDeviceURI(const std::string& device_id)
00896 {
00897   // retrieve available device URIs, they look like this: "1d27/0601@1/5"
00898   // which is <vendor ID>/<product ID>@<bus number>/<device number>
00899   boost::shared_ptr<std::vector<std::string> > available_device_URIs =
00900     device_manager_->getConnectedDeviceURIs();
00901 
00902   //for tes
00903   #if 0
00904    for (size_t i = 0; i < available_device_URIs->size(); ++i)
00905    {
00906        std::string s = (*available_device_URIs)[i];
00907         ROS_WARN("------------id %d, available_device_uri is %s-----------", i, s.c_str());
00908    }
00909    #endif
00910   //end
00911   // look for '#<number>' format
00912   if (device_id.size() > 1 && device_id[0] == '#')
00913   {
00914     std::istringstream device_number_str(device_id.substr(1));
00915     int device_number;
00916     device_number_str >> device_number;
00917     int device_index = device_number - 1; // #1 refers to first device
00918     if (device_index >= available_device_URIs->size() || device_index < 0)
00919     {
00920       THROW_OPENNI_EXCEPTION(
00921           "Invalid device number %i, there are %zu devices connected.",
00922           device_number, available_device_URIs->size());
00923     }
00924     else
00925     {
00926       return available_device_URIs->at(device_index);
00927     }
00928   }
00929   // look for '<bus>@<number>' format
00930   //   <bus>    is usb bus id, typically start at 1
00931   //   <number> is the device number, for consistency with astra_camera, these start at 1
00932   //               although 0 specifies "any device on this bus"
00933   else if (device_id.size() > 1 && device_id.find('@') != std::string::npos && device_id.find('/') == std::string::npos)
00934   {
00935     // get index of @ character
00936     size_t index = device_id.find('@');
00937     if (index <= 0)
00938     {
00939       THROW_OPENNI_EXCEPTION(
00940         "%s is not a valid device URI, you must give the bus number before the @.",
00941         device_id.c_str());
00942     }
00943     if (index >= device_id.size() - 1)
00944     {
00945       THROW_OPENNI_EXCEPTION(
00946         "%s is not a valid device URI, you must give a number after the @, specify 0 for first device",
00947         device_id.c_str());
00948     }
00949 
00950     // pull out device number on bus
00951     std::istringstream device_number_str(device_id.substr(index+1));
00952     int device_number;
00953     device_number_str >> device_number;
00954 
00955     // reorder to @<bus>
00956     std::string bus = device_id.substr(0, index);
00957     bus.insert(0, "@");
00958 
00959     for (size_t i = 0; i < available_device_URIs->size(); ++i)
00960     {
00961       std::string s = (*available_device_URIs)[i];
00962       if (s.find(bus) != std::string::npos)
00963       {
00964         // this matches our bus, check device number
00965         --device_number;
00966         if (device_number <= 0)
00967           return s;
00968       }
00969     }
00970 
00971     THROW_OPENNI_EXCEPTION("Device not found %s", device_id.c_str());
00972   }
00973   else
00974   {
00975     // check if the device id given matches a serial number of a connected device
00976     for(std::vector<std::string>::const_iterator it = available_device_URIs->begin();
00977         it != available_device_URIs->end(); ++it)
00978     {
00979         #if 0
00980         try 
00981         {
00982                 std::string serial = device_manager_->getSerial(*it);
00983                 if (serial.size() > 0 && device_id == serial)
00984                         return *it;
00985         }
00986         #else
00987         try 
00988         {
00989                 std::set<std::string>::iterator iter;
00990                 if((iter = alreadyOpen.find(*it)) == alreadyOpen.end())
00991                 {
00992                         // ROS_WARN("------------seraial num it is  %s, device_id is %s -----------", (*it).c_str(), device_id_.c_str());
00993                         std::string serial = device_manager_->getSerial(*it);
00994                         if (serial.size() > 0 && device_id == serial)
00995                         {
00996                                 alreadyOpen.insert(*it);
00997                                 return *it;
00998                         }
00999                 }
01000         }
01001         #endif
01002         catch (const AstraException& exception)
01003         {
01004                 ROS_WARN("Could not query serial number of device \"%s\":", exception.what());
01005         }
01006     }
01007 
01008     // everything else is treated as part of the device_URI
01009     bool match_found = false;
01010     std::string matched_uri;
01011     for (size_t i = 0; i < available_device_URIs->size(); ++i)
01012     {
01013       std::string s = (*available_device_URIs)[i];
01014       if (s.find(device_id) != std::string::npos)
01015       {
01016         if (!match_found)
01017         {
01018           matched_uri = s;
01019           match_found = true;
01020         }
01021         else
01022         {
01023           // more than one match
01024           THROW_OPENNI_EXCEPTION("Two devices match the given device id '%s': %s and %s.", device_id.c_str(), matched_uri.c_str(), s.c_str());
01025         }
01026       }
01027     }
01028     return matched_uri;
01029   }
01030 
01031   return "INVALID";
01032 }
01033 
01034 void AstraDriver::initDevice()
01035 {
01036   while (ros::ok() && !device_)
01037   {
01038     try
01039     {
01040       std::string device_URI = resolveDeviceURI(device_id_);
01041       #if 0
01042       if( device_URI == "" ) 
01043       {
01044         boost::this_thread::sleep(boost::posix_time::milliseconds(500));
01045         continue;
01046       }
01047       #endif
01048       device_ = device_manager_->getDevice(device_URI);
01049     }
01050     catch (const AstraException& exception)
01051     {
01052       if (!device_)
01053       {
01054         ROS_INFO("No matching device found.... waiting for devices. Reason: %s", exception.what());
01055         boost::this_thread::sleep(boost::posix_time::seconds(3));
01056         continue;
01057       }
01058       else
01059       {
01060         ROS_ERROR("Could not retrieve device. Reason: %s", exception.what());
01061         exit(-1);
01062       }
01063     }
01064   }
01065 
01066   while (ros::ok() && !device_->isValid())
01067   {
01068     ROS_DEBUG("Waiting for device initialization..");
01069     boost::this_thread::sleep(boost::posix_time::milliseconds(100));
01070   }
01071 
01072 }
01073 
01074 void AstraDriver::genVideoModeTableMap()
01075 {
01076   /*
01077    * #  Video modes defined by dynamic reconfigure:
01078 output_mode_enum = gen.enum([  gen.const(  "SXGA_30Hz", int_t, 1,  "1280x1024@30Hz"),
01079                                gen.const(  "SXGA_15Hz", int_t, 2,  "1280x1024@15Hz"),
01080                                gen.const(   "XGA_30Hz", int_t, 3,  "1280x720@30Hz"),
01081                                gen.const(   "XGA_15Hz", int_t, 4,  "1280x720@15Hz"),
01082                                gen.const(   "VGA_30Hz", int_t, 5,  "640x480@30Hz"),
01083                                gen.const(   "VGA_25Hz", int_t, 6,  "640x480@25Hz"),
01084                                gen.const(  "QVGA_25Hz", int_t, 7,  "320x240@25Hz"),
01085                                gen.const(  "QVGA_30Hz", int_t, 8,  "320x240@30Hz"),
01086                                gen.const(  "QVGA_60Hz", int_t, 9,  "320x240@60Hz"),
01087                                gen.const( "QQVGA_25Hz", int_t, 10, "160x120@25Hz"),
01088                                gen.const( "QQVGA_30Hz", int_t, 11, "160x120@30Hz"),
01089                                gen.const( "QQVGA_60Hz", int_t, 12, "160x120@60Hz"),
01090                                gen.const("640400_30Hz", int_t, 13, "640x400@30Hz"),
01091                                gen.const("320200_30Hz", int_t, 14, "320x200@30Hz")],
01092                                "output mode")
01093   */
01094 
01095   video_modes_lookup_.clear();
01096 
01097   AstraVideoMode video_mode;
01098 
01099   // SXGA_30Hz
01100   video_mode.x_resolution_ = 1280;
01101   video_mode.y_resolution_ = 1024;
01102   video_mode.frame_rate_ = 30;
01103 
01104   video_modes_lookup_[1] = video_mode;
01105 
01106   // SXGA_15Hz
01107   video_mode.x_resolution_ = 1280;
01108   video_mode.y_resolution_ = 1024;
01109   video_mode.frame_rate_ = 15;
01110 
01111   video_modes_lookup_[2] = video_mode;
01112 
01113   // XGA_30Hz
01114   video_mode.x_resolution_ = 1280;
01115   video_mode.y_resolution_ = 720;
01116   video_mode.frame_rate_ = 30;
01117 
01118   video_modes_lookup_[3] = video_mode;
01119 
01120   // XGA_15Hz
01121   video_mode.x_resolution_ = 1280;
01122   video_mode.y_resolution_ = 720;
01123   video_mode.frame_rate_ = 15;
01124 
01125   video_modes_lookup_[4] = video_mode;
01126 
01127   // VGA_30Hz
01128   video_mode.x_resolution_ = 640;
01129   video_mode.y_resolution_ = 480;
01130   video_mode.frame_rate_ = 30;
01131 
01132   video_modes_lookup_[5] = video_mode;
01133 
01134   // VGA_25Hz
01135   video_mode.x_resolution_ = 640;
01136   video_mode.y_resolution_ = 480;
01137   video_mode.frame_rate_ = 25;
01138 
01139   video_modes_lookup_[6] = video_mode;
01140 
01141   // QVGA_25Hz
01142   video_mode.x_resolution_ = 320;
01143   video_mode.y_resolution_ = 240;
01144   video_mode.frame_rate_ = 25;
01145 
01146   video_modes_lookup_[7] = video_mode;
01147 
01148   // QVGA_30Hz
01149   video_mode.x_resolution_ = 320;
01150   video_mode.y_resolution_ = 240;
01151   video_mode.frame_rate_ = 30;
01152 
01153   video_modes_lookup_[8] = video_mode;
01154 
01155   // QVGA_60Hz
01156   video_mode.x_resolution_ = 320;
01157   video_mode.y_resolution_ = 240;
01158   video_mode.frame_rate_ = 60;
01159 
01160   video_modes_lookup_[9] = video_mode;
01161 
01162   // QQVGA_25Hz
01163   video_mode.x_resolution_ = 160;
01164   video_mode.y_resolution_ = 120;
01165   video_mode.frame_rate_ = 25;
01166 
01167   video_modes_lookup_[10] = video_mode;
01168 
01169   // QQVGA_30Hz
01170   video_mode.x_resolution_ = 160;
01171   video_mode.y_resolution_ = 120;
01172   video_mode.frame_rate_ = 30;
01173 
01174   video_modes_lookup_[11] = video_mode;
01175 
01176   // QQVGA_60Hz
01177   video_mode.x_resolution_ = 160;
01178   video_mode.y_resolution_ = 120;
01179   video_mode.frame_rate_ = 60;
01180 
01181   video_modes_lookup_[12] = video_mode;
01182 
01183   // 640*400_30Hz
01184   video_mode.x_resolution_ = 640;
01185   video_mode.y_resolution_ = 400;
01186   video_mode.frame_rate_ = 30;
01187 
01188   video_modes_lookup_[13] = video_mode;
01189 
01190   // 320*200_30Hz
01191   video_mode.x_resolution_ = 320;
01192   video_mode.y_resolution_ = 200;
01193   video_mode.frame_rate_ = 30;
01194 
01195   video_modes_lookup_[14] = video_mode;
01196 }
01197 
01198 int AstraDriver::lookupVideoModeFromDynConfig(int mode_nr, AstraVideoMode& video_mode)
01199 {
01200   int ret = -1;
01201 
01202   std::map<int, AstraVideoMode>::const_iterator it;
01203 
01204   it = video_modes_lookup_.find(mode_nr);
01205 
01206   if (it!=video_modes_lookup_.end())
01207   {
01208     video_mode = it->second;
01209     ret = 0;
01210   }
01211 
01212   return ret;
01213 }
01214 
01215 sensor_msgs::ImageConstPtr AstraDriver::rawToFloatingPointConversion(sensor_msgs::ImageConstPtr raw_image)
01216 {
01217   static const float bad_point = std::numeric_limits<float>::quiet_NaN ();
01218 
01219   sensor_msgs::ImagePtr new_image = boost::make_shared<sensor_msgs::Image>();
01220 
01221   new_image->header = raw_image->header;
01222   new_image->width = raw_image->width;
01223   new_image->height = raw_image->height;
01224   new_image->is_bigendian = 0;
01225   new_image->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
01226   new_image->step = sizeof(float)*raw_image->width;
01227 
01228   std::size_t data_size = new_image->width*new_image->height;
01229   new_image->data.resize(data_size*sizeof(float));
01230 
01231   const unsigned short* in_ptr = reinterpret_cast<const unsigned short*>(&raw_image->data[0]);
01232   float* out_ptr = reinterpret_cast<float*>(&new_image->data[0]);
01233 
01234   for (std::size_t i = 0; i<data_size; ++i, ++in_ptr, ++out_ptr)
01235   {
01236     if (*in_ptr==0 || *in_ptr==0x7FF)
01237     {
01238       *out_ptr = bad_point;
01239     } else
01240     {
01241       *out_ptr = static_cast<float>(*in_ptr)/1000.0f;
01242     }
01243   }
01244 
01245   return new_image;
01246 }
01247 
01248 }


astra_camera
Author(s): Tim Liu
autogenerated on Wed Jul 10 2019 03:18:54