看本文前,先在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'
第一个告警是因为没有校正摄像头模型。第二个告警说明摄像头不支持在自动对焦和手动对焦之间切换。
[校正摄像头的方法](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