[开源]基于ESKF实现IMU和GPS融合定位
本文介绍了基于误差状态卡尔曼滤波(ESKF)的IMU与GPS融合定位方法。首先阐述了IMU测量模型和航迹推算原理,包括加速度/角速度测量公式和积分方法。其次概述了GPS定位的精度影响因素及常见坐标系转换。重点推导了ESKF算法的实现过程,包括名义状态变量与误差状态变量的定义、运动方程建立等关键步骤。该方法将IMU的高频局部定位与GPS的低频绝对定位相结合,通过分离状态传播与噪声处理,简化了计算过程
开源代码
使用ESKF实现了IMU和GPS的融合定位,开源代码提供了ROS2的实现:https://github.com/Yaepiii/ESKF_IMU_GPS_Fusion
下面简单梳理一下推导过程
1. IMU基础
1.1 IMU测量模型
IMU可以测量加速度和角速度,定义测量值为 a m , w m a_m, w_m am,wm,IMU的噪声通常会受到偏置 b b b和测量噪声 n n n的影响,因此IMU测量值可以表示为:
a m = I R W ( a − g ) + b a + n a w m = w + b g + n g \begin{aligned} a_m &= ^IR_W (a - g) + b_a + n_a \\ w_m &= w + b_g + n_g \end{aligned} amwm=IRW(a−g)+ba+na=w+bg+ng
其中, a , w a, w a,w为世界坐标系下真实值,偏置项符合随机游走模型,测量噪声符合零均值高斯分布。
1.2 IMU航迹推算
如果两次IMU测量的时间间隔为 Δ t \Delta t Δt,那么就可以使用积分的知识推导出下一个时刻的状态:
R ( t + Δ t ) = R ( t ) E x p ( ( w m − b g ) Δ t ) p ( t + Δ t ) = p ( t ) + v Δ t + 1 2 ( R ( t ) ( a m − b a ) ) Δ t 2 + 1 2 g Δ t 2 v ( t + Δ t ) = v ( t ) + R ( t ) ( a m − b a ) Δ t + g Δ t \begin{aligned} R(t+\Delta t)&=R(t)Exp((w_m-b_g)\Delta t) \\ p(t+\Delta t)&=p(t)+v\Delta t+\frac{1}{2}(R(t)(a_m-b_a))\Delta t^2+\frac{1}{2}g\Delta t^2 \\ v(t+\Delta t)&=v(t)+R(t)(a_m-b_a)\Delta t+g\Delta t \end{aligned} R(t+Δt)p(t+Δt)v(t+Δt)=R(t)Exp((wm−bg)Δt)=p(t)+vΔt+21(R(t)(am−ba))Δt2+21gΔt2=v(t)+R(t)(am−ba)Δt+gΔt
这里相当于使用了欧拉法的做法,认为 Δ t \Delta t Δt这段时间内的角速度和加速度就是起始时刻的值,在实际代码中,中值积分比较常用,例如:代码中的这里
2. GPS基础
GPS其实是美国的全球定位系统的简称,因为它出现的比较早,所以后面很多时候都把GPS等同于GNSS(全球卫星导航系统)了,其实GNSS才是一个更广的概念,GNSS包括很多国的卫星导航系统,比如:美国的全球定位系统(GPS)、中国的北斗卫星导航系统(Beidou)、俄罗斯的格罗纳斯系统(GLONASS)、欧盟的伽利略系统(GALILEO)。
2.1 测量精度影响因素
GPS是通过结果卫星信号解算进行定位的系统,最少需要接收4颗卫星的信号才能实现位置解算,通常分为单点定位和差分定位(RTK)技术,单点定位的精度比较低,消费级的GPS大概在米级精度,z轴的测量就会更高一些;而RTK是通过和额外的基站通信可以获得更高的精度,能够达到厘米级甚至毫米级的精度。
当然,即使使用RTK技术,在实际使用过程中仍然存在很多现实因素会影响定位精度,下面总结几条:
- 天气:比如今天天气不好,乌云密布,可能会导致搜星不好,搜星数量较少
- 遮挡:这种情况在城市运行时较为常见,高楼有时候会遮挡卫星信号,还会造成多径效应
- 安装:有时候接收器安装倾斜也会导致精度下降(很多厂商会提供倾斜测量的功能)
- 静置:很多情况下,让接收器原地静置几分钟精度会更高,因为很多接收器常常具有自校准功能
2.2 常见的坐标系
GPS受到的原始测量值大部分是经纬高(经度、纬度、海拔,LLA),这通常被称为地理坐标系,这是全局的绝对测量值,而IMU得到的是相对测量,如果想让二者进行融合,需要将GPS测量值转换为局部坐标系,例如东北天(ENU)坐标系。
网上有很多讲解怎么进行转换的,这里就不展开了,实际上,在代码中可以调用GeographicLib这个第三方库来方便的实现这个过程。
3. 基于ESKF的GINS系统
IMU提供了短期高频的局部定位,GPS实现了低频的绝对定位,所以很自然地想到可以使用卡尔曼滤波将二者进行融合。
3.1 为什么用ESKF
经典数据[1]中给出了经典的总结,大致如下:
- ESKF使用误差项做为状态量,这是一个小量,其二阶变量可以忽略,大多数情况下可以对雅克比矩阵进行简化,一些部分可以使用单位阵替代
- ESKF总是在原点附近,离奇异点较远,数值更稳定一些,这也会降低线性化近似误差
- ESKF使用三维变量来表达旋转增量,避免了传统KF中用四元数或旋转矩阵来表达的奇异性问题
3.2 公式推导
3.2.1 变量定义
经典的KF可能会将状态变量设置为:
x = [ p ˉ , v ˉ , R ˉ , b ˉ a , b ˉ g , g ˉ ] x=[\bar{p}, \bar{v}, \bar{R}, \bar{b}_a, \bar{b}_g, \bar{g}] x=[pˉ,vˉ,Rˉ,bˉa,bˉg,gˉ]
运动方程为:
p ˉ ˙ = v ˉ v ˉ ˙ = R ˉ ( a m − b ˉ a − n a ) + g ˉ R ˉ ˙ = R ˉ ( w m − b ˉ g − n g ) ∧ b ˉ g ˙ = n g b ˉ a ˙ = n a g ˉ ˙ = 0 \begin{aligned} \dot{\bar{p}}&=\bar{v} \\ \dot{\bar{v}}&=\bar{R}(a_m-\bar{b}_a-n_a)+\bar{g} \\ \dot{\bar{R}}&=\bar{R}(w_m-\bar{b}_g-n_g)^{\land} \\ \dot{\bar{b}_g}&=n_g \\ \dot{\bar{b}_a}&=n_a \\ \dot{\bar{g}}&=0 \end{aligned} pˉ˙vˉ˙Rˉ˙bˉg˙bˉa˙gˉ˙=vˉ=Rˉ(am−bˉa−na)+gˉ=Rˉ(wm−bˉg−ng)∧=ng=na=0
而在ESKF中通常会称上述状态变量为名义状态变量,而将真正的"传播"过程中的状态变量成为误差状态变量:
δ x = [ δ p , δ v , δ R , δ b a , δ b g , δ g ] \delta x=[\delta p, \delta v, \delta R, \delta b_a, \delta b_g, \delta g] δx=[δp,δv,δR,δba,δbg,δg]
将名义状态变量和误差状态变量相加,就可以得到真值状态
p = p ˉ + δ p v = v ˉ + δ v R = R ˉ δ R b a = b ˉ a + δ b a b g = b ˉ g + δ b g g = g ˉ + δ g \begin{aligned} p &= \bar{p} + \delta p \\ v &= \bar{v} + \delta v \\ R &= \bar{R} \delta R \\ b_a &= \bar{b}_a + \delta b_a \\ b_g &= \bar{b}_g + \delta b_g \\ g &= \bar{g} + \delta g \end{aligned} pvRbabgg=pˉ+δp=vˉ+δv=RˉδR=bˉa+δba=bˉg+δbg=gˉ+δg
这个过程相当于一个将状态传播和噪声分离的过程,在积分的过程中使用名义状态变量,认为是无噪声的,然后使用EKF的过程更新误差状态变量,最后进行"合并",这样其实是使得整个过程更简洁了。
整体流程引用高翔博士书中[2]的总结:
既然是使用误差状态变量 δ x \delta x δx进行EKF的过程,那么接下来需要推导一下关于 δ x \delta x δx的运动方程。
3.2.2 运动方程
在真值状态定义公式中,两边对时间求导可以得到:
δ p ˙ = δ v δ b ˙ a = n a δ b ˙ g = n g δ g ˙ = 0 \begin{aligned} \delta \dot{p}&=\delta v \\ \delta \dot{b}_a&=n_a \\ \delta \dot{b}_g&=n_g \\ \delta \dot{g} &= 0 \end{aligned} δp˙δb˙aδb˙gδg˙=δv=na=ng=0
多说一句推导过程,比如对于 δ p ˙ \delta \dot{p} δp˙,左边求导是 v v v,右边求导是 v ˉ + δ p ˙ \bar{v}+\delta \dot{p} vˉ+δp˙,,移个项就能得到结论了。
对于速度项和旋转项与 δ R \delta R δR相关,因此需要更复杂的推导。
对于旋转误差项
求导后:
R ˙ = R ˉ ˙ e x p ( δ θ ) + R ˉ e x p ( δ θ ) ˙ = R ˉ ( w m − b g ) ∧ e x p ( δ θ ) + R ˉ e x p ( δ θ ) δ θ ˙ ∧ \dot{R}=\dot{\bar{R}}exp(\delta \theta)+\bar{R}\dot{exp(\delta \theta)}=\bar{R}(w_m-b_g)^{\land}exp(\delta \theta)+\bar{R}exp(\delta \theta){\delta \dot{\theta}}^{\land} R˙=Rˉ˙exp(δθ)+Rˉexp(δθ)˙=Rˉ(wm−bg)∧exp(δθ)+Rˉexp(δθ)δθ˙∧
注意到,对真值 R R R求导还等于:
R ˙ = R ( w m − b g − n g ) ∧ = R ˉ δ R ( w m − b g − n g ) ∧ \dot{R}=R(w_m-b_g-n_g)^{\land}=\bar{R}\delta R(w_m-b_g-n_g)^{\land} R˙=R(wm−bg−ng)∧=RˉδR(wm−bg−ng)∧
联立这两个式子,可以消掉 R ˉ \bar{R} Rˉ,再整理一下可以得到:
e x p ( δ θ ) δ θ ˙ ∧ = δ R ( w m − b g − n g ) ∧ − ( w m − b g ) ∧ e x p ( δ θ ) exp(\delta \theta){\delta \dot{\theta}}^{\land} = \delta R(w_m-b_g-n_g)^{\land} - (w_m-b_g)^{\land}exp(\delta \theta) exp(δθ)δθ˙∧=δR(wm−bg−ng)∧−(wm−bg)∧exp(δθ)
利用伴随性质( ϕ ∧ R = R ( R T ϕ ) ∧ \phi ^{\land}R=R(R^T\phi)^{\land} ϕ∧R=R(RTϕ)∧),可得:
e x p ( δ θ ) δ θ ˙ ∧ = δ R ( w m − b g − n g ) ∧ − δ R ( δ R T ( w m − b g ) ) ∧ = δ R ( ( w m − b g − n g ) ∧ − ( δ R T ( w m − b g ) ) ∧ ) ≈ δ R ( ( w m − b g − n g ) ∧ − ( ( I − δ θ ∧ ) ( w m − b g ) ) ∧ ) = δ R ( w m − b g − n g − ( δ θ ∧ w m − δ θ ∧ b g ) ) ∧ = δ R ( ( − w m + b g ) ∧ δ θ − δ b g − n g ) ∧ \begin{aligned} exp(\delta \theta){\delta \dot{\theta}}^{\land} &= \delta R(w_m-b_g-n_g)^{\land} - \delta R(\delta R^T(w_m-b_g))^{\land} \\ &= \delta R((w_m-b_g-n_g)^{\land} - (\delta R^T(w_m-b_g))^{\land}) \\ &\approx \delta R((w_m-b_g-n_g)^{\land} - ((I-\delta \theta ^{\land})(w_m-b_g))^{\land}) \\ &= \delta R(w_m-b_g-n_g - (\delta \theta ^{\land}w_m-\delta \theta ^{\land}b_g))^{\land} \\ &= \delta R((-w_m+b_g)^{\land}\delta \theta-\delta b_g-n_g)^{\land} \end{aligned} exp(δθ)δθ˙∧=δR(wm−bg−ng)∧−δR(δRT(wm−bg))∧=δR((wm−bg−ng)∧−(δRT(wm−bg))∧)≈δR((wm−bg−ng)∧−((I−δθ∧)(wm−bg))∧)=δR(wm−bg−ng−(δθ∧wm−δθ∧bg))∧=δR((−wm+bg)∧δθ−δbg−ng)∧
其中, ≈ \approx ≈这一步,是对 δ R T \delta R^T δRT应用了 e x p ( ⋅ ) exp(\cdot) exp(⋅)泰勒展开,最后,约掉两侧的 e x p ( δ θ ) exp(\delta \theta) exp(δθ)和 ∧ ^{\land} ∧可得:
δ θ ˙ = ( − w m + b g ) ∧ δ θ − δ b g − n g \delta \dot{\theta} = (-w_m+b_g)^{\land}\delta \theta-\delta b_g-n_g δθ˙=(−wm+bg)∧δθ−δbg−ng
对于速度误差项
对两侧求导,根据公式(4),左边为:
v ˙ = R ( a m − b a − n a ) + g = R ˉ δ R ( a m − b ˉ a − δ b a − n a ) + g ˉ + δ g ≈ R ˉ ( I + δ θ ∧ ) ( a m − b ˉ a − δ b a − n a ) + g ˉ + δ g ≈ R ˉ a m − R ˉ b ˉ a − R ˉ δ b a − R ˉ n a − R ˉ a m ) ∧ δ θ − R ˉ b ˉ a ∧ δ θ + g ˉ + δ g \begin{aligned} \dot{v}&=R(a_m-b_a-n_a)+g \\ &= \bar{R}\delta R(a_m-\bar{b}_a-\delta b_a-n_a)+\bar{g}+\delta g \\ &\approx \bar{R}(I+\delta \theta ^{\land})(a_m-\bar{b}_a-\delta b_a-n_a)+\bar{g}+\delta g \\ &\approx \bar{R} a_m - \bar{R} \bar{b}_a - \bar{R}\delta b_a - \bar{R} n_a - \bar{R} {a_m)} ^{\land} \delta \theta - \bar{R} {\bar{b}_a} ^{\land} \delta \theta+\bar{g}+\delta g \end{aligned} v˙=R(am−ba−na)+g=RˉδR(am−bˉa−δba−na)+gˉ+δg≈Rˉ(I+δθ∧)(am−bˉa−δba−na)+gˉ+δg≈Rˉam−Rˉbˉa−Rˉδba−Rˉna−Rˉam)∧δθ−Rˉbˉa∧δθ+gˉ+δg
推导过程中需要忽略 δ θ ∧ \delta \theta ^{\land} δθ∧与 δ b a , n a \delta b_a, n_a δba,na相乘的二阶小量。
右边为:
v ˉ ˙ + δ v ˙ = R ˉ ( a m − b ˉ a ) + g ˉ + δ v ˙ \begin{aligned} \dot{\bar{v}}+\delta \dot{v} = \bar{R}(a_m-\bar{b}_a)+\bar{g}+\delta \dot{v} \end{aligned} vˉ˙+δv˙=Rˉ(am−bˉa)+gˉ+δv˙
联立两式可得:
δ v ˙ = − R ˉ ( a m − b ˉ a ) ∧ δ θ − R ˉ δ b a − R n a + δ g = − R ˉ ( a m − b ˉ a ) ∧ δ θ − R ˉ δ b a − n a + δ g \begin{aligned} \delta \dot{v}&=-\bar{R}(a_m-\bar{b}_a)^{\land}\delta \theta - \bar{R} \delta b_a - Rn_a+\delta g \\ &=-\bar{R}(a_m-\bar{b}_a)^{\land}\delta \theta - \bar{R} \delta b_a - n_a+\delta g \end{aligned} δv˙=−Rˉ(am−bˉa)∧δθ−Rˉδba−Rna+δg=−Rˉ(am−bˉa)∧δθ−Rˉδba−na+δg
至此,我们推导了所有状态量的运动方程形式,也不难写出它们的离散形式:
δ p ( t + Δ t ) = δ p + δ v Δ t δ v ( t + Δ t ) = δ v + ( − R ˉ ( a m − b ˉ a ) ∧ δ θ − R ˉ δ b a + δ g ) Δ t − n v δ θ ˙ ( t + Δ t ) = ( − w m + b g ) ∧ Δ t δ θ − δ b g Δ t − n θ δ b a ( t + Δ t ) = δ b a + n a δ b g ( t + Δ t ) = δ b b g + n g δ g ( t + Δ t ) = δ g \begin{aligned} \delta p(t+\Delta t)&=\delta p+\delta v \Delta t \\ \delta v(t+\Delta t)&=\delta v+(-\bar{R}(a_m-\bar{b}_a)^{\land}\delta \theta - \bar{R} \delta b_a+\delta g)\Delta t - n_v \\ \delta \dot{\theta}(t+\Delta t) &= (-w_m+b_g)^{\land}\Delta t\delta \theta-\delta b_g\Delta t-n_{\theta} \\ \delta b_a(t+\Delta t)&=\delta b_a+n_a \\ \delta b_g(t+\Delta t)&=\delta bb_g + n_g \\ \delta g(t+\Delta t) &= \delta g \end{aligned} δp(t+Δt)δv(t+Δt)δθ˙(t+Δt)δba(t+Δt)δbg(t+Δt)δg(t+Δt)=δp+δvΔt=δv+(−Rˉ(am−bˉa)∧δθ−Rˉδba+δg)Δt−nv=(−wm+bg)∧Δtδθ−δbgΔt−nθ=δba+na=δbbg+ng=δg
整体简写为:
δ x k + 1 = f ( δ x k ) + w \begin{aligned} \delta x_{k+1}=f(\delta x_{k})+w \end{aligned} δxk+1=f(δxk)+w
w是协方差为Q的0均值高斯噪声,那么接下来我们就可以按照EKF的方式进行线性化:
δ x ( t + δ t ) = f ( δ x ( t ) ) + F δ x + w \begin{aligned} \delta x(t+\delta t)=f(\delta x(t))+F\delta x+w \end{aligned} δx(t+δt)=f(δx(t))+Fδx+w
这里的F就是由我们上面推导的运动方程推导出来的,把他们的系数拿出来就可以得到F矩阵的形式:
F = [ I I Δ t 0 0 0 0 0 I − R ˉ ( a m − b ˉ a ) ∧ Δ t − R ˉ Δ t 0 I Δ t 0 0 ( − w m + b g ) ∧ Δ t 0 − I Δ t 0 0 0 0 I 0 0 0 0 0 0 I 0 0 0 0 0 0 I ] \begin{aligned} F=\left[ \begin{matrix} I& I\Delta t& 0& 0& 0& 0\\ 0& I& -\bar{R}\left( a_m-\bar{b}_a \right) ^{\land}\Delta t& -\bar{R}\Delta t& 0& I\Delta t\\ 0& 0& \left( -w_m+b_g \right) ^{\land}\Delta t& 0& -I\Delta t& 0\\ 0& 0& 0& I& 0& 0\\ 0& 0& 0& 0& I& 0\\ 0& 0& 0& 0& 0& I\\ \end{matrix} \right] \end{aligned} F= I00000IΔtI00000−Rˉ(am−bˉa)∧Δt(−wm+bg)∧Δt0000−RˉΔt0I0000−IΔt0I00IΔt000I
至此,我们就可以愉快地套用EKF的预测过程了:
δ x ^ = F δ x P ^ = F P P T + Q \begin{aligned} \delta \hat{x}&=F\delta x \\ \hat{P}&=FPP^T+Q \end{aligned} δx^P^=Fδx=FPPT+Q
3.2.3 观测方程
当收到GPS矫正信息后,可以执行EKF的更新过程,观测方程如下:
z = h ( x ^ ) + v \begin{aligned} z=h(\hat{x})+v \end{aligned} z=h(x^)+v
v是观测噪声,符合协方差为V的0均值高斯分布。
同样会对观测方程执行一阶泰勒展开:
z = H δ x ^ + v \begin{aligned} z=H\hat{\delta x}+v \end{aligned} z=Hδx^+v
这里的矩阵H可以通过链式法则获得对 δ x \delta x δx的导数:
H = ∂ h ∂ x ∂ x ∂ δ x H=\frac{\partial h}{\partial x} \frac{\partial x}{\partial \delta x} H=∂x∂h∂δx∂x
对于第一项其实就是GPS测量的位置 [ x , y , z ] [x, y, z] [x,y,z]对名义状态量的导数,就是单位阵,对于第二项,根据之前真值、名义状态量、误差状态量之间的关系可以得到:
∂ x ∂ δ x = d i a g ( I , I , J r − 1 ( R ˉ ) , I , I , I ) \frac{\partial x}{\partial \delta x}=diag(I,I,J^{-1}_r(\bar{R}),I,I,I) ∂δx∂x=diag(I,I,Jr−1(Rˉ),I,I,I)
其中旋转项求导的时候,相当于 R ˉ \bar{R} Rˉ右乘了一个小量,可以用BCH近似公式得到。
3.2.3 善后工作
在完成上述过程后,只需要把误差状态归入名义状态,然后重置ESKF即可,归入就很简单:
p k + 1 = p ˉ k + δ p v k + 1 = v ˉ k + δ v R k + 1 = R ˉ k δ R b a k + 1 = b ˉ a k + δ b a b g k + 1 = b ˉ g k + δ b g g k + 1 = g ˉ k + δ g \begin{aligned} p_{k+1} &= \bar{p}_{k} + \delta p \\ v_{k+1} &= \bar{v}_{k} + \delta v \\ R_{k+1} &= \bar{R}_{k} \delta R \\ {b_a}_{k+1} &= {\bar{b}_a}_{k} + \delta b_a \\ {b_g}_{k+1} &= {\bar{b}_g}_{k} + \delta b_g \\ g_{k+1} &= \bar{g}_{k} + \delta g \end{aligned} pk+1vk+1Rk+1bak+1bgk+1gk+1=pˉk+δp=vˉk+δv=RˉkδR=bˉak+δba=bˉgk+δbg=gˉk+δg
对于重置部分,均值的重置就直接把状态量全置零即可,对于协方差的重置有点说法,它对于除了旋转部分以外的状态量是没有影响的,对旋转部分有微小的影响,具体可参考[2],一般是有以下关系:
P r e s e t = J k P J k T P_{reset}=J_kPJ^T_k Preset=JkPJkT
不过,由于一般认为ESKF的误差状态量为小量, δ θ \delta \theta δθ很小,一般代码中直接将 J k J_k Jk作为单位阵处理。
3.3 总结
总之,整个过程其实和EKF类似,有这么几个公式:
δ x ^ = F δ x P ^ = F P ˉ F T + Q K = P ^ H T ( H P ^ H T + V ) − 1 δ x = K ( z − h ( x ^ ) ) x ˉ = x ^ + δ x P ˉ = ( I − K H ) P ^ \begin{aligned} \delta \hat{x}&=F\delta x \\ \hat{P} &= F\bar{P}F^T+Q \\ K&=\hat{P}H^T(H\hat{P}H^T+V)^{-1} \\ \delta x &= K(z-h(\hat{x})) \\ \bar{x} &= \hat{x} + \delta x \\ \bar{P} &= (I-KH)\hat{P} \end{aligned} δx^P^KδxxˉPˉ=Fδx=FPˉFT+Q=P^HT(HP^HT+V)−1=K(z−h(x^))=x^+δx=(I−KH)P^
4. 代码细节
代码中和文中描述有些不同之处,总结如下:
- 代码中为了省事,将重力项纳入状态变量中
- 代码目前没有实现IMU自动初始化过程,使用手动设置的一些参数,如偏置、噪声
- 注意代码统一使用的东北天坐标系
- 实际上,IMU和GPS的外参也需要考虑,代码给出了接口
参考文献
[1] Solà, J. (2017). Quaternion kinematics for the error-state Kalman filter. arXiv. https://arxiv.org/abs/1711.02508
[2]高翔, 等人. 自动驾驶与机器人中的SLAM技术[M]

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)