ueye_cam_nodelet.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002 * DO NOT MODIFY - AUTO-GENERATED
00003 *
00004 *
00005 * DISCLAMER:
00006 *
00007 * This project was created within an academic research setting, and thus should
00008 * be considered as EXPERIMENTAL code. There may be bugs and deficiencies in the
00009 * code, so please adjust expectations accordingly. With that said, we are
00010 * intrinsically motivated to ensure its correctness (and often its performance).
00011 * Please use the corresponding web repository tool (e.g. github/bitbucket/etc.)
00012 * to file bugs, suggestions, pull requests; we will do our best to address them
00013 * in a timely manner.
00014 *
00015 *
00016 * SOFTWARE LICENSE AGREEMENT (BSD LICENSE):
00017 *
00018 * Copyright (c) 2013, Anqi Xu
00019 * All rights reserved.
00020 *
00021 * Redistribution and use in source and binary forms, with or without
00022 * modification, are permitted provided that the following conditions
00023 * are met:
00024 *
00025 *  * Redistributions of source code must retain the above copyright
00026 *    notice, this list of conditions and the following disclaimer.
00027 *  * Redistributions in binary form must reproduce the above
00028 *    copyright notice, this list of conditions and the following
00029 *    disclaimer in the documentation and/or other materials provided
00030 *    with the distribution.
00031 *  * Neither the name of the School of Computer Science, McGill University,
00032 *    nor the names of its contributors may be used to endorse or promote
00033 *    products derived from this software without specific prior written
00034 *    permission.
00035 *
00036 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00037 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00038 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00039 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00040 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00041 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00042 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00043 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00044 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00045 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00046 *******************************************************************************/
00047 
00048 #include "ueye_cam/ueye_cam_nodelet.hpp"
00049 #include <cstdlib> // needed for getenv()
00050 #include <ros/package.h>
00051 #include <camera_calibration_parsers/parse.h>
00052 #include <sensor_msgs/fill_image.h>
00053 #include <sensor_msgs/image_encodings.h>
00054 
00055 
00056 //#define DEBUG_PRINTOUT_FRAME_GRAB_RATES
00057 
00058 
00059 using namespace std;
00060 using namespace sensor_msgs::image_encodings;
00061 
00062 
00063 namespace ueye_cam {
00064 
00065 
00066 const std::string UEyeCamNodelet::DEFAULT_FRAME_NAME = "camera";
00067 const std::string UEyeCamNodelet::DEFAULT_CAMERA_NAME = "camera";
00068 const std::string UEyeCamNodelet::DEFAULT_CAMERA_TOPIC = "image_raw";
00069 const std::string UEyeCamNodelet::DEFAULT_COLOR_MODE = "";
00070 constexpr int UEyeCamDriver::ANY_CAMERA; // Needed since CMakeLists.txt creates 2 separate libraries: one for non-ROS parent class, and one for ROS child class
00071 
00072 
00073 UEyeCamNodelet::UEyeCamNodelet() :
00074     nodelet::Nodelet(),
00075     UEyeCamDriver(ANY_CAMERA, DEFAULT_CAMERA_NAME),
00076     frame_grab_alive_(false),
00077     ros_cfg_(NULL),
00078     cfg_sync_requested_(false),
00079     ros_frame_count_(0),
00080     cam_topic_(DEFAULT_CAMERA_TOPIC),
00081     cam_intr_filename_(""),
00082     cam_params_filename_("") {
00083   cam_params_.image_width = DEFAULT_IMAGE_WIDTH;
00084   cam_params_.image_height = DEFAULT_IMAGE_HEIGHT;
00085   cam_params_.image_left = -1;
00086   cam_params_.image_top = -1;
00087   cam_params_.color_mode = DEFAULT_COLOR_MODE;
00088   cam_params_.subsampling = cam_subsampling_rate_;
00089   cam_params_.binning = cam_binning_rate_;
00090   cam_params_.sensor_scaling = cam_sensor_scaling_rate_;
00091   cam_params_.auto_gain = false;
00092   cam_params_.master_gain = 0;
00093   cam_params_.red_gain = 0;
00094   cam_params_.green_gain = 0;
00095   cam_params_.blue_gain = 0;
00096   cam_params_.gain_boost = 0;
00097   cam_params_.auto_exposure = false;
00098   cam_params_.exposure = DEFAULT_EXPOSURE;
00099   cam_params_.auto_white_balance = false;
00100   cam_params_.white_balance_red_offset = 0;
00101   cam_params_.white_balance_blue_offset = 0;
00102   cam_params_.auto_frame_rate = false;
00103   cam_params_.frame_rate = DEFAULT_FRAME_RATE;
00104   cam_params_.pixel_clock = DEFAULT_PIXEL_CLOCK;
00105   cam_params_.ext_trigger_mode = false;
00106   cam_params_.flash_delay = 0;
00107   cam_params_.flash_duration = DEFAULT_FLASH_DURATION;
00108   cam_params_.flip_upd = false;
00109   cam_params_.flip_lr = false;
00110 };
00111 
00112 
00113 UEyeCamNodelet::~UEyeCamNodelet() {
00114   disconnectCam();
00115 
00116   // NOTE: sometimes deleting dynamic reconfigure object will lock up
00117   //       (suspect the scoped lock is not releasing the recursive mutex)
00118   //
00119   //if (ros_cfg_ != NULL) {
00120   //  delete ros_cfg_;
00121   //  ros_cfg_ = NULL;
00122   //}
00123 };
00124 
00125 
00126 void UEyeCamNodelet::onInit() {
00127   ros::NodeHandle& nh = getNodeHandle();
00128   ros::NodeHandle& local_nh = getPrivateNodeHandle();
00129   image_transport::ImageTransport it(nh);
00130 
00131   // Load camera-agnostic ROS parameters
00132   local_nh.param<string>("camera_name", cam_name_, DEFAULT_CAMERA_NAME);
00133   local_nh.param<string>("frame_name", frame_name_, DEFAULT_FRAME_NAME);
00134   local_nh.param<string>("camera_topic", cam_topic_, DEFAULT_CAMERA_TOPIC);
00135   local_nh.param<string>("camera_intrinsics_file", cam_intr_filename_, "");
00136   local_nh.param<int>("camera_id", cam_id_, ANY_CAMERA);
00137   local_nh.param<string>("camera_parameters_file", cam_params_filename_, "");
00138   if (cam_id_ < 0) {
00139     NODELET_WARN_STREAM("Invalid camera ID specified: " << cam_id_ <<
00140       "; setting to ANY_CAMERA");
00141     cam_id_ = ANY_CAMERA;
00142   }
00143 
00144   loadIntrinsicsFile();
00145 
00146   // Setup dynamic reconfigure server
00147   ros_cfg_ = new ReconfigureServer(ros_cfg_mutex_, local_nh);
00148   ReconfigureServer::CallbackType f;
00149   f = bind(&UEyeCamNodelet::configCallback, this, _1, _2);
00150 
00151   // Setup publishers, subscribers, and services
00152   ros_cam_pub_ = it.advertiseCamera("/" + cam_name_ + "/" + cam_topic_, 1);
00153   set_cam_info_srv_ = nh.advertiseService("/" + cam_name_ + "/set_camera_info",
00154       &UEyeCamNodelet::setCamInfo, this);
00155 
00156   // Initiate camera and start capture
00157   if (connectCam() != IS_SUCCESS) {
00158     NODELET_ERROR_STREAM("Failed to initialize UEye camera '" << cam_name_ << "'");
00159     return;
00160   }
00161   ros_cfg_->setCallback(f); // this will call configCallback, which will configure the camera's parameters
00162   startFrameGrabber();
00163   NODELET_INFO_STREAM(
00164       "UEye camera '" << cam_name_ << "' initialized on topic " << ros_cam_pub_.getTopic() << endl <<
00165       "Width:\t\t\t" << cam_params_.image_width << endl <<
00166       "Height:\t\t\t" << cam_params_.image_height << endl <<
00167       "Left Pos.:\t\t" << cam_params_.image_left << endl <<
00168       "Top Pos.:\t\t" << cam_params_.image_top << endl <<
00169       "Color Mode:\t\t" << cam_params_.color_mode << endl <<
00170       "Subsampling:\t\t" << cam_params_.subsampling << endl <<
00171       "Binning:\t\t" << cam_params_.binning << endl <<
00172       "Sensor Scaling:\t\t" << cam_params_.sensor_scaling << endl <<
00173       "Auto Gain:\t\t" << cam_params_.auto_gain << endl <<
00174       "Master Gain:\t\t" << cam_params_.master_gain << endl <<
00175       "Red Gain:\t\t" << cam_params_.red_gain << endl <<
00176       "Green Gain:\t\t" << cam_params_.green_gain << endl <<
00177       "Blue Gain:\t\t" << cam_params_.blue_gain << endl <<
00178       "Gain Boost:\t\t" << cam_params_.gain_boost << endl <<
00179       "Auto Exposure:\t\t" << cam_params_.auto_exposure << endl <<
00180       "Exposure (ms):\t\t" << cam_params_.exposure << endl <<
00181       "Auto White Balance:\t" << cam_params_.auto_white_balance << endl <<
00182       "WB Red Offset:\t\t" << cam_params_.white_balance_red_offset << endl <<
00183       "WB Blue Offset:\t\t" << cam_params_.white_balance_blue_offset << endl <<
00184       "Flash Delay (us):\t" << cam_params_.flash_delay << endl <<
00185       "Flash Duration (us):\t" << cam_params_.flash_duration << endl <<
00186       "Ext Trigger Mode:\t" << cam_params_.ext_trigger_mode << endl <<
00187       "Auto Frame Rate:\t" << cam_params_.auto_frame_rate << endl <<
00188       "Frame Rate (Hz):\t" << cam_params_.frame_rate << endl <<
00189       "Pixel Clock (MHz):\t" << cam_params_.pixel_clock << endl <<
00190       "Mirror Image Upside Down:\t" << cam_params_.flip_upd << endl <<
00191       "Mirror Image Left Right:\t" << cam_params_.flip_lr << endl
00192       );
00193 };
00194 
00195 
00196 INT UEyeCamNodelet::parseROSParams(ros::NodeHandle& local_nh) {
00197   bool hasNewParams = false;
00198   ueye_cam::UEyeCamConfig prevCamParams = cam_params_;
00199   INT is_err = IS_SUCCESS;
00200 
00201   if (local_nh.hasParam("image_width")) {
00202     local_nh.getParam("image_width", cam_params_.image_width);
00203     if (cam_params_.image_width != prevCamParams.image_width) {
00204       if (cam_params_.image_width <= 0) {
00205         NODELET_WARN_STREAM("Invalid requested image width: " << cam_params_.image_width <<
00206           "; using current width: " << prevCamParams.image_width);
00207         cam_params_.image_width = prevCamParams.image_width;
00208       } else {
00209         hasNewParams = true;
00210       }
00211     }
00212   }
00213   if (local_nh.hasParam("image_height")) {
00214     local_nh.getParam("image_height", cam_params_.image_height);
00215     if (cam_params_.image_height != prevCamParams.image_height) {
00216       if (cam_params_.image_height <= 0) {
00217         NODELET_WARN_STREAM("Invalid requested image height: " << cam_params_.image_height <<
00218           "; using current height: " << prevCamParams.image_height);
00219         cam_params_.image_height = prevCamParams.image_height;
00220       } else {
00221         hasNewParams = true;
00222       }
00223     }
00224   }
00225   if (local_nh.hasParam("image_top")) {
00226     local_nh.getParam("image_top", cam_params_.image_top);
00227     if (cam_params_.image_top != prevCamParams.image_top) {
00228       hasNewParams = true;
00229     }
00230   }
00231   if (local_nh.hasParam("image_left")) {
00232     local_nh.getParam("image_left", cam_params_.image_left);
00233     if (cam_params_.image_left != prevCamParams.image_left) {
00234       hasNewParams = true;
00235     }
00236   }
00237   if (local_nh.hasParam("color_mode")) {
00238     local_nh.getParam("color_mode", cam_params_.color_mode);
00239     if (cam_params_.color_mode != prevCamParams.color_mode) {
00240       if (cam_params_.color_mode.length() > 0) {
00241         transform(cam_params_.color_mode.begin(),
00242             cam_params_.color_mode.end(),
00243             cam_params_.color_mode.begin(),
00244             ::tolower);
00245         if (cam_params_.color_mode != RGB8 &&
00246             cam_params_.color_mode != MONO8 &&
00247             cam_params_.color_mode != BAYER_RGGB8) {
00248           NODELET_WARN_STREAM("Invalid requested color mode: " << cam_params_.color_mode <<
00249             "; using current mode: " << prevCamParams.color_mode);
00250           cam_params_.color_mode = prevCamParams.color_mode;
00251         } else {
00252           hasNewParams = true;
00253         }
00254       } else { // Empty requested color mode string
00255         cam_params_.color_mode = prevCamParams.color_mode;
00256       }
00257     }
00258   }
00259   if (local_nh.hasParam("subsampling")) {
00260     local_nh.getParam("subsampling", cam_params_.subsampling);
00261     if (cam_params_.subsampling != prevCamParams.subsampling) {
00262       if (!(cam_params_.subsampling == 1 ||
00263           cam_params_.subsampling == 2 ||
00264           cam_params_.subsampling == 4 ||
00265           cam_params_.subsampling == 8 ||
00266           cam_params_.subsampling == 16)) {
00267         NODELET_WARN_STREAM("Invalid or unsupported requested subsampling rate: " << cam_params_.subsampling <<
00268             "; using current rate: " << prevCamParams.subsampling);
00269         cam_params_.subsampling = prevCamParams.subsampling;
00270       } else {
00271         hasNewParams = true;
00272       }
00273     }
00274   }
00275   if (local_nh.hasParam("auto_gain")) {
00276     local_nh.getParam("auto_gain", cam_params_.auto_gain);
00277     if (cam_params_.auto_gain != prevCamParams.auto_gain) {
00278       hasNewParams = true;
00279     }
00280   }
00281   if (local_nh.hasParam("master_gain")) {
00282     local_nh.getParam("master_gain", cam_params_.master_gain);
00283     if (cam_params_.master_gain != prevCamParams.master_gain) {
00284       if (cam_params_.master_gain < 0 || cam_params_.master_gain > 100) {
00285         NODELET_WARN_STREAM("Invalid master gain: " << cam_params_.master_gain <<
00286             "; using current master gain: " << prevCamParams.master_gain);
00287         cam_params_.master_gain = prevCamParams.master_gain;
00288       } else {
00289         hasNewParams = true;
00290       }
00291     }
00292   }
00293   if (local_nh.hasParam("red_gain")) {
00294     local_nh.getParam("red_gain", cam_params_.red_gain);
00295     if (cam_params_.red_gain != prevCamParams.red_gain) {
00296       if (cam_params_.red_gain < 0 || cam_params_.red_gain > 100) {
00297         NODELET_WARN_STREAM("Invalid red gain: " << cam_params_.red_gain <<
00298             "; using current red gain: " << prevCamParams.red_gain);
00299         cam_params_.red_gain = prevCamParams.red_gain;
00300       } else {
00301         hasNewParams = true;
00302       }
00303     }
00304   }
00305   if (local_nh.hasParam("green_gain")) {
00306     local_nh.getParam("green_gain", cam_params_.green_gain);
00307     if (cam_params_.green_gain != prevCamParams.green_gain) {
00308       if (cam_params_.green_gain < 0 || cam_params_.green_gain > 100) {
00309         NODELET_WARN_STREAM("Invalid green gain: " << cam_params_.green_gain <<
00310             "; using current green gain: " << prevCamParams.green_gain);
00311         cam_params_.green_gain = prevCamParams.green_gain;
00312       } else {
00313         hasNewParams = true;
00314       }
00315     }
00316   }
00317   if (local_nh.hasParam("blue_gain")) {
00318     local_nh.getParam("blue_gain", cam_params_.blue_gain);
00319     if (cam_params_.blue_gain != prevCamParams.blue_gain) {
00320       if (cam_params_.blue_gain < 0 || cam_params_.blue_gain > 100) {
00321         NODELET_WARN_STREAM("Invalid blue gain: " << cam_params_.blue_gain <<
00322             "; using current blue gain: " << prevCamParams.blue_gain);
00323         cam_params_.blue_gain = prevCamParams.blue_gain;
00324       } else {
00325         hasNewParams = true;
00326       }
00327     }
00328   }
00329   if (local_nh.hasParam("gain_boost")) {
00330     local_nh.getParam("gain_boost", cam_params_.gain_boost);
00331     if (cam_params_.gain_boost != prevCamParams.gain_boost) {
00332       hasNewParams = true;
00333     }
00334   }
00335   if (local_nh.hasParam("auto_exposure")) {
00336     local_nh.getParam("auto_exposure", cam_params_.auto_exposure);
00337     if (cam_params_.auto_exposure != prevCamParams.auto_exposure) {
00338       hasNewParams = true;
00339     }
00340   }
00341   if (local_nh.hasParam("exposure")) {
00342     local_nh.getParam("exposure", cam_params_.exposure);
00343     if (cam_params_.exposure != prevCamParams.exposure) {
00344       if (cam_params_.exposure < 0.0) {
00345         NODELET_WARN_STREAM("Invalid requested exposure: " << cam_params_.exposure <<
00346           "; using current exposure: " << prevCamParams.exposure);
00347         cam_params_.exposure = prevCamParams.exposure;
00348       } else {
00349         hasNewParams = true;
00350       }
00351     }
00352   }
00353   if (local_nh.hasParam("auto_white_balance")) {
00354     local_nh.getParam("auto_white_balance", cam_params_.auto_white_balance);
00355     if (cam_params_.auto_white_balance != prevCamParams.auto_white_balance) {
00356       hasNewParams = true;
00357     }
00358   }
00359   if (local_nh.hasParam("white_balance_red_offset")) {
00360     local_nh.getParam("white_balance_red_offset", cam_params_.white_balance_red_offset);
00361     if (cam_params_.white_balance_red_offset != prevCamParams.white_balance_red_offset) {
00362       if (cam_params_.white_balance_red_offset < -50 || cam_params_.white_balance_red_offset > 50) {
00363         NODELET_WARN_STREAM("Invalid white balance red offset: " << cam_params_.white_balance_red_offset <<
00364             "; using current white balance red offset: " << prevCamParams.white_balance_red_offset);
00365         cam_params_.white_balance_red_offset = prevCamParams.white_balance_red_offset;
00366       } else {
00367         hasNewParams = true;
00368       }
00369     }
00370   }
00371   if (local_nh.hasParam("white_balance_blue_offset")) {
00372     local_nh.getParam("white_balance_blue_offset", cam_params_.white_balance_blue_offset);
00373     if (cam_params_.white_balance_blue_offset != prevCamParams.white_balance_blue_offset) {
00374       if (cam_params_.white_balance_blue_offset < -50 || cam_params_.white_balance_blue_offset > 50) {
00375         NODELET_WARN_STREAM("Invalid white balance blue offset: " << cam_params_.white_balance_blue_offset <<
00376             "; using current white balance blue offset: " << prevCamParams.white_balance_blue_offset);
00377         cam_params_.white_balance_blue_offset = prevCamParams.white_balance_blue_offset;
00378       } else {
00379         hasNewParams = true;
00380       }
00381     }
00382   }
00383   if (local_nh.hasParam("ext_trigger_mode")) {
00384     local_nh.getParam("ext_trigger_mode", cam_params_.ext_trigger_mode);
00385     // NOTE: no need to set any parameters, since external trigger / live-run
00386     //       modes come into effect during frame grab loop, which is assumed
00387     //       to not having been initialized yet
00388   }
00389   if (local_nh.hasParam("flash_delay")) {
00390     local_nh.getParam("flash_delay", cam_params_.flash_delay);
00391     // NOTE: no need to set any parameters, since flash delay comes into
00392     //       effect during frame grab loop, which is assumed to not having been
00393     //       initialized yet
00394   }
00395   if (local_nh.hasParam("flash_duration")) {
00396     local_nh.getParam("flash_duration", cam_params_.flash_duration);
00397     if (cam_params_.flash_duration < 0) {
00398       NODELET_WARN_STREAM("Invalid flash duration: " << cam_params_.flash_duration <<
00399           "; using current flash duration: " << prevCamParams.flash_duration);
00400       cam_params_.flash_duration = prevCamParams.flash_duration;
00401     }
00402     // NOTE: no need to set any parameters, since flash duration comes into
00403     //       effect during frame grab loop, which is assumed to not having been
00404     //       initialized yet
00405   }
00406   if (local_nh.hasParam("auto_frame_rate")) {
00407     local_nh.getParam("auto_frame_rate", cam_params_.auto_frame_rate);
00408     if (cam_params_.auto_frame_rate != prevCamParams.auto_frame_rate) {
00409       hasNewParams = true;
00410     }
00411   }
00412   if (local_nh.hasParam("frame_rate")) {
00413     local_nh.getParam("frame_rate", cam_params_.frame_rate);
00414     if (cam_params_.frame_rate != prevCamParams.frame_rate) {
00415       if (cam_params_.frame_rate <= 0.0) {
00416         NODELET_WARN_STREAM("Invalid requested frame rate: " << cam_params_.frame_rate <<
00417           "; using current frame rate: " << prevCamParams.frame_rate);
00418         cam_params_.frame_rate = prevCamParams.frame_rate;
00419       } else {
00420         hasNewParams = true;
00421       }
00422     }
00423   }
00424   if (local_nh.hasParam("pixel_clock")) {
00425     local_nh.getParam("pixel_clock", cam_params_.pixel_clock);
00426     if (cam_params_.pixel_clock != prevCamParams.pixel_clock) {
00427       if (cam_params_.pixel_clock < 0) {
00428         NODELET_WARN_STREAM("Invalid requested pixel clock: " << cam_params_.pixel_clock <<
00429           "; using current pixel clock: " << prevCamParams.pixel_clock);
00430         cam_params_.pixel_clock = prevCamParams.pixel_clock;
00431       } else {
00432         hasNewParams = true;
00433       }
00434     }
00435   }
00436   if (local_nh.hasParam("flip_upd")) {
00437     local_nh.getParam("flip_upd", cam_params_.flip_upd);
00438     if (cam_params_.flip_upd != prevCamParams.flip_upd) {
00439       hasNewParams = true;
00440     }
00441   }
00442   if (local_nh.hasParam("flip_lr")) {
00443     local_nh.getParam("flip_lr", cam_params_.flip_lr);
00444     if (cam_params_.flip_lr != prevCamParams.flip_lr) {
00445       hasNewParams = true;
00446     }
00447   }
00448 
00449   if (hasNewParams) {
00450     // Configure color mode, resolution, and subsampling rate
00451     if ((is_err = setColorMode(cam_params_.color_mode, true)) != IS_SUCCESS) return is_err;
00452     if ((is_err = setResolution(cam_params_.image_width, cam_params_.image_height,
00453         cam_params_.image_left, cam_params_.image_top, false)) != IS_SUCCESS) return is_err;
00454     if ((is_err = setSubsampling(cam_params_.subsampling, false)) != IS_SUCCESS) return is_err;
00455     if ((is_err = setBinning(cam_params_.binning, false)) != IS_SUCCESS) return is_err;
00456     if ((is_err = setSensorScaling(cam_params_.sensor_scaling, true)) != IS_SUCCESS) return is_err;
00457 
00458     // (Re-)populate ROS image message
00459     // NOTE: the non-ROS UEye parameters and buffers have been updated by setColorMode, setResolution(), and setSubsampling()
00460     ros_image_.header.frame_id = "/" + frame_name_;
00461     ros_image_.height = cam_params_.image_height / (cam_params_.sensor_scaling * cam_params_.subsampling * cam_params_.binning);
00462     ros_image_.width = cam_params_.image_width / (cam_params_.sensor_scaling * cam_params_.subsampling * cam_params_.binning);
00463     ros_image_.encoding = cam_params_.color_mode;
00464     ros_image_.step = cam_buffer_pitch_;
00465     ros_image_.is_bigendian = 0;
00466     ros_image_.data.resize(cam_buffer_size_);
00467 
00468     // Check for mutual exclusivity among requested sensor parameters
00469     if (!cam_params_.auto_exposure) { // Auto frame rate requires auto shutter
00470       cam_params_.auto_frame_rate = false;
00471     }
00472     if (cam_params_.auto_frame_rate) { // Auto frame rate has precedence over auto gain
00473       cam_params_.auto_gain = false;
00474     }
00475 
00476     // Configure camera sensor parameters
00477     if ((is_err = setGain(cam_params_.auto_gain, cam_params_.master_gain,
00478         cam_params_.red_gain, cam_params_.green_gain,
00479         cam_params_.blue_gain, cam_params_.gain_boost)) != IS_SUCCESS) return is_err;
00480     if ((is_err = setPixelClockRate(cam_params_.pixel_clock)) != IS_SUCCESS) return is_err;
00481     if ((is_err = setFrameRate(cam_params_.auto_frame_rate, cam_params_.frame_rate)) != IS_SUCCESS) return is_err;
00482     if ((is_err = setExposure(cam_params_.auto_exposure, cam_params_.exposure)) != IS_SUCCESS) return is_err;
00483     if ((is_err = setWhiteBalance(cam_params_.auto_white_balance, cam_params_.white_balance_red_offset,
00484       cam_params_.white_balance_blue_offset)) != IS_SUCCESS) return is_err;
00485 
00486     if ((is_err = setMirrorUpsideDown(cam_params_.flip_upd)) != IS_SUCCESS) return is_err;
00487     if ((is_err = setMirrorLeftRight(cam_params_.flip_lr)) != IS_SUCCESS) return is_err;
00488   }
00489 
00490   return is_err;
00491 };
00492 
00493 
00494 void UEyeCamNodelet::configCallback(ueye_cam::UEyeCamConfig& config, uint32_t level) {
00495   if (!isConnected()) return;
00496 
00497   // See if frame grabber needs to be restarted
00498   bool restartFrameGrabber = false;
00499   bool needToReallocateBuffer = false;
00500   if (level == RECONFIGURE_STOP && frame_grab_alive_) {
00501     restartFrameGrabber = true;
00502     stopFrameGrabber();
00503   }
00504 
00505   // Configure color mode, resolution, and subsampling rate
00506   if (config.color_mode != cam_params_.color_mode) {
00507     needToReallocateBuffer = true;
00508     if (setColorMode(config.color_mode, false) != IS_SUCCESS) return;
00509   }
00510 
00511   if (config.image_width != cam_params_.image_width ||
00512       config.image_height != cam_params_.image_height ||
00513       config.image_left != cam_params_.image_left ||
00514       config.image_top != cam_params_.image_top) {
00515     needToReallocateBuffer = true;
00516     if (setResolution(config.image_width, config.image_height,
00517         config.image_left, config.image_top, false) != IS_SUCCESS) {
00518       // Attempt to restore previous (working) resolution
00519       config.image_width = cam_params_.image_width;
00520       config.image_height = cam_params_.image_height;
00521       config.image_left = cam_params_.image_left;
00522       config.image_top = cam_params_.image_top;
00523       if (setResolution(config.image_width, config.image_height,
00524           config.image_left, config.image_top) != IS_SUCCESS) return;
00525     }
00526   }
00527 
00528   if (config.subsampling != cam_params_.subsampling) {
00529     needToReallocateBuffer = true;
00530     if (setSubsampling(config.subsampling, false) != IS_SUCCESS) return;
00531   }
00532 
00533   if (config.binning != cam_params_.binning) {
00534     needToReallocateBuffer = true;
00535     if (setBinning(config.binning, false) != IS_SUCCESS) return;
00536   }
00537 
00538   if (config.sensor_scaling != cam_params_.sensor_scaling) {
00539     needToReallocateBuffer = true;
00540     if (setSensorScaling(config.sensor_scaling, false) != IS_SUCCESS) return;
00541   }
00542 
00543   if (needToReallocateBuffer) {
00544     if (reallocateCamBuffer() != IS_SUCCESS) return;
00545     needToReallocateBuffer = false;
00546   }
00547 
00548   // (Re-)populate ROS image message
00549   // NOTE: the non-ROS UEye parameters and buffers have been updated by setColorMode(),
00550   // setResolution(), setSubsampling(), setBinning(), and setSensorScaling()
00551   ros_image_.header.frame_id = "/" + frame_name_;
00552   ros_image_.height = config.image_height / (config.sensor_scaling * config.subsampling * config.binning);
00553   ros_image_.width = config.image_width / (config.sensor_scaling * config.subsampling * config.binning);
00554   ros_image_.encoding = config.color_mode;
00555   ros_image_.step = cam_buffer_pitch_;
00556   ros_image_.is_bigendian = 0;
00557   ros_image_.data.resize(cam_buffer_size_);
00558 
00559   // Check for mutual exclusivity among requested sensor parameters
00560   if (!config.auto_exposure) { // Auto frame rate requires auto shutter
00561     config.auto_frame_rate = false;
00562   }
00563   if (config.auto_frame_rate) { // Auto frame rate has precedence over auto gain
00564     config.auto_gain = false;
00565   }
00566 
00567   // Configure camera sensor parameters
00568   if (config.auto_gain != cam_params_.auto_gain ||
00569       config.master_gain != cam_params_.master_gain ||
00570       config.red_gain != cam_params_.red_gain ||
00571       config.green_gain != cam_params_.green_gain ||
00572       config.blue_gain != cam_params_.blue_gain ||
00573       config.gain_boost != cam_params_.gain_boost) {
00574     // If any of the manual gain params change, then automatically toggle off auto_gain
00575     if (config.master_gain != cam_params_.master_gain ||
00576       config.red_gain != cam_params_.red_gain ||
00577       config.green_gain != cam_params_.green_gain ||
00578       config.blue_gain != cam_params_.blue_gain ||
00579       config.gain_boost != cam_params_.gain_boost) {
00580       config.auto_gain = false;
00581     }
00582 
00583     if (setGain(config.auto_gain, config.master_gain,
00584         config.red_gain, config.green_gain,
00585         config.blue_gain, config.gain_boost) != IS_SUCCESS) return;
00586   }
00587 
00588   if (config.pixel_clock != cam_params_.pixel_clock) {
00589     if (setPixelClockRate(config.pixel_clock) != IS_SUCCESS) return;
00590   }
00591 
00592   if (config.auto_frame_rate != cam_params_.auto_frame_rate ||
00593       config.frame_rate != cam_params_.frame_rate) {
00594     if (setFrameRate(config.auto_frame_rate, config.frame_rate) != IS_SUCCESS) return;
00595   }
00596 
00597   if (config.auto_exposure != cam_params_.auto_exposure ||
00598       config.exposure != cam_params_.exposure) {
00599     if (setExposure(config.auto_exposure, config.exposure) != IS_SUCCESS) return;
00600   }
00601 
00602   if (config.auto_white_balance != cam_params_.auto_white_balance ||
00603       config.white_balance_red_offset != cam_params_.white_balance_red_offset ||
00604       config.white_balance_blue_offset != cam_params_.white_balance_blue_offset) {
00605     if (setWhiteBalance(config.auto_white_balance, config.white_balance_red_offset,
00606       config.white_balance_blue_offset) != IS_SUCCESS) return;
00607   }
00608 
00609   if (setMirrorUpsideDown(cam_params_.flip_upd) != IS_SUCCESS) return;
00610   if (setMirrorLeftRight(cam_params_.flip_lr) != IS_SUCCESS) return;
00611 
00612   // NOTE: nothing needs to be done for config.ext_trigger_mode, since frame grabber loop will re-initialize to the right setting
00613 
00614   if (config.flash_delay != cam_params_.flash_delay ||
00615       config.flash_duration != cam_params_.flash_duration) {
00616     // NOTE: need to copy flash parameters to local copies since
00617     //       cam_params_.flash_duration is type int, and also sizeof(int)
00618     //       may not equal to sizeof(INT) / sizeof(UINT)
00619     INT flash_delay = config.flash_delay;
00620     UINT flash_duration = config.flash_duration;
00621     if (setFlashParams(flash_delay, flash_duration) != IS_SUCCESS) return;
00622     // Copy back actual flash parameter values that were set
00623     config.flash_delay = flash_delay;
00624     config.flash_duration = flash_duration;
00625   }
00626 
00627   // Update local copy of parameter set to newly updated set
00628   cam_params_ = config;
00629 
00630   // Restart frame grabber if needed
00631   cfg_sync_requested_ = true;
00632   if (restartFrameGrabber) {
00633     startFrameGrabber();
00634   }
00635 };
00636 
00637 
00638 INT UEyeCamNodelet::queryCamParams() {
00639   INT is_err = IS_SUCCESS;
00640   INT query;
00641   double pval1, pval2;
00642 
00643   query = is_SetColorMode(cam_handle_, IS_GET_COLOR_MODE);
00644   if (query == IS_CM_MONO8) cam_params_.color_mode = MONO8;
00645   else if (query == IS_CM_SENSOR_RAW8) cam_params_.color_mode = BAYER_RGGB8;
00646   else if (query == IS_CM_RGB8_PACKED) cam_params_.color_mode = RGB8;
00647   else {
00648     NODELET_WARN_STREAM("Camera configuration loaded into an unsupported color mode; switching to MONO8.");
00649     cam_params_.color_mode = MONO8;
00650     setColorMode(cam_params_.color_mode);
00651   }
00652 
00653   if ((is_err = is_AOI(cam_handle_, IS_AOI_IMAGE_GET_AOI,
00654       (void*) &cam_aoi_, sizeof(cam_aoi_))) != IS_SUCCESS) {
00655     NODELET_ERROR_STREAM("Could not retrieve Area Of Interest from UEye camera '" <<
00656         cam_name_ << "' (" << err2str(is_err) << ")");
00657     disconnectCam();
00658     return is_err;
00659   }
00660   cam_params_.image_width = cam_aoi_.s32Width;
00661   cam_params_.image_height = cam_aoi_.s32Height;
00662   cam_params_.image_left = cam_aoi_.s32X;
00663   cam_params_.image_top = cam_aoi_.s32Y;
00664 
00665   query = is_SetSubSampling(cam_handle_, IS_GET_SUBSAMPLING);
00666   switch (query) {
00667     case IS_SUBSAMPLING_DISABLE:
00668       cam_params_.subsampling = 1;
00669       break;
00670     case IS_SUBSAMPLING_2X:
00671       cam_params_.subsampling = 2;
00672       break;
00673     case IS_SUBSAMPLING_4X:
00674       cam_params_.subsampling = 4;
00675       break;
00676     case IS_SUBSAMPLING_8X:
00677       cam_params_.subsampling = 8;
00678       break;
00679     case IS_SUBSAMPLING_16X:
00680       cam_params_.subsampling = 16;
00681       break;
00682     default:
00683       NODELET_WARN_STREAM("Query returned unsupported subsampling rate; resetting to 1X.");
00684       cam_params_.subsampling = 1;
00685       if ((is_err = setSubsampling(cam_params_.subsampling)) != IS_SUCCESS) return is_err;
00686       break;
00687   }
00688 
00689   query = is_SetBinning(cam_handle_, IS_GET_BINNING);
00690   switch (query) {
00691     case IS_BINNING_DISABLE:
00692       cam_params_.binning = 1;
00693       break;
00694     case IS_BINNING_2X:
00695       cam_params_.binning = 2;
00696       break;
00697     case IS_BINNING_4X:
00698       cam_params_.binning = 4;
00699       break;
00700     case IS_BINNING_8X:
00701       cam_params_.binning = 8;
00702       break;
00703     case IS_BINNING_16X:
00704       cam_params_.binning = 16;
00705       break;
00706     default:
00707       NODELET_WARN_STREAM("Query returned unsupported binning rate; resetting to 1X.");
00708       cam_params_.binning = 1;
00709       if ((is_err = setBinning(cam_params_.binning)) != IS_SUCCESS) return is_err;
00710       break;
00711   }
00712 
00713   SENSORSCALERINFO sensorScalerInfo;
00714   is_err = is_GetSensorScalerInfo(cam_handle_, &sensorScalerInfo, sizeof(sensorScalerInfo));
00715   if (is_err == IS_NOT_SUPPORTED) {
00716     cam_params_.sensor_scaling = 1.0;
00717   } else if (is_err != IS_SUCCESS) {
00718     NODELET_ERROR_STREAM("Failed to query sensor scaler info (" << err2str(is_err) << ")");
00719     return is_err;
00720   } else {
00721     cam_params_.sensor_scaling = sensorScalerInfo.dblCurrFactor;
00722     if (!(cam_params_.sensor_scaling == 1.0 ||
00723         cam_params_.sensor_scaling == 2.0 ||
00724         cam_params_.sensor_scaling == 4.0 ||
00725         cam_params_.sensor_scaling == 8.0 ||
00726         cam_params_.sensor_scaling == 16.0)) {
00727       NODELET_WARN_STREAM("Unsupported sensor scaling rate: " << cam_params_.sensor_scaling <<
00728           "; resetting to 1X.");
00729       cam_params_.sensor_scaling = 1.0;
00730       if ((is_err = setSensorScaling(cam_params_.sensor_scaling)) != IS_SUCCESS) return is_err;
00731     }
00732   }
00733 
00734   if ((is_err = is_SetAutoParameter(cam_handle_,
00735       IS_GET_ENABLE_AUTO_SENSOR_GAIN, &pval1, &pval2)) != IS_SUCCESS &&
00736       (is_err = is_SetAutoParameter(cam_handle_,
00737           IS_GET_ENABLE_AUTO_GAIN, &pval1, &pval2)) != IS_SUCCESS) {
00738     NODELET_ERROR_STREAM("Failed to query auto gain mode for UEye camera '" <<
00739         cam_name_ << "' (" << err2str(is_err) << ")");
00740     return is_err;
00741   }
00742   cam_params_.auto_gain = (pval1 != 0);
00743 
00744   cam_params_.master_gain = is_SetHardwareGain(cam_handle_, IS_GET_MASTER_GAIN,
00745       IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER);
00746   cam_params_.red_gain = is_SetHardwareGain(cam_handle_, IS_GET_RED_GAIN,
00747       IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER);
00748   cam_params_.green_gain = is_SetHardwareGain(cam_handle_, IS_GET_GREEN_GAIN,
00749       IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER);
00750   cam_params_.blue_gain = is_SetHardwareGain(cam_handle_, IS_GET_BLUE_GAIN,
00751       IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER);
00752 
00753   query = is_SetGainBoost(cam_handle_, IS_GET_GAINBOOST);
00754   if (query == IS_SET_GAINBOOST_ON) {
00755     cam_params_.gain_boost = true;
00756   } else if (query == IS_SET_GAINBOOST_OFF) {
00757     cam_params_.gain_boost = false;
00758   } else {
00759     NODELET_ERROR_STREAM("Failed to query gain boost for UEye camera '" <<
00760         cam_name_ << "' (" << err2str(query) << ")");
00761     return query;
00762   }
00763 
00764   if ((is_err = is_SetAutoParameter(cam_handle_,
00765       IS_GET_ENABLE_AUTO_SENSOR_SHUTTER, &pval1, &pval2)) != IS_SUCCESS &&
00766       (is_err = is_SetAutoParameter(cam_handle_,
00767           IS_GET_ENABLE_AUTO_SHUTTER, &pval1, &pval2)) != IS_SUCCESS) {
00768     NODELET_ERROR_STREAM("Failed to query auto shutter mode for UEye camera '" <<
00769         cam_name_ << "' (" << err2str(is_err) << ")");
00770     return is_err;
00771   }
00772   cam_params_.auto_exposure = (pval1 != 0);
00773 
00774   if ((is_err = is_Exposure(cam_handle_, IS_EXPOSURE_CMD_GET_EXPOSURE,
00775       &cam_params_.exposure, sizeof(cam_params_.exposure))) != IS_SUCCESS) {
00776     NODELET_ERROR_STREAM("Failed to query exposure timing for UEye camera '" <<
00777         cam_name_ << "' (" << err2str(is_err) << ")");
00778     return is_err;
00779   }
00780 
00781   if ((is_err = is_SetAutoParameter(cam_handle_,
00782       IS_GET_ENABLE_AUTO_SENSOR_WHITEBALANCE, &pval1, &pval2)) != IS_SUCCESS &&
00783       (is_err = is_SetAutoParameter(cam_handle_,
00784           IS_GET_ENABLE_AUTO_WHITEBALANCE, &pval1, &pval2)) != IS_SUCCESS) {
00785     NODELET_ERROR_STREAM("Failed to query auto white balance mode for UEye camera '" <<
00786         cam_name_ << "' (" << err2str(is_err) << ")");
00787     return is_err;
00788   }
00789   cam_params_.auto_white_balance = (pval1 != 0);
00790 
00791   if ((is_err = is_SetAutoParameter(cam_handle_,
00792       IS_GET_AUTO_WB_OFFSET, &pval1, &pval2)) != IS_SUCCESS) {
00793     NODELET_ERROR_STREAM("Failed to query auto white balance red/blue channel offsets for UEye camera '" <<
00794         cam_name_ << "' (" << err2str(is_err) << ")");
00795     return is_err;
00796   }
00797   cam_params_.white_balance_red_offset = pval1;
00798   cam_params_.white_balance_blue_offset = pval2;
00799 
00800   IO_FLASH_PARAMS currFlashParams;
00801   if ((is_err = is_IO(cam_handle_, IS_IO_CMD_FLASH_GET_PARAMS,
00802       (void*) &currFlashParams, sizeof(IO_FLASH_PARAMS))) != IS_SUCCESS) {
00803     ERROR_STREAM("Could not retrieve current flash parameter info for UEye camera '" <<
00804         cam_name_ << "' (" << err2str(is_err) << ")");
00805     return is_err;
00806   }
00807   cam_params_.flash_delay = currFlashParams.s32Delay;
00808   cam_params_.flash_duration = currFlashParams.u32Duration;
00809 
00810   if ((is_err = is_SetAutoParameter(cam_handle_,
00811       IS_GET_ENABLE_AUTO_SENSOR_FRAMERATE, &pval1, &pval2)) != IS_SUCCESS &&
00812       (is_err = is_SetAutoParameter(cam_handle_,
00813           IS_GET_ENABLE_AUTO_FRAMERATE, &pval1, &pval2)) != IS_SUCCESS) {
00814     NODELET_ERROR_STREAM("Failed to query auto frame rate mode for UEye camera '" <<
00815         cam_name_ << "' (" << err2str(is_err) << ")");
00816     return is_err;
00817   }
00818   cam_params_.auto_frame_rate = (pval1 != 0);
00819 
00820   if ((is_err = is_SetFrameRate(cam_handle_, IS_GET_FRAMERATE, &cam_params_.frame_rate)) != IS_SUCCESS) {
00821     NODELET_ERROR_STREAM("Failed to query frame rate for UEye camera '" <<
00822         cam_name_ << "' (" << err2str(is_err) << ")");
00823     return is_err;
00824   }
00825 
00826   UINT currPixelClock;
00827   if ((is_err = is_PixelClock(cam_handle_, IS_PIXELCLOCK_CMD_GET,
00828       (void*) &currPixelClock, sizeof(currPixelClock))) != IS_SUCCESS) {
00829     NODELET_ERROR_STREAM("Failed to query pixel clock rate for UEye camera '" <<
00830         cam_name_ << "' (" << err2str(is_err) << ")");
00831     return is_err;
00832   }
00833   cam_params_.pixel_clock = currPixelClock;
00834   
00835   INT currROP = is_SetRopEffect(cam_handle_, IS_GET_ROP_EFFECT, 0, 0);
00836   cam_params_.flip_upd = ((currROP & IS_SET_ROP_MIRROR_UPDOWN) == IS_SET_ROP_MIRROR_UPDOWN);
00837   cam_params_.flip_lr = ((currROP & IS_SET_ROP_MIRROR_LEFTRIGHT) == IS_SET_ROP_MIRROR_LEFTRIGHT);
00838 
00839   // Populate ROS image message
00840   // NOTE: the non-ROS UEye parameters and buffers have been updated by setColorMode, setResolution(), and setSubsampling()
00841   ros_image_.header.frame_id = "/" + frame_name_;
00842   ros_image_.height = cam_params_.image_height /
00843       (cam_params_.sensor_scaling * cam_params_.subsampling * cam_params_.binning);
00844   ros_image_.width = cam_params_.image_width /
00845       (cam_params_.sensor_scaling * cam_params_.subsampling * cam_params_.binning);
00846   ros_image_.encoding = cam_params_.color_mode;
00847   ros_image_.step = cam_buffer_pitch_;
00848   ros_image_.is_bigendian = 0;
00849   ros_image_.data.resize(cam_buffer_size_);
00850 
00851   return is_err;
00852 };
00853 
00854 
00855 INT UEyeCamNodelet::connectCam() {
00856   INT is_err = IS_SUCCESS;
00857 
00858   if ((is_err = UEyeCamDriver::connectCam()) != IS_SUCCESS) return is_err;
00859 
00860   // (Attempt to) load UEye camera parameter configuration file
00861   if (cam_params_filename_.length() <= 0) { // Use default filename
00862     cam_params_filename_ = string(getenv("HOME")) + "/.ros/camera_conf/" + cam_name_ + ".ini";
00863   }
00864   loadCamConfig(cam_params_filename_);
00865 
00866   // Query existing configuration parameters from camera
00867   if ((is_err = queryCamParams()) != IS_SUCCESS) return is_err;
00868 
00869   // Parse and load ROS camera settings
00870   if ((is_err = parseROSParams(getPrivateNodeHandle())) != IS_SUCCESS) return is_err;
00871 
00872   return IS_SUCCESS;
00873 };
00874 
00875 
00876 INT UEyeCamNodelet::disconnectCam() {
00877   INT is_err = IS_SUCCESS;
00878 
00879   if (isConnected()) {
00880     stopFrameGrabber();
00881     is_err = UEyeCamDriver::disconnectCam();
00882   }
00883 
00884   return is_err;
00885 };
00886 
00887 
00888 bool UEyeCamNodelet::setCamInfo(sensor_msgs::SetCameraInfo::Request& req,
00889     sensor_msgs::SetCameraInfo::Response& rsp) {
00890   ros_cam_info_ = req.camera_info;
00891   ros_cam_info_.header.frame_id = "/" + frame_name_;
00892   rsp.success = saveIntrinsicsFile();
00893   rsp.status_message = (rsp.success) ? "successfully wrote to file" : "failed to write to file";
00894   return true;
00895 };
00896 
00897 
00898 void UEyeCamNodelet::frameGrabLoop() {
00899 #ifdef DEBUG_PRINTOUT_FRAME_GRAB_RATES
00900   ros::Time prevStartGrab = ros::Time::now();
00901   ros::Time prevGrabbedFrame = ros::Time::now();
00902   ros::Time currStartGrab;
00903   ros::Time currGrabbedFrame;
00904   double startGrabSum = 0;
00905   double grabbedFrameSum = 0;
00906   double startGrabSumSqrd = 0;
00907   double grabbedFrameSumSqrd = 0;
00908   unsigned int startGrabCount = 0;
00909   unsigned int grabbedFrameCount = 0;
00910 #endif
00911 
00912   ros::Rate idleDelay(200);
00913 
00914   int prevNumSubscribers = 0;
00915   int currNumSubscribers = 0;
00916   while (frame_grab_alive_ && ros::ok()) {
00917     // Initialize live video mode if camera was previously asleep, and ROS image topic has subscribers;
00918     // and stop live video mode if ROS image topic no longer has any subscribers
00919     currNumSubscribers = ros_cam_pub_.getNumSubscribers();
00920     if (currNumSubscribers > 0 && prevNumSubscribers <= 0) {
00921       if (cam_params_.ext_trigger_mode) {
00922         if (setExtTriggerMode() != IS_SUCCESS) {
00923           NODELET_ERROR_STREAM("Shutting down UEye camera interface...");
00924           ros::shutdown();
00925           return;
00926         }
00927         NODELET_INFO_STREAM("Camera " << cam_name_ << " set to external trigger mode");
00928       } else {
00929         // NOTE: need to copy flash parameters to local copies since
00930         //       cam_params_.flash_duration is type int, and also sizeof(int)
00931         //       may not equal to sizeof(INT) / sizeof(UINT)
00932         INT flash_delay = cam_params_.flash_delay;
00933         UINT flash_duration = cam_params_.flash_duration;
00934         if ((setFreeRunMode() != IS_SUCCESS) ||
00935             (setFlashParams(flash_delay, flash_duration) != IS_SUCCESS)) {
00936           NODELET_ERROR_STREAM("Shutting down UEye camera interface...");
00937           ros::shutdown();
00938           return;
00939         }
00940         // Copy back actual flash parameter values that were set
00941         cam_params_.flash_delay = flash_delay;
00942         cam_params_.flash_duration = flash_duration;
00943         NODELET_INFO_STREAM("Camera " << cam_name_ << " set to free-run mode");
00944       }
00945     } else if (currNumSubscribers <= 0 && prevNumSubscribers > 0) {
00946       if (setStandbyMode() != IS_SUCCESS) {
00947         NODELET_ERROR_STREAM("Shutting down UEye camera interface...");
00948         ros::shutdown();
00949         return;
00950       }
00951       NODELET_INFO_STREAM("Camera " << cam_name_ << " set to standby mode");
00952     }
00953     prevNumSubscribers = currNumSubscribers;
00954 
00955     // Send updated dyncfg parameters if previously changed
00956     if (cfg_sync_requested_) {
00957       if (ros_cfg_mutex_.try_lock()) { // Make sure that dynamic reconfigure server or config callback is not active
00958         ros_cfg_mutex_.unlock();
00959         ros_cfg_->updateConfig(cam_params_);
00960         cfg_sync_requested_ = false;
00961       }
00962     }
00963 
00964 
00965 #ifdef DEBUG_PRINTOUT_FRAME_GRAB_RATES
00966     startGrabCount++;
00967     currStartGrab = ros::Time::now();
00968     if (startGrabCount > 1) {
00969       startGrabSum += (currStartGrab - prevStartGrab).toSec() * 1000.0;
00970       startGrabSumSqrd += ((currStartGrab - prevStartGrab).toSec() * 1000.0)*((currStartGrab - prevStartGrab).toSec() * 1000.0);
00971     }
00972     prevStartGrab = currStartGrab;
00973 #endif
00974 
00975     if (isCapturing()) {
00976       INT eventTimeout = (cam_params_.auto_frame_rate || cam_params_.ext_trigger_mode) ?
00977           (INT) 2000 : (INT) (1000.0 / cam_params_.frame_rate * 2);
00978       if (processNextFrame(eventTimeout) != NULL) {
00979         // Process new frame
00980 #ifdef DEBUG_PRINTOUT_FRAME_GRAB_RATES
00981         grabbedFrameCount++;
00982         currGrabbedFrame = ros::Time::now();
00983         if (grabbedFrameCount > 1) {
00984           grabbedFrameSum += (currGrabbedFrame - prevGrabbedFrame).toSec() * 1000.0;
00985           grabbedFrameSumSqrd += ((currGrabbedFrame - prevGrabbedFrame).toSec() * 1000.0)*((currGrabbedFrame - prevGrabbedFrame).toSec() * 1000.0);
00986         }
00987         prevGrabbedFrame = currGrabbedFrame;
00988 
00989         if (grabbedFrameCount > 1) {
00990           ROS_WARN_STREAM("\nPre-Grab: " << startGrabSum/startGrabCount << " +/- " <<
00991               sqrt(startGrabSumSqrd/startGrabCount - (startGrabSum/startGrabCount)*(startGrabSum/startGrabCount)) << " ms (" <<
00992               1000.0*startGrabCount/startGrabSum << "Hz)\n" <<
00993               "Post-Grab: " << grabbedFrameSum/grabbedFrameCount << " +/- " <<
00994               sqrt(grabbedFrameSumSqrd/grabbedFrameCount - (grabbedFrameSum/grabbedFrameCount)*(grabbedFrameSum/grabbedFrameCount)) << " ms (" <<
00995               1000.0*grabbedFrameCount/grabbedFrameSum << "Hz)\n" <<
00996               "Target: " << cam_params_.frame_rate << "Hz");
00997         }
00998 #endif
00999 
01000         if (!frame_grab_alive_ || !ros::ok()) break;
01001         
01002         ros_cam_info_.width = cam_params_.image_width / cam_sensor_scaling_rate_ / cam_subsampling_rate_ / cam_binning_rate_;
01003         ros_cam_info_.height = cam_params_.image_height / cam_sensor_scaling_rate_ / cam_subsampling_rate_ / cam_binning_rate_;
01004 
01005         // Check if content is contiguous
01006         unsigned int expected_row_stride = ros_cam_info_.width * bits_per_pixel_ / 8;
01007         if (expected_row_stride < cam_buffer_pitch_) {
01008           NODELET_ERROR_STREAM("Camera buffer pitch (" << cam_buffer_pitch_ << ") is smaller than expected: " <<
01009             "width (" << ros_cam_info_.width << ") * bytes per pixel (" << bits_per_pixel_/8 << ")");
01010           continue;
01011         } else if (expected_row_stride == cam_buffer_pitch_) {
01012           // Content is contiguous, so copy out the entire buffer
01013           copy((char*) cam_buffer_,
01014             ((char*) cam_buffer_) + cam_buffer_size_,
01015             ros_image_.data.begin());
01016         } else {
01017           // Each row contains extra content according to cam_buffer_pitch_, so must copy out each row independently
01018           std::vector<unsigned char>::iterator ros_image_it = ros_image_.data.begin();
01019           char* cam_buffer_ptr = cam_buffer_;
01020           for (int row = 0; row < ros_cam_info_.height; row++) {
01021             ros_image_it = copy(cam_buffer_ptr, cam_buffer_ptr + expected_row_stride, ros_image_it);
01022             cam_buffer_ptr += expected_row_stride;
01023           }
01024           ros_image_.step = expected_row_stride; // fix the row stepsize/stride value
01025         }
01026         ros_image_.header.stamp = ros_cam_info_.header.stamp = ros::Time::now();
01027         ros_image_.header.seq = ros_cam_info_.header.seq = ros_frame_count_++;
01028         ros_image_.header.frame_id = ros_cam_info_.header.frame_id;
01029 
01030         if (!frame_grab_alive_ || !ros::ok()) break;
01031         ros_cam_pub_.publish(ros_image_, ros_cam_info_);
01032       }
01033     }
01034 
01035     if (!frame_grab_alive_ || !ros::ok()) break;
01036     idleDelay.sleep();
01037   }
01038 
01039   setStandbyMode();
01040   frame_grab_alive_ = false;
01041 };
01042 
01043 
01044 void UEyeCamNodelet::startFrameGrabber() {
01045   frame_grab_alive_ = true;
01046   frame_grab_thread_ = thread(bind(&UEyeCamNodelet::frameGrabLoop, this));
01047 };
01048 
01049 
01050 void UEyeCamNodelet::stopFrameGrabber() {
01051   frame_grab_alive_ = false;
01052   if (frame_grab_thread_.joinable()) {
01053     frame_grab_thread_.join();
01054   }
01055   frame_grab_thread_ = thread();
01056 };
01057 
01058 
01059 void UEyeCamNodelet::loadIntrinsicsFile() {
01060   if (cam_intr_filename_.length() <= 0) { // Use default filename
01061     cam_intr_filename_ = string(getenv("HOME")) + "/.ros/camera_info/" + cam_name_ + ".yaml";
01062   }
01063 
01064   if (camera_calibration_parsers::readCalibration(cam_intr_filename_, cam_name_, ros_cam_info_)) {
01065     NODELET_DEBUG_STREAM("Loaded intrinsics parameters for UEye camera " << cam_name_);
01066   }
01067   ros_cam_info_.header.frame_id = "/" + frame_name_;
01068 };
01069 
01070 
01071 bool UEyeCamNodelet::saveIntrinsicsFile() {
01072   if (camera_calibration_parsers::writeCalibration(cam_intr_filename_, cam_name_, ros_cam_info_)) {
01073     NODELET_DEBUG_STREAM("Saved intrinsics parameters for UEye camera " << cam_name_ <<
01074         " to " << cam_intr_filename_);
01075     return true;
01076   }
01077   return false;
01078 };
01079 // TODO: 0 bug where nodelet locks and requires SIGTERM when there are still subscribers (need to find where does code hang)
01080 
01081 }; // namespace ueye_cam
01082 
01083 
01084 // TODO: 9 bug: when binning (and suspect when subsampling / sensor scaling), white balance / color gains seem to have different effects
01085 
01086 
01087 #include <pluginlib/class_list_macros.h>
01088 PLUGINLIB_DECLARE_CLASS(ueye_cam, ueye_cam_nodelet, ueye_cam::UEyeCamNodelet, nodelet::Nodelet)


ueye_cam
Author(s): Anqi Xu
autogenerated on Mon Oct 6 2014 08:20:41