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
00042 #include <wfov_camera_msgs/WFOVImage.h>
00043 #include <image_exposure_msgs/ExposureSequence.h>
00044
00045 #include <diagnostic_updater/diagnostic_updater.h>
00046 #include <diagnostic_updater/publisher.h>
00047
00048 #include <boost/thread.hpp>
00049
00050 #include <dynamic_reconfigure/server.h>
00051
00052 namespace pointgrey_camera_driver
00053 {
00054
00055 class PointGreyCameraNodelet: public nodelet::Nodelet
00056 {
00057 public:
00058 PointGreyCameraNodelet() {}
00059
00060 ~PointGreyCameraNodelet()
00061 {
00062 if(pubThread_)
00063 {
00064 pubThread_->interrupt();
00065 pubThread_->join();
00066 }
00067
00068 try
00069 {
00070 NODELET_DEBUG("Stopping camera capture.");
00071 pg_.stop();
00072 NODELET_DEBUG("Disconnecting from camera.");
00073 pg_.disconnect();
00074 }
00075 catch(std::runtime_error& e)
00076 {
00077 NODELET_ERROR("%s", e.what());
00078 }
00079 }
00080
00081 private:
00089 void paramCallback(pointgrey_camera_driver::PointGreyConfig &config, uint32_t level)
00090 {
00091 try
00092 {
00093 NODELET_DEBUG("Dynamic reconfigure callback with level: %d", level);
00094 pg_.setNewConfiguration(config, level);
00095
00096
00097 gain_ = config.gain;
00098 wb_blue_ = config.white_balance_blue;
00099 wb_red_ = config.white_balance_red;
00100
00101
00102 binning_x_ = 1;
00103 binning_y_ = 1;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 if(config.video_mode == "format7_mode0" || config.video_mode == "format7_mode1" || config.video_mode == "format7_mode2")
00124 {
00125 roi_x_offset_ = config.format7_x_offset;
00126 roi_y_offset_ = config.format7_y_offset;
00127 roi_width_ = config.format7_roi_width;
00128 roi_height_ = config.format7_roi_height;
00129 do_rectify_ = true;
00130 }
00131 else
00132 {
00133
00134 roi_x_offset_ = 0;
00135 roi_y_offset_ = 0;
00136 roi_height_ = 0;
00137 roi_width_ = 0;
00138 do_rectify_ = false;
00139 }
00140 }
00141 catch(std::runtime_error& e)
00142 {
00143 NODELET_ERROR("Reconfigure Callback failed with error: %s", e.what());
00144 }
00145 }
00146
00152 void connectCb()
00153 {
00154 NODELET_DEBUG("Connect callback!");
00155 boost::mutex::scoped_lock scopedLock(connect_mutex_);
00156
00157 if(it_pub_.getNumSubscribers() == 0 && pub_->getPublisher().getNumSubscribers() == 0)
00158 {
00159 try
00160 {
00161 NODELET_DEBUG("Disconnecting.");
00162 pubThread_->interrupt();
00163 pubThread_->join();
00164 sub_.shutdown();
00165 NODELET_DEBUG("Stopping camera capture.");
00166 pg_.stop();
00167
00168
00169 }
00170 catch(std::runtime_error& e)
00171 {
00172 NODELET_ERROR("%s", e.what());
00173 }
00174 }
00175 else if(!sub_)
00176 {
00177 NODELET_DEBUG("Connecting");
00178
00179 volatile bool connected = false;
00180 while(!connected && ros::ok())
00181 {
00182 try
00183 {
00184 NODELET_DEBUG("Connecting to camera.");
00185 pg_.connect();
00186 connected = true;
00187 }
00188 catch(std::runtime_error& e)
00189 {
00190 NODELET_ERROR("%s", e.what());
00191 ros::Duration(1.0).sleep();
00192 }
00193 }
00194
00195
00196 double timeout;
00197 getMTPrivateNodeHandle().param("timeout", timeout, 1.0);
00198 try
00199 {
00200 NODELET_DEBUG("Setting timeout to: %f.", timeout);
00201 pg_.setTimeout(timeout);
00202 }
00203 catch(std::runtime_error& e)
00204 {
00205 NODELET_ERROR("%s", e.what());
00206 }
00207
00208
00209 sub_ = getMTNodeHandle().subscribe("image_exposure_sequence", 10, &pointgrey_camera_driver::PointGreyCameraNodelet::gainWBCallback, this);
00210
00211 volatile bool started = false;
00212 while(!started && ros::ok())
00213 {
00214 try
00215 {
00216 NODELET_DEBUG("Starting camera capture.");
00217 pg_.start();
00218 started = true;
00219 }
00220 catch(std::runtime_error& e)
00221 {
00222 NODELET_ERROR("%s", e.what());
00223 ros::Duration(1.0).sleep();
00224 }
00225 }
00226
00227
00228 pubThread_.reset(new boost::thread(boost::bind(&pointgrey_camera_driver::PointGreyCameraNodelet::devicePoll, this)));
00229 }
00230 else
00231 {
00232 NODELET_DEBUG("Do nothing in callback.");
00233 }
00234 }
00235
00241 void onInit()
00242 {
00243
00244 ros::NodeHandle &nh = getMTNodeHandle();
00245 ros::NodeHandle &pnh = getMTPrivateNodeHandle();
00246
00247
00248 int serial;
00249 pnh.param<int>("serial", serial, 0);
00250 pg_.setDesiredCamera((uint32_t)serial);
00251
00252
00253 pnh.param<int>("packet_size", packet_size_, 1400);
00254 pnh.param<bool>("auto_packet_size", auto_packet_size_, true);
00255 pnh.param<int>("packet_delay", packet_delay_, 4000);
00256
00257
00258 pg_.setGigEParameters(auto_packet_size_, packet_size_, packet_delay_);
00259
00260
00261 std::string camera_info_url;
00262 pnh.param<std::string>("camera_info_url", camera_info_url, "");
00263
00264 pnh.param<std::string>("frame_id", frame_id_, "camera");
00265
00266
00267 boost::mutex::scoped_lock scopedLock(connect_mutex_);
00268
00269
00270 srv_ = boost::make_shared <dynamic_reconfigure::Server<pointgrey_camera_driver::PointGreyConfig> > (pnh);
00271 dynamic_reconfigure::Server<pointgrey_camera_driver::PointGreyConfig>::CallbackType f =
00272 boost::bind(&pointgrey_camera_driver::PointGreyCameraNodelet::paramCallback, this, _1, _2);
00273 srv_->setCallback(f);
00274
00275
00276 std::stringstream cinfo_name;
00277 cinfo_name << serial;
00278 cinfo_.reset(new camera_info_manager::CameraInfoManager(nh, cinfo_name.str(), camera_info_url));
00279
00280
00281 it_.reset(new image_transport::ImageTransport(nh));
00282 image_transport::SubscriberStatusCallback cb = boost::bind(&PointGreyCameraNodelet::connectCb, this);
00283 it_pub_ = it_->advertiseCamera("image_raw", 5, cb, cb);
00284
00285
00286 updater_.setHardwareID("pointgrey_camera " + cinfo_name.str());
00287
00288
00289 double desired_freq;
00290 pnh.param<double>("desired_freq", desired_freq, 7.0);
00291 pnh.param<double>("min_freq", min_freq_, desired_freq);
00292 pnh.param<double>("max_freq", max_freq_, desired_freq);
00293 double freq_tolerance;
00294 pnh.param<double>("freq_tolerance", freq_tolerance, 0.1);
00295 int window_size;
00296 pnh.param<int>("window_size", window_size, 100);
00297 double min_acceptable;
00298 pnh.param<double>("min_acceptable_delay", min_acceptable, 0.0);
00299 double max_acceptable;
00300 pnh.param<double>("max_acceptable_delay", max_acceptable, 0.2);
00301 ros::SubscriberStatusCallback cb2 = boost::bind(&PointGreyCameraNodelet::connectCb, this);
00302 pub_.reset(new diagnostic_updater::DiagnosedPublisher<wfov_camera_msgs::WFOVImage>(nh.advertise<wfov_camera_msgs::WFOVImage>("image", 5, cb2, cb2),
00303 updater_,
00304 diagnostic_updater::FrequencyStatusParam(&min_freq_, &max_freq_, freq_tolerance, window_size),
00305 diagnostic_updater::TimeStampStatusParam(min_acceptable, max_acceptable)));
00306 }
00307
00313 void devicePoll()
00314 {
00315 while(!boost::this_thread::interruption_requested())
00316 {
00317 try
00318 {
00319 wfov_camera_msgs::WFOVImagePtr wfov_image(new wfov_camera_msgs::WFOVImage);
00320
00321 NODELET_DEBUG("Starting a new grab from camera.");
00322 pg_.grabImage(wfov_image->image, frame_id_);
00323
00324
00325 wfov_image->header.frame_id = frame_id_;
00326
00327 wfov_image->gain = gain_;
00328 wfov_image->white_balance_blue = wb_blue_;
00329 wfov_image->white_balance_red = wb_red_;
00330
00331 wfov_image->temperature = pg_.getCameraTemperature();
00332
00333 ros::Time time = ros::Time::now();
00334 wfov_image->header.stamp = time;
00335 wfov_image->image.header.stamp = time;
00336
00337
00338 ci_.reset(new sensor_msgs::CameraInfo(cinfo_->getCameraInfo()));
00339 ci_->header.stamp = wfov_image->image.header.stamp;
00340 ci_->header.frame_id = wfov_image->header.frame_id;
00341
00342 ci_->binning_x = binning_x_;
00343 ci_->binning_y = binning_y_;
00344 ci_->roi.x_offset = roi_x_offset_;
00345 ci_->roi.y_offset = roi_y_offset_;
00346 ci_->roi.height = roi_height_;
00347 ci_->roi.width = roi_width_;
00348 ci_->roi.do_rectify = do_rectify_;
00349
00350 wfov_image->info = *ci_;
00351
00352
00353 pub_->publish(wfov_image);
00354
00355
00356 if(it_pub_.getNumSubscribers() > 0)
00357 {
00358 sensor_msgs::ImagePtr image(new sensor_msgs::Image(wfov_image->image));
00359 it_pub_.publish(image, ci_);
00360 }
00361
00362
00363 }
00364 catch(CameraTimeoutException& e)
00365 {
00366 NODELET_WARN("%s", e.what());
00367 }
00368 catch(std::runtime_error& e)
00369 {
00370 NODELET_ERROR("%s", e.what());
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 }
00382
00383 updater_.update();
00384 }
00385 NODELET_DEBUG("Leaving thread.");
00386 }
00387
00388 void gainWBCallback(const image_exposure_msgs::ExposureSequence &msg)
00389 {
00390 try
00391 {
00392 NODELET_DEBUG("Gain callback: Setting gain to %f and white balances to %u, %u", msg.gain, msg.white_balance_blue, msg.white_balance_red);
00393 gain_ = msg.gain;
00394 pg_.setGain(gain_);
00395 wb_blue_ = msg.white_balance_blue;
00396 wb_red_ = msg.white_balance_red;
00397 pg_.setBRWhiteBalance(false, wb_blue_, wb_red_);
00398 }
00399 catch(std::runtime_error& e)
00400 {
00401 NODELET_ERROR("gainWBCallback failed with error: %s", e.what());
00402 }
00403 }
00404
00405 boost::shared_ptr<dynamic_reconfigure::Server<pointgrey_camera_driver::PointGreyConfig> > srv_;
00406 boost::shared_ptr<image_transport::ImageTransport> it_;
00407 boost::shared_ptr<camera_info_manager::CameraInfoManager> cinfo_;
00408 image_transport::CameraPublisher it_pub_;
00409 boost::shared_ptr<diagnostic_updater::DiagnosedPublisher<wfov_camera_msgs::WFOVImage> > pub_;
00410 ros::Subscriber sub_;
00411
00412 boost::mutex connect_mutex_;
00413
00414 diagnostic_updater::Updater updater_;
00415 double min_freq_;
00416 double max_freq_;
00417
00418 PointGreyCamera pg_;
00419 sensor_msgs::CameraInfoPtr ci_;
00420 std::string frame_id_;
00421 boost::shared_ptr<boost::thread> pubThread_;
00422
00423 double gain_;
00424 uint16_t wb_blue_;
00425 uint16_t wb_red_;
00426
00427
00428 size_t binning_x_;
00429 size_t binning_y_;
00430 size_t roi_x_offset_;
00431 size_t roi_y_offset_;
00432 size_t roi_height_;
00433 size_t roi_width_;
00434 bool do_rectify_;
00435
00436
00438 bool auto_packet_size_;
00440 int packet_size_;
00442 int packet_delay_;
00443 };
00444
00445 PLUGINLIB_DECLARE_CLASS(pointgrey_camera_driver, PointGreyCameraNodelet, pointgrey_camera_driver::PointGreyCameraNodelet, nodelet::Nodelet);
00446 }