allen方差工具:
https://github.com/gaowenliang/imu_utils
在这题中我一共进行了三次实验,三次实验中加速度计以及陀螺仪的高斯白噪声和Bias随机游走噪声的大小是成等比例(比例为10)进行放大和缩小,下面先摆出实验结果然后分析实验数据
a. 参数设置
此参数设置在vio_data_simulation-ros_version/src/param.h中,分别是加速度计以及陀螺仪的高斯白噪声和Bias随机游走噪声的大小
double gyro_bias_sigma = 0.000005;
double acc_bias_sigma = 0.00005;
double gyro_noise_sigma = 0.0015;
double acc_noise_sigma = 0.0019;
b. 仿真结果
以下是由vio_data_simulation-master/main/gener_alldata.cpp生成数据,由vio_data_simulation-master/python-tool/draw_trajcory.py生成
c. 利用仿真工具画allen曲线并获得噪声估计结果
allen曲线为(这里是在静止的情况下测量的,另外抱歉这里有点看不清,纵坐标从上到下分别是 1 0 4 , 1 0 3 . 1 0 2 , 1 0 1 10^4,10^3.10^2,10^1 104,103.102,101):
Gyr:
unit: " rad/s"
avg-axis:
gyr_n: 2.1016644346403605e-02
gyr_w: 1.3328766989568059e-04
Acc:
unit: " m/s^2"
avg-axis:
acc_n: 2.6763958793439523e-02
acc_w: 4.6470131356570474e-04
a. 参数设置
此参数设置在vio_data_simulation-ros_version/src/param.h中,分别是加速度计以及陀螺仪的高斯白噪声和Bias随机游走噪声的大小
double gyro_bias_sigma = 0.00005;
double acc_bias_sigma = 0.0005;
double gyro_noise_sigma = 0.015;
double acc_noise_sigma = 0.019;
b. 仿真结果
以下是由vio_data_simulation-master/main/gener_alldata.cpp生成数据,由vio_data_simulation-master/python-tool/draw_trajcory.py生成
c. 利用仿真工具画allen曲线并获得噪声估计结果
allen曲线为(这里是在静止的情况下测量的,另外抱歉这里有点看不清,纵坐标从上到下分别是 1 0 5 , 1 0 4 , 1 0 3 . 1 0 2 10^5,10^4,10^3.10^2 105,104,103.102):
Gyr:
unit: " rad/s"
avg-axis:
gyr_n: 2.1426963216977588e-01
gyr_w: 1.0886455204925014e-03
Acc:
unit: " m/s^2"
avg-axis:
acc_n: 2.6881801136204303e-01
acc_w: 4.9716963622466080e-03
a. 参数设置
此参数设置在vio_data_simulation-ros_version/src/param.h中,分别是加速度计以及陀螺仪的高斯白噪声和Bias随机游走噪声的大小
double gyro_bias_sigma = 0.0005;
double acc_bias_sigma = 0.005;
double gyro_noise_sigma = 0.15;
double acc_noise_sigma = 0.19;
b. 仿真结果
以下是由vio_data_simulation-master/main/gener_alldata.cpp生成数据,由vio_data_simulation-master/python-tool/draw_trajcory.py生成
c. 利用仿真工具画allen曲线并获得噪声估计结果
allen曲线为(这里是在静止的情况下测量的,另外抱歉这里有点看不清,纵坐标从上到下分别是 1 0 6 , 1 0 5 , 1 0 4 , 1 0 3 10^6,10^5,10^4,10^3 106,105,104,103):
Gyr:
unit: " rad/s"
avg-axis:
gyr_n: 2.1370768874875155e+00
gyr_w: 4.8477797168896648e-03
Acc:
unit: " m/s^2"
avg-axis:
acc_n: 2.6832843026523694e+00
acc_w: 4.9509703964721895e-02
我上述实际噪声大小和标定结果汇总到下面表格中进行对比分析:
加速度计:
加速度计Bias随机游走大小 | 实际大小 | 标定结果 | 标定结果离散化后结果 |
---|---|---|---|
小噪声 | 0.0019 | 2.6763958793439523e-02 | 0.00188769 |
中噪声 | 0.019 | 2.6881801136204303e-01 | 0.0189476 |
大噪声 | 0.19 | 2.6832843026523694e+00 | 0.189476 |
加速度计高斯白噪声大小 | 实际大小 | 标定结果 | 标定结果离散化后结果 |
---|---|---|---|
小噪声 | 0.00005 | 4.6470131356570474e-04 | 0.0065728 |
中噪声 | 0.0005 | 4.9716963622466080e-03 | 0.0703209 |
大噪声 | 0.005 | 4.9509703964721895e-02 | 0.700268 |
陀螺仪:
陀螺仪Bias随机游走大小 | 实际大小 | 标定结果 | 标定结果离散化后结果 |
---|---|---|---|
小噪声 | 0.0015 | 2.1016644346403605e-02 | 0.001485407 |
中噪声 | 0.019 | 2.1426963216977588e-01 | 0.01514394 |
大噪声 | 0.19 | 2.1370768874875155e+00 | 0.1510859 |
陀螺仪高斯白噪声大小 | 实际大小 | 标定结果 | 标定结果离散化后结果 |
---|---|---|---|
小噪声 | 0.000005 | 1.3328766989568059e-04 | 0.001885148 |
中噪声 | 0.00005 | 1.0886455204925014e-03 | 0.01539801 |
大噪声 | 0.0005 | 4.8477797168896648e-03 | 0.06856817 |
这里对标定结果离散采用的公式是
高斯白噪声: σ d = σ 1 Δ t \sigma_{d}=\sigma \frac{1}{\sqrt{\Delta t}} σd=σΔt1Bias随机游走大小: σ b d = σ b Δ t \sigma_{b d}=\sigma_{b} \sqrt{\Delta t} σbd=σbΔt通过上面的对比可以发现,加速度计和陀螺仪的Bias随机游走大小allen方差的估计是较为准确的,但是高斯白噪声的估计却差了几个数量级,在陀螺仪大噪声的情况下还出现了一次数据较大的偏差,课程视频上贺博也解释了这种情况是正常的(大噪声情况下的数据偏差应该是不正常的),在实际的IMU使用中是对估计出来的白噪声进行等比例系数处理的。
代码如下:
MotionData next_imupose = imudata[i+1];
//delta_q = [1 , 1/2 * thetax , 1/2 * theta_y, 1/2 * theta_z]
Eigen::Quaterniond dq;
Eigen::Vector3d dtheta_half = (imupose.imu_gyro + last_imupose.imu_gyro) * dt / 4.0;
dq.w() = 1;
dq.x() = dtheta_half.x();
dq.y() = dtheta_half.y();
dq.z() = dtheta_half.z();
/// 中值积分
Qwb = last_Qwb * dq;
Eigen::Vector3d acc_w = 0.5*(last_Qwb*(last_imupose.imu_acc)+Qwb*(imupose.imu_acc)+2*gw);
Vw = Vw + acc_w * dt;
Pwb = Pwb + Vw * dt + 0.5 * dt * dt * acc_w;
last_Qwb = Qwb;
结果如下:
代码如下:
MotionData last_imupose = imudata[i-1];
//delta_q = [1 , 1/2 * thetax , 1/2 * theta_y, 1/2 * theta_z]
Eigen::Quaterniond dq;
Eigen::Vector3d dtheta_half = (imupose.imu_gyro + next_imupose.imu_gyro) * dt / 4.0;
dq.w() = 1;
dq.x() = dtheta_half.x();
dq.y() = dtheta_half.y();
dq.z() = dtheta_half.z();
/// 中值积分
Eigen::Vector3d acc_w = 0.5*(Qwb*(imupose.imu_acc)+Qwb*dq*(imupose.imu_acc)+2*gw);
Qwb = Qwb * dq;
Vw = Vw + acc_w * dt;
Pwb = Pwb + Vw * dt + 0.5 * dt * dt * acc_w;
结果如下:
这里我们通过对比欧拉积分的结果:
阅读论文《Spline Fusion: A continuous-time representation for visual-inertial fusion with application to rolling shutter cameras》总结推导过程如下:
k − 1 k-1 k−1阶的B次样条曲线如下: p ( t ) = ∑ i = 0 n p i B i , k ( t ) \mathbf{p}(t)=\sum_{i=0}^{n} \mathbf{p}_{i} B_{i, k}(t) p(t)=i=0∑npiBi,k(t)其中, p i ∈ R N \mathbf{p}_{i} \in \mathbb{R}^{N} pi∈RN是 t i , i ∈ [ 0 , … , n ] t_{i}, i \in[0, \dots, n] ti,i∈[0,…,n]时刻的控制点, B i , k ( t ) B_{i, k}(t) Bi,k(t)是基函数,如下 B i , 0 ( x ) : = { 1 if t i ≤ x < t i + 1 0 otherwise B_{i, 0}(x) :=\left\{\begin{array}{ll}{1} & {\text { if } \quad t_{i} \leq x
再本文中,主要研究的是四次累计B样条曲线,也就四说对于 t ∈ [ t i , t i + 1 ) t \in\left[t_{i}, t_{i+1}\right) t∈[ti,ti+1)这段时间中一共有 [ t i − 1 , t i , t i + 1 , t i + 2 ] \left[t_{i-1}, t_{i}, t_{i+1}, t_{i+2}\right] [ti−1,ti,ti+1,ti+2]四个控制点来确定时刻 t t t的样条曲线上的值,我们使用 s ( t ) = ( t − t 0 ) / Δ t s(t)=\left(t-t_{0}\right) / \Delta t s(t)=(t−t0)/Δt来表示平均时间的函数,那么控制点的时刻 t i t_i ti就可以由平均时间函数 s i ∈ [ 0 , 1 , … , n ] s_{i} \in[0,1, \ldots, n] si∈[0,1,…,n]来表示,对于时间 s i ≤ s ( t ) < s i + 1 s_{i} \leq s(t)
接下来就是将推导出来样条曲线应用到实际的惯性视觉数据上来
首先我们可以将一个空间点在两帧 a , b a,b a,b上的图像坐标表示为: p b = W ( p a ; T b , a , ρ ) = π ( [ K b ∣ 0 ] T b , a [ K a − 1 [ p a 1 ] ; ρ ] ) \mathbf{p}_{b}=\mathcal{W}\left(\mathbf{p}_{a} ; \mathbf{T}_{b, a}, \rho\right)=\pi\left(\left[\mathbf{K}_{b} | \mathbf{0}\right] \mathbf{T}_{b, a}\left[\mathbf{K}_{a}^{-1}\left[\begin{array}{c}{\mathbf{p}_{a}} \\ {1}\end{array}\right] ; \boldsymbol{\rho}\right]\right) pb=W(pa;Tb,a,ρ)=π([Kb∣0]Tb,a[Ka−1[pa1];ρ])其中 π ( P ) = 1 P 2 [ P 0 , P 1 ] ⊤ \pi(\mathbf{P})=\frac{1}{\mathbf{P}_{2}}\left[\mathbf{P}_{0}, \mathbf{P}_{1}\right]^{\top} π(P)=P21[P0,P1]⊤为归一化平面上坐标的投影方程, K a , K b ∈ R 3 × 3 \mathbf{K}_{a}, \mathbf{K}_{b} \in \mathbb{R}^{3 \times 3} Ka,Kb∈R3×3分别是两帧图像的内参,然后利用上面推导出来B样条曲线的公式,我们可以生成加速度计和陀螺仪的测量模型: Gyro ( u ) = R w , s ⊤ ( u ) ⋅ R ˙ w , s ( u ) + bias Accel ( u ) = R w , s ⊤ ( u ) ⋅ ( s w ( u ) + g w ) + bias \begin{aligned} \operatorname{Gyro}(u) &=\mathbf{R}_{w, s}^{\top}(u) \cdot \dot{\mathbf{R}}_{w, s}(u)+\text { bias } \\ \operatorname{Accel}(u) &=\mathbf{R}_{w, s}^{\top}(u) \cdot\left(\mathbf{s}_{w}(u)+g_{w}\right)+\text { bias } \end{aligned} Gyro(u)Accel(u)=Rw,s⊤(u)⋅R˙w,s(u)+ bias =Rw,s⊤(u)⋅(sw(u)+gw)+ bias 其中角速度 R ˙ w , s \dot{\mathbf{R}}_{w, s} R˙w,s和加速度 S ˙ W \dot{\mathbf{S}}_{\boldsymbol{W}} S˙W分别是矩阵 T w , s \mathbf{T}_{w, s} Tw,s和 T ¨ w , s \ddot{\mathbf{T}}_{w, s} T¨w,s的子矩阵,然后我们通过最小化下面这个由预测模型和实际观测构成的代价函数来求得曲线的参数 E ( θ ) = ∑ p ^ m ( p ^ m − W ( p r ; T c , s ( u m ) − 1 T w , s ( u r ) T s , c , ρ ) ) Σ p 2 + ∑ ω ^ m ( ω ^ m − Gyro ( u m ) ) Σ ω 2 + ∑ a ^ m ( a ^ m − Accel ( u m ) ) Σ a 2 \begin{aligned} E(\theta)=& \sum_{\hat{\mathbf{p}}_{m}}\left(\hat{\mathbf{p}}_{m}-\mathcal{W}\left(\mathbf{p}_{r} ; \mathbf{T}_{c, s}\left(u_{m}\right)^{-1} \mathbf{T}_{w, s}\left(u_{r}\right) \mathbf{T}_{s, c}, \rho\right)\right)_{\Sigma_{p}}^{2}+\\ & \sum_{\hat{\omega}_{m}}\left(\hat{\omega}_{m}-\operatorname{Gyro}\left(u_{m}\right)\right)_{\Sigma_{\omega}}^{2}+\sum_{\hat{\mathbf{a}}_{m}}\left(\hat{\mathbf{a}}_{m}-\operatorname{Accel}\left(u_{m}\right)\right)_{\Sigma_{\mathbf{a}}}^{2} \end{aligned} E(θ)=p^m∑(p^m−W(pr;Tc,s(um)−1Tw,s(ur)Ts,c,ρ))Σp2+ω^m∑(ω^m−Gyro(um))Σω2+a^m∑(a^m−Accel(um))Σa2其中 p ^ m , ω ^ m \hat{\mathbf{p}}_{m},\hat{\omega}_{m} p^m,ω^m, a ^ m \hat{\mathbf{a}}_{m} a^m就是测量值
总而言之,本文的大概思路是通过用四次B样条曲线来拟合相机的轨迹,而不是通过我们一般的思路建立运动学公式然后通过观测来对运动学公式进行修正这样的思路,文中提到这样做的一个优势是能很好地利用最小二乘法标定不同步时间的内外参矩阵,我想大概能了解其中的含义。
这次遇到的问题主要是在运行allen方差工具的时候环境配置的问题,我开始是尝试安装最新版本的ceres和Eigen,但是发现编译的时候会遇到ceres中Eigen的编译错误,纠结了很久,后来怀疑是不是最新版本的ceres和Eigen版本不匹配,因为就尝试卸载最新版的Eigen重新装了Eigen3.2,然后就好使了,中间耽误了不少时间,环境搞死人…