base_nodelet.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  Copyright (c) 2017, Intel Corporation
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without
00006  modification, are permitted provided that the following conditions are met:
00007 
00008  1. Redistributions of source code must retain the above copyright notice, this
00009  list of conditions and the following disclaimer.
00010 
00011  2. Redistributions in binary form must reproduce the above copyright notice,
00012  this list of conditions and the following disclaimer in the documentation
00013  and/or other materials provided with the distribution.
00014 
00015  3. Neither the name of the copyright holder nor the names of its contributors
00016  may be used to endorse or promote products derived from this software without
00017  specific prior written permission.
00018 
00019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00023  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00025  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *******************************************************************************/
00030 
00031 #include <string>
00032 #include <algorithm>
00033 #include <vector>
00034 #include <map>
00035 #include <realsense_camera/base_nodelet.h>
00036 
00037 using cv::Mat;
00038 using cv::Scalar;
00039 using std::string;
00040 using std::vector;
00041 
00042 PLUGINLIB_EXPORT_CLASS(realsense_camera::BaseNodelet, nodelet::Nodelet)
00043 namespace realsense_camera
00044 {
00045   const std::map<std::string, std::string> CAMERA_NAME_TO_VALIDATED_FIRMWARE
00046         (MAP_START_VALUES, MAP_START_VALUES + MAP_START_VALUES_SIZE);
00047   /*
00048    * Nodelet Destructor.
00049    */
00050   BaseNodelet::~BaseNodelet()
00051   {
00052     try
00053     {
00054       if (enable_tf_ == true && enable_tf_dynamic_ == true)
00055       {
00056         transform_thread_->join();
00057       }
00058 
00059       stopCamera();
00060 
00061       if (rs_context_)
00062       {
00063         rs_delete_context(rs_context_, &rs_error_);
00064         rs_context_ = NULL;
00065         checkError();
00066       }
00067 
00068       // Kill all old system progress groups
00069       while (!system_proc_groups_.empty())
00070       {
00071         killpg(system_proc_groups_.front(), SIGHUP);
00072         system_proc_groups_.pop();
00073       }
00074 
00075       ROS_INFO_STREAM(nodelet_name_ << " - Stopping...");
00076       if (!ros::isShuttingDown())
00077       {
00078         ros::shutdown();
00079       }
00080     }
00081     catch(const std::exception& ex)
00082     {
00083         ROS_ERROR_STREAM(ex.what());
00084     }
00085     catch(...)
00086     {
00087         ROS_ERROR_STREAM("Unknown exception has occured!");
00088     }
00089   }
00090 
00091   /*
00092    * Initialize the nodelet.
00093    */
00094   void BaseNodelet::onInit() try
00095   {
00096     getParameters();
00097 
00098     if (enable_[RS_STREAM_DEPTH] == false && enable_[RS_STREAM_COLOR] == false)
00099     {
00100       ROS_ERROR_STREAM(nodelet_name_ << " - None of the streams are enabled. Exiting!");
00101       ros::shutdown();
00102     }
00103 
00104     while (false == connectToCamera())  // Poll for camera and connect if found
00105     {
00106       ROS_INFO_STREAM(nodelet_name_ << " - Sleeping 5 seconds then retrying to connect");
00107       ros::Duration(5).sleep();
00108     }
00109 
00110     advertiseTopics();
00111     advertiseServices();
00112     std::vector<std::string> dynamic_params = setDynamicReconfServer();
00113     getCameraOptions();
00114     setStaticCameraOptions(dynamic_params);
00115     setStreams();
00116     startCamera();
00117 
00118     // Start transforms thread
00119     if (enable_tf_ == true)
00120     {
00121       getCameraExtrinsics();
00122 
00123       if (enable_tf_dynamic_ == true)
00124       {
00125         transform_thread_ =
00126           boost::shared_ptr<boost::thread>(new boost::thread (boost::bind(&BaseNodelet::prepareTransforms, this)));
00127       }
00128       else
00129       {
00130         publishStaticTransforms();
00131       }
00132     }
00133 
00134     // Start dynamic reconfigure callback
00135     startDynamicReconfCallback();
00136   }
00137   catch(const rs::error & e)
00138   {
00139     ROS_ERROR_STREAM(nodelet_name_ << " - " << "RealSense error calling "
00140         << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    "
00141         << e.what());
00142     ros::shutdown();
00143   }
00144   catch(const std::exception & e)
00145   {
00146     ROS_ERROR_STREAM(nodelet_name_ << " - " << e.what());
00147     ros::shutdown();
00148   }
00149   catch(...)
00150   {
00151     ROS_ERROR_STREAM(nodelet_name_ << " - Caught unknown exception...shutting down!");
00152     ros::shutdown();
00153   }
00154 
00155   /*
00156    * Get the nodelet parameters.
00157    */
00158   void BaseNodelet::getParameters()
00159   {
00160     nodelet_name_ = getName();
00161     nh_ = getNodeHandle();
00162     pnh_ = getPrivateNodeHandle();
00163     pnh_.getParam("serial_no", serial_no_);
00164     pnh_.getParam("usb_port_id", usb_port_id_);
00165     pnh_.getParam("camera_type", camera_type_);
00166     pnh_.param("mode", mode_, DEFAULT_MODE);
00167     pnh_.param("enable_depth", enable_[RS_STREAM_DEPTH], ENABLE_DEPTH);
00168     pnh_.param("enable_color", enable_[RS_STREAM_COLOR], ENABLE_COLOR);
00169     pnh_.param("enable_ir", enable_[RS_STREAM_INFRARED], ENABLE_IR);
00170     pnh_.param("enable_pointcloud", enable_pointcloud_, ENABLE_PC);
00171     pnh_.param("enable_tf", enable_tf_, ENABLE_TF);
00172     pnh_.param("enable_tf_dynamic", enable_tf_dynamic_, ENABLE_TF_DYNAMIC);
00173     pnh_.param("tf_publication_rate", tf_publication_rate_, TF_PUBLICATION_RATE);
00174     pnh_.param("depth_width", width_[RS_STREAM_DEPTH], DEPTH_WIDTH);
00175     pnh_.param("depth_height", height_[RS_STREAM_DEPTH], DEPTH_HEIGHT);
00176     pnh_.param("color_width", width_[RS_STREAM_COLOR], COLOR_WIDTH);
00177     pnh_.param("color_height", height_[RS_STREAM_COLOR], COLOR_HEIGHT);
00178     pnh_.param("depth_fps", fps_[RS_STREAM_DEPTH], DEPTH_FPS);
00179     pnh_.param("color_fps", fps_[RS_STREAM_COLOR], COLOR_FPS);
00180     pnh_.param("base_frame_id", base_frame_id_, DEFAULT_BASE_FRAME_ID);
00181     pnh_.param("depth_frame_id", frame_id_[RS_STREAM_DEPTH], DEFAULT_DEPTH_FRAME_ID);
00182     pnh_.param("color_frame_id", frame_id_[RS_STREAM_COLOR], DEFAULT_COLOR_FRAME_ID);
00183     pnh_.param("ir_frame_id", frame_id_[RS_STREAM_INFRARED], DEFAULT_IR_FRAME_ID);
00184     pnh_.param("depth_optical_frame_id", optical_frame_id_[RS_STREAM_DEPTH], DEFAULT_DEPTH_OPTICAL_FRAME_ID);
00185     pnh_.param("color_optical_frame_id", optical_frame_id_[RS_STREAM_COLOR], DEFAULT_COLOR_OPTICAL_FRAME_ID);
00186     pnh_.param("ir_optical_frame_id", optical_frame_id_[RS_STREAM_INFRARED], DEFAULT_IR_OPTICAL_FRAME_ID);
00187 
00188     // set IR stream to match depth
00189     width_[RS_STREAM_INFRARED] = width_[RS_STREAM_DEPTH];
00190     height_[RS_STREAM_INFRARED] = height_[RS_STREAM_DEPTH];
00191     fps_[RS_STREAM_INFRARED] = fps_[RS_STREAM_DEPTH];
00192   }
00193 
00194   /*
00195    * Connect to camera.
00196    */
00197   bool BaseNodelet::connectToCamera()
00198   {
00199     rs_context_ = rs_create_context(RS_API_VERSION, &rs_error_);
00200     if (rs_error_)
00201     {
00202       ROS_ERROR_STREAM(nodelet_name_ << " - No cameras detected!");
00203     }
00204     checkError();
00205 
00206     int num_of_cameras = rs_get_device_count(rs_context_, &rs_error_);
00207     checkError();
00208 
00209     // Exit with error if no cameras are connected.
00210     if (num_of_cameras < 1)
00211     {
00212       ROS_ERROR_STREAM(nodelet_name_ << " - No cameras detected!");
00213       rs_delete_context(rs_context_, &rs_error_);
00214       rs_context_ = NULL;
00215       checkError();
00216       return false;
00217     }
00218 
00219     // Print list of all cameras found
00220     std::vector<int> camera_type_index = listCameras(num_of_cameras);
00221 
00222     // Exit with error if no cameras of correct type are connected.
00223     if (camera_type_index.size() < 1)
00224     {
00225       ROS_ERROR_STREAM(nodelet_name_ << " - No '" << camera_type_ << "' cameras detected!");
00226       rs_delete_context(rs_context_, &rs_error_);
00227       rs_context_ = NULL;
00228       checkError();
00229       return false;
00230     }
00231 
00232     // Exit with error if no serial_no or usb_port_id is specified and multiple cameras are detected.
00233     if (serial_no_.empty() && usb_port_id_.empty() && camera_type_index.size() > 1)
00234     {
00235       ROS_ERROR_STREAM(nodelet_name_ <<
00236           " - Multiple cameras of same type detected but no input serial_no or usb_port_id specified");
00237       rs_delete_context(rs_context_, &rs_error_);
00238       rs_context_ = NULL;
00239       checkError();
00240       return false;
00241     }
00242 
00243     // init rs_device_ before starting loop
00244     rs_device_ = nullptr;
00245 
00246     // find camera
00247     for (int i : camera_type_index)
00248     {
00249       rs_device* rs_detected_device = rs_get_device(rs_context_, i, &rs_error_);
00250       checkError();
00251 
00252       // check serial_no and usb_port_id
00253       if ((serial_no_.empty() || serial_no_ == rs_get_device_serial(rs_detected_device, &rs_error_)) &&
00254           (usb_port_id_.empty() || usb_port_id_ == rs_get_device_usb_port_id(rs_detected_device, &rs_error_)))
00255       {
00256         // device found
00257         rs_device_ = rs_detected_device;
00258         break;
00259       }
00260       // continue loop
00261     }
00262 
00263     if (rs_device_ == nullptr)
00264     {
00265       // camera not found
00266       string error_msg = " - Couldn't find camera to connect with ";
00267       error_msg += "serial_no = " + serial_no_ + ", ";
00268       error_msg += "usb_port_id = " + usb_port_id_;
00269 
00270       ROS_ERROR_STREAM(nodelet_name_ << error_msg);
00271 
00272       rs_delete_context(rs_context_, &rs_error_);
00273       rs_context_ = NULL;
00274       checkError();
00275       return false;
00276     }
00277 
00278     // print device info
00279     ROS_INFO_STREAM(nodelet_name_ << " - Connecting to camera with Serial No: " <<
00280         rs_get_device_serial(rs_device_, &rs_error_) <<
00281         ", USB Port ID: " << rs_get_device_usb_port_id(rs_device_, &rs_error_));
00282     checkError();
00283     return true;
00284   }
00285 
00286   /*
00287    * List details of the detected cameras.
00288    */
00289   std::vector<int> BaseNodelet::listCameras(int num_of_cameras)
00290   {
00291     // print list of detected cameras
00292     std::vector<int> camera_type_index;
00293 
00294     for (int i = 0; i < num_of_cameras; i++)
00295     {
00296       std::string detected_camera_msg = " - Detected the following camera:";
00297       std::string warning_msg = " - Detected unvalidated firmware:";
00298       // get device
00299       rs_device* rs_detected_device = rs_get_device(rs_context_, i, &rs_error_);
00300 
00301       // get camera serial number
00302       std::string camera_serial_number = rs_get_device_serial(rs_detected_device, &rs_error_);
00303       checkError();
00304 
00305       // get camera name
00306       std::string camera_name = rs_get_device_name(rs_detected_device, &rs_error_);
00307       checkError();
00308 
00309       // get camera firmware
00310       std::string camera_fw = rs_get_device_firmware_version(rs_detected_device, &rs_error_);
00311       checkError();
00312 
00313       if (camera_name.find(camera_type_) != std::string::npos)
00314       {
00315         camera_type_index.push_back(i);
00316       }
00317       // print camera details
00318       detected_camera_msg = detected_camera_msg +
00319             "\n\t\t\t\t- Serial No: " + camera_serial_number + ", USB Port ID: " +
00320             rs_get_device_usb_port_id(rs_detected_device, &rs_error_) +
00321             ", Name: " + camera_name +
00322             ", Camera FW: " + camera_fw;
00323       checkError();
00324 
00325       std::string camera_warning_msg = checkFirmwareValidation("camera", camera_fw, camera_name, camera_serial_number);
00326 
00327       if (!camera_warning_msg.empty())
00328       {
00329         warning_msg = warning_msg + "\n\t\t\t\t- " + camera_warning_msg;
00330       }
00331 
00332       if (rs_supports(rs_detected_device, RS_CAPABILITIES_ADAPTER_BOARD, &rs_error_))
00333       {
00334         const char * adapter_fw = rs_get_device_info(rs_detected_device,
00335             RS_CAMERA_INFO_ADAPTER_BOARD_FIRMWARE_VERSION, &rs_error_);
00336         checkError();
00337         detected_camera_msg = detected_camera_msg + ", Adapter FW: " + adapter_fw;
00338         std::string adapter_warning_msg = checkFirmwareValidation("adapter", adapter_fw, camera_name,
00339               camera_serial_number);
00340         if (!adapter_warning_msg.empty())
00341         {
00342           warning_msg = warning_msg + "\n\t\t\t\t- " + adapter_warning_msg;
00343         }
00344       }
00345 
00346       if (rs_supports(rs_detected_device, RS_CAPABILITIES_MOTION_EVENTS, &rs_error_))
00347       {
00348         const char * motion_module_fw = rs_get_device_info(rs_detected_device,
00349             RS_CAMERA_INFO_MOTION_MODULE_FIRMWARE_VERSION, &rs_error_);
00350         checkError();
00351         detected_camera_msg = detected_camera_msg + ", Motion Module FW: " + motion_module_fw;
00352         std::string motion_module_warning_msg = checkFirmwareValidation("motion_module", motion_module_fw, camera_name,
00353               camera_serial_number);
00354         if (!motion_module_warning_msg.empty())
00355         {
00356           warning_msg = warning_msg + "\n\t\t\t\t- " + motion_module_warning_msg;
00357         }
00358       }
00359       ROS_INFO_STREAM(nodelet_name_ + detected_camera_msg);
00360       if (warning_msg != " - Detected unvalidated firmware:")
00361       {
00362         ROS_WARN_STREAM(nodelet_name_ + warning_msg);
00363       }
00364     }
00365 
00366     return camera_type_index;
00367   }
00368 
00369   /*
00370    * Advertise topics.
00371    */
00372   void BaseNodelet::advertiseTopics()
00373   {
00374     ros::NodeHandle color_nh(nh_, COLOR_NAMESPACE);
00375     image_transport::ImageTransport color_image_transport(color_nh);
00376     camera_publisher_[RS_STREAM_COLOR] = color_image_transport.advertiseCamera(COLOR_TOPIC, 1);
00377 
00378     ros::NodeHandle depth_nh(nh_, DEPTH_NAMESPACE);
00379     image_transport::ImageTransport depth_image_transport(depth_nh);
00380     camera_publisher_[RS_STREAM_DEPTH] = depth_image_transport.advertiseCamera(DEPTH_TOPIC, 1);
00381     pointcloud_publisher_ = depth_nh.advertise<sensor_msgs::PointCloud2>(PC_TOPIC, 1);
00382 
00383     ros::NodeHandle ir_nh(nh_, IR_NAMESPACE);
00384     image_transport::ImageTransport ir_image_transport(ir_nh);
00385     camera_publisher_[RS_STREAM_INFRARED] = ir_image_transport.advertiseCamera(IR_TOPIC, 1);
00386   }
00387 
00388   /*
00389    * Advertise services.
00390    */
00391   void BaseNodelet::advertiseServices()
00392   {
00393     get_options_service_ = pnh_.advertiseService(SETTINGS_SERVICE,
00394         &BaseNodelet::getCameraOptionValues, this);
00395     set_power_service_ = pnh_.advertiseService(CAMERA_SET_POWER_SERVICE,
00396         &BaseNodelet::setPowerCameraService, this);
00397     force_power_service_ = pnh_.advertiseService(CAMERA_FORCE_POWER_SERVICE,
00398         &BaseNodelet::forcePowerCameraService, this);
00399     is_powered_service_ = pnh_.advertiseService(CAMERA_IS_POWERED_SERVICE,
00400         &BaseNodelet::isPoweredCameraService, this);
00401   }
00402 
00403   /*
00404    * Get the latest values of the camera options.
00405    */
00406   bool BaseNodelet::getCameraOptionValues(realsense_camera::CameraConfiguration::Request & req,
00407       realsense_camera::CameraConfiguration::Response & res)
00408   {
00409     std::string get_options_result_str;
00410     std::string opt_name, opt_value;
00411 
00412     for (CameraOptions o : camera_options_)
00413     {
00414       opt_name = rs_option_to_string(o.opt);
00415       std::transform(opt_name.begin(), opt_name.end(), opt_name.begin(), ::tolower);
00416       o.value = rs_get_device_option(rs_device_, o.opt, 0);
00417       opt_value = boost::lexical_cast<std::string>(o.value);
00418       get_options_result_str += opt_name + ":" + opt_value + ";";
00419     }
00420 
00421     res.configuration_str = get_options_result_str;
00422     return true;
00423   }
00424 
00425   /*
00426    * Check for Nodelet subscribers
00427    */
00428   bool BaseNodelet::checkForSubscriber()
00429   {
00430     for (int index=0; index < STREAM_COUNT; index++)
00431     {
00432       if (camera_publisher_[index].getNumSubscribers() > 0)
00433       {
00434         return true;
00435       }
00436     }
00437     if (pointcloud_publisher_.getNumSubscribers() > 0)
00438     {
00439         return true;
00440     }
00441     return false;
00442   }
00443 
00444   /*
00445    * Service to check if camera is powered on or not
00446    */
00447   bool BaseNodelet::isPoweredCameraService(realsense_camera::IsPowered::Request & req,
00448       realsense_camera::IsPowered::Response & res)
00449   {
00450       if (rs_is_device_streaming(rs_device_, 0) == 1)
00451       {
00452         res.is_powered = true;
00453       }
00454       else
00455       {
00456         res.is_powered = false;
00457       }
00458       return true;
00459   }
00460 
00461   /*
00462    * Set Power Camera service
00463    */
00464   bool BaseNodelet::setPowerCameraService(realsense_camera::SetPower::Request & req,
00465       realsense_camera::SetPower::Response & res)
00466   {
00467     res.success = true;
00468 
00469     if (req.power_on == true)
00470     {
00471       start_camera_ = true;
00472       start_stop_srv_called_ = true;
00473     }
00474     else
00475     {
00476       if (rs_is_device_streaming(rs_device_, 0) == 0)
00477       {
00478         ROS_INFO_STREAM(nodelet_name_ << " - Camera is already Stopped");
00479       }
00480       else
00481       {
00482         if (checkForSubscriber() == false)
00483         {
00484           start_camera_ = false;
00485           start_stop_srv_called_ = true;
00486         }
00487         else
00488         {
00489           ROS_INFO_STREAM(nodelet_name_ << " - Cannot stop the camera. Nodelet has subscriber.");
00490           res.success = false;
00491         }
00492       }
00493     }
00494     return res.success;
00495 }
00496 
00497   /*
00498    * Force Power Camera service
00499    */
00500   bool BaseNodelet::forcePowerCameraService(realsense_camera::ForcePower::Request & req,
00501       realsense_camera::ForcePower::Response & res)
00502   {
00503     start_camera_ = req.power_on;
00504     start_stop_srv_called_ = true;
00505     return true;
00506   }
00507 
00508 
00509   /*
00510    * Get the options supported by the camera along with their min, max and step values.
00511    */
00512   void BaseNodelet::getCameraOptions()
00513   {
00514     for (int i = 0; i < RS_OPTION_COUNT; ++i)
00515     {
00516       CameraOptions o = { (rs_option) i };
00517 
00518       if (rs_device_supports_option(rs_device_, o.opt, &rs_error_))
00519       {
00520         rs_get_device_option_range(rs_device_, o.opt, &o.min, &o.max, &o.step, 0);
00521 
00522         // Skip the camera options where min and max values are the same.
00523         if (o.min != o.max)
00524         {
00525           o.value = rs_get_device_option(rs_device_, o.opt, 0);
00526           camera_options_.push_back(o);
00527         }
00528       }
00529     }
00530   }
00531 
00532   /*
00533    * Set the static camera options.
00534    */
00535   void BaseNodelet::setStaticCameraOptions(std::vector<std::string> dynamic_params)
00536   {
00537     ROS_INFO_STREAM(nodelet_name_ << " - Setting static camera options");
00538 
00539     // Iterate through the supported camera options
00540     for (CameraOptions o : camera_options_)
00541     {
00542       std::string opt_name = rs_option_to_string(o.opt);
00543       bool found = false;
00544 
00545       for (std::string param_name : dynamic_params)
00546       {
00547         std::transform(opt_name.begin(), opt_name.end(), opt_name.begin(), ::tolower);
00548         if (opt_name.compare(param_name) == 0)
00549         {
00550           found = true;
00551           break;
00552         }
00553       }
00554       // Skip the dynamic options and set only the static camera options.
00555       if (found == false)
00556       {
00557         std::string key;
00558         double val;
00559 
00560         if (pnh_.searchParam(opt_name, key))
00561         {
00562           double opt_val;
00563           pnh_.getParam(key, val);
00564 
00565           // Validate and set the input values within the min-max range
00566           if (val < o.min)
00567           {
00568             opt_val = o.min;
00569           }
00570           else if (val > o.max)
00571           {
00572             opt_val = o.max;
00573           }
00574           else
00575           {
00576             opt_val = val;
00577           }
00578           ROS_INFO_STREAM(nodelet_name_ << " - Setting camera option " << opt_name << " = " << opt_val);
00579           rs_set_device_option(rs_device_, o.opt, opt_val, &rs_error_);
00580           checkError();
00581         }
00582       }
00583     }
00584   }
00585 
00586   /*
00587   * Set up the callbacks for the camera streams
00588   */
00589   void BaseNodelet::setFrameCallbacks()
00590   {
00591     depth_frame_handler_ = [&](rs::frame frame)  // NOLINT(build/c++11)
00592     {
00593       publishTopic(RS_STREAM_DEPTH, frame);
00594 
00595       if (enable_pointcloud_ == true)
00596       {
00597         publishPCTopic();
00598       }
00599     };
00600 
00601     color_frame_handler_ = [&](rs::frame frame)  // NOLINT(build/c++11)
00602     {
00603       publishTopic(RS_STREAM_COLOR, frame);
00604     };
00605 
00606     ir_frame_handler_ = [&](rs::frame frame)  // NOLINT(build/c++11)
00607     {
00608       publishTopic(RS_STREAM_INFRARED, frame);
00609     };
00610 
00611     rs_set_frame_callback_cpp(rs_device_, RS_STREAM_DEPTH, new rs::frame_callback(depth_frame_handler_), &rs_error_);
00612     checkError();
00613 
00614     rs_set_frame_callback_cpp(rs_device_, RS_STREAM_COLOR, new rs::frame_callback(color_frame_handler_), &rs_error_);
00615     checkError();
00616 
00617     // Need to add this check due to a bug in librealsense which calls the IR callback
00618     // if INFRARED stream is disable AND INFRARED2 stream is enabled
00619     // https://github.com/IntelRealSense/librealsense/issues/393
00620     if (enable_[RS_STREAM_INFRARED])
00621     {
00622       rs_set_frame_callback_cpp(rs_device_, RS_STREAM_INFRARED, new rs::frame_callback(ir_frame_handler_), &rs_error_);
00623       checkError();
00624     }
00625   }
00626 
00627   /*
00628    * Set the streams according to their corresponding flag values.
00629    */
00630   void BaseNodelet::setStreams()
00631   {
00632     // Enable streams
00633     for (int stream=0; stream < STREAM_COUNT; stream++)
00634     {
00635       if (enable_[stream] == true)
00636       {
00637         enableStream(static_cast<rs_stream>(stream), width_[stream], height_[stream], format_[stream], fps_[stream]);
00638       }
00639       else if (enable_[stream] == false)
00640       {
00641         disableStream(static_cast<rs_stream>(stream));
00642       }
00643     }
00644   }
00645 
00646   /*
00647    * Enable individual streams.
00648    */
00649   void BaseNodelet::enableStream(rs_stream stream_index, int width, int height, rs_format format, int fps)
00650   {
00651     if (rs_is_stream_enabled(rs_device_, stream_index, 0) == 0)
00652     {
00653       if (mode_.compare("manual") == 0)
00654       {
00655         ROS_INFO_STREAM(nodelet_name_ << " - Enabling " << STREAM_DESC[stream_index] << " in manual mode");
00656         rs_enable_stream(rs_device_, stream_index, width, height, format, fps, &rs_error_);
00657         checkError();
00658       }
00659       else
00660       {
00661         ROS_INFO_STREAM(nodelet_name_ << " - Enabling " << STREAM_DESC[stream_index] << " in preset mode");
00662         rs_enable_stream_preset(rs_device_, stream_index, RS_PRESET_BEST_QUALITY, &rs_error_);
00663         checkError();
00664       }
00665     }
00666     if (camera_info_ptr_[stream_index] == NULL)
00667     {
00668       // Allocate image resources
00669       getStreamCalibData(stream_index);
00670       step_[stream_index] = camera_info_ptr_[stream_index]->width * unit_step_size_[stream_index];
00671       image_[stream_index] = cv::Mat(camera_info_ptr_[stream_index]->height,
00672           camera_info_ptr_[stream_index]->width, cv_type_[stream_index], cv::Scalar(0, 0, 0));
00673     }
00674     ts_[stream_index] = -1;
00675   }
00676 
00677   /*
00678    * Prepare camera_info for each enabled stream.
00679    */
00680   void BaseNodelet::getStreamCalibData(rs_stream stream_index)
00681   {
00682     rs_intrinsics intrinsic;
00683 
00684     if (stream_index == RS_STREAM_COLOR)
00685     {
00686       rs_get_stream_intrinsics(rs_device_, RS_STREAM_RECTIFIED_COLOR, &intrinsic, &rs_error_);
00687     }
00688     else
00689     {
00690       rs_get_stream_intrinsics(rs_device_, stream_index, &intrinsic, &rs_error_);
00691     }
00692 
00693     if (rs_error_)
00694     {
00695       ROS_ERROR_STREAM(nodelet_name_ << " - Verify camera firmware version and/or calibration data!");
00696     }
00697     checkError();
00698 
00699     sensor_msgs::CameraInfo * camera_info = new sensor_msgs::CameraInfo();
00700     camera_info_ptr_[stream_index] = sensor_msgs::CameraInfoPtr(camera_info);
00701 
00702     camera_info->header.frame_id = optical_frame_id_[stream_index];
00703     camera_info->width = intrinsic.width;
00704     camera_info->height = intrinsic.height;
00705 
00706     camera_info->K.at(0) = intrinsic.fx;
00707     camera_info->K.at(2) = intrinsic.ppx;
00708     camera_info->K.at(4) = intrinsic.fy;
00709     camera_info->K.at(5) = intrinsic.ppy;
00710     camera_info->K.at(8) = 1;
00711 
00712     camera_info->P.at(0) = camera_info->K.at(0);
00713     camera_info->P.at(1) = 0;
00714     camera_info->P.at(2) = camera_info->K.at(2);
00715     camera_info->P.at(3) = 0;
00716 
00717     camera_info->P.at(4) = 0;
00718     camera_info->P.at(5) = camera_info->K.at(4);
00719     camera_info->P.at(6) = camera_info->K.at(5);
00720     camera_info->P.at(7) = 0;
00721 
00722     camera_info->P.at(8) = 0;
00723     camera_info->P.at(9) = 0;
00724     camera_info->P.at(10) = 1;
00725     camera_info->P.at(11) = 0;
00726 
00727     if (stream_index == RS_STREAM_DEPTH)
00728     {
00729       // set depth to color translation values in Projection matrix (P)
00730       rs_extrinsics z_extrinsic;
00731       rs_get_device_extrinsics(rs_device_, RS_STREAM_DEPTH, RS_STREAM_COLOR, &z_extrinsic, &rs_error_);
00732       if (rs_error_)
00733       {
00734         ROS_ERROR_STREAM(nodelet_name_ << " - Verify camera is calibrated!");
00735       }
00736       checkError();
00737       camera_info->P.at(3) = z_extrinsic.translation[0];     // Tx
00738       camera_info->P.at(7) = z_extrinsic.translation[1];     // Ty
00739       camera_info->P.at(11) = z_extrinsic.translation[2];    // Tz
00740     }
00741 
00742     camera_info->distortion_model = "plumb_bob";
00743 
00744     // set R (rotation matrix) values to identity matrix
00745     camera_info->R.at(0) = 1.0;
00746     camera_info->R.at(1) = 0.0;
00747     camera_info->R.at(2) = 0.0;
00748     camera_info->R.at(3) = 0.0;
00749     camera_info->R.at(4) = 1.0;
00750     camera_info->R.at(5) = 0.0;
00751     camera_info->R.at(6) = 0.0;
00752     camera_info->R.at(7) = 0.0;
00753     camera_info->R.at(8) = 1.0;
00754 
00755     for (int i = 0; i < 5; i++)
00756     {
00757       camera_info->D.push_back(intrinsic.coeffs[i]);
00758     }
00759   }
00760 
00761   /*
00762    * Disable individual streams.
00763    */
00764   void BaseNodelet::disableStream(rs_stream stream_index)
00765   {
00766     if (rs_is_stream_enabled(rs_device_, stream_index, 0) == 1)
00767     {
00768       ROS_INFO_STREAM(nodelet_name_ << " - Disabling " << STREAM_DESC[stream_index] << " stream");
00769       rs_disable_stream(rs_device_, stream_index, &rs_error_);
00770       checkError();
00771     }
00772   }
00773 
00774   /*
00775    * Start camera.
00776    */
00777   std::string BaseNodelet::startCamera()
00778   {
00779     if (rs_is_device_streaming(rs_device_, 0) == 0)
00780     {
00781       ROS_INFO_STREAM(nodelet_name_ << " - Starting camera");
00782       // Set up the callbacks for each stream
00783       setFrameCallbacks();
00784       try
00785       {
00786         rs_device_->start(rs_source_);
00787       }
00788       catch (std::runtime_error & e)
00789       {
00790         ROS_ERROR_STREAM(nodelet_name_ << " - Couldn't start camera -- " << e.what());
00791         ros::shutdown();
00792       }
00793       camera_start_ts_ = ros::Time::now();
00794       return "Camera Started Successfully";
00795     }
00796     return "Camera is already Started";
00797   }
00798 
00799   /*
00800    * Stop camera.
00801    */
00802   std::string BaseNodelet::stopCamera()
00803   {
00804     if (rs_is_device_streaming(rs_device_, 0) == 1)
00805     {
00806       ROS_INFO_STREAM(nodelet_name_ << " - Stopping camera");
00807       try
00808       {
00809         rs_device_->stop(rs_source_);
00810       }
00811       catch (std::runtime_error & e)
00812       {
00813         ROS_ERROR_STREAM(nodelet_name_ << " - Couldn't stop camera -- " << e.what());
00814         ros::shutdown();
00815       }
00816       return "Camera Stopped Successfully";
00817     }
00818     return "Camera is already Stopped";
00819   }
00820 
00821 
00822   /*
00823    * Copy frame data from realsense to member cv images.
00824    */
00825   void BaseNodelet::setImageData(rs_stream stream_index, rs::frame & frame)
00826   {
00827     if (stream_index == RS_STREAM_DEPTH)
00828     {
00829       // fill depth buffer
00830       image_depth16_ = reinterpret_cast<const uint16_t *>(frame.get_data());
00831       float depth_scale_meters = rs_get_device_depth_scale(rs_device_, &rs_error_);
00832       if (depth_scale_meters == MILLIMETER_METERS)
00833       {
00834         image_[stream_index].data = (unsigned char *) image_depth16_;
00835       }
00836       else
00837       {
00838         cvWrapper_ = cv::Mat(image_[stream_index].size(), cv_type_[stream_index],
00839             const_cast<void *>(reinterpret_cast<const void *>(image_depth16_)), step_[stream_index]);
00840         cvWrapper_.convertTo(image_[stream_index], cv_type_[stream_index],
00841             static_cast<double>(depth_scale_meters) / static_cast<double>(MILLIMETER_METERS));
00842       }
00843     }
00844     else
00845     {
00846       image_[stream_index].data = (unsigned char *) (frame.get_data());
00847     }
00848   }
00849 
00850   /*
00851    * Set depth enable
00852    */
00853   void BaseNodelet::setDepthEnable(bool &enable_depth)
00854   {
00855     // Set flags
00856     if (enable_depth == false)
00857     {
00858       if (enable_[RS_STREAM_COLOR] == false)
00859       {
00860         ROS_INFO_STREAM(nodelet_name_ << " - Color stream is also disabled. Cannot disable depth stream");
00861         enable_depth = true;
00862       }
00863       else
00864       {
00865         enable_[RS_STREAM_DEPTH] = false;
00866       }
00867     }
00868     else
00869     {
00870       enable_[RS_STREAM_DEPTH] = true;
00871     }
00872   }
00873 
00874   /*
00875    * Determine the timestamp for the publish topic.
00876    */
00877   ros::Time BaseNodelet::getTimestamp(rs_stream stream_index, double frame_ts)
00878   {
00879     return ros::Time(camera_start_ts_) + ros::Duration(frame_ts * 0.001);
00880   }
00881 
00882   /*
00883    * Publish topic.
00884    */
00885   void BaseNodelet::publishTopic(rs_stream stream_index, rs::frame &frame) try
00886   {
00887     // mutex to ensure only one frame per stream is processed at a time
00888     std::unique_lock<std::mutex> lock(frame_mutex_[stream_index]);
00889 
00890     double frame_ts = frame.get_timestamp();
00891     if (ts_[stream_index] != frame_ts)  // Publish frames only if its not duplicate
00892     {
00893       setImageData(stream_index, frame);
00894       // Publish stream only if there is at least one subscriber.
00895       if (camera_publisher_[stream_index].getNumSubscribers() > 0)
00896       {
00897         sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(),
00898                         encoding_[stream_index],
00899                                 image_[stream_index]).toImageMsg();
00900         msg->header.frame_id = optical_frame_id_[stream_index];
00901         // Publish timestamp to synchronize frames.
00902         msg->header.stamp = getTimestamp(stream_index, frame_ts);
00903         msg->width = image_[stream_index].cols;
00904         msg->height = image_[stream_index].rows;
00905         msg->is_bigendian = false;
00906         msg->step = step_[stream_index];
00907         camera_info_ptr_[stream_index]->header.stamp = msg->header.stamp;
00908         camera_publisher_[stream_index].publish(msg, camera_info_ptr_[stream_index]);
00909       }
00910     }
00911     ts_[stream_index] = frame_ts;
00912   }
00913   catch(const rs::error & e)
00914   {
00915     ROS_ERROR_STREAM(nodelet_name_ << " - " << "RealSense error calling "
00916         << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    "
00917         << e.what());
00918     ros::shutdown();
00919   }
00920   catch(const std::exception & e)
00921   {
00922     ROS_ERROR_STREAM(nodelet_name_ << " - " << e.what());
00923     ros::shutdown();
00924   }
00925   catch(...)
00926   {
00927     ROS_ERROR_STREAM(nodelet_name_ << " - Caught unknown exception...shutting down!");
00928     ros::shutdown();
00929   }
00930 
00931   /*
00932    * Publish pointcloud topic.
00933    */
00934   void BaseNodelet::publishPCTopic()
00935   {
00936     cv::Mat & image_color = image_[RS_STREAM_COLOR];
00937     // Publish pointcloud only if there is at least one subscriber.
00938     if (pointcloud_publisher_.getNumSubscribers() > 0 && rs_is_stream_enabled(rs_device_, RS_STREAM_DEPTH, 0) == 1)
00939     {
00940       rs_intrinsics color_intrinsic;
00941       rs_extrinsics z_extrinsic;
00942 
00943       rs_intrinsics z_intrinsic;
00944       rs_get_stream_intrinsics(rs_device_, RS_STREAM_DEPTH, &z_intrinsic, &rs_error_);
00945       checkError();
00946 
00947       if (enable_[RS_STREAM_COLOR] == true)
00948       {
00949         rs_get_stream_intrinsics(rs_device_, RS_STREAM_COLOR, &color_intrinsic, &rs_error_);
00950         checkError();
00951         rs_get_device_extrinsics(rs_device_, RS_STREAM_DEPTH, RS_STREAM_COLOR, &z_extrinsic, &rs_error_);
00952         checkError();
00953       }
00954 
00955       // Convert pointcloud from the camera to pointcloud object for ROS.
00956       sensor_msgs::PointCloud2 msg_pointcloud;
00957       msg_pointcloud.width = width_[RS_STREAM_DEPTH];
00958       msg_pointcloud.height = height_[RS_STREAM_DEPTH];
00959       msg_pointcloud.header.stamp = ros::Time::now();
00960       msg_pointcloud.is_dense = true;
00961 
00962       sensor_msgs::PointCloud2Modifier modifier(msg_pointcloud);
00963 
00964       modifier.setPointCloud2Fields(4, "x", 1,
00965           sensor_msgs::PointField::FLOAT32, "y", 1,
00966           sensor_msgs::PointField::FLOAT32, "z", 1,
00967           sensor_msgs::PointField::FLOAT32, "rgb", 1,
00968           sensor_msgs::PointField::FLOAT32);
00969 
00970       modifier.setPointCloud2FieldsByString(2, "xyz", "rgb");
00971 
00972       sensor_msgs::PointCloud2Iterator<float>iter_x(msg_pointcloud, "x");
00973       sensor_msgs::PointCloud2Iterator<float>iter_y(msg_pointcloud, "y");
00974       sensor_msgs::PointCloud2Iterator<float>iter_z(msg_pointcloud, "z");
00975 
00976       sensor_msgs::PointCloud2Iterator<uint8_t>iter_r(msg_pointcloud, "r");
00977       sensor_msgs::PointCloud2Iterator<uint8_t>iter_g(msg_pointcloud, "g");
00978       sensor_msgs::PointCloud2Iterator<uint8_t>iter_b(msg_pointcloud, "b");
00979 
00980       float depth_point[3], color_point[3], color_pixel[2], scaled_depth;
00981       unsigned char *color_data = image_color.data;
00982       checkError();  // Default value is 0.001
00983 
00984       float depth_scale_meters = rs_get_device_depth_scale(rs_device_, &rs_error_);
00985       // Fill the PointCloud2 fields.
00986       for (int y = 0; y < z_intrinsic.height; y++)
00987       {
00988         for (int x = 0; x < z_intrinsic.width; x++)
00989         {
00990           scaled_depth = static_cast<float>(*image_depth16_) * depth_scale_meters;
00991           float depth_pixel[2] = {static_cast<float>(x), static_cast<float>(y)};
00992           rs_deproject_pixel_to_point(depth_point, &z_intrinsic, depth_pixel, scaled_depth);
00993 
00994           if (depth_point[2] <= 0.0f || depth_point[2] > max_z_)
00995           {
00996             depth_point[0] = 0.0f;
00997             depth_point[1] = 0.0f;
00998             depth_point[2] = 0.0f;
00999           }
01000 
01001           *iter_x = depth_point[0];
01002           *iter_y = depth_point[1];
01003           *iter_z = depth_point[2];
01004 
01005           // Default to white color.
01006           *iter_r = static_cast<uint8_t>(255);
01007           *iter_g = static_cast<uint8_t>(255);
01008           *iter_b = static_cast<uint8_t>(255);
01009 
01010           if (enable_[RS_STREAM_COLOR] == true)
01011           {
01012             rs_transform_point_to_point(color_point, &z_extrinsic, depth_point);
01013             rs_project_point_to_pixel(color_pixel, &color_intrinsic, color_point);
01014 
01015             if (color_pixel[1] < 0.0f || color_pixel[1] >= image_color.rows
01016                 || color_pixel[0] < 0.0f || color_pixel[0] >= image_color.cols)
01017             {
01018               // For out of bounds color data, default to a shade of blue in order to visually distinguish holes.
01019               // This color value is same as the librealsense out of bounds color value.
01020               *iter_r = static_cast<uint8_t>(96);
01021               *iter_g = static_cast<uint8_t>(157);
01022               *iter_b = static_cast<uint8_t>(198);
01023             }
01024             else
01025             {
01026               int i = static_cast<int>(color_pixel[0]);
01027               int j = static_cast<int>(color_pixel[1]);
01028 
01029               *iter_r = static_cast<uint8_t>(color_data[i * 3 + j * image_color.cols * 3]);
01030               *iter_g = static_cast<uint8_t>(color_data[i * 3 + j * image_color.cols * 3 + 1]);
01031               *iter_b = static_cast<uint8_t>(color_data[i * 3 + j * image_color.cols * 3 + 2]);
01032             }
01033           }
01034 
01035           image_depth16_++;
01036           ++iter_x; ++iter_y; ++iter_z; ++iter_r; ++iter_g; ++iter_b;
01037         }
01038       }
01039 
01040       msg_pointcloud.header.frame_id = optical_frame_id_[RS_STREAM_DEPTH];
01041       pointcloud_publisher_.publish(msg_pointcloud);
01042     }
01043   }
01044 
01045   /*
01046    * Get the camera extrinsics
01047    */
01048   void BaseNodelet::getCameraExtrinsics()
01049   {
01050     // Get offset between base frame and depth frame
01051     rs_get_device_extrinsics(rs_device_, RS_STREAM_DEPTH, RS_STREAM_COLOR, &color2depth_extrinsic_, &rs_error_);
01052     if (rs_error_)
01053     {
01054       ROS_ERROR_STREAM(nodelet_name_ << " - Verify camera is calibrated!");
01055     }
01056     checkError();
01057 
01058     // Get offset between base frame and infrared frame
01059     rs_get_device_extrinsics(rs_device_, RS_STREAM_INFRARED, RS_STREAM_COLOR, &color2ir_extrinsic_, &rs_error_);
01060     if (rs_error_)
01061     {
01062       ROS_ERROR_STREAM(nodelet_name_ << " - Verify camera is calibrated!");
01063     }
01064     checkError();
01065   }
01066 
01067   /*
01068    * Publish Static transforms.
01069    */
01070   void BaseNodelet::publishStaticTransforms()
01071   {
01072     // Publish transforms for the cameras
01073     ROS_INFO_STREAM(nodelet_name_ << " - Publishing camera transforms (/tf_static)");
01074 
01075     tf::Quaternion q_c2co;
01076     tf::Quaternion q_d2do;
01077     tf::Quaternion q_i2io;
01078     geometry_msgs::TransformStamped b2d_msg;
01079     geometry_msgs::TransformStamped d2do_msg;
01080     geometry_msgs::TransformStamped b2c_msg;
01081     geometry_msgs::TransformStamped c2co_msg;
01082     geometry_msgs::TransformStamped b2i_msg;
01083     geometry_msgs::TransformStamped i2io_msg;
01084 
01085     // Get the current timestamp for all static transforms
01086     transform_ts_ = ros::Time::now();
01087 
01088     // The color frame is used as the base frame.
01089     // Hence no additional transformation is done from base frame to color frame.
01090     b2c_msg.header.stamp = transform_ts_;
01091     b2c_msg.header.frame_id = base_frame_id_;
01092     b2c_msg.child_frame_id = frame_id_[RS_STREAM_COLOR];
01093     b2c_msg.transform.translation.x = 0;
01094     b2c_msg.transform.translation.y = 0;
01095     b2c_msg.transform.translation.z = 0;
01096     b2c_msg.transform.rotation.x = 0;
01097     b2c_msg.transform.rotation.y = 0;
01098     b2c_msg.transform.rotation.z = 0;
01099     b2c_msg.transform.rotation.w = 1;
01100     static_tf_broadcaster_.sendTransform(b2c_msg);
01101 
01102     // Transform color frame to color optical frame
01103     q_c2co.setRPY(-M_PI/2, 0.0, -M_PI/2);
01104     c2co_msg.header.stamp = transform_ts_;
01105     c2co_msg.header.frame_id = frame_id_[RS_STREAM_COLOR];
01106     c2co_msg.child_frame_id = optical_frame_id_[RS_STREAM_COLOR];
01107     c2co_msg.transform.translation.x = 0;
01108     c2co_msg.transform.translation.y = 0;
01109     c2co_msg.transform.translation.z = 0;
01110     c2co_msg.transform.rotation.x = q_c2co.getX();
01111     c2co_msg.transform.rotation.y = q_c2co.getY();
01112     c2co_msg.transform.rotation.z = q_c2co.getZ();
01113     c2co_msg.transform.rotation.w = q_c2co.getW();
01114     static_tf_broadcaster_.sendTransform(c2co_msg);
01115 
01116     // Transform base frame to depth frame
01117     b2d_msg.header.stamp = transform_ts_;
01118     b2d_msg.header.frame_id = base_frame_id_;
01119     b2d_msg.child_frame_id = frame_id_[RS_STREAM_DEPTH];
01120     b2d_msg.transform.translation.x =  color2depth_extrinsic_.translation[2];
01121     b2d_msg.transform.translation.y = -color2depth_extrinsic_.translation[0];
01122     b2d_msg.transform.translation.z = -color2depth_extrinsic_.translation[1];
01123     b2d_msg.transform.rotation.x = 0;
01124     b2d_msg.transform.rotation.y = 0;
01125     b2d_msg.transform.rotation.z = 0;
01126     b2d_msg.transform.rotation.w = 1;
01127     static_tf_broadcaster_.sendTransform(b2d_msg);
01128 
01129     // Transform depth frame to depth optical frame
01130     q_d2do.setRPY(-M_PI/2, 0.0, -M_PI/2);
01131     d2do_msg.header.stamp = transform_ts_;
01132     d2do_msg.header.frame_id = frame_id_[RS_STREAM_DEPTH];
01133     d2do_msg.child_frame_id = optical_frame_id_[RS_STREAM_DEPTH];
01134     d2do_msg.transform.translation.x = 0;
01135     d2do_msg.transform.translation.y = 0;
01136     d2do_msg.transform.translation.z = 0;
01137     d2do_msg.transform.rotation.x = q_d2do.getX();
01138     d2do_msg.transform.rotation.y = q_d2do.getY();
01139     d2do_msg.transform.rotation.z = q_d2do.getZ();
01140     d2do_msg.transform.rotation.w = q_d2do.getW();
01141     static_tf_broadcaster_.sendTransform(d2do_msg);
01142 
01143     // Transform base frame to infrared frame
01144     b2i_msg.header.stamp = transform_ts_;
01145     b2i_msg.header.frame_id = base_frame_id_;
01146     b2i_msg.child_frame_id = frame_id_[RS_STREAM_INFRARED];
01147     b2i_msg.transform.translation.x =  color2ir_extrinsic_.translation[2];
01148     b2i_msg.transform.translation.y = -color2ir_extrinsic_.translation[0];
01149     b2i_msg.transform.translation.z = -color2ir_extrinsic_.translation[1];
01150     b2i_msg.transform.rotation.x = 0;
01151     b2i_msg.transform.rotation.y = 0;
01152     b2i_msg.transform.rotation.z = 0;
01153     b2i_msg.transform.rotation.w = 1;
01154     static_tf_broadcaster_.sendTransform(b2i_msg);
01155 
01156     // Transform infrared frame to infrared optical frame
01157     q_i2io.setRPY(-M_PI/2, 0.0, -M_PI/2);
01158     i2io_msg.header.stamp = transform_ts_;
01159     i2io_msg.header.frame_id = frame_id_[RS_STREAM_INFRARED];
01160     i2io_msg.child_frame_id = optical_frame_id_[RS_STREAM_INFRARED];
01161     i2io_msg.transform.translation.x = 0;
01162     i2io_msg.transform.translation.y = 0;
01163     i2io_msg.transform.translation.z = 0;
01164     i2io_msg.transform.rotation.x = q_i2io.getX();
01165     i2io_msg.transform.rotation.y = q_i2io.getY();
01166     i2io_msg.transform.rotation.z = q_i2io.getZ();
01167     i2io_msg.transform.rotation.w = q_i2io.getW();
01168     static_tf_broadcaster_.sendTransform(i2io_msg);
01169   }
01170 
01171   /*
01172    * Publish Dynamic transforms.
01173    */
01174   void BaseNodelet::publishDynamicTransforms()
01175   {
01176     tf::Transform tr;
01177     tf::Quaternion q;
01178 
01179     // The color frame is used as the base frame.
01180     // Hence no additional transformation is done from base frame to color frame.
01181     tr.setOrigin(tf::Vector3(0, 0, 0));
01182     tr.setRotation(tf::Quaternion(0, 0, 0, 1));
01183     dynamic_tf_broadcaster_.sendTransform(tf::StampedTransform(tr, transform_ts_,
01184           base_frame_id_, frame_id_[RS_STREAM_COLOR]));
01185 
01186     // Transform color frame to color optical frame
01187     tr.setOrigin(tf::Vector3(0, 0, 0));
01188     q.setRPY(-M_PI/2, 0.0, -M_PI/2);
01189     tr.setRotation(q);
01190     dynamic_tf_broadcaster_.sendTransform(tf::StampedTransform(tr, transform_ts_,
01191           frame_id_[RS_STREAM_COLOR], optical_frame_id_[RS_STREAM_COLOR]));
01192 
01193     // Transform base frame to depth frame
01194     tr.setOrigin(tf::Vector3(
01195            color2depth_extrinsic_.translation[2],
01196           -color2depth_extrinsic_.translation[0],
01197           -color2depth_extrinsic_.translation[1]));
01198     tr.setRotation(tf::Quaternion(0, 0, 0, 1));
01199     dynamic_tf_broadcaster_.sendTransform(tf::StampedTransform(tr, transform_ts_,
01200           base_frame_id_, frame_id_[RS_STREAM_DEPTH]));
01201 
01202     // Transform depth frame to depth optical frame
01203     tr.setOrigin(tf::Vector3(0, 0, 0));
01204     q.setRPY(-M_PI/2, 0.0, -M_PI/2);
01205     tr.setRotation(q);
01206     dynamic_tf_broadcaster_.sendTransform(tf::StampedTransform(tr, transform_ts_,
01207           frame_id_[RS_STREAM_DEPTH], optical_frame_id_[RS_STREAM_DEPTH]));
01208 
01209     // Transform base frame to infrared frame
01210     tr.setOrigin(tf::Vector3(
01211            color2ir_extrinsic_.translation[2],
01212           -color2ir_extrinsic_.translation[0],
01213           -color2ir_extrinsic_.translation[1]));
01214     tr.setRotation(tf::Quaternion(0, 0, 0, 1));
01215     dynamic_tf_broadcaster_.sendTransform(tf::StampedTransform(tr, transform_ts_,
01216           base_frame_id_, frame_id_[RS_STREAM_INFRARED]));
01217 
01218     // Transform infrared frame to infrared optical frame
01219     tr.setOrigin(tf::Vector3(0, 0, 0));
01220     q.setRPY(-M_PI/2, 0.0, -M_PI/2);
01221     tr.setRotation(q);
01222     dynamic_tf_broadcaster_.sendTransform(tf::StampedTransform(tr, transform_ts_,
01223           frame_id_[RS_STREAM_INFRARED], optical_frame_id_[RS_STREAM_INFRARED]));
01224   }
01225 
01226   /*
01227    * Prepare transforms.
01228    */
01229   void BaseNodelet::prepareTransforms()
01230   {
01231     // Publish transforms for the cameras
01232     ROS_INFO_STREAM(nodelet_name_ << " - Publishing camera transforms (/tf)");
01233 
01234     ros::Rate loop_rate(tf_publication_rate_);
01235 
01236     while (ros::ok())
01237     {
01238       // update the time stamp for publication
01239       transform_ts_ = ros::Time::now();
01240 
01241       publishDynamicTransforms();
01242 
01243       loop_rate.sleep();
01244     }
01245   }
01246 
01247   /*
01248    * Display error details and shutdown ROS.
01249    */
01250   void BaseNodelet::checkError()
01251   {
01252     if (rs_error_)
01253     {
01254       ROS_ERROR_STREAM(nodelet_name_ << " - Error calling " << rs_get_failed_function(rs_error_) << " ( "
01255           << rs_get_failed_args(rs_error_) << " ): \n" << rs_get_error_message(rs_error_) << " \n");
01256       rs_free_error(rs_error_);
01257       rs_error_ = NULL;
01258       ros::shutdown();
01259     }
01260   }
01261 
01262   void BaseNodelet::wrappedSystem(const std::vector<std::string>& string_argv)
01263   {
01264     pid_t pid;
01265 
01266     // Convert the args to char * const * for exec
01267     char * argv[string_argv.size() + 1];
01268 
01269     for (size_t i = 0; i < string_argv.size(); ++i)
01270     {
01271       argv[i] = const_cast<char*>(string_argv[i].c_str());
01272     }
01273     argv[string_argv.size()] = NULL;
01274 
01275     pid = fork();
01276 
01277     if (pid == -1)
01278     {  // failed to fork
01279       ROS_WARN_STREAM(nodelet_name_ <<
01280           " - Failed to fork system command:"
01281           << boost::algorithm::join(string_argv, " ")
01282           << strerror(errno));
01283     }
01284     else if (pid == 0)
01285     {  // child process
01286       // set to it's own process group
01287       setpgid(getpid(), getpid());
01288 
01289       // sleep for 1 second to ensure previous calls are completed
01290       sleep(1);
01291       // environ is the current environment from <unistd.h>
01292       execvpe(argv[0], argv, environ);
01293 
01294       _exit(EXIT_FAILURE);  // exec never returns
01295     }
01296     else
01297     { // parent process
01298       // Save the progress pid (process group)
01299       system_proc_groups_.push(pid);
01300 
01301       // If more than 10, process the oldest now
01302       if (system_proc_groups_.size() > 10)
01303       {
01304         killpg(system_proc_groups_.front(), SIGHUP);
01305         system_proc_groups_.pop();
01306       }
01307       // do not wait as this is the main thread
01308     }
01309   }
01310 
01311   std::string BaseNodelet::checkFirmwareValidation(const std::string& fw_type,
01312                                                    const std::string& current_fw,
01313                                                    const std::string& camera_name,
01314                                                    const std::string& camera_serial_number)
01315   {
01316     for (auto& elem : CAMERA_NAME_TO_VALIDATED_FIRMWARE)
01317     {
01318         std::cout << elem.first << " ; " << elem.second << std::endl;
01319     }
01320 
01321     std::string warning_msg = "";
01322     std::string cam_name = camera_name + "_" + fw_type;
01323     auto it = CAMERA_NAME_TO_VALIDATED_FIRMWARE.find(cam_name);
01324     if (it == CAMERA_NAME_TO_VALIDATED_FIRMWARE.end())
01325     {
01326         warning_msg = "Camera " + cam_name + " not found!";
01327     }
01328     else
01329     {
01330         std::string validated_firmware = it->second;
01331         if (current_fw != validated_firmware)
01332         {
01333             warning_msg = camera_serial_number + "'s current " + fw_type + " firmware is " + current_fw +
01334                     ", Validated " + fw_type + " firmware is " + validated_firmware;
01335         }
01336     }
01337 
01338     return warning_msg;
01339   }
01340 
01341 }  // namespace realsense_camera


realsense_camera
Author(s): Rajvi Jingar , Reagan Lopez , Matt Hansen , Mark Horn
autogenerated on Thu Jun 6 2019 21:15:58