usb_cam.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2014, Robert Bosch LLC.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of the Robert Bosch nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  *********************************************************************/
36 
37 #include <linux/videodev2.h>
38 #include <ros/ros.h>
39 #include <sstream>
40 #include <stdexcept>
41 #include <string>
42 #include <vector>
43 #include "ros/service_server.h"
44 #include "usb_cam/usb_cam.h"
45 
46 using namespace usb_cam;
47 
48 bool UsbCam::create_suspended = false;
49 
50 /* ROS */
52 sensor_msgs::Image* UsbCam::img_msg = nullptr;
60 
61 /* Node parameters */
62 std::string UsbCam::camera_name = "head_camera";
63 std::string UsbCam::camera_frame_id = "head_camera";
64 std::string UsbCam::camera_transport_suffix = "image_raw";
65 std::string UsbCam::camera_info_url = "";
66 
67 /* ROS Service callback functions */
68 bool UsbCam::service_start_callback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
69 {
70  return start_capture();
71 }
72 
73 bool UsbCam::service_stop_callback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
74 {
75  return suspend();
76 }
77 
78 bool UsbCam::service_supported_formats_callback(std_srvs::Trigger::Request &request, std_srvs::Trigger::Response &response)
79 {
81  std::stringstream output_stream;
82  std::cout << "SUPPORTED INPUT FORMATS FOR V4L DEVICE " << video_device_name << std::endl;
83  for(auto fmt : supported_formats)
84  {
85  output_stream << " | " << fmt.format.description
86  << " [" << fmt.interval.width << " x "
87  << fmt.interval.height << "], "
88  << fmt.interval.discrete.denominator / fmt.interval.discrete.numerator
89  << " fps";
90  std::cout << "\t" << fmt.format.description
91  << " [" << fmt.interval.width << " x "
92  << fmt.interval.height << "], "
93  << fmt.interval.discrete.denominator / fmt.interval.discrete.numerator
94  << " fps" << std::endl;
95  }
96  response.success = true;
97  response.message = output_stream.str();
98  return true;
99 }
100 
101 bool UsbCam::service_supported_controls_callback(std_srvs::Trigger::Request &request, std_srvs::Trigger::Response &response)
102 {
103  std::stringstream output_stream;
104  std::cout << "SUPPORTED V4L CONTROLS FOR DEVICE " << video_device_name << std::endl;
105  std::cout << "NOTE: these controls are supported on host machine, not natively by ROS!" << std::endl;
106  for(auto c: controls)
107  {
108  output_stream << " | " << c.name << " [" << c.value << "]: " << c.description;
109  std::cout << c.name << " [" << c.value << "]" << std::endl << "\t" << c.description << std::endl;
110  }
111  response.success = true;
112  response.message = output_stream.str();
113  return true;
114 }
115 
118  node("~"),
119  _img_msg(),
121 {
122  img_msg = &_img_msg;
124  /* Loading parameters */
125  // Mandatory parameters are defined with getParam(), otherwise with param<>()
126  node.getParam("video_device", video_device_name);
127  node.getParam("io_method", io_method_name);
128  node.getParam("pixel_format", pixel_format_name);
129  node.getParam("color_format", color_format_name);
130  node.param<bool>("create_suspended", create_suspended, false);
131  node.param<bool>("full_ffmpeg_log", full_ffmpeg_log, false);
132  node.getParam("camera_name", camera_name);
133  node.getParam("camera_frame_id", camera_frame_id);
134  node.param<std::string>("camera_transport_suffix", camera_transport_suffix, "image_raw");
135  node.param<std::string>("camera_info_url", camera_info_url, "");
136  node.getParam("image_width", image_width);
137  node.getParam("image_height", image_height);
138  node.getParam("framerate", framerate);
139  node.param<std::string>("start_service_name", _service_start_name, "start_capture");
140  node.param<std::string>("stop_service_name", _service_stop_name, "stop_capture");
141 
142  // Advertising camera
143  ROS_INFO("Initializing ROS V4L USB camera '%s' (%s) at %dx%d via %s (%s) at %i FPS",
144  camera_name.c_str(),
145  video_device_name.c_str(),
146  image_width,
147  image_height,
148  io_method_name.c_str(),
149  pixel_format_name.c_str(),
150  framerate);
151  _image_pub = image_transport->advertiseCamera(camera_transport_suffix, 1);
154  img_msg->header.frame_id = camera_frame_id;
155  if(!camera_info->isCalibrated())
156  {
158  sensor_msgs::CameraInfo camera_info_msg;
159  camera_info_msg.header.frame_id = img_msg->header.frame_id;
160  camera_info_msg.width = image_width;
161  camera_info_msg.height = image_height;
162  camera_info->setCameraInfo(camera_info_msg);
163  }
164 
165  if(!init())
166  {
167  ROS_ERROR("Initialization error or wrong parameters");
168  node.shutdown();
169  return;
170  }
171 
172  /* Advertising services */
173  ROS_INFO("Advertising std_srvs::Empty start service under name '%s'", _service_start_name.c_str());
176  ROS_INFO("Advertising std_srvs::Empty suspension service under name '%s'", _service_stop_name.c_str());
179  ROS_INFO("Advertising std_srvs::Trigger supported formats information service under name 'supported_formats'");
182  ROS_INFO("Advertising std_srvs::Trigger supported V4L controls information service under name 'supported_controls'");
185 
186  /* All parameters set, running frame grabber */
187  if(!start())
188  {
189  ROS_ERROR("Error starting device");
190  node.shutdown();
191  return;
192  }
193  /* Device opened, creating parameter grabber*/
195  /* Dynamically created V4L2 parameters */
196  ROS_WARN("NOTE: the parameters generated for V4L intrinsic camera controls will be placed under namespace 'intrinsic_controls'");
197  ROS_INFO("Use 'intrinsic_controls/ignore' list to enumerate the controls provoking errors or the ones you just want to keep untouched");
198  for(auto c = controls.begin(); c != controls.end(); c++)
199  { // intrinsic_controls
200  ROS_INFO("Attempting to generate ROS parameter for V4L2 control '%s':\n\t%s [%s]%s", c->name.c_str(), c->description.c_str(), c->value.c_str(), c->type == V4L2_CTRL_TYPE_BOOLEAN ? " (bool 1/0)" : "");
201  std::string tps;
202  bool tpb;
203  int tpi;
204  bool generated = true;
205  long tpl;
206  switch(c->type)
207  {
208  case V4L2_CTRL_TYPE_INTEGER:
209  case V4L2_CTRL_TYPE_MENU:
210  case V4L2_CTRL_TYPE_INTEGER_MENU:
211  //tpi = std::stoi(c.value);
212  node.param<int>("intrinsic_controls/" + c->name, tpi, std::stoi(c->value));
213  c->value = std::to_string(tpi);
214  break;
215  case V4L2_CTRL_TYPE_BOOLEAN:
216  //tpb = c.value == "1" ? true : false;
217  node.param<bool>("intrinsic_controls/" + c->name, tpb, c->value == "1" ? true : false);
218  c->value = tpb ? std::to_string(1) : std::to_string(0);
219  break;
220  case V4L2_CTRL_TYPE_STRING:
221  //tps = c.value;
222  node.param<std::string>("intrinsic_controls/" + c->name, tps, c->value);
223  c->value = tps;
224  break;
225  case V4L2_CTRL_TYPE_INTEGER64:
226  node.param<std::string>("intrinsic_controls/" + c->name, tps, c->value);
227  try
228  {
229  tpl = std::stol(tps);
230  ROS_INFO("64-bit integer 0x%lX successfully transposed to control %s", tpl, c->name.c_str());
231  c->value = tps;
232  }
233  catch(std::invalid_argument)
234  {
235  ROS_ERROR("Cannot convert string value '%s' to 64-bit integer! Please check your configuration file! Dropping down parameter '%s'", tps.c_str(), std::string("intrinsic_controls/" + c->name).c_str());
236  node.deleteParam("intrinsic_controls/" + c->name);
237  }
238  break;
239  default:
240  ROS_WARN("Unsupported type descriptor (%u) for V4L control '%s'. This parameter cannot be set via ROS. Please consider to set this parameter via 3rd party controller application", c->type, c->name.c_str());
241  generated = false;
242  }
243  if(generated)
244  ROS_INFO("Parameter intrinsic_controls/%s exposed with value %s", c->name.c_str(), c->value.c_str());
245  }
246  std::vector<std::string>ignored;
247  node.param< std::vector<std::string> >("intrinsic_controls/ignore", ignored, std::vector<std::string>());
248  // Set up ignored control names
249  if(!ignored.empty())
250  for(auto n: ignored)
251  ignore_controls.insert(n);
252  /*
253  node.param<int>("exposure", exposure, 100);
254  node.param<int>("brightness", brightness, -1);
255  node.param<int>("contrast", contrast, -1);
256  node.param<int>("saturation", saturation, -1);
257  node.param<int>("sharpness", sharpness, -1);auto
258  node.param<int>("focus", focus, -1);
259  node.param<int>("white_balance", white_balance, 4000);
260  node.param<int>("gain", gain, -1);
261  node.param<bool>("autofocus", autofocus, false);
262  node.param<bool>("autoexposure", autoexposure, true);
263  node.param<bool>("auto_white_balance", auto_white_balance, false);
264  */
265  adjust_camera();
266 
267  // Creating timer
268  ros::Duration frame_period(1.f / static_cast<float>(framerate));
269  _frame_timer = node.createTimer(frame_period, &UsbCam::frame_timer_callback, false, true);
271  // Running capture engine
272  if(!create_suspended)
273  if(!start_capture())
274  {
275  ROS_ERROR("Error starting capture device");
276  node.shutdown();
277  return;
278  }
279 }
280 
282 {
283  if(streaming_status)
284  {
285  camera_image_t* new_image = read_frame();
286  if(new_image == nullptr)
287  {
288  ROS_ERROR("Video4linux: frame grabber failed");
289  return;
290  }
291  img_msg->header.stamp.sec = new_image->stamp.tv_sec;
292  img_msg->header.stamp.nsec = new_image->stamp.tv_nsec;
293  if (img_msg->data.size() != static_cast<size_t>(new_image->step * new_image->height))
294  {
295  img_msg->width = new_image->width;
296  img_msg->height = new_image->height;
297  img_msg->encoding = new_image->encoding;
298  img_msg->step = new_image->step;
299  //img_msg->data.resize(new_image->step * new_image->height);
300  }
301  // Fill in image data
302  // memcpy(&img_msg->data[0], new_image->image, img_msg->data.size());
303  // Direct assignment from constant length array: removes blinking on some integrated webcam systems using mmap access mode
304  // To be reworked if the plugin architecture planned to be implemented
305  img_msg->data.assign(new_image->image, new_image->image + (new_image->step * new_image->height));
306  auto ci = std::make_unique<sensor_msgs::CameraInfo>(camera_info->getCameraInfo());
307  ci->header = img_msg->header;
308  image_pub->publish((*img_msg), (*ci));
309  }
310 }
311 
313 {
314  delete camera_info;
315 }
316 
318 {
319  static UsbCam instance;
320  return instance;
321 }
322 
ros::ServiceServer _service_supported_formats
Definition: usb_cam.h:89
static image_transport::ImageTransport * image_transport
Definition: usb_cam.h:76
static camera_image_t * read_frame()
sensor_msgs::CameraInfo getCameraInfo(void)
f
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
static bool service_supported_controls_callback(std_srvs::Trigger::Request &request, std_srvs::Trigger::Response &response)
Definition: usb_cam.cpp:101
ros::ServiceServer _service_supported_controls
Definition: usb_cam.h:93
ros::ServiceServer _service_stop
Definition: usb_cam.h:85
static ros::ServiceServer * service_supported_controls
Definition: usb_cam.h:94
bool deleteParam(const std::string &key) const
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
static ros::ServiceServer * service_stop
Definition: usb_cam.h:86
std::string _service_stop_name
Definition: usb_cam.h:84
#define ROS_WARN(...)
static std::string color_format_name
Definition: camera_driver.h:74
image_transport::CameraPublisher _image_pub
Definition: usb_cam.h:72
static std::string io_method_name
Definition: camera_driver.h:72
ros::ServiceServer _service_start
Definition: usb_cam.h:80
static sensor_msgs::Image * img_msg
Definition: usb_cam.h:71
static std::vector< camera_control_t > controls
Definition: camera_driver.h:78
bool param(const std::string &param_name, T &param_val, const T &default_val) const
static std::vector< capture_format_t > & get_supported_formats()
virtual ~UsbCam()
Definition: usb_cam.cpp:312
static ros::ServiceServer * service_start
Definition: usb_cam.h:81
struct timespec stamp
Definition: types.h:120
static camera_info_manager::CameraInfoManager * camera_info
Definition: usb_cam.h:74
ros::Timer _frame_timer
Definition: usb_cam.h:65
static bool service_start_callback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: usb_cam.cpp:68
#define ROS_INFO(...)
bool getParam(const std::string &key, std::string &s) const
static void frame_timer_callback(const ros::TimerEvent &event)
Definition: usb_cam.cpp:281
ros::NodeHandle node
Definition: usb_cam.h:64
static std::string camera_info_url
Definition: usb_cam.h:102
static bool service_supported_formats_callback(std_srvs::Trigger::Request &request, std_srvs::Trigger::Response &response)
Definition: usb_cam.cpp:78
static bool create_suspended
Definition: usb_cam.h:61
sensor_msgs::Image _img_msg
Definition: usb_cam.h:70
static ros::Timer * frame_timer
Definition: usb_cam.h:66
bool setCameraInfo(const sensor_msgs::CameraInfo &camera_info)
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
static std::set< std::string > ignore_controls
Definition: camera_driver.h:79
image_transport::ImageTransport _image_transport
Definition: usb_cam.h:75
static std::string camera_transport_suffix
Definition: usb_cam.h:101
static std::string video_device_name
Definition: camera_driver.h:71
static std::string pixel_format_name
Definition: camera_driver.h:73
std::string _service_start_name
Definition: usb_cam.h:79
static std::string camera_name
Definition: usb_cam.h:99
std::string encoding
Definition: types.h:117
static std::vector< capture_format_t > supported_formats
Definition: camera_driver.h:67
static UsbCam & Instance()
Definition: usb_cam.cpp:317
#define ROS_ERROR(...)
bool setCameraName(const std::string &cname)
static image_transport::CameraPublisher * image_pub
Definition: usb_cam.h:73
static std::string camera_frame_id
Definition: usb_cam.h:100
static ros::ServiceServer * service_supported_formats
Definition: usb_cam.h:90
static bool service_stop_callback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: usb_cam.cpp:73


usb_cam
Author(s): Benjamin Pitzer
autogenerated on Sat May 27 2023 02:53:05