先说个题外话。我在做传感器融合和定位相关项目时,经常遇到这种情况:同学或同事一听到“卡尔曼滤波”这个名字,第一反应是“那是搞控制或无人机的人才会用的高级算法”,然后就绕道走了。但当我告诉他们“你看手机里的导航、手环里的计步、甚至你打游戏时鼠标的平滑移动,背后都有这个算法的影子”时,大家又往往露出“原来是它”的表情。
所以这篇系列开篇,我打算不画任何复杂的流程图,不搬一堆云里雾里的公式吓人,而是沿着一条最自然的思考路径,把“贝叶斯滤波”和“卡尔曼滤波”这两件事彻底讲清楚。尤其要把“为什么卡尔曼滤波是贝叶斯滤波的一种特例”这种听起来很抽象的话,落到可以手推、可以写代码、可以跑起来看效果的程度。这篇偏重梳理脉络和推导,下一篇会专门聊工程实现和参数调优。
1. 先把问题摆出来:我们到底在“滤”什么东西
先说个经典场景。你有一个无人机,想知道它现在飞在什么位置。GPS告诉你一个位置,但GPS有误差,可能有5到10米的偏移;惯性传感器告诉你一个位置,但它是通过对加速度积分算出来的,时间一长就会飘。两个来源都有噪声,都不完美,你该怎么判断无人机到底在哪?
这就是状态估计问题的雏形:系统里有一个我们看不见的真实状态(位置、速度、温度、电压等),我们手上只有一组被噪声污染过的观测数据,需要想办法把真实状态“估计”出来。“滤波”这个词听起来像是在说“滤掉噪声”,其实是这个意思——从有噪声的观测里把干净的状态提取出来。
假设我们从第1帧观测一直做到第k帧观测,拿到了 (z_{1:k}),希望求当前状态 (x_k) 的概率分布:
[
P(x_k | z_{1:k})
]
这个式子翻译成人话就是:在已经看到了到目前为止全部观测数据的前提下,状态是 (x_k) 的可能性有多大。在数学上,它叫“后验概率分布”。有了这个分布,我们不光能知道“状态最可能是多少”(取分布的均值),还能知道“我们有多确定”(看分布的方差)。这就是贝叶斯滤波的起点——把估计问题当成“算概率”的问题来做。
如果状态变量是离散的,那这个概率分布就是一堆离散值上的概率质量;如果状态变量是连续的,那就是一个概率密度函数。不管是离散还是连续,思路完全一样。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 贝叶斯滤波:一个朴素但“算不动”的框架
2.1 预测和更新:贝叶斯滤波的两板斧
贝叶斯滤波不指定系统长什么样,它只要求我们能用两个模型描述这个系统:
- 状态转移模型:描述状态随时间怎么演化,即 (x_k) 如何从 (x_{k-1}) 变化而来,记为 (P(x_k|x_{k-1}))。
- 观测模型:描述在某个状态下我们会观测到什么,即 (z_k) 与 (x_k) 的关系,记为 (P(z_k|x_k))。
有了这两个模型,贝叶斯滤波就是一个两步循环:
第一步,预测(也叫先验更新): 在上一步得到后验 (P(x_{k-1}|z_{1:k-1})) 之后,利用状态转移模型预测当前时刻的状态:
[
P(x_k | z_{1:k-1}) = \int P(x_k | x_{k-1}) P(x_{k-1} | z_{1:k-1}) , dx_{k-1}
]
这其实就是全概率公式。它相当于在说:我不确定上一时刻的状态具体是哪一个,但我对上一时刻的状态有一个概率描述,把这些可能性全部“加权平均”地往前推进。
第二步,更新(也叫后验修正): 当新的观测 (z_k) 到来,用贝叶斯公式修正预测结果:
[
P(x_k | z_{1:k}) = \frac{P(z_k | x_k) P(x_k | z_{1:k-1})}{P(z_k | z_{1:k-1})}
]
分母是一个归一化常数,作用是保证右边积分出来等于1:
[
P(z_k | z_{1:k-1}) = \int P(z_k | x_k) P(x_k | z_{1:k-1}) , dx_k
]
这个框架在概念上非常优雅,每一步都有清晰的概率含义。它的缺点也一眼就能看出来:每一步都有一个积分,而一般函数的积分没有解析解,只能在离散网格上做数值近似。如果状态是连续的高维向量(比如位置+速度+朝向就是4到9维),离散网格的网格点数量会随维度指数爆炸,根本算不过来。
2.2 贝叶斯滤波的工程困境:积分这个拦路虎
我在实际课程和代码里,见过太多人在贝叶斯滤波这一步被劝退。因为一旦涉及连续状态,贝叶斯滤波需要数值积分,而这个数值积分的代价高到不可接受。
MIT 有一门经典课程叫“Underactuated Robotics”,里面就专门讲到:贝叶斯滤波是概率机器人学的灵魂框架,但实际实现时几乎没有人直接积分贝叶斯公式,所有人都在寻找能够绕过那个积分、同时保持问题结构的方式。卡尔曼滤波就是其中最成功的一种“特例”。
