第 3 章 MPPI 六大变体——鲁棒、平滑、多模态与不确定性¶
本章是**纯采样 MPC**:六个变体都还在 MPPI 的采样框架内,不引入梯度或学习模块(那是第 5–7 章的事)。
📋 前置自测¶
答不出 ≥ 2 题,先回第 1 章(自由能–KL、重要性采样、零方差提议)与第 2 章(warm-start、ESS、样本效率主线),再读本章。
- 第 2 章的 warm-start 改善的是采样提议分布的什么?为什么说"位置比数量更重要"?
- 第 2 章的"样本效率"主线:为什么 vanilla MPPI 大半 rollout 被浪费?它的提议分布"盲"在哪里?
- 第 1 章证明过:重要性采样里若提议分布偏离目标分布,估计量会怎样?(提示:与权重方差、ESS 的关系)
- 第 2 章里 SGF 平滑是"事后"还是"采样层面"的?为什么说采样层面的平滑更彻底、不破坏最优性?
- 第 2 章指出 MPPI 的约束是软还是硬?这对安全攸关、约束绝不能破的场景意味着什么?
参考答案要点(自评用,不必逐字对照):(1) 改善提议分布的**中心/均值位置**——把采样中心挪到接近上一周期最优解处;位置比数量重要,是因为撒在错的中心、样本再多也大多落在低权重区(第 2 章实测有效样本约 14 倍差距)。
(2) vanilla MPPI 的提议是**各向同性高斯**,对环境结构一无所知,大半 rollout 撒进高代价/不可行区被浪费;它"盲"在不知道哪个方向有希望。
(3) 提议偏离目标分布会使**重要性权重方差增大、ESS 骤降**,极端时权重集中在极少数样本上、估计量方差爆炸甚至坍缩。
(4) SGF 是**事后**平滑(优化算完再磨),破坏信息论最优性;采样层面平滑(如本章 Smooth-MPPI)让平滑发生在优化**之内**,是被优化对象的一部分,故不破坏最优性。
(5) 软约束(靠罚值/barrier,撞了才重罚,不保证不撞);对安全攸关、约束绝不能破的场景,这意味着 vanilla MPPI 不够,需要本章 §3.1/§3.5 或前沿的安全增强(CBF 滤波、机会约束等)。这五点正是本章六个变体的出发点——如果某一题答得吃力,对应的本章小节会帮你补上。
本章目标¶
学完本章后,你应该能够:
- 说清 vanilla MPPI 的**四大缺陷**(抖动、模型失配脆弱、采样效率/可行性低、单模态),并把六大变体一一对应到各自要修的那个缺陷;
- 理解 Tube-MPPI 的 nominal + ancillary 双层架构,并说出"planner-tracker 冲突"的两个根因;
- 理解 RMPPI 如何把跟踪反馈嵌入重要性采样,以及它的**自由能增长上界**——MPPI 家族第一个理论保证;
- 掌握 Smooth-MPPI 的 input-lifting 技巧——在控制导数空间采样为何能从源头消除抖动且不破坏最优性;
- 理解 Log-MPPI 的 NLN 重尾混合分布如何提高杂乱环境里可行 rollout 的比例;
- 理解 SVG-MPPI 如何用 Stein 变分梯度侦察并锁定最优分布的**单个目标 mode**(mode-seeking),从而避开多峰平均、解决单模态导致的撞墙问题;
- 能根据应用场景(要鲁棒保证 / 要平滑 / 环境杂乱 / 多条等优路径 / 要不确定性感知)从六大变体中**合理选型**。
本章知识导航¶
第 2 章交付了一个能部署的 vanilla MPPI,并埋下一条主线:样本效率——提议分布是盲目的各向同性高斯,大半 rollout 被浪费,几乎每一种 MPPI 改进本质上都是"让提议更聪明"。
本章就是这条主线的兑现。把 vanilla MPPI 的毛病按"问题驱动"摊开,恰好是**四大缺陷**,六个变体分别去修:
| 缺陷 | 表现 | 对应变体 | 修法一句话 | 难度 |
|---|---|---|---|---|
| 模型失配脆弱 | 扰动/建模误差让提议失效、约束被违反 | Tube-MPPI / RMPPI(§3.1) | 加跟踪反馈层,并让采样"知道"有反馈 | ⭐⭐⭐ |
| 抖动 | 控制高频颤动、伤执行器 | Smooth-MPPI(§3.2) | 在控制导数空间采样(input-lifting) | ⭐⭐⭐ |
| 采样效率/可行性低 | 杂乱环境里 rollout 几乎全碰撞 | Log-MPPI(§3.3) | 重尾混合分布让少量样本探到远处可行区 | ⭐⭐ |
| 单模态 | 多条等优路径只能覆盖一条 | SVG-MPPI(§3.4) | Stein 变分把粒子送到各个 mode | ⭐⭐⭐ |
| 不确定性不可见 | 纯蒙特卡洛传播、无法估碰撞概率 | U-MPPI(§3.5) | Unscented Transform 传播均值+协方差 | ⭐⭐⭐ |
四节之后(§3.6)给一棵选型决策树,把六个变体收成一个可操作的判断流程。读法建议:§3.1 是本章理论含量最高、也最重要的一节(它带来 MPPI 家族第一个性能保证),值得精读;§3.3 相对轻量,可快速过;其余按你关心的缺陷挑读。
把上面这张表再往深看一层:四大缺陷看似各不相干,其实**同出一源**——都来自第 2 章那个朴素的高斯提议分布。
vanilla MPPI 围绕一条控制序列、用一个各向同性高斯撒噪声、开环前向、只看均值,这一个设定同时埋下了四颗雷:高斯是开环的(扰动一来就失效→模型失配脆弱)、是逐点独立的白噪声(→抖动)、是薄尾单峰的(→杂乱环境采不到可行区、多峰取中间)、是只传均值的(→看不见不确定性)。
所以本章六个变体不是六个互不相干的零散改法,而是从**同一个朴素高斯**出发、各自松开它的一个限定——这也是为什么它们大多能正交叠加(松开的是不同限定)、为什么可以用一张"五侧面表"统一(每个变体认领高斯的一个侧面)。
带着"四缺陷同根于朴素高斯"这个认识读下去,你会发现每一节其实都在回答同一个问题的一个分支:怎样让提议分布少像一点那个朴素高斯、多像一点真实的目标分布。
前置知识桥接¶
回顾第 1 章:最优提议分布是零方差的。 第 1 章 §1.4 证明过一个结论:重要性采样里,让估计量方差最小(精确为零)的提议分布,就是目标分布本身——对 MPPI 而言,目标是吉布斯分布 \(\mathbb{P}^\star \propto \mathbb{Q}\,e^{-S/\lambda}\)。
它恰恰是采样采不到的隐式分布,所以 MPPI 及其全部变体做的,本质上都是**用各种手段构造一个尽量接近 \(\mathbb{P}^\star\) 的提议分布**。本章的六个变体,正是六种不同的"构造手段"。
回顾第 1 章:MPPI 权重公式。 控制更新是对 \(K\) 条 rollout 噪声的加权平均,权重
其中 \(S_k\) 是第 \(k\) 条 rollout 的总代价,\(\lambda\) 是温度。本章多个变体改的不是这个加权公式,而是**噪声 \(\varepsilon_k\) 怎么撒**(Smooth/Log/SVG)或**rollout 怎么算**(Tube/RMPPI/U-MPPI)。
回顾第 2 章:warm-start 与样本效率主线。 第 2 章把"改善提议分布"具体化为 warm-start——用上一周期的解当采样中心,把提议挪到接近最优处(实测有效样本约 14 倍差距)。
并指出 vanilla MPPI 的核心矛盾是样本效率:盲目的各向同性高斯让大半 rollout 落在平庸区。
本章的变体可以按"它们怎么改善提议"重新理解:Tube/RMPPI 改善的是**在扰动下提议是否还有效**,Smooth 改善**提议的时间结构**,Log 改善**提议的尾部**,SVG 改善**提议的模态覆盖**,U-MPPI 改善**rollout 对不确定性的刻画**。
iLQR / iLQG 基础(本章 §3.1 假定已具备)。 Tube-MPPI 的下层跟踪器用 iLQG(迭代线性二次高斯,即 iLQR 的高斯噪声版本)。
本章假定你了解 iLQR/iLQG 是一种基于动力学线性化、代价二次化的**确定性、可微**最优控制器,能高效解跟踪问题(第 2 章 §2.4 已把它与 MPPI 对比过)。不熟悉也不必中断——用到时正文会用 2-3 句重新激活它的角色。
如果跳过本章会怎样¶
- 场景一:你用第 2 章的 vanilla MPPI 控一台越野车,仿真里跑得很好;一上真车,地面摩擦和坡度的建模误差让车冲出预定轨迹、甚至越过安全边界——因为你不知道 §3.1 的鲁棒变体:vanilla MPPI 的提议分布建立在"模型准确"的隐含假设上,一旦真实状态被扰动推到提议覆盖不到的区域,采样就失效了。
- 场景二:你给机器人写 MPPI 穿越密集障碍,发现它常常"卡住"——输出近乎随机地抖。你以为是 bug,其实是两个本章问题叠加:杂乱环境里高斯 rollout 几乎全碰撞、权重全趋零(§3.3 要修的可行性问题),以及高斯噪声本身带来的抖动(§3.2 要修的)。不读本章,你会把算法层面的固有缺陷误当成实现 bug 去反复调。
预计阅读时间¶
| 模式 | 时间 | 适合 |
|---|---|---|
| 精读(推导自由能上界、跑通各变体采样对比、画 augmented state 数据流) | 9–12 小时 | 要实现/选型这些变体的工程师 |
| 速读(读懂每个变体解决什么缺陷、核心机制) | 3–4 小时 | 先建立"变体地图" |
| 速查(查某个变体的采样公式 / 选型决策树) | 0.5 小时 | 已了解、回来查细节 |
科研发展脉络¶
六大变体不是同时冒出来的,而是沿着"vanilla MPPI 暴露一个缺陷 → 提出一个针对性修法"逐步发展,主线仍由 Georgia Tech 的 Theodorou 组及其合作者推动,近年扩展到多个团队:
| 年份 | 工作 | Venue | 修哪个缺陷 | 核心贡献 |
|---|---|---|---|---|
| 2018 | Williams 等, Robust Sampling Based MPC with Sparse Objective Information | RSS XIV | 模型失配 | Tube-MPPI:nominal MPPI + iLQG 跟踪的双层架构 |
| 2021 | Gandhi 等, Robust MPPI: Analysis and Performance Guarantees | RA-L 6(2):1423–1430 | 模型失配 | RMPPI:跟踪反馈融入重要性采样;自由能增长上界(家族首个理论保证) |
| 2022 | Kim 等, Smooth MPPI Control without Smoothing | RA-L | 抖动 | Smooth-MPPI:input-lifting 到控制导数空间 |
| 2022 | Mohamed 等, Log-MPPI Control Strategy | RA-L | 可行性 | Log-MPPI:Normal-Log-Normal 重尾混合采样 |
| 2024 | Honda 等, SVG-MPPI | ICRA | 单模态 | SVG-MPPI:Stein 变分引导→侦察并锁定单个目标 mode(mode-seeking) |
| 2025 | Mohamed 等, U-MPPI | IEEE T-RO | 不确定性 | U-MPPI:Unscented Transform 传播均值+协方差 |
这条线的内在逻辑:2018 先解决"扰动让 MPPI 失效"(Tube),2021 把它做出理论保证(RMPPI),2022 两篇分别攻抖动(Smooth)和可行性(Log),2024–2025 转向更难的单模态(SVG)与不确定性量化(U-MPPI)。
一个清晰的趋势是:越往后,变体越关心"提议分布的形状"——从"位置对不对"(warm-start、Tube)走向"覆盖几个 mode、尾部多重、协方差怎么贴合地形"。这正是第 2 章样本效率主线的延续。
这些变体不是停在仿真的纸面方法,它们大多在真实机器人上验证过——这对工程读者尤其重要,因为"仿真能跑"和"真机能用"之间隔着本章 §3.1 反复强调的模型失配鸿沟。把各变体的真实平台证据汇总一下:
| 变体 | 真实平台 | 验证场景 |
|---|---|---|
| Tube-MPPI / RMPPI | GT AutoRally 越野车 | 高速越野,扰动与打滑下的鲁棒驾驶 |
| Smooth-MPPI | 自动驾驶赛车(神经网络动力学) | 赛道急弯、变摩擦路面,侧滑角受控 |
| Log-MPPI / GP-MPPI | 地面车(AGV / Jackal) | 未知杂乱环境的无碰撞导航 |
| SVG-MPPI | 快速机动地面车 | 快速漂移的多模态避障与路径跟踪 |
| U-MPPI | Clearpath Jackal | 室内杂乱环境,风险感知导航 |
可以看到,这些变体的"主战场"集中在**地面车辆**(越野、赛车、AGV)——这并非偶然:地面车速度快、模型失配明显(轮胎-地面摩擦最难建模)、环境常杂乱多障碍,恰好同时触发本章的多个缺陷,是检验变体的理想试金石。
而把它们迁移到无人机、腿足、机械臂时,各缺陷的权重会变(见 §3.6 跨章案例的迁移讨论)。一个工程提醒:真机验证过不等于"开箱即用"——这些工作都伴随大量平台特定的调参与系统辨识(尤其 Smooth-MPPI 论文强调其敏捷性依赖足够准的系统辨识),照搬论文参数到你的平台往往需要重新整定。
§3.1 Tube-MPPI 与 RMPPI:双层鲁棒架构 ⭐⭐⭐¶
动机:扰动一来,提议分布就失效了¶
第 2 章反复强调,MPPI 的成败系于**采样所围绕的那条控制序列**——也就是重要性采样轨迹(importance-sampling trajectory)。warm-start 之所以有效,是因为上一周期的解是对"最优控制长什么样"的一个好估计,以它为中心撒噪声,提议分布就贴近最优。但这套逻辑有一个**隐含假设**:系统大致按你的模型演化,所以"上一周期的好解"在这一周期附近仍然好。
真实机器人会打破这个假设。地面摩擦、负载变化、风、坡度、未建模的动力学——这些**扰动与模型失配**会把系统的真实状态推到一个你的提议分布预料之外的区域。
RMPPI 的论文把这件事说得很直接:控制器的性能取决于采样所围绕的控制序列,而一个严重的扰动会把系统的初始状态推到一个重要性采样器不再有效的区域。
一旦如此,你在"过时的好解"周围撒出的 rollout,绝大多数都不再描述真实系统会发生什么——提议分布与真实最优分布脱节,加权平均给出的方向不再可靠。这就是 vanilla MPPI 的第二个核心缺陷:模型失配脆弱。
注意它和第 2 章"样本效率"的关系:样本效率说的是"在标称模型下,盲目采样浪费了大半样本";模型失配脆弱说的是"连标称模型本身都不准时,采样围绕的中心都错了"。
前者是提议**不够聪明**,后者是提议**根本失效**。后者更致命,因为它常常以"约束被违反、机器人冲出安全边界"的形式爆发。
读到这里你可能会问:既然扰动会让提议失效,为什么不直接**把采样协方差调大**,让 rollout 散得更广、覆盖被扰动推到的新区域?这个想法直觉上合理,但行不通,原因有二。
其一,调大协方差是**各向同性**地散开(第 2 章 §2.1 已批评),它不知道扰动把系统往哪个方向推,只是盲目地全方向加宽——大部分额外样本仍落在无关区域,浪费且降低有效样本数。
其二,更根本的是,问题不在于"撒得够不够广",而在于"采样的**中心**错了"——提议分布仍围绕那条过时的、开环的名义轨迹,而真实系统已经在反馈作用下走向别处。把一个中心错位的分布加宽,只是让它更弥散地错位,治标不治本。
真正的解法必须改变采样的**中心**让它跟上真实状态(这正是 RMPPI 把反馈纳入采样要做的),而非改变它的**宽度**。
这个区分很重要:很多 MPPI 调参的误区都源于"一遇问题就调协方差",但协方差只能解决"宽度"问题,解决不了"中心错位"和"开环失效"——后者需要结构性的改动。
如果不这样做会怎样¶
把"忽略扰动"的后果跑出来看。考虑一个一维系统:状态是位置 \(x\) 与速度 \(v\),控制 \(u\) 是加速度,有一个持续的扰动 \(d\)(比如恒定的下坡分量)一直在推动系统。
任务是把 \(x\) 停到目标 \(4.5\),同时有一道墙 \(x\le 5\)(越过即重罚 \(1000\))。对比两种规划:
dt=0.1; T=30; K=2048; lam=1.0; sigma=2.0; D=3.0; XMAX=5.0; GOAL=4.5
def mppi_plan(rollout_disturb): # 在(可选含扰动的)动力学上规划一条控制序列
U=np.zeros(T); rng=np.random.default_rng(0)
for _ in range(60):
eps=sigma*rng.standard_normal((K,T)); V=U[None]+eps
x=np.zeros(K); v=np.zeros(K); J=np.zeros(K)
for t in range(T):
a=V[:,t]+(rollout_disturb or 0.0)
v=v+a*dt; x=x+v*dt
J+=(x-GOAL)**2+0.1*v*v+(x>XMAX)*1000.0
rho=J.min(); w=np.exp(-(J-rho)/lam); w/=w.sum()
U=U+(w[:,None]*(V-U[None])).sum(0)
return U
def simulate_real(U): # 把序列施加到“真实”(总含扰动 D)系统, 取轨迹峰值 x
x=v=0.0; xmax=-1e9
for t in range(T):
v=v+(U[t]+D)*dt; x=x+v*dt; xmax=max(xmax,x)
return xmax
U_nom = mppi_plan(rollout_disturb=None) # 名义规划: rollout 不含扰动
U_rob = mppi_plan(rollout_disturb=D) # 鲁棒规划: rollout 含扰动
print(f"名义规划(忽略扰动): 真实峰值 x = {simulate_real(U_nom):.2f}")
print(f"鲁棒规划(rollout含扰动): 真实峰值 x = {simulate_real(U_rob):.2f}")
输出:
名义规划在"无扰动"的想象世界里算出一条恰好停在 \(4.5\) 的漂亮轨迹;可一旦把它开环地交给带扰动的真实系统,那个一直在推的 \(d\) 让速度不断累积,\(x\) 一路冲到 \(18.41\)——把墙撞穿了。
而让 rollout **看见**扰动的规划,预见到"这股推力会把我顶过去",于是主动留出裕度,真实峰值稳在 \(4.55\)。
这个例子用夸张的扰动把效果放大,但道理是普适的:rollout 必须反映真实系统会发生什么,否则算出的最优解只是对一个不存在的世界最优。
这里要说清楚:上面的"鲁棒规划"只是把扰动塞进了 rollout,是最朴素的鲁棒化,并不是 Tube-MPPI/RMPPI。真实的扰动往往未知、时变,不能简单当成已知常量塞进模型。
Tube-MPPI 和 RMPPI 给的是处理"未知扰动"的**架构性**方案——用一个反馈跟踪器实时纠偏,并让规划层与这个跟踪器协同。下面正式展开。
历史:从 Tube-MPPI 到 RMPPI¶
鲁棒 MPC 里有一个经典思路叫 tube(管道):把系统轨迹分解成一个"名义(无扰动)轨迹"加一个"被反馈控制器约束在管道内的误差"。只要误差始终留在管道里,名义轨迹安全就意味着真实轨迹安全。
Williams 等人 2018 年在 RSS 上把这个思路搬进 MPPI,提出 Tube-MPPI(论文题为 Robust Sampling Based Model Predictive Control with Sparse Objective Information)。
三年后,Gandhi 等人 2021 年在 RA-L 上指出 Tube-MPPI 的两个结构性缺陷并修复之,提出 RMPPI,还给出了 MPPI 家族的第一个性能保证。两者一脉相承,所以放在一节里讲。
值得补一句 tube 思想的渊源与"移植到 MPPI 为何不平凡"。在传统(优化式)鲁棒 MPC 里,tube 是一套成熟理论:名义轨迹由一个确定性优化求出,误差动力学是线性的,于是"管道"可以用不变集(invariant set)严格刻画,配一个线性反馈就能保证误差永远留在管道内——这套做法依赖**线性误差动力学 + 凸优化**。
但 MPPI 的用武之地恰恰是**非光滑代价、黑箱/非线性动力学**(第 2 章 §2.4 的杀手级场景),传统 tube 那套"线性 + 凸"的严格机器在这里用不上:名义轨迹得用采样求(因为代价非光滑),误差动力学可能非线性,不变集难以刻画。
所以把 tube 搬进 MPPI 不是简单拼接——Tube-MPPI 保留了"名义 + 管道反馈"的**架构思想**,但放弃了传统 tube 的严格集合保证(这也埋下了它两个缺陷的根,以及 RMPPI 改用"自由能增长上界"这种更适合采样框架的保证形式的伏笔)。
理解这一点,你就明白为什么 §3.1 的保证是"自由能上界"而非传统 tube 的"硬约束不变集"——不是 RMPPI 不想要后者,而是采样框架与非光滑/黑箱设定让后者难以成立。
Tube-MPPI:上层规划 + 下层跟踪的双层架构¶
Tube-MPPI 把控制拆成两层,各司其职:
- 上层——名义控制器(nominal MPPI):在**无扰动**的标称动力学上跑标准 MPPI,规划出一条名义轨迹 \(\bar{x}(\cdot)\) 和名义控制 \(u_{\text{nom}}(\cdot)\)。它需要是采样式的,因为要处理稀疏/非光滑代价(第 2 章 §2.4 的杀手级场景)。
- 下层——辅助控制器(ancillary controller,iLQG):解一个**跟踪问题**——把系统的真实状态 \(x\) 拉回名义轨迹 \(\bar{x}\),使真实状态始终留在以名义轨迹为中心的"管道"内。这是个标准的、初始误差小的二次跟踪问题,辅助控制器用更短的时域(1 秒)、但以更快的频率(100Hz)运行,iLQG 给出一个简单的线性反馈增益就能胜任。
分工的道理很清楚:**采样擅长全局、非光滑的规划,但不擅长高频纠偏;线性反馈擅长高频纠偏,但处理不了非光滑代价。
** Tube-MPPI 让两者各管自己擅长的一段——上层用 MPPI 在复杂代价地形上找一条好的名义路径(低频、重规划),下层用 iLQG 高频地把真实状态摁在这条路径附近(抗扰)。这正是第 2 章 §2.4"混合方案"里"梯度法做反馈跟踪"那一类的鼻祖。
上下层的时域和频率为什么**不对称**(上层长时域低频、下层短时域高频),值得想清楚,因为它体现了双层架构的分工本质。
上层 MPPI 要规划一条完整的、远视的名义路径,需要**长时域**(看得远才能绕开远处障碍、规划全局最优),但长时域的采样优化贵,所以只能**低频**重规划。
下层 iLQG 只做一件事——把真实状态摁回名义轨迹,这是个误差很小的局部跟踪问题,短时域(1 秒,只需看够纠偏的近期)就够,而抗扰必须**高频**(100Hz,扰动随时来、要随时纠)。
这个不对称恰好让两层的"贵"和"快"错开:贵的(长时域全局规划)跑得慢、便宜的(短时域线性反馈)跑得快,合起来既远视又抗扰。
如果反过来——让昂贵的全局规划高频跑、或让纠偏用长时域——要么算不过来、要么纠偏迟钝。所以"上层慢而远、下层快而近"不是随意设定,而是把计算预算花在刀刃上的必然安排。
下层的反馈增益从哪来:iLQG 一瞥¶
前面一直说"下层用 iLQG 给出反馈增益 \(K_{\text{fb}}\)",但这个增益究竟怎么算出来的?读到这里你可能会问:它和 RMPPI 公式里那个 \(K_{\text{fb}}\) 是不是同一个东西?值得用几句话讲清,因为它既是 Tube-MPPI 下层的核心,也是 §3.1 后面 RMPPI 反馈项的来源。
iLQG(iterative Linear-Quadratic-Gaussian,迭代线性二次高斯) 是 iLQR 的带噪声版本,思路是把一个非线性最优控制问题**反复线性化–二次化**来逼近求解。
给定一条参考轨迹(这里就是名义轨迹 \(\bar x\)),它在轨迹附近把动力学**线性化**(求雅可比 \(A_t=\partial f/\partial x\)、\(B_t=\partial f/\partial u\))、把代价**二次化**,得到一个局部的线性二次(LQ)问题;这个 LQ 问题有闭式解——通过一个**反向的 Riccati 递推**,从终端往初始逐时刻算出一组**时变的反馈增益** \(K_t\)。
每一步迭代用这组增益更新轨迹,再重新线性化,直至收敛。Todorov 与 Li 在 2005 年导出了 iLQG 控制器,Tassa 等人 2012 年进一步给出了让生成的轨迹序列稳定的方法(如正则化与线搜索)。
关键在于它产出的东西:iLQG 最终给出的是一个**时变线性(高斯)反馈律** \(u_t = \bar u_t + K_t(x_t - \bar x_t)\)——这正是 Tube-MPPI 下层用来把真实状态拉回名义轨迹的纠偏律,也正是 RMPPI 那个 \(K_{\text{fb}}(x_k-\bar x)\) 的形式来源。
所以"用 iLQG 做 ancillary"具体就是:在名义轨迹附近解一个 LQ 跟踪问题,拿到时变增益 \(K_t\),用它做高频反馈。
这也解释了为什么 §3.1 开头说"下层是个初始误差小的二次跟踪问题"——因为真实状态离名义轨迹不远,线性化–二次化的近似在这个小邻域里足够准,LQ 的闭式解(Riccati)又快又稳,正适合高频运行。
本质洞察:这里出现了一个贯穿现代机器人控制的范式——"慢规划 + 快线性反馈"的分层。Riccati 反馈增益的妙处在于它把"如何在轨迹附近最优地纠偏"压缩成了一组可离线/低频算好、在线高频查用的矩阵 \(K_t\):纠偏时只需一次矩阵乘 \(K_t(x_t-\bar x_t)\),不必重解优化。这一思想在本章之外反复出现:足式机器人用它做 WBC 之下的关节反馈,最新的 Feedback-MPPI(arXiv:2506.14855, 2025)甚至从 DDP 提取 Riccati 增益、让一个 2kHz 的内环在不重解 MPC 的情况下逼近 MPC 解——把"慢 MPC + 快 Riccati 内环"做到了极致。Tube-MPPI/RMPPI 的双层正是这个范式在采样式 MPC 里的体现:上层 MPPI 负责"非凸、远视"的规划,下层 Riccati 反馈负责"局部、高频"的纠偏,各取所长。理解了这一点,你会在后续许多控制架构里反复认出它。
最后补一句 ancillary 的"另一种选择"。RMPPI 论文不止用 iLQG,还用了一种基于**收缩度量(contraction metric)**的跟踪器来验证它的理论界——这印证了 §3.1 开头说的"ancillary 是个通用接口"。
收缩理论关心的是"两条轨迹会不会随时间指数地互相靠拢":如果系统在某个度量下是收缩的,那么任意两条轨迹(这里是真实轨迹与名义轨迹)的距离会指数衰减,跟踪误差自然被压住。
和 iLQG 相比,收缩度量给的是更强的、带数学保证的收敛性质(指数收缩),但设计一个有效的收缩度量本身不平凡(往往要解一个矩阵不等式或学一个度量)。
所以两种 ancillary 各有取舍:iLQG 实现直接、对光滑可微系统好用;收缩度量控制器提供更强的收缩保证、更契合 RMPPI 想要"可证明的鲁棒性"这一目标。
RMPPI 用两种跟踪器都验证了它的自由能上界,恰恰说明那个界**不依赖**具体跟踪器——只要跟踪器够好,界就成立。
这也回扣了上界三部件里"跟踪性能"那一项:它是个抽象的"跟踪有多好",不绑定你用 iLQG 还是收缩度量去实现。
planner-tracker 冲突:Tube-MPPI 的两个根因¶
Tube-MPPI 能抗扰,但它的两层是**各想各的**,由此带来 RMPPI 论文点明的两个结构性缺陷:
- 缺陷一:名义状态与真实状态会发散。 上层 MPPI 规划名义轨迹时,名义状态 \(\bar{x}\) 的演化是独立于真实状态 \(x\) 选取的。扰动持续把真实状态推离名义轨迹,而上层并不知情,两者越拉越远。名义状态独立于真实状态来选取,因此二者很容易发散——状态发散是 Tube-MPPI 的主要失效模式。
- 缺陷二:采样器无视下层反馈。 上层 MPPI 在围绕 \(u_{\text{nom}}\) 撒噪声、评估 rollout 时,完全不知道下层还有一个 iLQG 反馈在纠偏。于是它采样出的轨迹反映的是"没有反馈时"系统的行为,而不是"有反馈纠偏时"系统真实会走的轨迹。重要性采样轨迹不反映真实系统行为,因而给出对最优控制的有偏估计。结果上层可能规划出一条其实很容易被反馈跟住的激进轨迹却以为很危险、或反过来——这就是 planner-tracker 冲突:规划者和跟踪者没有共享同一个对"系统会怎么动"的认识。
这两个缺陷有个共同的根:上层的提议分布建立在一个不完整的系统模型上——它既不看真实状态(缺陷一),也不看反馈的存在(缺陷二)。
换句话说,Tube-MPPI 只是把反馈"挂"在了 MPPI 外面,没有让 MPPI 在采样时把反馈算进去。
RMPPI:把反馈嵌进重要性采样¶
RMPPI 的修法,正是堵上这两个根。先用一张表把 Tube-MPPI 与 RMPPI 逐点对照,看清 RMPPI 到底改了什么:
| 维度 | Tube-MPPI | RMPPI |
|---|---|---|
| 名义状态如何传播 | 独立于真实状态选取 | 增广状态 + 安全逻辑:偏离过大就拉回真实状态附近 |
| rollout 用什么控制 | 名义控制 + 噪声 | 名义控制 + 反馈纠偏项 + 噪声 |
| rollout 用什么动力学 | 名义(无扰动) | **含扰动的真实**动力学 |
| 采样器是否知道有反馈 | 否(反馈只挂在执行端) | 是(反馈写进 rollout) |
| 理论保证 | 无 | 自由能增长上界 |
| 失效模式 | 名义/真实态发散、采样有偏 | (堵上了上述两者) |
可以看到,RMPPI 不是给 Tube-MPPI 加东西,而是在三个维度上**改变了采样所基于的模型**——名义状态怎么传、rollout 用什么控制、用什么动力学。它的两个关键改动:
改动一:增广状态,让采样从真实状态出发。 RMPPI 用一个**增广状态空间**同时表示名义动力学与真实动力学,并配一套**安全逻辑**决定名义状态如何传播——当名义与真实状态偏离过大时,把名义状态拉回真实状态附近,从源头避免缺陷一的发散。
具体说,这个"增广状态"是把名义状态 \(\bar x\) 和真实状态 \(x\) **并在一起**作为一个扩展的状态向量来处理(维度大致翻倍)。
为什么要并在一起、而非像 Tube-MPPI 那样分开管?因为只有把两者放进**同一个**状态空间,规划过程才能"同时看到"名义和真实、并据二者之差做决策(安全逻辑的"偏离过大就重置"正是基于这个差)。
这就像把"计划"和"实况"画在同一张图上——分开画两张图,你看不出它们何时开始背离;画在一张图上,背离一目了然。
Tube-MPPI 的两层各持一张图(名义层不知道真实层的状况),RMPPI 把两张图叠成一张,于是"计划与实况的偏差"成了规划过程能直接读取、并据以行动的量。
这是 RMPPI 堵住"发散"缺陷的结构基础:不是事后发现发散了再补救,而是把"是否在发散"做成规划过程时刻可见的状态分量。
改动二:让 rollout 包含反馈,权重却用名义代价。 这是 RMPPI 最核心、也最巧妙的一步。
采样时,每条 rollout 用的控制不再是"名义控制 + 噪声",而是**名义控制 + 反馈纠偏项 + 噪声**:
其中 \(K_{\text{fb}}\) 是下层反馈增益,\(x_k(t)\) 是第 \(k\) 条 rollout 在 \(t\) 时刻的(含扰动的真实)状态,\(\bar{x}(t)\) 是名义状态。
rollout 用**含扰动的真实动力学**前向,于是每条采样轨迹都"带着反馈"演化——它反映的正是真实闭环系统会走的轨迹(堵上缺陷二)。
而计算权重时仍用**名义代价**。这样一来,MPPI 规划出的轨迹**天生就是下层反馈能够跟踪的**,因为采样过程已经把反馈的纠偏能力考虑进去了——规划者和跟踪者第一次共享了同一个"系统会怎么动"的模型。
这里"rollout 用真实动力学、权重却用名义代价"的搭配初看有点拧巴,值得解释。rollout 用真实(含扰动、含反馈)动力学,是为了让采样轨迹**反映系统真实会怎么走**(堵缺陷二);而权重评估用名义代价,是因为 MPPI 要优化的目标是**名义层面的任务表现**——你想让名义轨迹完成任务(到达目标、避开障碍),扰动是要靠反馈去吸收的"干扰项"、而非优化目标本身。
换个角度:真实动力学回答"这条控制实际会把系统带到哪",名义代价回答"这个去向对任务好不好"。两者分工明确——前者管"会发生什么"(要真实),后者管"想要什么"(按名义任务)。
如果权重也用含扰动的真实代价,优化目标就会被随机扰动污染、每次采样的"好坏"评判都带着扰动噪声,反而不稳。
所以这个搭配不是拧巴,而是把"系统的真实行为"和"任务的评判标准"恰当地分开——这也正是 RMPPI 能在保持任务导向的同时获得鲁棒性的关键设计。
把 RMPPI 一个控制周期内的增广状态数据流画出来,能看清这两个改动怎么串起来(这也是本节练习 3 让你对照源码补全的那张图的概念版):
真实状态 x ──────────────┐
│ │
┌────────▼─────────┐ │ (反馈项 K_fb(x_k - x̄) 用到名义/真实之差)
│ 安全逻辑: │ │
│ 更新名义状态 x̄ │ │
│ (若与 x 偏离过大, │ │
│ 把 x̄ 拉回 x 附近) │ │
└────────┬─────────┘ │
│ 名义 x̄, 名义 u_nom │
┌────────▼──────────────────────▼─────────┐
│ 采样 K 条 rollout: │
│ u_k = u_nom + K_fb·(x_k - x̄) + ε_k │ ← 反馈进 rollout(堵缺陷二)
│ x_k 用【含扰动的真实动力学】从 x 前向 │
│ 代价 S_k 用【名义代价】评估 │ ← 权重用名义代价
└────────┬─────────────────────────────────┘
│ 加权平均更新 u_nom
▼
执行 u_nom(0) + 反馈, 测下一真实状态 x ──(回到顶部)
读这张图的关键有两处:左侧的**安全逻辑**用名义/真实状态之差决定是否重置 \(\bar x\)(堵缺陷一的发散),中间的采样把**反馈项**写进每条 rollout、并用真实动力学前向(堵缺陷二的有偏估计)。两处合起来,才让"规划"和"跟踪"共享同一套对系统的认识。
把"反馈是否进采样"的效果直接跑出来。一维跟踪任务:让系统贴着参考线 \(p_{\text{ref}}=3.0\) 行驶、不越过边界 \(p\le 3.6\),有持续扰动 \(D\) 推着系统偏离,执行端有一个比例反馈实时纠偏。
对比两种 rollout——Tube 式(rollout 开环前向,不含反馈)与 RMPPI 式(rollout 含反馈前向):
def rollout(U, with_fb, rng):
eps = sigma*rng.standard_normal((K,T)); V = np.clip(U[None]+eps, -15, 15)
p = np.zeros(K); v = np.zeros(K); J = np.zeros(K)
for t in range(T):
a = V[:,t] + (KFB*(PREF - p) if with_fb else 0.0) + D # 含/不含反馈
v = v + a*dt; p = p + v*dt
J += (p-PREF)**2 + (p>PMAX)*800.0 + 0.01*V[:,t]**2
rho = J.min(); w = np.exp(-(J-rho)/lam); w /= w.sum()
return U + (w[:,None]*(V-U[None])).sum(0)
# 真实执行端总是有反馈 + 扰动, 评估闭环跟踪误差
输出:
差别在跟踪精度上很明显:RMPPI 式的平均跟踪误差只有 Tube 式的约 \(1/3\)(\(1.467\) vs \(5.167\))。
原因正是前面讲的——Tube 式 rollout 开环前向,MPPI"以为"系统会被扰动 \(D\) 推得很远,于是规划得保守、与执行端真实的闭环行为脱节;RMPPI 式 rollout 带反馈前向,MPPI 看到的就是"反馈纠偏后"的真实闭环轨迹,于是规划与执行一致、跟踪贴合得多。
这个例子也诚实地暴露了一个细节:两种方式的峰值都越了界(\(6.43\)、\(4.22\) 都 \(>3.6\))。这不是 bug,而是真实工程约束——这里执行端用的是最简单的**比例反馈**,它压不住瞬态超调。RMPPI 论文用的是 iLQG(或收缩度量控制器)这类更强的反馈,才能真正把状态摁在管道内。
换句话说,"反馈入采样"解决的是**规划与执行的一致性**(跟踪误差大幅下降已证明这一点),而"反馈本身够不够强"是另一个正交的问题——它取决于你下层用 P、PID 还是 iLQG。
把这两件事分开看,你就明白 RMPPI 的两个支柱缺一不可:既要有一个**够强的跟踪器**,又要让采样**知道**这个跟踪器的存在。
本质洞察:Tube-MPPI 与 RMPPI 的差别,是"把反馈挂在外面"与"让采样知道有反馈"的差别。vanilla MPPI 的提议分布默认系统开环演化;Tube-MPPI 在执行端加了闭环反馈,却没告诉规划端;RMPPI 则让提议分布本身**在闭环意义下**有效——采样出的每条轨迹都是"反馈纠偏后"的真实轨迹。回到第 1 章那条主线:MPPI 的一切改进都是在让提议分布更接近真实最优分布,而"真实"在有扰动、有反馈的系统里,指的就是**闭环**最优分布。RMPPI 的洞见是:要在扰动下鲁棒,提议分布必须建立在闭环现实之上,而不是开环想象之上。这也解释了为什么仅仅"把反馈挂在外面"(Tube-MPPI)不够——挂在外面的反馈改变了系统的真实行为,却没改变 MPPI 对系统行为的估计,二者一脱节,planner-tracker 冲突就来了。
理论保证:自由能增长上界¶
RMPPI 最被看重的贡献,是它给了 MPPI 家族**第一个性能保证**。利用增广状态、安全逻辑和考虑跟踪能力的重要性采样这几样材料,论文推导出系统**自由能增长的一个上界**。
回顾第 1 章 §1.3:自由能是 MPPI 理论的核心量,它刻画了"在当前提议分布下,离最优还有多远"。
一个对自由能增长的上界,本质上是在说"在扰动作用下,系统离最优的偏离不会无限放大、被控制在一个可量化的范围内"——这正是鲁棒性的数学表达。
这个上界是三样东西的函数:任务约束的满足程度、底层跟踪控制器的性能、以及 RMPPI 内部随机优化的采样误差。
这三项每一项都有清晰的工程含义,把"鲁棒性"拆成了可测量、可改善的部件:约束满足得越好、跟踪器越强、采样误差越小(ESS 越高,见第 2 章),自由能增长的上界就越紧、系统越鲁棒。
读到这里你可能会问:为什么界的对象是自由能的**增长**,而不是自由能的**值**?这是个微妙但关键的点。自由能本身(回顾第 1 章)刻画的是"当前提议分布离最优有多远"的一个绝对量;但在一个有持续扰动的闭环系统里,逐周期地谈"绝对的离最优距离"意义不大——每个周期扰动都在变、最优本身也在动。
真正决定系统会不会"越跑越偏、最终失控"的,是这个量**每一步会不会被放大**:如果每个周期自由能的增长都被一个界压住,那么误差就不会无限累积、系统就稳定在最优附近的一个可控邻域内。
这正是鲁棒性的动态本质——不是"某一刻离最优多近",而是"扰动反复作用下,离最优的偏离会不会失控放大"。所以界住"增长"比界住"值"更贴合"在扰动序列下保持稳定"这个真实目标。
这也和控制理论里用 Lyapunov 函数的"差分"(而非函数值本身)来证稳定性的思路一脉相承:要证不发散,关键看每步的变化量有没有被压住。
论文用两种跟踪器(iLQG 与基于收缩度量的控制器)在仿真中验证了这个界,并在真实的 GT AutoRally 越野车上演示:RMPPI 同时缓解了 MPPI 缺乏鲁棒性、与 Tube-MPPI 过度保守这两个问题,在敏捷性与抗扰之间取得了两全。
本质洞察:这个上界的真正价值不在"有个公式",而在它把一句模糊的工程口号——"系统要鲁棒"——翻译成了三个可以分别下手改善的旋钮:约束满足、跟踪性能、采样误差。这与第 2 章用 ESS 把"采样健康"变成可观测量是同一种工程思维:把不可控的玄学变成可测量、可分解的部件。也正因如此,RMPPI 被视为 MPPI 从"经验上好用"走向"有性能保证"的关键一步——尽管它给的是自由能增长的界,而非传统鲁棒 MPC 那种硬约束满足的严格保证(后者至今仍是开放问题,见本章末尾)。
上界的三个部件、跟踪器的选择,与"采样器失效"¶
把上界的三个部件逐一拆开看,每一个都对应一个你能动手的工程层面,这正是它实用的地方。约束满足度——任务约束(如不撞墙)被违反得越少,界越紧;它把"安全"直接写进了保证。
跟踪性能——下层反馈把真实状态拉回名义轨迹的能力越强,界越紧;这解释了为什么 RMPPI 要把反馈纳入采样:跟踪器越好,规划层能"信任"的纠偏余量越大、可以规划得越激进而不失安全。
采样误差——RMPPI 内部随机优化的误差越小(直接对应第 2 章的 ESS——有效样本越多、采样误差越小),界越紧。三者任意一项变好,鲁棒性都可量化地提升——这就是把"鲁棒"从形容词变成了三个可调旋钮。
跟踪器是可插拔的,这一点常被忽视。RMPPI 论文用了**两种**不同的下层跟踪器来验证上界:一种是熟悉的 iLQG(第 2 章 §2.4 的梯度法),另一种是**基于收缩度量(contraction metric)**的控制器。
这呼应了 §3.1 开头说的"ancillary controller 是个通用接口"——RMPPI 的架构不绑定具体跟踪器,谁能把真实状态稳稳拉回名义轨迹都行。工程上这给了你自由:动力学光滑可微就用 iLQG,想要更强的收缩性保证就用收缩度量控制器。
最后值得记住的是这条主线最尖锐的那句话——"扰动会把状态推到重要性采样器不再有效的区域"。重要性采样有一个隐含前提:新状态离上一周期的状态不远,所以围绕上一周期的解撒样本仍然有效。
严重扰动打破这个前提:状态被推远,提议分布(围绕旧解)和真实最优分布(围绕新状态的解)脱节,采样器"失效"。
Tube-MPPI 的安全逻辑(偏离过大就重置名义状态)、RMPPI 的反馈入采样,本质上都是在**维持重要性采样器的有效性**——让提议分布始终贴着真实状态所在的区域。
把这件事想透,你就理解了本节所有机制的共同目的:不是"加个反馈"那么表面,而是"在扰动下保住重要性采样这一整套机器赖以成立的前提"。
何时 Tube-MPPI 就够、何时需要 RMPPI。 既然 RMPPI 更复杂(增广状态、反馈入采样),也要判断何时不必上。一个粗略的判据是看**扰动相对反馈纠偏能力有多强**。
若扰动较温和、下层反馈能轻松把真实状态摁在名义轨迹附近(名义/真实态偏离始终很小),那么 Tube-MPPI 的两个缺陷都不严重——发散小、采样偏差也小,Tube 够用且实现更简单。
反之,若扰动强到让真实状态频繁大幅偏离名义轨迹(比如高速越野、强打滑),名义/真实态发散就成了主要失效模式、采样偏差也变大,这时 RMPPI 的两个改动才真正物有所值。
另一个考量是**是否需要可量化的鲁棒性保证**:要把鲁棒性写进设计指标、或要在论文/认证里给出界,就需要 RMPPI 的自由能上界;只求工程上能用,Tube 往往已足够。
换句话说,RMPPI 不是"永远更好",而是"扰动强、或需要保证时更好"——这与 §3.6"别为了用而用"的告诫一致。
⚠️ 常见陷阱¶
编程陷阱:把 RMPPI 的 rollout 反馈项漏掉,退化成"换皮 Tube-MPPI"。
- 错误描述:实现 RMPPI 时,rollout 仍写成 v = u_nom + eps,只在执行端套了个反馈,以为这就是 RMPPI。
- 现象/后果:抗扰能力和 Tube-MPPI 没区别,planner-tracker 冲突依旧;自由能上界的前提(采样考虑跟踪能力)不成立,理论保证失效。表面上"加了反馈",实际退回了 Tube-MPPI。
- 根本原因:RMPPI 的核心恰恰是**在 rollout 内部**加 \(K_{\text{fb}}(x_k-\bar{x})\) 这一项,让采样轨迹反映闭环行为;漏掉它,提议分布就还是开环的。
- 正确做法:rollout 的控制必须是 \(u_{\text{nom}} + K_{\text{fb}}(x_k-\bar{x}) + \varepsilon_k\),且用含扰动的真实动力学前向;权重才用名义代价。自检:去掉反馈项后结果若与实现无差别,说明反馈根本没进采样。
概念误区:以为"鲁棒"就是"把协方差调大、多探索一点"。 - 错误描述:遇到扰动就把采样协方差 \(\Sigma\) 调大,以为撒得更开就能抗扰。 - 现象/后果:\(\Sigma\) 一大,样本效率骤降(第 2 章:大半 rollout 被浪费、ESS 崩),且根本没解决"提议中心被扰动推偏"的问题——中心错了,撒得再开也是围着错的地方撒。 - 根本原因:模型失配脆弱的根源是提议分布的**中心(位置)在闭环下失效,不是探索范围不够。这是位置问题,不是宽度问题(呼应第 2 章"位置比数量更重要")。 - **正确做法:用反馈把真实状态拉回名义附近(让中心重新有效),并让采样在闭环意义下评估(RMPPI),而不是盲目加大 \(\Sigma\)。
思维陷阱:以为有了 RMPPI 的自由能上界,就等于有了硬约束的安全保证。 - 错误描述:把"自由能增长有上界"理解成"约束一定不被违反、安全已被证明"。 - 现象/后果:在安全攸关场景里过度信任 RMPPI,省掉额外的硬安全层,一旦遇到超出假设的扰动仍可能出事。 - 根本原因:自由能上界是关于"离最优的偏离被控制在范围内"的概率/能量意义的保证,不是**传统鲁棒 MPC 那种"在有界扰动下硬约束必然满足"的严格保证。MPPI 的约束本质上仍是软的(第 2 章)。 - **正确做法:把 RMPPI 的保证理解为"显著更鲁棒、且鲁棒性可量化",而非"绝对安全";安全攸关时仍叠加硬安全层(如控制屏障函数滤波,见本章末尾的 Shield-MPPI)。
练习¶
- (实现题) 把上面"如果不这样做会怎样"的最朴素鲁棒化(rollout 含已知常量扰动 \(D\))扩展一步:让扰动**未知**,改为在执行端加一个简单的比例反馈 \(u_{\text{exec}}=u_{\text{nom}}+k_p(\bar{x}-x)\) 来跟踪名义轨迹,但 rollout 仍不含反馈(即 Tube-MPPI 的近似)。在 \(D\) 较小和较大两种情形下分别测真实峰值 \(x\),观察"名义态与真实态发散"何时成为主要失效模式。
- (设计扩展题) 在上一题基础上,把反馈项 \(k_p(\bar{x}-x_k)\) 也加进 rollout(即 RMPPI 的近似),重跑对比。
说明为什么"rollout 含反馈"会让 MPPI 倾向于规划出更平、更易被反馈跟住的轨迹,并把它和 RMPPI 论文"采样考虑跟踪能力"的表述对应起来。
3. (B 型·源码精读) 精读 MPPI-Generic 仓库里 controllers/TubeMPPI/ 与 controllers/RMPPI/ 的实现,画出 RMPPI 的 augmented state(名义 + 真实)在一个控制周期内的数据流:名义状态从哪来、真实状态从哪进、反馈项在 rollout 的哪一步注入、权重用的是哪套代价。对照本节的两个改动验证你的理解。
§3.2 Smooth-MPPI:input-lifting 从源头消除抖动 ⭐⭐⭐¶
动机:抖动不是 bug,是高斯采样的固有产物¶
把第 2 章那个 vanilla MPPI 的控制输出画出来,你会看到它**高频颤动**——相邻时刻的控制值上下乱跳。
第 2 章把这归因于"原始 MPPI 输出天然带噪声",并用 Savitzky–Golay(SGF)事后磨平。但事后磨平只是治标。要治本,先得看清抖动从哪来。
抖动的根源在于:vanilla MPPI 在**控制空间**里、对**每个时刻独立**地撒高斯噪声 \(\varepsilon_k(t)\sim\mathcal{N}(0,\Sigma)\)。
"每个时刻独立"意味着相邻时刻的噪声毫无相关性——\(\varepsilon_k(t)\) 和 \(\varepsilon_k(t{+}1)\) 是两个独立随机数。加权平均后,这种逐点独立的噪声残留为控制序列里的高频分量,无法消除。换句话说,只要你在控制空间撒白噪声,抖动就是不可避免的——它是采样方式的固有产物,不是哪里写错了。
更值得警惕的是:抖动**在环境快速变化时会加剧,极端情况下甚至让 MPPI 发散**。这是 SMPPI 论文特别强调的一点。
原因在于,MPPI 的闭式快速收敛在环境平稳时是优点,但当环境(如代价图、障碍布局)变化太快时,每个周期的最优解都在大幅跳变,warm-start 来不及衔接,逐点独立的白噪声又持续注入高频——两者叠加,控制序列可能越抖越厉害,最终失稳。
所以抖动不只是"输出不好看"的表面问题,它在快变环境里会升级成"能不能稳定工作"的生死问题。这也是为什么 Smooth-MPPI 强调它在环境快速变化的场景里相对 vanilla MPPI 的优势最明显——它从源头掐断了这条"高频累积→发散"的链路。
读到这里你可能会问:要让控制平滑,为什么不直接给控制的变化率加一个**硬约束**(限制 \(|u_{t+1}-u_t|\le \Delta_{\max}\)),强制相邻时刻不能跳变?这个想法在梯度 MPC 里确实常用,但放到 MPPI 里有两个麻烦。
其一,MPPI 是采样式的——它不解带约束的优化问题,而是撒噪声再加权平均。即便你把违反变化率约束的样本罚成高代价,加权平均仍可能给出一个轻微违反约束的结果(软约束的通病,§3.1/§3.5 反复讲过)。
其二,更微妙的是,硬限制变化率会**砍掉合理的快速动作**——有时任务就需要一个陡峭的转向(急避障),一刀切地限制变化率会让控制器在该果断时变得迟钝。
input-lifting 的高明正在于它不"禁止"快速变化,而是让快速变化变得"连续"——控制由导数积分而来,天然平滑过渡,但需要时仍能积分出大的变化。
这是"塑造"而非"禁止":把抖动塑造成平滑的快速变化,而不是粗暴地禁止变化。理解这个区别,你就明白为什么 Smooth-MPPI 选择改采样空间,而非加一条变化率硬约束——前者保留了敏捷性,后者会牺牲它。
如果不这样做会怎样¶
抖动的代价很实在:高频控制让电机反复正反转、发热、磨损,液压/气动执行器嗡鸣,舵机寿命骤降;在四旋翼、机械臂上还可能激起机械共振。
第 2 章给的对策是 SGF 事后平滑,但那有两个本质问题(第 2 章 §2.1 已点明):其一,它在最优解算完之后再磨一遍,破坏了信息论最优性——磨平后的控制不再是那个加权平均给出的最优控制;其二,事后滤波只是在结果上抹平,无法在源头保证导数有界,控制的变化率仍可能超限。
第 2 章当时就埋了个伏笔:采样层面的平滑(从源头让采样出的轨迹就平滑)比事后平滑更彻底、不破坏最优性。Smooth-MPPI 正是这个伏笔的兑现。
历史与核心思想:在控制导数空间采样¶
Kim 等人 2022 年在 RA-L 上提出 Smooth-MPPI(论文题为 Smooth MPPI Control without Smoothing,标题里的 "without smoothing" 就是在强调"不靠事后平滑")。
核心思想叫 input-lifting:既然在控制空间撒白噪声必然带来高频,那就**不在控制空间撒**——改成在**控制的导数空间** \(\delta u = \mathrm{d}u/\mathrm{d}t\) 里撒噪声,再积分回控制:
为什么这就平滑了?因为控制 \(u_k(t)\) 现在是导数噪声的**累积和**(积分),而对白噪声做积分,相当于一个**低通滤波**——高频被积分天然压制,相邻时刻的控制值因为共享了前面累积的历史而彼此相关、变化平缓。
同时在代价里加一个**控制变化率惩罚** \(\ell_{\text{smooth}}=\alpha\|\mathrm{d}u/\mathrm{d}t\|^2\),进一步压制剧烈变化。把它跑出来看:
def run(mode, sigma):
rng=np.random.default_rng(0); U=np.zeros(T); x=v=0.0; exec_u=[]
for step in range(60):
if mode=='vanilla': # 控制空间: 每步独立高斯 → 高频
V=U[None]+sigma*rng.standard_normal((K,T))
else: # 导数空间(input-lifting): 采 δu 再积分 → 平滑
dU=sigma*rng.standard_normal((K,T))
V=U[None]+np.cumsum(dU,axis=1)*dt
# ... 双积分 rollout, 加权更新 U, 执行 u0 ...
u=np.array(exec_u)
return np.sum(np.abs(np.diff(u))), ... # 控制总变差 TV(越小越平滑)
输出:
控制空间采样(vanilla): 到达 24 步, 控制总变差 TV=51.99, 高频能量=48.34
导数空间采样(Smooth): 到达 35 步, 控制总变差 TV=16.43, 高频能量=15.05
→ 导数空间把控制总变差降到约 32%、高频能量降到约 31%
同一个任务,仅仅把"在控制空间撒噪声"改成"在导数空间撒噪声再积分",控制的总变差就降到约 \(1/3\)、高频能量降到约 \(1/3\)——抖动被从源头压下去了。
代价是到达稍慢(\(35\) vs \(24\) 步):平滑的控制更"温吞"、不那么激进,这是平滑性与敏捷性之间合理的权衡。
input-lifting 这个"把控制变成导数的积分"的做法,在控制理论里其实有更深的根,点出来能帮你把它接入已有的知识体系。
它本质上是给系统**串联了一个积分器**:原系统的输入端接一个积分器,积分器的输入(即原控制的导数)成为新的控制量。串联积分器是控制理论里的经典手段——它能改变系统的相对阶、平滑输入、消除稳态误差(PID 里的 I 项就是积分器)。从这个角度看,Smooth-MPPI 不过是把"串联积分器"这个老技巧用到了采样式 MPC 的采样空间上。
它还和**微分平坦(differential flatness)**的思想隐约呼应:平坦系统可以用输出及其导数来参数化状态和输入,于是"在导数层面规划再积分回去"成为自然的做法(四旋翼、车辆的轨迹规划常用平坦性)。Smooth-MPPI 没有显式用平坦性,但"在导数空间操作、积分得到平滑控制"的直觉是相通的。
把这些联系记在心里,你就不会把 input-lifting 看成一个孤立的技巧,而能认出它是控制理论里"通过提升输入的微分阶数来获得平滑性"这一大类方法在采样框架下的实例——这也解释了为什么它如此自然地保持了最优性(下一小节详述):串联积分器只是改变了系统的表示,没有改变要优化的目标。
关键:input-lifting 不破坏最优性¶
Smooth-MPPI 最要紧、也最容易被忽视的一点是:它没有破坏 MPPI 的信息论最优性,而 SGF 事后平滑破坏了。
原因在于 input-lifting 的数学本质是**扩展状态空间**——把控制 \(u\) 本身提升(lift)为系统状态的一部分,把"真正的控制输入"换成它的导数 \(\delta u\)。
把这个"扩状态"写明白。原系统是 \(x_{t+1}=f(x_t,u_t)\),控制是 \(u\)。input-lifting 定义一个**增广状态** \(\tilde{x}=(x,u)\),并把控制换成导数 \(\delta u\):
看这个增广系统:原来的控制 \(u\) 现在是增广状态 \(\tilde{x}\) 的一个分量、按 \(u_{t+1}=u_t+\delta u_t\,\mathrm{d}t\) 演化(一个积分器),而真正被采样、被优化的"控制"变成了导数 \(\delta u\)。
两件事立刻清楚了。其一,平滑是结构内生的:\(u\) 由 \(\delta u\) 积分而来,积分把白噪声 \(\delta u\) 滤成平滑的 \(u\)——平滑写在了增广动力学里,不是事后加的。
其二,最优性不受影响:在增广系统 \((\tilde{x},\delta u)\) 上,MPPI 是标准跑法,对 \(\delta u\) 做完整的采样-加权-更新,信息论推导原样成立。
这也顺带解释了 §3.2 那句"惩罚 \(u\) 的变化率写进状态代价"——\(u\) 现在是状态,惩罚它的变化(即 \(\delta u\) 的大小)当然是状态代价的事,而非控制代价。
一个自然的延伸问题:既然把控制提升一阶(到 \(\delta u\))能让控制平滑,那继续提升到**二阶**(采样加加速度 jerk、积分两次得到控制)会不会更平滑?答案是:原则上可以,且会让控制的**一阶导也连续**(更平滑),但代价是状态空间又扩了一维、且系统响应更"迟钝"(要积分两次,控制对采样的反应更慢)。
这其实揭示了 input-lifting 是一个**可选择提升阶数**的框架——提升到几阶,取决于你需要平滑到哪一阶导数。
多数应用提升一阶(平滑控制本身)就够了;对要求加加速度也平滑的场景(如载人飞行的舒适性、精密加工),才提升到二阶。
这也对应了平滑↔敏捷权衡的加剧:每多提升一阶,平滑度更高但敏捷性更低。所以"提升到几阶"本身就是一个要按任务权衡的设计选择,而非越高越好。
在这个扩展后的系统上,Smooth-MPPI 跑的仍是一个**标准的、未经事后篡改的 MPPI**:它在 \(\delta u\) 空间里做完整的采样-加权-更新,加权平均给出的就是扩展系统上的最优解。平滑性不是事后磨出来的,而是因为"控制是导数的积分"这一系统结构**内生**的。
所以信息论推导一字不动地成立(这一点在 SMPPI 的相关分析里也被强调:input-lifting 保持了路径积分控制的全部理论性质,甚至在非仿射动力学下也成立)。
把"事后平滑破坏最优性、采样层平滑不破坏"这句话用代价数字坐实。让 vanilla MPPI 算出最优控制后,分别用事后 SGF(滑动平均)和 input-lifting 两种方式获得平滑控制,再用**同一个真实代价函数**评估它们离最优有多远:
U_van = mppi('vanilla') # vanilla 算出的(未平滑)最优控制
J_van = cost_of(U_van) # 它的真实代价(基准)
U_sgf = moving_average(U_van); J_sgf = cost_of(U_sgf) # 事后 SGF 平滑
U_lift = mppi('lift'); J_lift = cost_of(U_lift) # input-lifting(导数空间采样)
输出:
vanilla MPPI(未平滑): 代价=51.531 TV=18.49
事后SGF平滑: 代价=78.064 TV=11.57 (代价上升+51.5%, 偏离最优)
input-lifting(导数空间): 代价=52.758 TV=17.09 (平滑且代价未退化)
数字很说明问题:事后 SGF 确实把控制磨得更平(TV 从 \(18.49\) 降到 \(11.57\)),但**代价飙升了 51.5%**——磨平的同时把解推离了最优。
而 input-lifting 的代价几乎不变(\(52.8\) vs \(51.5\),差异在采样随机性范围内),因为它在扩展系统上跑的本就是最优 MPPI。
要诚实指出一点:input-lifting 的 TV(\(17.09\))并不比 SGF 更低——它的平滑是结构内生的、温和的,不像 SGF 那样"硬磨"。
这恰恰是关键:SGF 用"偏离最优"换来了更激进的平滑,input-lifting 则在不偏离最优的前提下提供恰当的平滑。
如果你只看 TV 会以为 SGF 更好,但代价那一栏揭示了它的隐藏成本——这正是"事后修补"与"优化之内"的本质差别。
本质洞察:这正是第 2 章 §2.1 那个"两种平滑"洞察的落地。事后平滑(SGF)是"把不平滑的最优解强行磨平",磨的是结果、破坏最优性;采样层平滑(Smooth-MPPI)是"让最优解本身就平滑",改的是采样所在的空间、不碰最优性。它俩的根本区别在于平滑发生在**优化之后**还是**优化之内**:发生在之内,平滑就成了被优化对象的一部分,最优性自然保住。把这件事想透,你就理解了一条贯穿采样式控制的设计原则——要改变解的某种性质(平滑、多模、重尾),最干净的做法是改变采样的空间或分布,而不是在解算完之后去修补。本章后面的 Log-MPPI(改尾部)、SVG-MPPI(改模态)走的都是同一条路:在采样层面动手,而非事后。
两个轴上的抖动:i-轴与 t-轴¶
SMPPI 的论文把"抖动"拆成两个正交的轴,这个区分非常有助于理解它到底治的是哪种抖。考虑控制序列这张二维表:横轴是时域内的时刻 \(t\)(一条 rollout 内部),纵轴是控制周期的迭代 \(i\)(一周期到下一周期)。抖动可能发生在两个方向:
- i-轴抖动:相邻两个控制周期算出的序列之间的跳变("这一周期的解和上一周期差多少")。这个方向 vanilla MPPI 本来就能压——第 2 章的 warm-start 让相邻周期的解平滑衔接,限制控制方差也有帮助。
- t-轴抖动:同一条 rollout 内部、相邻时刻控制值之间的跳变("\(u(t)\) 到 \(u(t{+}1)\) 跳多少")。这正是 vanilla MPPI **压不住**的那种抖——因为它在控制空间对每个时刻独立撒高斯噪声,时刻之间天然无相关。
Smooth-MPPI 真正要治的是 t-轴抖动。input-lifting 把控制变成导数的累积积分,让同一条 rollout 内相邻时刻的控制天然相关、平缓变化,直接压低 t-轴的跳变。
这解释了为什么单纯的 warm-start(只管 i-轴)治不了抖动——它管的是周期间的衔接,而抖动主要长在 rollout 内部的 t-轴上。
这个二维视角还解释了 SMPPI 那条"动作变差代价"该放哪。回顾第 2 章 §2.1:MPPI 的控制代价不是随便写的,它由重要性采样**内在地**决定(自由能–KL 推导里那一项),任意往控制代价上加东西都会破坏理论推导。
SMPPI 的巧妙在于:把控制提升为**增广状态**之后,原来的控制 \(u\) 现在是"状态",于是"惩罚 \(u\) 的变化率"这件事可以写进**状态代价**而非控制代价——状态代价是可以自由设计的。
论文报告,加上这个 t-轴动作变差代价后,赛车在所有弯道的圈速都比不加时更快:减少 t-轴上不必要的抖动,直接提升了控制性能。
把"Smooth 治的是 t-轴"这句话量化一下。在一个点质量到达任务上,分别度量 vanilla 与 Smooth 算出的控制序列的 t-轴跳变(序列内相邻时刻控制值之差的平均绝对值):
def t_axis_jump(mode, sigma=3.0):
# ... 跑 MPPI, 每周期记录 mean(|diff(U)|), 即序列内相邻时刻的跳变 ...
if mode == 'smooth': # 导数空间采样再积分
V = U[None] + np.cumsum(dU, axis=1) * dt
else: # 控制空间白噪声
V = U[None] + sigma * rng.standard_normal((K, T))
return np.mean([np.mean(np.abs(np.diff(U_t))) for U_t in trajectory])
输出:
Smooth-MPPI 把 t-轴跳变压到了 vanilla 的约 \(18\%\)——这正是 input-lifting 的靶心:序列**内部**相邻时刻的平滑度。
注意这度量的是 t-轴(一条序列内部),而非 i-轴(周期之间);warm-start 改善的是后者、对前者无能为力,所以治 t-轴抖动非 input-lifting 莫属。
实验佐证与同类平滑方法¶
SMPPI 的实验很能说明问题。在一个用神经网络动力学的自动驾驶赛道任务上,几种带不同控制更新律的 vanilla MPPI 在直道和第一个弯还行,但在赛道**最急的第 2、第 3 弯**全部失败——撞上边界或失控;而 SMPPI 顺利以高速跑完所有圈,侧滑角受控(论文报告约 \(\le 11^\circ\)),并能在摩擦变化时不抖动地快速适应。
"减少转向和油门指令里的无谓噪声,与提升车速强相关"——这句实验结论把"平滑"和"性能"直接挂了钩:抖动不只是难看,它真的让你跑得更慢、甚至失控。
把 Smooth-MPPI 放进更大的"控制平滑"方法谱系里看,会更清楚它的位置。这一谱系本质上都在**塑造控制序列的频谱**、压制高频:
- Smooth-MPPI(input-lifting):在导数空间采样再积分,积分等效于一个**固定的低通**,且因为发生在采样空间、保最优性。
- Low-Pass MPPI(Kicki, 2025):对采样噪声直接施加一个**显式低通滤波器**,塑造扰动的频谱、滤掉有害高频——比 input-lifting 更直接地控制频谱形状。
- π-MPPI(Andrejev 等, 2025):用一个**投影滤波器**(解一个 QP)把采样控制序列投影到满足硬边界的平滑可行集上,对控制**及其导数**强加硬约束,产生任意光滑且可行的控制——专为固定翼这类对平滑性、可行性要求极苛刻的系统设计(见本章前沿)。
- KMPPI(核插值平滑):
pytorch_mppi提供的另一种平滑扩展——用核函数/样条在稀疏控制点之间插值,生成天然平滑的控制序列。它和 input-lifting 同属"让采样出的序列本就平滑"这一思路,但手段是插值而非积分;样条参数化还顺带降低了有效采样维度(少数控制点决定整条序列)。SCP-MPPI(前沿)进一步把这种样条参数化与 SVGD 多模结合。
它们和事后 SGF 的共同区别在于:事后滤波是**因果滤波**,会引入**相位滞后**(输出比输入延迟),在快速机动时这种滞后会损害性能;而 input-lifting / 投影 / 频谱塑造都在优化之内或采样阶段动手,避开了相位滞后。这也是 SMPPI 论文强调"post-hoc 平滑在保证导数有界上是劣等的"的原因。
为什么因果滤波**必然**有相位滞后?因为"因果"意味着 \(t\) 时刻的输出只能依赖 \(t\) 及之前的输入——它看不到未来。
要平滑掉高频,滤波器本质上是在做某种"加权平均最近若干个值",而这个平均的结果总是**滞后于**当前真实趋势:当信号正在快速上升时,对"最近几个较低的值"取平均会把输出往下拽、慢半拍。这就是相位滞后的来源,是因果性的数学必然,不是滤波器设计得不好。
对快速机动控制(急转弯、急避障),这半拍的滞后可能正好让你转向慢了、错过时机。而 input-lifting 不是"事后对已算出的控制做因果平均",它是在采样阶段就让序列平滑、再整条交给优化——优化能"看到"整条序列(非因果地),所以不引入这种滞后。
这正是"优化之内 vs 优化之后"在频域上的另一个体现:之内的平滑能非因果地利用整条序列,之后的因果滤波只能滞后地修补。
调参提示:SMPPI 多一个旋钮——导数空间的协方差 \(\Sigma_\delta\)。它和采样时间 \(\Delta t\) 强耦合(因为控制是导数 \(\times\Delta t\) 累积)。
实用做法是先按 vanilla MPPI 调好控制空间的协方差,再据此设 \(\Sigma_\delta\)——经验范围是若 vanilla 用 \(\mathrm{Diag}(1,1)\),SMPPI 的 \(\Sigma_\delta\) 可在 \(\mathrm{Diag}(0.1,0.1)\) 到 \(\mathrm{Diag}(1,1)\) 之间微调。
什么时候不需要 Smooth-MPPI。 平滑不是免费的(虽然计算上几乎免费,但有平滑↔敏捷的权衡),所以也要判断何时不必上。
三种情形可以省掉它:其一,执行器本身就是低通的——比如带大惯量的机械臂、或控制信号先过一级硬件滤波再到电机,高频指令到不了执行器,抖动无害;其二,任务本就需要 bang-bang 式的剧烈切换——某些时间最优控制的最优解就是在边界间快速跳变,强行平滑反而偏离最优;其三,仿真/离线规划、不上真机——抖动只在真实执行器上造成磨损,纯仿真里它只影响美观、不影响指标。
SMPPI 论文也提醒:input-lifting 要发挥敏捷优势,依赖**足够准的系统辨识**——模型差时,平滑带来的好处会被模型误差吃掉。所以一句话:执行器娇贵、需要平滑、且模型够准时上 Smooth;否则未必。
⚠️ 常见陷阱¶
编程陷阱:在导数空间采样后忘记积分、或积分时未累积。
- 错误描述:采了 \(\delta u\) 却直接拿它当控制喂给动力学,或写成 u[t] = u_prev + δu[t] 漏了 ·dt、又或每步都从同一基准而非累积。
- 现象/后果:要么控制量纲/尺度全错、系统乱跑;要么"积分"没起到低通作用,抖动照旧——白白套了个 input-lifting 的壳。
- 根本原因:input-lifting 的平滑性来自**累积积分**这一步(\(u(t)=u(t{-}1)+\delta u(t)\,\mathrm{d}t\)),它把白噪声变成随机游走式的平滑序列;漏掉累积或 \(\mathrm{d}t\),低通效应就没了。
- 正确做法:严格按 \(u_k(t)=u_k(t{-}1)+\delta u_k(t)\cdot\mathrm{d}t\) 从上一时刻累积;自检:画出采样轨迹,导数空间采样的控制曲线应明显比控制空间的平滑(总变差更小)。
概念误区:以为 Smooth-MPPI 和"事后加个低通滤波"等价。 - 错误描述:认为既然 input-lifting 相当于低通,那直接对 vanilla MPPI 的输出加一个低通滤波器是一回事。 - 现象/后果:用了事后低通,确实更平滑了,但和 SGF 一样破坏了最优性,且滤波器的相位滞后还可能损害控制性能;遇到对最优性敏感的任务表现变差。 - 根本原因:两者平滑的**位置**不同——Smooth-MPPI 的低通发生在采样空间(优化之内,最优性保留),事后滤波发生在优化之后(破坏最优性)。"效果上都更平滑"不等于"数学上等价"。 - 正确做法:要保最优性就在采样层面平滑(Smooth-MPPI);只有当你能接受最优性损失、且图省事时,才用事后滤波。
思维陷阱:把"平滑"无条件当成好事,一律调到最平滑。 - 错误描述:见抖动就把平滑力度(\(\Sigma_\delta\) 减小、\(\alpha\) 增大)拉满,追求绝对平滑的控制。 - 现象/后果:控制过度平滑、响应迟钝,在需要快速机动(急避障、抓取瞬间)的任务上反应不过来,到达变慢甚至错失时机(demo 里 \(35\) vs \(24\) 步已显露这一权衡的苗头)。 - 根本原因:平滑性与敏捷性是一对此消彼长的权衡——平滑压制了高频,也压制了快速变化的能力。没有免费的平滑。 - 正确做法:按执行器和任务需求折中——执行器娇贵、任务平缓就多平滑;需要急动作就少平滑。把平滑力度当成一个要调的旋钮,而非越大越好。
练习¶
- (A 型·实现 + 频谱分析) 在你的 MPPI 实现上加入 input-lifting:把控制空间采样换成导数空间采样 + 积分。
对"有/无 input-lifting"两种情形,分别对执行的控制序列做 FFT,画出频谱,定量比较高频段能量的差异。
再扫描平滑力度(\(\Sigma_\delta\) 或 \(\alpha\)),观察"高频能量"与"到达步数"如何此消彼长。 2. (设计扩展题) 把控制变化率惩罚 \(\ell_{\text{smooth}}=\alpha\|\mathrm{d}u/\mathrm{d}t\|^2\) 加进代价,与 input-lifting 配合。
设计一个实验说明:单独用变化率惩罚(不做 input-lifting)能否达到同样的平滑效果?为什么 input-lifting 是"采样层面"的、而变化率惩罚是"代价层面"的,二者作用机制有何不同? 3. (思考题) Smooth-MPPI 在导数空间采样、再积分回控制,本质上是对采样噪声做了低通滤波;而另一类做法(如 iCEM、有色噪声 MPPI)直接采**有色噪声**(带时间相关性的噪声)来获得平滑。
从**频域**视角对比这两条路线:它们分别把"压制高频"这件事放在了采样管线的哪一步?各有什么优劣?(提示:积分是一种特定的低通,有色噪声可以设计任意频谱。)
§3.3 Log-MPPI:重尾采样改善杂乱环境可行性 ⭐⭐¶
动机:杂乱环境里,所有 rollout 都撞了¶
前两节修的是"提议中心在扰动下失效"(§3.1)和"提议的时间结构带来抖动"(§3.2)。这一节面对一个更基础的困境:在**高度杂乱**的环境里(密集障碍、窄通道),从当前控制序列周围撒高斯噪声,绝大多数 rollout 一头撞进障碍、拿到极高代价。
当**几乎所有** \(S_k\) 都因碰撞而巨大时,权重 \(w_k\propto e^{-S_k/\lambda}\) 全部趋近于零、彼此难分高下——加权平均退化成对一堆"全是坏的"轨迹求平均,MPPI 的输出近乎随机。
这不是样本效率高低的问题(第 2 章那条主线讲的是"有用样本占比"),而是更尖锐的**可行性**问题:你手里可能**一条可行的 rollout 都没有**,巧妇难为无米之炊。
把这两者的层次关系说透。第 2 章的样本效率问的是"在一堆**有好有坏**的 rollout 里,有用的占多少"——前提是至少有一些可行的、好的样本,只是被大量平庸样本稀释了。而 §3.3 的可行性问的是更底层的"**到底有没有**可行样本"。
可以分三个层次看 MPPI 的健康度:层次一,有大量可行样本(理想,vanilla 就好用);层次二,可行样本稀少、被淹没(样本效率问题,warm-start/调 λ 能救);层次三,几乎没有可行样本(可行性问题,本节要救)。
重尾采样针对的正是层次三——当连一条可行 rollout 都凑不出来时,先靠重尾的偶发大动作"捞"出哪怕几条可行的,把 MPPI 从层次三拉回层次二,让它重新有米下锅。
所以 Log-MPPI 不是在"提升效率",而是在"保住下限"——它解决的是比效率更基础的"有没有"问题。理解这个层次差别,你就知道杂乱环境卡死时该先查"有没有可行样本"(可行性),而不是急着调 λ 提"效率"——后者在层次三根本不适用,因为没有好样本可供"更有效地利用"。
读到这里你可能会问:既然要"敢迈大步",为什么不直接用**均匀分布**采样,让大动作和小动作等概率出现?这样不是更敢探索吗?问题在于均匀分布**丢掉了精细探索**。
回顾第 2 章:MPPI 大部分时候需要在当前好解附近做**精细**的小幅调整(exploitation),只是偶尔需要大胆探索(exploration)。高斯分布的钟形恰好编码了这个"以小扰动为主"的先验——大部分样本集中在均值附近做精细搜索。
均匀分布把概率均摊到整个范围,小扰动和大扰动一样多,结果是**精细搜索的样本被稀释了**——你为了偶尔的大动作,牺牲了大量本该用于精细调优的样本。
重尾分布(NLN)的高明正在于它**两者兼顾**:主体仍是高斯(保留精细探索),只在尾部叠加重尾(提供偶发大动作)。
这是"大部分精细 + 少量大胆"的最优配比,而非均匀分布那种"什么都平均"的浪费。理解这一点,你就明白重尾不是"让采样更狂野",而是"在保留精细探索的前提下,额外开一个大胆探索的低概率通道"——这是个精心设计的平衡,不是简单的"撒得更广"。
如果不这样做会怎样¶
把"高斯采样在杂乱场景的乏力"量化出来。考虑一个需要大幅度机动才能脱困的一维场景:要越过一段障碍带、冲到远处的目标,只有施加足够大的控制冲量才能过去。对比纯高斯采样与重尾采样能产生多少"够大"的样本、又有多少 rollout 真能到达:
# (1) 尾部: 超过 3σ 的样本比例 (2) 越障可行比例
g = sigma*rng.standard_normal(N) # 纯高斯
mask=rng.binomial(1,0.7,N); gg=rng.normal(0,sigma,N)
ln =rng.lognormal(0,1.0,N)*rng.choice([-1,1],N) # 对称化对数正态(重尾)
nln = mask*gg + (1-mask)*ln # NLN 混合
输出:
(1) 尾部: |样本|>3σ 的比例 高斯=0.29% NLN=4.31%
最大幅度 高斯=4.7 NLN=74.9
(2) 可行比例(能越障到达的 rollout 占比): 高斯=0.0% NLN=0.8%
高斯采样里,超过 \(3\sigma\) 的"大动作"只占 \(0.29\%\)、最大幅度也就 \(4.7\)——它被自己的钟形分布死死困在均值附近,几乎产生不了脱困所需的大冲量,结果**没有一条 rollout 能越障到达**(\(0.0\%\))。
而 NLN 混合采样里,大动作占 \(4.31\%\)、最大幅度冲到 \(74.9\),于是有 \(0.8\%\) 的 rollout 真的越障到了目标。
\(0.8\%\) 听起来很小,但关键正在这里:当高斯给你 \(0\%\) 可行(MPPI 彻底卡死、输出随机),NLN 给你的这"区区几条"可行 rollout,就是 MPPI 能抓住、并加权放大的救命稻草——从"无米"变成了"有几粒米"。
历史与核心思想:Normal-Log-Normal 混合分布¶
Mohamed 等人 2022 年在 RA-L 上提出 Log-MPPI(Log-MPPI Control Strategy),思路直接:既然高斯的钟形尾巴太薄、产生不了大动作,那就给采样分布**接一条重尾**。具体用 NLN(Normal-Log-Normal)混合分布:
以概率 \(\pi\) 从普通高斯采样(负责均值附近的精细探索),以概率 \(1-\pi\) 从对数正态分布采样(对称化后提供**重尾**)。
这里"对称化"三个字值得展开,因为它是个容易忽略却必须做对的细节。对数正态分布天生是**单侧**的——它只取正值(因为它是"指数的高斯",\(\exp\) 的结果恒正),分布形状向右偏斜。
但控制扰动必须能**双向**:既要能加大油门、也要能减小油门,既要能左转、也要能右转。如果直接用单侧的对数正态做扰动,所有大动作都只朝一个方向,这显然不对。
所以 Log-MPPI 要把它**对称化**:常见做法是给对数正态采样值随机乘上 \(\pm 1\)(或等价地用两个镜像的对数正态),让重尾对称地分布在零的两侧。对称化之后,大动作可以朝任意方向甩出,重尾的探索能力才能真正服务于"双向都敢迈大步"。
这个细节如果漏掉,会导致一个隐蔽的 bug:控制只在单方向探索得开,反方向被卡住,表现为机器人在某些朝向下能脱困、另一些朝向下却卡死——而且因为不报错,极难 debug。所以实现 NLN 采样时,务必确认对数正态分量做了对称化(本节陷阱里也会再强调)。
对数正态分量的重尾意味着:大多数时候它也给小扰动,但偶尔会甩出一个很大的值——正是这些偶发的大动作,让少数 rollout 能探到远处的可行区域,在杂乱环境里"翻过"障碍带。
为什么选**对数正态**而非别的重尾分布(如 Student-t、Cauchy)?几个实际考量。其一,对数正态与高斯有天然的数学联系(取对数即高斯),便于和高斯主体组合成 NLN 这种解析上可处理的混合。
其二,它的重尾程度可由参数 \(\sigma_{\ln}\) 平滑调节——尾巴要多厚可控,不像 Cauchy 那样尾巴重到连均值/方差都不存在(Cauchy 的极端重尾会让采样过于狂野、难控制)。
其三,对数正态的"多数样本集中在小值、少数甩到大值"的形态,恰好匹配"多数精细探索 + 少数大胆远探"的需求。
当然这不是唯一选择——理论上任何"尖峰厚尾"的分布都能用,NLN 只是 Log-MPPI 验证有效且工程上好处理的一个具体选择。关键不在于非得是对数正态,而在于**用一个尾巴比高斯厚、但又不至于失控的分布**去替换薄尾高斯。
后续工作 GP-MPPI(IROS 2023)进一步用稀疏高斯过程(SGP)在线推荐子目标,引导这些重尾探索的方向,让"大动作"不只是盲目地大、而是朝着有希望的方向大。
本质洞察¶
本质洞察:Log-MPPI 改的是提议分布的**尾部**,而这把它和本章其他变体串成了一条清晰的线——它们都在**重塑提议分布的某个侧面**,且都在采样层面动手(呼应 §3.2 那条原则):warm-start 改提议的**位置**(第 2 章),Smooth-MPPI 改提议的**时间结构**(§3.2),Log-MPPI 改提议的**尾部**(本节),后面 SVG-MPPI 改提议的**模态覆盖**(§3.4)。回到第 1 章的零方差理想:最优提议分布就是目标分布 \(\mathbb{P}^\star\propto\mathbb{Q}e^{-S/\lambda}\),而在杂乱环境里这个目标分布常常是**重尾、多峰、形状古怪**的——单个各向同性高斯(薄尾、单峰、各向同性)从根上就拟合不了它。所以这些变体的共同逻辑是:目标分布长什么样,就把提议分布往那个形状上改一步。Log-MPPI 认领的,是"目标分布有重尾"这一侧面。理解这一点,你看待"该用哪个变体"就有了统一标尺:先判断你的目标分布在哪个侧面上最不像高斯,再选对应的变体去补。
给重尾装上方向:GP-MPPI 与安全变体¶
§3.3 的思维陷阱已经点出重尾的天花板:它让你"敢迈大步",但方向仍是盲目的。Log-MPPI 的作者们(Mohamed、Liu 等)顺着这条线做了两个有价值的后续,正好补上"方向"和"安全"两块。
GP-MPPI(IROS 2023):用感知给重尾装上方向盘。 它的动机是:局部轨迹优化(MPPI)在杂乱环境需要**全局引导**,尤其当目标在规划时域之外、或机器人陷入局部极小(被障碍围住、来回打转)时。
GP-MPPI 用一个**稀疏高斯过程(SGP)作局部感知模型:SGP 把局部感知数据"抽象"成一张**方差(不确定性)曲面,让机器人"看懂"周围哪里是可通行空间;据此识别出一组候选**子目标**,再挑出使预定义代价最小的那个**最优子目标**推荐给 MPPI;MPPI 随后朝这个子目标算控制。
关键好处是它**不需要全局地图、也不需要离线训练**,纯在线,且能帮机器人**逃出局部极小**。把它和 Log-MPPI 配合:Log-MPPI 的重尾负责"在子目标方向上敢于大步探索",GP-MPPI 的子目标负责"大步往哪迈"——盲目重尾就变成了有方向的探索,正好治了那个思维陷阱。
DBaS-Log-MPPI:给可行性加上安全。 另一条后续把**离散屏障状态(Discrete Barrier States, DBaS)**整合进 log-MPPI,在保持自适应探索、提升可行性的同时确保安全,报告超过 vanilla MPPI 与 log-MPPI。
这条线和本章 §3.5 的机会约束、前沿的 Shield-MPPI 殊途同归,都是在"可行/探索"之外再叠一层"安全"——反映出 MPPI 工程化的一个普遍趋势:先解决能不能走(可行性),再解决走得安不安全(安全约束)。
这里值得做一个跨领域的类比来加深理解:Log-MPPI 的重尾探索,与强化学习里的**探索机制**是同一类问题的不同解法。
RL 里智能体也面临"如何跳出当前策略、探到更优动作"的难题,常见手段有 ε-greedy(以小概率随机动作)、熵正则(鼓励策略保持随机性)、或给奖励加探索 bonus。
把它们和重尾对照:ε-greedy 的"小概率随机大动作"和 NLN 的"小概率甩出大扰动"在精神上几乎一致——都是在以利用为主的分布上,留一个低概率的"大胆探索"通道。
但要标注这个类比的边界:RL 的探索是为了在**多个 episode 间**学到更好的策略(跨时间积累),而 MPPI 的重尾是在**单个控制周期内**让 rollout 探到可行区(无跨周期学习);RL 探索改变的是被学习的策略参数,MPPI 重尾改变的是采样分布的形状。
相同的是"用低概率的大动作打破局部最优"这一核心直觉,不同的是它作用的时间尺度与对象。理解这个类比,你能把采样式控制的探索和 RL 的探索放进同一个认知框架——它们都在回答"如何不被当前的‘还行’困住、去够一够更好的"。
DBaS-Log-MPPI 与 U-MPPI 的关系澄清。顺带厘清一个容易混的点:log-MPPI 和 §3.5 的 U-MPPI 出自同一个团队(Mohamed、Liu 等),但改的是**不同侧面**——log-MPPI 改采样分布的**尾部**(NLN),U-MPPI 改 rollout 对不确定性的**刻画**(UT 传播均值+协方差)。
把它们看成同一群人沿"提议分布的不同侧面"逐个攻克的系列工作,就不会把二者搞混。实现上,log-MPPI 开源为 ROS + PyCUDA(IhabMohamed/log-MPPI_ros),并把 2D 占据栅格作为局部代价图直接并入 MPPI,在静态和动态杂乱环境都验证过实车导航。
最后把"提升探索"这件事的几条路线摆在一起对照,免得把重尾误当成唯一手段。调大协方差 \(\Sigma\):让所有样本都散开——简单,但破坏近处精细探索、且各向同性地散(§3.3 概念误区已批评)。
调高温度 \(\lambda\) 或退火:让权重更平、更多样本被纳入平均——改的是"如何利用样本"而非"如何撒样本",能缓解过早收敛,但同样不解决"撒不到远处可行区"的问题。
重尾采样(Log-MPPI):保留近处精细、只在尾部偶发大动作——专门解决"敢不敢迈大步探到远处"。方向性引导(GP-MPPI、上层规划):给探索装方向盘——解决"往哪迈"。
这四者作用在不同环节:\(\Sigma\) 和重尾改**采样分布的形状**(一个改宽度、一个改尾部),\(\lambda\)/退火改**权重的利用方式**,引导改**探索的方向**。
它们大多可组合,但要对症:杂乱环境"撒不到可行区"是尾部问题,首选重尾 + 引导,而非盲目调大 \(\Sigma\) 或 \(\lambda\)。把这张对照记在心里,你就不会一遇探索不足就只会"调大方差"这一招。
⚠️ 常见陷阱¶
编程陷阱:对数正态分量忘记对称化,导致采样系统性偏向一侧。
- 错误描述:直接用 np.random.lognormal(...) 当扰动分量,没有乘上随机符号 \(\pm 1\)。
- 现象/后果:对数正态恒为正,扰动系统性地偏向控制的一个方向,机器人莫名其妙总往一边偏;采样分布不再零均值,破坏 MPPI 的无偏性假设。
- 根本原因:对数正态分布只取正值,必须乘一个对称的随机符号才能得到零均值的重尾分布。
- 正确做法:lognormal(...) * rng.choice([-1,1]) 对称化;自检:画出采样分布直方图,应关于 0 对称、且尾部明显比高斯厚。
概念误区:把"重尾"和"调大高斯方差 \(\sigma\)"混为一谈。 - 错误描述:以为想要大动作,把高斯的 \(\sigma\) 调大就行,不必搞什么混合分布。 - 现象/后果:调大 \(\sigma\) 会让**所有** rollout 都变散——近处的精细探索也被破坏了,均值附近反而采不密,样本效率和精度双输;而杂乱环境真正需要的是"大多数样本精细 + 少数样本敢甩很远"。 - 根本原因:重尾分布与宽高斯的形状不同——重尾是"尖峰 + 厚尾"(多数样本集中、少数样本极远),宽高斯是"整体摊平"(处处稀疏)。两者对应不同的探索行为。 - 正确做法:用 NLN 这类"高斯主体 + 重尾分量"的混合,保留近处精细、同时获得远处偶发探索,而不是粗暴地把单个高斯调宽。
思维陷阱:以为可行性问题总能靠"采样更猛"解决。 - 错误描述:遇到 MPPI 在杂乱环境卡死,一律靠加重尾、加大探索来救。 - 现象/后果:极端杂乱(如必须走一条特定的长绕行路径)时,纯靠随机重尾采样命中可行路径的概率仍然极低(demo 里 NLN 也只有 \(0.8\%\));一味加猛探索还会让控制更抖、更不安全。 - 根本原因:重尾改善的是"偶发大动作"的概率,但它仍是**无方向的盲目探索**;当可行区域需要精心引导才能到达时,盲目重尾的命中率有天花板。 - 正确做法:重尾解决"敢不敢迈大步",方向问题要靠**引导**——如 GP-MPPI 用子目标引导、或上层规划器给路径。把 Log-MPPI 当成"提高可行样本下限"的手段,而非杂乱环境的万能解;必要时与全局引导配合。
练习¶
- (A 型·实现 + 统计对比) 在一个 2D 迷宫(或带密集障碍的场景)里,分别用纯高斯采样和 NLN 混合采样跑 MPPI,固定 \(K=512\),各跑 100 次,统计两者的**碰撞率**与**到达成功率**。再扫描混合比例 \(\pi\),观察"高斯主体占比"如何在"近处精细探索"与"远处重尾探索"之间权衡。
- (设计扩展题) 把 Log-MPPI 的 NLN 采样与第 2 章的 ESS 监控结合:在杂乱场景里同时记录高斯采样与 NLN 采样的 ESS 随时间的变化。
解释为什么在"几乎全碰撞"的时刻,NLN 的 ESS 仍能维持在一个非零水平,而高斯的 ESS 会崩到接近 \(1\)。 3. (思考题) Log-MPPI 用重尾分布提高"偶发大动作"的概率来改善可行性。如果把这件事和 §3.1 的鲁棒性、§3.2 的平滑性放在一起看:重尾采样会不会与"平滑控制"的目标冲突(偶发大动作本身就是一种高频跳变)?设计一个场景说明这种张力,并讨论在"既要平滑、又要在杂乱环境可行"的任务里该如何取舍。
阶段性回顾:已修复的三大缺陷¶
本章过半,把已讲的三节按"问题驱动"收一收,能看清这条主线的走向——每一节都在 vanilla MPPI 的提议分布上动一处刀,且都动在采样层面:
| 节 | 缺陷 | 变体 | 在提议分布上改了什么 | 核心机制一句话 | 不破坏最优性? |
|---|---|---|---|---|---|
| §3.1 | 模型失配脆弱 | Tube/RMPPI | 让提议在**闭环**下有效(位置 + 反馈) | rollout 含反馈、权重用名义代价 | RMPPI 给自由能增长上界 |
| §3.2 | 抖动 | Smooth-MPPI | 改提议的**时间结构** | 在控制导数空间采样再积分 | 是(input-lifting = 扩状态) |
| §3.3 | 杂乱可行性低 | Log-MPPI | 改提议的**尾部** | NLN 重尾混合分布 | 是(只改采样分布) |
三节连起来回答了同一个问题的不同侧面:当 vanilla MPPI 那个"各向同性、薄尾、单峰、开环"的高斯提议在某个侧面上不够用时,就把提议往目标分布的那个侧面改一步。
还剩两个侧面没补:目标分布是**多峰**的(多条等优路径)怎么办——§3.4 SVG-MPPI 用 Stein 变分**找出并锁定一个目标 mode**;以及如何让 rollout 显式刻画不确定性、进而估计碰撞概率——§3.5 U-MPPI 用 Unscented Transform 传播均值与协方差。下面就来补齐这两个侧面,随后给出选型决策树。
§3.4 SVG-MPPI:Stein 变分引导的多模态求解 ⭐⭐⭐¶
动机:两条都安全的路,平均一下就撞墙¶
前三节改的是提议分布的位置、时间结构、尾部,但都默认提议是**单峰**的——一个高斯,一个峰。可现实里最优动作分布常常是**多峰**的:绕过一个障碍,向左绕和向右绕可能同样好,对应两条分开的最优路径,是最优分布的两个峰(mode)。
vanilla MPPI 只能用一个高斯去近似这个双峰分布,而一个单峰高斯要同时覆盖两个分得很开的峰,它的均值只能落在两峰**中间**——那恰恰是障碍所在。
把这个"多模平均的灾难"跑出来看。2D 导航从 \((0,0)\) 到 \((4,4)\),障碍在正中 \((2,2)\)。左绕(先上后右)和右绕(先右后上)是两条等优的安全路径,把它们的控制逐元素平均:
U_left = make_path([[0,0],[0,4],[4,4]]) # 左绕
U_right = make_path([[0,0],[4,0],[4,4]]) # 右绕
U_avg = 0.5*(U_left + U_right) # 两模平均
for name,U in [("左绕",U_left),("右绕",U_right),("两模平均",U_avg)]:
dgoal,hit,dmin = sim(U) # 终点距目标, 是否撞障碍, 最近障碍距
print(f"{name}: 终点距目标={dgoal:.2f}, 最近障碍距={dmin:.2f}, {'撞障碍!' if hit else '安全'}")
输出:
左绕安全、右绕安全,可把两者的控制逐元素平均,得到的轨迹笔直穿过障碍中心、最近障碍距 \(0.00\)——撞了。
这背后有个简单的几何直觉:逐元素平均是一种凸组合,而可行区域(绕开障碍的路径集合)不是凸集。两条绕障路径分居障碍两侧,它们的"中点"自然落在障碍上——就像圆环上两个对称点的连线中点落在圆心,而圆心恰是要避开的地方。
MPPI 的加权平均本质上就是在求一个(加权)凸组合,当最优解集非凸(多个分离的可行区)时,凸组合可能落到可行区之外的禁区。这不是 MPPI 实现的瑕疵,而是"用一个点(加权均值)代表一个非凸集合"这件事的固有矛盾。
这正是 SVG-MPPI 论文 Fig.1 点明的失效:在避障任务里 MPPI 可能把一条碰撞轨迹当作"最优解"输出,因为两条分叉的避障路径对应两个 mode,而高斯近似的动作分布把两个 mode 都覆盖了,加权平均落进了两峰之间的危险地带。
这就是 vanilla MPPI 的第四个核心缺陷:单模态——它的高斯提议表达不了多峰,一遇等优分叉就可能取了个致命的折中。
还有一层更难的:在快速机动的车辆上,多模不仅**存在**,还在**快速漂移**(SVG-MPPI 论文标题里的 "rapidly shifting" 正指此)。
随着车高速前进、障碍相对位置快速变化,"该走左还是右"这个最优 mode 会一帧一帧地切换——这一刻左绕更优,下一刻可能右绕更优。这让问题雪上加霜:不仅要在某一时刻不取两峰中间,还要能**快速地重新判断当前该锁定哪个峰**。
这正是 SVG-MPPI 坚持保留 MPPI 闭式快速收敛的深层原因——若用迭代式的多模方法(SV-MPC、GMM),每次重新判断 mode 都要迭代收敛,跟不上 mode 漂移的速度;而 SVG-MPPI 的"轻量 SVGD 侦察 + 闭式 MPPI 收敛"足够快,能在每个控制周期重新锁定当前最优 mode。
所以"快速漂移"这个限定,既是 SVG-MPPI 要解的难点,也解释了它为什么非要走"寻峰 + 闭式"而非"覆盖 + 迭代"这条路。
为什么不能简单"调小 λ 让它选一个"¶
你可能会想:把温度 \(\lambda\) 调小、让权重更尖,MPPI 不就会选定代价更低的那条、而不是平均吗?这在两个 mode 代价**有明显高低**时管用——权重会集中到更优的那个峰。
但当两个 mode **几乎等优**时(左右绕一样好),权重在两峰间难分伯仲,\(\lambda\) 再小也压不出唯一赢家,平均仍然发生;而且 \(\lambda\) 调得过小会让 ESS 崩、退化成贪婪(第 2 章)。
更根本的是:单个高斯提议在**结构上**就是单峰的,无论怎么调 \(\lambda\)/\(\Sigma\),它都无法同时表达"要么往左、要么往右"这种**离散的选择**。
这是分布的**表达能力**问题,不是参数问题——必须改提议分布的形式,而不是它的参数。这也是它与前三节的微妙不同:位置/尾部/时间结构都是连续可调的量,而"覆盖几个峰"是个离散的结构问题。
读到这里你可能会问:那为什么不**并行跑多个 MPPI**,每个锁定一个 mode,最后选代价最低的那个输出?这个想法(有时叫 multi-hypothesis MPPI)确实可行,某些工作也这么做,但它有两个代价。
其一,计算翻倍:跑 \(M\) 个 MPPI 就是 \(M\) 倍计算,而 MPPI 本就吃 GPU,多开几路对实时性是硬负担。
其二,也是更微妙的,你得先知道有几个 mode、它们在哪——才能给每个 MPPI 设好初始中心,而这恰恰是难点:mode 的数量和位置随环境快速变化(前面说的 rapidly shifting),静态地预设 \(M\) 路往往跟不上。
SVG-MPPI 的做法更经济:它不预设 \(M\) 路,而是用一次轻量 SVGD 侦察**动态地**找出当前最该锁定的那个 mode,只跑**一路** MPPI。
这是"动态侦察一个"与"静态并行多个"的取舍——前者省计算、能适应 mode 漂移,代价是只保留一个 mode(放弃了同时握多个候选)。
理解这个对比,你会看到 SVG-MPPI 的设计不是唯一解,而是"实时性优先"约束下的一个聪明权衡;若你的平台算力充裕、mode 又相对稳定,并行多路 MPPI 也是一条合理的路。
历史与核心思想:用 Stein 变分找出一个目标 mode¶
Honda 等人 2024 年在 ICRA 上提出 SVG-MPPI(Stein Variational Guided MPPI,arXiv:2309.11040),专门处理快速机动车辆那种**快速漂移的多模态**最优分布。
它的关键思路有点反直觉:不是"同时覆盖所有 mode",而是**找出一个目标 mode 并引导解收敛到它**——论文称之为 mode-seeking(寻峰)。
为什么不覆盖所有峰?因为覆盖多峰会牺牲 MPPI 最宝贵的性质——闭式、不需迭代更新的快速收敛。SVG-MPPI 的做法是:用改进的 Stein 变分梯度下降(SVGD)粗略估计**出一个收敛的目标 mode,再把它嵌入 MPPI,求一个**只覆盖该目标 mode 的闭式解。这样既避开了"取两峰中间"的灾难,又保住了 MPPI 的快速收敛。要理解它,先得理解 SVGD。
Stein 变分梯度下降(SVGD):用一组粒子逼近一个分布。 SVGD 是一种确定性的变分推断方法:维护一组粒子 \(\{\theta_1,\dots,\theta_M\}\)(每个 \(\theta_i\) 是一条候选控制序列),通过迭代更新让这组粒子整体逼近目标分布 \(p(\theta)\propto e^{-J(\theta)/\lambda}\)。更新规则为
其中 \(k\) 是 RBF 核函数。这条更新有两项,各管一件事:
- 第一项 \(k(\theta_j,\theta_i)\,\nabla\log p(\theta_j)\)——吸引(exploitation):把粒子推向高概率(低代价)区域。\(\nabla\log p\) 指向代价下降最快的方向,核 \(k\) 让邻近粒子互相借用梯度信息。
- 第二项 \(\nabla_{\theta_j}k(\theta_j,\theta_i)\)——排斥(exploration/diversity):把彼此靠太近的粒子推开,防止所有粒子坍缩到同一点。正是这一项让粒子**铺开**去探索分布的不同区域、感知到不同 mode 的存在。
两项合力,粒子既往低代价区聚拢、又保持多样,最终铺在目标分布的高概率区域上——这组铺开的粒子天然能"看见"分布是不是多峰的。
这是 SVGD 相对单个高斯的根本优势:它用**一群**粒子表示分布,自然能表达多峰,而单个高斯只有一个峰。
把排斥项的作用直接跑出来看。一维双峰目标 \(p(x)\propto e^{-J(x)}\),\(J=(x^2-4)^2/8\) 有两个等深的谷在 \(\pm 2\);把 \(20\) 个粒子全初始化在 \(0\) 附近,分别用"完整 SVGD"和"去掉排斥项(只剩吸引)"各跑若干步:
def grad_logp(x): return -gradJ(x) # ∇log p = -∇J, J 两谷在 ±2
def svgd(with_repulsion, M=20, eps=0.05, steps=300):
X = rng.uniform(-0.5, 0.5, M) # 全部初始化在 0 附近
for _ in range(steps):
K, gK = rbf(X) # RBF 核及其梯度(带宽用中位数启发)
attract = K @ grad_logp(X) / M # 第一项: 吸引(向高概率区)
repulse = gK.sum(0) / M if with_repulsion else 0.0 # 第二项: 排斥
X = X + eps * (attract + repulse)
return X
输出:
完整 SVGD 把粒子均匀铺到了两个峰(左 \(10\)、右 \(10\)),而去掉排斥项后粒子分布失衡(\(15\) vs \(5\))、整体更"缩"。
这就是排斥项的价值:没有它,粒子会一窝蜂涌向最近或最陡的那个峰、丢掉对另一个峰的感知;有了它,粒子被推开、铺向不同区域,多峰才被"看见"。
这也直观解释了为什么 SVG-MPPI 要用 SVGD(而非单个高斯)来侦察 mode——它需要的正是这种"铺开去感知多峰结构"的能力,哪怕最后只锁定其中一个峰。这段代码即本节练习 2 的脚手架。
实现 SVGD 时有两个旋钮值得一提,因为它们直接影响"多峰能不能被感知"。RBF 核带宽 \(h\):它决定排斥的作用范围。
带宽太小,每个粒子只"看见"紧邻的粒子,排斥范围太窄,远处的峰感知不到、粒子容易各自聚成小簇;带宽太大,所有粒子互相强排斥、铺得过散、聚不进峰里。
常用的**中位数启发**(median heuristic)把 \(h\) 设成粒子两两距离平方的中位数(再除以 \(\log M\)),让带宽随粒子分布自适应——这正是上面代码 rbf 里做的。步长 \(\epsilon\):太大粒子会越过峰、震荡不收敛;太小则需要很多步。
对 SVG-MPPI 这种"只跑少数几步做侦察"的用法,步长要配合步数调——既然只跑几步,步长不能太小,否则粒子还没铺开就停了。
这两个旋钮调不好,SVGD 的"感知多峰"能力就发挥不出来,寻峰也就无从谈起——这也是为什么 §3.4 的思维陷阱强调"排斥项缺失或带宽过小会让粒子坍缩"。
值得多想一层:排斥项在**控制**语境里到底意味着什么?在纯变分推断里,排斥项只是"防止粒子坍缩、保证逼近质量"的数学装置;但在 MPPI 的控制语境里,它有了更具体的含义——保留多个候选行为方案。
每个粒子是一条候选控制序列,排斥项让粒子铺开,等价于让控制器同时"考虑"多种可能的应对(左绕的、右绕的、加速的、减速的),而不是过早地一头扎进某一种。
这正是避障所需的"开放心态":在还没确定哪条路更好之前,先保留所有可行的候选。等 SVGD 侦察出哪个 mode 最优、再由 MPPI 锁定收敛——这是一个"先发散探索、后收敛锁定"的过程。排斥项管前半段(发散、保留多样),mode-seeking 管后半段(收敛、锁定单峰)。
所以排斥项不是可有可无的数学细节,它对应着控制上一个实在的需求:在做决定之前,别太早把选项排除掉。
这也和探索-利用的经典张力呼应——排斥项是探索,吸引项是利用,SVGD 的两项恰好把这对张力编码进了粒子的运动。
SVG-MPPI 的四步工程流程。 SVG-MPPI 用一个**改进的** SVGD(注意是改进版,不是直接跑标准 SVGD)来"侦察"出一个好的目标 mode,再交给 MPPI 收敛:
- 输运 guide particles、估计目标 mode:用改进 SVGD 最小化反向 KL(RKL)散度,把一小组 guide particles 输运到分布的高概率区;这些粒子的**输运轨迹**被用来粗略估计一个收敛的目标 mode。
- 取峰为名义序列:把这组粒子里**序列代价最低**的那个粒子,直接当作目标 mode 的峰、即 MPPI 的名义控制序列。
- 拟合协方差:用一个高斯拟合算法、结合粒子的输运轨迹,粗略估计这个 mode 的协方差,得到自适应的 \(\Sigma\)。
- mode-seeking MPPI:以上面估出的均值(名义序列)与协方差,跑一次标准 MPPI 采样——因为均值和协方差已锁定在单个目标 mode 上,这次采样只覆盖该 mode,加权平均不再跨峰、不会取两峰中间的危险折中。
注意第 1 步用的是**反向 KL(RKL)**散度,这不是随意的选择,而是 mode-seeking 的数学根源。
逼近一个分布 \(p\),有两种 KL 方向:前向 KL \(\mathrm{KL}(p\,\|\,q)\) 是 mode-covering(覆盖型)——它惩罚"\(p\) 有概率而 \(q\) 没有",逼着 \(q\) 把 \(p\) 的所有峰都盖住,用单高斯逼近双峰时 \(q\) 会摊在两峰之间(正是那个撞墙的平均);反向 KL \(\mathrm{KL}(q\,\|\,p)\) 是 mode-seeking(寻峰型)——它惩罚"\(q\) 有概率而 \(p\) 没有",逼着 \(q\) 缩进 \(p\) 的某一个峰里、而不敢跨到峰间的低概率区。
SVG-MPPI 要的恰恰是后者:它**故意**用 RKL,让解收敛进单个 mode、躲开峰间危险地带。所以"mode-seeking"不只是一句工程口号,它对应着"选反向 KL 而非前向 KL"这个具体的数学决定——理解了 KL 的两个方向,你就理解了为什么 SVG-MPPI 天然不会取两峰中间,而 vanilla MPPI 的高斯加权平均(隐含 mode-covering 式的矩匹配)会。
这两个 KL 方向有个形象的几何说法,帮你记牢。前向 KL(mode-covering)有"矩匹配"倾向——它逼着近似分布 \(q\) 的均值和方差去匹配目标 \(p\) 的整体矩,双峰时均值落在两峰中间、方差被撑大去覆盖两峰,结果 \(q\) 摊成一个跨越两峰的胖高斯(正是撞墙的那个平均)。
反向 KL(mode-seeking)则有"零强制(zero-forcing)"倾向——它强烈惩罚"\(p\) 几乎为零处 \(q\) 却有显著概率",于是 \(q\) 不敢延伸到两峰之间的低概率谷底,只能缩进某一个峰里。
一句话:前向 KL"贪心地要盖住所有峰"(结果摊在中间),反向 KL"保守地只占一个峰"(避开谷底)。vanilla MPPI 的加权平均本质是矩匹配(用样本估计目标分布的均值),所以它继承了前向 KL 的"摊到中间"毛病;SVG-MPPI 改用反向 KL,正是为了换上零强制的"只占一峰"行为。
把"矩匹配 vs 零强制"这对几何直觉记住,你以后看到任何变分推断方法,一看它用哪个 KL 方向,就能立刻判断它会 mode-covering 还是 mode-seeking。
第 2 步还有个易被忽略的细节值得想清楚:为什么取**序列代价最低**的那个粒子当峰,而不是取所有 guide particles 的**均值**?因为这正是要避免的陷阱的翻版——如果 guide particles 已经铺到了两个峰(SVGD 的排斥项让它们这么做),取均值又会把均值拉到两峰中间,重蹈"多模平均撞墙"的覆辙。取最低代价粒子则是在已铺开的粒子里**挑一个**真实落在某个峰上的,天然落在 mode 内、不在峰间。
这个选择和"用 RKL 寻峰"是一致的:整个流程从头到尾都在**避免任何形式的跨峰平均**——SVGD 用排斥铺开感知多峰、RKL 让收敛偏向单峰、取最低代价粒子而非均值挑出峰上的点、最后 MPPI 只在这一个峰内加权。每一步都在防"平均到峰间",这才是 SVG-MPPI 能避开撞墙的完整逻辑链。
把"寻峰怎么救"用一个最小实现跑出来,与朴素平均对照。同样的双峰避障场景:候选轨迹分成左绕、右绕两簇(模拟 SVGD 铺开后感知到的两个 mode),分别用"朴素全局加权平均"和"按中途位置聚类、取低代价簇加权"处理:
# 候选轨迹: 左绕(先+y后+x)与右绕(先+x后+y)各半 + 噪声, 模拟双峰提议
# (A) 朴素全局加权平均(vanilla 式)
w = np.exp(-(J - J.min())/lam); w /= w.sum(); U_avg = (w[:,None,None]*U).sum(0)
# (B) 寻峰: 按中途点位置聚成两簇, 各自加权, 取代价更低的那簇
lab = midpoint[:,1] > midpoint[:,0] # 左上簇 vs 右下簇
for L in [True, False]:
idx = np.where(lab==L)[0]
ww = np.exp(-(J[idx]-J[idx].min())/lam); ww /= ww.sum()
U_cluster = (ww[:,None,None]*U[idx]).sum(0) # 单簇内加权, 不跨峰
输出:
朴素全局平均把左右两簇平均到一起,落进障碍、代价高达 \(1544\)(撞了);而聚类寻峰只在**单个簇内**加权,避开了跨峰平均,代价仅 \(45.5\)、安全通过。
这个最小实现用聚类来"分峰",是寻峰思想最朴素的体现;SVG-MPPI 用改进 SVGD 做这件事更精细(用粒子输运轨迹估计 mode 与协方差),但内核一致——先把不同 mode 分开,只在选定的一个 mode 内加权。这段代码也正是本节练习 1 让你实现的那个"最朴素寻峰"的参考。
论文在快速机动地面车的仿真与实车实验中表明,SVG-MPPI 在路径跟踪与避障上胜过原始 MPPI 及其他先进的采样式随机最优控制算法;源码开放在 kohonda/proj-svg_mppi(ICRA 2024,ROS + Docker 一键复现)。
这里要强调"改进的 SVGD"而非标准 SVGD。标准 SVGD 要迭代很多步、用很多粒子才能让粒子群充分逼近目标分布,那样既慢又重,会抵消 MPPI 闭式快速的优势。
SVG-MPPI 用的是一个**轻量化**的版本:它不追求让粒子精确逼近整个分布,只用**少量** guide particles、跑**少数几步**,目的仅仅是"粗略侦察出一个值得收敛的目标 mode"——侦察到位就交棒给 MPPI。
这是一种典型的"够用就好"工程取舍:把昂贵的 SVGD 压缩成一次廉价的方向侦察,而不是让它扛起整个推断任务。
理解这一点很重要——如果你照搬完整的标准 SVGD,会发现它慢得无法实时,那不是 SVG-MPPI 的本意。
这种"只跑少数几步就够用"的做法,背后有一个更一般的思想值得点出——它和机器学习里的**摊销推断(amortized inference)**精神相通。
传统变分推断对每个新问题都要从头迭代到收敛(昂贵);摊销推断则训练一个网络,把"如何快速给出近似解"这件事预先学好,新问题来了只需一次前向(便宜)。
SVG-MPPI 没有训练网络,但它做了一件类似的事:它不让 SVGD 从头收敛到完美,而是利用**时序连续性**——上一周期已经侦察出的 mode,为这一周期提供了极好的起点(warm-start 的思想用到了 SVGD 上),于是这一周期只需在上次结果附近跑几步微调即可。
换句话说,跨周期的连续性"摊销"了 SVGD 的收敛成本:不必每周期从零开始,因为 mode 不会在一个控制周期内突变。
要标注边界:摊销推断靠**离线训练**的网络来摊销,SVG-MPPI 靠**在线的时序 warm-start** 来摊销——机制不同,但"用历史/预学习避免每次从头收敛"的核心直觉一致。
理解这个联系,你会发现 SVG-MPPI 的"少数步"不是偷工减料,而是合理利用了控制问题的时序结构——这和第 2 章 warm-start 让 MPPI 每周期只需少量迭代是同一种智慧。
与 SV-MPC 的对比:为什么不直接输运所有样本¶
要真正理解 SVG-MPPI 的取舍,得把它和另一条更"正统"的多模态路线——SV-MPC(Stein Variational MPC)——摆在一起。
处理多模态最优分布,学界大体有两条路:其一,把 MPC 当成贝叶斯推断,用 SVGD 直接把一大群样本输运到后验上去逼近整个多峰分布(SV-MPC,Lambert 等, CoRL 2020);其二,用**高斯混合模型(GMM)等更有表达力的模型**、通过变分推断去拟合多峰分布。
这两条路都擅长**捕获**多峰,但有一个共同的致命伤:它们**求不出闭式解**,必须迭代地"采样—评估—更新"才能收敛。
迭代为什么是代价?SVG-MPPI 论文点得很清楚:迭代更新会**劣化收敛**——因为每次迭代的解都是次优的,而且序列化的迭代过程**限制了并行度和每次迭代能用的样本数**。
这恰恰打在 MPPI 最珍贵的性质上:MPPI 之所以快,就是因为它一步闭式(采样—加权平均,不迭代),能把上千条 rollout 一次性并行(第 2 章 §2.2 的 GPU 并行)。一旦改成 SVGD 那样迭代,闭式没了、并行也被迭代串行化卡住了。
SV-MPC 还有一个具体的工程负担:它要**输运所有样本**(哪怕在不可微情形下用代理梯度也能做),但这让**每个样本的计算成本大幅上升**,从而**限制了样本总数**。
SVG-MPPI 的破解之道正在于"分工":它不输运所有样本,只更新**一小撮 guide particles** 做侦察,再把侦察结果(一个目标 mode 的均值和协方差)交给标准 MPPI 去并行采样——既探索到了好解,又把计算成本压住了,而且和 SV-MPC 一样适用于不可微问题。
一句话:SV-MPC 用 SVGD 扛起整个推断(慢、样本少、但覆盖多峰);SVG-MPPI 用 SVGD 只做轻量侦察、把重活交给闭式 MPPI(快、样本多、但只锁一个 mode)。
这个取舍不是没有代价。后续研究(如 Aldrich 与 Jenkins 2025 的 SOPPI)观察到,SVG-MPPI 的**单模特性**在某些任务上有副作用:因为它只锁定一个 mode,会倾向于偏好某一侧的动作(比如倒立摆任务里更偏向正向或负向的大幅摆动),在一部分指标上收敛更快、另一部分上反而更慢。
这提醒你:mode-seeking 是一种**有意的偏置**——用"放弃覆盖其他 mode"换"闭式快速收敛"。
当任务确实只需要一条好路径时,这个交易很划算;当任务需要同时保留多个候选方案(如需要随时在左绕/右绕间切换以应对动态障碍)时,可能就需要真正多模的方法(SV-MPC、轨迹聚类)了。
顺带说说第三条多模路线——高斯混合(GMM)变分。既然单个高斯表达不了多峰,一个自然念头是用**多个高斯的混合**去拟合多峰分布(每个高斯盖一个峰),通过变分推断估计混合参数。
这类方法确实擅长**捕获**多峰,但 SVG-MPPI 论文把它和"输运样本"那条线归为一类,指出了共同短板:它们**求不出闭式解、需要迭代更新**,于是和 SV-MPC 一样丢掉了 MPPI 的闭式快速收敛与并行优势。
所以三条多模路线可以这样排:SV-MPC(输运全部样本逼近后验)和 GMM 变分(多高斯拟合)都走"完整捕获多峰"的路、代价是迭代;轨迹聚类**走"先分簇再各自平均"的路、避免跨峰平均但保留多个候选;**SVG-MPPI 走"侦察后锁定单峰"的路、用放弃多峰换闭式速度。没有哪条绝对最优——取决于你是否真的需要同时握着多个 mode,还是只要这一刻最好的那一个。
给一个选择多模路线的实用原则。问自己一个问题:下游需不需要多个候选方案? 如果你的系统只需要"当前最好的那一条路"去执行(大多数实时控制就是如此),那 SVG-MPPI 的"锁定单峰"最划算——它不浪费算力维护用不上的其他 mode。如果你的系统确实要**同时保留多个候选**——比如一个上层决策模块要在"左绕"和"右绕"之间根据后续信息再做选择、或者要随时准备在两个方案间切换以应对突变——那就需要真正多模的方法(轨迹聚类保留多簇、SV-MPC/GMM 保留完整后验)。
再叠加计算预算:要多模又要实时,轨迹聚类比 SV-MPC/GMM 更可行(前者不需迭代)。所以决策链是:先问"要不要多候选",不要就 SVG-MPPI;要的话再问"算力够不够迭代",够就 SV-MPC/GMM、不够就轨迹聚类。把这条决策链记住,面对多模需求时就不会在四条路线里盲目纠结。
本质洞察:SVG-MPPI 的精髓是"用 SVGD 侦察、用 MPPI 收敛"的分工。SVGD 擅长感知多峰但迭代慢;MPPI 闭式快但只有单峰。SVG-MPPI 让 SVGD 只干"挑哪个峰"这件轻量侦察活(少量 guide particles、粗略估计),把"在选定的峰内快速收敛"交给 MPPI。这又是第 2 章 §2.4 那种"让两种方法各管自己擅长的一段"的混合哲学的实例。而真正的关键转折是 mode-seeking 而非 mode-covering——不贪心地要覆盖所有峰(那既慢、又会退回"平均"的老问题),而是果断锁定一个好峰、全力收敛。这份"克制"与 §3.1 的 RMPPI 一脉相承:在 MPPI 的采样框架内做**最小必要**的结构改动去解决一个具体缺陷,而不是推倒重来换一套优化器。
本质洞察:把四节连起来看,"单模态"是高斯提议最难补的一个侧面。位置(warm-start)、尾部(Log)、时间结构(Smooth)都是对单个高斯做**连续形变**就能改善的;而多峰是一个**离散结构**——"向左还是向右"无法靠连续地挪动、加宽、加重尾来表达。SVG-MPPI 的贡献正在于:它引入了一种"用一群粒子去感知离散结构、再坍缩回单个 mode"的机制,在不放弃 MPPI 闭式高斯采样的前提下,绕过了单高斯表达不了多峰这个结构性障碍。这提示了一个更一般的判断:当你的困难是"参数不对",调 \(\lambda\)/\(\Sigma\)/均值即可;当你的困难是"分布形式不对"(多峰、离散选择),就得换表示,而不是继续调参数。
⚠️ 常见陷阱¶
编程陷阱:在多峰场景直接对全部采样做加权平均,不做寻峰。 - 错误描述:照搬 vanilla MPPI 的"采样→加权平均",在左右绕这类双峰场景直接输出加权平均控制。 - 现象/后果:如本节 demo,输出落在两峰中间、笔直撞向障碍——而且代价评估还可能显示这条平均轨迹"代价不高"(因为它没绕远路),让你误以为算法在正常工作。 - 根本原因:加权平均假设最优解是单峰的;多峰时,两个低代价峰的平均可能落在高代价的谷底(障碍)。 - 正确做法:先识别多峰(如 guide particles 铺开后聚成几簇),锁定一个目标 mode(取最低代价峰),只在该 mode 内做 MPPI 加权(SVG-MPPI 的寻峰);或用轨迹聚类先把跨峰的样本分开再各自平均。自检:画出采样轨迹,若它们明显分成两簇,就绝不能直接平均。
概念误区:以为 SVG-MPPI 同时覆盖所有 mode。 - 错误描述:把 SVG-MPPI 理解成"用 SVGD 维护多个高斯、同时覆盖所有避障路径"。 - 现象/后果:照这个错误理解去实现,要么维护多模分布让算法变慢、丢掉 MPPI 的闭式快速收敛,要么没真正解决"别取中间"的问题。 - 根本原因:SVG-MPPI 是 mode-seeking(寻峰、只锁定一个目标 mode),不是 mode-covering(覆盖所有峰)。覆盖所有峰会牺牲快速收敛,正是论文要避免的。 - 正确做法:理解 SVGD 在这里只用于**侦察、挑出一个**目标 mode;最终的 MPPI 采样是围绕单个 mode 的标准高斯采样。覆盖多峰是另一类方法(如多假设/聚类),与 SVG-MPPI 的设计取舍不同。
思维陷阱:以为多峰问题靠"加大 K、加大 Σ、多撒样本"就能解决。 - 错误描述:遇到双峰避障卡住,就把样本数 \(K\) 和协方差 \(\Sigma\) 调大,指望撒得多、撒得开就能选对路。 - 现象/后果:撒再多再开,最后那一步加权平均仍可能把左右两簇样本平均到中间撞墙;\(\Sigma\) 过大还会让样本效率崩、控制变抖。 - 根本原因:多峰是提议分布的**表示**问题,不是样本数量问题。单个高斯无论撒多少样本,它的加权均值还是单峰式的、可能落在峰间。 - 正确做法:换提议的表示(寻峰、多假设、聚类),从根上让"跨峰平均"不会发生,而不是在错误的单峰表示上堆样本。
练习¶
- (实现题) 复现本节的多模平均失败:构造左绕、右绕两条安全路径,验证它们各自安全但逐元素平均后撞障碍。
再实现一个最朴素的"寻峰":把两簇样本按终点位置聚成两类,分别求加权平均,取代价更低的那一类输出,验证它能避开障碍。
2. (设计扩展题) 实现 SVGD 更新规则(RBF 核 + 两项),在一个一维双峰目标分布 \(p(\theta)\propto e^{-J(\theta)/\lambda}\)(\(J\) 有两个等深的谷)上跑若干步,画出粒子的分布演化。去掉第二项(排斥项)重跑,观察粒子是否坍缩到单个峰——以此理解排斥项对"感知多峰"的作用。
3. (B 型·源码精读 / 思考题) 精读 kohonda/proj-svg_mppi 的 svg_mppi.cpp 与 stein_variational_mppi.cpp,对照本节四步流程,找出代码里"输运 guide particles""取最低代价粒子为名义""高斯拟合协方差""mode-seeking MPPI 采样"分别在哪。思考:为什么用 guide particles 的**输运轨迹**(而非最终位置)来估计协方差?
§3.5 U-MPPI:Unscented Transform 感知不确定性 ⭐⭐⭐¶
动机:MPPI 看得见"撞没撞",看不见"多大概率撞"¶
到这里,前四节修的都是**提议分布**本身——位置、时间结构、尾部、模态。这一节换一个角度:rollout 怎么算。
vanilla MPPI 的每条 rollout 是一条确定的轨迹——给定一个噪声样本,前向积分出一条状态序列,看它撞没撞、代价多少。
但真实系统有不确定性(状态估计噪声、模型误差、扰动),系统从某个状态出发,下一步其实是一个**分布**而非一个点。
vanilla MPPI 不显式传播这个分布,于是它只能回答"这条采样轨迹撞没撞",回答不了"考虑到不确定性,从这里走有多大概率撞"。
这个区别在安全攸关场景很要命。一条轨迹可能恰好擦着障碍边缘没撞(代价低),但只要状态稍有偏差就会撞——它其实很危险,碰撞**概率**很高。vanilla MPPI 看不到这一点,可能把这条"侥幸没撞但高风险"的轨迹当成好解。
这里有必要厘清不确定性的两个来源,因为它和 §3.1 容易混。其一是**模型失配/扰动**——系统的真实演化偏离你的标称模型(§3.1 RMPPI 处理的就是这个,靠反馈把状态拉回来);其二是**状态估计噪声/过程噪声**——你对当前状态本身就测不准,或动力学带随机性。§3.1 关心的是前者,用反馈对抗;§3.5 关心的是后者,用传播量化。
两者都叫"不确定性",但 §3.1 是"我的模型对不对、能不能纠回来",§3.5 是"我对状态的认识有多确定、风险多大"。
一个用反馈**对抗**不确定性,一个用传播**量化**不确定性——视角互补,也能叠加(一个鲁棒、一个风险感知)。
读到这里你可能会问:与其费力传播不确定性,为什么不干脆**把模型做得更精确**,让不确定性本身变小?这个想法在某些场景成立,但在 U-MPPI 的目标场景里行不通,原因有三。
其一,有些不确定性是**不可消除的**——状态估计噪声(传感器精度有限)、环境的内在随机性(其他智能体的不可预测行为)不会因为你的模型更精确而消失。
其二,即便模型能更精确,代价往往过高——高保真模型可能慢到无法实时 rollout,违背 MPPI 的实时前提。
其三,也是最根本的:"知道不确定性有多大"本身就是有价值的信息,而不只是要消除的麻烦。一个诚实地告诉你"这条路我有 20% 把握会撞"的控制器,比一个假装"我精确知道不会撞"却基于错误自信的控制器**更安全**——因为前者会主动避开高风险轨迹。
这正是 §3.5 风险感知的精髓:不是消除不确定性(做不到也不必),而是**正视它、量化它、据此做更安全的决策**。
把不确定性当信息而非噪声,是 U-MPPI 区别于"盲目相信标称模型"的 vanilla MPPI 的根本视角转变。
要让 MPPI 具备风险意识,就得让它**显式传播状态的不确定性**(均值 + 协方差),进而能估计碰撞概率。
问题是:传播一个分布,最朴素的办法是再撒一大堆蒙特卡洛样本——可 MPPI 本来就已经在撒 \(K\) 条 rollout 了,每条再套一层蒙特卡洛,计算量爆炸。U-MPPI 的答案是用 Unscented Transform 高效地传播不确定性。
历史与核心思想:用少数 sigma 点传播均值与协方差¶
Mohamed 等人 2025 年在 IEEE T-RO 上提出 U-MPPI(Towards efficient MPPI trajectory generation with unscented guidance: U-MPPI control strategy),在 MPPI 里嵌入 Unscented Transform(UT):不用大量随机样本,而用 \(2n_x+1\) 个**确定性**的 **sigma 点**来传播状态的均值和协方差(\(n_x\) 是状态维数)。
UT 本身不是 U-MPPI 发明的——它源自 Julier 与 Uhlmann 在 1990 年代为非线性滤波提出的工具,最广为人知的应用是**无迹卡尔曼滤波(UKF)**:在状态估计里,UKF 用 UT 取代 EKF 的雅可比线性化来传播状态分布,因更准、且不需算雅可比而被广泛采用。
U-MPPI 的贡献是把这件在**滤波/估计**领域成熟的工具,迁移到**控制/规划**的 rollout 里——让 MPPI 的每条轨迹也能像 UKF 传播状态那样,高效地带上协方差演化。
这是一次典型的跨领域工具迁移:滤波界用 UT 解决"如何传播带噪声的状态估计",U-MPPI 借它解决"如何让 rollout 携带不确定性"——同一个数学工具,两个领域的同构需求。
把 UT 放进"如何传播一个分布"的方法谱系里,能更清楚它的取舍。传播分布大体三条路:线性化(EKF)——用一阶泰勒近似,最便宜但强非线性下失真(前面 demo 已示 42% 误差);粒子滤波(蒙特卡洛)——撒大量随机粒子,最通用、能表示任意分布(包括多峰),但要成百上千个粒子才准、计算贵;UT(sigma 点)——介于两者之间,用 \(2n{+}1\) 个**确定性**点,对高斯(及近高斯)分布能精确到二阶矩、代价极小。
三者是"精度 vs 成本"谱上的三个点:EKF 最省最糙,粒子滤波最准最贵且能处理非高斯,UT 在"分布近高斯"的假设下取得了精度与成本的甜点。
U-MPPI 选 UT 而非粒子滤波,正是因为它要**在每条 rollout 内部**传播不确定性——若每条 rollout 再套几百个粒子,计算量直接爆炸;UT 的 \(2n{+}1\) 个点让这件事便宜到可行。
这个选择也暴露了 UT 的适用边界:当 rollout 内的状态分布强烈非高斯、多峰时,UT 的高斯假设会失准,那时才需要更贵的粒子式传播。
理解这个谱系,你就知道 U-MPPI 的 UT 不是"最好的传播方法",而是"在实时 rollout 这个约束下最划算的传播方法"。
UT 的逻辑分三步。第一步,生成 sigma 点:围绕当前状态均值 \(\mu_x\)、按协方差 \(P\) 摆放 \(2n+1\) 个确定性采样点——中心一个,沿协方差矩阵平方根的每个方向正负各一个:
第二步,传播:把每个 sigma 点通过(非线性)动力学前向一步 \(\chi_i' = F(\chi_i,\,u+\varepsilon)\)。
第三步,加权重组:用预设权重 \(w^m,w^c\) 把传播后的 sigma 点重新组合成新的均值和协方差:
这里的权重 \(w^m\)(算均值用)和 \(w^c\)(算协方差用)以及 sigma 点的"展开尺度" \(\lambda\)(即上面 \(\sqrt{(n{+}\lambda)P}\) 里的那个)不是随手定的,它们由几个标准参数决定:\(\alpha\) 控制 sigma 点离中心多远(通常取一个小正数,让点不要散太开)、\(\kappa\) 是次级缩放、\(\beta\) 用于在协方差权重里纳入分布的高阶信息(高斯下取 \(\beta=2\) 最优)。
直觉上,中心点 \(\chi_0\) 的均值权重最大(它最代表均值),两侧的点权重较小且对称;协方差权重在中心点上会因 \(\beta\) 而与均值权重略有不同。
这些参数有成熟的默认取值(沿用 UKF 的经验),实践中很少需要大改——理解"它们共同决定 sigma 点撒多开、各点占多大话语权"即可,不必每个都手调。
真正要小心的是前面陷阱讲的:sigma 点必须沿**矩阵平方根**摆放、权重必须按公式归一,这两点错了结果才会崩。
为什么这能行、又高效?把 UT 和蒙特卡洛对照跑一遍就清楚了——同一个非线性映射、同一个输入分布,比较 UT(\(2n{+}1\) 个点)和蒙特卡洛(\(20\) 万样本)算出的均值与协方差:
# UT: 2n+1 个确定性 sigma 点
sqrtP=np.linalg.cholesky((n+lam)*P)
sig=[mu]+[mu+sqrtP[:,i] for i in range(n)]+[mu-sqrtP[:,i] for i in range(n)]
Y=[f(s) for s in sig] # 传播
mu_ut=sum(w*y for w,y in zip(Wm,Y))
P_ut =sum(w*np.outer(y-mu_ut,y-mu_ut) for w,y in zip(Wc,Y))
# MC: 20 万随机样本传播后求样本均值/协方差
输出:
UT (5个点) 均值=[1.564 0.911] 协方差对角=[0.338 0.687]
MC (200000样本) 均值=[1.565 0.906] 协方差对角=[0.361 0.667]
→ UT 用 5 个确定性点就逼近了 20 万样本的均值/协方差
\(n=2\) 时 UT 只用 \(5\) 个点,算出的均值 \([1.564,0.911]\)、协方差对角 \([0.338,0.687]\),与 \(20\) 万蒙特卡洛样本的 \([1.565,0.906]\)、\([0.361,0.667]\) 几乎一致。UT 对高斯分布能精确捕获到均值和协方差(直至三阶矩),而代价只有 \(2n+1\) 个确定性样本——比蒙特卡洛高效几个数量级。这正是 U-MPPI 名字里 "efficient" 的来源:它让"传播不确定性"这件事便宜到可以塞进 MPPI 的每条 rollout。
为什么不用更省事的**一阶线性化**(EKF 那套:用雅可比 \(J\) 把协方差按 \(P'=JPJ^\top\) 传播)?因为线性化只取了非线性映射的一阶项,在强非线性处会失真。同一个非线性映射上对比 UT 与线性化、以蒙特卡洛为真值:
线性化把协方差估偏了约 \(42\%\),UT 只偏约 \(19.5\%\)——明显更接近真值,且 UT 根本不需要算雅可比(对黑箱/不可微动力学也能用,这与 MPPI 的黑箱友好一脉相承),只需把 sigma 点喂进动力学正向传播即可。
这正是 UT 在非线性系统里通常优于 EKF 式线性化的原因:它用少数确定性点"探"出非线性的形状,而非用一阶切线去近似。
对 MPPI 这种动力学常常非线性、甚至是神经网络黑箱的场景,UT 的"无需雅可比 + 更准"双重优势,使它成为传播不确定性的自然选择。
从不确定性到风险意识与机会约束¶
有了高效传播的均值和协方差,U-MPPI 就能做 vanilla MPPI 做不到的两件事。其一,风险敏感的代价:U-MPPI 引入一个显式考虑轨迹不确定性/风险的代价函数,在评估每条 rollout 时把"这条路有多不确定"算进去——这不仅提升安全性,还增强了状态空间探索、降低陷入局部极小的风险(论文报告它在室内杂乱环境里比 vanilla MPPI 和 Log-MPPI 的碰撞率显著更低)。
其二,机会约束(chance constraints):它的扩展 C²U-MPPI 用传播出的协方差**估算碰撞概率**,当某条轨迹的碰撞概率 \(P(\text{collision})>\delta\)(一个用户设定的风险阈值)时给它加上高代价。
这把"约束"从 vanilla MPPI 那种"撞了才罚"的硬碰硬,变成了"快要太危险了就提前规避"的概率性约束——是 MPPI 走向**安全认证**的重要一步。
那么"协方差"具体怎么变成"碰撞概率"?直觉上,UT 在每个时刻给出状态的均值 \(\mu_x'\) 和协方差 \(P'\),等于说"机器人此刻大概在 \(\mu_x'\),但有 \(P'\) 这么大的不确定椭球"。
把这个不确定椭球与障碍的几何叠加,就能算出"椭球有多大一块落进了障碍"——那就是碰撞概率。协方差越大(越不确定)、或均值离障碍越近,这个概率就越高。
于是同样一条"擦边"轨迹,若它协方差大,碰撞概率就高、被加重罚;若协方差小(很确定能擦过去),概率低、罚得轻。
这正是 vanilla MPPI 缺的那一环:它只有均值("大概在哪"),没有协方差("可能偏多远"),所以分不清"稳稳擦过"和"侥幸擦过"——而在安全攸关的场景里,这二者天差地别。
把"稳稳擦过 vs 侥幸擦过"量化出来。设障碍是中心在原点、半径 \(R=1\) 的圆,两条轨迹的均值都落在距障碍**边缘 \(0.3\)** 处(即同样擦边),但协方差不同——一条很确定(\(P=\mathrm{Diag}(0.01,0.01)\)),一条很不确定(\(P=\mathrm{Diag}(0.25,0.25)\))。用传播的协方差估计各自的碰撞概率:
def collision_prob(mu, P, rng): # 估 P(位置落入障碍圆内)
pts = rng.multivariate_normal(mu, P, 100000)
return np.mean(np.hypot(pts[:,0]-OBS[0], pts[:,1]-OBS[1]) < R)
mu = np.array([1.3, 0.0]) # 距中心1.3, 距边缘0.3, 两条轨迹均值相同
p_small = collision_prob(mu, np.diag([0.01, 0.01]), rng) # 稳稳擦过
p_large = collision_prob(mu, np.diag([0.25, 0.25]), rng) # 侥幸擦过
输出:
两条轨迹的均值**完全相同**——vanilla MPPI 只看均值,会给它们打**一样**的分;但机会约束按协方差区分:协方差大的那条碰撞概率高达 \(20.4\%\),是协方差小那条(\(0.1\%\))的约 \(158\) 倍。
C²U-MPPI 正是对这种高碰撞概率的轨迹(\(P(\text{collision})>\delta\))加重罚,于是控制器会主动避开"侥幸擦过"的危险轨迹、偏好"稳稳擦过"的安全轨迹。
这就是把协方差捡回来的实际威力:同样的均值,因为不确定性不同,风险可以差两个数量级——而这个差别,没有协方差的 vanilla MPPI 完全看不见。
那为什么不用更简单的办法——直接把安全距离调大(要求离障碍更远)?因为"调大安全距离"是一刀切的:它对所有轨迹施加同一个保守裕度,不管这条轨迹其实很确定(本可以贴近)还是很不确定(确实该远离)。
结果是**过度保守**——在开阔、确定性高的地方也强行绕远,牺牲性能;而在拥挤、不确定性高的地方一个固定裕度可能又不够。
机会约束的高明之处正是**让保守程度随不确定性自适应**:协方差小(确定)就允许贴近,协方差大(不确定)才要求远离。
这等于把"该多保守"这件事,从一个手调的固定常数,变成了由传播出的协方差**自动决定**的量。这也呼应了 §3.1 RMPPI 把"鲁棒"拆成可调旋钮、第 2 章把"采样健康"变成 ESS 的同一种思路——把一个靠经验拍脑袋的裕度,换成由可观测量驱动的、自适应的决策。
那这个碰撞概率阈值 \(\delta\)(C²U-MPPI 里 \(P(\text{collision})<\delta\) 的那个 \(\delta\))该怎么选?这是个有实际意义的工程旋钮,不是随便取的。\(\delta\) 直接编码了你愿意承担多大风险:\(\delta\) 取得越小(如 \(0.001\)),控制器越保守、越远离障碍、但可能错失贴近障碍的高效路径;\(\delta\) 取得越大(如 \(0.1\)),控制器越激进、路径越高效、但碰撞风险也越高。
选 \(\delta\) 的实用原则是看**任务的容错性**:载人系统、贵重设备、不可逆失败的场景(如悬崖边导航)取很小的 \(\delta\),宁可保守;可恢复、低代价失败的场景(如扫地机器人轻碰墙)可以取大一些的 \(\delta\),换取效率。
还要注意 \(\delta\) 与传感器质量耦合——状态估计越不准(协方差本底越大),同样的 \(\delta\) 会让控制器更保守,因为不确定椭球本来就大。所以在噪声大的平台上,\(\delta\) 可能需要相应放宽,否则控制器会因为"对什么都没把握"而寸步难行。
一个常见的调试现象是:\(\delta\) 设得过小导致机器人在稍微拥挤的地方就完全不敢动(过度保守的另一种表现),这时该适当放大 \(\delta\) 或改善状态估计,而非一味压小。
实验佐证与 UT 在 MPPI 里的双重角色¶
U-MPPI 的实验印证了"风险代价提升探索"这个略反直觉的说法。论文在地面机器人(如 Jackal)的导航任务上,对比了 vanilla MPPI、Log-MPPI 与 U-MPPI:U-MPPI 引入显式考虑轨迹不确定性的风险敏感代价后,不仅碰撞率显著更低,还**增强了状态空间探索、降低了陷入局部极小的风险**。
为什么"考虑风险"反而探索更强?因为 UT 传播的协方差让控制器看到了"哪些方向不确定性大",于是它能更聪明地在这些方向上展开、而不是盲目地撒——风险信息本身成了引导探索的线索。这把"安全"和"探索"这对常被视为对立的目标,统一在了同一个不确定性传播机制之下。
再追问一层:为什么风险感知能帮 MPPI 逃出局部极小?vanilla MPPI 陷局部极小,通常是因为它围着当前这条"还行但不最优"的轨迹反复采样、出不来——所有样本都挤在一个局部最优附近。
而当代价里纳入了不确定性信息,控制器对"高不确定性的区域"会有不同的态度:这些区域往往正是"还没充分探索、可能藏着更好解"的地方。
风险敏感代价让控制器在评估时把这种不确定性算进去,相当于给"去未充分探索的方向看看"提供了一个内在的驱动力,而非死守当前局部最优。
这与强化学习里"用不确定性驱动探索"(如基于好奇心/信息增益的探索)是同一种思想——不确定性不只是要回避的风险,也是指示"哪里值得一探"的信号。
U-MPPI 把这个思想带进了采样式 MPC:同一个协方差,既用来回避真正危险的高风险轨迹,又用来标记值得探索的高不确定区域,一举两得。这也解释了论文里那个略反直觉的结果——加了风险代价,碰撞率降低的**同时**探索还增强了。
值得点明的是,Unscented Transform 在 MPPI 生态里其实有两种不同的用法,初学时容易混淆。
其一是本节讲的 U-MPPI:用 UT 传播**每条 rollout 内部的状态不确定性**(状态估计噪声、过程噪声),从而给每条轨迹算风险/碰撞概率。
其二出现在前一节提到的某些工作里:用 UT 来**塑造采样分布本身**——把 sigma 点当作一种结构化的采样方式去探索控制空间,目的是提升状态空间探索、跳出局部极小(一些资料把这类思路也归到"unscented 引导"名下)。
两者都借了 UT"用少数确定性点高效表示一个分布"的本事,但作用对象不同:一个作用在**状态不确定性的传播**上(回答"多大概率撞"),一个作用在**控制采样的结构**上(回答"往哪些方向探")。读论文时分清"UT 在传播什么",就不会把两种用法搞混。
这也再次回扣样本效率主线,但角度很特别。第 2 章讲的样本效率,是"在上千条**随机** rollout 里,有用的占多少"。
UT 给出的是另一种效率:用 \(2n{+}1\) 个**确定性**点,精确(对高斯直至三阶矩)地表示一个分布的均值和协方差——这是"表示一个分布"所需样本的理论下限级别。
所以 U-MPPI 同时活在两种采样哲学里:外层仍是 MPPI 的大批随机采样(为了优化控制),内层每条 rollout 套一个 UT 的少数确定性采样(为了传播不确定性)。
理解这个"外随机、内确定"的双层结构,就抓住了 U-MPPI 计算上为何可行的关键——内层只多花 \(2n{+}1\) 个点的代价,而不是再套一层蒙特卡洛。
本质洞察:U-MPPI 改的不是提议分布(前四节),而是 rollout 对世界的刻画——从"一条确定轨迹"升级为"带不确定性的轨迹分布"。它和样本效率主线也有呼应,但方向相反:第 2 章担心"撒太多随机样本浪费",UT 则反过来用**确定性**的少数 sigma 点替代大批随机样本来估计分布——这是另一种"少而精"的样本效率。更深一层,传播**协方差**(而不只是均值)是这一切的关键:均值告诉你"预期走到哪",协方差告诉你"可能偏多远",只有后者才能回答"撞的概率多大"。vanilla MPPI 丢掉了协方差,所以它只有"撞没撞"的二元视角;U-MPPI 把协方差捡回来,于是有了"多大概率撞"的连续风险视角。从二元到概率,正是从"能跑"走向"敢认证安全"的分水岭。
⚠️ 常见陷阱¶
编程陷阱:sigma 点用错协方差平方根,或权重 \(w^m\)/\(w^c\) 不归一。
- 错误描述:用普通逐元素开方代替矩阵平方根(Cholesky/对称平方根)来摆 sigma 点,或重组时权重没设对、不满足 \(\sum w^m=1\)。
- 现象/后果:传播出的协方差错误(甚至非正定),碰撞概率估计离谱,风险代价完全失真;调试时表现为"加了 UT 反而更不安全"。
- 根本原因:sigma 点必须沿协方差矩阵平方根 \(\sqrt{(n{+}\lambda)P}\) 的列方向摆放,这是矩阵平方根(Cholesky 分解的列),不是元素开方;权重 \(w^m,w^c\) 有特定公式且均值权重须归一。
- 正确做法:用 np.linalg.cholesky 得到矩阵平方根,按标准 UT 公式生成 sigma 点与权重;自检:对一个线性映射,UT 的输出协方差应与解析传播 \(APA^\top\) 完全一致。
概念误区:以为 sigma 点就是"少撒几个随机样本"。 - 错误描述:把 \(2n+1\) 个 sigma 点理解成"为了省事只随机撒 \(2n+1\) 个样本"。 - 现象/后果:若真用随机样本代替确定性 sigma 点,\(2n+1\) 个随机样本估计协方差的方差极大、极不可靠,效果远不如 UT。 - 根本原因:sigma 点是**确定性**地、精心摆放在协方差主轴上的点,专门为"精确重构均值和协方差"设计;它不是随机抽样,而是一种确定性求积(quadrature)。少量随机样本和少量 sigma 点是两回事。 - 正确做法:严格按 UT 公式确定性地放置 sigma 点;理解它的精度来自"摆放位置 + 权重"的数学设计,而非随机性。
思维陷阱:以为有了机会约束的概率估计,就等于硬安全保证。 - 错误描述:把 C²U-MPPI 的 \(P(\text{collision})<\delta\) 当成"碰撞被严格杜绝"。 - 现象/后果:在安全攸关系统里过度信任这个概率约束,省掉硬安全层;而概率估计本身依赖"协方差估得准、分布近似成立"等假设,一旦假设被破坏(强非线性、非高斯),估计就不可靠。 - 根本原因:机会约束是**概率**意义的约束("碰撞概率小于 \(\delta\)"),不是确定性意义的"绝不碰撞";且它建立在 UT/高斯近似之上,近似失效时保证也失效。 - 正确做法:把 C²U-MPPI 的保证理解为"显式、可调地控制碰撞风险",比 vanilla MPPI 的软约束强得多,但仍非硬保证;安全攸关时叠加硬安全层(如 CBF 滤波,见下文前沿)。
练习¶
- (实现题) 实现 Unscented Transform:给定均值 \(\mu\)、协方差 \(P\) 和一个非线性映射 \(f\),生成 \(2n+1\) 个 sigma 点、传播、重组出 \(\mu',P'\)。
用蒙特卡洛(大样本)验证你的 \(\mu',P'\)。再对一个**线性**映射 \(f(x)=Ax\) 验证 UT 输出的协方差精确等于 \(APA^\top\)。 2. (设计扩展题) 在一个带障碍的 2D 导航里,给 vanilla MPPI 加上"风险代价":用 UT 传播每条 rollout 的状态协方差,对"离障碍近且协方差大"的轨迹加罚。对比有/无风险代价时,控制器对"擦边飞过障碍"这类高风险轨迹的偏好如何变化。 3. (思考题) UT 用 \(2n+1\) 个确定性点高效传播不确定性,而 vanilla MPPI 用 \(K\)(上千)个随机样本做加权平均。
这两种"采样"的目的根本不同——一个为了**估计分布的矩**,一个为了**优化控制**。讨论:能否把它们的样本预算统一起来思考?U-MPPI 在"每条 rollout 套 UT"时,总的确定性点数是多少量级,相比"每条 rollout 套蒙特卡洛"省了多少?
§3.6 选型决策树:六个变体,怎么挑¶
六大变体讲完,最实用的问题是:面对一个具体任务,该用哪个?把它收成一棵决策树——按"哪个缺陷最致命"自上而下判断:
你的任务最大的痛点是什么?
├─ 扰动/模型失配导致约束被违反、行为发散? ──→ RMPPI(要理论保证)/ Tube-MPPI(实现简单)
├─ 控制抖动不可接受(执行器娇贵、需平滑)? ──→ Smooth-MPPI
├─ 环境高度杂乱、rollout 几乎全碰撞? ──→ Log-MPPI / GP-MPPI(带子目标引导)
├─ 存在多条等优路径、怕取中间撞墙? ──→ SVG-MPPI(寻峰)
├─ 需要风险/不确定性感知、想控制碰撞概率? ──→ U-MPPI / C²U-MPPI
├─ 需要收敛保证、想最优地设计协方差? ──→ CoVO-MPC(见第 4 章)
└─ 以上都不突出、标称模型够准、环境不杂乱? ──→ vanilla MPPI(第 2 章)就够了
读这棵树有个要点:它是按"最致命的痛点"**自上而下**走的,命中第一个匹配的分支即可——不是让你把所有分支都过一遍、把对应变体全堆上。
工程上通常有一个缺陷最突出(最影响任务成败),先解决它收益最大;其余缺陷若也存在,等主缺陷解决后再按"组合与冲突"那套逐个叠加。所以决策树给的是"先动哪个"的起点,不是"全都要"的清单。
把六个变体连同它们的取舍列成一张总表,便于横向对照:
| 变体 | 修哪个缺陷 | 在提议/rollout 上改了什么 | 核心机制一句话 | 主要代价 |
|---|---|---|---|---|
| Tube-MPPI | 模型失配 | 在执行端加跟踪层(挂在外面) | nominal MPPI + iLQG 管道跟踪 | planner-tracker 冲突、过度保守 |
| RMPPI | 模型失配 | 让提议在**闭环**下有效 | 增广状态 + rollout 含反馈 + 名义代价 | 多一个跟踪器与增广状态;保证是自由能上界、非硬约束 |
| Smooth-MPPI | 抖动 | 提议的**时间结构** | 控制导数空间采样再积分 | 略保守(平滑↔敏捷权衡) |
| Log-MPPI | 杂乱可行性 | 提议的**尾部** | NLN 重尾混合分布 | 偶发大动作本身偏抖;盲目探索有天花板 |
| SVG-MPPI | 单模态 | 提议的**模态**(寻峰) | SVGD 侦察目标 mode + mode-seeking MPPI | 多一步 SVGD 侦察 |
| U-MPPI | 不确定性 | rollout 的刻画(均值+协方差) | Unscented Transform 传播 + 风险代价 | 每条 rollout 多算 \(2n{+}1\) 个 sigma 点 |
这棵树是起点,不是教条。 三点提醒。其一,这些变体**大多不互斥、可以叠加**——你完全可以在杂乱且需要平滑的任务里同时用 Log(重尾)+ Smooth(导数空间采样),或在需要鲁棒又怕抖的任务里 RMPPI + Smooth。它们改的是提议分布的不同侧面,叠加往往是正交的。
其二,先判断主要缺陷:决策树按"最致命的痛点"分叉,是因为工程上通常有一个缺陷最突出,先解决它收益最大;其余缺陷可后续叠加。
其三,别忘了 vanilla 就够用的情形:如果你的模型准、环境不杂乱、路径唯一、执行器也不娇贵,第 2 章的 vanilla MPPI 加上 warm-start、平滑、约束钳位就完全够了——不要为了用变体而用变体,每个变体都带额外的复杂度和调参负担。
还有一个常见的选型误区值得专门点出:按论文的新旧或"听起来先不先进"来选,而不是按缺陷选。U-MPPI(2025)比 Tube-MPPI(2018)新,不代表它"更好"——它们解的是完全不同的缺陷(不确定性 vs 模型失配),新的那个对你的任务可能毫不相关。
同理,SVG-MPPI 用了时髦的 Stein 变分,但如果你的任务根本没有多条等优路径,它的寻峰机制就是多余的开销。年份和数学的精巧程度都不是选型依据,**你的任务暴露了哪个缺陷**才是。
这也是为什么本章从头到尾按"缺陷"而非"年份"组织——科研脉络的时间线(§科研发展脉络)只用来理解"为什么先有这个、后有那个",选型时要切换回"缺陷视角"。把这两个视角分开:读历史用时间轴,做工程用缺陷轴。
选型的另一维:计算开销¶
决策树按"缺陷"选型,但工程上还有一条硬约束常被忽略——计算预算。MPPI 是实时控制器(第 2 章的延迟预算),变体带来的额外计算可能直接顶破控制周期。
把几个变体相对 vanilla 的单周期开销实测一下(同样的 \(K=4096\)、\(T=30\),CPU numpy,仅作**相对**量级参考,GPU 上绝对值会小得多):
vanilla MPPI : 9.4 ms (基准 1.0x)
Smooth-MPPI : 9.4 ms (0.99x) — 只多一次 cumsum, 几乎免费
RMPPI : 10.0 ms (1.06x) — rollout 内多一个反馈项
Log-MPPI : 24.4 ms (2.59x) — NLN 采样比高斯贵
U-MPPI : 43.4 ms (4.61x) — 每条 rollout 套 2n+1 个 sigma 点
这组数字给选型加了一条很实在的提醒。Smooth-MPPI 和 RMPPI 几乎免费(约 1.0–1.06×)——它们只在采样方式或 rollout 内做了轻量改动,不增加传播的样本量;既然这么便宜,符合条件就值得加。
Log-MPPI 约 2.6×——开销主要来自 NLN 采样(对数正态 + 掩码比单次高斯贵),但仍在可接受范围。
U-MPPI 最贵,约 \(2n{+}1\) 倍(这里 \(n=4\) 故约 5×)——因为每条 rollout 内要传播 \(2n{+}1\) 个 sigma 点,这是它"感知不确定性"的内在代价。状态维数 \(n\) 越高,U-MPPI 越贵,高维系统要特别权衡。
要强调上面是 CPU numpy 的相对量级,GPU 上的图景会不同。第 2 章讲过,MPPI 在 GPU 上把 \(K\) 条 rollout 并行,绝对延迟小得多。
变体的额外开销在 GPU 上也会被重新分配:Smooth 的 cumsum、Log 的 NLN 采样都是逐元素操作,在 GPU 上几乎可以和原采样融合、额外成本被并行吃掉,相对开销可能比 CPU 上更小;而 U-MPPI 的 \(2n{+}1\) 倍传播意味着 \(2n{+}1\) 倍的 rollout 计算量,这个倍数在 GPU 上同样存在(并行度被 sigma 点占用),但若 GPU 算力有余、\(K\) 不顶满,它可能被现有并行容量吸收而不显著增加延迟。
所以这些相对数字要结合你的硬件读:CPU 上是"算力稀缺、倍数直接体现为时间",GPU 上是"看并行容量还有没有余量"。
一个实用建议是:在你的目标硬件上**实测**变体的单周期延迟,而不是照搬任何相对倍数——延迟预算是否被顶破,最终由硬件和 \(K/T\) 共同决定。
所以完整的选型其实是二维的:横轴是"修哪个缺陷"(决策树),纵轴是"花得起多少计算"。同样能改善某个侧面时,优先选便宜的;只有当便宜的不够、且计算预算允许时,才上贵的。
比如都为了鲁棒,RMPPI(1.06×)显然比某些重采样方案划算;而 U-MPPI 的风险感知虽好,但若你的控制周期已经吃紧、状态维数又高,就得掂量这 5× 是否真的花得起——或者退而用更轻量的风险近似。把"计算开销"这一维并入考量,选型才算落到真实工程上。
这里有个实用的"腾预算"技巧值得知道:当一个变体的额外开销让你超出延迟预算时,可以用**减少样本数 \(K\) 或时域 \(T\)** 来换回预算。
比如 U-MPPI 的 \(2n{+}1\) 倍传播让你超时,那把 \(K\) 降到原来的 \(1/(2n{+}1)\),总计算量就持平了。
但这不是免费的——第 2 章讲过,\(K\) 减小会降低有效样本数、采样质量下降。所以这是一个**三方权衡**:变体带来的能力提升、\(K/T\) 减小带来的采样质量下降、延迟预算的硬上限,三者要一起平衡。
实操上建议这样做:先在不限延迟的离线环境测出"用满 \(K\) 时变体能带来多大改善",再逐步降 \(K\) 看改善何时被采样质量下降抵消——那个临界点就是这个变体在你硬件上的"性价比甜点"。
如果降到延迟达标时改善已所剩无几,说明这个变体在你的预算下不划算,该换更便宜的变体或更强的硬件。这套"离线标定、在线达标"的流程,比拍脑袋设参数靠谱得多,也呼应了累积项目里"逐个加、逐个测"的方法论。
本质洞察:这张表最值得记住的,是最左和最右两列的对应关系——每个变体都只改提议分布(或 rollout)的一个侧面。这把"六个看起来各不相同的算法"统一成了一句话:vanilla MPPI 的高斯提议在"位置、时间结构、尾部、模态、不确定性刻画"这几个侧面上各有短板,每个变体认领一个侧面去补。理解了这个统一视角,你选型时就不必死记六个名字,而是反过来问:我的任务让目标分布在哪个侧面上最不像那个朴素高斯? 答案直接指向该用的变体。这也预告了第 4 章——CEM、Stein、Tsallis 等会把"MPPI 及其变体"进一步统一进一个更大的概率推断框架,那时你会看到,本章这些"侧面"其实是同一个母问题的不同投影。
统一视角:提议分布的五个侧面¶
把全章反复出现的"侧面"观点正式收口。第 1 章给了一个理想:最优提议分布就是目标分布 \(\mathbb{P}^\star\propto\mathbb{Q}e^{-S/\lambda}\),采样越接近它越好。
vanilla MPPI 用一个**开环、各向同性、单峰、薄尾、只传播均值**的高斯去近似 \(\mathbb{P}^\star\)——这五个限定词,正是它的五个短板,也正是本章六个变体各自要松开的那一个:
| 侧面 | vanilla 的假设 | 真实 \(\mathbb{P}^\star\) 常常是 | 松开它的变体 | 怎么松 |
|---|---|---|---|---|
| 位置(中心) | 围绕旧解、开环外推 | 围绕真实状态的闭环解 | warm-start(第 2 章)/ RMPPI | 反馈把中心拉回真实状态、并让采样知道有反馈 |
| 时间结构 | 各时刻独立(白噪声) | 时间相关、平滑 | Smooth-MPPI | 在导数空间采样再积分(积分=低通) |
| 尾部 | 薄尾(高斯钟形) | 重尾(偶有大动作) | Log-MPPI | NLN 重尾混合分布 |
| 模态 | 单峰 | 多峰(多条等优路径) | SVG-MPPI | SVGD 侦察、锁定一个目标 mode |
| 不确定性刻画 | 只传均值(确定轨迹) | 带协方差的轨迹分布 | U-MPPI | UT 传播均值 + 协方差 |
这张表是本章的"压缩包"。它给你三层价值。第一层是记忆:六个变体不再是六个孤立名字,而是五个侧面的一一对应,忘了细节也能从"哪个侧面"反推。
第二层是选型:面对新任务,逐个侧面自问"我的 \(\mathbb{P}^\star\) 在这个侧面上像不像高斯",不像的那个侧面直接点名对应变体(这比决策树更本质,因为决策树问"症状"、这张表问"病根")。
第三层是预判组合:因为五个侧面**大致正交**,多个变体叠加通常不冲突——你甚至能预判一个尚不存在的组合(如"重尾 + 多峰"该怎么拼),这正是 §3.6 越野车案例做的事。
更重要的是,这张表指向第 4 章的入口。本章是"一个侧面一处改进"地逐项增强 vanilla MPPI;而第 4 章会问一个更釜底抽薪的问题:能不能不做这种逐项增强,直接用一个更有表达力的分布族去拟合整个 \(\mathbb{P}^\star\)? CEM 用迭代精炼的高斯(甚至高斯混合)、Stein 用粒子、Tsallis 用更一般的指数族——它们试图一次性逼近 \(\mathbb{P}^\star\) 的多个侧面,并把 MPPI 揭示为这个更大框架里的一个特例。
本章的五个侧面,到那时会显出它们是同一个"如何逼近 \(\mathbb{P}^\star\)"母问题的不同投影。带着这张表进第 4 章,你会读得格外顺。
横向定位:六变体在控制方法版图里的位置¶
读到这里,你已经掌握了六个 MPPI 变体的细节。但要真正用好它们,还需要知道它们在更大的控制方法版图里站在哪——这样选型时才不会"只在 MPPI 内部打转",而忽略了别的范式可能更合适。把 MPPI 系列和读者已熟悉的几类方法对照:
| 方法 | 处理非光滑代价 | 处理黑箱动力学 | 硬约束保证 | 计算特点 | 多模态 |
|---|---|---|---|---|---|
| LQR / iLQR | ✗(需可微二次型) | ✗(需可微) | ✗(软,靠罚) | 快,闭式/迭代 | ✗ 单一最优 |
| 梯度 MPC(acados 等) | ✗(需光滑) | ✗(需可微/解析) | ✓(硬约束严格) | 快,但需好初值 | ✗ 局部最优 |
| MPPI(及本章变体) | ✓ 任意代价 | ✓ 黑箱可用 | ✗(软,本章核心局限) | GPU 并行、采样 | △ SVG-MPPI 部分解决 |
| 强化学习(PPO/SAC) | ✓ 任意奖励 | ✓ 免模型 | ✗(软,靠 reward shaping) | 离线训练贵、在线快 | △ 随机策略部分覆盖 |
这张表点出了 MPPI 系列的**生态位**:它的不可替代之处在于**同时**处理非光滑代价和黑箱动力学(第 2 章的杀手级场景)——这是梯度 MPC 和 LQR 做不到的;而它最大的短板是硬约束(本章反复强调),恰是梯度 MPC 的强项。
所以一个清醒的选型观是:代价光滑、动力学可微、且硬约束至关重要 → 用梯度 MPC(acados);代价非光滑或动力学是黑箱(如学到的神经网络模型、含接触的腿足)→ MPPI 系列是主力;愿意离线训练、追求在线极快 → RL;而 MPPI 与 RL 并非对立,第 2 章已提"用 RL 策略做 MPPI 的提议分布"是热门方向(Biased-MPPI 的一种用法)。
和 RL 的关系尤其值得厘清,因为初学者常把"采样"和"免模型 RL"混淆。MPPI 用模型(要前向 rollout),每个控制周期**在线**重新优化,不学习、不训练;RL(免模型)不用模型,**离线**训练出一个策略网络,在线只做前向推理。
一句话:MPPI 是"在线规划器",RL 是"离线学到的策略"。它们可以互补——RL 策略给 MPPI 提供好的提议分布(先验),MPPI 给 RL 提供安全的在线纠偏。
理解了这个版图,你选型时就会先问"我的问题该用哪个范式",而非默认"MPPI 一定对"——这比在六个变体里纠结更重要。
变体的组合与冲突:实操指南¶
§3.6 反复说"变体大多可叠加",但工程上"怎么叠、何时冲突"需要更具体的指导。把组合关系分成三类:
第一类:几乎自由叠加(改不同侧面、互不干扰)。 Smooth(时间结构)+ Log(尾部)是典型——一个管"序列内部平不平滑",一个管"采样尾巴厚不厚",作用在采样分布的不同维度上,直接相乘即可(在导数空间用 NLN 采样)。
U-MPPI 的不确定性传播(改 rollout 刻画)也几乎和任何改采样分布的变体正交——你可以在 Smooth + Log 的采样基础上,照样对每条 rollout 套 UT 算风险。
这一类组合的判据是:它们改的侧面在那张五侧面表里位于不同行,且都在"采样分布"或"rollout"各自的层面。
第二类:可叠加但需安排次序(都动"名义序列怎么来")。 SVG-MPPI(寻峰)和 RMPPI(反馈入采样)都要决定"采样围绕哪条名义序列"。
SVG-MPPI 先用 SVGD 侦察出目标 mode 的均值,RMPPI 再以这个均值为名义序列、在其周围做含反馈的 rollout——**先寻峰、后反馈采样**是合理次序。
反过来(先 RMPPI 定均值再寻峰)逻辑上别扭,因为寻峰本就是为了挑名义序列。这类组合能用,但你得想清楚数据流的先后,不能简单"两个开关一起打开"。
第三类:存在内在张力(一个变体的目标削弱另一个)。 §3.3 思维陷阱已点出一例:Log 的重尾会甩出偶发大动作,而这些大动作本身是高频跳变——与 Smooth 的平滑目标**对着干**。
叠加它们不会崩,但要调平衡:重尾比例 \(\pi\) 不能太低(否则大动作太频繁、抵消平滑),导数空间协方差也要相应收一点。
另一例是探索与安全的张力:Log/重尾鼓励大胆探索,而 U-MPPI 的风险代价抑制冒险,二者叠加时风险权重要调得不至于把重尾的探索价值完全压死。这类组合需要你理解两个变体的目标是否在某个量上**反向拉扯**,并通过调参找平衡点。
一条总的实操心法:先按需求优先级单独加变体、each 验证有效,再两两组合、观察指标是否如预期叠加(§3.6 越野车案例和累积项目都建议这么做)。
不要一上来就把五个开关全打开——那样一旦出问题,你分不清是哪个变体、还是哪对组合的张力导致的。逐个加、逐对验证,既符合工程严谨,也正好把那张五侧面表的"正交性"一条条落到实处。
本章前沿与开放问题¶
六大变体勾勒了 MPPI 鲁棒化、平滑化、多模态、不确定性的主线,但这条线仍在快速延伸。把值得关注的前沿按"它们各自再往哪个方向推"分组来看:
安全方向(向硬约束靠拢)。
- Shield-MPPI(Gandhi 等, 2023):在 rollout 中嵌入**控制屏障函数(CBF)安全滤波**。前面 §3.1/§3.5 反复提到 MPPI 的保证是软的、概率的;Shield-MPPI 试图在采样过程中用 CBF 这种有硬安全语义的工具做一层滤波,把明显违反安全的样本挡掉,向"硬安全"靠拢。这类工作(也包括带安全屏蔽的机会约束信息论 MPC)代表了"采样灵活性 + 形式化安全"结合的努力。
- DBaS-Log-MPPI:把**离散屏障状态**整合进 Log-MPPI(§3.3 已提),在提升可行性的同时叠加安全语义,是"可行性 + 安全"的组合范例。这条线和 Shield-MPPI 同向,都是把某种带硬语义的安全工具焊进采样式 MPC。
- DRA-MPPI(Trevisan 等, IROS 2025):动态风险感知 MPPI,针对"在人群/动态障碍中导航"这一难题。它利用 MPPI 的无梯度特性,用**蒙特卡洛近似**实时估计**数百条采样轨迹**与多个动态障碍之间的**联合碰撞概率(CP)**——而且能处理任意形状、甚至非高斯的预测。据此既可拒绝 CP 超阈值的样本、也可把 CP 作为加权目标并入代价,从而缓解"机器人冻结问题"(freezing robot:障碍预测不确定性太大时机器人不敢动)。它和 §3.5 的 C²U-MPPI 是近亲(都做碰撞概率约束),但 DRA-MPPI 专攻"多个动态障碍 + 非高斯预测 + 实时"这一更难的设定,是 2025 年把 MPPI 推向拥挤动态环境安全导航的代表性工作。
平滑方向(更强的频谱/可行性控制)。
- π-MPPI(Andrejev 等, 2025):把控制序列**投影到一个平滑可行集**上(解一个 QP),对控制及其导数强加硬边界,专为固定翼飞行器这类对轨迹平滑性、可行性要求苛刻的系统设计。它和 §3.2 的 Smooth-MPPI 思路相邻但手段不同——一个在采样空间做低通,一个用投影强制可行。
- Low-Pass MPPI(Kicki, 2025):对采样噪声直接施加显式低通滤波器、塑造扰动频谱。相比 input-lifting 的"固定低通",它能更自由地设计频谱形状——是把"平滑"从一个固定技巧推向"任意频谱整形"的一步。
多模态方向(覆盖 vs 寻峰的不同取舍)。
- 轨迹聚类(Patrick 等, 2024):与 SVG-MPPI 互补的另一条多模态路线——把采样轨迹**聚类**,阻止把"穿过不同 mode 之间不安全谷底"的路径一起加权平均,从而降低碰撞风险。它和 §3.4 的寻峰殊途同归,都为避免"跨峰平均",但保留了多个候选而非锁定一个。
- SCP-MPPI(Miura 等, 2024):用稀疏点 + 样条参数化控制,再用 SVGD 做多模优化——把 §3.2 的平滑(样条天然光滑)与 §3.4 的多模(SVGD)合在一处,是两个侧面的联合改进。
- BiC-MPPI / DRPA-MPPI(2024–2025):两条针对"避免坏的加权平均、增强可达性"的新路线。BiC-MPPI(双向 rollout 聚类)用目标导向的双向 rollout + 聚类来改善轨迹优化的可达性;DRPA-MPPI(动态排斥势增强)在非结构化环境里给 rollout 加一个动态排斥势来做反应式导航。它们和轨迹聚类同属"不要盲目平均所有样本"的思路,反映出多模态/可行性方向上仍在快速涌现新变体——本章讲的 SVG-MPPI 是其中理论最清晰的一支,但远非终点。
采样效率方向(更聪明的提议)。
- Biased-MPPI:把一个由 iLQR/PID 等算出的"还不错"的控制序列作为采样**偏置均值**,让多数 rollout 落在更可能成功的区域(第 2 章 §2.4 已提)。它直接对应那条样本效率主线——改提议的位置以提效率。
- 自适应重要性采样(AIS,Asmar 等, 2022):把 MPPI 的推导推广到"控制序列上的单一联合分布",从而能把 AIS 算法接进重要性采样步骤,在保留 MPPI 处理任意动力学/代价的前提下,让提议分布在线自适应。它在大动作空间、多车/高自由度场景下相对逐时刻高斯 rollout 的 MPPI 表现出更好的扩展性。
- Biased-MPPI(Trevisan & Alonso-Mora, 2024):把 §2.4 提到的"注入先验均值"做成了一个更一般的框架——给出一个允许**任意采样分布**的 MPPI 推导,可同时融合**多个** ancillary 控制器(经典的或学习的)作为采样先验。它解决的痛点很具体:当环境突变、所有"围绕旧解"的样本都碰撞时,vanilla MPPI 会算出一个同样碰撞的新解;Biased-MPPI 靠 ancillary 控制器的先验快速收敛到避障机动,缓解局部极小与"机器人冻结"。这把"改提议的位置"从 warm-start 的单一来源,扩展到"多个信息源融合"。
- LP-MPPI / 有色噪声(Kicki 等, 2025;及更早的 colored-noise MPPI):都在**频域**改采样。有色噪声 MPPI(受 iCEM 启发)用带频谱的噪声替代白噪声,但它按频率倒数衰减各分量、会在通带内也偏置频率,对需要重复性动作(腿足、搅拌、切剁)的任务不利;LP-MPPI 改用一个**低通滤波器**只切掉有害高频,而**不偏置通带内的频率**,从而在允许的频率范围内更高效地探索。这条线和 §3.2 的 input-lifting 同属"塑造控制频谱",但 input-lifting 是"固定低通"(积分),LP-MPPI/有色噪声给了更灵活的频谱控制。
核心开放问题:硬约束如何以数学严格的方式嵌入 MPPI? 贯穿本章你会反复看到一句话:"MPPI 的约束是软的"。
RMPPI 给的是自由能增长上界,C²U-MPPI 给的是碰撞概率约束,Shield-MPPI 用 CBF 做滤波——它们都在逼近"安全",但**没有一个**能像传统鲁棒 MPC 那样,在有界扰动下给出"硬约束必然满足"的严格保证。
MPPI 处理硬约束目前仍依赖罚值、barrier、投影、滤波这些**近似**手段。如何在保留 MPPI"处理非光滑代价与黑箱动力学"这一核心优势的同时,获得硬约束的严格满足,是这个领域尚未解决的根本问题——也是采样式 MPC 与传统优化式 MPC 之间最后一道没有完全打通的鸿沟。
通往第 4 章的伏笔。 注意上面"采样效率方向"已经露出一个转向:AIS 不再是"改提议的某一个侧面",而是把提议分布本身做成**可在线自适应、更一般**的形式。
这正是第 4 章的主题——CEM 迭代精炼分布、CoVO-MPC 给出**最优协方差设计**并带来收敛保证、Tsallis 用更一般的指数族。
本章是"一个侧面一处改进",第 4 章则把这些改进**统一**进一个"如何最优地构造提议分布"的框架,并第一次为采样式 MPC 的**收敛性**给出理论。本章末尾那张五侧面表,是你进入第 4 章前最好的地图。
六大变体的共同局限¶
最后诚实地列一列:尽管六个变体各自补上了 vanilla MPPI 的一个短板,它们仍**共享一些没解决的根本局限**——这些局限不属于某一个变体,而是整个采样式 MPC 范式的边界,也正是第 4 章及更后续章节要继续攻的。
其一,没有硬约束的严格保证(本章反复出现)。六个变体都在"逼近安全",但没有一个能给出传统鲁棒 MPC 那种"有界扰动下硬约束必然满足"的证明——这是范式级的开放问题。其二,调参负担。
每个变体都引入新旋钮(\(\Sigma_\delta\)、\(\pi\)、guide particle 数、sigma 点参数……),叠加后旋钮更多、相互耦合,调参成本随之上升;本章给的调参提示都是经验性的,缺乏自动整定的理论。其三,仍是局部方法。
即便加了重尾、寻峰,MPPI 本质仍是围绕当前解的局部优化,时域之外、全局尺度的引导仍需外部提供(GP-MPPI 的子目标、上层规划)——单靠本章变体走不出"局部"。其四,理论保证有限。
只有 RMPPI 给了自由能增长上界,其余变体大多停留在"经验上有效",缺乏收敛性、最优性的理论刻画(这正是第 4 章 CoVO-MPC 要补的第一块收敛性理论)。其五,协方差仍多为手工设定。
除了 SVG-MPPI/U-MPPI 在特定意义下估计协方差,大多数变体的采样协方差 \(\Sigma\) 仍靠手调,没有"最优协方差"的原则(第 4 章的核心议题之一)。
把这五条共同局限记住,你就明白本章在全书的**定位与边界**:它把 vanilla MPPI 在五个侧面上各推进了一步,但"硬约束、自动调参、全局性、收敛理论、最优协方差"这些更深的问题,要到后续章节(统一框架、学习采样、安全规划)才逐步触及。承认局限不是否定本章的价值——恰恰相反,清楚边界在哪,才知道下一步该往哪走。
还有一点值得点破:这五条局限**并非各自孤立**,它们背后有一个共同的根——MPPI 是一个**无导数、基于采样、单步闭式**的方法。正是"无导数"让它能处理黑箱和非光滑(优点),但也让它拿不到硬约束所需的梯度信息(局限一);正是"基于采样"让它天然并行(优点),但采样的方差又带来调参负担和理论分析的困难(局限二、四);正是"单步闭式"让它快(优点),但放弃了迭代精炼,于是只能局部、协方差只能预设(局限三、五)。
换句话说,MPPI 的优点和局限是**同一组设计选择的一体两面**——你不可能只要优点不要局限。这也预告了后续章节的思路:要突破这些局限,往往要在某个维度上"放弃一点 MPPI 的纯粹性"——引入迭代(CEM)、引入梯度(混合方法)、引入学习(神经采样)。理解了"优点与局限同根",你就不会期待某个变体能"既保留 MPPI 全部优点、又消除全部局限"——那在逻辑上就不可能。每个后续方法都是在这组权衡里挪动位置,而非凭空消除权衡。
本章常见误解汇总¶
| 误解 | 正确理解 |
|---|---|
| 六大变体是六种全新的、互相竞争的算法 | 它们都在 vanilla MPPI 框架内,各改提议分布/rollout 的**一个侧面**;大多可叠加使用 |
| 加大协方差 \(\Sigma\) 就能让 MPPI 更鲁棒 | 模型失配脆弱是提议**中心**在闭环下失效(位置问题),加大 \(\Sigma\) 解决不了,还会崩 ESS(§3.1) |
| RMPPI 的自由能上界 = 硬约束安全保证 | 它是"离最优的偏离被控制在范围内"的能量意义保证,**非**硬约束必然满足;MPPI 约束本质仍软(§3.1) |
| Smooth-MPPI 等价于给 MPPI 输出加低通滤波 | 二者平滑的**位置**不同:Smooth 在采样空间(优化之内,保最优性),事后滤波在优化之后(破坏最优性)(§3.2) |
| 想要大动作,把高斯 \(\sigma\) 调大就行 | 调大 \(\sigma\) 让所有样本都散、破坏近处精细探索;重尾是"尖峰+厚尾",保留精细又获偶发远探(§3.3) |
| SVG-MPPI 同时覆盖所有 mode | 它是 mode-seeking:用 SVGD 侦察、锁定**一个**目标 mode,只覆盖该 mode,以保住闭式快速收敛(§3.4) |
| 多峰问题靠加大 \(K\)、撒更多样本能解决 | 多峰是提议的**表示**问题,单高斯撒再多样本其加权均值仍可能落在峰间撞墙;需换表示(§3.4) |
| UT 的 sigma 点就是"少撒几个随机样本" | sigma 点是**确定性**摆在协方差主轴上的求积点,精度来自摆位+权重的设计,与随机抽样根本不同(§3.5) |
| 用了变体就一定比 vanilla 好 | 每个变体都带额外复杂度与调参;模型准、环境不杂乱、路径唯一时,vanilla + warm-start 就够(§3.6) |
| 新变体层出不穷,本章六大变体已过时 | 新变体(Biased/LP/DRA/BiC-MPPI 等)大多仍在"改提议分布/rollout 的某个侧面"这一框架内,是六大变体所属侧面的延伸或组合;掌握"五侧面"框架就能理解并归类新变体,而非被名字淹没(§前沿、§统一视角) |
跨章综合应用:给一辆越野车选型¶
把本章六个变体放回一个具体系统,串起第 1–3 章,是检验你是否真正掌握"选型"的最好方式。设想你要给一辆**高速越野车**写规控(正是 AutoRally、SMPPI 那类任务),需求逐条摊开,看每一条把你引向哪个变体:
起点(第 2 章):先搭一个 vanilla MPPI——GPU 并行上千条 rollout(§2.2)、warm-start 衔接周期(§2.1)、控制约束钳到转向/油门物理范围(§2.1)、代价用赛道中心线 + 边界碰撞罚 + 速度奖励。这是地基,没有它谈不上变体。
需求一:转向/油门指令不能高频抖动(执行器是真实舵机和电机,抖动伤硬件、还按 SMPPI 实验会拖慢圈速甚至失控)。
→ 上 Smooth-MPPI(§3.2):在转向/油门的**导数空间**采样再积分,治住 t-轴抖动;动作变差代价写进状态代价。
需求二:地面摩擦多变(柏油、碎石、湿滑),模型必然失配,开环规划一遇打滑就冲出赛道。→ 上 RMPPI(§3.1):加一个 iLQG 反馈把车拉回名义轨迹,且把反馈纳入 rollout,让规划"知道"有纠偏能力——这正是 RMPPI 在 AutoRally 上同时压住"MPPI 不鲁棒"和"Tube-MPPI 过保守"的场景。
需求三:赛道上有动态障碍(其他车),绕障有左右两条等优路径,怕 MPPI 取中间撞上去。→ 上 SVG-MPPI(§3.4):用轻量 SVGD 侦察出"这一刻该走左还是右"的目标 mode,锁定它做 mode-seeking,避免跨峰平均。
需求四:高速下状态估计有噪声,擦着障碍过太危险,要控制碰撞概率。→ 上 U-MPPI / C²U-MPPI(§3.5):UT 传播每条 rollout 的状态协方差,对"擦边且不确定性大"的轨迹按碰撞概率加罚。
关键判断:这些能同时用吗? 大体能,因为它们改的是提议分布/rollout 的**不同侧面**(§3.6 的正交性):Smooth 改时间结构、RMPPI 改闭环有效性、U-MPPI 改不确定性刻画——可以叠加。
但 SVG-MPPI 的寻峰与 RMPPI 的增广状态都动了"名义序列怎么来",叠加时要想清楚谁先谁后(先寻峰定 mode、再在该 mode 内跑 RMPPI 的反馈采样,是一种合理的串接)。
而需求的**优先级**也要排:摩擦失配(需求二)通常最致命,应最先解决;抖动(需求一)次之;多模与风险按赛道是否真有动态障碍、状态噪声是否真大来决定要不要上——别为了用而用(§3.6 的告诫)。
回到第 1 章:这一整套之所以成立,根在第 1 章那个零方差理想——最优提议就是目标分布本身。越野车的目标分布在高速、多摩擦、有动态障碍下,恰恰是**重尾**(偶发大动作救场)、多峰(左右绕)、非各向同性(协方差贴合赛道)、闭环(带反馈才是真实演化)的——单个开环各向同性高斯哪个侧面都不沾。
六个变体合起来,就是把这个朴素高斯往真实目标分布的各个侧面上拽。理解到这一层,"选型"就不再是查表,而是**读懂你的目标分布长什么样**。
这套"读目标分布"的方法对别的平台同样管用,换个平台只是各侧面的权重变了。四旋翼/固定翼无人机:执行器(电机/舵面)对抖动敏感,平滑(§3.2)权重高;固定翼还对轨迹可行性要求苛刻,可能需要前沿的 π-MPPI;高速下也有多模避障(§3.4)。
腿足机器人:动力学含接触、高度非线性且常是学到的黑箱,这恰是 MPPI 的主场(第 2 章杀手级场景),而接触的不确定性、落足点的风险让不确定性感知(§3.5)变得重要;地形快速变化时抖动也可能致发散(§3.2)。
机械臂:通常环境结构化、路径相对唯一,多模(§3.4)不突出,但精密操作对平滑和安全(避免碰撞工件)要求高。
可以看到,同一套"五侧面"判断框架,换平台只是重新分配各侧面的权重——越野车重鲁棒+平滑,无人机重平滑+可行,腿足重黑箱+不确定性,机械臂重平滑+安全。
这正是把六个变体统一成"提议分布的侧面"之后的迁移价值:你不必为每个新平台重学一套算法,而是用同一框架重新问"这个平台让目标分布在哪个侧面上最不像高斯"。
把上面这套推演浓缩成一份可操作的选型 checklist,下次面对新平台直接照着走:第一步,确认范式——你的代价光滑、动力学可微、且硬约束至关重要吗?是则先考虑梯度 MPC,否则 MPPI 系列是主力(§横向定位)。
第二步,搭地基——先实现 vanilla MPPI(warm-start + 约束钳位 + ESS 监控),跑起来看哪些缺陷真正出现,别凭空想象。
第三步,逐缺陷排查:模型失配/冲出边界?→ §3.1;控制抖动/伤执行器?→ §3.2;杂乱环境卡死/rollout 全碰撞?→ §3.3;多条等优路径/撞向障碍中间?→ §3.4;要风险感知/控制碰撞概率?→ §3.5。
第四步,按优先级加变体——挑最致命的缺陷对应的变体先加,验证有效后再考虑下一个(§3.6 的"逐个加、逐对验证")。
第五步,核算预算——每加一个变体测一次单周期延迟,超预算就用减 \(K\) 换或重新权衡(§计算开销)。第六步,别过度工程——若 vanilla 加基础增强已达标,就停手,不为用变体而用变体。
这份 checklist 把本章所有零散的判断串成了一条可执行的流程,它对越野车管用,对无人机、腿足、机械臂同样管用——变的只是第三步里哪些缺陷会亮灯。
跨章综合思考题:接上面的越野车。(a) 写出叠加了 Smooth + RMPPI 两个变体后,单条 rollout 的控制如何生成、用什么动力学前向、权重用什么代价(提示:把 §3.2 的导数空间采样与 §3.1 的反馈入采样、名义代价权重组合起来,注意控制此时已是"导数的积分")。(b) 这套系统里,第 2 章的 ESS 监控仍然有用吗?它现在度量的"采样健康"和 RMPPI 自由能上界里的"采样误差"是不是一回事?(c) 若把动力学换成一个学到的神经网络模型(第 7 章方向),上述哪些变体仍直接适用、哪些需要改动?为什么 RMPPI 的下层 iLQG 可能出问题,而 vanilla MPPI 的采样部分不受影响?
本章小结¶
本章沿"问题驱动"把 vanilla MPPI 的四大缺陷逐一摊开,用六个变体去修,而它们背后是同一条主线(也是第 2 章那条主线的延续):vanilla MPPI 的高斯提议在某个侧面上不够用时,就把提议或 rollout 往目标分布的那个侧面改一步。
§3.1 的 Tube/RMPPI 让提议在**闭环**下有效(位置 + 反馈),RMPPI 还带来家族第一个理论保证——自由能增长上界;§3.2 的 Smooth-MPPI 在控制导数空间采样、改提议的**时间结构**,从源头消抖且不破坏最优性;§3.3 的 Log-MPPI 用 NLN 重尾改提议的**尾部**,提高杂乱环境的可行样本比例;§3.4 的 SVG-MPPI 用 Stein 变分**寻峰**、改提议的**模态**,避开多峰平均的撞墙;§3.5 的 U-MPPI 用 Unscented Transform 改 rollout 的刻画(传播均值+协方差),让 MPPI 有了风险意识与机会约束。§3.6 把六者收成一棵选型树,并强调它们大多可叠加、且 vanilla 够用时不必硬上变体。
回到章首的两个"如果跳过"场景:现在你知道,越野车冲出边界是模型失配脆弱(§3.1 的 Tube/RMPPI),机器人"卡住乱抖"是可行性(§3.3)与抖动(§3.2)两个缺陷叠加——它们都是 MPPI 算法层面的固有缺陷,对应着明确的变体解法,而非实现 bug。
掌握"哪个缺陷 → 哪个变体 → 改提议的哪个侧面"这条线,你就把六个看似零散的算法装进了一个统一的判断框架。
把本章放回全书也值得一提。第 1 章给了理论根(自由能–KL、零方差最优提议),第 2 章把它做成能部署、能并行的 vanilla MPPI 并埋下样本效率主线,本章则沿这条主线把 vanilla MPPI 在五个侧面上各自增强——这三章合起来,是"采样式 MPC"从理论到工程、再到变体的完整一跳。
但本章的方法论仍是"一个侧面一处改进"的**局部增强**:每个变体盯住一个短板,不动其余。下一章会换一种更整体的视角——不再逐个打磨提议分布的某个侧面,而是问"如何从根本上、最优地构造整个提议分布",并第一次为采样式 MPC 的收敛性给出理论保证。
本章末尾那张"五侧面表"是这一跳的最佳跳板:当你看到第 4 章把这些侧面统一进一个框架时,会发现本章的六个变体其实是同一个母问题的不同切面。带着这个认识往下读,采样式 MPC 的全貌就会逐渐清晰起来。
术语速查表¶
| 术语 | 一句话定义 |
|---|---|
| Tube(管道) | 以名义轨迹为中心、由反馈控制器约束真实状态留在其内的邻域 |
| ancillary controller(辅助控制器) | Tube-MPPI 下层负责跟踪名义轨迹、抗扰的控制器(用 iLQG) |
| augmented state(增广状态) | RMPPI 同时表示名义动力学与真实动力学的状态空间 |
| importance-sampling trajectory | MPPI 采样所围绕的那条控制序列;扰动使其失效是鲁棒性的核心难点 |
| 自由能增长上界 | RMPPI 的理论保证;是任务约束满足度、跟踪性能、采样误差的函数 |
| input-lifting(输入提升) | 把控制提升为状态、改在控制导数空间采样的技巧(Smooth-MPPI) |
| NLN(Normal-Log-Normal) | 高斯 + 对称化对数正态的重尾混合采样分布(Log-MPPI) |
| SVGD(Stein 变分梯度下降) | 用一组粒子(吸引项 + 排斥项)逼近目标分布的确定性变分推断 |
| mode-seeking(寻峰) | 只锁定并覆盖一个目标 mode、不覆盖所有峰,以保住闭式快速收敛(SVG-MPPI) |
| RKL 散度 | 反向 KL 散度,SVG-MPPI 用改进 SVGD 最小化它来输运 guide particles |
| Unscented Transform(UT) | 用 \(2n{+}1\) 个确定性 sigma 点高效传播分布均值与协方差 |
| sigma 点 | UT 中沿协方差主轴确定性摆放的采样点(求积点,非随机样本) |
| chance constraint(机会约束) | 基于碰撞概率的约束(\(P(\text{collision})<\delta\)),C²U-MPPI 用它 |
| CBF(控制屏障函数) | 一种带硬安全语义的工具;Shield-MPPI 用它在 rollout 中做安全滤波 |
知识点总表¶
| 编号 | 知识点 | 核心要点 | 对应节 | 难度 |
|---|---|---|---|---|
| 1 | 四大缺陷框架 | 抖动 / 模型失配脆弱 / 可行性 / 单模态(+ 不确定性),各对应一个变体 | 知识导航 | ⭐⭐ |
| 2 | Tube-MPPI 双层架构 | nominal MPPI(规划)+ ancillary iLQG(跟踪、管道) | §3.1 | ⭐⭐⭐ |
| 3 | planner-tracker 冲突 | 名义/真实态发散 + 采样器无视反馈 → 有偏估计 | §3.1 | ⭐⭐⭐ |
| 4 | RMPPI 反馈入采样 | rollout 含 \(K_{\text{fb}}(x_k-\bar x)\)、用真实动力学、权重用名义代价 | §3.1 | ⭐⭐⭐ |
| 5 | 自由能增长上界 | = f(约束满足, 跟踪性能, 采样误差);家族首个保证(非硬约束) | §3.1 | ⭐⭐⭐⭐ |
| 6 | input-lifting | 控制导数空间采样再积分;= 扩状态,不破坏最优性 | §3.2 | ⭐⭐⭐ |
| 7 | 采样层 vs 事后平滑 | 平滑发生在优化之内才不破坏最优性 | §3.2 | ⭐⭐⭐ |
| 8 | NLN 重尾混合 | 高斯主体 + 对称对数正态尾;提偶发大动作概率 | §3.3 | ⭐⭐ |
| 9 | 可行性 vs 样本效率 | 杂乱环境的问题是"有没有可行 rollout",比效率更基础 | §3.3 | ⭐⭐ |
| 10 | SVGD 两项 | 吸引(向高概率)+ 排斥(保多样、感知多峰) | §3.4 | ⭐⭐⭐ |
| 11 | SVG-MPPI 寻峰四步 | SVGD 侦察 mode → 取最低代价粒子 → 拟合协方差 → mode-seeking MPPI | §3.4 | ⭐⭐⭐ |
| 12 | 多峰是表示问题 | 单高斯结构上单峰,调参无解,需换表示 | §3.4 | ⭐⭐⭐ |
| 13 | Unscented Transform | \(2n{+}1\) 确定性 sigma 点传播均值+协方差,逼近大样本蒙特卡洛 | §3.5 | ⭐⭐⭐ |
| 14 | 风险代价 / 机会约束 | 传协方差 → 估碰撞概率 → 风险敏感代价 / \(P(\text{collision})<\delta\) | §3.5 | ⭐⭐⭐ |
| 15 | 选型与叠加 | 按主要缺陷选;变体大多正交可叠加;vanilla 够用时不硬上 | §3.6 | ⭐⭐ |
本章综合练习¶
下面几道题跨越多个变体,检验你是否把"提议分布的五个侧面"这条主线真正用起来了(难度从易到难)。
- (选型推理,⭐⭐) 一台仓库 AGV 在密集货架间导航,激光雷达给出局部占据栅格作代价图,地面平整、速度不高、执行器普通,但货架间常有"左绕/右绕都通"的岔口。
请按本章决策树和五侧面表,判断它最需要哪个变体、最不需要哪个,并说明理由。(提示:地面平整、速度低意味着哪些缺陷不突出?)
-
(机制辨析,⭐⭐) 下面四种"让控制更平滑"的做法——(a) 事后 SGF 滤波、(b) input-lifting(Smooth-MPPI)、(c) 显式低通滤采样噪声(Low-Pass MPPI)、(d) 投影到平滑可行集(π-MPPI)——哪些保留 MPPI 的信息论最优性、哪些不保留?哪些能对控制**导数**强加硬边界?把它们按"平滑发生在采样管线的哪一步"排个序。
-
(组合设计,⭐⭐⭐) 你要同时解决"杂乱可行性"和"抖动"两个缺陷,决定叠加 Log-MPPI + Smooth-MPPI。(a) 写出叠加后单条 rollout 的噪声如何生成(提示:在导数空间用 NLN 采样)。
(b) 这两个变体在 §3.6 的组合分类里属第几类?存在什么张力?(c) 你会怎样调 \(\pi\) 和 \(\Sigma_\delta\) 来找平衡,并用什么指标验证两个目标都达成了?
- (陷阱诊断,⭐⭐⭐) 同事实现了"RMPPI",但你发现它在扰动下的表现和 Tube-MPPI 几乎一样。
请设计一个**最小实验**判断他是否犯了"反馈没进 rollout"的错误(提示:本章 §3.1 给了一个可直接改造的判别法——去掉某一项看结果是否变化)。如果确实如此,他的代码该改哪一行?
- (开放性,⭐⭐⭐⭐) 设想一个本章没有专门变体覆盖的组合需求:既要多模态(多条等优路径)、又要不确定性感知(控制碰撞概率)。
基于五侧面表,这对应哪两个侧面?你会如何把 SVG-MPPI 的寻峰与 U-MPPI 的 UT 传播拼起来?数据流上谁先谁后?可能在哪里出现张力或重复计算?(这是一道没有标准答案的设计题,重在推理过程。)
累积项目:本章新增模块¶
第 2 章的累积项目交付了一个完整的 vanilla MPPI 参考实现(warm-start + \(\rho\) 减法 + SGF + 约束钳位 + ESS 监控)。
本章的模块是把它升级为一个**可切换变体的 MPPI**——在同一个主循环上,用开关挂上本章三个改提议/rollout 的变体,亲手验证"每个变体只改一个侧面、且大多可叠加"。
先看这个"可切换"骨架长什么样。本章反复说"六变体各改提议分布/rollout 的一个侧面",落到代码上,就是同一个主循环里有几个**钩子**,不同变体只替换对应的钩子(这也正是 MPPI-Generic 用可插拔组件、pytorch_mppi 用相同 API 挂不同变体的设计思想):
def mppi_step(U, mode, rng): # 统一主循环, 钩子处分叉
V = sample(U, mode, rng) # 钩子1: 采样提议(Smooth/Log/SVG 改这里)
J = rollout_and_cost(V) # 钩子2+3: rollout(RMPPI/U 改) + 代价
w = np.exp(-(J - J.min())/lam); w /= w.sum() # 钩子4: 聚合(SVG 改为先分簇)
return U + (w[:,None,None]*(V - U[None])).sum(0)
def sample(U, mode, rng): # 仅此钩子不同即得三种变体
if mode == 'smooth': # 导数空间采样再积分(§3.2)
dU = sigma*rng.standard_normal((K,T,m)); return U[None] + np.cumsum(dU,1)*dt
if mode == 'log': # NLN 重尾混合(§3.3)
mask = rng.binomial(1,0.7,(K,T,m)); g = rng.normal(0,sigma,(K,T,m))
ln = rng.lognormal(0,1.0,(K,T,m))*rng.choice([-1,1],(K,T,m)); return U[None] + mask*g+(1-mask)*ln
return U[None] + sigma*rng.standard_normal((K,T,m)) # vanilla
在一个点质量到达任务上跑这三种 mode,输出:
三种变体共享**完全相同**的主循环,只有 sample() 钩子不同——Smooth 把控制总变差从 \(50.83\) 压到 \(17.88\)(治抖动),Log 的尾部更重(图上可见偶发大动作,TV 与 vanilla 相近因为本任务无需脱困)。
这印证了本章的核心观点:变体不是另起炉灶,而是在同一套 MPPI 骨架上替换某个钩子。下面把三个钩子的具体改法逐一展开为可插拔开关。
三个可插拔开关:
开关一:input-lifting(Smooth-MPPI,改时间结构)。 把采样从控制空间换到导数空间再积分:
if smooth: # 导数空间采样 → 积分回控制(天然平滑)
dU = sigma * rng.standard_normal((K, T, m))
V = U[None] + np.cumsum(dU, axis=1) * dt
else:
V = U[None] + sigma * rng.standard_normal((K, T, m))
开关二:NLN 重尾(Log-MPPI,改尾部)。 把高斯噪声换成 Normal-Log-Normal 混合(记得对称化):
if heavy_tail: # NLN: 高斯主体 + 对称对数正态重尾
mask = rng.binomial(1, pi, (K, T, m))
g = rng.normal(0, sigma, (K, T, m))
ln = rng.lognormal(0, sigma_ln, (K, T, m)) * rng.choice([-1, 1], (K, T, m))
eps = mask * g + (1 - mask) * ln
开关三:rollout 含反馈(RMPPI 思路,改闭环有效性)。 rollout 时给控制加一个跟踪反馈项、并用含扰动的动力学前向,权重仍用名义代价:
for t in range(T):
a = V[:, t] + (K_fb * (x_nom[t] - xx) if robust else 0.0) # 反馈纠偏入 rollout
xx = step(xx, a, disturb=True if robust else False) # 含扰动的真实动力学
J += running_cost(xx, V[:, t]) # 权重仍用名义代价
建议的验证实验:在一个带障碍、有持续扰动、且执行器对抖动敏感的 2D 导航任务上,逐个打开开关,记录三项指标——控制总变差(抖动,开关一应显著降低)、可行 rollout 比例(杂乱可行性,开关二应提升)、扰动下的约束违反次数(鲁棒性,开关三应降低)。再同时打开开关一 + 二,验证"平滑 + 重尾"可以正交叠加。
进阶开关四:SVGD 侦察目标 mode(SVG-MPPI 思路,改模态)。 在双峰避障场景里,先用一小组 guide particles 跑几步 SVGD(吸引 + 排斥两项,见 §3.4 的双峰演示代码),用最低代价粒子定出目标 mode 的均值,再让主 MPPI 围绕该均值采样——避免跨峰平均:
if multimodal: # 先侦察 mode, 再在 mode 内采样
guides = svgd_explore(guide_init, grad_logp, steps=5) # 少量粒子, 少数步
U_center = guides[np.argmin([seq_cost(g) for g in guides])] # 取最低代价粒子
else:
U_center = U # 单模: 沿用 warm-start 的中心
V = U_center[None] + sigma * rng.standard_normal((K, T, m))
进阶开关五:UT 传播不确定性(U-MPPI 思路,改 rollout 刻画)。 对每条 rollout 不只前向均值,而用 \(2n{+}1\) 个 sigma 点传播协方差,再据协方差给"擦边且不确定大"的轨迹加风险罚:
if uncertainty_aware: # 每条 rollout 内套一层 UT
mu_t, P_t = ut_propagate(mu_t, P_t, step, V[:, t]) # 传播均值+协方差
risk = collision_prob(mu_t, P_t, obstacles) # 协方差→碰撞概率
J += w_risk * risk
整合与对照:五个开关分别对应提议分布/rollout 的五个侧面(位置/反馈、时间结构、尾部、模态、不确定性),与本章"统一视角"那张表一一对齐。
建议的总实验是:在越野车那样的综合场景(§3.6 跨章案例)里,按需求优先级逐个打开开关,每加一个就记录对应指标的变化,亲手验证"每个变体只动一个侧面、且大多正交可叠加"。本章末尾的故障排查手册里若遇到对应症状,可回到这个项目对照定位。
延伸阅读¶
核心论文(按本章顺序):
- Williams 等, Robust Sampling Based MPC with Sparse Objective Information, RSS XIV, 2018 ——Tube-MPPI 原始论文。⭐⭐⭐
- Gandhi 等, Robust MPPI: Analysis and Performance Guarantees, RA-L 6(2):1423–1430, 2021(arXiv:2102.09027)——RMPPI 与自由能增长上界,本章 §3.1 的主要依据。⭐⭐⭐⭐
- Kim 等, Smooth MPPI Control without Smoothing, RA-L, 2022 ——Smooth-MPPI / input-lifting。⭐⭐⭐
- Mohamed 等, Log-MPPI Control Strategy, RA-L, 2022 ——Log-MPPI / NLN 采样;及其后续 GP-MPPI(IROS 2023)。⭐⭐
- Honda 等, Stein Variational Guided MPPI, ICRA, 2024(arXiv:2309.11040)——SVG-MPPI / 寻峰,源码
kohonda/proj-svg_mppi。⭐⭐⭐ - Mohamed 等, Towards Efficient MPPI Trajectory Generation with Unscented Guidance: U-MPPI, IEEE T-RO, 2025 ——U-MPPI / UT 传播。⭐⭐⭐
前沿与综述:Biased-MPPI(Trevisan & Alonso-Mora, 2024,多 ancillary 控制器融合采样)、DRA-MPPI(Trevisan 等, IROS 2025,动态风险感知 + MC 联合碰撞概率)、Shield-MPPI(CBF 安全滤波)、π-MPPI(Andrejev 等, 2025,投影到平滑可行集,固定翼)、LP-MPPI(Kicki 等, 2025,低通采样、不偏置通带频率)、轨迹聚类(Patrick 等, 2024)、SCP-MPPI(Miura 等, 2024,样条 + SVGD)、自适应重要性采样 MPPI(Asmar 等, 2022);工程实现层面的 MPPI-Generic 论文(Vlahov 等, arXiv:2409.07563, 2024,含 Tube/RMPPI 的 GPU 参考实现);MPPI 概率推断视角的统一综述(如 arXiv:2511.08019)可作为通往第 4 章的桥梁。⭐⭐⭐⭐
相关方法(多模态/变分的另一条线):Lambert 等, Stein Variational Model Predictive Control, CoRL 2020 ——SV-MPC,把 MPC 当贝叶斯推断、用 SVGD 逼近整个后验(与 SVG-MPPI 的寻峰取舍对照阅读)。
⭐⭐⭐;以及 DuSt-MPC、Q-SVMPC 等后续;SOPPI(Aldrich & Jenkins, 2025)对 SVG-MPPI 单模特性的实验分析。
背景基础:Liu & Wang, Stein Variational Gradient Descent, NeurIPS 2016 ——SVGD 原始论文(吸引 + 排斥两项的来源);Julier & Uhlmann 关于 Unscented Transform 的经典工作 ——UT/UKF 的源头(sigma 点与权重设计)。⭐⭐⭐
开源实现对照(落地时按语言/平台/已实现变体选库):
- MPPI-Generic(Vlahov 等, arXiv:2409.07563, 2024;
ACDSLab/MPPI-Generic):C++/CUDA 模板库,官方实现了 vanilla MPPI、Tube-MPPI、RMPPI 三者——这是本章 §3.1 两个鲁棒变体最权威的参考实现。它把系统拆成六类可插拔组件(Dynamics / Cost / Sampling Distribution / Feedback Controller / Controller / Plant),写自定义 Dynamics/Cost 无需改 MPPI 核心代码。依赖 Eigen + CUDA + yaml-cpp,是已知第一个"GPU 加速 + 多内置模型 + 可替换采样分布与控制器 + 实时"的 MPPI 库。同组的 Low-Frequency Sampling(RA-L 2024)也基于它。 - pytorch_mppi(
UM-ARM-Lab/pytorch_mppi):PyTorch 实现,从 0.8.0 起内置 SMPPI 与自家的 KMPPI(核插值平滑,§3.2)——是本章 §3.2 平滑变体的便捷参考。KMPPI 的 API 几乎与基础 MPPI 相同,额外传入核(如RBFKernel)与控制支撑点数num_support_pts(≤ 时域)。适合用神经网络近似动力学的快速原型(有tests/pendulum_approximate.py示例)。 - log-MPPI_ros(
IhabMohamed/log-MPPI_ros):ROS + PyCUDA 实现的 vanilla MPPI 与 Log-MPPI(§3.3),把 2D 占据栅格作局部代价图并入,验证过静态/动态杂乱环境的实车导航。 - proj-svg_mppi(
kohonda/proj-svg_mppi):SVG-MPPI(§3.4)的 ROS 实现,Docker 一键复现,ICRA 2024 配套。
选库的实用判断:要鲁棒变体(Tube/RMPPI)且能用 CUDA → MPPI-Generic;要平滑变体且偏好 PyTorch/快速原型 → pytorch_mppi;要 Log-MPPI 做 ROS 导航 → log-MPPI_ros;要 SVG-MPPI → proj-svg_mppi。注意没有任何单一库实现了全部六个变体——这也侧面印证本章"变体各改一个侧面、按需选用"的观点。
本章与后续章节的关系¶
| 后续章节 | 关系 | 本章铺垫的知识点 |
|---|---|---|
| 第 4 章 CEM 家族与统一视角 | 把 MPPI 及本章变体统一进 CEM/Stein/Tsallis 的概率推断框架;CoVO-MPC 给收敛保证与最优协方差设计 | "改提议分布的不同侧面"这一统一视角(§3.6)、SVGD(§3.4)、协方差自适应 |
| 第 5–6 章 扩散启发 / 学习采样 | 用学到的分布(扩散模型等)直接拟合目标分布 \(\mathbb{P}^\star\),是"改提议"的终极形态 | 提议分布逼近 \(\mathbb{P}^\star\) 的主线、多模态(§3.4) |
| 第 7 章 学习世界模型 TD-MPC | 学到的值函数当终端代价、学到的动力学当 rollout 模型 | rollout 的刻画(§3.5)、终端代价(第 2 章) |
| 第 8–9 章 腿足 / 导航自驾无人机 | 这些变体在真实平台的落地:鲁棒(§3.1)、平滑(§3.2)、杂乱避障(§3.3/§3.4)、风险(§3.5) | 全部六个变体的选型(§3.6) |
🔧 故障排查手册¶
| 症状 | 可能原因 | 排查步骤 | 相关节 |
|---|---|---|---|
| 仿真好、上真机就冲出边界/发散 | 模型失配脆弱;提议中心在闭环下失效 | 检查是否有跟踪反馈层;若有,反馈是否进了 rollout(否则退化成 Tube);查名义/真实态是否发散 | §3.1 |
| 控制高频抖动、电机嗡鸣 | 在控制空间撒白噪声的固有产物 | 改用 input-lifting(导数空间采样);查"积分"是否带 \(\cdot dt\)、是否累积;必要时加控制变化率惩罚 | §3.2 |
| 杂乱环境里 MPPI 输出近乎随机、卡住 | 几乎所有 rollout 碰撞、权重全趋零(可行性) | 查可行 rollout 比例与 ESS;换 NLN 重尾采样;极端时配全局/子目标引导 | §3.3 |
| 避障时径直撞向障碍中心 | 两条等优路径被加权平均到峰间(单模态) | 画采样轨迹看是否分两簇;若是,绝不能直接平均;用寻峰(SVG-MPPI)或聚类 | §3.4 |
| "擦边飞过"高风险轨迹被当成好解 | 未传播不确定性、看不见碰撞概率 | 用 UT 传协方差、加风险代价;查 sigma 点是否用矩阵平方根、权重是否归一 | §3.5 |
| 加了重尾后控制更抖 | 重尾的偶发大动作本身是高频跳变 | 平衡重尾比例 \(\pi\);与 Smooth(导数空间采样)叠加以兼顾可行与平滑 | §3.3/§3.2 |
| RMPPI 加了反馈却和 Tube 没区别 | 反馈只挂在执行端、没进 rollout(退化成 Tube) | 确认 rollout 控制是 \(u_{\text{nom}}+K_{\text{fb}}(x_k-\bar x)+\varepsilon_k\)、且用真实动力学前向;去掉反馈项若结果不变则反馈根本没进采样 | §3.1 |
| RMPPI 跟踪误差降了但仍超调/越界 | 下层反馈太弱(如纯比例),压不住瞬态 | "反馈入采样"与"反馈够不够强"是两件事;把下层 P 换成 PID 或 iLQG | §3.1 |
| Smooth-MPPI 反应迟钝、错失急动作 | 平滑力度过大(\(\Sigma_\delta\) 太小、\(\alpha\) 太大) | 调大 \(\Sigma_\delta\);按"先调 vanilla 协方差、再据此设 \(\Sigma_\delta\)"的次序重调;接受平滑↔敏捷的折中 | §3.2 |
| SVGD 粒子全坍缩到一个峰、丢掉其他 mode | 排斥项缺失或核带宽过小 | 确认更新含第二项 \(\nabla k\);用中位数启发设带宽;参考 §3.4 双峰演示 | §3.4 |
| U-MPPI 协方差非正定/碰撞概率离谱 | sigma 点用了元素开方而非矩阵平方根 | 改用 Cholesky 得矩阵平方根;对线性映射验证 UT 协方差 \(=APA^\top\) | §3.5 |
| U-MPPI 单周期超出控制周期 | 每条 rollout 套 \(2n{+}1\) 个 sigma 点,高维下成本激增 | 降 \(K\)/\(T\)、或用更轻量的风险近似;高维系统重新权衡是否值得 | §3.5 |
| 同时开多个变体后行为难以预测 | 组合中存在张力(如重尾↔平滑、探索↔风险) | 回到逐个加、逐对验证;查阅"变体组合与冲突"三类划分调平衡 | §3.6 |
API / 参数速查表¶
| 变体 | 关键参数/接口 | 说明 |
|---|---|---|
| Tube-MPPI | ancillary 控制器、tube 容差 | 下层 iLQG 跟踪;ancillary 短时域(1s)、高频率(100Hz) |
| RMPPI | \(K_{\text{fb}}\)(反馈增益)、名义传播安全逻辑 | rollout 含反馈、真实动力学;权重用名义代价 |
| Smooth-MPPI | \(\Sigma_\delta\)(导数空间协方差)、\(\alpha\)(变化率惩罚权重) | 越大越平滑、越保守;与敏捷性权衡 |
| Log-MPPI | \(\pi\)(高斯/重尾混合比)、\(\sigma_g\)、\(\sigma_{\ln}\) | \(\pi\) 大偏精细、\(\pi\) 小偏重尾探索;记得对称化对数正态 |
| SVG-MPPI | guide particle 数 \(M\)、SVGD 步长 \(\epsilon\)、RBF 核带宽 | 少量粒子做侦察;最终为单个 mode 的标准 MPPI 采样 |
| U-MPPI | sigma 点参数(\(\lambda/\kappa\))、风险代价权重、\(\delta\)(碰撞概率阈值) | \(2n{+}1\) 个 sigma 点;\(\delta\) 越小越保守 |
六大变体速查卡¶
一页纸浓缩六个变体,供随时查阅。每张卡按"机制 / 何时用 / 何时不用 / 成本 / 开源"组织:
Tube-MPPI(§3.1,⭐⭐⭐) 机制:名义 MPPI 规划 + 下层 iLQG 跟踪(管道)。何时用:有扰动/模型失配、想要实现相对简单的鲁棒方案。
何时不用:要理论保证(用 RMPPI)、或会遇到名义/真实态发散。成本:≈ vanilla + 一个 iLQG。开源:MPPI-Generic 的 controllers/TubeMPPI/。
RMPPI(§3.1,⭐⭐⭐) 机制:增广状态 + rollout 含反馈 + 权重用名义代价,给自由能增长上界。何时用:要鲁棒**且**要可量化的性能保证。
何时不用:把它当成硬约束安全保证(它不是)。成本:≈ 1.06×(实测)。开源:MPPI-Generic 的 controllers/RMPPI/。
Smooth-MPPI(§3.2,⭐⭐⭐) 机制:在控制导数空间采样再积分(input-lifting),治 t-轴抖动、不破坏最优性。
何时用:执行器娇贵、需平滑、环境快速变化致抖动甚至发散。何时不用:任务需要极致敏捷(平滑↔敏捷权衡)。成本:≈ 1.0×(几乎免费)。开源:pytorch_mppi 的 SMPPI/KMPPI。
Log-MPPI(§3.3,⭐⭐) 机制:NLN 重尾混合采样,提高杂乱环境可行 rollout 比例。何时用:高度杂乱、rollout 近乎全碰撞。
何时不用:可行区需精心引导才能到达(盲目重尾有天花板,配 GP-MPPI 引导)。成本:≈ 2.6×(NLN 采样开销)。开源:IhabMohamed/log-MPPI_ros(ROS + PyCUDA)。
SVG-MPPI(§3.4,⭐⭐⭐) 机制:改进 SVGD 侦察并锁定一个目标 mode,再做 mode-seeking MPPI。何时用:多条等优路径、怕取中间撞墙、要保闭式快速收敛。
何时不用:需同时保留多个候选方案(用轨迹聚类/SV-MPC)。成本:≈ vanilla + 少量 guide particles 的 SVGD。开源:kohonda/proj-svg_mppi(ICRA 2024,ROS + Docker)。
U-MPPI(§3.5,⭐⭐⭐) 机制:UT 用 \(2n{+}1\) 个 sigma 点传播均值+协方差,做风险敏感代价/机会约束。何时用:要风险感知、想控制碰撞概率、状态噪声大。
何时不用:状态维数高且控制周期吃紧(成本随 \(n\) 增长)。成本:≈ \(2n{+}1\) 倍传播(实测 \(n{=}4\) 约 4.6×)。开源:见 U-MPPI 论文(IEEE T-RO 2025)配套。
研究实践建议¶
按你的角色与目标,本章内容有不同的用法:
如果你是要落地某个变体的工程师。 先用决策树(§3.6)按主缺陷选一个变体,从对应的开源库起步(§延伸阅读的四库对照),不要从零造轮子——Tube/RMPPI 直接用 MPPI-Generic,平滑用 pytorch_mppi 的 SMPPI/KMPPI。
落地时把本章的"何时不用"判断和故障排查手册放在手边:多数线上问题(冲出边界、抖动、卡死、撞障碍)都能对应到手册里的某一行。
最关键的工程心法是 §3.6 的"逐个加、逐对验证"——别一次性堆叠多个变体,否则出问题时无法定位。先用累积项目的统一骨架搭好可切换框架,再按需挂变体。
如果你是要做研究、找选题的人。 本章末尾的"共同局限"那一节就是选题地图——硬约束严格保证、自动调参、全局性、收敛理论、最优协方差,每一条都是开放方向。
前沿小节里的近两年工作(DRA-MPPI、LP-MPPI、Biased-MPPI 等)显示这个领域仍在快速演进,且大多沿"改提议分布的某个侧面"或"组合多个侧面"展开——这正是寻找增量贡献的富矿。
一个务实建议:先复现 SVG-MPPI 或 U-MPPI(它们有开源代码和清晰的理论),在复现中往往能发现可改进的细节。
如果你只是想建立理解、为后续章节打基础。 抓住"五侧面"这一条主线就够了——不必记住六个变体的全部实现细节,但要能在看到一个新变体(无论本章内外)时,立刻判断它在改提议分布/rollout 的哪个侧面。带着这个框架进第 4 章,你会看到它如何被统一进一个更一般的概率推断视角。
给所有人的一条共识:不要为了用变体而用变体(§3.6 反复强调)。vanilla MPPI 加 warm-start、约束钳位、必要的平滑,已经能覆盖大量场景。变体是针对特定缺陷的"对症药",先确认你真的有那个缺陷,再上对应的变体。
版本信息速查¶
本章涉及的关键工作、年份与开源实现一览(便于查阅与引用):
| 变体 / 工具 | 提出年份 | 发表 | 开源实现 |
|---|---|---|---|
| Tube-MPPI | 2018 | RSS XIV | MPPI-Generic(C++/CUDA) |
| RMPPI | 2021 | RA-L 6(2) | MPPI-Generic(C++/CUDA) |
| Smooth-MPPI (SMPPI) | 2022 | RA-L | pytorch_mppi 0.8.0+ |
| Log-MPPI | 2022 | RA-L | IhabMohamed/log-MPPI_ros |
| GP-MPPI | 2023 | IROS | (log-MPPI 系列后续) |
| SVG-MPPI | 2024 | ICRA | kohonda/proj-svg_mppi |
| U-MPPI | 2025 | IEEE T-RO | (论文配套) |
| KMPPI | 2024 | (pytorch_mppi 论文) | pytorch_mppi 0.8.0+ |
| MPPI-Generic(库) | 2024 | arXiv:2409.07563 | ACDSLab/MPPI-Generic |
依赖环境提示:MPPI-Generic 需 CUDA + Eigen + yaml-cpp;pytorch_mppi 需 PyTorch;log-MPPI_ros 与 proj-svg_mppi 基于 ROS(后者提供 Docker)。本章正文的 CPU 演示仅需 NumPy,可在任意环境复现其定性结论(GPU 性能数字引自各论文)。
本章正文与全部章末组件已完成:六大变体(§3.1–§3.5)+ 选型决策树与统一视角(§3.6)+ 前沿与开放问题 + 误解汇总 + 跨章综合应用 + 本章小结 + 累积项目 + 延伸阅读 + 后续关系 + 故障排查 + API 速查 + 速查卡 + 研究实践建议 + 版本信息速查。本章紧扣"提议分布的五个侧面"这条主线,把六个看似零散的变体统一为对 vanilla MPPI 各个短板的针对性增强;带着这条主线与五侧面表,即可进入第 4 章的统一框架。