00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00031 
00032 #include "ros/ros.h"
00033 #include <pluginlib/class_list_macros.h>
00034 #include <nodelet/nodelet.h>
00035 
00036 #include "pointgrey_camera_driver/PointGreyCamera.h" 
00037 
00038 #include <image_transport/image_transport.h> 
00039 #include <camera_info_manager/camera_info_manager.h> 
00040 #include <sensor_msgs/CameraInfo.h> 
00041 #include <std_msgs/Float64.h>
00042 
00043 #include <wfov_camera_msgs/WFOVImage.h>
00044 #include <image_exposure_msgs/ExposureSequence.h> 
00045 
00046 #include <diagnostic_updater/diagnostic_updater.h> 
00047 #include <diagnostic_updater/publisher.h>
00048 
00049 #include <boost/thread.hpp> 
00050 
00051 #include <dynamic_reconfigure/server.h> 
00052 
00053 namespace pointgrey_camera_driver
00054 {
00055 
00056 class PointGreyStereoCameraNodelet: public nodelet::Nodelet
00057 {
00058 public:
00059   PointGreyStereoCameraNodelet() {}
00060 
00061   ~PointGreyStereoCameraNodelet()
00062   {
00063     pubThread_->interrupt();
00064     pubThread_->join();
00065     cleanUp();
00066   }
00067 
00068 private:
00076   void paramCallback(pointgrey_camera_driver::PointGreyConfig &config, uint32_t level)
00077   {
00078 
00079     
00080     config.video_mode = "format7_mode3";
00081 
00082     try
00083     {
00084       NODELET_DEBUG("Dynamic reconfigure callback with level: %d", level);
00085       pg_.setNewConfiguration(config, level);
00086 
00087       
00088       gain_ = config.gain;
00089       wb_blue_ = config.white_balance_blue;
00090       wb_red_ = config.white_balance_red;
00091 
00092 
00093       
00094       if(config.video_mode == "640x480_mono8" || config.video_mode == "format7_mode1")
00095       {
00096         binning_x_ = 2;
00097         binning_y_ = 2;
00098       }
00099       else if(config.video_mode == "format7_mode2")
00100       {
00101         binning_x_ = 0;
00102         binning_y_ = 2;
00103       }
00104       else
00105       {
00106         binning_x_ = 0;
00107         binning_y_ = 0;
00108       }
00109 
00110       
00111       if(config.video_mode == "format7_mode0" || config.video_mode == "format7_mode1" || config.video_mode == "format7_mode2")
00112       {
00113         roi_x_offset_ = config.format7_x_offset;
00114         roi_y_offset_ = config.format7_y_offset;
00115         roi_width_ = config.format7_roi_width;
00116         roi_height_ = config.format7_roi_height;
00117         do_rectify_ = true; 
00118       }
00119       else
00120       {
00121         
00122         roi_x_offset_ = 0;
00123         roi_y_offset_ = 0;
00124         roi_height_ = 0;
00125         roi_width_ = 0;
00126         do_rectify_ = false; 
00127       }
00128     }
00129     catch(std::runtime_error& e)
00130     {
00131       NODELET_ERROR("Reconfigure Callback failed with error: %s", e.what());
00132     }
00133   }
00134 
00140   void onInit()
00141   {
00142     
00143     ros::NodeHandle &nh = getMTNodeHandle();
00144     ros::NodeHandle &pnh = getMTPrivateNodeHandle();
00145     std::string firstcam;
00146     pnh.param<std::string>("first_namespace", firstcam, "left");
00147     ros::NodeHandle lnh(getMTNodeHandle(), firstcam);
00148     std::string secondcam;
00149     pnh.param<std::string>("second_namespace", secondcam, "right");
00150     ros::NodeHandle rnh(getMTNodeHandle(), secondcam);
00151 
00152     
00153     int serialParam;
00154     pnh.param<int>("serial", serialParam, 0);
00155     uint32_t serial = (uint32_t)serialParam;
00156     
00157     std::string camera_info_url;
00158     pnh.param<std::string>("camera_info_url", camera_info_url, "");
00159     std::string second_info_url;
00160     pnh.param<std::string>("second_info_url", second_info_url, "");
00161     
00162     pnh.param<std::string>("frame_id", frame_id_, "camera");
00163     pnh.param<std::string>("second_frame_id", second_frame_id_, frame_id_); 
00164     
00165     double timeout;
00166     pnh.param("timeout", timeout, 1.0);
00167 
00168     
00169     volatile bool connected = false;
00170     while(!connected && ros::ok())
00171     {
00172       try
00173       {
00174         NODELET_INFO("Connecting to camera serial: %u", serial);
00175         pg_.setDesiredCamera(serial);
00176         NODELET_DEBUG("Actually connecting to camera.");
00177         pg_.connect();
00178         connected = true;
00179         NODELET_DEBUG("Setting timeout to: %f.", timeout);
00180         pg_.setTimeout(timeout);
00181       }
00182       catch(std::runtime_error& e)
00183       {
00184         NODELET_ERROR("%s", e.what());
00185         ros::Duration(1.0).sleep(); 
00186       }
00187     }
00188 
00189     
00190     srv_ = boost::make_shared <dynamic_reconfigure::Server<pointgrey_camera_driver::PointGreyConfig> > (pnh);
00191     dynamic_reconfigure::Server<pointgrey_camera_driver::PointGreyConfig>::CallbackType f =  boost::bind(&pointgrey_camera_driver::PointGreyStereoCameraNodelet::paramCallback, this, _1, _2);
00192     srv_->setCallback(f);
00193 
00194     
00195     std::stringstream cinfo_name;
00196     cinfo_name << serial;
00197     cinfo_.reset(new camera_info_manager::CameraInfoManager(lnh, cinfo_name.str(), camera_info_url));
00198     rcinfo_.reset(new camera_info_manager::CameraInfoManager(rnh, cinfo_name.str(), second_info_url));
00199     
00200 
00201 
00202     ci_.reset(new sensor_msgs::CameraInfo(cinfo_->getCameraInfo()));
00203     ci_->header.frame_id = frame_id_;
00204     rci_.reset(new sensor_msgs::CameraInfo(rcinfo_->getCameraInfo()));
00205     rci_->header.frame_id = second_frame_id_;
00206 
00207     
00208     it_.reset(new image_transport::ImageTransport(lnh));
00209     it_pub_ = it_->advertiseCamera("image_raw", 5);
00210     rit_.reset(new image_transport::ImageTransport(rnh));
00211     rit_pub_ = rit_->advertiseCamera("image_raw", 5);
00212 
00213     
00214     updater_.setHardwareID("pointgrey_camera " + serial);
00215 
00217     temp_pub_ = nh.advertise<std_msgs::Float64>("temp", 5);
00218 
00219     
00220     sub_ = nh.subscribe("image_exposure_sequence", 10, &pointgrey_camera_driver::PointGreyStereoCameraNodelet::gainWBCallback, this);
00221 
00222     volatile bool started = false;
00223     while(!started)
00224     {
00225       try
00226       {
00227         NODELET_DEBUG("Starting camera capture.");
00228         pg_.start();
00229         started = true;
00230         
00231         pubThread_ = boost::shared_ptr< boost::thread > (new boost::thread(boost::bind(&pointgrey_camera_driver::PointGreyStereoCameraNodelet::devicePoll, this)));
00232       }
00233       catch(std::runtime_error& e)
00234       {
00235         NODELET_ERROR("%s", e.what());
00236         ros::Duration(1.0).sleep(); 
00237       }
00238     }
00239   }
00240 
00246   void cleanUp()
00247   {
00248     try
00249     {
00250       NODELET_DEBUG("Stopping camera capture.");
00251       pg_.stop();
00252       NODELET_DEBUG("Disconnecting from camera.");
00253       pg_.disconnect();
00254     }
00255     catch(std::runtime_error& e)
00256     {
00257       NODELET_ERROR("%s", e.what());
00258     }
00259   }
00260 
00266   void devicePoll()
00267   {
00268     while(!boost::this_thread::interruption_requested())   
00269     {
00270       try
00271       {
00272         sensor_msgs::ImagePtr image(new sensor_msgs::Image);
00273         sensor_msgs::ImagePtr second_image(new sensor_msgs::Image);
00274         pg_.grabStereoImage(*image, frame_id_, *second_image, second_frame_id_);
00275 
00276         ros::Time time = ros::Time::now();
00277         image->header.stamp = time;
00278         second_image->header.stamp = time;
00279         ci_->header.stamp = time;
00280         rci_->header.stamp = time;
00281         ci_->binning_x = binning_x_;
00282         rci_->binning_x = binning_x_;
00283         ci_->binning_y = binning_y_;
00284         rci_->binning_y = binning_y_;
00285         ci_->roi.x_offset = roi_x_offset_;
00286         rci_->roi.x_offset = roi_x_offset_;
00287         ci_->roi.y_offset = roi_y_offset_;
00288         rci_->roi.y_offset = roi_y_offset_;
00289         ci_->roi.height = roi_height_;
00290         rci_->roi.height = roi_height_;
00291         ci_->roi.width = roi_width_;
00292         rci_->roi.width = roi_width_;
00293         ci_->roi.do_rectify = do_rectify_;
00294         rci_->roi.do_rectify = do_rectify_;
00295 
00296         it_pub_.publish(image, ci_);
00297         rit_pub_.publish(second_image, rci_);
00298         std_msgs::Float64 temp;
00299         temp.data = pg_.getCameraTemperature();
00300         temp_pub_.publish(temp);
00301       }
00302       catch(CameraTimeoutException& e)
00303       {
00304         NODELET_WARN("%s", e.what());
00305       }
00306       catch(std::runtime_error& e)
00307       {
00308         NODELET_ERROR("%s", e.what());
00309         try
00310         {
00311           
00312           pg_.disconnect();
00313           ros::Duration(1.0).sleep(); 
00314           pg_.connect();
00315           pg_.start();
00316         }
00317         catch(std::runtime_error& e2)
00318         {
00319           NODELET_ERROR("%s", e2.what());
00320         }
00321       }
00322       
00323       updater_.update();
00324     }
00325   }
00326 
00327   void gainWBCallback(const image_exposure_msgs::ExposureSequence &msg)
00328   {
00329     try
00330     {
00331       NODELET_DEBUG("Gain callback:  Setting gain to %f and white balances to %u, %u", msg.gain, msg.white_balance_blue, msg.white_balance_red);
00332       gain_ = msg.gain;
00333       pg_.setGain(gain_);
00334       wb_blue_ = msg.white_balance_blue;
00335       wb_red_ = msg.white_balance_red;
00336       pg_.setBRWhiteBalance(false, wb_blue_, wb_red_);
00337     }
00338     catch(std::runtime_error& e)
00339     {
00340       NODELET_ERROR("gainWBCallback failed with error: %s", e.what());
00341     }
00342   }
00343 
00344   boost::shared_ptr<dynamic_reconfigure::Server<pointgrey_camera_driver::PointGreyConfig> > srv_; 
00345   boost::shared_ptr<image_transport::ImageTransport> it_; 
00346   boost::shared_ptr<camera_info_manager::CameraInfoManager> cinfo_; 
00347   image_transport::CameraPublisher it_pub_; 
00348   ros::Publisher temp_pub_; 
00349   ros::Subscriber sub_; 
00350 
00351   diagnostic_updater::Updater updater_; 
00352   double min_freq_;
00353   double max_freq_;
00354 
00355   PointGreyCamera pg_; 
00356   sensor_msgs::CameraInfoPtr ci_; 
00357   std::string frame_id_; 
00358   boost::shared_ptr<boost::thread> pubThread_; 
00359 
00360   double gain_;
00361   uint16_t wb_blue_;
00362   uint16_t wb_red_;
00363 
00364   
00365   std::string second_frame_id_; 
00366   boost::shared_ptr<image_transport::ImageTransport> rit_; 
00367   boost::shared_ptr<camera_info_manager::CameraInfoManager> rcinfo_; 
00368   image_transport::CameraPublisher rit_pub_; 
00369   sensor_msgs::CameraInfoPtr rci_; 
00370 
00371   
00372   size_t binning_x_; 
00373   size_t binning_y_; 
00374   size_t roi_x_offset_; 
00375   size_t roi_y_offset_; 
00376   size_t roi_height_; 
00377   size_t roi_width_; 
00378   bool do_rectify_; 
00379 };
00380 
00381 PLUGINLIB_DECLARE_CLASS(pointgrey_camera_driver, PointGreyStereoCameraNodelet, pointgrey_camera_driver::PointGreyStereoCameraNodelet, nodelet::Nodelet);  
00382 }