capture.cpp
Go to the documentation of this file.
00001 // Copyright [2015] Takashi Ogura<t.ogura@gmail.com>
00002 
00003 #include "cv_camera/capture.h"
00004 #include <sstream>
00005 #include <string>
00006 
00007 namespace cv_camera
00008 {
00009 
00010 namespace enc = sensor_msgs::image_encodings;
00011 
00012 Capture::Capture(ros::NodeHandle &node, const std::string &topic_name,
00013                  int32_t buffer_size, const std::string &frame_id)
00014     : node_(node),
00015       it_(node_),
00016       topic_name_(topic_name),
00017       buffer_size_(buffer_size),
00018       frame_id_(frame_id),
00019       info_manager_(node_, frame_id),
00020       capture_delay_(ros::Duration(node_.param("capture_delay", 0.0)))
00021 {
00022 }
00023 
00024 void Capture::loadCameraInfo()
00025 {
00026   std::string url;
00027   if (node_.getParam("camera_info_url", url))
00028   {
00029     if (info_manager_.validateURL(url))
00030     {
00031       info_manager_.loadCameraInfo(url);
00032     }
00033   }
00034 
00035   rescale_camera_info_ = node_.param<bool>("rescale_camera_info", false);
00036 
00037   for (int i = 0;; ++i)
00038   {
00039     int code = 0;
00040     double value = 0.0;
00041     std::stringstream stream;
00042     stream << "property_" << i << "_code";
00043     const std::string param_for_code = stream.str();
00044     stream.str("");
00045     stream << "property_" << i << "_value";
00046     const std::string param_for_value = stream.str();
00047     if (!node_.getParam(param_for_code, code) || !node_.getParam(param_for_value, value))
00048     {
00049       break;
00050     }
00051     if (!cap_.set(code, value))
00052     {
00053       ROS_ERROR_STREAM("Setting with code " << code << " and value " << value << " failed"
00054                                             << std::endl);
00055     }
00056   }
00057 }
00058 
00059 void Capture::rescaleCameraInfo(int width, int height)
00060 {
00061   double width_coeff = static_cast<double>(width) / info_.width;
00062   double height_coeff = static_cast<double>(height) / info_.height;
00063   info_.width = width;
00064   info_.height = height;
00065 
00066   // See http://docs.ros.org/api/sensor_msgs/html/msg/CameraInfo.html for clarification
00067   info_.K[0] *= width_coeff;
00068   info_.K[2] *= width_coeff;
00069   info_.K[4] *= height_coeff;
00070   info_.K[5] *= height_coeff;
00071 
00072   info_.P[0] *= width_coeff;
00073   info_.P[2] *= width_coeff;
00074   info_.P[5] *= height_coeff;
00075   info_.P[6] *= height_coeff;
00076 }
00077 
00078 void Capture::open(int32_t device_id)
00079 {
00080   cap_.open(device_id);
00081   if (!cap_.isOpened())
00082   {
00083     std::stringstream stream;
00084     stream << "device_id" << device_id << " cannot be opened";
00085     throw DeviceError(stream.str());
00086   }
00087   pub_ = it_.advertiseCamera(topic_name_, buffer_size_);
00088 
00089   loadCameraInfo();
00090 }
00091 
00092 void Capture::open(const std::string &device_path)
00093 {
00094   cap_.open(device_path, cv::CAP_V4L);
00095   if (!cap_.isOpened())
00096   {
00097     throw DeviceError("device_path " + device_path + " cannot be opened");
00098   }
00099   pub_ = it_.advertiseCamera(topic_name_, buffer_size_);
00100 
00101   loadCameraInfo();
00102 }
00103 
00104 void Capture::open()
00105 {
00106   open(0);
00107 }
00108 
00109 void Capture::openFile(const std::string &file_path)
00110 {
00111   cap_.open(file_path);
00112   if (!cap_.isOpened())
00113   {
00114     std::stringstream stream;
00115     stream << "file " << file_path << " cannot be opened";
00116     throw DeviceError(stream.str());
00117   }
00118   pub_ = it_.advertiseCamera(topic_name_, buffer_size_);
00119 
00120   std::string url;
00121   if (node_.getParam("camera_info_url", url))
00122   {
00123     if (info_manager_.validateURL(url))
00124     {
00125       info_manager_.loadCameraInfo(url);
00126     }
00127   }
00128 }
00129 
00130 bool Capture::capture()
00131 {
00132   if (cap_.read(bridge_.image))
00133   {
00134     ros::Time stamp = ros::Time::now() - capture_delay_;
00135     bridge_.encoding = enc::BGR8;
00136     bridge_.header.stamp = stamp;
00137     bridge_.header.frame_id = frame_id_;
00138 
00139     info_ = info_manager_.getCameraInfo();
00140     if (info_.height == 0 && info_.width == 0)
00141     {
00142       info_.height = bridge_.image.rows;
00143       info_.width = bridge_.image.cols;
00144     }
00145     else if (info_.height != bridge_.image.rows || info_.width != bridge_.image.cols)
00146     {
00147       if (rescale_camera_info_)
00148       {
00149         int old_width = info_.width;
00150         int old_height = info_.height;
00151         rescaleCameraInfo(bridge_.image.cols, bridge_.image.rows);
00152         ROS_INFO_ONCE("Camera calibration automatically rescaled from %dx%d to %dx%d",
00153                       old_width, old_height, bridge_.image.cols, bridge_.image.rows);
00154       }
00155       else
00156       {
00157         ROS_WARN_ONCE("Calibration resolution %dx%d does not match camera resolution %dx%d. "
00158                       "Use rescale_camera_info param for rescaling",
00159                       info_.width, info_.height, bridge_.image.cols, bridge_.image.rows);
00160       }
00161     }
00162     info_.header.stamp = stamp;
00163     info_.header.frame_id = frame_id_;
00164 
00165     return true;
00166   }
00167   return false;
00168 }
00169 
00170 void Capture::publish()
00171 {
00172   pub_.publish(*getImageMsgPtr(), info_);
00173 }
00174 
00175 bool Capture::setPropertyFromParam(int property_id, const std::string &param_name)
00176 {
00177   if (cap_.isOpened())
00178   {
00179     double value = 0.0;
00180     if (node_.getParam(param_name, value))
00181     {
00182       ROS_INFO("setting property %s = %lf", param_name.c_str(), value);
00183       return cap_.set(property_id, value);
00184     }
00185   }
00186   return true;
00187 }
00188 
00189 } // namespace cv_camera


cv_camera
Author(s): Takashi Ogura
autogenerated on Thu May 9 2019 02:53:02