看本文前,先在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
。
奇怪的是,我发现在自己的笔记本上摄像头对应video2
和video3
,但用这两个都没有获得图像,应该是电脑问题。
另外在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_raw
,image_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'
第一个告警是因为没有校正摄像头模型。第二个告警说明摄像头不支持在自动对焦和手动对焦之间切换。
问题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