卡尔曼滤波器(一维):几种方法?

Kalman filter (one-dimensional): several approaches?

我试图了解卡尔曼滤波器的工作原理,但由于多维变体一开始太令人困惑,所以我从一个一维示例开始。

我找到了 3 个不同的来源来解释温度计的场景,但所有这些场景实现的方程略有不同,我不明白这一点。

我实施了解决方案 2,但我的卡尔曼滤波器并没有真正发挥作用(它高度适应了测量结果,并没有真正考虑到它的噪声)。

所以,在我浪费更多时间尝试解决方案 1 或 3(到目前为止我刚刚阅读)之前:有人可以提供一个清晰的解释 and/or 一维卡尔曼代码示例过滤器?


解决方案 1

// x_est: current estimate;           p: current estimate error;
// a:     constant of the system;    kg: kalman gain
// z:     current observation; 

// Predict
x_est   =   a * x_est
p       =   a * p * a

// Update
kg      =   p  / (p  + r)
x_est   =   x_est + kg * (z - x_est)
p       =   (1 - kg) * p

作者(此处)仅说明我们仅更改当前值,因为温度计无需考虑上次值。

所以他简化了:

p[k] = (1 - kg) * p[k-1] p = (1 - kg) * p

x_est[k] = x_est[k-1] + kg * (z - x_est[k-1]) x_est = x_est + kg * (z - x_est)

...等等...

我不明白为什么这是可能的。我认为卡尔曼滤波器的主要部分之一是考虑当前观察 z 是否有用(通过卡尔曼增益)。因此,对于高卡尔曼增益 kg * (z - x_est[k-1]),将增量 z - x_est[k-1] 的 "big chunk" 添加到新估计中。如果总是计算当前值,这整个事情不是变得毫无意义吗?


解决方案 2

# q: process variance / process noise
# r: error in measurement

x_est = x_est
p     = p + q;

k     = p / (p + r);
x_est = x_est + k * (z – x_est);
p     = (1 – k) * p;

这倒是差不多,但是作者连为什么x[k-1]p[k-1]都没有解释 可以更改为 xp.


解决方案 3

# Q: process variance / process noise
# R: error in measurement

# prediction
x_est_kminus1[k] = x_est[k - 1]
p_kminus1[k]        = p[k - 1] + Q

# update
kg[k]     = p_kminus1[k] / (p_kminus1[k] + R)
x_est[k] = x_est_kminus1[k] + kg[k] * (z[k] - x_est_kminus1[k])
p[k]     = (1 - kg[k]) * p_kminus1[k]

在此解决方案中,作者为 x_estx_est 本身和 x_est_kminus1)和 pp 本身和 p_kminus1).

是否需要两个列表,否则 p[k] 将被计算两次(在预测和更新步骤中)?

所有这些解都是一般方程的特例,我们必须看看每个解有什么特别之处。

正确的方程式

让我们从适合一维情况的一般方程开始:

# prediction
x[k] = a * x[k - 1]
p[k] = a * p[k - 1] * a + q
# update
y = z - h * x[k]
kg = p * h / (h * p * h + r)
x[k] = x[k] + kg * y
p[k] = (1 - kg * h) * p[k]
  • x - 状态
  • p - 误差(协方差)
  • a - 状态转换
  • q - 转换错误
  • z - 测量
  • h - 状态到测量的转换
  • y - 我们根据预测预期测量的结果与实际测量结果之间的差异
  • kg - 卡尔曼增益
  • r - 测量误差

模型的所有参数(aqrh)原则上也可以有一个索引 k 和随着系统的发展而变化。但在简单的情况下,它们都可以作为常数。

解与正确方程有何不同

只有解决方案 1 实现了 a,这很好。 a 告诉您状态如何从一个步骤变为另一个步骤,如果您假设温度是固定的,那么 a == 1,就像解决方案 2 和 3 一样。

解决方案 1 没有 qq 是我们可以估计过程误差的地方。同样,如果该过程是关于系统静止的 (a == 1),那么我们可以设置 q = 0.

None 你的解决方案有一个 h,这是观察转换(如何从测量到状态)。如果您要根据温度测量值估算温度,则 h = 1

h 可能与 1 不同的一个例子是,如果您测量的是您感兴趣的其他东西,例如使用湿度测量来估计温度。那么 h 将是 线性 变换 T(humidity) = h * humidity。我强调线性是因为以上是线性卡尔曼滤波方程,它们只适用于线性(数学意义上的)系统。

当前和上一步问题

kk - 1 以及 x_estx_est_kminus1 的问题纯粹是一个实现问题。在这方面你所有的解决方案都是一样的。

您对解决方案 1 中 kk - 1 的想法是错误的。只有预测阶段需要考虑当前和上一步(因为它是基于上一步对当前状态的预测),而不是更新步骤。更新步骤作用于预测。

从可读性的角度来看,解决方案 3 最接近数学方程式。原则上,预测步骤还没有给我们 x_est[k],但更像是 predicted_x_est[k]。然后更新步骤在此 predicted_x_est[k] 上运行并为我们提供实际的 x_est[k].

然而正如我所说,所有实现都是等效的,因为在对它们进行编程时,您可以看到在预测步骤之后,不再需要过去。因此,您可以安全地为 px 使用一个变量,而无需保留列表。

关于卡尔曼增益

您写道:

So that for a high Kalman gain kg * (z - x_est[k-1]) a "big chunk" of the delta z - x_est[k-1] is added to the new estimate. Isn't this whole thing getting pointless, if one always calculates the current values?

在这些情况下,卡尔曼增益只能在0和1之间。什么时候最大?当 r(测量误差)为 0 时,这意味着我们无限信任我们的测量。然后等式简化为

x_est = x_est + z - x_est

这意味着我们放弃了我们的预测值(右侧的 x_est)并将更新后的估计值设置为等于我们的测量值。当我们无限相信我们测量的东西时,这是一件有效的事情。

适应测量

I implemented solution 2 but my kalman filter was not really working (it highly adapted itself to the measurements and not really considered the noise on it).

调整卡尔曼滤波器非常棘手,需要深入了解系统并正确估计 qr。请记住,q 是过程(状态演化)的误差,r 是我们测量的误差。如果您的卡尔曼滤波器过于适应测量结果,则意味着:

  • q 太大
  • r太小了

或两者的结合。您必须尝试使用​​这些值才能找到有效的值。