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(),
120  _image_transport(node)
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 
response
const std::string response
usb_cam::UsbCam::service_stop_callback
static bool service_stop_callback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: usb_cam.cpp:73
usb_cam::camera_image_t::step
uint32_t step
Definition: types.h:116
usb_cam::camera_image_t::encoding
std::string encoding
Definition: types.h:117
usb_cam::UsbCam::create_suspended
static bool create_suspended
Definition: usb_cam.h:129
usb_cam::UsbCam::_service_supported_controls
ros::ServiceServer _service_supported_controls
Definition: usb_cam.h:161
usb_cam::AbstractV4LUSBCam::supported_formats
static std::vector< capture_format_t > supported_formats
Definition: camera_driver.h:67
usb_cam::UsbCam::camera_info_url
static std::string camera_info_url
Definition: usb_cam.h:170
camera_info_manager::CameraInfoManager::getCameraInfo
virtual sensor_msgs::CameraInfo getCameraInfo(void)
usb_cam::AbstractV4LUSBCam::full_ffmpeg_log
static bool full_ffmpeg_log
Definition: camera_driver.h:51
usb_cam::UsbCam::service_supported_formats_callback
static bool service_supported_formats_callback(std_srvs::Trigger::Request &request, std_srvs::Trigger::Response &response)
Definition: usb_cam.cpp:78
image_transport::ImageTransport
usb_cam::UsbCam::UsbCam
UsbCam()
Definition: usb_cam.cpp:116
usb_cam::AbstractV4LUSBCam::v4l_query_controls
static void v4l_query_controls()
Definition: camera_driver.cpp:932
usb_cam
Definition: camera_driver.h:35
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
ros.h
usb_cam::UsbCam::frame_timer
static ros::Timer * frame_timer
Definition: usb_cam.h:134
ros::NodeHandle::deleteParam
bool deleteParam(const std::string &key) const
ros::NodeHandle::advertiseService
ServiceServer advertiseService(AdvertiseServiceOptions &ops)
image_transport::CameraPublisher::publish
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
usb_cam::camera_image_t
Definition: types.h:112
usb_cam::AbstractV4LUSBCam::streaming_status
static bool streaming_status
Definition: camera_driver.h:70
usb_cam::AbstractV4LUSBCam::framerate
static int framerate
Definition: camera_driver.h:77
usb_cam::camera_image_t::width
uint32_t width
Definition: types.h:114
usb_cam::camera_image_t::stamp
struct timespec stamp
Definition: types.h:120
usb_cam::UsbCam::camera_frame_id
static std::string camera_frame_id
Definition: usb_cam.h:168
usb_cam::AbstractV4LUSBCam::io_method_name
static std::string io_method_name
Definition: camera_driver.h:72
f
f
ros::ServiceServer
usb_cam::UsbCam::service_start
static ros::ServiceServer * service_start
Definition: usb_cam.h:149
usb_cam::UsbCam::_service_stop
ros::ServiceServer _service_stop
Definition: usb_cam.h:153
usb_cam::AbstractV4LUSBCam::controls
static std::vector< camera_control_t > controls
Definition: camera_driver.h:78
usb_cam::UsbCam::_service_start_name
std::string _service_start_name
Definition: usb_cam.h:147
usb_cam.h
usb_cam::UsbCam::img_msg
static sensor_msgs::Image * img_msg
Definition: usb_cam.h:139
usb_cam::AbstractV4LUSBCam::color_format_name
static std::string color_format_name
Definition: camera_driver.h:74
usb_cam::UsbCam::_service_stop_name
std::string _service_stop_name
Definition: usb_cam.h:152
usb_cam::AbstractV4LUSBCam::image_width
static int image_width
Definition: camera_driver.h:75
usb_cam::UsbCam::service_supported_formats
static ros::ServiceServer * service_supported_formats
Definition: usb_cam.h:158
usb_cam::camera_image_t::image
char * image
Definition: types.h:121
usb_cam::UsbCam::Instance
static UsbCam & Instance()
Definition: usb_cam.cpp:317
usb_cam::UsbCam::~UsbCam
virtual ~UsbCam()
Definition: usb_cam.cpp:312
usb_cam::camera_image_t::height
uint32_t height
Definition: types.h:115
camera_info_manager::CameraInfoManager::isCalibrated
virtual bool isCalibrated(void)
camera_info_manager::CameraInfoManager
image_transport::CameraPublisher
ROS_WARN
#define ROS_WARN(...)
usb_cam::UsbCam::node
ros::NodeHandle node
Definition: usb_cam.h:132
usb_cam::UsbCam::service_supported_controls_callback
static bool service_supported_controls_callback(std_srvs::Trigger::Request &request, std_srvs::Trigger::Response &response)
Definition: usb_cam.cpp:101
ros::TimerEvent
usb_cam::AbstractV4LUSBCam::get_supported_formats
static std::vector< capture_format_t > & get_supported_formats()
Definition: camera_driver.cpp:830
usb_cam::AbstractV4LUSBCam::suspend
static bool suspend()
Definition: camera_driver.cpp:433
usb_cam::AbstractV4LUSBCam::start
static bool start()
Definition: camera_driver.cpp:90
usb_cam::UsbCam::image_transport
static image_transport::ImageTransport * image_transport
Definition: usb_cam.h:144
camera_info_manager::CameraInfoManager::setCameraInfo
virtual bool setCameraInfo(const sensor_msgs::CameraInfo &camera_info)
usb_cam::UsbCam
Definition: usb_cam.h:86
usb_cam::UsbCam::_image_transport
image_transport::ImageTransport _image_transport
Definition: usb_cam.h:143
usb_cam::AbstractV4LUSBCam::image_height
static int image_height
Definition: camera_driver.h:76
usb_cam::AbstractV4LUSBCam::adjust_camera
static void adjust_camera()
Definition: camera_driver.cpp:1003
usb_cam::AbstractV4LUSBCam::video_device_name
static std::string video_device_name
Definition: camera_driver.h:71
usb_cam::UsbCam::_img_msg
sensor_msgs::Image _img_msg
Definition: usb_cam.h:138
camera_info_manager::CameraInfoManager::setCameraName
virtual bool setCameraName(const std::string &cname)
ROS_ERROR
#define ROS_ERROR(...)
usb_cam::AbstractV4LUSBCam::start_capture
static bool start_capture()
Definition: camera_driver.cpp:375
usb_cam::UsbCam::service_supported_controls
static ros::ServiceServer * service_supported_controls
Definition: usb_cam.h:162
usb_cam::UsbCam::image_pub
static image_transport::CameraPublisher * image_pub
Definition: usb_cam.h:141
image_transport
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
usb_cam::AbstractV4LUSBCam::init
static bool init()
Definition: camera_driver.cpp:53
usb_cam::AbstractV4LUSBCam::ignore_controls
static std::set< std::string > ignore_controls
Definition: camera_driver.h:79
usb_cam::UsbCam::_image_pub
image_transport::CameraPublisher _image_pub
Definition: usb_cam.h:140
usb_cam::UsbCam::camera_name
static std::string camera_name
Definition: usb_cam.h:167
usb_cam::UsbCam::camera_transport_suffix
static std::string camera_transport_suffix
Definition: usb_cam.h:169
usb_cam::UsbCam::service_start_callback
static bool service_start_callback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: usb_cam.cpp:68
ROS_INFO
#define ROS_INFO(...)
ros::NodeHandle::shutdown
void shutdown()
usb_cam::AbstractV4LUSBCam::pixel_format_name
static std::string pixel_format_name
Definition: camera_driver.h:73
ros::NodeHandle::createTimer
Timer createTimer(Duration period, const TimerCallback &callback, bool oneshot=false, bool autostart=true) const
usb_cam::UsbCam::camera_info
static camera_info_manager::CameraInfoManager * camera_info
Definition: usb_cam.h:142
ros::Duration
usb_cam::UsbCam::service_stop
static ros::ServiceServer * service_stop
Definition: usb_cam.h:154
service_server.h
usb_cam::AbstractV4LUSBCam
Definition: camera_driver.h:38
ros::Timer
usb_cam::UsbCam::_service_start
ros::ServiceServer _service_start
Definition: usb_cam.h:148
usb_cam::UsbCam::_service_supported_formats
ros::ServiceServer _service_supported_formats
Definition: usb_cam.h:157
usb_cam::AbstractV4LUSBCam::read_frame
static camera_image_t * read_frame()
Definition: camera_driver.cpp:495
usb_cam::UsbCam::_frame_timer
ros::Timer _frame_timer
Definition: usb_cam.h:133
usb_cam::UsbCam::frame_timer_callback
static void frame_timer_callback(const ros::TimerEvent &event)
Definition: usb_cam.cpp:281


usb_cam
Author(s): Benjamin Pitzer
autogenerated on Sun Sep 3 2023 02:44:54