0 概述
硬件:Realsense D435i(含imu)、AprilTag或棋盘格标定板(本文均使用棋盘格)
说明:本文非手把手教你如何教程,需要一定的ROS基础和D435i相机调试基础,当然玩过其他相机也可以。写作过程参考了部分作者成果,如有侵权,请联系删除。
标定主要包括四部分内容:
- 为什么要做相机标定
- 利用Kalibr对D435i进行相机标定、相机-imu标定
- 利用opencv对D435i的RGB相机进行内参标定(Opencv也可实现)
- 利用opencv对D435i的RGB进行外参标定(单目测距的基础)
1 为什么要做相机标定?
这里涉及四个坐标系世界坐标系、相机坐标系、图像物理坐标系、图像像素坐标系,在由世界坐标系变换到像素坐标系的过程,就涉及到这四个坐标系的变换,具体如下:
世界坐标系与相机坐标系之间的变换
相机坐标系与图像物理坐标系之间的变换
图像物理坐标系与图像像素坐标系之间的变换
通过上述变换,可得物理世界坐标系与图像像素坐标系之间的变换公式如下:
坐标变换总图
2 Kalibr相机标定
ROS 录制bag包
roslaunch realsense2_camera rs_camera.launch
可视化单目影像
这个仅作为摄像头的图像查看,不用这个也不影响标定
rqt_image_view
影像 topic 重新发布(修改发布频率)
使用ros自带的topic_tools工具即可,这个工具很给力,有空看看它的源代码写法,自己原先写过一个类似功能的,结果问题不少。
rosrun topic_tools throttle messages /camera/color/image_raw 4.0 /image_raw
后面三个参数为:源话题名称, 重新发布频率, 重新发布的话题名称
影像包录制
rosbag record /image_raw
标定板和相机相对运动方式:绕x y z轴旋转三次、平移三次。Ctrl+c停止录制后,可使用如下命令查看包信息,尤其关注下时间长度,因为后面标定的时候最好设定下起止时间,
rosbag info 包名称
配置Kalibr标定板参数
这里需要特别注意两点:
- 标定板的类型不同,配置文件也不同,此处使用棋盘格(可以正常使用),aprilgrid的配置没测试
- 这里的8和6是内部角点的数量,也就是四个方块的交点,标定板最外侧那种两块交点不算
checkerboard.yaml文件如下:
# example for checkerboard
target_type: 'checkerboard'
targetCols: 8
targetRows: 6
rowSpacingMeters: 0.055
colSpacingMeters: 0.055 # size of the one chessboard square [m]
# example for aprilgrid
target_type: 'aprilgrid'
tagCols: 8
tagRows: 6
tagSize: 0.055
tagSpacing: 0.3 # 这个参数不太清楚
启动Kalibr进行相机标定
注意更换为自己的配置文件名、Topic名等,
kalibr_calibrate_cameras --target checkerboard.yaml --bag 录制包名称.bag --bag-from-to 5 98 --models pinhole-radtan --topics /image_raw
- 这里的 5 98 是使用录制包的起止时间(秒为单位)
- 如果卡住了,在后面加上 --show-extraction --approx-sync 0.04
- 如果上面还不行,使用终极解决办法:找到src/Kalibr/aslam_offline_calibration/kalibr/python/kalibr_calibrate_cameras中的如下代码,然后注释掉
if not graph.isGraphConnected():
obsdb.printTable()
print "Cameras are not connected through mutual observations, please check the dataset. Maybe adjust the approx. sync. tolerance."
graph.plotGraph()
sys.exit(-1)
结果会生成三个文件,重点关注yaml文件
3 相机-IMU标定
很多步骤和上面一致就不细说,只列出有这个步骤
启动相机Realsense节点
启动前要打开 rs_camera.launch 这个文件,确保“enable_gyro”和“enable_accel”均设置为True
可视化相机影像
相机与IMU的Topic重新发布
rosrun topic_tools throttle messages /camera/color/image_raw 20.0 /image_raw
rosrun topic_tools throttle messages /camera/accel/samples 200.0 /imu
- 有的可能是/camera/accel/sample,也就是后面不是samples
- 千万注意 imu对应的topic是/camera/accel/samples,陀螺仪对应的是/camera/gyro/samples,不要搞混了
相机与IMU包录制
rosbag record /image_raw /imu
配置Kalibr标定板,相机和IMU参数
这里需要三个文件:
- 描述标定板信息的yaml文件,见上面的checkerboard.yaml文件
- 描述相机内参的文件 camchain-xxx.yaml (上一步标定生成文件)
- IMU的参数文件(主要包含噪声密度和随机游走),有的参数根据具体传感器修改下,D435i的参数示例如下
imu.yaml文件内容如下:
#Accelerometers
accelerometer_noise_density: 2.64e-02 #Noise density (continuous-time)
accelerometer_random_walk: 7.21e-04 #Bias random walk
#Gyroscopes
gyroscope_noise_density: 3.18e-03 #Noise density (continuous-time)
gyroscope_random_walk: 3.07e-05 #Bias random walk
rostopic: /imu #the IMU ROS topic
update_rate: 200.0 #Hz (for discretization of the values above)
启动Kalibr进行相机标定
kalibr_calibrate_imu_camera --target 标定板位置/标定板名称.yaml --cam 相机标定位置/相机标定名称.yaml --imu imu.yaml --bag 录制包名称.bag --bag-from-to 5 98 --show-extraction
标定完成后,会得到四个文件,重点看camchain-imu和results-imucam,表示的都是相机和IMU之间的变换关系
4 相机标定之Matlab和Opencv——内参标定
4.1 Matlab标定内外参数
- 2016a版本的matlab中 Camera_Calibrator 界面跟以前不太一样了,有的图像可能无法使用,也就是无法add进去
- 注意标定后直接把外参也就是R T也输出了,特别注意这里旋转矩阵和平移向量是相机坐标系在世界坐标系的描述
- 重投影误差一般在0.5个pixel之内
- matlab求得的内参矩阵与opencv求得的内参矩阵是转置关系
标定后的结果(含重投影误差和相机图像相对位置示意图)
生成的标定结构体数据(标定结果都在这里)
5 单目测距
这里用到opencv的外参标定
有几点需要特别注意的:
- 这里标定的外参就是棋盘格相对相机的姿态,即求出这张棋盘格的外参,也就是最上面相机成像模型中的R T
- 在由像素到世界坐标的变换中,注意最后的方程式求解是求解线性方程组,通过 u和v求解在棋盘格定义的世界坐标系下的x y z(这里z=0)
整个过程折腾了我一天多,主要问题出在两个地方:
- 外参标定的RT结果到底是哪个相对于哪个坐标系的变换
- 在求像素到棋盘格定义的世界坐标系的过程中,变换出错(把u v错代入x y直接计算Zc),错误计算如下:
原理公式如下: