Go to the documentation of this file.00001
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
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 ¶m_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 }