前言
有两种方式进行kalibr标定。一种是编译好的kelibr-cde,另一种是源码编译,使用rosrun运行。我推荐源码安装方式。
一. kalibr-cde方式
想使用kalibr-cde见如下过程
软件
我使用了Kalibr-cde软件,先进入kalibr-cde
的目录,再执行如下命令。
多相机标定
参考网页:Multi camera calibration
参考命令
./kalibr_calibrate_cameras --bag /media/wzy/EB5E-C002/SLAM/bag/cam3_imu_calib_2022-08-19-18-12-46.bag --topics /camera3/camera/infra1/image_rect_raw /camera3/camera/infra2/image_rect_raw --models pinhole-equi pinhole-equi --target dynamic/april_6x6_80x80cm.yaml
相机与IMU标定
参考网页:Camera IMU calibration
参考命令
./kalibr_calibrate_imu_camera --bag dynamic/camera4-infra12-imu-2022-07-18-09-37-41.bag --cam dynamic/camchain-camera4-infra12-2022-07-18-09-37-41.yaml --imu dynamic/camera4_imu.yaml --target dynamic/april_6x6_80x80cm.yaml --bag-from-to 8 70
二. 源码编译方式
网上一般的方式都是源码编译,首先git clone到ros工作空间下,然后catkin_make。以下链接可以参考。
链接:使用kalibr标定流程非常详细
我直接给出我的编译指令,供参考
2.1 先采集数据
运动方式是相机正对二维码, 沿x y z轴向平移3次,再绕x y z轴来回转动3次,最后随机运动一下。(我看YouTube是这样,但每次标定出来,像素投影误差都有1~2个像素,没有官方给出的那么好。)
rosbag record /imu/data /camera5/camera/infra1/image_rect_raw /camera5/camera/infra2/image_rect_raw /camera5/camera/infra1/camera_info /infra1/image_rect_raw /camera5/camera/infra1/image_rect_raw /camera5/camera/infra2/camera_info -o cam5_cams_imu_calib
2.2 运行两个相机镜头标定
这里需要预先准备../april_6x6_80x80cm.yaml
文件,需要用A0大小打印出来,文件内容如下:
target_type: 'aprilgrid'
tagCols: 6
tagRows: 6
tagSize: 0.088
tagSpacing: 0.264
codeOffset: 0
然后运行下面命令
$ rosrun kalibr kalibr_calibrate_cameras --bag ~/rosbag/kalibr_bag/cam5_cams_imu_calib_2022-12-04-11-23-38.bag --topics /camera5/camera/infra1/image_rect_raw /camera5/camera/infra2/image_rect_raw --models pinhole-radtan pinhole-radtan --target ../april_6x6_80x80cm.yaml --bag-from-to 5 115 --approx-sync 0.06
我用的D455相机的两个红外镜头。一般得到的标定结果和D455原厂标定结果有些许差别,我一般信任原厂,所以如果标定结果差别不大,就手动改一改标定的内参,取当次标定和原厂数值的平均值更为可靠。得到如下结果。
cam5_cams_imu_calib_camchain_mean.yaml
文件:
cam0:
cam_overlaps: [1]
camera_model: pinhole
distortion_coeffs: [-0.0006436511438276515, -0.01165348200528119, 0.0019951321118770325, -0.0007110618480805931]
distortion_model: radtan
intrinsics: [387.1605481551291, 387.84054907181496, 313.4358013166151, 243.71198013921006]
resolution: [640, 480]
rostopic: /camera5/camera/infra1/image_rect_raw
cam1:
T_cn_cnm1:
- [0.9999914754079172, 0.0025116449302754144, -0.003277308535519918, -0.09558105539360899]
- [-0.0024762063385359804, 0.999938904212508, 0.010772940381051388, 0.006515065205643839]
- [0.0033041661068663195, -0.010764733253960138, 0.9999365994923405, -0.007410902436475767]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [0]
camera_model: pinhole
distortion_coeffs: [-0.007400396837104382, -0.005671860746890236, -0.0034262073549618543, -0.0009614868304447853]
distortion_model: radtan
intrinsics: [387.8555715413133, 387.8953278983378, 314.73981903087537, 241.981461]
resolution: [640, 480]
rostopic: /camera5/camera/infra2/image_rect_raw
解释一下T_cn_cnm1:
含义,cam0
在cam1
图像坐标系下的位姿。由于图像坐标系是:x右,y下,z前。那么4x4矩阵最后一列,t_x = -0.0955 , t_y = 0.0065, t_z = -0.0074
表示cam0
在cam1
的右边-0.095m,也就是左边0.095m,正好是D455的双目基线长度。y和z几乎为0。因为双目镜头位置在这两个方向几乎一样。
2.3 将imu与两个相机镜头标定
需要预先准备cam5_cams_imu_calib_camchain_mean.yaml
(这个2.2步骤是两个镜头标定输出的参数文件)。另一个需要cam5_imu.yaml
(这个文件一般是Allan标定的结果,通过IMU静置2小时,然后分析误差,我试过,但后面懒,直接手动给噪声参数了,而且手持IMU噪声和装在飞机上时IMU振动时噪声又不一样,所以感觉没必要静置标定。如下所示)
rostopic: /imu/data
update_rate: 200.0
accelerometer_noise_density: 0.01
accelerometer_random_walk: 0.0002
gyroscope_noise_density: 0.005
gyroscope_random_walk: 4.0e-06
然后运行
$ rosrun kalibr kalibr_calibrate_imu_camera --bag ~/rosbag/kalibr_bag/cam5_cams_imu_calib_2022-12-04-13-40-59.bag --cam camera5/cam5_cams_imu_calib_camchain_mean.yaml --imu camera5/cam5_imu.yaml --target ../april_6x6_80x80cm.yaml --bag-from-to 5 85
得到结果如下:
%YAML:1.0
cam0:
T_cam_imu:
- [0.005396026321574626, -0.9999262748511594, 0.01087785650850831, 0.02]
- [-0.06457685627174603, -0.011203751804069656, -0.997849841198349, -0.02]
- [0.9978981473747679, 0.004681966231790791, -0.06463255107304097, 0.01]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [1]
camera_model: pinhole
distortion_coeffs: [-0.0006436511438276515, -0.01165348200528119, 0.0019951321118770325, -0.0007110618480805931]
distortion_model: radtan
intrinsics: [387.1605481551291, 387.84054907181496, 313.4358013166151, 243.71198013921006]
resolution: [640, 480]
rostopic: /camera5/camera/infra1/image_rect_raw
timeshift_cam_imu: -0.029391262854232037
cam1:
T_cam_imu:
- [0.0019633660730125624, -0.9999612349818692, 0.008583340095701053, -0.07]
- [-0.05383597532440887, -0.008676604979094116, -0.9985120952131259, -0.02]
- [0.9985478621250626, 0.001498352285640936, -0.053850923723694155, 0.01]
- [0.0, 0.0, 0.0, 1.0]
T_cn_cnm1:
- [0.9999914754079181, 0.0025116449302754144, -0.003277308535519918, -0.095]
- [-0.0024762063385359804, 0.9999389042125089, 0.010772940381051388, 0.00]
- [0.0033041661068663195, -0.010764733253960138, 0.9999365994923414, 0.00]
- [0.0, 0.0, 0.0, 1.0]
cam_overlaps: [0]
camera_model: pinhole
distortion_coeffs: [-0.007400396837104382, -0.005671860746890236, -0.0034262073549618543, -0.0009614868304447853]
distortion_model: radtan
intrinsics: [387.8555715413133, 387.8953278983378, 314.73981903087537, 241.981461]
resolution: [640, 480]
rostopic: /camera5/camera/infra2/image_rect_raw
timeshift_cam_imu: -0.019921372808489393
注意文件开头的 %YAML:1.0
是我标定结果出来以后手动添加的。还有一些缩进也是我后来手动调整的。kalibr给出的yaml文件格式原本这些都没有。
解释一下矩阵含义,在cam0
坐标系下,imu
的位姿。依旧按照图像坐标系(x右,y下,z前)来看。imu
位于相机右边0.02m,下方-0.02m,前方0.01m。旋转矩阵R看作,imu
的xyz在cam0
的xyz下的表示,即[x_cam,y_cam,z_cam]’ = R * [x_imu,y_imu,z_imu]
cam0:
T_cam_imu:
- [0.005396026321574626, -0.9999262748511594, 0.01087785650850831, 0.02]
- [-0.06457685627174603, -0.011203751804069656, -0.997849841198349, -0.02]
- [0.9978981473747679, 0.004681966231790791, -0.06463255107304097, 0.01]
- [0.0, 0.0, 0.0, 1.0]
可以看出矩阵最后一列是我手动填写的。因为kalibr在标定效果不好时,结果非常差。不如手动给,一般在跑SLAM算法时,都有实时标定外参,所以给一个基本正确的初值就可以了。
同理,下面是在cam1
坐标系下,imu
的位姿
cam1:
T_cam_imu:
- [0.0019633660730125624, -0.9999612349818692, 0.008583340095701053, -0.07]
- [-0.05383597532440887, -0.008676604979094116, -0.9985120952131259, -0.02]
- [0.9985478621250626, 0.001498352285640936, -0.053850923723694155, 0.01]
- [0.0, 0.0, 0.0, 1.0]
同理,下面是在cam1
坐标系下,cam0
的位姿
T_cn_cnm1:
- [0.9999914754079181, 0.0025116449302754144, -0.003277308535519918, -0.095]
- [-0.0024762063385359804, 0.9999389042125089, 0.010772940381051388, 0.00]
- [0.0033041661068663195, -0.010764733253960138, 0.9999365994923414, 0.00]
- [0.0, 0.0, 0.0, 1.0]
三.下面是一些我遇到的报错
安装报错1:关于SuiteSparse
链接:参考链接
具体操作我参考了链接:更改cmakelist文件
虽然可以成功下载,但是包的名字有后缀,导致后面找不到文件路径,参考链接:修改文件夹名称,见文章末尾
运行报错1:python-igraph
这个错误一般是标定多个相机时候,运行如下命令时
kalibr_calibrate_cameras --bag stereo_calib_20hz.bag --topic /infra1 /infra2 --models pinhole-equi pinhole-equi --target april_6x6.yaml
调用了一个python库叫igraph
如果直接使用sudo pip install python-graph
会安装最新的版本0.9.1,但是我的ubuntu18.04会报错(可能是python2.7的原因)。
于是下载0.8.3版本就没问题
命令sudo pip install python-graph==0.8.3
运行报错2:相机图像不同步
Cameras are not connected through mutual observations, please check the dataset. Maybe adjust the approx. sync. tolerance.
原因是两个相机不同步,既可以提高采集频率到20hz,也可以同时增加同步忍耐度 --bag-from-to 5 35 --approx-sync 0.04
,
完整参数如下:
kalibr_calibrate_cameras --bag stereo_calib_20hz.bag --topic /infra1 /infra2 --models pinhole-equi pinhole-equi --target april_6x6.yaml --bag-from-to 5 35 --approx-sync 0.04
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)