目录
关于需要下载的环境和具体的包参考【1】
记录标定过程:
一、IMU标定:
①录制imu的rosbag
rosbag record /JpImu -O imu.bag
②标定
roslaunch imu_utils myimu.launch
rosbag play -r 200 imu.bag
#myimu.launch中的内容
<launch>
<node pkg="imu_utils" type="imu_an" name="imu_an" output="screen">
<param name="imu_topic" type="string" value= "/JpImu"/> #需要修改话题
<param name="imu_name" type="string" value= "Jumper"/>
<param name="data_save_path" type="string" value= "$(find imu_utils)/data/"/>
<param name="max_time_min" type="int" value= "120"/> #录制的rosbag需要大于120分钟
<param name="max_cluster" type="int" value= "100"/> #频率?
</node>
</launch>
单位问题:
①连续时间
②离散时间
parameter | symbol | units |
gyr_n | ||
acc_n | ||
gyr_w | ||
acc_w |
对于离散时间的白噪声 = 连续时间的白噪声 * 频率的平方根
对于离散时间的随机游走 = 连续时间的随机游走 / 频率的平方根
结果分析:
使用imu_utils得到的白噪声(white_noise)和随机游走(random_walk)单位有问题,这些参数实际上是离散时间的,但认为是连续时间的。 (参考【2】中matrin的回复)。这位大佬也在github开源了他修改后的代码。(imu_utils修改)
kalibr联合标定imu参数应该是连续时间的(根据下面结果得到的结论,对连续白噪声乘根号频率得到离散的白噪声)
之后使用kalibr_allan又标定了一次imu的内参,根据单位得到是连续时间的结果。
对比两个方法结果:
acc_n | acc_w | gyr_n | gyr_w | |
imu_utils | 1.37e-3 | 2.86e-5 | 8.96e-5 | 9.36e-6 |
kalibr_allan | 1.85e-3 | 5.95e-5 | 1.02e-5 | 1.57e-8 |
这两个结果后续都使用kalibr进行过联合标定,得到的相机到imu的外参矩阵中的旋转和平移估计的差不多。
参考kalibr中wiki的介绍,使用vins的时候需要对imu参数扩大10倍甚至更多。
二、相机标定
①相机标定录制rosbag前需要降低图像帧率
将<intopic>上的消息到指定的频率
rosrun topic_tools throttle messages <intopic> <msgs_per_sec> [outtopic]
# intopic: 订阅的话题
# msgs_per_sec: 频率,每秒允许通过的最大消息数
# outtopic: throttle节点发布的话题名,可以省略,默认为intopic_throttle
rosrun topic_tools throttle messages /JpImage 4.0 /jpimage
②录制相机的rosbag
rosbag record /jpimage -O camera.bag
标定板选用aprilgrid
③相机标定
rosrun kalibr kalibr_calibrate_cameras --bag cam.bag --topics /jpimage --models pinhole-radtan --target apriltag.yaml --show-extraction
###############
--bag后面是录制的数据包的路径;
--topics后面是待标定的话题数据(已经控制频率后的);
--models后面是相机/畸变模型,有几目相机就要写几个,这里是两个针孔模型相机,所以是两个pinhole-radtan;相应地,其他支持的模型可以查看https://github.com/ethz-asl/kalibr/wiki/supported-models。
--target后面是标定板参数文件的路径;
--show-extraction是在标定过程中的一个显示界面,可以看到图片提取的过程,可以不要;
--bag-from-to后面是想要使用数据时间段的起始时间和结束时间,单位:秒(s),这个参数可以剔除掉刚开始录制和结束时一些出入视野等画面。
④相机标定结果
cam-report-cam.pdf
包含绘制的图片和标定的参数。cam-results-cam.txt
以文本文件储存的标定结果。cam-camchain.yaml
以YAML格式储存的标定结果。它可以直接用来作为相机-IMU校正的输入。
相机标定也可以使用ROS自带的camera_calibration进行标定
三、联合标定
相机-IMU联合标定总共需要准备好4个文件,分别是包含标定相机和IMU数据的rosbag,IMU内参yaml,相机内外参yaml,标定板yaml.
①录制相机和imu的rosbag
注意:
- 录制数据包时,充分激励IMU在三轴平移和三轴旋转上的运动;
- 尽可能减少震动,尤其是在拿起和放下传感器时(使用参数--bag-from-to指定数据包使用的时间,但在过程中依然要减少传感器的震动)
- 通过保持较低的快门时间和良好的照明等来尽量减少图片的运动模糊。
rosbag record /JpImage /JpImu -O cam-imu.bag
②IMU内参yaml、相机内外参yaml、标定板yaml
1)联合标定中imu内参yaml格式如下(imu.yaml)
#Accelerometers
accelerometer_noise_density: 0.00184825 #Noise density (continuous-time)
accelerometer_random_walk: 0.00005951 #Bias random walk
#Gyroscopes
gyroscope_noise_density: 0.00001015 #Noise density (continuous-time)
gyroscope_random_walk: 0.00000002 #Bias random walk
rostopic: /JpImu #the IMU ROS topic
update_rate: 100.0 #Hz (for discretization of the values above)
2)相机内外参yaml用之前得到的cam-camchain.yaml
3) 标定板yaml apriltag.yaml
③联合标定
rosrun kalibr kalibr_calibrate_imu_camera --target apriltag.yaml --cam cam-camchain.yaml --imu imu.yaml --bag cam_imu.bag --bag-from-to 5 85 --show-extraction --max-iter 15 --timeoffset-padding 0.1
######
--target后面是标定板路径;
--cam后面相机内外参路径;
--imu后面是对应格式的imu内参路径;
--bag后面是录制的数据包路径;
--bag-from-to后面是想要使用数据时间段的起始时间和结束时间,单位:秒(s)
--show-extraction是在标定过程中的一个显示界面,可以看到图片提取的过程,可以不要。
--max-iter 15 设置优化迭代次数为15次,默认30.
④结果
Calibration results
===================
Normalized Residuals
----------------------------
Reprojection error (cam0): mean 0.390286482254, median 0.317746394015, std: 0.300230148191
Gyroscope error (imu0): mean 32.6522783268, median 23.0843301194, std: 31.6409904226
Accelerometer error (imu0): mean 0.8012206628, median 0.710658698229, std: 0.476728405819
Residuals
----------------------------
Reprojection error (cam0) [px]: mean 0.390286482254, median 0.317746394015, std: 0.300230148191
Gyroscope error (imu0) [rad/s]: mean 0.00331420625017, median 0.00234305950712, std: 0.0032115605279
Accelerometer error (imu0) [m/s^2]: mean 0.0148085609002, median 0.01313474939, std: 0.00881113276055
Transformation (cam0):
-----------------------
T_ci: (imu0 to cam0):
[[-0.06307385 -0.99792457 0.01297083 -0.01153176]
[-0.00327611 -0.0127896 -0.99991284 -0.10529782]
[ 0.99800349 -0.06311084 -0.00246262 -0.0980539 ]
[ 0. 0. 0. 1. ]]
T_ic: (cam0 to imu0):
[[-0.06307385 -0.00327611 0.99800349 0.09678581]
[-0.99792457 -0.0127896 -0.06311084 -0.0190428 ]
[ 0.01297083 -0.99991284 -0.00246262 -0.10538053]
[ 0. 0. 0. 1. ]]
timeshift cam0 to imu0: [s] (t_imu = t_cam + shift)
-0.0425947143499
Gravity vector in target coords: [m/s^2]
[ 9.76501268 -0.08904055 -0.89723018]
Calibration configuration
=========================
cam0
-----
Camera model: pinhole
Focal length: [954.75292, 1072.76737]
Principal point: [306.50129, 259.28774]
Distortion model: radtan
Distortion coefficients: [-0.081587, 0.118449, 0.002166, -0.003205]
Type: aprilgrid
Tags:
Rows: 6
Cols: 6
Size: 0.024 [m]
Spacing 0.0072 [m]
IMU configuration
=================
IMU0:
----------------------------
Model: calibrated
Update rate: 100.0
Accelerometer:
Noise density: 0.00184825
Noise density (discrete): 0.0184825
Random walk: 5.951e-05
Gyroscope:
Noise density: 1.015e-05
Noise density (discrete): 0.0001015
Random walk: 2e-08
T_ib (imu0 to imu0)
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
[ 0. 0. 1. 0.]
[ 0. 0. 0. 1.]]
time offset with respect to IMU0: 0.0 [s]
踩坑记录:
1.确定imu的坐标系
在rostopic echo /话题 中观察imu加速度x、y、z轴值。如果imu静止的时候acc_z值为9.8,说明z轴向上,因为 a是实际的加速度值,a_m是imu的测量值,静止的时候a= 0, a_m = -g = 9.8。 同理, 哪个轴朝上观察加速度计哪个轴输出值是9.8,就可以确定这个轴。我使用的imu坐标系前左上分别为x、y和z。角速度按右手定则旋转后观察正负,imu角速度单位是rad/s,为了观察变化可以修改为°/s观察更直观。
2.确定了相机和imu坐标系可以估计相机到imu的旋转矩阵。
相机的x轴旋转后变成了之前z轴的正方向,y轴旋转后变成了之前x轴的负方向,z轴旋转后变成了之前y轴的负方向。
3.估计的旋转矩阵和标定结果差不多,但是平移非常小。这个问题困扰了很久,之后换了另一个imu后解决了。(两个imu同一个型号,但很玄学有一个就是不能使用...)