卡尔曼滤波详解——预测更新循环的直觉理解
上篇聊了传感器数据融合的基础——为什么要融合、融合的层次、集中式和分布式架构的区别。讲到融合的具体实现时,我提了一嘴卡尔曼滤波,说它是传感器融合中最核心的工具。
这话真不是吹的。你去面试任何一家做移动机器人的公司,面试官问"你了解卡尔曼滤波吗",这基本是送分题——你要答不上来,后面聊SLAM、聊控制理论都没底气。
但卡尔曼滤波这个东西,教科书上的公式看着吓人,网上博客讲得又太抽象。今天这篇,我想换个方式——从直觉出发,把预测-更新这个循环掰开了讲清楚,让你面试的时候能用自己的话讲出来,而不是背公式。
从一个最蠢的例子说起
想象你蒙着眼睛在一片空旷的平地上走路。你只知道两件事:
- 你每一步大概走多远(但不太准,可能走多了也可能走少了)
- 有个朋友在旁边看着你,时不时告诉你"你现在大概在哪个位置"(但他眼神也不太好)
你怎么确定自己的位置?
这就是卡尔曼滤波要解决的核心问题——结合"我知道大概会怎样"和"我看到的测量值",得到一个比两者都更准的估计。
你的步伐信息就是预测,朋友的提示就是更新。卡尔曼滤波做的事情,说白了就是这个预测-更新循环的不断重复。
预测步:我觉得我会到哪
每一步预测,卡尔曼滤波干的事情就两件事:
预测状态:根据上一步的最优估计和运动模型,推算这一步的状态。比如上一步你估计自己在(3, 0)的位置,速度是1m/s向东,那0.1秒后你大概在(3.1, 0)。
预测协方差:这个估计有多不确定?因为上一步的估计本身就有误差,运动模型也不完美,所以预测的不确定性一定会比上一步大。协方差矩阵就是描述这种不确定性的。
用数学表达就是:
# 预测步
x_pred = F @ x_prev + B @ u # 状态预测
P_pred = F @ P_prev @ F.T + Q # 协方差预测
这里F是状态转移矩阵(描述系统怎么从一步变到下一步),B @ u是控制输入(比如你的加速度),Q是过程噪声协方差(模型有多不准)。
面试的时候,面试官问你"预测步的物理意义是什么",你就说:预测步就是拿上一步最好的估计,往前推一步。但因为模型不完美、上一步估计也有误差,所以预测结果的不确定性一定比上一步大——协方差矩阵变大了。
更新步:看到测量值后修正
预测完了,你拿到了一个新的传感器测量值。这个测量值准不准?不一定。但它提供了新的信息,你应该用它来修正你的预测。
更新步也干两件事:
计算卡尔曼增益:这个增益是个权重,决定了"我到底该更相信预测还是更相信测量"。如果预测很准(协方差小),增益就小,更相信预测。如果测量很准(测量噪声小),增益就大,更相信测量。
修正状态和协方差:用测量值和预测值的差(叫"新息"),乘以卡尔曼增益,修正预测状态。同时,因为融合了新的测量信息,不确定性减小了——协方差矩阵变小。
# 更新步
K = P_pred @ H.T @ np.linalg.inv(H @ P_pred @ H.T + R) # 卡尔曼增益
x_est = x_pred + K @ (z - H @ x_pred) # 状态更新
P_est = (np.eye(n) - K @ H) @ P_pred # 协方差更新
这里H是观测矩阵(把状态空间映射到测量空间),R是测量噪声协方差,z是实际测量值,z - H @ x_pred就是新息。
讲真,卡尔曼增益的物理意义是面试高频考点。你就记住一句话:卡尔曼增益是一个最优权重,它在"预测的不确定性"和"测量的不确定性"之间做权衡,使得最终估计的均方误差最小。
为什么叫"最优"?它有啥假设?
卡尔曼滤波被称为"最优"估计器,但这个最优是有前提的:
- 系统是线性的:状态转移和观测都必须是线性关系。如果不是线性的,就得用扩展卡尔曼滤波(EKF)或无迹卡尔曼滤波(UKF),后面两篇会讲。
- 噪声是高斯的:过程噪声和测量噪声都服从高斯分布。这个假设在实际中通常近似成立(中心极限定理嘛)。
- 噪声统计特性已知:Q和R矩阵你得提前知道或者调出来。这个在工程上是个大坑——Q和R的调参直接影响滤波效果,但很多时候只能靠经验或者反复试验。
面试的时候,如果面试官问"卡尔曼滤波的局限性是什么",你就说这三条。然后补充一句"实际应用中最大的问题是Q和R的调参,以及线性假设在很多系统中不成立"。面试官会觉得你真的做过工程。
一个完整的Python示例
来看一个一维匀速运动跟踪的例子。假设一个目标沿直线匀速运动,我们用位置传感器来跟踪它。
import numpy as np
dt = 0.1 # 时间步长
F = np.array([[1, dt], [0, 1]]) # 状态转移矩阵
H = np.array([[1, 0]]) # 观测矩阵
Q = np.array([[0.01, 0], [0, 0.01]]) # 过程噪声
R = np.array([[0.5]]) # 测量噪声
x = np.array([[0], [1]]) # 初始状态 [位置, 速度]
P = np.eye(2) # 初始协方差
for z_meas in measurements:
# 预测
x_pred = F @ x
P_pred = F @ P @ F.T + Q
# 更新
S = H @ P_pred @ H.T + R
K = P_pred @ H.T @ np.linalg.inv(S)
x = x_pred + K @ (np.array([[z_meas]]) - H @ x_pred)
P = (np.eye(2) - K @ H) @ P_pred
这个例子虽然简单,但包含了卡尔曼滤波的全部核心逻辑。实际工程中,比如机器人定位,状态向量会变成[x, y, yaw, vx, vy, omega]六维,F和H矩阵会复杂一些,但预测-更新的框架完全一样。
工程中Q和R怎么调
讲真,教科书上从不讲这个,但这恰恰是工程中最头疼的问题。
R(测量噪声)相对好搞。如果你用的是厂家给的传感器规格书,上面通常会写精度(比如GPS定位精度±2m),你可以把这个精度当作标准差,平方一下就得到R。如果条件允许,做个静态实验——让传感器静止不动,采几百个数据,算方差,就是R。
Q(过程噪声)就麻烦了。它描述的是"你的运动模型有多不准"。如果你用匀速模型,但实际运动有加速度变化,那Q就得大一些来吸收这些未建模的加速度。经验做法是:先把Q设小,看滤波结果是否跟不上实际轨迹(滞后),如果滞后了就加大Q。反过来,如果滤波结果跳变太厉害,说明Q太大了,测量噪声的影响太大,减小Q。
之前做AMR的时候,我们在调EKF的Q矩阵上花了整整两周。最后发现,与其用一个固定的Q,不如根据机器人的运动状态动态调整——直线匀速时Q小一些,转弯时Q大一些。这个技巧在面试中可以提,会让面试官觉得你有实战经验。
面试中怎么聊
面试官问卡尔曼滤波,按这个思路回答:先用蒙眼走路的例子讲直觉(预测-更新循环),再说数学表达(状态转移方程、观测方程、五个核心方程),然后说假设条件(线性、高斯、已知噪声统计),最后说工程实践(Q和R怎么调)。
如果面试官追问"卡尔曼增益的推导过程",你可以说:核心思想是最小化后验估计误差的迹,对误差协方差关于K求导令其为零,就能解出最优K。具体推导复杂,但直觉就是"找一个权重让融合后不确定性最小"。
如果面试官追问"卡尔曼滤波和互补滤波的区别",你可以说:互补滤波用固定权重融合预测和测量,卡尔曼滤波的权重是动态调整的——根据当前不确定性自动决定更相信谁。互补滤波计算量小,适合资源受限场景,但精度不如卡尔曼滤波。
如果面试官追问"协方差矩阵P的物理意义",P矩阵描述状态估计的不确定性。对角线元素是各状态分量的方差,非对角线是不同分量间不确定性的关联。预测步P增大,更新步P减小,稳态下两者平衡,P收敛到固定值。面试时候能讲清楚P矩阵的物理意义,说明你不只是会套公式,而是真正理解了卡尔曼滤波的数学本质。
下一篇讲扩展卡尔曼滤波EKF——当系统不是线性的时候,怎么把卡尔曼滤波推广到非线性系统。
如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。
「机器人软件开发面试·从入门到精通」连载系列 上一篇:第165篇 传感器数据融合基础——面试翻车实录 下一篇预告:第167篇 扩展卡尔曼滤波EKF——非线性系统的状态估计
有任何问题欢迎评论区留言,我会尽量回复。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)