ROS安装配置单目摄像头

看本文前,先在Linux上安装cheese,插上摄像头后看能不能正常显示图像,如果不能,就是摄像头有问题,摄像头正常之后再进行下面操作

安装摄像头驱动

先装驱动: sudo apt-get install ros-kinetic-usb-cam,最终把package安装到/opt/ros/kinetic/lib
从Github安装usb_cam驱动
usb_cam包用于和摄像头交互,将图片发布为sensor_msgs::Image主题,使用image_transport库来传递压缩图片。

运行和配置

USB摄像头插到工控机上后,默认是video0,用ls /dev | grep video查看,也就是/dev/video0
在机器人工控机上运行roslaunch usb_cam usb_cam.launch,包含下列参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
~video_device (string, default: "/dev/video0")
~pixel_format (string, default: "mjpeg") //图像格式,还可取mjpeg, yuyv, uyvy
~io_method (string, default: "mmap")  // 还可取mmap, read, userptr
~camera_frame_id (string, default: "head_camera")  // 相机的tf frame

~image_width (integer, default: 640)
~image_height (integer, default: 480)
~framerate (integer, default: 30) // 要求的framerate
~contrast (integer, default: 32) // 图像的对比度(0-255)
~brightness (integer, default: 32) // 图像的亮度(0-255)
~saturation (integer, default: 32) // 图像的饱和度(0-255)
~sharpness (integer, default: 22) // 图像的锐度(0-255)
~autofocus (boolean, default: false) // 自动对焦,默认是false
~focus (integer, default: 51) // 如果关闭自动对焦,相机的焦点,0代表无穷

~camera_info_url (string, default: ) //标定文件的地址,文件将被CameraInfoManager类读取
~camera_name (string, default: head_camera) //相机名称,与相机标定中的名称要一致

注意launch文件中的参数video_device要设置成对应摄像头的接口,比如/dev/video0

奇怪的是,我发现在自己的笔记本上摄像头对应video2video3,但用这两个都没有获得图像,应该是电脑问题。
另外在VMWare的Ubuntu里试了一下,虽然能出现图像,但是卡的要命,估计是虚拟机问题,所以不用考虑虚拟机上配置摄像头了。

摄像头常见分辨率有160X120, 320X240, 640X480以及1280X960。如果CPU和图形处理器处理20帧320X240时已经饱和,那么使用640X480时,实际只有5帧,这就太低了,我们一般取折中的320x240

比如我的launch文件是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
<launch>
<node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
<param name="video_device" value="/dev/video0" />
<param name="image_width" value="640" />
<param name="image_height" value="480" />
<param name="pixel_format" value="yuyv" />
<param name="framerate" value="20" />
<param name="autofocus" value="true" />
<param name="camera_frame_id" value="usb_cam" />
<param name="io_method" value="mmap"/>
</node>
</launch>

注意布尔量也要用value="true"的形式,要设置自动对焦,因为偶尔插上摄像头会模糊。

launch中的节点发布了两个主题:

1
2
/usb_cam/camera_info     // 类型 sensor_msgs/CameraInfo
/usb_cam/image_raw   // 类型 sensor_msgs/Image

然后到上位机运行image_view包:rosrun image_view image_view image:=usb_cam/image_rawimage_view订阅了image_view主题,结果会出现一个窗口显示了摄像头的图像。或者在终端运行rqt,在话题列表里会直接出现/usb_cam/image_raw,选择即可

对于图像消息,如果需要跨设备图传,不要使用原始的sensor_msgs/Image,会非常慢,改为sensor_msgs/CompressedImage

上面的配置只发布了usb_cam/image_raw一个话题,有一个插件compressed-image-transport还可以发布三个话题:usb_cam/image_raw/compressed, usb_cam/image_raw/compressedDepth, usb_cam/image_raw/theora

安装命令如下:

1
sudo apt-get install ros-indigo-compressed-image-transport

发现的问题

问题1:未校正摄像头

运行之后出现一些告警:

1
2
[ WARN ] : Camera calibration file /home/..../.ros/camera_info/head_camera.yaml not found
[ WARN ] : unknown control 'focus_auto'

第一个告警是因为没有校正摄像头模型。第二个告警说明摄像头不支持在自动对焦和手动对焦之间切换。

[校正摄像头的方法](https://rjosodtssp.github.io/2019/02/02/ROS/ROS%E6%9C%BA%E5%99%A8%E4%BA%BA/ROS%E6%A0%A1%E6%AD%A3%E6%91%84%E5%83%8F%E5%A4%B4/)

问题2:分辨率和帧率

launch文件中可以进行图像长宽和帧率的设置。长宽默认是640X480,帧率默认30。如果参数都设置太大,程序所占CPU会很大,可以适当降低。分辨率的比例最好维持在4x3

问题3:输入输出错误

有时重启程序会出现告警信息,启动失败

这种现象偶尔会出现,后来发现在一个虚拟机上测试时每次都如此,原因是视频流本身的问题,用cheese打开后的视频不正常。
在工控机上只有重插摄像头,然后恢复正常。

问题4:v4l2-ctl:not found

启动usb_cam出现告警:warn the information as the title "sh: 1: v4l2-ctl:not found",
解决方法:sudo apt-get install v4l-utils

插入其他 USB也可能导致摄像头的端口改变

比如/dev/video0变成了/dev/video1

某些报错没有规律,只能加respawn解决


压缩图片格式出错

有时启动摄像头程序会出现下面的错误:

这应该是个视频流格式问题,目前没有造成影响,加上是偶尔出现,所以可以不管

源码分析

usb_cam是先找到USB设备,例如/dev/video0,使用Linux的open函数打开,获得文件描述符再操作.

UsbCamNode::take_and_send_image()函数中的image_pub_.publish(img_, *ci);是发布视频流话题,不止usb_cam/image_raw,还有compressed等几个话题。

参考:
ROS官方介绍: usb_cam
ROS官方介绍: camera_calibration
how to install a driver like usb_cam