Skip to content

Commit

Permalink
Total refactoring
Browse files Browse the repository at this point in the history
	- 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
  • Loading branch information
twdragon authored and knorth55 committed Mar 3, 2023
1 parent a8add13 commit a663562
Show file tree
Hide file tree
Showing 16 changed files with 1,918 additions and 1,732 deletions.
157 changes: 99 additions & 58 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,82 +1,123 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.2)
project(usb_cam)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS cv_bridge image_transport roscpp std_msgs std_srvs sensor_msgs camera_info_manager)

# Find OpenCV
find_package(OpenCV REQUIRED)

## pkg-config libraries
message(STATUS "Searching required modules")
find_package(PkgConfig REQUIRED)
# FFMPEG
pkg_check_modules(avcodec libavcodec REQUIRED)
pkg_check_modules(avutil libavutil REQUIRED)
pkg_check_modules(swscale libswscale REQUIRED)
pkg_check_modules(video4linux libv4l2 REQUIRED)
# OPENCV
find_package(OpenCV REQUIRED)
# Reporting
if(avcodec_FOUND)
message(STATUS "Found libavcodec: ${avcodec_VERSION}")
endif()
if(avutil_FOUND)
message(STATUS "Found libavutil: ${avutil_VERSION}")
endif()
if(swscale_FOUND)
message(STATUS "Found libswscale: ${swscale_VERSION}")
endif()
if(OpenCV_FOUND)
message(STATUS "Found OpenCV: ${OpenCV_VERSION}")
endif()
if(video4linux_FOUND)
message(STATUS "Found Video4Linux kernel library: ${video4linux_VERSION}")
endif()

###################################################
## Declare things to be passed to other projects ##
###################################################

## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
# Catkin
find_package(catkin REQUIRED COMPONENTS
cv_bridge
image_transport
roscpp
std_msgs
std_srvs
sensor_msgs
camera_info_manager
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
INCLUDE_DIRS include
LIBRARIES usb_cam
)

###########
## Build ##
###########
# Build scenario
option(SUPPRESS_BIND_GLOBAL_PLACEHOLDERS
"Suppresses Boost >= 1.68 deprecation warning message for global placeholders in boost::bind instantiation"
ON
) # Workaround for deprecation message from instantiation of Boost::bind
if(SUPPRESS_BIND_GLOBAL_PLACEHOLDERS)
add_compile_definitions(BOOST_BIND_GLOBAL_PLACEHOLDERS)
endif(SUPPRESS_BIND_GLOBAL_PLACEHOLDERS)

include_directories(include
${catkin_INCLUDE_DIRS}
${avcodec_INCLUDE_DIRS}
${swscale_INCLUDE_DIRS}
${avutil_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
include_directories(include)
link_directories(
${video4linux_LIBRARY_DIRS}
${avcodec_LIBRARY_DIRS}
${avutil_LIBRARY_DIRS}
${swscale_LIBRARY_DIRS}
)

## Build the USB camera library
add_library(${PROJECT_NAME} src/usb_cam.cpp)
target_link_libraries(${PROJECT_NAME}
${avcodec_LIBRARIES}
${avutil_LIBRARIES}
${swscale_LIBRARIES}
${catkin_LIBRARIES}
${OpenCV_LIBS}
set(usb_cam_SHARED_HEADERS
include/usb_cam/types.h
include/usb_cam/util.h
include/usb_cam/converters.h
include/usb_cam/usb_cam.h
)
add_library(usb_cam
${usb_cam_SHARED_HEADERS}
src/util.cpp
src/converters.cpp
src/usb_cam.cpp
)
target_include_directories(usb_cam PUBLIC
${catkin_INCLUDE_DIRS}
${video4linux_INCLUDE_DIRS}
${avcodec_INCLUDE_DIRS}
${swscale_INCLUDE_DIRS}
${avutil_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
)
target_link_libraries(usb_cam
${video4linux_LIBRARIES}
${avcodec_LIBRARIES}
${avutil_LIBRARIES}
${swscale_LIBRARIES}
${catkin_LIBRARIES}
${OpenCV_LIBS}
)

## Declare a cpp executable
add_executable(${PROJECT_NAME}_node nodes/usb_cam_node.cpp)
target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME}
${avcodec_LIBRARIES}
${avutil_LIBRARIES}
${swscale_LIBRARIES}
${catkin_LIBRARIES}
${OpenCV_LIBS}
add_executable(usb_cam_node
src/usb_cam_node.cpp
)
target_include_directories(usb_cam_node PRIVATE
${catkin_INCLUDE_DIRS}
${avcodec_INCLUDE_DIRS}
${swscale_INCLUDE_DIRS}
${avutil_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
)
target_link_libraries(usb_cam_node
usb_cam
${catkin_LIBRARIES}
${OpenCV_LIBS}
)

#############
## Install ##
#############

## Mark executables and/or libraries for installation
# Installation scenario
# Executables and libraries
install(TARGETS ${PROJECT_NAME}_node ${PROJECT_NAME}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
)

## Copy launch files
# Launch files
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
FILES_MATCHING PATTERN "*.launch"
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
FILES_MATCHING PATTERN "*.launch"
)

# Include files
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
)
45 changes: 45 additions & 0 deletions config/usb_cam.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
video_device: /dev/video0 # Device driver's entrypoint
io_method: mmap # I/O method
# - read - for devices supporting virtual filesystem or block I/O
# - mmap - for devices with direct libusb memory mapping
# - userptr - for userspace devices supporting userspace pointer exchange
pixel_format: yuv # Pixel format for Video4linux device (also selects decoder mode)
# https://wiki.videolan.org/YUV#YUV_4:2:0_.28I420.2FJ420.2FYV12.29
# - yuyv - YUV420
# - yuv - synonym for yuyv
# - uyvy - UVY240
# - yuvmono10 - Monochrome 10-bit pseudo-YUV
# - rgb24 - Linear 8-bit RGB
# - bgr24 - OpenCV-compatible 8-bit BGR
# - grey - Grayscale 8-bit monochrome
# - yu12 - YU-reversed YUV420
# - mjpeg - FFMPEG decoder, MotionJPEG, for compatible hardware
# - h264 - FFMPEG decoder, H.264, for compatible hardware
color_format: yuv422p # On-chip color representation mode for the input frame encoded by hardware
# - yuv422p - YUV422 - default, compatible with most MJPEG hardware encoders
# - yuv420p - YUV420 - mandatory for H.264 and H.265 hardware encoders
create_suspended: false # Instructs the node whether to start streaming immediately after launch
# or to wait until the start service will be triggered
full_ffmpeg_log: false # Allows to suppress warning messages generated by libavcodec, cleans log
camera_name: head_camera # ROS internal name for the camera, used to generate camera_info message
camera_frame_id: head_camera # Frame ID used to generate coordinate transformations
camera_transport_suffix: image_raw # Suffix used by image_transport to generate topic names
camera_info_url: "" # URI for camera calibration data (likely a YML file obtained from camera_calibration)
image_width: 640 # Frame dimensions, should be supported by camera hardware
image_height: 480
framerate: 30 # Camera polling frequency, Hz (integer)
# Auxiliary parameters, hardware-dependent, some may not be supported by all cameras
exposure: 100 # Absolute exposure, percents or hardware-defined coefficient (integer)
brightness: -1 # Brightness, percents, 0-100, default -1 to ignore (integer)
contrast: -1 # Contrast, percents, 0-100, default -1 to ignore (integer)
saturation: -1 # Saturation, percents, 0-100, default -1 to ignore (integer)
sharpness: -1 # Shapening, hardware-defined unit, default -1 to ignore (integer)
focus: -1 # Focal distance, hardware-defined unit, default -1 to ignore (integer)
white_balance: 4000 # Absolute color temperature, K (integer)
gain: -1 # Gain coefficient, hardware-defined unit, default -1 to ignore (integer)
autofocus: false # Toggles auto focusing, once supported by hardware
autoexposure: true # Toggles auto exposure, once supported by hardware
auto_white_balance: true # Toggles auto color temperature adjustment, once supported by hardware
start_service_name: "start_capture" # Defines name suffix for std_srvs::Empty service which restarts suspended streaming
stop_service_name: "stop_capture" # Defines name suffix for std_srvs::Empty service which suspends camera polling timer

73 changes: 73 additions & 0 deletions include/usb_cam/converters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef USB_CAM_CONVERTERS_H
#define USB_CAM_CONVERTERS_H

#include "usb_cam/types.h"

namespace usb_cam
{

namespace util
{

namespace converters
{
/* Helper functions and table converters */
io_method_t io_method_from_string(const std::string & str);
pixel_format_t pixel_format_from_string(const std::string & str);
std::string pixel_format_to_string(const uint32_t & pixelformat);
color_format_t color_format_from_string(const std::string & str);
unsigned int v4l_pixel_format_from_pixel_format(const pixel_format_t& pixelformat, bool& mono);

/* Standalone format converters */
/**
* Conversion from YUV to RGB.
* The normal conversion matrix is due to Julien (surname unknown):
*
* [ R ] [ 1.0 0.0 1.403 ] [ Y ]
* [ G ] = [ 1.0 -0.344 -0.714 ] [ U ]
* [ B ] [ 1.0 1.770 0.0 ] [ V ]
*
* and the firewire one is similar:
*
* [ R ] [ 1.0 0.0 0.700 ] [ Y ]
* [ G ] = [ 1.0 -0.198 -0.291 ] [ U ]
* [ B ] [ 1.0 1.015 0.0 ] [ V ]
*
* Corrected by BJT (coriander's transforms RGB->YUV and YUV->RGB
* do not get you back to the same RGB!)
* [ R ] [ 1.0 0.0 1.136 ] [ Y ]
* [ G ] = [ 1.0 -0.396 -0.578 ] [ U ]
* [ B ] [ 1.0 2.041 0.002 ] [ V ]
*
*/
bool YUV2RGB(const unsigned char & y,
const unsigned char & u,
const unsigned char & v,
unsigned char * r,
unsigned char * g,
unsigned char * b);
bool MONO102MONO8(const char * RAW,
char * & MONO,
const int & NumPixels);
bool YUYV2RGB(const char * YUV,
char * & RGB,
const int & NumPixels);
bool COPY2RGB(const char * input,
char * & output,
const int & NumPixels);
bool YUV4202RGB(char * YUV,
char * & RGB,
const int & width,
const int & height);
std::string FCC2S(const unsigned int & val);
bool UYVY2RGB(const char * YUV,
char * & RGB,
const int & NumPixels);

}

}

}

#endif // USB_CAM_CONVERTERS_H
Loading

0 comments on commit a663562

Please sign in to comment.