Skip to content

Commit 97b43fe

Browse files
committed
Total refactoring
- The node implemented as singleton with monopolistic device access model (one node per device) - Moved and separated into different blocks the the code using V4L2, ROS and FFMPEG APIs - Removed message pointers completely, the node uses runtime- constant shared object addresses - Debugged FFMPEG decoder algorithm, removed memory leak. Closes ros-drivers#211 - Added (using @flynneva's code) the conditional compilation directives to exploit properly versioned libavcodec API. Closes ros-drivers#207 - Closes ros-drivers#203 - Added separated launch files to run the node and to test it using image_view. Removed image_view from ROS dependencies. - Node parameters with convenient defaults moved from the launch file to YML file for the parameter server - Documented parameter names and default values
1 parent b19346b commit 97b43fe

23 files changed

+1877
-1717
lines changed

.gitignore

100644100755
File mode changed.

.travis.yml

100644100755
File mode changed.

AUTHORS.md

100644100755
File mode changed.

CHANGELOG.rst

100644100755
File mode changed.

CMakeLists.txt

100644100755
+58-42
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,62 @@
1-
cmake_minimum_required(VERSION 2.8.12)
1+
cmake_minimum_required(VERSION 3.2)
22
project(usb_cam)
33

4-
## Find catkin macros and libraries
5-
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
6-
## is used, also find other catkin packages
7-
find_package(catkin REQUIRED COMPONENTS cv_bridge image_transport roscpp std_msgs std_srvs sensor_msgs camera_info_manager)
8-
9-
# Find OpenCV
10-
find_package(OpenCV REQUIRED)
11-
12-
## pkg-config libraries
4+
message(STATUS "Searching required modules")
135
find_package(PkgConfig REQUIRED)
6+
# FFMPEG
147
pkg_check_modules(avcodec libavcodec REQUIRED)
158
pkg_check_modules(avutil libavutil REQUIRED)
169
pkg_check_modules(swscale libswscale REQUIRED)
10+
pkg_check_modules(video4linux libv4l2 REQUIRED)
11+
# OPENCV
12+
find_package(OpenCV REQUIRED)
13+
# Reporting
14+
if(avcodec_FOUND)
15+
message(STATUS "Found libavcodec: ${avcodec_VERSION}")
16+
endif()
17+
if(avutil_FOUND)
18+
message(STATUS "Found libavutil: ${avutil_VERSION}")
19+
endif()
20+
if(swscale_FOUND)
21+
message(STATUS "Found libswscale: ${swscale_VERSION}")
22+
endif()
23+
if(OpenCV_FOUND)
24+
message(STATUS "Found OpenCV: ${OpenCV_VERSION}")
25+
endif()
26+
if(video4linux_FOUND)
27+
message(STATUS "Found Video4Linux kernel library: ${video4linux_VERSION}")
28+
endif()
1729

18-
###################################################
19-
## Declare things to be passed to other projects ##
20-
###################################################
21-
22-
## LIBRARIES: libraries you create in this project that dependent projects also need
23-
## CATKIN_DEPENDS: catkin_packages dependent projects also need
24-
## DEPENDS: system dependencies of this project that dependent projects also need
30+
# Catkin
31+
find_package(catkin REQUIRED COMPONENTS
32+
cv_bridge
33+
image_transport
34+
roscpp
35+
std_msgs
36+
std_srvs
37+
sensor_msgs
38+
camera_info_manager
39+
)
2540
catkin_package(
26-
INCLUDE_DIRS include
27-
LIBRARIES ${PROJECT_NAME}
41+
INCLUDE_DIRS include
42+
LIBRARIES usb_cam
2843
)
2944

30-
###########
31-
## Build ##
32-
###########
45+
# Build scenario
46+
option(SUPPRESS_BIND_GLOBAL_PLACEHOLDERS
47+
"Suppresses Boost >= 1.68 deprecation warning message for global placeholders in boost::bind instantiation"
48+
ON
49+
) # Workaround for deprecation message from instantiation of Boost::bind
50+
if(SUPPRESS_BIND_GLOBAL_PLACEHOLDERS)
51+
add_compile_definitions(BOOST_BIND_GLOBAL_PLACEHOLDERS)
52+
endif(SUPPRESS_BIND_GLOBAL_PLACEHOLDERS)
3353

34-
include_directories(include
35-
${catkin_INCLUDE_DIRS}
36-
${avcodec_INCLUDE_DIRS}
37-
${swscale_INCLUDE_DIRS}
38-
${avutil_INCLUDE_DIRS}
39-
${OpenCV_INCLUDE_DIRS}
54+
include_directories(include)
55+
link_directories(
56+
${video4linux_LIBRARY_DIRS}
57+
${avcodec_LIBRARY_DIRS}
58+
${avutil_LIBRARY_DIRS}
59+
${swscale_LIBRARY_DIRS}
4060
)
4161

4262
## Build the USB camera library
@@ -60,23 +80,19 @@ target_link_libraries(${PROJECT_NAME}_node
6080
${OpenCV_LIBS}
6181
)
6282

63-
#############
64-
## Install ##
65-
#############
66-
67-
## Mark executables and/or libraries for installation
83+
# Installation scenario
84+
# Executables and libraries
6885
install(TARGETS ${PROJECT_NAME}_node ${PROJECT_NAME}
69-
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
70-
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
86+
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
87+
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
7188
)
72-
73-
## Copy launch files
89+
# Launch files
7490
install(DIRECTORY launch/
75-
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
76-
FILES_MATCHING PATTERN "*.launch"
91+
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
92+
FILES_MATCHING PATTERN "*.launch"
7793
)
78-
94+
# Include files
7995
install(DIRECTORY include/${PROJECT_NAME}/
80-
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
81-
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
96+
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
97+
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
8298
)

LICENSE

100644100755
File mode changed.

README.md

100644100755
File mode changed.

config/usb_cam.yml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
video_device: /dev/video0 # Device driver's entrypoint
2+
io_method: mmap # I/O method
3+
# - read - for devices supporting virtual filesystem or block I/O
4+
# - mmap - for devices with direct libusb memory mapping
5+
# - userptr - for userspace devices supporting userspace pointer exchange
6+
pixel_format: yuv # Pixel format for Video4linux device (also selects decoder mode)
7+
# https://wiki.videolan.org/YUV#YUV_4:2:0_.28I420.2FJ420.2FYV12.29
8+
# - yuyv - YUV420
9+
# - yuv - synonym for yuyv
10+
# - uyvy - UVY240
11+
# - yuvmono10 - Monochrome 10-bit pseudo-YUV
12+
# - rgb24 - Linear 8-bit RGB
13+
# - bgr24 - OpenCV-compatible 8-bit BGR
14+
# - grey - Grayscale 8-bit monochrome
15+
# - yu12 - YU-reversed YUV420
16+
# - mjpeg - FFMPEG decoder, MotionJPEG, for compatible hardware
17+
# - h264 - FFMPEG decoder, H.264, for compatible hardware
18+
color_format: yuv422p # On-chip color representation mode for the input frame encoded by hardware
19+
# - yuv422p - YUV422 - default, compatible with most MJPEG hardware encoders
20+
# - yuv420p - YUV420 - mandatory for H.264 and H.265 hardware encoders
21+
create_suspended: false # Instructs the node whether to start streaming immediately after launch
22+
# or to wait until the start service will be triggered
23+
full_ffmpeg_log: false # Allows to suppress warning messages generated by libavcodec, cleans log
24+
camera_name: head_camera # ROS internal name for the camera, used to generate camera_info message
25+
camera_frame_id: head_camera # Frame ID used to generate coordinate transformations
26+
camera_transport_suffix: image_raw # Suffix used by image_transport to generate topic names
27+
camera_info_url: "" # URI for camera calibration data (likely a YML file obtained from camera_calibration)
28+
image_width: 640 # Frame dimensions, should be supported by camera hardware
29+
image_height: 480
30+
framerate: 30 # Camera polling frequency, Hz (integer)
31+
# Auxiliary parameters, hardware-dependent, some may not be supported by all cameras
32+
exposure: 100 # Absolute exposure, percents or hardware-defined coefficient (integer)
33+
brightness: -1 # Brightness, percents, 0-100, default -1 to ignore (integer)
34+
contrast: -1 # Contrast, percents, 0-100, default -1 to ignore (integer)
35+
saturation: -1 # Saturation, percents, 0-100, default -1 to ignore (integer)
36+
sharpness: -1 # Shapening, hardware-defined unit, default -1 to ignore (integer)
37+
focus: -1 # Focal distance, hardware-defined unit, default -1 to ignore (integer)
38+
white_balance: 4000 # Absolute color temperature, K (integer)
39+
gain: -1 # Gain coefficient, hardware-defined unit, default -1 to ignore (integer)
40+
autofocus: false # Toggles auto focusing, once supported by hardware
41+
autoexposure: true # Toggles auto exposure, once supported by hardware
42+
auto_white_balance: true # Toggles auto color temperature adjustment, once supported by hardware
43+
start_service_name: "start_capture" # Defines name suffix for std_srvs::Empty service which restarts suspended streaming
44+
stop_service_name: "stop_capture" # Defines name suffix for std_srvs::Empty service which suspends camera polling timer
45+

include/usb_cam/converters.h

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#ifndef USB_CAM_CONVERTERS_H
2+
#define USB_CAM_CONVERTERS_H
3+
4+
#include "usb_cam/types.h"
5+
6+
namespace usb_cam
7+
{
8+
9+
namespace util
10+
{
11+
12+
namespace converters
13+
{
14+
/* Helper functions and table converters */
15+
io_method_t io_method_from_string(const std::string & str);
16+
pixel_format_t pixel_format_from_string(const std::string & str);
17+
std::string pixel_format_to_string(const uint32_t & pixelformat);
18+
color_format_t color_format_from_string(const std::string & str);
19+
unsigned int v4l_pixel_format_from_pixel_format(const pixel_format_t& pixelformat, bool& mono);
20+
21+
/* Standalone format converters */
22+
/**
23+
* Conversion from YUV to RGB.
24+
* The normal conversion matrix is due to Julien (surname unknown):
25+
*
26+
* [ R ] [ 1.0 0.0 1.403 ] [ Y ]
27+
* [ G ] = [ 1.0 -0.344 -0.714 ] [ U ]
28+
* [ B ] [ 1.0 1.770 0.0 ] [ V ]
29+
*
30+
* and the firewire one is similar:
31+
*
32+
* [ R ] [ 1.0 0.0 0.700 ] [ Y ]
33+
* [ G ] = [ 1.0 -0.198 -0.291 ] [ U ]
34+
* [ B ] [ 1.0 1.015 0.0 ] [ V ]
35+
*
36+
* Corrected by BJT (coriander's transforms RGB->YUV and YUV->RGB
37+
* do not get you back to the same RGB!)
38+
* [ R ] [ 1.0 0.0 1.136 ] [ Y ]
39+
* [ G ] = [ 1.0 -0.396 -0.578 ] [ U ]
40+
* [ B ] [ 1.0 2.041 0.002 ] [ V ]
41+
*
42+
*/
43+
bool YUV2RGB(const unsigned char & y,
44+
const unsigned char & u,
45+
const unsigned char & v,
46+
unsigned char * r,
47+
unsigned char * g,
48+
unsigned char * b);
49+
bool MONO102MONO8(const char * RAW,
50+
char * & MONO,
51+
const int & NumPixels);
52+
bool YUYV2RGB(const char * YUV,
53+
char * & RGB,
54+
const int & NumPixels);
55+
bool COPY2RGB(const char * input,
56+
char * & output,
57+
const int & NumPixels);
58+
bool YUV4202RGB(char * YUV,
59+
char * & RGB,
60+
const int & width,
61+
const int & height);
62+
std::string FCC2S(const unsigned int & val);
63+
bool UYVY2RGB(const char * YUV,
64+
char * & RGB,
65+
const int & NumPixels);
66+
67+
}
68+
69+
}
70+
71+
}
72+
73+
#endif // USB_CAM_CONVERTERS_H

include/usb_cam/types.h

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#ifndef USB_CAM_TYPES_H
2+
#define USB_CAM_TYPES_H
3+
4+
#include <vector>
5+
#include <string>
6+
#include <chrono>
7+
#include <memory>
8+
#include <sstream>
9+
#include <string>
10+
#include <vector>
11+
#include <cmath>
12+
#include <ctime>
13+
#include <climits>
14+
#include <cstring>
15+
#include <stdexcept>
16+
17+
#include <asm/types.h> // for videodev2.h
18+
#include <linux/videodev2.h>
19+
#include <sys/ioctl.h>
20+
#include <sys/time.h>
21+
22+
#include <opencv2/imgproc.hpp>
23+
24+
namespace usb_cam
25+
{
26+
namespace constants
27+
{
28+
29+
static const std::vector<unsigned char> uchar_clipping_table = {
30+
0, 0, 0, 0, 0, 0, 0, 0, // -128 - -121
31+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -120 - -101
32+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -100 - -81
33+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -80 - -61
34+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -60 - -41
35+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -40 - -21
36+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -20 - -1
37+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
38+
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
39+
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
40+
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
41+
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
42+
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
43+
116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
44+
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
45+
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
46+
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
47+
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
48+
191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
49+
206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
50+
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
51+
236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
52+
251, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 256-263
53+
255, 255, 255, 255, 255, 255, 255, 255, // 264-271
54+
255, 255, 255, 255, 255, 255, 255, 255, // 272-279
55+
255, 255, 255, 255, 255, 255, 255, 255, // 280-287
56+
255, 255, 255, 255, 255, 255, 255, 255, // 288-295
57+
255, 255, 255, 255, 255, 255, 255, 255, // 296-303
58+
255, 255, 255, 255, 255, 255, 255, 255, // 304-311
59+
255, 255, 255, 255, 255, 255, 255, 255, // 312-319
60+
255, 255, 255, 255, 255, 255, 255, 255, // 320-327
61+
255, 255, 255, 255, 255, 255, 255, 255, // 328-335
62+
255, 255, 255, 255, 255, 255, 255, 255, // 336-343
63+
255, 255, 255, 255, 255, 255, 255, 255, // 344-351
64+
255, 255, 255, 255, 255, 255, 255, 255, // 352-359
65+
255, 255, 255, 255, 255, 255, 255, 255, // 360-367
66+
255, 255, 255, 255, 255, 255, 255, 255, // 368-375
67+
255, 255, 255, 255, 255, 255, 255, 255, // 376-383
68+
};
69+
70+
static const int clipping_table_offset = 128;
71+
72+
} // namespace constants
73+
74+
enum io_method_t
75+
{
76+
IO_METHOD_READ,
77+
IO_METHOD_MMAP,
78+
IO_METHOD_USERPTR,
79+
IO_METHOD_UNKNOWN,
80+
};
81+
82+
83+
enum pixel_format_t
84+
{
85+
PIXEL_FORMAT_YUYV,
86+
PIXEL_FORMAT_UYVY,
87+
PIXEL_FORMAT_MJPEG,
88+
PIXEL_FORMAT_YUVMONO10,
89+
PIXEL_FORMAT_RGB24,
90+
PIXEL_FORMAT_BGR24,
91+
PIXEL_FORMAT_GREY,
92+
PIXEL_FORMAT_YU12,
93+
PIXEL_FORMAT_H264,
94+
PIXEL_FORMAT_UNKNOWN
95+
};
96+
97+
98+
enum color_format_t
99+
{
100+
COLOR_FORMAT_YUV420P,
101+
COLOR_FORMAT_YUV422P,
102+
COLOR_FORMAT_UNKNOWN,
103+
};
104+
105+
106+
struct buffer
107+
{
108+
void * start;
109+
std::size_t length;
110+
};
111+
112+
struct camera_image_t
113+
{
114+
uint32_t width;
115+
uint32_t height;
116+
uint32_t step;
117+
std::string encoding;
118+
int bytes_per_pixel;
119+
int image_size;
120+
struct timespec stamp;
121+
char * image;
122+
int is_new;
123+
};
124+
125+
struct capture_format_t
126+
{
127+
struct v4l2_fmtdesc format;
128+
struct v4l2_frmsizeenum size;
129+
struct v4l2_frmivalenum interval;
130+
};
131+
132+
} // namespace usb_cam
133+
134+
#endif // USB_CAM_TYPES_H

0 commit comments

Comments
 (0)