以图的形式解释卡尔曼滤波工作(How a Kalman filter works, in pictures)
本文是一个学习笔记,内容的 原文
What is it?
卡尔曼滤波是一种通用的强大的信息融合(combining information)工具(但是因为最原始卡尔曼滤波是一种线性的,对严重的非线性无法很好的估计,所以有后续的扩展卡尔曼滤波,后续更新),可以在任何有不确定信息(uncertain information)的地方使用,即使系统又很大的干扰也可以得到不错的结果,并且可以利用到你想象不到的相关性。
卡尔曼滤波非常适合这些不断变化的系统。它们具有的优点是:轻量级存储(它们不需要保存上一状态以外的任何历史数据),计算快速,这使得它们非常适合于实时问题和嵌入式系统。
What we do with a Kalman filter?
看一个小栗子:有一个机器人在深林里漫步,她需要知道自己哪里可以走
假设她在状态
x
k
⃗
\vec{x_k}
xk,包含有位置和速度信息:
x
k
⃗
=
(
p
⃗
,
v
⃗
)
\vec{x_k} = (\vec{p}, \vec{v})
xk=(p,v)
状态就是你系统基本配置(configuration)的数字列表;它可以是任何变量。在这个例子中,状态就是位置和速度,但是它可以是油罐中液体的总量数据、引擎的温度、用户手指在平板上的位置,或者任何你想要观察的数据。
我们的机器人有一个 GPS,精确约为10米,正常工作,但是我们对机器人定位的精度要求高于10米。树林里有很多沟和崖,如果机器人走错几英尺,就可能跌落悬崖。所以仅有 GPS 是不够的。
我们还知道机器人如何移动的一些信息:她发送给轮子的指令,她的头的朝向以及没有障碍,下一步,它可能就沿着这个方向前进。当然,它不可能知道运动过程中的所有状况:它可能被风刮倒,车轮可能打滑,或者在颠簸的路面侧翻;所以轮子的转角并不能精确的表示机器人走了多远,这个预测不是完美的。
GPS告诉我们一些状态信息,但是不直接的,有一些不确定性和不准确性。我们的预测是告诉我们机器人如何移动,但也是不直接的,有一些不确定性和不准确性。
如果我们能利用所有可用的信息,能给我们跟好的估计结果,这既是卡尔曼滤波的精髓。
How a Kalman filter sees your problem
继续刚才的问题,我们还是使用简单的状态,只有位置和速度的情况:
x
⃗
=
[
p
v
]
\vec{x} = \begin{bmatrix} p\\ v \end{bmatrix}
x=[pv]
我们不知道实际的位置和速度,有一系列可能的位置与速度的组合,但是其中的一些可能性更高:
上图是一个二维高斯分布的投影图片,卡尔曼滤波假设两个变量(位置和速度,在我们的case中)是随机高斯分布的。每个变量都有均值
μ
\mu
μ(随机分布的中心)和方差
σ
2
\sigma^2
σ2(表示不确定性)。
上图表示的是位置和速度是不相关的,相关性的概念在概率论里有讲。大概意思就是一个变量不会告诉你另一个变量的信息。
下面的例子中:位置和速度是相关的。一个指定位置的可能观测值取决于速度:
这种情况用于利用上旧的状态估计下一个状态,速度越大跑的越远。
这种关系在跟踪定位时非常重要,因为这会提供更多信息:一个测量值告诉我们其他测量值的可能范围。这就是卡尔曼滤波器的目标,我们希望从不确定的测量值中得到尽可能多的信息。
这种关系由协方差矩阵给出。简单来说,协方差矩阵的每个元素 Σ i j \Sigma_{ij} Σij都是第 i i i个状态变量和第 j j j个状态变量的相关程度。(所以协方差矩阵是对称的,交换 i i i和 j j j并不影响)协方差矩阵通常用“ Σ \Sigma Σ”表示,所以将其元素称为“ Σ i j \Sigma_{ij} Σij”。
Describing the problem with matrices
我们要建模需要在时间
k
k
k上的Gaussian blob,需要两条信息,最优估计
x
^
k
\mathbf{\hat{x}_k}
x^k(也称为均值
μ
\mu
μ)和协方差矩阵
P
k
\mathbf{P_k}
Pk。
x
^
k
=
[
position
velocity
]
P
k
=
[
Σ
p
p
Σ
p
v
Σ
v
p
Σ
v
v
]
(1)
\begin{aligned} \mathbf{\hat{x}}_k &= \begin{bmatrix} \text{position}\\ \text{velocity} \end{bmatrix}\\ \mathbf{P}_k &= \begin{bmatrix} \Sigma_{pp} & \Sigma_{pv} \\ \Sigma_{vp} & \Sigma_{vv} \\ \tag{1} \end{bmatrix} \end{aligned}
x^kPk=[positionvelocity]=[ΣppΣvpΣpvΣvv](1)
(这里只用到了位置和速度,但记得状态可以包括许多变量你想要的都可以呈现上去)
接下来我们需要在当前状态(current state) k − 1 k-1 k−1 时刻去预测在在 k k k 时刻的下一个状态。记得我们并不知道哪个状态是真实的,但是预测方程并不关心。它根据所有可能状态,给出一个新的分布:
我们可以用矩阵
F
k
\mathbf{F_k}
Fk 表示该预测步骤:
把我们原始估计(original estimate)的每一个点移动到新的预测点,如果原始估计是对的话,这些预测点就是系统可能移动的地方。(注:这里的原始估计就是上图中蓝色的框框的区域,是
k
−
2
k-2
k−2时刻估计出来的)
我们用基本的运动学方程来表示这个估计:
p
k
=
p
k
−
1
+
Δ
t
v
k
−
1
v
k
=
v
k
−
1
\begin{aligned} \color{deeppink}{p_k} &= \color{royalblue}{p_{k-1}} + \Delta t &\color{royalblue}{v_{k-1}} \\ \color{deeppink}{v_k} &= &\color{royalblue}{v_{k-1}} \end{aligned}
pkvk=pk−1+Δt=vk−1vk−1
用矩阵表示:
x
^
k
=
[
1
Δ
t
0
1
]
x
^
k
−
1
=
F
k
x
^
k
−
1
(2)
\begin{aligned} \color{deeppink}{\mathbf{\hat{x}}_k} &= \begin{bmatrix} 1 & \Delta t \\ 0 & 1 \end{bmatrix} \color{royalblue}{\mathbf{\hat{x}}_{k-1}}\\ &= \mathbf{F}_k \color{royalblue}{\mathbf{\hat{x}}_{k-1}} \tag{2} \end{aligned}
x^k=[10Δt1]x^k−1=Fkx^k−1(2)
我们现在有了预测下一状态的预测矩阵,但是仍然不知道怎样更新协方差矩阵。
我们需要另一个方程。如果我们对分布中的每一个点乘以一个矩阵 A \color{firebrick}{\mathbf{A}} A,那么协方差矩阵 Σ \Sigma Σ这比较简单,我将直接给出:
C
o
v
(
x
)
=
Σ
C
o
v
(
A
x
)
=
A
Σ
A
T
(3)
\begin{aligned} Cov(x) &= \Sigma\\ Cov(\color{firebrick}{\mathbf{A}}x) &= \color{firebrick}{\mathbf{A}} \Sigma \color{firebrick}{\mathbf{A}}^T \end{aligned} \tag{3}
Cov(x)Cov(Ax)=Σ=AΣAT(3)
结合(2)和(3):
x
^
k
=
F
k
x
^
k
−
1
P
k
=
F
k
P
k
−
1
F
k
T
(4)
\begin{aligned} \color{deeppink}{\mathbf{\hat{x}}_k} &= \mathbf{F}_k \color{royalblue}{\mathbf{\hat{x}}_{k-1}} \\ \color{deeppink}{\mathbf{P}_k} &= \mathbf{F_k} \color{royalblue}{\mathbf{P}_{k-1}} \mathbf{F}_k^T \end{aligned} \tag{4}
x^kPk=Fkx^k−1=FkPk−1FkT(4)
External influence
我们没有利用到所有信息,外部世界的某些变化可能跟状态没有关系,但是会影响到系统。例如列车员推动气阀会使车的速度变化,同样我们的机器人会发送指令给轮子走或停。如果我们知道更多的关于真实世界的信息,我们可以将这些写成一个向量叫做
u
k
⃗
\color{darkorange}{\vec{\mathbf{u}_k}}
uk,加入到我们的预测作为一种修正。
例如我们知道加速度
a
\color{darkorange}{a}
a表示控制指令,从基础的运动学公式:
p
k
=
p
k
−
1
+
Δ
t
v
k
−
1
+
1
2
a
Δ
t
2
v
k
=
v
k
−
1
+
a
Δ
t
\begin{aligned} \color{deeppink}{p_k} &= \color{royalblue}{p_{k-1}} + {\Delta t} &\color{royalblue}{v_{k-1}} + &\frac{1}{2} \color{darkorange}{a} {\Delta t}^2 \\ \color{deeppink}{v_k} &= &\color{royalblue}{v_{k-1}} + & \color{darkorange}{a} {\Delta t} \end{aligned}
pkvk=pk−1+Δt=vk−1+vk−1+21aΔt2aΔt
矩阵形式:
x
^
k
=
F
k
x
^
k
−
1
+
[
Δ
t
2
2
Δ
t
]
a
=
F
k
x
^
k
−
1
+
B
k
u
k
⃗
(5)
\begin{aligned} \color{deeppink}{\mathbf{\hat{x}}_k} &= \mathbf{F}_k \color{royalblue}{\mathbf{\hat{x}}_{k-1}} + \begin{bmatrix} \frac{\Delta t^2}{2} \\ \Delta t \end{bmatrix} \color{darkorange}{a} \\ &= \mathbf{F}_k \color{royalblue}{\mathbf{\hat{x}}_{k-1}} + \mathbf{B}_k \color{darkorange}{\vec{\mathbf{u}_k}} \end{aligned} \tag{5}
x^k=Fkx^k−1+[2Δt2Δt]a=Fkx^k−1+Bkuk(5)
B
k
\mathbf{B}_k
Bk叫控制矩阵(control matrix),
u
k
⃗
\color{darkorange}{\vec{\mathbf{u}_k}}
uk叫控制向量(control vector),如果没有外界控制影响可以忽略他们。
External uncertainty
如果状态只根据自身的属性变化,则没有问题。如果状态同时根据外部作用变化,只要我们知道外部作用力是啥,也没有问题。原文举例这里不解释了。
我们关于“世界”(我们没有keep track的)的不确定性建模,每一步预测都添加一点新的不确定性:
在原始估计中的每一个状态都能够转移到一定状态范围。因为高斯斑,可以说,在
x
^
k
−
1
\color{royalblue}{\mathbf{\hat{x}}_{k-1}}
x^k−1的每一个点,都移动到了一个协方差为
Q
k
\color{mediumaquamarine}{\mathbf{Q}_k}
Qk的高斯斑中。换一种说法就是,我们将不确定的影响看作是协方差
Q
k
\color{mediumaquamarine}{\mathbf{Q}_k}
Qk的噪声。
(注:增加了不确定性以后,原来的一个点转移到下一时刻就是根据方程算出来对应的某处,但是增加了不确定性以后,可能在新的区域绿色框框内的某处了)
这会产生一个新的高斯斑,有新的协方差(相同的期望):
这个扩展的协方差通过加
Q
k
\color{mediumaquamarine}{\mathbf{Q}_k}
Qk得到,所以完整的预测表达式:
x
^
k
=
F
k
x
^
k
−
1
+
B
k
u
k
⃗
P
k
=
F
k
P
k
−
1
F
k
T
+
Q
k
\begin{aligned} \color{deeppink}{\mathbf{\hat{x}}_k} &= \mathbf{F}_k \color{royalblue}{\mathbf{\hat{x}}_{k-1}} + \mathbf{B}_k \color{darkorange}{\vec{\mathbf{u}_k}} \\ \color{deeppink}{\mathbf{P}_k} &= \mathbf{F_k} \color{royalblue}{\mathbf{P}_{k-1}} \mathbf{F}_k^T + \color{mediumaquamarine}{\mathbf{Q}_k} \end{aligned}
x^kPk=Fkx^k−1+Bkuk=FkPk−1FkT+Qk
也就是说,新的最优估计是由上一时刻的最优估计进行预测,加上已知外部影响的修正得到的。
新的不确定性是由上一时刻的不确定性进行预测,加上一些环境中额外的不确定性。
这就简单了,我们有了系统当前状态的模糊估计( x ^ k , P k \color{deeppink}{\mathbf{\hat{x}}_k},\color{deeppink}{\mathbf{P}_k} x^k,Pk)。接下来看看从传感器获取数据时发生了什么。
Refining the estimate with measurements(测量值矫正估计)
系统有一些传感器,间接给一些状态信息,换句话说就是:传感器在某一状态,给出一系列读数。
读数的单位和量程可能与状态的不同,我们用矩阵
H
k
\mathbf{H}_k
Hk对传感器建模。
我们能够得到传感器读数的分布:
μ
⃗
expected
=
H
k
x
^
k
Σ
expected
=
H
k
P
k
H
k
T
\begin{aligned} \vec{\mu}_{\text{expected}} &= \color{deeppink}\mathbf{H}_k \color{deeppink}{\mathbf{\hat{x}}_k} \\ \mathbf{\Sigma}_{\text{expected}} &= \color{deeppink}\mathbf{H}_k \color{deeppink}{\mathbf{P}_k} \mathbf{H}_k^T \end{aligned}
μexpectedΣexpected=Hkx^k=HkPkHkT
卡尔曼滤波适合于处理传感器的噪声。也就是说,传感器多少都会有些不可靠性,原始估计中的每一个状态的传感器读数都会是一个范围值。
从我们观测到的每一个读数,我们可能猜测系统在一个特定的状态。但是因为存在不确定性,观测到的数据中某些状态的可能性会比较高。(眼见不一定为实,某些数据偏高了)
称这个不确定性(传感器噪声)的协方差为
R
k
\color{mediumaquamarine}{\mathbf{R}_k}
Rk。该分布的期望和观测到的读数相同 ,称为
z
k
⃗
\color{yellowgreen}{\vec{\mathbf{z}_k}}
zk。
现在,我们得到两个高斯斑:一个表示系统状态预测;一个表示传感器读数。
接下来就是要协调预测值和传感器读数值。
所以哪个更接近真实的状态呢?我们认为观测的是错误的,预测值是我们想看到的。如果我们有两个概率,想知道两个概率都是真的(重叠)只要把他们乘起来(概率论的知识)。
重叠的部分就是最有可能的部分,就是根据已有的新的的最好估计。看起来像另一个高斯斑(gaussian blob)。
Combining Gaussians
(注:这节前面就是一些概率论的知识,两个高斯函数相乘的分布等等,不会的就补数学知识咯)
先假设一维的高斯分布相乘:
N
(
x
,
μ
0
,
σ
0
)
⋅
N
(
x
,
μ
1
,
σ
1
)
=
?
N
(
x
,
μ
’
,
σ
’
)
\begin{aligned} \mathcal{N}(x, \color{fuchsia}{\mu_0}, \color{deeppink}{\sigma_0}) \cdot \mathcal{N}(x, \color{yellowgreen}{\mu_1}, \color{mediumaquamarine}{\sigma_1}) \stackrel{?}{=} \mathcal{N}(x, \color{royalblue}{\mu’}, \color{mediumblue}{\sigma’}) \end{aligned}
N(x,μ0,σ0)⋅N(x,μ1,σ1)=?N(x,μ’,σ’) 结果:
μ
’
=
μ
0
+
σ
0
2
(
μ
1
–
μ
0
)
σ
0
2
+
σ
1
2
σ
’
2
=
σ
0
2
–
σ
0
4
σ
0
2
+
σ
1
2
\begin{aligned} \color{royalblue}{\mu’} &= \mu_0 + \frac{\sigma_0^2 (\mu_1 – \mu_0)} {\sigma_0^2 + \sigma_1^2}\\ \color{mediumblue}{\sigma’}^2 &= \sigma_0^2 – \frac{\sigma_0^4} {\sigma_0^2 + \sigma_1^2} \end{aligned}
μ’σ’2=μ0+σ02+σ12σ02(μ1–μ0)=σ02–σ02+σ12σ04
简单分解出一个因子
k
\color{purple}{\mathbf{k}}
k:
k
=
σ
0
2
σ
0
2
+
σ
1
2
\begin{aligned} \color{purple}{\mathbf{k}} = \frac{\sigma_0^2}{\sigma_0^2 + \sigma_1^2} \end{aligned}
k=σ02+σ12σ02
μ
’
=
μ
0
+
k
(
μ
1
–
μ
0
)
σ
’
2
=
σ
0
2
–
k
σ
0
2
\begin{aligned} \color{royalblue}{\mu’} &= \mu_0 + &\color{purple}{\mathbf{k}} (\mu_1 – \mu_0)\\ \color{mediumblue}{\sigma’}^2 &= \sigma_0^2 – &\color{purple}{\mathbf{k}} \sigma_0^2 \end{aligned}
μ’σ’2=μ0+=σ02–k(μ1–μ0)kσ02
我们把上式写成高维的形式:
Σ
\Sigma
Σ表示高斯斑的协方差矩阵,
μ
⃗
\vec{\mu}
μ表示每个轴的均值:
K
=
Σ
0
(
Σ
0
+
Σ
1
)
−
1
\begin{aligned} \color{purple}{\mathbf{K}} = \Sigma_0 (\Sigma_0 + \Sigma_1)^{-1} \end{aligned}
K=Σ0(Σ0+Σ1)−1
K
\color{purple}{\mathbf{K}}
K称为卡尔曼增益矩阵。
Putting it all together
我们有两个分布:预估测量
(
μ
0
,
Σ
0
)
=
(
H
k
x
^
k
,
H
k
P
k
H
k
T
)
(\color{fuchsia}{\mu_0}, \color{deeppink}{\Sigma_0}) = (\color{fuchsia}{\mathbf{H}_k \mathbf{\hat{x}}_k}, \color{deeppink}{\mathbf{H}_k \mathbf{P}_k \mathbf{H}_k^T})
(μ0,Σ0)=(Hkx^k,HkPkHkT)和观测测量
(
μ
1
,
Σ
1
)
=
(
z
k
⃗
,
R
k
)
(\color{yellowgreen}{\mu_1}, \color{mediumaquamarine}{\Sigma_1}) = (\color{yellowgreen}{\vec{\mathbf{z}_k}}, \color{mediumaquamarine}{\mathbf{R}_k})
(μ1,Σ1)=(zk,Rk),把他们弄到一起:
H
k
x
^
k
’
=
H
k
x
^
k
+
K
(
z
k
⃗
–
H
k
x
^
k
)
H
k
P
k
’
H
k
T
=
H
k
P
k
H
k
T
–
K
H
k
P
k
H
k
T
\begin{aligned} \mathbf{H}_k \color{royalblue}{\mathbf{\hat{x}}_k’} &= \color{fuchsia}{\mathbf{H}_k \mathbf{\hat{x}}_k} & + & \color{purple}{\mathbf{K}} ( \color{yellowgreen}{\vec{\mathbf{z}_k}} – \color{fuchsia}{\mathbf{H}_k \mathbf{\hat{x}}_k} ) \\ \mathbf{H}_k \color{royalblue}{\mathbf{P}_k’} \mathbf{H}_k^T &= \color{deeppink}{\mathbf{H}_k \mathbf{P}_k \mathbf{H}_k^T} & – & \color{purple}{\mathbf{K}} \color{deeppink}{\mathbf{H}_k \mathbf{P}_k \mathbf{H}_k^T} \end{aligned}
Hkx^k’HkPk’HkT=Hkx^k=HkPkHkT+–K(zk–Hkx^k)KHkPkHkT
卡尔曼增益是:
K
=
H
k
P
k
H
k
T
(
H
k
P
k
H
k
T
+
R
k
)
−
1
\begin{aligned} \color{purple}{\mathbf{K}} = \color{deeppink}{\mathbf{H}_k \mathbf{P}_k \mathbf{H}_k^T} ( \color{deeppink}{\mathbf{H}_k \mathbf{P}_k \mathbf{H}_k^T} + \color{mediumaquamarine}{\mathbf{R}_k})^{-1} \end{aligned}
K=HkPkHkT(HkPkHkT+Rk)−1
把
H
k
x
^
k
’
\mathbf{H}_k \color{royalblue}{\mathbf{\hat{x}}_k’}
Hkx^k’ 的
H
k
\mathbf{H}_k
Hk 去掉,把
H
k
P
k
’
H
k
T
\mathbf{H}_k \color{royalblue}{\mathbf{P}_k’} \mathbf{H}_k^T
HkPk’HkT 的左右两边都去掉,怎么去就是 线性代数的基本问题了,得到:
x
^
k
’
=
x
^
k
+
K
’
(
z
k
⃗
–
H
k
x
^
k
)
P
k
’
=
P
k
–
K
’
H
k
P
k
\begin{aligned} \color{royalblue}{\mathbf{\hat{x}}_k’} &= \color{fuchsia}{\mathbf{\hat{x}}_k} & + & \color{purple}{\mathbf{K}’} ( \color{yellowgreen}{\vec{\mathbf{z}_k}} – \color{fuchsia}{\mathbf{H}_k \mathbf{\hat{x}}_k} ) \\ \color{royalblue}{\mathbf{P}_k’} &= \color{deeppink}{\mathbf{P}_k} & – & \color{purple}{\mathbf{K}’} \color{deeppink}{\mathbf{H}_k \mathbf{P}_k} \end{aligned}
x^k’Pk’=x^k=Pk+–K’(zk–Hkx^k)K’HkPk
K
’
=
P
k
H
k
T
(
H
k
P
k
H
k
T
+
R
k
)
−
1
\begin{aligned} \color{purple}{\mathbf{K}’} = \color{deeppink}{\mathbf{P}_k \mathbf{H}_k^T} ( \color{deeppink}{\mathbf{H}_k \mathbf{P}_k \mathbf{H}_k^T} + \color{mediumaquamarine}{\mathbf{R}_k})^{-1} \end{aligned}
K’=PkHkT(HkPkHkT+Rk)−1
得到了完整的更新步骤。
x
^
k
’
\color{royalblue}{\mathbf{\hat{x}}_k’}
x^k’是校正后的最优估计,我们可以继续,将其与
P
k
’
\color{royalblue}{\mathbf{P}_k’}
Pk’投入下一轮的预测、更新。
后记
后记是我在看这篇intro的时候学到的一些知识点。感觉对一些参数有更深刻的理解或者解开了一些疑惑吧。
- 首先对于参数 A A A ,就是上面写的 F k F_k Fk 是 k − 1 k-1 k−1 到 k k k 的关系矩阵,实际过程中可能是个变化量,这个值跟现控里面的状态空间表达式那个有点类似吧(这个我个人感觉,还不太确定待求证); B B B 是和输入相关的矩阵; H H H 是测量状态到测量值 z k z_k zk 的变换矩阵,实际过程也可能是变换的,有时候假设不变。
- 测量误差协方差 R k R_k Rk 通常都是经验值,我们也可以使用一些off-line sample measurements去计算,但是怎么算,概率论只学了一维的协方差计算,还没学习高维的,以后可能会学到。
- 过程噪声协方差 Q k Q_k Qk 通常更难确定,因为我们没有能力去直接观察我们estimating的过程,但是通常简单的过程模型就能产生不错的结果了,如果过于复杂就会给系统认为“injects”不确定性。
- 通常我们就手动调参,理论上能获的更好的结果,如果需要先验地算出这两个参数,就需要系统辨识(system identification)的知识,我表示不会。
- 通常在 Q Q Q 和 R R R 是固定的常数下, P k P_k Pk 和 K k K_k Kk 可以快速地收敛并保持不变,这种情况下我们就可以off-line地估计出这两个数。