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 }