ROS2与Navigation2入门教程-使用ROS2进行相机标定
说明:
- 介绍如何使用ROS2进行相机标定
概述
- 相机(摄像头)是一种非常精密的光学仪器,对外界环境的感知非常敏感。
- 由于摄像头内部和外部的一些原因,摄像头采集的图像常常会发生一定的畸变。
- 如果直接将采集到的图像拿来进行图像处理,会产生很大的问题。
- 为了避免图像数据源造成的误差,需要对摄像头的相关参数进行标定。
- 本教程将会说明如何标定单目(monocular)相机,从而获取单目相机的标定参数。
要求
- 使用操作系统的软件包管理器apt安装相机标定需要用到的以下软件包,命令如下:
sudo apt install ros-<ros2-distro>-camera-calibration-parsers
sudo apt install ros-<ros2-distro>-camera-info-manager
sudo apt install ros-<ros2-distro>-launch-testing-ament-cmake
- 需要在您的工作空间中从源代码构建Image Pipeline软件包,命令如下:
cd ~/dev_ws/src (根据您的工作空间更改成相应的目录)
git clone https://github.com/ros-perception/image_pipeline.git
cd image_pipeline
git checkout ros2
cd ~/dev_ws
colcon build --symlink-install --packages-select image_pipeline
如果您的工作空间中只有image_pipeline软件包,则可以不用--packages-select image_pipeline选项,即直接执行colcon build --symlink-install命令即可。
但如果您的工作空间有很多软件包,为节省时间和避免破坏已经构建好的软件包,则应该选择仅构建image_pipeline软件包。
实际上image_pipeline只是一个元软件包,真正起作用的是下面的这几个软件包:camera_calibration、depth_image_proc、image_proc、 image_publisher、image_rotate、image_view、stereo_image_proc。
如果在构建过程中出现错误,提示在您的系统上是否尚未构建camera_calibration、depth_image_proc、image_proc、 image_publisher、image_rotate、image_view、stereo_image_proc软件包,则需要先构建这些软件包.
命令为:
colcon build --packages-select camera_calibration depth_image_proc image_proc image_publisher image_rotate image_view stereo_image_proc
构建好这些软件包后再运行
colcon build --symlink-install --packages-select image_pipeline
命令就可以成功构建该软件包了。构建好image_pipeline软件包后,需要对该工作空间进行source。
为了避免每次打开终端时都需要设置环境,可以直接运行以下命令来一次性设置好运行环境:
echo “source ~/dev_ws/install/setup.bash” >> .bashrc
- 此外,标定相机还需要依赖其它一些软件包,可以执行以下命令以确保安装了这些软件包:
sudo apt install ros-foxy-vision-opencv ros-foxy-image-transport-plugins ros-foxy-image-transport ros-foxy-image-common
sudo apt install python3-polled-camera polled-camera-tool libpolled-camera0d
sudo apt install libtheora-dev libogg-dev libboost-python-dev
sudo apt-get install -y libssl-dev libusb-1.0-0-dev pkg-config libgtk-3-dev
sudo apt-get install -y libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev
- 如果您的机器上已经安装了这些软件包的最新版本,则会自动跳过,否则会安装这些软件包。
其它要求
还请确保您具备以下条件:
(1)一个已知尺寸的大棋盘。本教程使用的是200mm×200mm的正方形棋盘,用于相机定标需要7行×9列棋盘格。由于相机标定使用的是棋盘格的内部顶点,因此需要8行×10列的棋盘,这样使用内部顶点参数就正好是7行×9列,如下图所示。可以从这里下载具有设定尺寸的棋盘格PDF文件,然后打印出来备用。
(2)一个明亮的5m×5m区域,没有障碍物和棋盘图案。
(3)一个可以在ROS上发布图像的单目相机。
具体标定步骤
在GUI中打开一个终端。
为您的相机启动ROS驱动程序。
对于普通USB相机,需要一个节点把普通USB相机的影像流转换成ROS的话题(topic)发布出来,才能被标定工具使用。在ROS 1中该节点是usb_cam;但在ROS 2中该节点更改为v4l2_camera。
在ROS 2中,执行以下命令来启动待标定相机:
ros2 run v4l2_camera v4l2_camera_node --ros-args -p video_device:="/dev/video0" -p image_size:=[1280,720]
- 这样就会在终端中出现如下图所示的消息:
注意:此时会出现错误,提示找不到相机标定参数yaml文件,这是由于尚未标定该相机或者尚未将标定参数yaml文件复制到该目录中。
后面在完成相机标定并保存了标定结果后,就需要将相机标定参数yaml文件复制到该目录并修改成提示中的文件名。
如果不能成功地运行上一条命令,提示找不到v4l2_camera软件包,则需要手动安装该软件包,命令为:
sudo apt install ros-foxy-v4l2-camera
*提示:若您的ROS 2发行版不是Foxy,则需要把上一条命令中的“foxy”替换成您的具体发行版名称。
另外还注意到上条命令中的参数video_device:="/dev/video0",用于指定要启动的摄像头设备,即要启动和标定哪个相机,特别是如果您的机器上安装有多个相机的话。
如果机器上只有一部USB相机,则一般应该是/dev/video0。
为了验证这一点,需要执行以下操作:
列出机器上的所有相机(摄像头)设备,命令为:
ls /dev/video*
- 在笔者的机器上输出消息如下:
/dev/video0 /dev/video1
找出真正的摄像头设备。笔者的笔记本电脑上只有一个USB相机,到底哪个才是真正的摄像头?这就需要用到v4l2-utils软件包的v4l2-ctl命令。
首先执行命令sudo apt install v4l2-utils安装该软件包,然后再对上面列出的2个摄像头设备的驱动程序信息进行查询,命令分别为
v4l2-ctl -d /dev/video0 --all和v4l2-ctl -d /dev/video1 --all。
- 这样,/dev/video0的驱动程序信息输出结果如下所示:
Driver Info:
Driver name : uvcvideo
Card type : Integrated_Webcam_HD: Integrate
Bus info : usb-0000:00:14.0-11
Driver version : 5.8.18
Capabilities : 0x84a00001
Video Capture
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Extended Pix Format
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
Width/Height : 1280/720
Pixel Format : 'YUYV' (YUYV 4:2:2)
Field : None
Bytes per Line : 2560
Size Image : 1843200
Colorspace : sRGB
Transfer Function : Default (maps to sRGB)
YCbCr/HSV Encoding: Default (maps to ITU-R 601)
Quantization : Default (maps to Limited Range)
Flags :
Crop Capability Video Capture:
Bounds : Left 0, Top 0, Width 1280, Height 720
Default : Left 0, Top 0, Width 1280, Height 720
Pixel Aspect: 1/1
Selection Video Capture: crop_default, Left 0, Top 0, Width 1280, Height 720, Flags:
Selection Video Capture: crop_bounds, Left 0, Top 0, Width 1280, Height 720, Flags:
Streaming Parameters Video Capture:
Capabilities : timeperframe
Frames per second: 10.000 (10/1)
Read buffers : 0
(省略部分内容)
- 而/dev/video1的驱动程序信息输出结果为:
Driver Info:
Driver name : uvcvideo
Card type : Integrated_Webcam_HD: Integrate
Bus info : usb-0000:00:14.0-11
Driver version : 5.8.18
Capabilities : 0x84a00001
Video Capture
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04a00000
Metadata Capture
Streaming
Extended Pix Format
Priority: 2
Format Metadata Capture:
Sample Format : 'UVCH' (UVC Payload Header Metadata)
Buffer Size : 1024
其中/dev/video0的驱动程序信息中出现了Video input : 0 (Camera 1: ok)这一行,而/dev/video1的则没有这行,表明/dev/video0才是真正的USB相机。
确保待标定的相机可以在ROS上发布图像。
为此,在待标定单目相机ROS驱动程序正在另一个终端中启动运行的情况下,在一个新的终端中执行以下命令:
ros2 topic list
- 这样在该终端中应该就会输出如下消息:
/camera_info
/image_raw
/image_raw/compressed
/image_raw/compressedDepth
/image_raw/theora
/parameter_events
/rosout
可以看到您的系统正在发布image_raw等多个与摄像头相关的ROS话题。
为了确认image_raw话题是一个真实的话题且实际上正在发布图像,需要检查该话题的发布频率,命令为:
ros2 topic hz /image_raw
- 这样终端中应该就会不断输出如下所示的消息:
average rate: 10.035
min: 0.096s max: 0.100s std dev: 0.00114s window: 12
average rate: 10.019
min: 0.096s max: 0.100s std dev: 0.00084s window: 23
average rate: 10.024
min: 0.096s max: 0.100s std dev: 0.00096s window: 34
average rate: 10.028
min: 0.096s max: 0.100s std dev: 0.00100s window: 45
average rate: 10.022
min: 0.096s max: 0.100s std dev: 0.00091s window: 55
average rate: 10.025
min: 0.096s max: 0.100s std dev: 0.00096s window: 66
从输出消息中可以看出,该相机确实正在发布图像,且其图像发布频率平均约为10帧/秒。
启动相机标定节点,命令为:
ros2 run camera_calibration cameracalibrator --size 7x9 --square 0.015 --ros-args --remap /image:=/image_raw --ros-args --remap camera:=/custom_camera
这条命令中需要注意以下三个容易出错的地方:
棋盘格行列数即--size参数,7x9不能写成7*9或者7×9,那个乘号必须写成小写字母x,否则会出错;
棋盘格的格子大小即--square参数,应该是每个正方形格子的边长,单位为m,本例中用的格子边长为15mm,因此该参数应该为0.015,而不是英语原文教程中的0.2m;
指定相机名和话题名时应该使用新的语法,即采用--ros-args --remap选项来重映射图像话题名称和相机名称,否则会提示警告消息,但这并不会影响该命令的执行,而更重要的是重映射前后的话题名称/image和/image_raw以及相机名称camera和/custom_camera不能写错,而且等号前必须有冒号(:),否则该命令无法成功运行。
输入命令正确的话,应该就会成功地输出如下消息:
Waiting for service camera/set_camera_info ...
OK
Waiting for service left_camera/set_camera_info ...
OK
Waiting for service right_camera/set_camera_info ...
OK
- 然后就会弹出一个带有摄像头视频的窗口,如下图所示。
为了更好地标定相机,需要在相机视野范围内不断移动棋盘格和变换位置(先拿着打印好的棋盘格纸张置于摄像头前并适当歪斜,当视频窗口中的棋盘格上出现彩色线条时,就可以缓慢地上下左右平移棋盘格、让棋盘格远离和接近摄像头、旋转和倾斜棋盘格等),以便达到以下效果:
让棋盘格出现在相机视场或视野(FOV,field of view)的左、右、上、下不同部位
X条——相机视野中的左/右方向
Y条——相机视野的上/下方向
尺寸条——接近/远离相机和相对于相机进行倾斜
让棋盘格填满整个视野
让棋盘格向左、右、上、下倾斜(歪斜Skew)
随着棋盘格的不断移动,标定窗口侧边栏上的4个横条的长度会不断增长。而在终端窗口中,则会出现如下图所示的图像样本采集情况的消息输出。
当所有4个横条都变成绿色并且有足够的数据可用于标定时(笔者标定测验时系统采集了42幅图像时4个横条全部变成了绿色),“标定(CALIBRATE)”按钮将会变亮。单击它以执行相机标定。
标定大约需要花一分钟时间。
- 完成标定后,“保存(SAVE)”按钮和“提交(COMMIT)”按钮都会变亮。而且在终端中也可以看到相机标定的各个参数。
按下“保存”按钮来保存相机标定结果。相机标定数据会保存在/tmp/calibrationdata.tar.gz文件中
要使用该相机标定结果文件,请执行以下命令解压缩该文件:
tar -xvf calibration.tar.gz
在标定结果文件夹中,可以看到系统采集的用于标定的所有图像以及ost.yaml和ost.txt文件(如下图所示)。
在启动相机驱动程序时会使用这个包含校准参数的yaml文件
- 为了让相机ROS 2启动程序能够找到该yaml文件,需要把这个ost.yaml文件复制到~/.ros/camera_info/目录下,并将文件名修改为integrated_webcam_hd:_integrate.yaml(具体路径和文件名可能在不同机器上会不相同,需要查看运行v4l2_camera节点启动相机时那条找不到相机标定参数yaml文件的错误消息,该错误消息中包含了相机驱动程序会寻找的标定参数yaml文件的相应路径和文件名)。
参考资料
- Navigation2普通教程系列中的“相机标定”教程,其英语原文网址
- 古月居网站上机器视觉专栏文章“在ROS平台上标定普通摄像头与Kinect摄像头”
- ChinaUnix博客文章“ROS2 摄像头校准”
- CSDN博客文章“ubuntu20.04如何识别到连接的摄像头?”
- OS2 Image Pipeline Tutorial: How to create Point Clouds using two USB cameras
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号