粒子滤波
卡尔曼滤波只会用一个高斯表示"我在哪",可真实的信念常常有好几个峰。粒子滤波 (particle filter) 干脆放弃用公式描述信念:撒一群带权重的样本,每个样本是一个"可能的机器人"。预测时让每个样本自己走一步,加权时按传感器读数给每个样本打分,重采样时让高分者繁殖、低分者淘汰。用它做的机器人定位叫蒙特卡洛定位 (MCL)。
1为什么机器人需要它
卡尔曼滤波 (4.8) 又快又准,可它有两个硬伤:信念只能是单峰的高斯,模型最好是线性的。现实不总这样:
- 走廊里有几扇一模一样的门,机器人看到一扇门,它可能在任何一扇门前:信念天然是多峰的。
- 机器人被人突然抱到别的房间(绑架问题,kidnapped robot):它必须放弃原来的自信,在全图上重新搜索。
- 激光对地图的匹配、里程计的转弯,都是强非线性的,线性化 (EKF) 会失真。
4.7 节的网格(直方图)滤波能处理这些,但网格数随维度指数增长:三维位姿 \((x,y,\theta)\) 在一张大地图上要几百万个格子。粒子滤波用样本代替网格:只在"概率大的地方"放样本,所以算力集中在真正重要的区域,实现简单,还能直接使用任何你能仿真的运动模型和传感器模型。这也是 ROS 里最常用的室内定位器 AMCL 的核心。
2直觉:预测、加权、重采样
回到 4.7 节那条有五扇门的走廊,这次位置是连续的。我们用 \(N\) 个粒子表示信念,每个粒子是走廊上的一个位置 \(x^{[i]}\),带一个权重 \(w^{[i]}\)。每一轮三步:
- 预测:下令"向右走 1 m",每个粒子独立地走 \(1\) m 再加一点随机噪声(就是从运动模型中采样,4.9 节)。粒子群整体平移、散开。
- 加权:传感器说"我看到一扇门"。门里的粒子得到高分(似然 \(a\)),墙边的粒子得到低分(\(1-a\))。这一步粒子不动,只改权重(FIG 1 里圆点变大、竖线变长)。
- 重采样:权重是"繁殖概率"。把带权重的粒子集合替换成 \(N\) 个等权重的新粒子:高权重的被复制多份,低权重的多半消失。这样粒子就重新集中到可能性大的地方。
重采样的做法就是 4.9 节的逆 CDF 采样:把权重首尾相接铺成一条 [0,1] 的线段(图中紫色长条),按等间距撒 \(N\) 根指针(系统重采样),每根指针落在谁的线段上,就复制谁。
- 多峰:先把机器人拖到一扇门(蓝块)上,"重置",再"加权"(应读到"门")、"重采样":粒子集中到几扇门前,出现至少两个相距 5 m 以上、各占 18% 以上质量的簇(簇 = 一格加左右相邻两格)。如果读到的是"墙",重置后再试一次。
- 定位成功:交替"移动 → 加权 → 重采样",让真实位置 ±1 m 内的粒子占 90% 以上。
- 粒子太少:把粒子数调到 12 个以下,切到"多项式重采样",不移动,反复"加权 → 重采样":看看会不会"一个粒子也没落在真实位置附近",滤波器还一脸自信(一格里聚了 60% 以上的粒子)。
粒子滤波就是 4.7 节贝叶斯滤波的"蒙特卡洛版":粒子的疏密就是概率密度。预测 = 让每个粒子按运动模型采样;更新 = 按似然给粒子加权;重采样 = 把权重"兑现"成粒子的疏密。它不需要线性、不需要高斯,代价是随机性:样本不够时,估计会抖,甚至把真值整个漏掉。
3动手玩:重采样本身也会"伤"粒子
重采样有一个副作用:每次都是有放回抽样,高权重的粒子被复制,别的粒子消失,粒子群里不同的"祖先"越来越少。即使没有任何新信息(所有权重相等),只要你每一步都重采样,多样性也会像"遗传漂变"那样一代代流失,最后所有粒子都是同一个祖先的拷贝。这叫粒子贫化 / 粒子耗尽 (sample impoverishment / particle depletion)。注意它和"权重退化"(少数粒子占去全部权重)不是一回事:权重退化靠重采样来治,粒子贫化却是重采样造成的。
FIG 2 把每一代粒子画成一行,从上往下是时间。起初粒子均匀铺在 \([0,10]\) 上,没有运动、没有观测,只做重采样,看看有多少个不同的祖先能活下来。
- 取 N = 50,"总是重采样"、无观测,跑 60 代:看看还剩几个不同的祖先(通常不到 10 个)。
- 切换到"仅当 N_eff < N/2",同样设置再跑 60 代:多样性保住了吗?为什么?
无信息时,"总是重采样"让粒子群像一个无记忆的随机游走:期望 \(O(N)\) 代之内,所有粒子就会合并成同一祖先。这意味着:重采样是必须付出的代价(它让计算资源别浪费在低权重粒子上),但是不该每一步都做。常用的规则是只在有效粒子数 \(N_{\mathrm{eff}}=1/\sum_i (w^{[i]})^2\) 低于 \(N/2\) 时才重采样;系统重采样(等间距指针)方差比多项式重采样小,而且权重全相等时一个粒子都不会丢。
4再看数学
提示:悬停下面带底色的符号,FIG 1 与 FIG 3 中对应的元素会高亮。
算法
信念用 \(N\) 个带权样本表示:\(\mathrm{bel}(x_k)\approx\sum_{i=1}^N w_k^{[i]}\,\delta\big(x_k - x_k^{[i]}\big)\)。每个时刻:
这个版本叫自举粒子滤波 (bootstrap filter),是最简单的一种。
为什么权重是 \(p(z\mid x)\)?重要性采样的视角
我们想从 \(\mathrm{bel}(x_k)\propto p(z_k\mid x_k)\int p(x_k\mid x_{k-1},u_k)\,\mathrm{bel}(x_{k-1})\,dx_{k-1}\) 里抽样,它直接抽不出来。但"预测"步骤恰好提供了一个容易抽的提议分布:先按旧信念抽 \(x_{k-1}\),再按运动模型抽 \(x_k\),得到的分布就是 \(\mathrm{bel}^-(x_k)\)。按 4.9 节的重要性采样,权重 = 目标 ÷ 提议:
于是"加权"的就是传感器模型。重采样则是把一组带权样本转成等权样本,防止权重退化(少数粒子占去全部权重)。当 \(N\to\infty\),估计收敛到真实后验,误差按 \(1/\sqrt N\) 下降。
系统重采样
取一个随机数 \(u_0\sim\mathrm{U}(0,1/N)\),令指针 \(u_j=u_0+j/N\)(\(j=0,\dots,N-1\)),选中满足 \(\sum_{i'\lt i}w^{[i']}\lt u_j\le\sum_{i'\le i}w^{[i']}\) 的那个粒子 \(i\)。只用一个随机数,复杂度 \(O(N)\),粒子 \(i\) 被复制的次数是 \(\lfloor Nw^{[i]}\rfloor\) 或 \(\lceil Nw^{[i]}\rceil\),比 \(N\) 次独立抽样(多项式重采样,次数服从二项分布)的方差小得多。
从粒子读出估计
位置的估计是加权平均 \(\hat{\mathbf p}=\sum_i w^{[i]}\mathbf p^{[i]}\)。角度不能直接平均:358° 和 2° 的平均应是 0°,不是 180°。要用圆周平均 \(\hat\theta=\operatorname{atan2}\big(\sum_i w^{[i]}\sin\theta^{[i]},\,\sum_i w^{[i]}\cos\theta^{[i]}\big)\)。更要警惕:多峰分布的均值可能落在没有任何粒子的地方(FIG 3 里的"镜像"就是例子),这时应对粒子聚类,取最大的簇,或者干脆把整个粒子集交给下游。
5机器人中的它:对称房间里的蒙特卡洛定位
一台带 8 束测距的机器人在 10 m × 6 m 的房间里。房间几乎中心对称:两个方块、两段隔墙关于房间中心互为镜像,只有右下角那个小方块是"独一份"。机器人知道地图,但一开始不知道自己在哪、朝哪:全局定位,粒子均匀铺满整张地图的位置和朝向。
点"前进 / 左转 / 右转",或打开"自动巡航",看粒子怎样聚拢。大多数时候你会看到两团:一团在真实位置,一团在镜像位置,直到机器人看见那个独一份的小方块才能排除。接着拖动机器人把它"绑架"到别处,看粒子滤波能不能醒悟;再打开"随机注入"救它。
- 镜像歧义:重置后驱动机器人,等到粒子分成两团:真实位姿和它的点对称镜像各占 25% 以上。这时加权平均落在哪里?
- 全局定位成功:让粒子的位置散布 < 0.5 m,估计误差 < 0.4 m。(提示:绕到右下角,让机器人看到那个独一份的小方块。)
- 绑架并救援:定位成功后把机器人拖到 3 m 以外,打开"随机注入",让滤波器重新收敛(误差 < 0.5 m)。
- 粒子不够:把粒子数降到 40 以下并重置,驱动 8 步以上:滤波器常常自信地收敛到错误的位置(误差 > 1.5 m 而散布 < 0.4 m)。
ROS 导航栈里的 AMCL 就是这样的滤波器:状态 \((x,y,\theta)\),运动模型来自里程计,观测模型来自激光对占据栅格地图的匹配(似然场模型)。它用 KLD 采样自适应地决定粒子数(粒子占据的状态空间格子越多,就用越多粒子),并在短期平均似然相对长期平均似然突然下降时注入随机粒子(这就是 FIG 3 的"随机注入",对应增广 MCL)。仓库 AGV 常常遇到"整排货架长得一样"的歧义,靠多峰信念和多走几步来消除。
6常见误区
全局定位时,粒子要足够密才能"碰巧"有一个落在真值附近。粒子太少时,真值附近一个粒子也没有,别的粒子在错误的地方越聚越紧,滤波器自信地走向错误(FIG 3 的最后一个任务)。需要的粒子数随状态维度和地图大小快速增长;跟踪(已知大致位置)时几十到几百个就够,全局定位可能要几千个。
如果似然很尖(传感器噪声设得很小,或者束数很多),几乎所有粒子的权重都接近 0,只有一两个例外,\(N_{\mathrm{eff}}\) 塌到 1 到 2,一次更新就丢掉绝大多数粒子。工程办法是:故意把传感器噪声设得比实际大(相当于对似然做"退火"),只取一部分束,或给似然加一个均匀的底噪混合(对付野值)。
跟 4.7 节的"零概率"同一个病:粒子群已经收缩到旧位置,新位置周围没有任何粒子,重采样不会凭空造出来。要么定期混入一小撮全图随机粒子,要么监测平均似然、在它突然下降时扩散粒子。代价是注入过多会让稳定的估计变得抖动,要调。
多峰时的平均值可能是一个没有任何粒子、甚至在墙里的点;角度用算术平均会在 ±180° 附近翻车。读估计时,先看分布(聚类或直方图),再决定怎么报告。
FIG 2 已经演示:重采样会损失多样性。用 \(N_{\mathrm{eff}}\) 阈值触发,并且用系统重采样代替多项式重采样。
7小练习
8延伸阅读
- S. Thrun, W. Burgard & D. Fox, Probabilistic Robotics, MIT Press, 2005, Ch. 4.3 & Ch. 8.3 — 粒子滤波与蒙特卡洛定位(含 KLD 采样与随机注入)
- F. Dellaert, D. Fox, W. Burgard & S. Thrun, "Monte Carlo Localization for Mobile Robots", ICRA, 1999 — MCL 的原始论文
- N. J. Gordon, D. J. Salmond & A. F. M. Smith, "Novel approach to nonlinear/non-Gaussian Bayesian state estimation", IEE Proceedings F, 1993 — 自举粒子滤波
- T. D. Barfoot, State Estimation for Robotics, Cambridge University Press, 2017, Ch. 4 — 非线性非高斯估计,包括粒子滤波
- R. Douc & O. Cappé, "Comparison of resampling schemes for particle filtering", ISPA, 2005 — 多项式、分层与系统重采样的比较