引用地址:http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it/
另外一篇可以参考:详解卡尔曼滤波原理【https://blog.csdn.net/u010720661/article/details/63253509】

长期以来,我一直对kalman文件管理器及其工作方式感到困惑,我还在我的Balancing机器人(网址:http://blog.tkjelectronics.dk/2012/03/the-balancing-robot/)上使用了kalman过滤器,但我从未解释过它是如何实现的。实际上,我从来没有花时间坐在笔和纸上坐下来自己尝试做数学,所以我实际上不知道它是如何实现的。
事实证明这是一件好事,因为我实际上在原始代码中发现了一个错误,但稍后我会再讲到。

我实际上是在2011年12月在高中时就将卡尔曼滤波器作为我的主要作业写的。但是,我仅使用卡尔曼滤波器来计算由已知的Gaussian white noise调制的直流信号的真实电压。我的作业可以在以下zip文件中找到:http://www.tkjelectronics.dk/uploads/Kalman_SRP.zip。它是丹麦语,但您可以正确地使用Google翻译来翻译其中的一些内容。如果您对作业有任何具体问题,请在下面的评论中提问。

好的,但是回到主题。令我难过的是,我从未花时间坐下来对基于加速度计和陀螺仪的卡尔曼滤波器进行数学运算。这并不像我预期的那么难,但是我必须承认,我仍然没有研究背后的更深层的理论,即它为何真正起作用。但是对于我和大多数人来说,与实施更深层的理论以及方程为何起作用相比,我对实施过滤器更感兴趣。

在开始之前,您必须具有一些有关矩阵的基本知识,例如矩阵的乘法和矩阵的转置。如果没有,请访问以下网站:

http://en.wikipedia.org/wiki/Matrix_multiplication#Matrix_product_.28two_matrices.29
http://www.mathwarehouse.com/algebra/matrix/multiply-matrix.php
http://en.wikipedia.org/wiki/Transpose
http://en.wikipedia.org/wiki/Covariance_matrix
对于不知道卡尔曼滤波器是什么的人来说,它是一种使用一段时间内观察到的一系列测量值的算法,在这里,是加速度计和陀螺仪的数据。这些测量将包含会导致测量误差的噪声。然后,卡尔曼滤波器将尝试根据当前和以前的状态来估计系统状态,该状态比单独的测量更为精确。

在这种情况下,问题在于,由于机器人来回运动,当加速度计用于测量重力加速度时,加速度计通常非常嘈杂。陀螺仪的问题在于它会随时间漂移-就像旋转的陀螺仪在失去速度时会开始掉落一样。
简而言之,可以说您只能短期信任陀螺仪,但能长期信任加速度计。

实际上,有一个非常简单的方法可以通过使用一个免费的滤波器来解决这个问题,该滤波器基本上只由加速度计上的数字低通滤波器和陀螺仪读数上的数字高通滤波器组成。但是它不如卡尔曼滤波器那么精确,但是其他人已经使用微调的免费滤波器成功构建了平衡机器人。

有关陀螺仪,加速度计和complimentary滤波器的更多信息,请参见此pdf(http://web.mit.edu/scolton/www/filter.pdf)。在下面的博客文章中可以找到互补滤波器和卡尔曼滤波器之间的比较。

卡尔曼滤波器通过基于测量结果生成系统状态的统计最优估计来进行操作。为此,需要知道滤波器输入的噪声(称为测量噪声),还需要知道系统本身的噪声(称为过程噪声)。为此,噪声必须是高斯分布并且均值为零,幸运的是,对于我们来说,大多数随机噪声都具有此特性。
有关过滤器原理的更多信息,请查看以下页面:

http://en.wikipedia.org/wiki/kalman_filter
http://www.cs.unc.edu/~welch/media/pdf/kalman_intro.pdf
http://academic.csuohio.edu/simond/courses/eec644/kalman.pdf

1. 系统状态 xk\boldsymbol{x}_kxk​

对于某些人来说,本文的下一部分可能看起来很混乱,但是我向您保证,如果您精通数学,那么只要拿起笔和一张纸并尝试推导它,就不那么困难了。

如果像我一样,如果您没有可用于矩阵的计算器或计算机程序,那么我建议您使用免费的在线计算器Wolfram Alpha:http://www.wolframalpha.com/。我将其用于本文的所有计算。

我将使用与Wikipedia:http://en.wikipedia.org/wiki/Kalman_filter文章相同的表示法,但我想指出的是,当矩阵是常数且不依赖于当前时间时,您不必在其后写k。因此,例如FkF_kFk​可以简化为F。

我也想对这些符号的其他方面做一个小的解释。
首先,我将记录一下所谓的先前状态:
x^k−1∣k−1\boldsymbol{\hat{x}}_{k-1 | k-1}x^k−1∣k−1​

这是基于先前状态及其之前状态的估计的先前估计状态。
接下来是先验状态:
x^k∣k−1\boldsymbol{\hat{x}}_{k | k-1}x^k∣k−1​

先验表示基于系统的先前状态及其之前状态的估计,在当前时间k对状态矩阵的估计。
最后一个称为后验状态:
x^k∣k\boldsymbol{\hat{x}}_{k | k}x^k∣k​

是在给定k并包括k的情况下在k时刻估计的状态。
问题在于系统状态本身是隐藏的,只能通过观察来观察zkz_kzk​。这也称为隐马尔可夫模型。

这意味着该状态将基于时间k处的状态以及所有先前状态。这也意味着在kalman滤波器稳定之前,您不能相信状态的估计–请看我作业首页的图表。

x^\hat{x}x^是对状态的估计。与x意味着真实状态的单一状态不同-我们试图估计的状态。
因此,在时间k的状态表示为:
xk\boldsymbol{x}_k xk​
如果由下式给出,则系统在时间k的状态:

xk=Fxk−1+Buk+wk\boldsymbol{x}_k =\boldsymbol{F}x_{k-1}+\boldsymbol{B}u_k + w_kxk​=Fxk−1​+Buk​+wk​
xkx_kxk​状态矩阵表示为:

xk=[θθ˙b]k\boldsymbol{x}_k =\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_kxk​=[θθ˙b​​]k​
如您所见,滤波器的输出将是角度θ\thetaθ,θ˙b\dot{\theta}_bθ˙b​是基于加速度计和陀螺仪的测量结果的偏差。偏差是陀螺仪漂移的量。这意味着可以通过从陀螺仪测量值中减去偏差来获得真实速率。

下一个是F矩阵,它是应用于prevouis状态的状态转换模型xk−1x_{k-1}xk−1​。

在这种情况下F定义为:
F=[1−Δt01]\boldsymbol{F}=\begin{bmatrix} 1 &-\Delta t \\ 0 & 1 \end{bmatrix}F=[10​−Δt1​]
我知道这种方法−Δt-\Delta t−Δt似乎令人困惑,但是稍后会有意义(请看我的评论)。

接下来是控制输入uku_kuk​,在这里,它是在时间k处以每秒度数(°/ s)为单位的陀螺仪测量值,也称为速率θ˙\dot{\theta}θ˙。我们实际上将状态方程重写为:
xk=Fxk−1+Bθ˙k+wk\boldsymbol{x}_k =\boldsymbol{F}x_{k-1}+\boldsymbol{B}{\dot{\theta}_k}+ w_kxk​=Fxk−1​+Bθ˙k​+wk​
接下来是B矩阵。称为控制输入模型,定义为:
B=[Δt0]\boldsymbol{B}=\begin{bmatrix}\Delta t\\0\end{bmatrix}B=[Δt0​]
这是完全合理的,因为当您将速率θ˙\dot{\theta}θ˙与增量时间Δt\Delta tΔt相乘时,您将获得角度θ\thetaθ,并且由于我们无法直接基于该速率计算偏差,因此我们将设置 矩阵为0。

wkw_kwk​是过程噪声,它是高斯分布,均值为零,并且与Q时间k呈协方差:

wk∼N(0,Qk)\boldsymbol{w}_k\sim N\left(0,\boldsymbol{Q}_k\right)wk​∼N(0,Qk​)
QkQ_kQk​是过程噪声协方差矩阵,在这种情况下是加速度计和偏差状态估计的协方差矩阵。在这种情况下,我们将认为偏置和加速度计的估计值是独立的,因此它实际上等于加速度计和偏置的估计值的方差。
最终矩阵的定义如下:
Qk=[Qθ00Qθ˙b]Δt\boldsymbol{Q}_k =\begin{bmatrix}Q_\theta & 0\\0 & Q _{\dot{\theta}_b}\end{bmatrix}\Delta t Qk​=[Qθ​0​0Qθ˙b​​​]Δt
如您所见,QkQ_kQk​协方差矩阵取决于当前时间k,因此加速度计方差QθQ_\thetaQθ​和偏差方差
Qθ˙bQ_{\dot{\theta}_b}Qθ˙b​​ 乘以增量时间Δt\Delta tΔt。
这是有道理的,因为自从上次更新状态以来,过程噪声会随着时间的延长而变大。例如,陀螺仪可能已经漂移了。
您必须知道这些常数才能使kalman滤波器起作用。

请注意,如果设置较大的值,则状态估计中的噪声会更多。 因此,例如,如果估计角度开始漂移,则必须增加Qθ˙bQ_{\dot{\theta}_b}Qθ˙b​​的值。 否则,如果估计趋于缓慢,则说明您对角度的估计过于信任,应尝试减小QθQ_\thetaQθ​的值以使其更具响应性。

2. 测量zk\boldsymbol{z}_kzk​

现在我们来看一下真实状态xkx_kxk​的观测值或测量值zkz_kzk​。观察结果zkz_kzk​如下:

zk=Hxk+vk\boldsymbol{z}_k =\boldsymbol{H}x_{k}+ v_kzk​=Hxk​+vk​
如您所见,测量zkz_kzk​是通过当前状态xkx_kxk​乘以H矩阵加上测量噪声得出的vkv_kvk​。

H称为观察模型,用于将真实状态空间映射到观察空间。无法观察到真实状态。由于测量只是来自加速度计的测量,因此H可表示为:
H=[10]\boldsymbol{H}=\begin{bmatrix}1 & 0\end{bmatrix}H=[1​0​]
测量的噪声必须是高斯分布,并且均值为零,并且R协方差为:
vk∼N(0,R)\boldsymbol{v}_k\sim N\left(0,\boldsymbol{R}\right)vk​∼N(0,R)
但是由于R不是矩阵,所以测量噪声仅等于测量的方差,因为同一变量的协方差等于方差。 有关更多信息,请参见此页面。
现在我们可以这样定义R

R=E[vkvkT]=var(vk)\boldsymbol{R}= E\begin{bmatrix}v_k&{v_k}^ T\end{bmatrix}= var(v_k) R=E[vk​​vk​T​]=var(vk​)
有关协方差的更多信息,请参见Wikipedia和我的作业。

我们将假设测量噪声是相同的,并且不依赖于时间k:

var(vk)=var(v)var(v_k)= var(v) var(vk​)=var(v)
请注意,如果将测量噪声方差var(v)var(v)var(v)设置得太高,则滤波器对新测量的信任度会降低,因此响应会非常缓慢,但是如果该值太小,则该值可能会过冲并且会产生噪声,因为我们对加速度计的测量结果过于信任。

因此,要四舍五入,您必须找到过程噪声方差Qθ和Qθ˙bQ_\theta和Q _{\dot{\theta}_b}Qθ​和Qθ˙b​​以及测量噪声var(v)var(v)var(v)的测量方差。 有多种找到它们的方法,但这超出了本文的范围。

3. 卡尔曼滤波方程

现在,我们将使用这些方程来估计系统在时间k的真实状态x^k\hat{x}_kx^k​。一些聪明的家伙想出了下面的等式来估计系统的状态。
这些方程式可以写得更紧凑,但我更喜欢将其扩展,因此更易于实现和理解不同的step 。

3.1 预测

在前两个方程中,我们将尝试预测时间k的当前状态和误差协方差矩阵。首先,过滤器将尝试基于所有先前状态和陀螺仪测量来估计当前状态:
x^k∣k−1=Fx^k−1∣k−1+Bθ˙k\boldsymbol{\hat{x}}_{k | k-1}=\boldsymbol{F}\hat{x}_{k-1 | k-1}+\boldsymbol{B}{\dot{\theta}_k}x^k∣k−1​=Fx^k−1∣k−1​+Bθ˙k​

这就是为什么将其称为控制输入的原因,因为我们将其用作估计当前时间k的状态的额外输入,称为先验状态x^k∣k−1\hat{x}_{k|k-1}x^k∣k−1​,如本文开头所述。
接下来的事情是,我们将尝试估计先验误差协方差矩阵Pk∣k−1P_{k|k-1}Pk∣k−1​基于先前的误差协方差矩阵Pk−1∣k−1P_{k-1|k-1}Pk−1∣k−1​,其定义为:
Pk∣k−1=FPk−1∣k−1FT+Qk\boldsymbol{P}_{k | k-1}=\boldsymbol{F}\boldsymbol{P}_{k-1 | k-1}\boldsymbol{F}^ T +\boldsymbol{Q}_kPk∣k−1​=FPk−1∣k−1​FT+Qk​

该矩阵用于估计我们对估计状态的当前值的信任程度。 越小,我们越信任当前的估计状态。 上面方程的原理实际上很容易理解,因为很明显,自从我们上次更新状态估计值以来,误差协方差会增加,因此我们将误差协方差矩阵乘以状态转换模型F和转置FTF^TFT的乘积,并在时间k加上当前过程噪声QkQ_kQk​。

P在我们的情况下,误差协方差矩阵是2×2矩阵:
P=[P00P01P10P11]\boldsymbol{P}=\begin{bmatrix}P_{00}&P_{01}\\P_{10}&P_{11}\end{bmatrix}P=[P00​P10​​P01​P11​​]

3.2. 更新

我们要做的第一件事是计算测量值zkz_kzk​与先验状态之间的差xk∣k−1x_{k | k-1}xk∣k−1​,这也称为创新:
y~k=zk−Hx^k∣k−1\boldsymbol{\tilde{y}}_ k =\boldsymbol{z}_k-\boldsymbol{H}\hat{x}_{k | k-1}y~​k​=zk​−Hx^k∣k−1​
观测模型H用于将先验状态映射xk∣k−1x_{k | k-1}xk∣k−1​到观测空间,该状态是来自加速度计的测量值,因此,该创新不是矩阵
y~k=[y~]k\boldsymbol{\tilde{y}}_ k =\begin{bmatrix}\boldsymbol{\tilde{y}}\end{bmatrix}_ky~​k​=[y~​​]k​
我们要做的下一步是计算所谓的创新协方差:
Sk=HPk∣k−1HT+R\boldsymbol{S}_k =\boldsymbol{H}\boldsymbol{P}_{k | k-1}\boldsymbol{H}^ T +\boldsymbol{R}Sk​=HPk∣k−1​HT+R

它的作用是尝试根据先验误差协方差矩阵Pk∣k−1P_{k | k-1}Pk∣k−1​和测量协方差矩阵预测我们应该信任测量的程度R。观测模型H用于将先验误差协方差矩阵映射Pk∣k−1P_{k | k-1}Pk∣k−1​到观测空间。
测量噪声的值越大,S的值就越大小号,这意味着我们不太相信传入的测量。
在这种情况下S,不是矩阵,而是写为:
Sk=[S]k\boldsymbol{S}_k =\begin{bmatrix}\boldsymbol{S}\end{bmatrix}_kSk​=[S​]k​
下一步是计算卡尔曼增益。卡尔曼增益用于表示我们对创新的信任程度,其定义为:
Kk=Pk∣k−1HTSk−1\boldsymbol{K}_k =\boldsymbol{P}_{k | k-1}\boldsymbol{H}^ T\boldsymbol{S}_k ^{-1}Kk​=Pk∣k−1​HTSk−1​
您会看到,如果我们不信任创新,那么创新协方差小号会很高;如果我们信任状态的估计值,那么误差协方差矩阵P将很小,因此,如果我们信任创新,卡尔曼增益将很小且相反但不信任当前状态的估计。

如果您更深入地看,您会发现观察模型的转置H用于将误差协方差矩阵的状态映射P到观察空间。然后,我们乘以创新协方差的倒数,比较误差协方差矩阵小号。

这很有意义,因为我们将使用观察模型H从状态误差协方差中提取数据,并将其与创新协方差的当前估计值进行比较。

请注意,如果您不知道启动时的状态,则可以这样设置误差协方差矩阵:
P=[L00L]\boldsymbol{P}=\begin{bmatrix}L & 0\\0 & L\end{bmatrix}P=[L0​0L​]

其中L代表大量。
对于我的平衡机器人,我知道启动角度,并且可以通过校准找到启动时陀螺仪的偏置,因此我假设启动时状态是已知的,因此我按如下方式初始化误差协方差矩阵:
P=[0000]\boldsymbol{P}=\begin{bmatrix}0 & 0\\0 & 0\end{bmatrix}P=[00​00​]
请查看我的校准例程以获取更多信息。

在这种情况下,卡尔曼增益为2×1矩阵:
K=[K0K1]\boldsymbol{K}=\begin{bmatrix}K_0\\K_1\end{bmatrix}K=[K0​K1​​]
现在我们可以更新当前状态的后验估计:
x^k∣k=x^k∣k−1+Kky~k\boldsymbol{\hat{x}}_{k | k}=\boldsymbol{\hat{x}}_{k | k-1}+\boldsymbol{K}_k\;\boldsymbol{\tilde{y}}_kx^k∣k​=x^k∣k−1​+Kk​y~​k​

这是通过将先验状态x^k∣k−1\hat{x}_{k | k-1}x^k∣k−1​与kalman增益乘以创新得到的y~k\tilde{y}_ky~​k​。
请记住,创新y~k\tilde{y}_ky~​k​是度量zkz_kzk​与先验状态之间的差异x^k∣k−1\hat{x}_{k | k-1}x^k∣k−1​,因此创新可以是正面的,也可以是负面的。
当我们简单地校正先验状态的估计值时,就可以理解该方程式,该估计值x^k∣k−1\hat{x}_{k | k-1}x^k∣k−1​是使用先前的状态和陀螺仪测量以及测量(在此情况下为加速度计)计算得出的。

我们要做的最后一件事是更新后验误差协方差矩阵:
Pk∣k=(I−kkH)Pk∣k−1\boldsymbol{P}_{k | k}=(\boldsymbol{I}-\boldsymbol{k}_k\boldsymbol{H})\boldsymbol{P}_{k | k-1}Pk∣k​=(I−kk​H)Pk∣k−1​
其中I称为身份矩阵,定义为:
I=[1001]\boldsymbol{I}=\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}I=[10​01​]
过滤器正在做的是,它基本上是根据我们对估计值的校正量对误差协方差矩阵进行自我校正。这是有道理的,因为我们根据先验误差协方差矩阵校正了状态Pk∣k−1P_{k | k-1}Pk∣k−1​,而且根据创新协方差校正了状态SkS_kSk​。

3.4 实现过滤器

在本节中,我将使用上面的公式将过滤器实现为简单的c ++代码,该代码可用于平衡机器人,四轴飞行器和其他需要计算角度,偏差或比率的应用。

如果您想要旁边的代码,可以在github上找到它:https : //github.com/TkJElectronics/kalmanFilter。

我将简单地在每个step 的顶部编写方程式,然后对其进行简化,然后在C中编写如何完成该方程式,最后,如我所使用的,我将在每个step 的底部链接至Wolfram Alpha中完成的计算。他们来做计算。

3.4.1 第1步:

x^k∣k−1=Fx^k−1∣k−1+Bθ˙k\boldsymbol{\hat{x}}_{k | k-1}=\boldsymbol{F}\hat{x}_{k-1 | k-1}+\boldsymbol{B}{\dot{\theta}_k}x^k∣k−1​=Fx^k−1∣k−1​+Bθ˙k​
[θθ˙b]k∣k−1=[1−Δt01][θθ˙b]k−1∣k−1+[Δt0]θ˙k\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_{k | k-1}=\begin{bmatrix}1 & -\Delta t\\0 & 1\end{bmatrix}\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_{k -1 | k-1}+\begin{bmatrix}\Delta t\\0\end{bmatrix}\dot{\theta}_k[θθ˙b​​]k∣k−1​=[10​−Δt1​][θθ˙b​​]k−1∣k−1​+[Δt0​]θ˙k​
=[θ−θ˙bΔtθ˙b]k−1∣k−1+[Δt0]θ˙k=\begin{bmatrix}\theta-\dot{\theta}_b\Delta t\\\dot{\theta}_b\end{bmatrix}_{k-1 | k-1}+\begin{bmatrix}\Delta t\\0\end{bmatrix}\dot{\theta}_k=[θ−θ˙b​Δtθ˙b​​]k−1∣k−1​+[Δt0​]θ˙k​
=[θ−θ˙bΔt+θ˙Δtθ˙b]=\begin{bmatrix}\theta-\dot{\theta}_b\Delta t +\dot{\theta}\Delta t\\\dot{\theta}_b\end{bmatrix}=[θ−θ˙b​Δt+θ˙Δtθ˙b​​]
=[θ+Δt(θ˙−θ˙b)θ˙b]=\begin{bmatrix}\theta +\Delta t(\dot{\theta}-\dot{\theta}_b)\\\dot{\theta}_b\end{bmatrix}=[θ+Δt(θ˙−θ˙b​)θ˙b​​]
如您所见,角度的先验估计θ^k∣k−1\hat{\theta}_{k | k-1}θ^k∣k−1​等于先前状态的估计θ^k−1∣k−1\hat{\theta}_{k-1 | k-1}θ^k−1∣k−1​加上无偏率乘以增量时间Δt\Delta tΔt。
由于我们无法直接测量偏差,因此先验偏差的估算值恰好等于前一个偏差。

可以这样用C编写:

rate= newRate -bias;
angle + = dt * rate;

请注意,我计算的是无偏速率,因此用户也可以使用它。

Wolfram Alpha链接:

Eq. 1.1

3.4.2 第2步:

Pk∣k−1=FPk−1∣k−1FT+Qk\boldsymbol{P}_{k | k-1}=\boldsymbol{F}\boldsymbol{P}_{k-1 | k-1}\boldsymbol{F}^ T +\boldsymbol{Q}_kPk∣k−1​=FPk−1∣k−1​FT+Qk​
[P00P01P10P11]k∣k−1=[1−Δt01][P00P01P10P11]k−1∣k−1[10−Δt1]+[Qθ00Qθ˙b]Δt\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k-1}=\begin{bmatrix}1 & -\Delta t\\0 & 1\end{bmatrix}\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11 }\end{bmatrix}_{k-1 | k-1}\begin{bmatrix}1 & 0\\-\Delta t & 1\end{bmatrix}+\begin{bmatrix}Q_\theta & 0\\0 & Q _{\dot{\theta}_b}\end{bmatrix}\Delta t[P00​P10​​P01​P11​​]k∣k−1​=[10​−Δt1​][P00​P10​​P01​P11​​]k−1∣k−1​[1−Δt​01​]+[Qθ​0​0Qθ˙b​​​]Δt
=[P00−ΔtP10P01−ΔtP11P10P11]k−1∣k−1[10−Δt1]+[Qθ00Qθ˙b]Δt=\begin{bmatrix}P_{00}-\Delta t P_{10} & P_{01}-\Delta t P_{11}\\P_{10} & P_{11}\end{bmatrix}_{k -1 | k-1}\begin{bmatrix}1 & 0\\-\Delta t & 1\end{bmatrix}+\begin{bmatrix}Q_\theta & 0\\0 & Q _{\dot{\theta}_b}\end{bmatrix}\Delta t=[P00​−ΔtP10​P10​​P01​−ΔtP11​P11​​]k−1∣k−1​[1−Δt​01​]+[Qθ​0​0Qθ˙b​​​]Δt
=[P00−ΔtP10−Δt(P01−ΔtP11)P01−ΔtP11P10−ΔtP11P11]k−1∣k−1+[Qθ00Qθ˙b]Δt=\begin{bmatrix}P_{00}-\Delta t P_{10}-\Delta t(P_{01}-\Delta t P_{11}) & P_{01}-\Delta t P_{11}\\P_{10}-\Delta t P_{11} & P_{11}\end{bmatrix}_{k-1 | k-1}+\begin{bmatrix}Q_\theta & 0\\0 & Q _{\dot{\theta}_b}\end{bmatrix}\Delta t=[P00​−ΔtP10​−Δt(P01​−ΔtP11​)P10​−ΔtP11​​P01​−ΔtP11​P11​​]k−1∣k−1​+[Qθ​0​0Qθ˙b​​​]Δt
=[P00−ΔtP10−Δt(P01−ΔtP11)+QθΔtP01−ΔtP11P10−ΔtP11P11+Qθ˙bΔt]=\begin{bmatrix}P_{00}-\Delta t P_{10}-\Delta t(P_{01}-\Delta t P_{11})+ Q_\theta\Delta t & P_{01}-\Delta t P_{11}\\P_{10}-\Delta t P_{11} & P_{11}+ Q _{\dot{\theta}_b}\Delta t\end{bmatrix}=[P00​−ΔtP10​−Δt(P01​−ΔtP11​)+Qθ​ΔtP10​−ΔtP11​​P01​−ΔtP11​P11​+Qθ˙b​​Δt​]
=[P00+Δt(ΔtP11−P01−P10+Qθ)P01−ΔtP11P10−ΔtP11P11+Qθ˙bΔt]=\begin{bmatrix}P_{00}+\Delta t(\Delta t P_{11}-P_{01}-P_{10}+ Q_\theta) & P_{01}-\Delta t P_{11}\\P_{10}-\Delta t P_{11} & P_{11}+ Q _{\dot{\theta}_b}\Delta t\end{bmatrix}=[P00​+Δt(ΔtP11​−P01​−P10​+Qθ​)P10​−ΔtP11​​P01​−ΔtP11​P11​+Qθ˙b​​Δt​]
上面的等式可以用C编写,如下所示:

P[0][0] += DT * ( DT * P[1][1] - P[0][1] - P[1][0] + Q_angle );
P[0][1] -= dt * P[1][1] ;
P[1][0] -= dt * P[1][1] ;
P[1][1] += Q_gyroBias * dt ;

请注意,这是我使用的原始代码中存在错误的代码部分。

Wolfram Alpha链接:

Eq. 2.1
Eq. 2.2
Eq. 2.3
Eq. 2.4

3.4.3 第三步:

y~k=zk−Hx^k∣k−1=zk−[10][θθ˙b]k∣k−1=zk−θk∣k−1\boldsymbol{\tilde{y}}_ k =\boldsymbol{z}_k-\boldsymbol{H}\hat{x}_{k | k-1} =\boldsymbol{z}_k-\begin{bmatrix}1 & 0\end{bmatrix}\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_{k | k-1} =\boldsymbol{z}_k-\theta_{k | k-1}y~​k​=zk​−Hx^k∣k−1​=zk​−[1​0​][θθ˙b​​]k∣k−1​=zk​−θk∣k−1​
可以像这样用C计算创新:

y = newAngle - angle ;

Wolfram Alpha链接:

Eq. 3.1

3.4.4 第四步:

Sk=HPk∣k−1HT+R\boldsymbol{S}_k =\boldsymbol{H}\boldsymbol{P}_{k | k-1}\boldsymbol{H}^ T +\boldsymbol{R}Sk​=HPk∣k−1​HT+R
=[10][P00P01P10P11]k∣k−1[10]+R=\begin{bmatrix}1 & 0\end{bmatrix}\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k-1}\begin{bmatrix}1\\0\end{bmatrix}+\boldsymbol{R}=[1​0​][P00​P10​​P01​P11​​]k∣k−1​[10​]+R
=P00k∣k−1+R={P_{00}}_{k | k-1}+\boldsymbol{R}=P00​k∣k−1​+R
=P00k∣k−1+var(v)={P_{00}}_{k | k-1}+ var(v)=P00​k∣k−1​+var(v)
同样,C代码非常简单:

S = P [ 0 ] [ 0 ] + R_{measure} ;

Wolfram Alpha链接:

Eq. 4.1

3.4.5 step 5:

kk=Pk∣k−1HTSk−1\boldsymbol{k}_k =\boldsymbol{P}_{k | k-1}\boldsymbol{H}^ T\boldsymbol{S}_k ^{-1}kk​=Pk∣k−1​HTSk−1​
[k0k1]k=[P00P01P10P11]k∣k−1[10]Sk−1\begin{bmatrix}k_0\\k_1\end{bmatrix}_k =\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k-1}\begin{bmatrix}1\\0\end{bmatrix}\boldsymbol{S}_k ^{-1}[k0​k1​​]k​=[P00​P10​​P01​P11​​]k∣k−1​[10​]Sk−1​
=[P00P10]k∣k−1Sk−1=\begin{bmatrix}P_{00}\\P_{10}\end{bmatrix}_{k | k-1}\boldsymbol{S}_k ^{-1}=[P00​P10​​]k∣k−1​Sk−1​
=[P00P10]k∣k−1Sk=\dfrac{\begin{bmatrix}P_{00}\\P_{10}\end{bmatrix}_{k | k-1}}{\boldsymbol{S}_k}=Sk​[P00​P10​​]k∣k−1​​
请注意,在其他情况下,它S可以是矩阵,而不能仅P由除以S。相反,您必须计算矩阵的逆。有关如何操作的更多信息,请参见下一页。

C实现看起来像这样:

k [ 0 ] = P [ 0 ] [ 0 ] / S ;
k [ 1 ] = P [ 1 ] [ 0 ] / S ;

Wolfram Alpha链接:

Eq. 5.1

3.4.6 step 6:

x^k∣k=x^k∣k−1+Kky~k\boldsymbol{\hat{x}}_{k | k}=\boldsymbol{\hat{x}}_{k | k-1}+\boldsymbol{K}_k\;\boldsymbol{\tilde{y}}_kx^k∣k​=x^k∣k−1​+Kk​y~​k​
[θθ˙b]k∣k=[θθ˙b]k∣k−1+[K0K1]ky~k\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_{k | k}=\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_{k | k-1}+\begin{bmatrix}K_0\\K_1\end{bmatrix}_k\boldsymbol{\tilde{y}}_ k[θθ˙b​​]k∣k​=[θθ˙b​​]k∣k−1​+[K0​K1​​]k​y~​k​
=[θθ˙b]k∣k−1+[K0y~K1y~]k=\begin{bmatrix}\theta\\\dot{\theta}_b\end{bmatrix}_{k | k-1}+\begin{bmatrix}K_0\;\boldsymbol{\tilde{y}}\\K_1\;\boldsymbol{\tilde{y}}\end{bmatrix}_k=[θθ˙b​​]k∣k−1​+[K0​y~​K1​y~​​]k​
再一次,方程式的结尾很短,可以这样用C编写:


angle + = k [ 0 ] * y ;
bias + = k [ 1 ] * y ;

3.4.7 step 7:

Pk∣k=(I−kkH)Pk∣k−1\boldsymbol{P}_{k | k}=(\boldsymbol{I}-\boldsymbol{k}_k\boldsymbol{H})\boldsymbol{P}_{k | k-1}Pk∣k​=(I−kk​H)Pk∣k−1​
[P00P01P10P11]k∣k=([1001]−[k0k1]k[10])[P00P01P10P11]k∣k−1\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k}=\left(\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}-\begin{bmatrix}k_0\\k_1\end{bmatrix}_k\begin{bmatrix}1 & 0\end{bmatrix}\right)\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k-1}[P00​P10​​P01​P11​​]k∣k​=([10​01​]−[k0​k1​​]k​[1​0​])[P00​P10​​P01​P11​​]k∣k−1​
=([1001]−[k00k10]k)[P00P01P10P11]k∣k−1=\left(\begin{bmatrix}1 & 0\\0 & 1\end{bmatrix}-\begin{bmatrix}k_0 & 0\\k_1 & 0\end{bmatrix}_k\right)\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k-1}=([10​01​]−[k0​k1​​00​]k​)[P00​P10​​P01​P11​​]k∣k−1​
=[P00P01P10P11]k∣k−1−[k0P00k0P01k1P00k1P01]=\begin{bmatrix}P_{00} & P_{01}\\P_{10} & P_{11}\end{bmatrix}_{k | k-1}-\begin{bmatrix}k_0\; P_{00} & k_0\; P_{01}\\k_1\; P_{00} & k_1\; P_{01}\end{bmatrix} =[P00​P10​​P01​P11​​]k∣k−1​−[k0​P00​k1​P00​​k0​P01​k1​P01​​]
请记住,由于状态估计的误差已减小,因此我们再次减小了误差协方差矩阵。
C代码如下所示:

float P00_temp = P [ 0 ] [ 0 ] ;
float  P01_temp = P [ 0 ] [ 1 ] ;P [ 0 ] [ 0 ] -= k [ 0 ] * P00_temp ;
P [ 0 ] [ 1 ] -= k [ 0 ] * P01_temp ;
P [ 1 ] [0 ] -= k [ 1 ] * P00_temp ;
P [ 1 ] [ 1 ] -= k [ 1 ] * P01_temp ;

Wolfram Alpha链接:

Eq. 7.1
Eq. 7.2
Eq. 7.3
请注意,我发现以下变化对大多数IMU都适用:

float Q_angle = 0.001 ;
float Q_gyroBias = 0.003 ;
float R_measure = 0.03 ;
请记住,如果需要在启动时使用输出,则在启动时设置目标角度非常重要。有关更多信息,请参见平衡机器人的校准例程。

如果您错过了它,这里是我编写的库,任何支持float 数学的微控制器都可以使用该库。可以在github上找到源代码:https : //github.com/TkJElectronics/kalmanFilter。

如果您喜欢有关卡尔曼滤波器的视频说明,建议您观看以下视频系列:http : //www.youtube.com/watch?v=FkCT_LV9Syk。

请注意,如果您需要以完整的3D方向表示物体,则不能使用该库,因为欧拉角会受到所谓的“ 云台锁定”的困扰,您将需要使用四元数来做到这一点,但这是一个完整的故事。现在,请看下面的页面。

这是所有已知的信息,希望对您有帮助,或者您有任何疑问可以在下面发表评论,如果您需要编写方程式,它也支持LaTex语法。
如果您发现任何错误,也请通知我。

另外,作为一名控制工程师,我想补充一点细节:万向节锁定的发生是由于系统的机械特性,与数学表示无关。它反映为欧拉角表示中的自由度损失和雅可比矩阵中的奇点。但是四元数也会发生同样的问题。尽管四元数不会受到奇异性的影响,因此可以跟踪角度,但是仍然会发生机械万向节锁定。考虑一下机械臂,您会发现有时一只手腕必须非常(几乎无限地)快速运动。发生这种情况是由于用于构建机器人的欧拉角的奇异性(可以在公式中使用欧拉角来反映),但是即使我们使用四元数进行跟踪(也可以正确跟踪,但速度是无限的),也会发生这种情况。不幸的是,我们无法基于四元数构建机器人手臂。问题在于逆动力学。

最后,从过滤的角度来看,只能通过欧拉角观察到万向节锁定,但是从控制的角度来看,由于机器人的机械原理,可能发生这种情况。

原文最后的评论很精彩

卡尔曼滤波器的实用方法及其实现方法相关推荐

  1. 西门子s7300 C MATLAB,卡尔曼滤波器在s7-300系列plc中的实现方法

    卡尔曼滤波器在s7-300系列plc中的实现方法 [专利摘要]本发明公开了一种卡尔曼滤波器在S7-300系列PLC中的实现方法.在S7-300系列PLC系统中定义16个数据块,其中的14个数据块和卡尔 ...

  2. 智慧交通day02-车流量检测实现05:卡尔曼滤波器实践(小车模型)

    1.filterpy FilterPy是一个实现了各种滤波器的Python模块,它实现著名的卡尔曼滤波和粒子滤波器.我们可以直接调用该库完成卡尔曼滤波器实现.其中的主要模块包括: filterpy.k ...

  3. 卡尔曼转矩观测_基于扩展卡尔曼滤波器的表贴式永磁同步电机负载转矩观测方法与流程...

    本发明涉及永磁同步电机技术领域,具体涉及基于扩展卡尔曼滤波器的表贴式永磁同步电机负载转矩观测方法. 背景技术: 永磁同步电机(pmsm:permanentmagnetsynchronousmotor) ...

  4. 教你百分百实用监控安装摄像头的方法与技巧

    教你百分百实用监控安装摄像头的方法与技巧    监控安装指导与注意事项     A.线路安装与选材    1.电源线:要选"阻燃"电缆,皮结实,在省成本前提下,尽量用粗点的,以减少 ...

  5. FBAR滤波器的工作原理及制备方法

    近年来,随着无线通信技术朝着高频率和高速度方向迅猛发展,以及电子元器件朝着微型化和低功耗的方向发展,基于薄膜体声波谐振器(Film Bulk Acoustic Resonator,FBAR)的滤波器的 ...

  6. 指尖江湖鸿蒙抽奖,《剑网3指尖江湖》里最实用的赚金方法,这招成搬砖党的福利!...

    原标题:<剑网3指尖江湖>里最实用的赚金方法,这招成搬砖党的福利! 最近正在内测的<剑网3:指尖江湖>引起不小的热议,除了硬核玩法拉高了手游玩家的门槛外,对于细节的注重也给了不 ...

  7. 卡尔曼滤波器的特殊案例

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 什么是卡尔曼滤波器? 卡阿尔曼滤波器为每个结果状态找到最佳的平均因 ...

  8. 面向软件工程师的卡尔曼滤波器

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|磐创AI 与我的朋友交谈时,我经常听到:"哦, ...

  9. matlab中卡尔曼滤波,卡尔曼滤波器和matlab代码.doc

    完美WORD格式 专业整理分享 信息融合大作业 --维纳最速下降法滤波器,卡尔曼滤波器设计及Matlab仿真 时间:2010-12-6 专业:信息工程 班级学号:2007302171 姓名:马志强 滤 ...

最新文章

  1. jenkins android sdk,Jenkins为什么找不到Android SDK?
  2. 平均数、中位数和众数及它们之间的关系
  3. Linux 爱好者的飞行棋:sudo
  4. python基础语法手册format-python基础知识之格式化
  5. VMware ESXi导出OVF模板
  6. java自动关闭吗_JAVA问题--浏览器老是自动关闭
  7. 李彦宏千字愿景内部信:10次提到“用户”
  8. [C++][IO]读写二进制文件
  9. vue 外部方法调用内部_vue函数内部调用外部函数,报错外部函数不是函数
  10. 192.168.8.1手机登陆_手机怎么登陆192.168.2.1入口?
  11. 记录——《C Primer Plus (第五版)》第八章编程练习第六题
  12. android按钮点击后闪退_iphone闪退是什么原因?
  13. Deepin使用苹果主题
  14. SENT协议学习总结
  15. WPS安装office自定义项安装期间出错
  16. 强化学习——Q学习算法
  17. python贴吧签到-百度贴吧签到脚本
  18. 【Scratch案例实操】scratch西游记师徒谁人气高 scratch编程案例教学 scratch创意编程 少儿编程教案
  19. 高效能人士的七个习惯(一)由内而外全面造就自己
  20. 23位子网掩码是多少_24位子网掩码,多少个IP地址

热门文章

  1. 汇编语言 AND逻辑与指令
  2. 减字 浣溪沙-听歌有感 (清)况周颐
  3. P3644 [APIO2015]八邻旁之桥(中位数、堆)
  4. Maven 自己下载依赖包安装到本地仓库
  5. MSVS2008和VS2010的痛苦加装
  6. 抛弃了wordpress
  7. 阿里巴巴1688诚信通通过市场全面分析选品策略
  8. Java8里不得不说的那些常用日期处理,码起来~
  9. 对待前任你有遗憾么?
  10. XTransfer技术专家亮相Flink CDC Meetup