billmania / roboquest_core

The backend functionality for the RoboQuest project
1 stars 0 forks source link

Add support for multiple USB and CSI cameras #59

Closed billmania closed 1 year ago

billmania commented 1 year ago

This capability is required for rq_ui Issue 121 Provide support for 0 to 1 ArduCams and 0 to 3 USB cameras, simultaneously. Probe the hardware at startup for the usable cameras. For those cameras identified, provide their video frames in a way which can be consumed and displayed by the browser UI, but only from one camera at a time. The choice of which camera's frames to display in the browser UI will be made at run-time by the browser UI.

billmania commented 1 year ago

v4l2py Python module

Can identify USB cameras and their /dev/video device file

picamera2 Python module and python3-libcamera, libcamera-dev, libcap-dev apt packages

Can identify RaspPi CSI cameras

https://index.ros.org/r/v4l2_camera/

fswebcam ubuntu package

Capture a frame from a USB web cam. Won't work with the ArduCam.

fswebcam -r 640x480 --no-banner --device /dev/video4 /tmp/video4.jpg

v4l2-ctl to probe and configure cameras Seems to find all cameras, but will require some work to make the output programmatically useful.

v4l2-ctl -d 0 -D

https://stackoverflow.com/questions/57577445/list-available-cameras-opencv-python Doesn't work.

arducam node The running node has devices 0, 13, 14, 15, and 16 open

apt install ros-humble-usb-cam With CSI camera connected and camera_ros node running:

root@rq-23eb:/usr/src/ros2ws# ros2 run usb_cam usb_cam_node_exe
[INFO] [1700189288.995431722] [usb_cam]: camera_name value: default_cam
[WARN] [1700189288.995809063] [usb_cam]: framerate: 30.000000
[INFO] [1700189289.001898577] [usb_cam]: using default calibration URL
[INFO] [1700189289.002166194] [usb_cam]: camera calibration URL: file:///root/.ros/camera_info/default_cam.yaml
[ERROR] [1700189289.002369976] [camera_calibration_parsers]: Unable to open camera calibration file [/root/.ros/camera_info/default_cam.yaml]
[WARN] [1700189289.002564776] [usb_cam]: Camera calibration file /root/.ros/camera_info/default_cam.yaml not found
[INFO] [1700189289.002654741] [usb_cam]: Starting 'default_cam' (/dev/video0) at 640x480 via mmap (yuyv) at 30 FPS
terminate called after throwing an instance of 'char*'
[ros2run]: Aborted

usb_cam won't support the ArduCam. Will camera_ros support plain USB cameras?

When only a single CSI camera is connected, without any USB cams, it works fine and has the following devices open:

camera_no 303 root   28uW     CHR  238,1      0t0      61 /dev/media1
camera_no 303 root   29uW     CHR  238,2      0t0      62 /dev/media2
camera_no 303 root   30u      CHR  253,1      0t0      22 /dev/dma_heap/linux,cma
camera_no 303 root   31u      CHR  81,21      0t0     181 /dev/v4l-subdev0
camera_no 303 root   32u      CHR  81,20      0t0     231 /dev/video6
camera_no 303 root   33u      CHR   81,2      0t0     216 /dev/video13
camera_no 303 root   34u      CHR   81,3      0t0     217 /dev/video14
camera_no 303 root   35u      CHR   81,4      0t0     218 /dev/video15
camera_no 303 root   36u      CHR   81,5      0t0     219 /dev/video16
billmania commented 1 year ago

ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:=/dev/video0 -p framerate:=10.0 -p camera_name:=video0 -r image_raw:=video0_raw

ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:=/dev/video4 -p framerate:=10.0 -p camera_name:=video4 -r image_raw:=video4_raw

billmania commented 1 year ago

find_cameras.py will probe the CSI and USB to find cameras. It writes the file ${OS_PERSIST}/cameras_info with the details. A script is added to roboquest_core/scripts/start.sh which will rebuild install/roboquest_core/share/roboquest_core/config/*camera.yaml before calling ros2 launch.

The following template files are required:

For each hardware camera present a parameter file will be created and placed in the "install" config directory. For each hardware camera present a launch Node object definition will be created and added to the single "install" roboquest_core.launch.py.

billmania commented 1 year ago

I'm able to detect the presence or absence of one CSI camera and up to three USB cameras. I can also get frames from any collection of USB cameras. However, when there are both CSI and USB cameras connected, I can get frames from the USB but NOT from the CSI camera. If there's only a CSI camera connected, I can get frames from it.

The camera_node from the camera_ros package can retrieve and publish frames from a non-CSI, USB camera! It can publish from multiple cameras when both CSI and USB are connected.

ros2 run camera_ros camera_node --ros-args -p camera:=1 -r /camera/image_raw:=/camera/image_1_raw -r /camera/image_raw/compressed:=/camera/image_1_raw/compressed
ros2 run camera_ros camera_node \
    --ros-args \
    --params-file src/roboquest_core/config/rq_camera0.yaml

NB It appears the ROS parameter "FrameDurationLimits: [ 100000, 100000 ]" is not, and maybe never was, supported.