G1 微分博弈理论与 HJI 可达性¶
这一章是整条博弈规划线(G1–G4)的数学底座。 它回答一个看似简单、实则改写了整个问题结构的问题: 当两个(或多个)各有目标的智能体,在连续时间、连续状态下同时操控一个彼此耦合的动力系统时,"最优"意味着什么、又该如何求解?
单智能体最优控制里,"最优"等价于某个 \(\min_u J(x,u)\)——凸情形下存在唯一全局最优。 一旦进入博弈,"最优"这个词就塌缩成了"均衡":每个人在别人策略固定时无法单方面改善。 零和博弈的均衡由 Hamilton–Jacobi–Isaacs(HJI)偏微分方程刻画,它是单人 HJB 方程的博弈推广。
本章把 HJI 方程从动机一路讲到数值求解,并在过程中搭好两块后续要反复取用的积木: (1)可达性安全验证——贯穿 G4 的安全证书,也与不确定性规划里的 Tube MPC 同源; (2)LQ 博弈的耦合 Riccati 方程——这是 G2 中 iLQGames 每一步迭代所解的子问题。 理解了这两块,G2 之后的"实时化"工作才有根可依。
本章侧重理论理解:HJI 的维度诅咒决定了它很难直接上工程,真正跑在车上的是 G2 的局部近似方法。 所以本章代码很少,重心在推导链和物理意义。
前置自测¶
答不出 ≥ 2 题,建议先回到公共基础(最优控制 / 凸分析)补齐,再读本章。 这 5 题对应本章会反复用到的前置工具。
- 单人有限时域最优控制问题 \(\min_u\,[\,g(x(T))+\int_t^T L\,ds\,]\) 的值函数 \(V(x,t)\) 满足什么偏微分方程?终端条件是什么?(→ HJB 方程)
- 线性二次调节器(LQR)的代数/微分 Riccati 方程长什么样?给定 Riccati 解 \(P\),最优反馈增益 \(K\) 怎么算出来?(→ 最优控制)
- 对一个二元函数 \(H(u,v)\),\(\min_u\max_v H\) 与 \(\max_v\min_u H\) 一般相等吗?什么条件下相等?(→ 凸分析 / minimax 定理)
- 给定标量函数 \(V:\mathbb{R}^n\to\mathbb{R}\),集合 \(\{x:V(x)\le 0\}\) 叫什么?\(V\) 取"到某集合的带符号距离"时,这个集合是什么?(→ 微积分 / 水平集)
- Pontryagin 最大值原理(PMP)给出最优轨迹的什么必要条件?协态(costate)变量在其中扮演什么角色?(→ 最优控制)
本章目标¶
读完本章,你应当能够:
- 建模:把一个双智能体对抗问题写成零和微分博弈,写出它的 Isaacs 方程,并判断 Isaacs 条件是否成立(即这个博弈是否"有值")。
- 推导:从单人 HJB 出发推广出 HJI 方程;解释为什么 HJI 的解一般不是经典可微解、而必须是粘性解,并能用消失黏性法定出粘性解的上/下解条件。
- 关联可达性:把"安全验证"问题转化为一个可达性计算——分清后向可达集(BRS)、后向可达管(BRT)、reach–avoid 集三者的区别,写出各自的 HJI 方程,并解释哈密顿量里 \(\min/\max\) 的取法由玩家角色(控制 vs 干扰、存在 vs 任意)唯一决定。
- 理解数值方法:说清楚为什么要用水平集方法把"是否到达"这种布尔问题转成连续值函数的演化,以及网格离散带来的维度诅咒从何而来。
- 推导耦合 Riccati:写出 \(N\) 人 LQ 博弈的反馈 Nash 条件与耦合 Riccati 方程组,并理解它为什么"耦合"、为什么不保证有解——这是 G2 的直接前置。
- 掌握绕维度诅咒的三条路:状态解耦/STP、FaSTrack、神经近似(DeepReach),并能按"精确性 vs 可扩展性"权衡选型。
- 落地经典问题:解释 Homicidal Chauffeur 与 Air3D 这两个追逃博弈基准,以及为什么要在相对坐标下建模。
知识导航¶
本章的内容可以挂在一棵清晰的知识树上。 树根是一个问题——"对抗交互下'最优'是什么"; 树干是从理论方程到可算近似的下降链; 树枝是数值方法与经典问题。
博弈 = 最优控制 + "对手也在最优决策"
│
┌───────────────────┴───────────────────┐
零和(对抗) 一般和(混合动机)
追逃 / 安全验证 ← 本章重心 交互式驾驶 ← G2/G3 重心
│
§1.1 为什么需要博弈视角(三次认知跨越 + frozen robot)
│
§1.2 Isaacs 方程:零和博弈的最优性条件(min-max / 鞍点 / 信息结构)
│
§1.3 HJI PDE 与粘性解:值函数为何不可微,弱解如何唯一确定
│
§1.4 可达性:BRS(恰好到达)/ BRT(曾经到达)/ reach–avoid,角色决定 max/min
│
┌──────────┴──────────┐
§1.5 水平集数值方法 §1.6 LQ 博弈 + 耦合 Riccati ★(G2 地基)
(WENO5 + TVD-RK3) │
│ └─→ 预告 G2:iLQGames 每步就解这个
§1.7 维度诅咒与三条绕行路(解耦/STP · FaSTrack · DeepReach)
│
§1.8 追逃经典问题(Homicidal Chauffeur · Air3D)
一条贯穿全章的主线索是**"从理论最优到可算近似的步步退让"**。 HJI 给出全局最优和严格安全证书(§1.2–§1.4),但它在网格上算,维度一上去就爆炸(§1.5、§1.7)。 于是要么对状态结构动手术(解耦 / FaSTrack),要么放弃网格改用神经网络近似(DeepReach),要么——这正是 G2 要做的——把一般非线性博弈在每个时刻**局部近似**成一个 LQ 博弈,用耦合 Riccati 闭式求解(§1.6)。 本章把这条退让链讲透,G2 之后才接得上。
本章难度集中在 §1.2–§1.4 与 §1.6。 若时间紧张,§1.5(数值细节)与 §1.8(经典问题)可先速读、回头再精读。
前置知识桥接¶
本章建立在单人最优控制之上,这里把会用到的核心结论激活一下,读者不必翻回前置材料也能跟上。
HJB 方程(单人,最小化)。 考虑 \(\min_u\,[\,g(x(T))+\int_t^T L(x,u)\,ds\,]\),受 \(\dot x=f(x,u)\) 约束。 其值函数 \(V(x,t)=\min_u\,(\text{从 }(x,t)\text{ 出发的最优剩余代价})\) 满足
直觉是:最优剩余代价随时间往前推进的变化率,等于"当前这一步最优地花掉的代价 + 状态移动带来的未来代价变化"。 这里 \(\nabla_x V\) 就是 PMP 里的协态 \(\lambda\)——值函数对状态的梯度即影子价格。 本章的 HJI 方程,就是把这个 \(\min_u\) 换成博弈的 \(\min_u\max_v\)。
LQR 与 Riccati。 线性系统 \(\dot x=Ax+Bu\)、二次代价 \(\int(x^\top Qx+u^\top Ru)\,ds\) 的最优反馈是 \(u^*=-Kx\),\(K=R^{-1}B^\top P\),其中 \(P\) 解 Riccati 方程
本章 §1.6 会看到:\(N\) 人 LQ 博弈把这一条 Riccati 变成 \(N\) 条相互耦合的 Riccati——这就是从"单人最优"到"多人均衡"在线性世界里的全部数学增量。
带符号距离与水平集。 给定闭集 \(\mathcal{T}\),其带符号距离函数 \(g(x)\) 满足:\(x\in\mathcal{T}\Leftrightarrow g(x)\le 0\),且 \(|g(x)|\) 是 \(x\) 到边界 \(\partial\mathcal{T}\) 的距离。 于是"集合"被编码成"函数的零下水平集" \(\{x:g(x)\le 0\}\),集合的演化变成函数的演化。 这是 §1.4–§1.5 把布尔问题(到没到达)转成连续问题(值函数)的关键技巧。
预计阅读时间¶
| 模式 | 时间 | 说明 |
|---|---|---|
| 精读(含手推 Isaacs/Riccati + 跑一个 Air3D) | 20–28 小时(约 2 周) | 完整训练本章目标列出的全部能力 |
| 速读(理解概念脉络,跳过数值细节与手推) | 5–7 小时 | 抓住 §1.1–§1.4 + §1.6 主线 |
| 速查(回头查某个公式/陷阱) | — | 用章末速查表与符号表定位 |
§1.1 从最优控制到微分博弈:为什么需要博弈视角 ⭐⭐¶
这一节解决什么问题:说清楚单智能体规划在交互场景下到底缺了什么,从而让"博弈"这个看似抽象的工具显得不可回避。 这一节没有公式,但它定下了整条线的世界观——后面三章都在为这里提出的三次认知跨越提供数学工具。
动机:一个十字路口的两难¶
设想一个无保护左转。 你的车要左转穿过对向直行车道,对向有一辆车正在接近。 你的规划器需要决定:是抢在对方前面转过去,还是让对方先过。
把这个场景交给一个标准的"预测—然后—规划"管线,它会这样做: 先用一个预测模块预测对向车未来 3 秒的轨迹,把这条轨迹当作一个**移动的障碍物**; 然后在"避开这个障碍物"的约束下,为自己求一条最优轨迹。
问题出在第一步。 预测模块预测对向车轨迹时,它假设对向车的行为与你无关——它不知道(也没建模)"如果你果断地把车头探进路口,对向车很可能会减速让你"。 换句话说,对向车的真实轨迹**取决于你的行为**,而你的规划又取决于对它的预测。 这是一个鸡生蛋的循环,而"预测—然后—规划"把这个循环粗暴地切断了:先固定一方,再优化另一方。
反面案例:被切断的反馈环会怎样¶
把这个循环切断,会催生两种典型病灶。
病灶一:frozen robot(僵住的机器人)。 如果预测模块给出的是"对向车会一直匀速直行"(因为它没建模交互),那么在你看来,整条对向车道在未来几秒内都被占满,没有任何安全间隙。 于是你的规划器得出唯一"安全"的结论:原地不动,等对方过完。 可现实里,只要你稍微往前探,对方就会让——但你的模型里没有这个机制,于是你永远在等,对方也因为你不动而继续直行,僵局形成。 在密集人流中导航的机器人最容易犯这个病:把每个行人都当成不可协商的移动障碍,结果寸步难行。 量化地说:当行人密度超过某个阈值,"把所有人当固定障碍"的规划器会发现可行集为空,从而完全停摆——而人类在同样的人流里照样能穿行,靠的正是"我动一下、对方会让一下"的隐式协商。
病灶二:预测与规划的不一致。 预测和规划脱节还会反向出问题。 如果预测器乐观地认为"对方会让我",而对方其实是个不让的激进司机,规划器就会做出危险的抢行; 反过来,如果预测器悲观,又退化成 frozen robot。 根子是同一个:预测把对手的策略当成了与己无关的外生输入,而它本该是内生的、对你的行为做出反应的。
本质洞察:交互场景里真正缺的不是"更准的预测器",而是承认对手是一个**有目标的决策者**——它的轨迹不是一条要去拟合的曲线,而是它自己优化问题的解。 一旦接受这一点,"预测"就不再是独立模块:对手的"预测轨迹"应当是博弈均衡中对手的最优响应。 这就是后面 G3 会展开的"预测即均衡"。
三次认知跨越:博弈规控到底新在哪¶
把上面的直觉提炼一下,从单智能体规控走到博弈规控,要完成三次认知跨越。 这三句话是整条 G 线(G1–G4)的精神主轴,值得反复回味——后面每一章都在为其中某一跨越提供数学工具。
跨越一:从"最优控制"到"均衡"。 单智能体规控的核心是 \(\min_u J(x,u)\)——凸时存在唯一全局最优。 博弈规控没有"最优"的概念,只有"均衡"——每个人在其他人策略固定时不能单方面改善。 把单智能体和博弈并排放,差异一目了然:
| 维度 | 单智能体最优控制 | 微分博弈 |
|---|---|---|
| 目标 | \(\min_u J(x,u)\) | 每人有各自的 \(J_i\) |
| "最好"的含义 | 全局最优(凸时唯一) | 均衡:他人固定时无法单方面改善 |
| 解的存在性 | 通常存在 | 纯策略下可能不存在 |
| 解的唯一性 | 凸时唯一 | 通常**不唯一**(选哪个是设计决策) |
| 求解 | 一个优化问题 | 耦合的多个优化问题(求不动点) |
这张表里最容易被低估、却最重要的一行是"唯一性"。 在十字路口,"你让我先过"和"我让你先过"都是**合法的纳什均衡——双方都没有单方面改善的动机。 数学不会告诉你该选哪个;**均衡选择是一个设计决策,而不是一个数学结果。 这是从单智能体到博弈最大的认知转变:你不再是在求一个确定的最优,而是在一族均衡里,用额外的准则(社会习俗、礼让规则、谁先公示意图)去挑一个。 后面 G2 讲 iLQGames 时会反复撞上这件事——同一个场景,换个初始化,求解器会收敛到不同的均衡。 本章 §1.2 的 Isaacs 方程,正是零和博弈里刻画均衡的工具。
跨越二:从"预测-然后-规划"到"预测即均衡"。 传统管线先用 predictor 预测他人轨迹,再把预测当固定障碍做规划——这就是上面 frozen robot 的根源。 博弈规划把预测和规划统一:他人的"预测"就是博弈均衡中他人的最优响应,不需要独立的 predictor 模块。 ego 的"规划"是均衡里 ego 的最优策略,他人的"预测"是同一个均衡里他人的最优策略,两者同时求解、自洽。 G3 的 GameFormer、可微博弈都在兑现这一跨越。
跨越三:从"我的代价函数已知"到"对手的代价函数需要推断"。 单智能体规控的 \(J(x,u)\) 由设计者确定。 博弈规控中,对手的代价函数 \(J_i\) 往往是未知的——需要从观测轨迹反推(逆博弈 / 逆强化学习)。 这把优化问题从"给定目标求最优"升级为"先推断目标、再求均衡"的双层结构。 G3 的逆博弈、Level-k 推理就是为跨越三准备的工具。
不是 X 而是 Y:博弈规划**不是**"更复杂版本的最优控制",而是一类**结构不同**的问题。 最优控制求一个点(最优解),博弈求一个不动点(均衡); 最优控制问"怎样最好",博弈问"在别人也最好的前提下,什么是稳定的"。 把博弈当成"多约束的最优控制"来套求解器,会在均衡不唯一、不存在时栽跟头。
博弈在机器人学中的出没地图¶
博弈视角不是个别场景的奇技淫巧,它在机器人学里反复出现。 下表给出一张"出没地图",并标出每类问题更适合零和还是一般和建模——这个区分直接决定后面用哪套工具。
| 场景 | 玩家 | 博弈类型 | 本线对应 |
|---|---|---|---|
| 无人机空战 / 拦截 | 拦截方 vs 入侵方 | 零和(纯对抗) | §1.8 追逃、§1.2 HJI |
| 安全验证(系统 vs 最坏扰动) | 控制 vs 干扰 | 零和(鲁棒视角) | §1.4 可达性、U2 Tube/CBF |
| 无保护左转 / 并线汇入 | 车 vs 车 | 一般和(都想快、都想不撞) | G2 iLQGames / ALGAMES |
| 无人机竞速 | 选手 vs 选手 | 一般和(抢线但不愿撞) | G2 SE-IBR |
| 人机协作 / 自驾与人类司机 | 机器 vs 人 | 一般和 + 层级 | G2 Stackelberg、G3 Level-k |
| 多机器人协调 / 覆盖 | 多机器人 | 一般和(势博弈) | G4 势博弈、Multi 线 |
多视角理解(零和 ↔ 鲁棒控制)。 "安全验证"这一行值得单独点出:它表面上不是博弈,但把"最坏情况干扰"想成一个对抗玩家,它就变成了纯零和博弈。 相似之处:干扰像一个处处与你作对的对手,你求"在它最坏发挥下仍安全"的控制——这正是 \(\min_u\max_v\)。 不同之处:真实干扰并没有"意图",它只是恰好取到最坏值;把它拟人化为玩家只是为了用博弈工具,不要因此以为风、噪声真的在"算计"你。 这条把零和博弈和鲁棒控制接起来的视角,是 §1.4 可达性、以及不确定性规划 U2 的共同出发点。
历史:Isaacs 与微分博弈的起源¶
把"对手也在最优决策"这件事数学化的,是 Rufus Isaacs。 1950 年代他在兰德公司(RAND Corporation)研究空战与追逃问题,提出了"微分博弈(differential game)"这一框架,并在 1965 年出版专著 Differential Games(Wiley)系统化了它。 Isaacs 的标志性问题——后面 §1.8 会细讲的 Homicidal Chauffeur("开车的杀手")——就是一个追逃博弈:一个转弯半径受限的追捕者去抓一个机动灵活的逃跑者,双方都在连续时间里实时最优地决策。
Isaacs 的关键贡献不只是提出问题,而是给出了刻画双方最优策略的方程(今天叫 Isaacs 方程 / HJI 方程,§1.2),并发现了一个深刻的对称性条件(Isaacs 条件,决定博弈是否"有值")。 他还区分了两类博弈,这个区分后面会反复用到:
- "程度博弈"(game of degree):结果是一个连续的数值(如最终被抓住时两者的距离、追上所需时间),双方优化这个数值。
- "类型博弈"(game of kind):结果是一个布尔判断(追上了没有、撞了没有),双方争的是定性的胜负。
这套理论后来经 Basar 与 Olsder 在 Dynamic Noncooperative Game Theory(SIAM,1982 初版,1999 SIAM Classics 版)中系统整理为动态/微分博弈的统一框架,又经 Evans 与 Souganidis(1984)从粘性解理论给出严格的数学基础。 这些是 §1.2、§1.3 的主角。 §1.4 还会看到一个漂亮的转化:水平集方法能把"类型博弈"(到没到达)化成"程度博弈"(值函数的零下水平集),从而可数值求解——这是整个可达性领域的奠基技巧。
零和 vs 一般和:本章的边界¶
博弈分两大类,本章重心在零和:
- 零和博弈:一方所得即另一方所失,\(J_1=-J_2\)。 追逃、安全验证(你 vs 最坏情况干扰)属于此类——它有最干净的理论(HJI 方程,§1.2–§1.4)。
- 一般和博弈:各方目标不完全对立也不完全一致(如交互式驾驶——大家都想快、也都想不撞)。 这是 G2/G3 的重心,理论更复杂、均衡更易不唯一。
本章先在零和的干净世界里把 HJI 方程、可达性、耦合 Riccati 这些工具打磨好,G2 再带着它们进入一般和的真实交通。 一个提醒:§1.6 的 LQ 博弈是个例外——它本身就是一般和(每人有自己的 \(Q_i,R_i\)),放在本章是因为它的耦合 Riccati 是 G2 iLQGames 的直接数学前置,与零和理论无缝衔接。
⚠️ 常见陷阱¶
陷阱 1:把博弈当成"加了对手约束的最优控制" - 错误描述:新手常想"那我把对手的最优轨迹当约束塞进我的优化不就行了?这和避障没区别"。 - 现象/后果:在均衡不唯一时,求解器随机停在某个均衡上,行为不可预测;在 frozen robot 场景下,规划器把对手当固定障碍,导致僵死或危险抢行。 - 根本原因:对手的轨迹不是外生约束,而是它自己优化问题的解,且这个解依赖于你的策略。把它当固定约束,等于人为切断了交互的反馈环。 - 正确做法:把双方的优化问题联立,求**均衡**(不动点)而非单方最优。检验方法:问自己"如果我换个策略,对手的'最优轨迹'会不会变?"——会变,就说明它不该被当固定约束。
陷阱 2:默认博弈均衡唯一、必然存在 - 错误描述:把单智能体"凸问题有唯一全局最优"的直觉直接搬过来,假设博弈也有唯一确定的解。 - 现象/后果:设计的系统在多均衡场景下行为漂移(同样的输入,时而让行时而抢行);在纯策略均衡不存在的博弈里,求解器不收敛却找不到原因。 - 根本原因:纳什均衡是不动点,不动点可能多个、可能没有(纯策略下)、可能不稳定。存在唯一性需要额外条件(如势博弈、严格凹凸),不是默认。 - 正确做法:先判断博弈类型与均衡结构;接受"均衡选择是设计决策",显式引入选择准则(礼让规则、初始化偏好等)。检验方法:在十字路口场景里手动找出至少两个不同的均衡,确认你的系统知道该挑哪个、为什么。
练习¶
- (开放分析) 找一个你亲身遇到过的"预测—然后—规划"会失败的真实交互场景(路口、电梯口、人流、并线),写出:(a)如果把对手当固定障碍,规划器会得出什么结论;(b)这个结论为什么不合理;(c)"承认对手在最优决策"会如何改变结论。把它对应到三次认知跨越中的哪一次。
- (概念) 用自己的话解释为什么"均衡选择是设计决策而非数学结果",并举一个均衡不唯一的日常例子(不限于交通)。再说明:在你的例子里,人类社会用什么"额外准则"挑选均衡?
- (辨析) 下面四个问题,分别更适合零和、一般和,还是根本不需要博弈?说明理由:(i) 无人机空战拦截;(ii) 两车并线汇入;(iii) 机器人在空旷房间里走向充电桩;(iv) 扫地机器人与家里的猫"抢"同一条走道。
§1.2 零和微分博弈与 Isaacs 方程 ⭐⭐⭐¶
这一节解决什么问题:把"双方实时对抗"这件事写成一个能求解的数学对象——Isaacs 方程,并回答一个微妙但要命的问题:这个博弈到底有没有一个确定的"值"?
动机:追逃博弈里"同一个代价,一方想小一方想大"¶
零和博弈最纯粹的形态是追逃。 设状态 \(x\)(比如追捕者与逃跑者的相对位置)按 \(\dot x=f(x,u,v)\) 演化,其中 \(u\) 是玩家 1(追捕者)的控制、\(v\) 是玩家 2(逃跑者)的控制。 定义一个代价
比如 \(g(x(T))\) 取终端时刻两者的距离。 追捕者想让这个距离**小**(\(\min_u\)),逃跑者想让它**大**(\(\max_v\))。 同一个 \(J\),一方求最小、一方求最大——这就是零和。 问题是:双方同时连续地决策,谁也不能预知对方下一刻的动作,最优策略到底长什么样?
反面案例:天真地"我先优化、你再优化"会丢掉什么¶
一个诱人的错误是把它拆成两步:先固定 \(v\),让 \(u\) 求最优;再固定这个 \(u\),让 \(v\) 求最优。 但这会丢掉博弈的核心——同时性**与**信息结构。 如果你让 \(u\) 先承诺一条完整轨迹、\(v\) 再针对它最优响应,那 \(v\) 占了全部便宜(它知道 \(u\) 的全部计划); 反过来则 \(u\) 占便宜。 这两种拆法给出不同的结果,且都不是"双方同时实时博弈"的真相。 真相介于两者之间,由**值的上下界是否相等**来界定——这正是 Isaacs 条件要回答的。
先看最简单的情形:2×2 矩阵博弈与鞍点¶
连续时间的 Isaacs 条件听起来抽象,但它的内核在一个**有限的 2×2 矩阵博弈**里就能看得一清二楚。 先把这个最简单的台阶踩稳,再上连续情形就不悬空了。
设两个玩家各有两个动作。 玩家 1 选行(记为 \(r_1,r_2\)),玩家 2 选列(\(c_1,c_2\)),收益写成一个矩阵 \(M\),其中 \(M_{ij}\) 是"玩家 1 付给玩家 2"的数额——零和,所以**玩家 1 想让它小(最小化)、玩家 2 想让它大(最大化)**。
和连续情形一样,先后手会带来差异,于是有两个值:
- 下值(maxmin):玩家 2 先"承诺"选哪列,玩家 1 看到后挑最优的行。对每一列,玩家 1 会挑该列最小的数(行最小);玩家 2 则挑能让这个行最小**最大**的列:\(\underline V=\max_j\min_i M_{ij}\)。
- 上值(minmax):玩家 1 先承诺选哪行,玩家 2 看到后挑最优的列。对每一行,玩家 2 挑该行最大的数(列最大);玩家 1 挑能让这个列最大**最小**的行:\(\overline V=\min_i\max_j M_{ij}\)。
例一:有鞍点。 取
逐步算:每行的最大是 \(\max(2,3)=3\)、\(\max(1,4)=4\),故 \(\overline V=\min(3,4)=3\)(玩家 1 选第 1 行)。 每列的最小是 \(\min(2,1)=1\)、\(\min(3,4)=3\),故 \(\underline V=\max(1,3)=3\)(玩家 2 选第 2 列)。 两者相等:\(\overline V=\underline V=3\)。 对应的格子 \((r_1,c_2)=3\) 是一个**鞍点**——它同时是所在行的最大、所在列的最小:玩家 1 在第 1 行时玩家 2 最优就是第 2 列,玩家 2 在第 2 列时玩家 1 最优就是第 1 行,谁都不想单方面偏离。 这就是博弈"有值"的离散版:先后手无所谓,纯策略下存在稳定均衡。
例二:没有鞍点。 把矩阵换成
行最大 \(\max(3,1)=3\)、\(\max(2,4)=4\),故 \(\overline V=\min(3,4)=3\)。 列最小 \(\min(3,2)=2\)、\(\min(1,4)=1\),故 \(\underline V=\max(2,1)=2\)。 这次 \(\overline V=3>\underline V=2\),没有纯策略鞍点:谁先暴露策略谁就吃亏,先后手有差异(差额 \(3-2=1\) 就是"信息优势"的价值)。 要让博弈重新"有值",得允许**混合策略**(按概率随机选行/列)——von Neumann 的 minimax 定理保证:任何有限零和博弈在混合策略下 \(\overline V=\underline V\),总有鞍点。
对比性思维(矩阵博弈 ↔ 微分博弈的 Isaacs 条件)。 把这两个例子和 §1.2 后面的 Isaacs 条件对起来,抽象就落地了。 相似之处:例一(有鞍点、\(\overline V=\underline V\))正是 **Isaacs 条件成立**的离散缩影——博弈有唯一的值、先后手无所谓;例二(无鞍点、\(\overline V>\underline V\))则是 **Isaacs 条件失效**的缩影。 微分博弈里那个 \(\min_u\max_v\) 与 \(\max_v\min_u\) 是否相等,就是在问"逐点的哈密顿量这个小博弈有没有鞍点"——和矩阵博弈是同一个问题,只是把有限矩阵换成了关于连续动作 \((u,v)\) 的函数。 不同之处:矩阵博弈靠混合策略总能恢复鞍点(minmax 定理),而微分博弈的 Isaacs 条件讨论的是**纯反馈策略**下的鞍点,它依赖哈密顿量的可分离/凸凹结构、不总成立。 记住这个台阶:以后看到 \(\min\max\) 与 \(\max\min\),先在脑子里画一个 2×2 矩阵,问"有没有一个格子同时是行最大、列最小"。
上值、下值与信息结构¶
严格定义博弈的解,要先固定**信息结构**——谁能看到谁的什么。 一种标准做法(也是 §1.4 可达性里用的)是**非预期策略(non-anticipative strategy)**。 让一方(比如 \(v\))可以根据对方**到当前时刻为止**的控制来决定自己的动作,但不能预知未来。 形式上,\(v\) 的非预期策略 \(\gamma\) 是一个从"\(u\) 的历史"到"\(v\) 的动作"的映射,且满足因果性:若两个 \(u\) 在 \([t,s]\) 上一致,则 \(\gamma\) 对它们的响应在 \([t,s]\) 上也一致。 这给了 \(v\) 一个"瞬时信息优势"——它能看到 \(u\) 此刻的动作再回应。
在此设定下定义博弈的**下值**
其中 \(\gamma\) 取遍 \(v\) 的非预期策略。 对称地,让 \(u\) 拥有信息优势(\(u\) 用非预期策略回应 \(v\)),可定义**上值** \(V^+\)。 直觉上,上值是"让谁占信息便宜"换了一方的结果。 一般地有
为什么 \(\max\min\le\min\max\):先动者吃亏¶
上面那个不等式方向不是约定,而是可以两行证明的普适事实,它的直觉就是"先暴露策略的一方吃亏"。 对任意二元函数 \(H(u,v)\),固定任意 \(v_0\):\(\min_u H(u,v_0)\) 是 \(H(\cdot,v_0)\) 在所有 \(u\) 上的最小值,按最小值的定义,它不大于任何一个具体的 \(H(u,v_0)\),即 \(\min_u H(u,v_0)\le H(u,v_0)\) 对一切 \(u\) 成立。 两边对 \(v_0\) 取最大(注意左边 \(\min_u H(u,v_0)\) 仍依赖 \(v_0\)):
右边对一切 \(u\) 成立,那它也不小于"挑最好的 \(u\)",即对左边再取 \(\min_u\) 不会破坏不等式:
本质洞察:\(\max\min\le\min\max\) 的物理含义是**信息优势永远非负**。 内层先动的一方(被 \(\min\)/\(\max\) 套在里面、要先确定)处于劣势,因为外层的对手能看到它的选择再回应。 谁后动、谁能"见招拆招",谁就不吃亏。 等号成立——即先后手无所谓——是一个特殊而美好的情形,由 Isaacs 条件刻画。
动态规划与 HJI 方程的推导¶
下面把刻画下值 \(V^-\)(下面统一记为 \(V\))的偏微分方程真正一步步推出来,而不是直接抛结论。 核心工具是动态规划原理:把时间窗 \([t,T]\) 切成很短的第一段 \([t,t+\delta]\) 与剩下的 \([t+\delta,T]\)。 第一段里双方博弈一小步,第二段的剩余博弈递归地由值函数 \(V\) 自己描述。 这给出动态规划递归式:
它的直觉是:从 \((x,t)\) 出发的对抗最优值,等于"第一小段里累积的瞬时代价"加上"走到新状态 \((x(t+\delta),t+\delta)\) 后剩余博弈的值",双方在第一段就把这个总和博弈到鞍点。 这一步的合法性正是 §1.3 的粘性解理论所保证的——这里先用它推方程,严格性回头补。
第一步,处理第二段。 当 \(\delta\) 很小时状态只移动了一点点,\(x(t+\delta)\approx x+\delta\, f(x,u,v)\),对 \(V\) 在 \((x,t)\) 处做一阶 Taylor 展开:
第二步,处理第一段的积分。 区间长 \(\delta\) 很短,被积函数近似为常值,故
第三步,代回 (1.1a)。 等式两边都出现的 \(V(x,t)\) 相互抵消,剩下:
第四步,两边除以 \(\delta\) 并令 \(\delta\to 0\)。 当步长趋于零,第一段的非预期策略博弈退化为关于瞬时动作的逐点静态博弈,\(\inf_\gamma\sup_u\) 就变成逐点的 \(\min_u\max_v\)(这正是 Isaacs 条件保证其良定义的那个内部博弈); 而 \(\partial V/\partial t\) 不含 \(u,v\),可以提到博弈外面:
移项,并补上终端条件——在 \(t=T\) 时已无剩余博弈,值即终端代价——就得到 Hamilton–Jacobi–Isaacs(HJI)方程:
HJB ↔ HJI:换了一个旋钮¶
把 (1.1) 和前置桥接里的 HJB 方程 (HJB) 并排看,结构完全平行——唯一的区别是单人的 \(\min_u\) 变成了博弈的 \(\min_u\max_v\)。
多视角理解(HJB ↔ HJI)。 HJB 与 HJI 像同一台机器换了个旋钮。 HJB 在每个状态点问"我这一步该怎么走,使(当前代价 + 未来代价变化)最小"; HJI 问的是"我求最小、对手求最大,在这个对抗下这一步的鞍点值是多少"。 相似之处:都是值函数对状态梯度 \(\nabla_x V\)(协态)与动力学 \(f\) 做内积,再叠加瞬时代价 \(L\),构成哈密顿量。 不同之处:HJI 的哈密顿量内部是一个 \(\min\)-\(\max\) 博弈而非单个 \(\min\),这一个改动把"最优"变成了"鞍点",也带来了下面 Isaacs 条件这个全新的问题。 这个类比的边界:不要因此以为 HJI"只是 HJB 多套一层优化"——多出来的这层让解的存在唯一性、可微性都变复杂了(§1.3)。
哈密顿量与最优策略¶
定义哈密顿量
给定值函数,双方的瞬时最优策略由这个内部博弈的鞍点给出:
也就是说,求解 HJI 方程同时给出了值函数和最优反馈策略——和单人 HJB 一样,这是动态规划方法相对 PMP 的核心优点:PMP 给的是单条最优轨迹(开环),HJI 给的是全状态空间的反馈律 \(u^*(x,t)\)。 反馈律的好处在 §1.4 会再强调:有扰动时,反馈策略能"见状态调整",比开环鲁棒得多。
新手常见困惑(Q&A)¶
推导走完,这里集中回答几个初学时最容易卡住的问题——它们不是细节,而是理解 HJI 的关键关节。
Q1:为什么 (1.1a) 里那个 \(\inf_\gamma\sup_u\)(对整段策略求极值)到极限就变成了逐点的 \(\min_u\max_v\)(只对此刻动作求极值)? 因为取了 \(\delta\to 0\)。 \(\inf_\gamma\sup_u\) 是对 \([t,t+\delta]\) 这一小段上的**策略函数**求极值;当 \(\delta\to 0\),这一段塌缩成一个时刻,"策略函数"退化为"此刻的一个动作 \((u,v)\)",于是对函数的 \(\inf\sup\) 就变成了对当前动作的 \(\min\max\)。 未来的全部影响已经被 \(\nabla_x V\cdot f\) 那一项(值函数的梯度)打包带走了,此刻只需在瞬时动作上博弈。
Q2:为什么 HJI 是终端条件 \(V(\cdot,T)=g\)、向"过去"解,而不是初始条件向未来解? 因为代价定义在未来:\(V(x,t)\) 是"从 \((x,t)\) 出发到终点 \(T\) 的最优剩余代价"。 终点处没有剩余博弈,值就等于终端代价 \(g\)——这是唯一能直接写出的"已知边界"。 其余时刻的值要靠它向回(\(t\) 减小方向)递推。 这和单人 HJB 完全一致,是动态规划"从终点倒推"的本性。 (§1.4 的可达性用 \(t<0\) 的记号把"向过去解"写成了"向 \(t\) 负方向积分",是同一回事换了个坐标。)
Q3:HJI 和 Pontryagin 最大值原理(PMP)什么关系?为什么说 HJI 给反馈、PMP 给开环? 两者都刻画最优性,但层次不同。 PMP 是**必要条件**,沿**一条**最优轨迹给出协态方程和极值条件,解出来是一条**开环**轨迹 \(u^*(t)\)(时间的函数)。 HJI 是**充分**的动态规划方程,在**整个状态空间**上解出值函数,进而给出**反馈律** \(u^*(x,t)\)(状态的函数)。 反馈的好处在有扰动时立刻显现:开环轨迹被扰偏了就失效,反馈律能"看当前状态"实时纠正——这也是 §1.4 可达性、§1.6 LQ 博弈都要反馈解的原因。 代价是 HJI 要解全空间的 PDE(维度诅咒,§1.7),PMP 只解一条轨迹的两点边值问题(便宜,但只得开环)。
Q4:HJI 里的协态 \(\lambda=\nabla_x V\) 和 PMP 里的协态是一回事吗? 本质是同一个东西。 PMP 的协态 \(\lambda(t)\) 沿最优轨迹,恰好等于值函数在该点的梯度 \(\nabla_x V(x^*(t),t)\)——都是"状态的影子价格"(状态微小变化引起的最优代价变化率)。 HJI 是这个关系在全空间的版本,PMP 是它沿单条轨迹的切片。
Isaacs 条件:博弈到底有没有"值"¶
这是本节的关键。 \(V^-\) 用 (1.1) 里的 \(\min_u\max_v\),而 \(V^+\) 用 \(\max_v\min_u\)。 上一小节已证 \(V^-\le V^+\)(等价地 \(\max_v\min_u\le\min_u\max_v\))。 当两者相等时,博弈有明确定义的"值",且存在鞍点策略——这就是 Isaacs 条件(鞍点条件):
本质洞察:Isaacs 条件成立,意味着"谁先暴露策略"不影响结果——上值等于下值,博弈有唯一的值,先后手优势消失。 它在博弈论里对应 von Neumann 的 minimax 定理在逐点哈密顿量层面的体现:内部那个关于 \((u,v)\) 的静态博弈存在鞍点。
什么时候成立? 一个充分(非必要)条件是哈密顿量内部对 \(u\)、\(v\) 可分离。 如果动力学与代价能写成
那么 \(\min_u\) 只作用在"只含 \(u\) 的项"上、\(\max_v\) 只作用在"只含 \(v\) 的项"上,二者作用于互不重叠的部分、互不干涉;既然先对哪一部分取极值都不影响另一部分,交换 \(\min_u\) 与 \(\max_v\) 的顺序就不改变结果,Isaacs 条件自动成立。 大量追逃博弈恰好满足这个可分离性,因为 \(u\) 和 \(v\) 常常各自**线性地**出现在动力学里(如 \(f=a(x)+b(x)u+c(x)v\)),且代价对二者解耦。 更一般地,只要内部博弈对 \(u\) 凸、对 \(v\) 凹(鞍点存在的经典充分条件),Isaacs 条件就成立。
对比性思维(成立 vs 失效)。 成立的情形:\(f=a(x)+b(x)u+c(x)v\)、\(L\) 对 \(u,v\) 解耦——\(\min_u\) 和 \(\max_v\) 各管各的项,顺序无关。 失效的情形:当 \(u\) 与 \(v\) 在哈密顿量里**乘在一起**(如出现 \(u^\top M v\) 这样的双线性耦合且 \(M\) 不定),内部博弈未必有鞍点,\(\min\max>\max\min\) 严格成立,博弈只有上下值而没有统一的"值"。 此时强行套 (1.1) 会得到一个并不对应任何一方真实最优的"伪值"。
一个算到底的例子:一维追逃¶
抽象推导之后,落一个能从头算到尾的例子,把哈密顿量、最优策略、Isaacs 条件都走一遍。 设相对位置 \(x\in\mathbb{R}\),动力学
无运行代价 \(L=0\),终端代价 \(g(x)=|x|\)(追捕者想让 \(|x|\) 小、逃跑者想让它大)。 协态记 \(\lambda=\partial V/\partial x\)。 哈密顿量
这里 \(u\) 项与 \(v\) 项已经分离,所以 \(\min\max=\max\min\),Isaacs 条件成立。 逐项求极值:
于是 \(H(x,\lambda)=-|\lambda|+|\lambda|=0\)。 代入 HJI 方程 \(-\partial_t V=H=0\),得 \(\partial_t V=0\)——值函数不随时间变化,恒等于终端代价 \(V(x,t)=|x|\)。
这个结果有清晰的物理意义: 追捕者和逃跑者的"操控权"在动力学里完全对称(\(-u+v\),各自系数大小相同),双方全力对抗的净效果是**相互抵消**,相对距离 \(|x|\) 保持不变。 最优策略 \(u^*=v^*=\operatorname{sign}(\lambda)=\operatorname{sign}(x)\) 也直白:当 \(x>0\),追捕者取 \(u=+1\) 想把 \(x\) 拉小、逃跑者取 \(v=+1\) 想把 \(x\) 推大,两者打平。 注意值函数 \(|x|\) 在 \(x=0\) 处不可微——这正是 §1.3 要处理的"棱",也提醒我们 \(\lambda=\operatorname{sign}(x)\) 在原点没有定义、需要粘性解框架来收尾。
⚠️ 常见陷阱¶
陷阱 1:默认 \(\min_u\max_v=\max_v\min_u\) - 错误描述:写 Isaacs 方程时随手把 \(\min\max\) 写成 \(\max\min\),或反过来,以为两者本来就一样。 - 现象/后果:在 Isaacs 条件不成立的博弈里,你算出的值函数既不是上值也不是下值,得到的"最优策略"对任何一方都不是真的最优;在仿真里表现为双方行为诡异、解对初始化异常敏感。 - 根本原因:\(\max\min\le\min\max\) 是普适不等式,等号只在 Isaacs 条件(鞍点存在)下成立。先暴露策略的一方天然吃亏,所以顺序一般有影响。 - 正确做法:写方程前先验证 Isaacs 条件——检查哈密顿量对 \(u,v\) 是否可分离(或凸-凹)。可分离时随便用哪个顺序都行;不可分离时必须明确你算的是上值还是下值,并据此选 \(\min\max\) 或 \(\max\min\)。
陷阱 2:忽略信息结构,以为只有"一个"博弈值 - 错误描述:把零和博弈当成"双方各求一次极值",不区分谁能看到谁的当前动作。 - 现象/后果:在需要鲁棒安全保证的场景(§1.4),用错了信息结构会高估安全集——让对手(干扰)反而吃了亏,得到偏乐观、不安全的结果。 - 根本原因:博弈的值依赖信息结构(开环 / 反馈 / 非预期策略)。安全验证里要给对手瞬时信息优势(非预期策略),才能保证"最坏情况"真的被覆盖。 - 正确做法:明确写出谁用非预期策略、谁先承诺。安全验证默认让干扰拥有瞬时信息优势(取下值),这样得到的安全集是保守的、可信的。检验方法:问"如果对手能多看我一眼,结果会不会更糟?"——会,就说明你的信息结构给安全留了漏洞。
练习¶
- (手推,照着例子做一遍) 把正文那个一维追逃改成"操控权不对称":\(\dot x=-2u+v\)(追捕者更强),其余不变。重新写哈密顿量,求 \(u^*,v^*\) 与 \(H(x,\lambda)\),解出 \(V(x,t)\),并解释结果(追捕者能不能稳定缩小距离?)。
- (判定 Isaacs 条件) 对哈密顿量 \(H(u,v)=u^2-v^2+\lambda(u+v)\)(\(u,v\in\mathbb{R}\))与 \(H(u,v)=uv+\lambda u\)(\(u,v\in[-1,1]\)),分别判断 \(\min_u\max_v\) 是否等于 \(\max_v\min_u\),给出鞍点(若存在)或说明为何不存在。把结论对应到"可分离 / 凸-凹 / 双线性耦合"哪种情形。
- (概念联系) 解释为什么"安全验证"天然是零和博弈:谁是 \(\min\) 方、谁是 \(\max\) 方?为什么给对手(干扰)非预期策略对应"最坏情况安全"?再用 \(\max\min\le\min\max\) 说明:如果错误地让控制(而非干扰)占信息优势,安全集会被高估还是低估?
§1.3 HJI 偏微分方程与粘性解:值函数为什么不可微 ⭐⭐⭐¶
这一节解决什么问题:上一节写出了 HJI 方程,但回避了一个尖锐的事实——它的解通常不是处处可微的经典解。 这一节交代为什么,以及数学上该用什么"弱解"概念把方程救活,并用一个经典反例演示这个弱解如何唯一地挑出物理正确的那一个。
动机:从静态方程到可数值求解的演化方程¶
§1.2 的 (1.1) 是一个终端值偏微分方程:给定终端时刻 \(V(x,T)=g(x)\),向时间负方向推出每个时刻的值函数。 直觉上只要从终端往回积分这个 PDE 就能得到 \(V\)。 但这里藏着一个数学陷阱:这个积分过程会产生不可微的"棱"。 而一旦 \(\nabla_x V\) 在某处不存在,方程 (1.1) 里的 \(\nabla_x V\cdot f\) 就失去了意义,经典意义下的"解"根本不存在。 §1.2 末尾那个一维追逃的例子已经撞上了这件事:值函数 \(V(x,t)=|x|\) 在 \(x=0\) 处有一道棱,协态 \(\lambda=\operatorname{sign}(x)\) 在原点没定义。
反面案例:为什么值函数会长出"棱"¶
来看棱是怎么冒出来的。 在追逃博弈里,从某个初始状态出发,可能有两条不同的最优策略给出相同的代价(比如向左绕和向右绕都一样快地被追上)。 在这两类初始状态的分界面上,值函数 \(V\) 是连续的,但它的梯度从一侧跳到另一侧——出现一道折痕,就像两个斜面相交的屋脊。
多视角理解(值函数的"棱" ↔ 距离场的脊线)。 这道棱不是病态特例,而是普遍现象。 一个直观的类比:考虑平面上一个非凸障碍物的"到障碍物的距离场"——在障碍物凹进去的地方背后,会形成一条脊线,脊线上每一点到障碍边界有两个等距最近点,距离函数在那里有折痕、不可微。 HJI 值函数的棱与此同源:它本质也是一种"代价场",在"有多条等价最优路径"的地方就会起脊。 相似之处:二者都是"多个等距/等价竞争者在某处打平"导致的不可微。 不同之处:距离场只关于几何,而 HJI 值函数还编码了对抗动力学。 这个类比提醒我们:要求 HJI 的解处处可微,就像要求一个非凸物体的距离场处处可微一样不现实。
经典 PDE 理论要求解一阶连续可微,HJI 的解满足不了。 更糟的是,如果硬要找"几乎处处满足方程"的弱解,会发现**这样的弱解不唯一**——能构造出无穷多个几乎处处满足方程、却物理上荒谬的函数。 方程本身不足以钉死正确的那一个。 下面用一个能从头算到尾的小例子,把"非唯一"和"如何唯一化"都看清楚。
一个能算到底的反例:eikonal 方程 \(|u'|=1\)¶
抛开时间,看最简单的一阶 HJ 方程——一维 eikonal 方程
它的物理意义是"到边界 \(\{-1,1\}\) 的距离场应满足梯度模长为 1"。 现在找它的解。 问题在于:几乎处处满足 \(|u'|=1\) 的连续函数有无穷多个。 最简单的两个:
- \(u_+(x)=1-|x|\):一个尖朝上的帐篷,在 \(x=0\) 达到峰值 1,两臂斜率分别为 \(\mp 1\),处处(除 \(x=0\))满足 \(|u'|=1\),且 \(u_+(\pm1)=0\)。
- \(u_-(x)=|x|-1\):一个尖朝下的山谷,在 \(x=0\) 达到谷底 \(-1\),同样几乎处处满足 \(|u'|=1\)、满足边界条件。
除此之外还能拼出各种锯齿状的解(在 \((-1,1)\) 里来回折,每段斜率 \(\pm1\))。 单看方程,它们平起平坐。 但**物理上正确的只有一个**:\(u_+(x)=1-|x|\),它恰好是到边界的距离(\(x\) 离最近边界点的距离),处处非负、在中点最大。 \(u_-\)(负的距离)和那些锯齿解都是数学假象。 怎么用一个原则把 \(u_+\) 挑出来、把其余否决掉?这就是粘性解。
循序渐进:为什么朴素的弱解都行不通¶
在跳到粘性解的定义之前,先放慢脚步,把"我们到底需要一个什么样的解"想清楚。 面对一个解会起棱的方程,最自然的做法是依次试几种现成的"解"概念——看着它们一个个失败,粘性解为什么非它不可就水落石出了。
尝试一:经典解(处处可微)。 最理想的当然是要求解处处一阶连续可微、逐点满足方程。 但 §1.3 开头已经说明:值函数普遍有不可微的棱(eikonal 的 \(1-|x|\) 在 \(x=0\) 处、追逃值函数在散射面上)。 棱处 \(\nabla V\) 不存在,方程里的 \(\nabla V\cdot f\) 无从谈起——经典解根本不存在。✗
尝试二:分布意义的弱解(像线性 PDE 那样)。 线性 PDE 里有个标准招数:把方程乘上一个光滑测试函数、做分部积分,把导数"转移"到测试函数身上,于是即便解本身不可微也能定义弱解(分布解)。 这招对线性方程无往不利。 可 HJ/HJI 方程对梯度是**非线性**的——哈密顿量里是 \(|\nabla V|\)、\(H(\nabla V)\) 这种非线性项。 分部积分搬不动一个非线性的梯度函数,分布之间也不能做非线性的复合或相乘。 分布弱解这套机器对非线性 HJ 根本启动不了。✗
尝试三:"几乎处处"满足方程。 那退一步:棱是测度零的集合,要求解在可微的地方(也就是几乎处处)逐点满足方程,行不行? 这个概念是良定义的——但 §1.3 的 eikonal 反例已经演示过它的致命伤:a.e. 解不唯一。 \(1-|x|\)、\(|x|-1\)、以及各种锯齿解都几乎处处满足 \(|u'|=1\),方程加"a.e."这个条件太弱,选不出物理正确的那一个。✗
三次尝试,三种失败,恰好框定了我们需要的解必须同时满足三个看似矛盾的要求:
| 要求 | 经典解 | 分布弱解 | a.e. 解 | 我们想要的 |
|---|---|---|---|---|
| 允许棱(不要求处处可微) | ✗ | ✓ | ✓ | ✓ |
| 适用于对梯度非线性的方程 | ✓ | ✗ | ✓ | ✓ |
| 唯一(能选出物理解) | ✓ | — | ✗ | ✓ |
粘性解正是同时满足这三条的那个概念:它弱到允许棱、绕开了分布对非线性的无能、又强到能唯一确定物理解。 下面看它怎么做到这一点——关键的巧思是:不直接对 \(V\) 求导,而是借一个光滑的"陪练"函数从两侧去碰它。
慢动作:怎样在不可微的点上"满足"一个方程¶
在抛出形式定义前,先把它背后那个真问题用最慢的节奏想一遍——这个概念对没学过偏微分方程的工程师是全章最反直觉的一处,值得多花几分钟。
问题摆明白。 方程 (1.1) 里有 \(\nabla_x V\)。 在值函数的棱上,\(\nabla_x V\) 根本不存在。 那么"\(V\) 在棱上满足方程"到底是什么意思? 这不是抠技术细节——如果连"满足"都定义不清,整个 HJI 方程在最关键的棱处就是一句空话。
第一念(退一步)。 我们其实不必强求 \(V\) 在棱上可微。 我们真正需要的,只是一个"在棱上也说得通、且能挑出物理正确解"的判据。 换句话说:放弃"直接验证 \(V\) 满足方程",改成找一个等价的、绕开 \(\nabla V\) 的检验方式。
关键的转念。 你不能对 \(V\) 求导,但你可以拿一根**光滑**的函数 \(\phi\) 去贴住 \(V\),然后对 \(\phi\) 求导——\(\phi\) 是你自己挑的光滑函数,它的导数处处存在。 于是"方程在 \(x_0\) 处成立"这件对 \(V\) 做不到的事,被转嫁给了在 \(x_0\) 处贴住 \(V\) 的那根光滑 \(\phi\)。 这就是粘性解的全部诡计。 剩下的只是把"贴住"说清楚,以及搞明白该要求 \(\phi\) 满足什么。
慢动作之一:从上方贴。 想象在棱点 \(x_0\) 处,一根光滑的、开口向下的"碗" \(\phi\) 从**上方**压下来,一路下降到刚好碰到 \(V\)(数学上:\(\phi\ge V\) 在 \(x_0\) 附近,且 \(\phi(x_0)=V(x_0)\);等价地 \(V-\phi\) 在 \(x_0\) 取局部极大)。 在这个碰触点,\(\phi\) 有一个确定的斜率 \(\nabla\phi(x_0)\)。 粘性解要求:方程对这个斜率成立**一个方向的不等式**(次解条件,下面会写明是哪个方向)。
为什么是"一个方向",不是等号? 因为从上方贴的 \(\phi\),它的斜率被 \(V\) 的形状"卡"在一个范围里,不是唯一值。 拿 §1.3 后面 eikonal 的尖峰举例:在一个向上的尖峰处,能从上方贴住的光滑 \(\phi\),斜率可以是两条臂的斜率(\(+1\) 与 \(-1\))之间的任意值。 对所有这些可能的 \(\phi\) 都要求方程取等号,太强、根本做不到; 只要求它们都满足同一个方向的不等式,就刚刚好——既约束住了棱、又不至于无解。
慢动作之二:从下方贴。 对称地,一根开口向上的光滑"碗" \(\phi\) 从**下方**顶上来碰到 \(V\)(\(\phi\le V\) 附近、\(\phi(x_0)=V(x_0)\),即 \(V-\phi\) 取局部极小),给出**另一个方向**的不等式(超解条件)。
两面一卡,棱就定住了。 一个点若从上方贴得到一个方向、从下方贴得到另一个方向,两者都满足,它就是粘性解。 打个比方:像用两块光滑模板从上下两面卡一个有棱的零件——单独一面卡不死棱的位置,两面同时卡,棱就被唯一确定了。 这正是粘性解能从无穷多个 a.e. 弱解里挑出唯一物理解的几何直觉。 有了这个画面,下面的形式定义就只是把"从上/下方贴"和"哪个方向的不等式"写成符号而已。
解决这个困境的,是 1980 年代发展起来的**粘性解(viscosity solution)**理论(Crandall 与 Lions 1983 为 Hamilton–Jacobi 方程奠定,Lions 后来因相关工作获菲尔兹奖)。 粘性解的核心思想,是不直接要求 \(V\) 可微,而是用**光滑测试函数**从两侧"夹"住 \(V\),把"在不可微点满足方程"这件不可能的事,转嫁给在该点触碰 \(V\) 的光滑函数。
把方程统一写成 \(F(x,\nabla u)=0\) 的形式(eikonal 即 \(F=|\nabla u|-1\);HJI 即 \(F=\partial_t V+H\))。 精确定义如下:
- 粘性次解(subsolution):对任意光滑 \(\phi\),只要 \(u-\phi\) 在某点 \(x_0\) 取**局部极大**(即 \(\phi\) 从**上方**触碰 \(u\)),就要求 \(F(x_0,\nabla\phi(x_0))\le 0\)。
- 粘性超解(supersolution):对任意光滑 \(\phi\),只要 \(u-\phi\) 在某点 \(x_0\) 取**局部极小**(即 \(\phi\) 从**下方**触碰 \(u\)),就要求 \(F(x_0,\nabla\phi(x_0))\ge 0\)。
- 粘性解:同时是次解和超解。
在 \(u\) 可微的点,上下两个条件合起来退化为 \(F(x,\nabla u)=0\)(经典方程); 在棱上,则由上下夹逼挑出唯一正确的解。
这两个不等号方向不是约定,可由"消失黏性"推出来。 给方程加一个小扩散项,考虑 \(F(x,\nabla u^\varepsilon)=\varepsilon\,\Delta u^\varepsilon\),其光滑解为 \(u^\varepsilon\)。 设 \(\phi\) 光滑且 \(u-\phi\) 在 \(x_0\) 取严格局部极大;当 \(\varepsilon\) 小时,\(u^\varepsilon-\phi\) 在附近某点 \(x_\varepsilon\to x_0\) 也取局部极大。 在极大点处,一阶条件给 \(\nabla u^\varepsilon=\nabla\phi\),二阶条件给 \(\Delta(u^\varepsilon-\phi)\le 0\),即 \(\Delta u^\varepsilon\le\Delta\phi\)。 代入正则化方程:
这就推出了次解的 \(\le 0\)。 超解(从下方触碰、局部极小)对称地给出 \(\ge 0\)。 所以"从上方碰得 \(\le 0\)、从下方碰得 \(\ge 0\)"是消失黏性极限的逻辑后果,不是人为规定的。
本质洞察:粘性解不是"放松要求凑合用"的妥协,而是抓住了正确解的本质特征。 "粘性"二字正来自上面这个极限:给方程加一个无穷小的黏性(扩散)项,扩散会把棱磨光,得到光滑解 \(u^\varepsilon\);让 \(\varepsilon\to 0\),\(u^\varepsilon\) 收敛到的那个极限,恰好就是粘性解。 所以粘性解 = "无穷小黏性正则化的极限"——它是物理上、数值上都站得住的那一个,也正是带符号扩散的单调数值格式(§1.5)会收敛到的解。
用粘性解否决假解:回到 eikonal¶
现在用这套机制审判前面那两个候选解,看它怎么把 \(u_+\) 留下、把 \(u_-\) 踢掉。 关键都发生在尖点 \(x=0\)(别处都光滑、自动满足方程)。
审判 \(u_+(x)=1-|x|\)(尖朝上的峰)。 能否有光滑 \(\phi\) 从**下方**触碰(\(u_+-\phi\) 局部极小)? 要 \(\phi\le u_+\) 附近、且 \(\phi(0)=u_+(0)\)。 但 \(u_+\) 在 \(0\) 处是个向上的尖峰,两臂以斜率 \(\mp1\) 下降; 一个光滑函数要从下方贴住这个尖峰,需同时满足 \(x>0\) 侧斜率 \(\le-1\)、\(x<0\) 侧斜率 \(\ge+1\),自相矛盾——没有光滑 \(\phi\) 能从下方触碰。 于是超解条件在 \(x=0\) 处**空洞地满足**(没有需要检验的 \(\phi\))。 而从上方触碰的 \(\phi\),其斜率 \(\phi'(0)\in[-1,1]\),次解条件 \(|\phi'(0)|-1\le 0\) 成立。 所以 \(u_+\) 同时是次解和超解,是粘性解。✓
审判 \(u_-(x)=|x|-1\)(尖朝下的谷)。 现在 \(u_-\) 在 \(0\) 处是向下的尖谷。 取一条平缓的光滑曲线(比如开口向下的抛物线 \(\phi(x)=-1+\tfrac12 x^2\) 附近的修正)从**下方**触碰谷底,\(\phi'(0)=0\) 是允许的(它确实能贴在谷底下方、在 \(0\) 处相切)。 此时 \(u_--\phi\) 在 \(0\) 取局部极小,触发超解条件:要求 \(F(0,\phi'(0))=|\phi'(0)|-1\ge 0\)。 但 \(|\phi'(0)|-1=|0|-1=-1<0\),违反超解条件。 所以 \(u_-\) 不是粘性超解,不是粘性解,被否决。✗
对比性思维(峰 vs 谷的命运)。 同样是一道尖,朝上的峰能当粘性解、朝下的谷不能,差别全在"哪个方向能被光滑函数触碰"。 向上的尖峰挡住了来自下方的所有光滑触碰(超解条件空洞满足); 向下的尖谷却任由光滑函数从下方贴入,于是被超解条件抓个正着。 这背后是一条几何直觉:粘性解只允许"凸向正确方向"的棱。 对距离场而言,正确的棱是"远离边界的脊线"(向上的峰),所以 \(u_+=1-|x|\)(距离)胜出。 那些锯齿解里也藏着向下的谷,会被同样的机制逐一否决——这就是粘性解把无穷多个 a.e. 解收缩到唯一一个的方式。
HJ 方程 ↔ 守恒律:棱就是激波¶
粘性解的概念在另一个领域有个孪生兄弟,点出来能加深理解。
多视角理解(HJ 的棱 ↔ 守恒律的激波)。 把一维 HJ 方程 \(u_t+H(u_x)=0\) 对 \(x\) 求导,令 \(w=u_x\),就得到一个**标量守恒律** \(w_t+H(w)_x=0\)。 在这个映射下:HJ 解 \(u\) 的不可微"棱"(\(u_x\) 跳变处)恰好对应守恒律解 \(w\) 的"激波"(间断); HJ 的粘性解条件,恰好对应守恒律的**熵条件**(哪些激波是物理可容许的)。 相似之处:两者都面对"a.e. 弱解不唯一"的困境,都用一个额外条件(粘性/熵,都来自加无穷小扩散再取极限)挑出唯一物理解。 不同之处:这个精确对应只在一维成立;高维里 HJ 与守恒律的关系松散得多,不能逐字搬用。 但它给了一个有力的直觉:HJI 值函数的棱,就是"代价场里的激波",处理它要用处理激波的同一种智慧。
值函数 = HJI 的唯一粘性解¶
把这一切钉死的关键定理来自 Evans 与 Souganidis(1984,Indiana University Mathematics Journal)。 他们证明了零和微分博弈的上值与下值分别是相应 HJI 方程的**唯一粘性解**,并给出了它们的表示公式。 唯一性的机制是**比较原理(comparison principle)**:若 \(u\) 是次解、\(w\) 是超解,且在边界/终端上 \(u\le w\),则在整个区域上 \(u\le w\);把一个粘性解既当次解又当超解套进去,立刻得到任意两个粘性解必相等。 这个结果的意义是双重的:
- 它保证了 §1.2 写出的 HJI 方程**在粘性解意义下有且仅有一个解**,方程不再因为不可微和弱解不唯一而失效;
- 它把"博弈的值"(一个由策略定义的对象)与"HJI 方程的粘性解"(一个由 PDE 定义的对象)严格等同起来——这正是后续一切数值方法的合法性根基:在网格上算 PDE 的粘性解,就是在算博弈的值。
到这里,从动机到严格基础的链条闭合了: §1.2 用动态规划把博弈写成 HJI 方程,§1.3 用粘性解理论保证这个方程有且仅有一个物理正确的解。 剩下的问题是——怎么把它算出来? 这就引出 §1.4 的可达性表述与 §1.5 的数值方法。 特别地,§1.5 的数值格式必须"尊重粘性":用带数值耗散的单调格式(如 Lax–Friedrichs 型、WENO),才能在棱处稳定收敛到粘性解,而不是收敛到某个被否决的假解。
新手常见困惑(Q&A)¶
粘性解是全章最抽象的一块,这里把几个反复被问到的问题摆出来。
Q1:为什么偏偏叫"粘性"解?和黏性有什么关系? 名字直接来自上面那个消失黏性的极限。 给方程加的 \(\varepsilon\Delta V\) 是一个**扩散/黏性**项(就像流体里的黏性会把激波抹平),它把值函数的棱磨光成光滑的 \(V_\varepsilon\);让黏性 \(\varepsilon\to0\),得到的极限就是粘性解。 所以"粘性"指的是"无穷小黏性正则化的极限"——这个解记得"自己是被黏性磨出来的",因而在棱上的取法是物理正确的那一种。
Q2:加的那个扩散项可以随便选吗?换一种正则化会不会得到不同的解? 关键的好性质正在这里:对一大类正则化,极限都收敛到同一个粘性解。 不管你用 \(\varepsilon\Delta V\) 还是别的合理的椭圆正则化,\(\varepsilon\to0\) 的极限都是那个唯一的粘性解。 正是这种"对正则化方式不敏感"的稳健性,让粘性解成为一个**良定义**的概念,而不是依赖于你恰好怎么加黏性。 数值上对应的事实是:不同的单调(带耗散)格式都收敛到同一个粘性解。
Q3:博弈的值函数一定是粘性解吗?还是说粘性解只是个数学构造? 一定是——这正是 Evans–Souganidis(1984)定理的内容。 在 Isaacs 条件下,博弈的值(由策略、动态规划定义的那个对象)恰好就是 HJI 方程的唯一粘性解。 所以粘性解不是凭空的数学构造,而是"博弈的值"这个物理对象的精确刻画。 这座桥是双向的:要算博弈的值,就去求 HJI 的粘性解;求得了粘性解,就得到了博弈的值。
Q4:比较原理凭什么能保证唯一? 直觉是一个"夹逼"。 比较原理说:若 \(u\) 是次解、\(w\) 是超解,且在边界(终端)上 \(u\le w\),则在整个区域内 \(u\le w\)。 现在假设有两个粘性解 \(V_1,V_2\),它们终端条件相同(都等于 \(g\))。 把 \(V_1\) 当次解、\(V_2\) 当超解用比较原理 → \(V_1\le V_2\);反过来把 \(V_2\) 当次解、\(V_1\) 当超解 → \(V_2\le V_1\)。 两者一夹,\(V_1=V_2\)——唯一性就出来了。 次解/超解那两个看似古怪的单边条件,正是为了让这个夹逼论证能跑通而设计的。
⚠️ 常见陷阱¶
陷阱 1:默认 HJI 值函数处处可微,直接用 \(\nabla V\) - 错误描述:把值函数当成光滑函数,在推导或写数值格式时随手对 \(V\) 求梯度、求二阶导。 - 现象/后果:在棱附近梯度不存在,数值上 \(\nabla V\) 剧烈震荡甚至发散;用中心差分等不带耗散的格式会在折痕处产生伪振荡,可达集边界长出毛刺或断裂。 - 根本原因:HJI 值函数普遍含不可微的棱(多条等价最优路径的分界面),它是粘性解而非经典解。 - 正确做法:用为粘性解设计的、带数值耗散的单调格式(§1.5 的 WENO + 合适的数值哈密顿量),它们在折痕处稳定收敛到正确的粘性解。理论分析时引用粘性解框架而非假设可微。
陷阱 2:以为"几乎处处满足方程"就是正确解 - 错误描述:找到一个几乎处处满足 HJI 方程的连续函数,就当成博弈的值。 - 现象/后果:可能得到物理上荒谬的解(如前面 eikonal 的 \(u_-=|x|-1\),或各种锯齿解),且无法察觉错在哪——因为它确实几乎处处满足方程。 - 根本原因:HJI 方程的几乎处处弱解不唯一,方程本身不足以选出正确的那个;只有粘性解(或等价的黏性极限)才是唯一物理解。 - 正确做法:以粘性解为唯一正确解的判据。直觉检验:你的解能不能由"加小扩散再取极限"得到?若它在棱上的取法与"磨光后取极限"矛盾(如出现向下的尖谷),它就不是粘性解。
练习¶
- (亲手否决一个锯齿解) 在 \((-1,1)\) 上构造 eikonal \(|u'|=1\)、\(u(\pm1)=0\) 的一个锯齿解(比如在 \([-1,0]\) 升、\([0,1]\) 降之外再多折一次)。指出它在哪个尖点会被粘性解的哪个条件(次解还是超解)否决,照着正文 \(u_-\) 的审判过程写一遍。
- (构造直觉) 取 §1.2 的一维追逃值函数 \(V(x,t)=|x|\)。说明它在 \(x=0\) 处为何不可微、对应"哪条最优路径在此打平",并验证它是相应 HJI 方程的粘性解(提示:原点是向上还是向下的尖?)。
- (文献定位) 查阅 Evans–Souganidis(1984)的主结论陈述(不必读全文),用 2–3 句话写出:他们证明了博弈的上/下值与 HJI 方程的什么解等同?比较原理在唯一性证明中起什么作用?这个等同为什么是后续数值方法的合法性基础?
§1.4 可达性分析:BRS、BRT 与 reach–avoid ⭐⭐⭐¶
这一节解决什么问题:把抽象的"安全验证"落成一个能算的对象——可达集 / 可达管 / reach–avoid 集。 这一节也是本章最容易踩坑的地方:后向可达**集**与后向可达**管**只差一个词,方程不同,含义更不同。
动机:把"安全吗"变成"从哪些状态出发会出事"¶
安全验证要回答的是:从当前状态出发,在最坏情况干扰下,系统会不会进入危险区? 把这个问题反过来问更好算——有哪些初始状态,会不可避免地(在对手最优、我方也最优的对抗下)落入危险集? 这个"会出事的初始状态集合"就是可达性分析的产物。 它一旦算出来,安全控制就有了依据:只要系统不在这个集合里,就有控制能保证安全;它的补集就是安全集。 注意这里用的正是 §1.1 的"零和 ↔ 鲁棒控制"视角:把最坏情况干扰当成对抗玩家。
历史与背景¶
把可达集计算与 HJI 方程严格挂钩、并给出网格数值方法的,是 Mitchell、Bayen 与 Tomlin(2005,IEEE Transactions on Automatic Control, vol. 50, pp. 947–957)——"连续动态博弈的可达集的时变 Hamilton–Jacobi 表述",这是可达性领域的奠基性工程文献。 本节的公式与角色分析主要依据这条线后来的标准教程整理(Bansal、Chen、Herbert、Tomlin,2017,CDC,arXiv:1709.07523),它把 BRS/BRT 与角色取法讲得最清楚。 "既要到达目标、又要全程避开危险"的 reach–avoid 表述由 Margellos 与 Lygeros(2011,IEEE TAC)系统化,Fisac 等(2015,HSCC)进一步推广到时变的动力学、目标与约束。
理论:把布尔问题编码成连续值函数¶
可达性本质是个**布尔问题**(系统到没到危险集),布尔问题不好做连续优化——这正是 §1.1 末尾提到的"类型博弈 vs 程度博弈"。 水平集方法的核心技巧(已在前置桥接里铺垫)是把类型博弈化成程度博弈:用一个 Lipschitz 函数 \(g(x)\) 把目标集 \(\mathcal{T}\) 编码成它的零下水平集,
然后把代价取成纯终端代价 \(J=g(x(0))\)(无运行代价)。 这样"到没到目标"就等价于"终端代价是否 \(\le 0\)",布尔问题被一个连续值函数接管。 下面采用可达性文献的标准约定:时间反向,\(t<0\) 表示"距终端还有 \(|t|\) 时长",系统在 \([t,0]\) 上演化。
后向可达集(BRS):恰好在终点到达¶
设玩家 1(控制 \(a\))想**远离**目标、玩家 2(干扰 \(b\))想**驱入**目标。 BRS 是这样一组初始状态:从中出发,干扰能(用非预期策略)在时刻 \(0\) 把系统送进目标,不管控制怎么努力:
对应的值函数 \(V(x,t)\)(取下值,给干扰瞬时信息优势)是下面 HJI 方程的粘性解:
于是 BRS 就是值函数的零下水平集:\(\mathcal{R}(t)=\{x:V(x,t)\le 0\}\)。 注意 (1.2) 不含任何额外的冻结项——这是"集"的方程。
哈密顿量里 max/min 的取法:一句口诀¶
(1.3) 里 \(\max_a\min_b\) 的取法不是随手定的,由角色决定,这一点必须讲透(它正是下面的陷阱之一)。 规则极简,记住它能省掉无数次符号纠结:
系统性分类(哈密顿量里 max/min 的取法)。 看你对每个玩家问的是"存在"还是"任意": - 求一个控制的**存在性**(\(\exists a\),"只要有一个动作能……")→ 在哈密顿量里对它取 \(\min\)。 - 集合要对该控制的**所有取值**都成立(\(\forall a\),"不管它怎么动……")→ 对它取 \(\max\)。
在 BRS 定义里,我们要"\(\exists\) 干扰 \(b\)"(干扰能驱入)且"\(\forall\) 控制 \(a\)"(不管控制怎么挡),所以哈密顿量是 \(\max_a\min_b\),与 (1.3) 一致。 换一种角色——"\(\exists\) 控制把系统送进好的目标,\(\forall\) 干扰捣乱"——就翻成 \(\min_a\max_b\)。 这套"存在取 min、任意取 max"的口诀对 reach、avoid、reach–avoid 一律适用。
一个能算到底的例子:单积分器的可达管¶
抛开干扰先看最干净的情形。 设一维单积分器 \(\dot x=u\),控制 \(u\in[-1,1]\)(最大速度 1),目标 \(\mathcal{T}=\{|x|\le 1\}\),带符号距离 \(g(x)=|x|-1\)。 这里控制想**到达**目标,所以"\(\exists u\)",哈密顿量取 \(\min\):
直觉上,在时间 \(|t|\) 内,最大速度 1 的系统能覆盖距离 \(|t|\),所以能到达目标的初始状态就是"离目标不超过 \(|t|\)"的那些,即 \(\{|x|\le 1+|t|\}\)。 对应值函数 \(V(x,t)=|x|-1-|t|\)。 验证一下(用下面 BRT 的冻结项方程,因为"在窗内到达"是管):\(\partial_x V=\operatorname{sign}(x)\) 故 \(|\partial_x V|=1\)、\(H=-1\);对 \(t<0\) 有 \(\partial_t V=+1\);于是 \(D_t V+\min[0,H]=1+\min[0,-1]=1-1=0\),且 \(V(x,0)=|x|-1=g(x)\),正确。 可达管 \(\mathcal{R}_{\text{tube}}(t)=\{V\le0\}=\{|x|\le 1+|t|\}\) 随 \(|t|\) 线性扩张,完全符合"速度 × 时间"的直觉。
加上对抗干扰会怎样? 设 \(\dot x=u+d\),控制 \(u\in[-1,1]\) 想远离一个**危险**目标 \(\{|x|\le1\}\)、干扰 \(d\in[-\bar d,\bar d]\) 想把系统推入。
- 若**控制更强**(\(\bar d<1\)):从危险集外的任何点,控制能以净速度 \(1-\bar d>0\) 把系统推开,干扰追不上——有效不安全集不扩张,就是危险集本身 \(\{|x|\le1\}\)。
- 若**干扰更强**(\(\bar d>1\)):干扰能压制控制,以净速度 \(\bar d-1>0\) 把系统拽向危险集——有效不安全集扩张为 \(\{|x|\le 1+(\bar d-1)|t|\}\)。
这个对比把"安全集大小取决于控制与干扰的相对操控权"这件事量化了,也预演了 §1.8 追逃博弈里"谁的操控权强谁占优"的核心。
后向可达管(BRT):在区间内曾经到达¶
安全分析里我们关心的往往不是"恰好在终点出事",而是"在整个时间窗内**有没有任何一刻**出事"。 这就是后向可达**管**:
注意定义里多出来的 \(\exists\,s\in[t,0]\)——只要**某个时刻**进了目标就算。 BRT 对应的方程在 (1.2) 上加一个**冻结项**,保证"一旦进入目标,就永久标记为已到达",从而让零下水平集随时间单调扩张成一根管。 两种等价写法:
或 Mitchell–Tomlin(2005)的原始形式(把哈密顿量整体截断):
两者都实现同一件事:阻止值函数在已进入目标的区域回升,使 \(\{V\le 0\}\) 只增不减——这就是"管"而非"集"。 上面单积分器例子里用的正是 (1.4b)。
集还是管:一个让两者分道扬镳的例子。 前面单积分器里 BRS 和 BRT 恰好重合(因为系统能"走到目标就停下来等"),看不出差别。 换一个会**穿过**目标又出来的系统,两者立刻分道扬镳,冻结项的必要性也就一目了然。 设想一个钟摆/振子式的状态,在相空间里绕圈:从某个初始状态出发,它的轨迹会在 \(t=1\text{s}\) 时**正好扫过**危险集、然后在 \(t=2\text{s}\) 时**已经荡出去**、离危险集很远。 现在问:这个初始状态危险吗?
- 用 BRS("恰好在终点 \(t=2\text{s}\) 是否在危险集内")来判:终点时刻它已经荡出去了,不在危险集内——于是 BRS 判它安全。
- 用 BRT("在 \([0,2\text{s}]\) 内是否曾进入危险集")来判:它在 \(t=1\text{s}\) 穿过了危险集——于是 BRT 判它危险。
对安全验证,该用的是 BRT,道理很直接:撞车是"撞过就算撞",不会因为之后又弹开就当没撞。 那个 \(\min[0,\cdot]\) 冻结项做的正是这件事——它在轨迹首次进入目标的那一刻把值"锁住",不让它随后荡出去时再回升到 0 以上,于是这个"中途穿过"的初始状态被牢牢记在 \(\{V\le0\}\) 里。 没有冻结项的 BRS 方程会让值函数跟着轨迹回升、把这个危险状态"放掉"。
本质洞察:BRS 与 BRT 的全部差别,浓缩在那个冻结项里。 BRS(无冻结项,(1.2))回答"恰好在终点能否到达"; BRT(带冻结项,(1.4))回答"在窗内曾经能否到达"。 安全验证几乎总是要 BRT——因为撞车是"任意时刻撞了都算撞",不是"只看终点撞没撞"。 把 BRS 的方程用到本该用 BRT 的安全分析上,会漏掉那些"中途撞了又弹出去"的危险状态,给出偏乐观、不安全的结论。 这就是文献里 \(\min[0,\cdot]\) 这个看似神秘的项真正的来历,也是下面那条陷阱的实质。
reach–avoid:既要到达又要全程避险¶
很多真实任务不是单纯的"到达"或"避免",而是二者叠加:到达一个目标集 \(\mathcal{T}\),同时全程不进入危险集 \(\mathcal{A}\)。 比如无人机要飞到终点、但途中不能撞障碍;自动驾驶要并入目标车道、但全程不能与他车相撞。 下面不直接抛公式,而是一步步把它的方程搭出来——这能让你看清那个看起来吓人的"双障碍变分不等式"其实只是两件已经会的事拼在一起。
第一步:我们已经有了"到达"的零件。 §1.4 前面的 BRT 变分不等式 (1.4a),处理纯"到达目标 \(\mathcal{T}=\{g\le0\}\)":
回顾它怎么工作:那个 \(\min\{\cdot,\ g-V\}\) 把 \(V\) 封顶**在目标距离 \(g\) 之下(一旦能到达,\(V\) 就掉到 \(\le g\le0\),并被冻住不再回升)。 零下水平集 \(\{V\le0\}\) 因此只增不减,恰是"窗内能到达"的集合。 记住这个结构:**内层的 \(\min\) + 目标项 \(g-V\) = "reach 冻结"。
第二步:加一个"避险"的零件。 现在多一个危险集 \(\mathcal{A}\),用它的带符号距离 \(c(x)\) 编码(沿用标准约定:\(c\le0\) 在 \(\mathcal{A}\) 内、\(c>0\) 在安全区)。 "避险"的要求是:任何最优路径若必须穿过 \(\mathcal{A}\) 才能到达目标,这个起点就不算赢——哪怕它能到达目标,也要被一票否决。 怎么"否决"?让值函数在危险集内被**强行顶高**到正值(这样它就落不进 \(\{V\le0\}\) 这个胜利集)。 实现这件事的,是一个**外层的 \(\max\) + 障碍项 \(-c-V\): 在 \(\mathcal{A}\) 内 \(c\le0\) 故 \(-c\ge0\),外层 \(\max\{\cdot,\ -c-V\}=0\) 会强制 \(V\ge -c\ge0\),把危险集内的点顶成正值、踢出胜利集; 在安全区 \(c>0\) 故 \(-c<0\),这一项是负的、不起作用,交回内层的 reach 冻结管。 记住:**外层的 \(\max\) + 障碍项 \(-c-V\) = "avoid 否决"。
第三步:把两个零件拼起来。 reach–avoid 的值函数满足的,就是"reach 冻结"嵌进"avoid 否决"里的**双障碍变分不等式**(Margellos–Lygeros 2011;Fisac、Chen、Tomlin、Sastry 2015 推广到时变情形):
其中 \(g\) 是目标 \(\mathcal{T}\) 的带符号距离、\(c\) 是危险集 \(\mathcal{A}\) 的带符号距离,二者都用"集合内 \(\le0\)"的标准约定;reach–avoid 集(捕获域)就是 \(\{x:V(x,t)\le0\}\)。 \(H\) 的 \(\max/\min\) 仍按 §1.4 口诀——这里控制争取"存在一条到达且安全的路径"故对控制取 \(\min\)、干扰处处作对取 \(\max\)。
一个一致性检查(确认没记错)。 若根本没有危险集(\(\mathcal{A}=\varnothing\),相当于 \(-c\equiv-\infty\)),外层那一项永远是负无穷、不起作用,(1.4c) 立刻塌回第一步的纯 reach 冻结 (1.4a)——这正说明 (1.4c) 是 BRT 的真正推广,多出来的外层 \(\max\) 就是"避险"这一件事。
本质洞察(双障碍 = 两个方向的"夹"):(1.4c) 看着复杂,本质是从两个方向夹住值函数。 reach 冻结从**上方**把 \(V\) 压向目标(\(V\le g\),鼓励集合朝目标长大); avoid 否决从**下方**把危险区的 \(V\) 顶起来(\(V\ge -c\),把碰障碍的点逐出)。 两个障碍一上一下,夹出的零下水平集,恰好是"能到达且全程安全"的那批起点。 这也是为什么它叫"双障碍(double-obstacle)"——不是两个物理障碍,而是值函数被两个方向的约束同时"挡住"。 Fisac 等用这一个方程,连时变的目标/障碍/动力学都一并处理了,且数值代价与时不变情形几乎一样(用 §1.5 的 WENO 格式即可)。
这是 G2 之后处理"带安全约束的交互"时反复要用的形式,也与 §1.7 的安全 + 到达任务、G4 的安全证书一脉相承。 按口诀,控制对"找到一条既到达又安全的路径"求存在(\(\min\))、干扰处处作对(\(\max\)),(1.4c) 里各项的 max/min 都由这些 \(\exists/\forall\) 逐项定出。 直觉一句话:你可以朝目标推进、到了就算赢,但任何会碰危险集的走法都被提前枪毙。
把本节的三种可达性放到一起,能看清 reach–avoid 在谱系里的位置:纯到达(BRT,"窗内曾到达目标",冻结项锁成功)、纯避险(把危险集当目标算 BRT、取补集得安全集,"全程未进危险集")、reach–avoid(既到达又全程避险,(1.4c) 把到达冻结与避险障碍合进一个方程)。 三者共用同一台机器——HJI 演化 + 水平集——区别只在装了几个、哪种约束项。这也是为什么掌握了 BRS/BRT,reach–avoid 只是"再加一个外层 \(\max\)"而非全新的东西。
前向可达:从初始集出发能到哪¶
到目前讲的都是"后向"——从目标倒推初始状态。 对偶地也有**前向可达集 / 管(FRS / FRT):给定一个初始状态集 \(\mathcal{X}_0\),系统在时长 \(|t|\) 内能到达的所有状态(管则是"曾经到达过的")。 前向问题在求解上与后向几乎一样,只是把终端值 PDE 换成初始值 PDE(两者可经时间变量代换互相转化)。 用途也不同:后向集回答"哪些初始状态危险"(适合安全验证),前向集回答"系统会扩散到哪里"(适合包络分析、碰撞预测、给下游规划划定可行域)。 记住一句话区分:**后向问"从哪来会出事",前向问"从这出发会到哪"。
非预期策略:为什么把信息优势给干扰¶
前面 BRS/BRT 的定义里都出现了"\(\exists\gamma\)"——干扰用一个**非预期策略** \(\gamma\)(§1.2 已引入:它能看到控制到当前时刻为止的动作再回应,但不能预知未来)。 为什么安全验证要把这个瞬时信息优势给干扰,而不是给控制? 因为安全保证要覆盖**最坏情况**。 让干扰"见招拆招",等于假设了一个最难对付的对手; 在这种最悲观的假设下仍判定为安全的状态,才是真的、可信的安全。 这与 §1.2 的 \(\max\min\le\min\max\) 一脉相承:给干扰信息优势取到的是下值,它给出**保守**的安全集。 如果反过来把信息优势给控制,会高估安全集——把一些其实危险的状态误判为安全,这正是下面陷阱之外、§1.2 陷阱 2 警告过的事。
安全集、最优安全控制与"最小限制滤波器"——通往 CBF¶
可达性分析的产物不止一个集合,还附带一个控制器,这一点对工程极其有用。 当目标 \(\mathcal{T}\) 取"危险/不安全状态"、玩家 2 取最坏情况干扰时:
- BRT \(\mathcal{R}_{\text{tube}}(t)\) 是**有效不安全集**——从中出发,干扰能在窗内某刻把系统逼入危险,无论控制怎么挡;
- 它的补集是**安全集**;
- (1.3) 里 \(\arg\max_a\) 给出把系统留在安全集内的**最优安全控制** \(a^*(x,t)\)。
这个安全控制有一个漂亮的"最小限制(least-restrictive)"性质:在安全集**内部**,系统离边界还远,怎么动都安全,控制完全自由;只有当系统逼近安全集**边界**时,\(a^*\) 才介入、把系统推回。
多视角理解(HJI 安全滤波 ↔ CBF 安全滤波)。 这个"平时不管、临界才介入"的最小限制思想,正是控制屏障函数(Control Barrier Function, CBF)安全滤波器的灵魂——后面 G4 与不确定性规划 U2 会专门讲。 相似之处:两者都用一个标量函数刻画安全(HJI 用值函数 \(V\) 的零下水平集 \(\{V\le0\}\) 表示不安全、CBF 用某函数 \(h\) 的零上水平集 \(\{h\ge0\}\) 表示安全),都用这个函数的梯度构造一个"只在边界处约束控制"的滤波器。 事实上,HJI 的安全值函数本身就可以直接当作一个 CBF 用——它的零水平集就是精确的安全边界,\(\nabla V\) 给出约束方向。 不同之处:HJI 值函数是**算出来的精确**安全证书(但受维度诅咒所限,§1.7),CBF 通常是**手工设计的、可能保守**的安全证书(但便宜、可在线求解)。 一句话:CBF 是"廉价、可在线、可能保守"的安全证书,HJI 值函数是"精确但算不动"的安全证书,二者是同一思想在计算代价两端的化身。
BRT ↔ Tube MPC:跨专题的同一根管¶
最后把这根"安全管"接到不确定性规划那一侧。
多视角理解(BRS/BRT ↔ Tube MPC 的 RPI 集)。 这条联系把博弈和不确定性规划接了起来,值得记牢。 不确定性规划里的 Tube MPC,把有界扰动 \(w\in\mathcal{W}\) 当作一个对抗玩家,计算一个鲁棒正不变(Robust Positively Invariant, RPI)集——名义轨迹周围的一根"管子",保证不管扰动怎么取,真实状态都待在管内。 这与 HJI 可达性的 BRT 是同一种思想的两个化身:都把最坏情况干扰建模成对手,都算一根"在干扰下系统必然待在/必然落入的区域"的管。 相似之处:对手即干扰、产物即不变/可达管、目的都是给出可证明的安全保证。 不同之处:Tube MPC 通常在线性/局部、用集合递推(Minkowski 和)高效算,得到的是不变管;HJI 用 PDE 在网格上算,能处理一般非线性、得到的是可达管,但代价是维度诅咒(§1.7)。 一句话:RPI 集是 BRT 在线性鲁棒控制里的高效特例。 (不确定性规划 U2 会从 Tube MPC 那一侧再讲一遍这根管。)
⚠️ 常见陷阱¶
陷阱 1:混淆后向可达集(BRS)与后向可达管(BRT) - 错误描述:把"在终点到达"的 BRS 方程(无冻结项)用到本该问"窗内曾经到达"的安全分析上;或反过来。许多人甚至以为带 \(\min[0,\cdot]\) 的式子算的是 BRS。 - 现象/后果:用 BRS 做安全验证,会漏掉"中途撞了、终点又恰好弹出危险区"的状态,安全集被高估,得到偏乐观甚至致命的结论。 - 根本原因:BRS 只看终端时刻是否在目标内;BRT 看整个时间窗内是否曾进入目标。撞车这类安全事件是"任意时刻发生都算",对应 BRT;\(\min[0,\cdot]\) / 变分不等式里的冻结项正是把"集"变成"管"的机制。 - 正确做法:安全验证一律用 BRT(带冻结项的 (1.4))。检验方法:问"我关心的坏事是'只在终点发生才算',还是'窗内任何时刻发生都算'?"——后者就必须用 BRT。
陷阱 2:哈密顿量里 max/min 取反(reach 与 avoid 搞混) - 错误描述:不区分玩家角色,凭习惯把哈密顿量写成 \(\min_a\max_b\) 或 \(\max_a\min_b\),赌对一半。 - 现象/后果:算出的可达集张错了方向——本该收缩的在扩张,安全集和危险集对调,可视化出来"看着像那么回事"却完全错误,且极难自查。 - 根本原因:max/min 的取法由"对每个玩家问存在还是任意"唯一决定,弄反等于把控制和干扰的角色互换,求的是另一个完全不同的博弈。 - 正确做法:套用"存在取 \(\min\)、任意取 \(\max\)"的口诀,先写清可达集定义里每个玩家是 \(\exists\) 还是 \(\forall\),再据此定哈密顿量。检验方法:把干扰强度调到 0,看可达集是否退化为单人最优控制的可达集(如前面单积分器例子退化为 \(\{|x|\le1+|t|\}\))——若方向不对,多半是 max/min 取反了。
练习¶
- (精读 + 推导,B 型) 精读 Mitchell–Bayen–Tomlin(2005)的可达性表述部分,自己重走一遍"可达集 ↔ HJI 零下水平集"的等价论证。重点回答:为什么 BRT 要用 \(\min[0,\cdot]\)(或等价的变分不等式)这个截断/冻结项,而 BRS 不用?把这与"避免进入"的语义对应起来,并与本节单积分器例子的验证对照。
- (跨专题思考题) HJI 可达性(零和博弈)和不确定性规划里的 Tube MPC 在概念上是什么关系?请论证:"Tube MPC 把有界扰动 \(w\in\mathcal{W}\) 当作一个对抗玩家,它的 RPI 不变集 ≈ HJI 的后向可达管。"指出这个类比成立的地方,以及它在哪里会失效(提示:从动力学是否线性、集合如何表示两个角度想)。
- (角色辨析 + reach–avoid) 对"无人机要在窗内**始终**待在一个安全走廊内、同时**最终**到达终点"这一 reach–avoid 任务,写出你会对控制和干扰分别问"存在"还是"任意",据此定出哈密顿量里每个 \(\min/\max\) 的取法。你需要 BRS、BRT,还是 reach–avoid 的组合?说明理由,并解释障碍项在这里起什么作用。
§1.5 水平集数值方法:WENO 与 TVD-RK ⭐⭐⭐¶
这一节解决什么问题:HJI 方程有了(§1.2)、粘性解唯一了(§1.3)、可达集表述清楚了(§1.4),但这些都还在纸上。 这一节交代怎么在计算机上把 HJI 方程真正算出来——以及为什么"随便挑个差分格式"会算出被 §1.3 否决的假解。
动机:从连续 PDE 到网格上的数值演化¶
HJI 方程 (1.2) 是连续状态空间上的偏微分方程,计算机没法直接处理连续对象。 标准做法是把状态空间划成网格,在每个网格点上存一个值 \(V\),把 PDE 的时间演化离散成一步步的更新——从终端条件 \(V(x,0)=g(x)\) 出发,沿时间负方向一步步推回去,每一步用相邻网格点的值近似空间梯度 \(\nabla V\)、算出哈密顿量、更新这一点的值。 听起来很直接,难点全在"怎么近似 \(\nabla V\)"和"怎么走时间步"——因为 §1.3 告诉我们值函数有不可微的棱,天真的近似会在棱处崩掉。
反面案例:天真的中心差分会怎样¶
最自然的想法是用中心差分近似梯度:\(\partial_x V\approx (V_{i+1}-V_{i-1})/(2\Delta x)\)。 在光滑区域这没问题,但在值函数的棱附近(§1.3),中心差分会产生剧烈的**伪振荡**: 它"看不见"间断的方向性,把棱两侧的信息对称地搅在一起,导致数值解在棱附近上下抖动、长出毛刺,可达集边界变得锯齿化甚至断裂。 更糟的是,不带耗散的格式可能收敛到一个**几乎处处满足方程、却不是粘性解**的假解——正是 §1.3 里 eikonal 的 \(|x|-1\) 那类被否决的解。 方程本身选不出正确解,数值格式也一样:格式必须"尊重粘性",才能收敛到对的那个。
理论:尊重粘性的数值格式¶
数值哈密顿量与迎风思想。 要让格式稳定且收敛到粘性解,关键是用**带方向性、带数值耗散**的格式构造一个**数值哈密顿量** \(\hat H\) 去近似 \(H(x,\nabla V)\)。 最基础的是 Lax–Friedrichs 型数值哈密顿量:它在中心差分的基础上人为加一个正比于梯度跳变的耗散项,
其中 \(p^\pm\) 是从两侧估计的梯度、\(\alpha\) 是与哈密顿量对梯度的敏感度(最大特征速度)相关的耗散系数。 那个 \(-\tfrac{\alpha}{2}(p^+-p^-)\) 项就是数值耗散:它在梯度有跳变(棱)的地方自动加阻尼,把伪振荡压下去。
本质洞察(数值耗散 = 消失黏性的离散身影)。 这里加的数值耗散项,正是 §1.3 里"消失黏性"\(\varepsilon\Delta V\) 的离散版本。 §1.3 用"加无穷小扩散再取极限"在理论上挑出粘性解;数值格式用"加一点正比于网格的耗散"在计算上逼近同一个粘性解。 网格越细,等效的 \(\varepsilon\) 越小,数值解越接近真正的粘性解。 相似之处:两者都靠"受控的扩散"把棱磨光、把假解排除。 不同之处:理论里 \(\varepsilon\to 0\) 是取极限,数值里耗散量由网格步长决定、不能真取 0(否则振荡回来)。 这条对应是理解"为什么单调格式收敛到粘性解"的钥匙——收敛到粘性解,不是格式的幸运巧合,而是它内建的数值耗散在兑现 §1.3 的黏性极限。
空间离散:WENO5。 Lax–Friedrichs 只有一阶精度,在光滑区域太耗散(把本该锐利的特征也磨钝了)。 工程上用高阶的**加权本质无振荡格式(Weighted Essentially Non-Oscillatory, WENO)——helperOC 等工具默认用五阶 WENO(WENO5)。 WENO 的核心思想:估计某点梯度时,不固定用一组网格点,而是从几组候选模板里**按光滑度自适应加权——在光滑区给所有模板高权重(达到高阶精度),在棱附近自动给"跨过间断"的模板几乎零权重(避免把间断信息搅进来)。 这就是"本质无振荡":高阶精度与棱处不振荡两者兼得。
把 WENO 的思路拆慢一点。 为什么需要这么个东西,循序渐进地看就清楚了。 要点是一个**两难**:估计梯度时,用到的网格点越多(模板越宽),在光滑区域精度越高(这是好事);但模板一旦"跨过"一道棱,就会把棱两侧本不该混的信息搅在一起,产生伪振荡(这是坏事)。 固定用宽模板 → 高精度但棱处振荡;固定用窄模板 → 棱处稳但精度低。 怎么两全?分三步走:
- 先给出几组候选模板。对要估梯度的那个点,准备几组不同的相邻网格点组合(比如偏左的、居中的、偏右的)。每组都能给一个梯度估计,但它们"看"的是不同侧的数据。
- ENO 的想法——只挑最光滑的一组。早期的 ENO(Essentially Non-Oscillatory)格式:哪组候选模板覆盖的数据最光滑(没跨过棱),就用哪组,丢掉其余。这样自动避开了跨棱的模板,棱处不振荡。代价:硬性二选一,浪费了其他模板的信息,精度没拉满。
- WENO 的改进——按光滑度加权混合。WENO(Weighted ENO)不做非黑即白的选择,而是给每组模板算一个**光滑度指标**,据此分配权重:光滑的模板给大权重、跨棱的给近乎零的权重,再把各组估计加权平均。 于是在光滑区域所有模板都被"信任"、加权后达到高阶精度(五阶就是 WENO5);在棱附近跨棱的那组被自动压成零权重、退化为只用光滑侧的低阶估计但稳定不振荡。
多视角理解(WENO 的自适应加权 ↔ 鲁棒统计里的加权)。 WENO"按光滑度给模板分权重、把异常的那组压到near-zero"这招,和鲁棒统计里"按残差给样本分权重、把离群点压低"是同一种智慧。 相似之处:都在"我有几个来源、其中某些被污染(跨棱 / 离群),该信谁多一点"的问题上,用一个连续权重而非硬性取舍来兼顾精度与稳健。 不同之处:WENO 的"污染"是几何的(模板跨过间断),权重由光滑度指标定;鲁棒统计的"污染"是数据的,权重由残差定。 看懂这个类比,就不会把 WENO 当成一堆神秘系数,而是"对若干梯度估计做稳健加权融合"。
时间推进:TVD-RK3。 空间离散后,HJI 变成一个关于网格值向量的常微分方程组,需要时间积分器往回推。 直接用高阶 Runge–Kutta 可能引入振荡,所以用**总变差不增(Total Variation Diminishing, TVD)的三阶 Runge–Kutta(TVD-RK3,又称 SSP-RK3)**。 它的设计保证:只要每个子步是稳定的(不增加解的总变差),三阶组合后整体也不增加总变差——即时间方向上也"不无中生有地长出振荡",与空间的 WENO 配合,全程保持非振荡。
CFL 条件:时间步不能太大。 显式时间推进有个硬约束——CFL(Courant–Friedrichs–Lewy)条件:一个时间步内,信息在数值上传播的距离不能超过一个网格格子,否则格式发散。 形式上 \(\Delta t\lesssim \Delta x/\alpha\)(\(\alpha\) 是最大特征速度)。 直觉:物理信息以有限速度传播,数值格式每步只能"看"到相邻格点,若 \(\Delta t\) 太大、真实信息在一步内越过了好几个格子,格式就跟丢了、爆掉。 所以网格越细(\(\Delta x\) 越小),允许的 \(\Delta t\) 越小,步数越多——这是细网格代价的一部分。
helperOC 的数据流:一次 HJI 求解长什么样¶
把上面的零件串起来,看可达性工具(如 helperOC,MATLAB,基于 Mitchell 的 Level Set Toolbox)求一次 BRS/BRT 的概念流程。 这里只走数据流、不贴大段代码(具体接口见 §1.8 与练习中的精读任务):
- 定义网格:在状态空间的关心区域上铺一个均匀网格(每维若干格点),决定分辨率。
- 定义动力学:给出 \(\dot x=f(x,a,b)\) 与控制/干扰的取值范围 \(a\in A,\,b\in B\)(如追逃的
Air3D动力学,§1.8)。 - 定义目标:把目标集 \(\mathcal{T}\) 编码成初值 \(V(x,0)=g(x)\)(带符号距离)。
- 设置数值哈密顿量与角色:按 §1.4 的口诀确定 \(\max_a\min_b\) 还是 \(\min_a\max_b\),构造 \(\hat H\);选 BRS(无冻结)还是 BRT(带 \(\min[0,\cdot]\) 冻结项)。
- 时间步进 + 提取水平集:用 WENO5 + TVD-RK3 沿时间负方向推进到所需时长 \(|t|\),最后取零下水平集 \(\{V\le0\}\) 作为 BRS/BRT,并可由 \(\arg\max_a\) 同时导出安全控制器。
用 hj_reachability 实跑一次:Air3D 的 BRT¶
前面都是原理,这里看这一领域**最现代、最干净的开源工具之一**怎么把它跑起来。 hj_reachability(Stanford ASL,JAX 实现,helperOC 的现代继任者)专门求解零和微分博弈的 HJI-PDE,把可达集表示成值函数粘性解的零下水平集——和本章 §1.4–§1.5 的表述逐字对应。 下面用它算 §1.8 那个 Air3D 追逃的后向可达管,顺带把 §1.5 的概念落到 API 上(接口以 hj_reachability 当前官方文档为准):
import jax.numpy as jnp
import hj_reachability as hj
# 1) 动力学:Air3D(库内置)。追捕机/逃逸机各以固定速度飞、转弯率有界。
# 相对坐标 (x, y, ψ),正是 §1.8 的三维相对动力学——避免绝对坐标的 6 维。
dynamics = hj.systems.Air3d(
evader_speed=5.0, pursuer_speed=5.0,
evader_max_turn_rate=1.0, pursuer_max_turn_rate=1.0)
# 2) 网格:在相对状态空间铺均匀网格。第 2 维 ψ 是角度,取周期边界(绕一圈相接)。
grid = hj.Grid.from_lattice_parameters_and_boundary_conditions(
hj.sets.Box(lo=jnp.array([-6., -10., 0.]),
hi=jnp.array([20., 10., 2 * jnp.pi])),
(51, 41, 50),
periodic_dims=2)
# 3) 初值 = 到碰撞圆盘 {x²+y²≤R²} 的带符号距离(§1.4 的水平集编码)。
R = 5.0
initial_values = jnp.linalg.norm(grid.states[..., :2], axis=-1) - R
# 4) 求解器设置。"very_high" 精度 ≈ 高阶 WENO 空间离散(§1.5);
# backwards_reachable_tube 后处理就是 (1.4b) 那个 min[0,·] 冻结项——把"集"变"管"。
solver_settings = hj.SolverSettings.with_accuracy(
"very_high",
hamiltonian_postprocessor=hj.solver.backwards_reachable_tube)
# 5) 从 t=0 反向积分到 t=-T(时间推进内部用 TVD-RK,自动满足 CFL)。
T = 2.8
target_values = hj.step(solver_settings, dynamics, grid,
0.0, initial_values, -T)
# BRT(逃逸机无法避免被捕获的相对位形)= {x : target_values(x) ≤ 0}
把这段和 §1.5 的原理对一遍,能看清"理论概念 ↔ 库参数"的一一对应:
| 代码里的东西 | 对应本章的概念 |
|---|---|
initial_values = ‖·‖ - R |
§1.4 把目标集编码成带符号距离的零下水平集 |
with_accuracy("very_high") |
§1.5 的高阶 WENO 空间离散(非振荡、棱处不冒毛刺) |
hamiltonian_postprocessor=backwards_reachable_tube |
(1.4b) 的 \(\min[0,\cdot]\) 冻结项——选 BRT(管)而非 BRS(集) |
periodic_dims=2 |
§1.8 相对朝向 \(\psi\) 是角度,绕一圈相接 |
hj.step(..., 0.0, ..., -T) |
从终端沿时间负方向积分(TVD-RK 内部保证 CFL) |
target_values ≤ 0 |
取零下水平集得到可达管 |
本质洞察(理论与工具的同构):一个好的可达性库不是把理论"封装掉",而是把理论的每个部件**暴露成一个可调参数**——你选的精度档对应 WENO 的阶、你挑的后处理对应 BRS/BRT 的冻结项、你给的初值对应目标集的水平函数。 看懂这段代码的前提,恰恰是看懂 §1.4–§1.5;反过来,跑通这段代码也最能巩固那些抽象概念。 这也是为什么本章先讲透原理、再给工具:工具是原理的接口,不是替代品。
从零写一个最小可达性求解器¶
成熟工具好用,但"会调库"不等于"懂数值"。 下面用**纯 NumPy、零依赖**从头写一个一维可达性求解器,把 §1.5 的 Lax–Friedrichs 数值哈密顿量、CFL、冻结项全落成几行能跑的代码,并用 §1.4 的解析解 BRT \(=\{|x|\le 1+T\}\) 检验它对不对。 对象就是 §1.4 那个单积分器 \(\dot x=u,\ u\in[-1,1]\),目标 \(\{|x|\le 1\}\),控制争取到达。 BRT 的"时间-到-达"形式是 \(V_\tau=-|V_x|\)(零下水平集以单位速度向外扩),用 Lax–Friedrichs 离散:
import numpy as np
# 一维单积分器 ẋ=u, u∈[-1,1];目标 {|x|≤1};算时长 T 的 BRT。
# HJI(BRT) 的时间-到-达形式:V_τ = -|V_x|({V≤0} 以单位速度向外扩)。
xs = np.linspace(-6.0, 6.0, 1201)
dx = xs[1] - xs[0]
V = np.abs(xs) - 1.0 # 初值 = 到目标的带符号距离 g(x)=|x|-1(§1.4)
T, alpha = 3.0, 1.0 # 时长;α = max|∂H/∂p| = 1(最大特征速度)
dt = 0.4 * dx / alpha # CFL:dt ≲ dx/α,取 0.4 倍裕量(§1.5)
for _ in range(int(T / dt)):
pm = np.empty_like(V); pp = np.empty_like(V)
pm[1:] = (V[1:] - V[:-1]) / dx; pm[0] = pm[1] # 左差分 p⁻
pp[:-1] = (V[1:] - V[:-1]) / dx; pp[-1] = pp[-2] # 右差分 p⁺
pc = 0.5 * (pm + pp) # 中心梯度
# Lax–Friedrichs 数值哈密顿量:|V_x|_LF = |pc| - (α/2)(pp - pm)
# 后一项是数值耗散 = §1.3 消失黏性 εΔV 的离散身影,在尖点处加阻尼防振荡
Vx_LF = np.abs(pc) - 0.5 * alpha * (pp - pm)
V = V - dt * Vx_LF # V_τ = -|V_x|,推进一步
# 注:本例 H = -|V_x| ≤ 0,(1.4b) 的 min[0,H] 冻结项恒不激活(集合本就只增);
# 在 avoid(安全)问题里,正是该冻结项阻止安全集回缩——见 §1.4 陷阱 1。
lo, hi = xs[V <= 0].min(), xs[V <= 0].max()
print(f"数值 BRT ≈ [{lo:.2f}, {hi:.2f}];解析解 = [-{1+T:.0f}, {1+T:.0f}]")
# 典型输出:数值 BRT ≈ [-3.99, 3.99];解析解 = [-4, 4]
短短二十几行,把 §1.5 的三件套都跑了一遍:
中心梯度 + 那个 \(-\tfrac{\alpha}{2}(p^+-p^-)\) 耗散项就是 Lax–Friedrichs 数值哈密顿量(在 \(x=0\) 的尖点处加阻尼,对应 §1.3 的消失黏性);
dt = 0.4*dx/alpha 就是 CFL;
注释里点明的 min[0,H] 冻结项在这个 reach 例子里恰好不激活,但换成 avoid(安全)问题它就是阻止安全集回缩的关键。
跑出来的数值 BRT \([-3.99,3.99]\) 与解析解 \([-4,4]\) 吻合到网格精度——这既验证了代码,也验证了 §1.4 那个"\(\{|x|\le 1+T\}\)"的手算。
多视角理解(手写求解器 ↔ 成熟库):上面 hj_reachability 那段和这段从零写的,是理解 §1.5 的两条互补路径。 相似之处:内核完全一样——都是"带耗散的数值哈密顿量 + 满足 CFL 的时间推进 + 零下水平集"。 不同之处:库做的是高维、高阶(WENO)、GPU 加速、多种动力学的工程化版本,而这段手写的只处理一维、用最简单的 Lax–Friedrichs,但**每一行都看得见**。 建议的学习顺序:先用手写版把"为什么要耗散、CFL 是什么、冻结项干嘛的"彻底搞懂,再去用库跑高维问题——这样调库时你知道每个参数背后对应着哪段数值机制。
工程权衡:分辨率、内存与时间¶
水平集方法精确、能处理一般非线性、自带安全控制器——但它在网格上算,代价直接由网格规模决定。
| 旋钮 | 调高的收益 | 调高的代价 |
|---|---|---|
| 空间分辨率(每维格点数 \(N\)) | BRS 边界更精确、棱更锐利 | 内存与每步计算量按 \(N^d\)(\(d\) 为维数)增长 |
| 时间精度(步数) | 演化更准、CFL 更安全 | 步数随 \(\Delta t\) 减小而线性增加 |
| 维数 \(d\) | 能处理更复杂系统 | 指数爆炸:\(N^d\) 个网格点 |
前两行是常规的"精度换算力"权衡。 真正的拦路虎是最后一行的**维数 \(d\):网格点数 \(N^d\) 随维数指数增长,\(N=50\)、\(d=6\) 就是 \(50^6\approx 1.5\times10^{10}\) 个点,内存与时间都到了单机极限。 这就是 helperOC 这类网格法被卡在约 6 维的根本原因,也正是 §1.7 要正面处理的**维度诅咒——以及 §1.6 那条"退而用局部 LQ 近似"路线(G2)之所以必要的理由。
⚠️ 常见陷阱¶
陷阱 1:用不带耗散的格式(如纯中心差分)解 HJI - 错误描述:图省事或图"高精度",用中心差分近似梯度、用普通 RK 推进时间。 - 现象/后果:在值函数的棱附近出现伪振荡,可达集边界长毛刺、断裂;严重时收敛到一个几乎处处满足方程、却不是粘性解的假解,安全判断完全错误。 - 根本原因:HJI 值函数有不可微的棱(§1.3),不带方向性/耗散的格式无法正确处理间断,且不"尊重粘性",于是收敛不到正确的粘性解。 - 正确做法:用为粘性解设计的单调/本质无振荡格式——WENO5(空间)+ TVD-RK3(时间)+ 合适的数值哈密顿量(如 Lax–Friedrichs 型耗散)。检验方法:加密网格,看 BRS 边界是否收敛、是否仍光滑无毛刺。
陷阱 2:违反 CFL 条件,时间步取太大 - 错误描述:为了少跑几步、加快计算,把 \(\Delta t\) 设得很大。 - 现象/后果:数值解发散——值函数出现爆炸性的大数甚至 NaN,可达集面目全非。 - 根本原因:显式格式每步只能传播一个格子的信息,\(\Delta t\) 太大时真实信息越过多个格子,格式跟丢、不稳定。 - 正确做法:让 \(\Delta t\lesssim \Delta x/\alpha\)(\(\alpha\) 为最大特征速度),网格加密时同步减小 \(\Delta t\);多数工具会自动按 CFL 选步长,自己写格式时务必加这个约束。检验方法:若细化网格后突然发散,先查 \(\Delta t\) 是否随 \(\Delta x\) 同步减小。
练习¶
- (概念联系,回扣 §1.3) 用自己的话说明:为什么"加数值耗散的单调格式"会收敛到粘性解,而中心差分不会?把它和 §1.3 的"消失黏性 \(\varepsilon\Delta V\)、取 \(\varepsilon\to0\)"对应起来——数值里的 \(\varepsilon\) 大致相当于什么量?
- (估算维度诅咒) 估算用每维 50 格点的均匀网格存储一个 6 维 HJI 值函数需要多少个网格点、多少内存(设每点一个 8 字节 double)。若提到 8 维呢?由此说明为什么 helperOC 卡在约 6 维。
- (数值实验,A 型) 用任一可达性工具(helperOC / optimized_dp / hj_reachability)对一个 2D 系统(如 §1.4 的单积分器升到 2D,或 §1.8 的 Air3D)算 BRT。把空间分辨率从粗到细跑几档,观察 BRS 边界如何收敛;再故意把 \(\Delta t\) 调大违反 CFL,记录发散现象。
§1.6 LQ 博弈与耦合 Riccati ⭐⭐⭐ ★ 本章最关键¶
这一节解决什么问题:HJI 给出全局最优却算不动(§1.5 已点明维度诅咒,§1.7 还会正面展开)。 这一节问:如果动力学是线性的、代价是二次的,博弈能不能像单人 LQR 那样闭式求解? 答案是能——代价是从"一条 Riccati"变成"\(N\) 条耦合的 Riccati"。 这一节是从"理论最优"退让到"可算"的关键一步,更是 G2 中 iLQGames 每一步迭代所解的子问题。 整章若只精读一节,就是这一节。
动机:唯一能闭式求解的博弈,也是局部近似的归宿¶
一般非线性微分博弈没有解析解,只能靠 §1.5 的网格法硬算,又被维度诅咒卡死。 但有一个特例能闭式求解——线性二次(LQ)博弈:动力学线性、每人代价二次。 它之所以重要,有两层:
第一,它本身可解,给出反馈 Nash 均衡的闭式表达。 第二,也是更深的一层——任何光滑的微分博弈,都能在一条名义轨迹附近局部近似成一个 LQ 博弈(动力学一阶 Taylor 展开成线性、代价二阶展开成二次)。 这正是 G2 中 iLQGames 的核心套路:反复地"线性化—二次化—解一个 LQ 博弈—更新轨迹",直到收敛。 所以本节解的这组耦合 Riccati,就是 iLQGames 每一步迭代里那个被反复求解的内核。 打通了它,G2 的实时博弈求解才有根。
提醒一句:与本章前几节的零和设定不同,LQ 博弈这里是**一般和**——每个玩家有自己的 \(Q_i,R_i\),目标不必对立。 这正是 §1.1 预告过的"本章中的一般和例外",它放在这里是因为与 G2 无缝衔接,而非因为属于零和理论。
反面案例:多人 LQ 就是各自解一个 LQR?¶
一个很自然、却错得很彻底的想法是:"既然每人都是线性二次,那让每个玩家各自解一个标准 LQR、各拿各的反馈增益不就行了?" 这忽略了博弈的耦合:玩家 \(i\) 面对的"系统",其动力学里含着别人的控制 \(u_j\)——而别人的 \(u_j\) 又是别人反馈增益的产物。 你按"别人不动"去解自己的 LQR,得到的增益在别人也按最优反馈行动时**根本不是最优响应**,于是它不构成纳什均衡。 正确的做法必须把所有玩家的最优性条件**联立**求解——这就逼出了"耦合"的 Riccati。
理论:N 人 LQ 博弈与反馈 Nash¶
问题设定。 \(N\) 个玩家共享线性动力学,每人有自己的控制输入:
玩家 \(i\) 最小化自己的二次代价(这里取只惩罚自身控制的常见形式):
反馈 Nash 均衡。 我们找**反馈**策略 \(u_i=-K_i(t)\,x\)(依赖当前状态,不是开环的时间函数)——§1.2 强调过反馈策略有天然的扰动拒绝能力,也是 iLQGames 输出的形式。 "反馈 Nash"的含义:在所有其他玩家的反馈增益 \(K_j\,(j\ne i)\) 固定时,\(K_i\) 是玩家 \(i\) 的最优反馈。 每个玩家的值函数取二次形式 \(V_i(x,t)=\tfrac12 x^\top P_i(t)\,x\),\(P_i\succeq0\) 待定。
推导耦合 Riccati。 固定其他玩家的策略 \(u_j=-K_j x\,(j\ne i)\),玩家 \(i\) 面对的是一个**修正过的**线性系统:
这下玩家 \(i\) 的问题退化成一个标准单人 LQR——系统矩阵 \(\tilde A_i\)、输入矩阵 \(B_i\)、代价权重 \(Q_i,R_{ii}\)。 单人 LQR 的解我们在前置桥接里复习过:最优反馈 \(K_i=R_{ii}^{-1}B_i^\top P_i\),其中 \(P_i\) 解关于 \((\tilde A_i,B_i,Q_i,R_{ii})\) 的 Riccati 方程
现在把 \(\tilde A_i=A-\sum_{j\ne i}B_jK_j=A-\sum_{j\ne i}S_jP_j\) 代回(记 \(S_j:=B_jR_{jj}^{-1}B_j^\top\),对称半正定),展开那两个含 \(\tilde A_i\) 的项:
代回整理,就得到玩家 \(i\) 的 耦合 Riccati 方程(反馈 Nash,有限时域微分形式):
闭环动力学则是 \(\dot x=\big(A-\sum_j S_jP_j\big)x\)。 对所有 \(i=1,\dots,N\),(1.5) 是一组**相互耦合**的矩阵微分方程:从终端 \(P_i(T)=Q_i^f\) 出发,沿时间负方向**同时**反向积分这 \(N\) 条方程,每一步每条方程都要用到所有其他 \(P_j\)。
为什么"耦合"。 看 (1.5) 里那个求和项 \(-\sum_{j\ne i}(P_jS_jP_i+P_iS_jP_j)\)——它把玩家 \(i\) 的 \(P_i\) 和所有别人的 \(P_j\) 缠在了一起。 玩家 \(i\) 的最优反馈依赖别人的反馈(通过 \(\tilde A_i\) 里的 \(\sum_{j\ne i}S_jP_j\)),别人的又依赖 \(i\) 的,循环往复。 所以这 \(N\) 条方程不能各解各的,必须当成一个整体同时求解。
把两人情形写全:交叉项逐项现身。 一般式 (1.5) 看着密,把它落到 \(N=2\) 写全,就能看清交叉项是怎么从单人 Riccati 里"长"出来的。 两条方程是:
把第一条逐段读: 前半截 \(A^\top P_1+P_1A+Q_1-P_1S_1P_1\) **就是**前置桥接里那条标准单人 Riccati——如果玩家 2 不存在,玩家 1 解的恰好是它。 后半截 \(-(P_2S_2P_1+P_1S_2P_2)\) 是玩家 2 一出现就冒出来的修正项,它从哪来? 回到推导:玩家 1 面对的不是原系统 \(A\),而是被玩家 2 反馈改写过的 \(\tilde A_1=A-S_2P_2\)(这里 \(S_2P_2=B_2K_2\) 正是玩家 2 的反馈作用)。 把 \(\tilde A_1\) 代进 \(\tilde A_1^\top P_1+P_1\tilde A_1\) 并减去原来的 \(A^\top P_1+P_1A\),多出来的正是
(用了 \(S_2\) 对称、\((S_2P_2)^\top=P_2S_2\))——这就是那个交叉项的全部来历。 一句话:交叉项 = "对手的反馈改写了我的系统矩阵"留下的痕迹。 两条方程通过各自的交叉项把 \(P_1,P_2\) 钩在一起,于是必须联立——这就是"耦合"二字最具体的样子。
本质洞察:耦合 Riccati = \(N\) 条单人 Riccati 被那些交叉项 \(P_jS_jP_i\) 相互纠缠在一起。 把交叉项去掉,(1.5) 就退化成 \(N\) 条互不相干的标准 Riccati——那对应"每人当别人不存在、各解各的 LQR"的错误做法。 正是那些交叉项,把"各自最优"修正成了"互为最优响应"。 换句话说,这个纠缠就是"纳什均衡"在线性世界里的数学化身——均衡的本质(我的最优依赖你的最优)被精确地编码进了交叉项。
对比性思维(单人 Riccati vs N 人耦合 Riccati)。 单人 LQR 的 Riccati:\(-\dot P=A^\top P+PA+Q-PSP\),一条方程、自洽、在可镇定性下必有解。 N 人耦合 Riccati (1.5):多了交叉项 \(-\sum_{j\ne i}(P_jS_jP_i+P_iS_jP_j)\),\(N\) 条方程相互依赖、必须联立。 差别就在这些交叉项上——它们是"博弈"相对"最优控制"的全部线性增量。 一个关键后果:单人 Riccati 的解在温和条件下保证存在,耦合 Riccati 的解却不保证存在。 交叉项可能导致反向积分在有限时间内发散(finite escape),即便每个玩家单独的 LQR 都好端端有解。 所以用 (1.5) 时必须检查解是否存在、是否在整个时域上有界,不能想当然。
一个能算到底的例子:两人标量 LQ 博弈¶
把 (1.5) 落到最小的可解例子。 设标量状态 \(x\in\mathbb{R}\),两个玩家:
记 \(s_i=b_i^2/r_i\)。 看**稳态**(无穷时域,令 \(\dot P_i=0\),\(P_i\to p_i\) 为标量常数),(1.5) 化为两条耦合的代数方程:
取**对称情形**(\(q_1=q_2=q\),\(s_1=s_2=s\),由对称性 \(p_1=p_2=p\))一条方程就够:
解得(取正根)\(p=\dfrac{a+\sqrt{a^2+3sq}}{3s}\)。
对照**单人 LQR**(玩家 1 当玩家 2 不存在,即去掉交叉项 \(2s_2p_2p_1\)):
两者明显不同:博弈解的分母是 \(3s\)、根号里是 \(a^2+3sq\),比单人解小。 物理含义:当两个玩家都在用各自的控制影响同一个状态、各自承担二次代价时,每人"愿意"施加的控制力度(增益 \(\propto p\))比"独占系统"时更克制——因为对方也在使劲,过度用力既浪费自己的代价、又被对方部分抵消。 均衡是双方"互相迁就"后的不动点,而非各自的最优。 存在性方面:此例判别式 \(a^2+3sq>0\) 恒成立(\(s,q>0\)),故实解总存在;但换成非对称权重或有限时域、特定 \(Q_i\),耦合方程可能无解或反向积分发散——这正是上面本质洞察里强调的、单人 LQR 没有的麻烦。
参考实现:耦合 Riccati 反向积分器¶
把 (1.5) 写成能跑的代码,是项目甲 G1 模块的标准答案,也是理解 iLQGames 内核最直接的方式。 下面给一个**自包含、可直接运行**的两人版参考实现(NumPy + SciPy),关键行都注明在做什么、对应公式哪一项。 项目甲要求的是 Eigen/C++ 版本(见练习 1),这里先给等价的 Python 参考便于理解与验证,C++ 移植留作那个模块——逻辑一字不差。
import numpy as np
from scipy.integrate import solve_ivp
def coupled_riccati_2p(A, B1, B2, Q1, Q2, R1, R2, Qf1, Qf2, T, N=400):
"""两人有限时域 LQ 博弈的反馈 Nash 耦合 Riccati 求解(公式 (1.5)–(1.6))。
动力学: ẋ = A x + B1 u1 + B2 u2
代价 i: Ji = ∫₀ᵀ (xᵀ Qi x + uiᵀ Ri ui) dt + xᵀ(T) Qfi x(T)
返回: 真实时间网格 ts、P1(t)/P2(t)、反馈增益 K1(t)/K2(t)(策略 ui = -Ki x)
"""
n = A.shape[0]
S1 = B1 @ np.linalg.solve(R1, B1.T) # S_j = B_j R_jj^{-1} B_jᵀ(对称半正定)
S2 = B2 @ np.linalg.solve(R2, B2.T)
def deriv(tau, y):
# 用 τ = T - t 把"反向积分"变成 SciPy 的正向积分:dPi/dτ = -Ṗi = RHSi
P1 = y[:n * n].reshape(n, n)
P2 = y[n * n:].reshape(n, n)
# RHS1 = AᵀP1 + P1 A + Q1 - P1 S1 P1 - (P2 S2 P1 + P1 S2 P2) ← (1.5) 玩家1
dP1 = A.T @ P1 + P1 @ A + Q1 - P1 @ S1 @ P1 - (P2 @ S2 @ P1 + P1 @ S2 @ P2)
# RHS2 = AᵀP2 + P2 A + Q2 - P2 S2 P2 - (P1 S1 P2 + P2 S1 P1) ← (1.5) 玩家2
dP2 = A.T @ P2 + P2 @ A + Q2 - P2 @ S2 @ P2 - (P1 @ S1 @ P2 + P2 @ S1 @ P1)
return np.concatenate([dP1.ravel(), dP2.ravel()])
y0 = np.concatenate([Qf1.ravel(), Qf2.ravel()]) # τ=0 ↔ 真实终端 t=T,Pi(T)=Qfi
taus = np.linspace(0.0, T, N)
sol = solve_ivp(deriv, (0.0, T), y0, t_eval=taus, rtol=1e-9, atol=1e-11)
if not sol.success: # 反向发散 = 耦合 Riccati 无界解
raise RuntimeError("耦合 Riccati 反向积分发散:解可能不存在(§1.6 陷阱 2)")
ts = T - taus # 换回真实时间(从 T 递减到 0)
P1 = sol.y[:n * n].T.reshape(-1, n, n)
P2 = sol.y[n * n:].T.reshape(-1, n, n)
K1 = np.stack([np.linalg.solve(R1, B1.T @ P) for P in P1]) # (1.6): Ki = Ri^{-1} Biᵀ Pi
K2 = np.stack([np.linalg.solve(R2, B2.T @ P) for P in P2])
return ts, P1, P2, K1, K2
几处值得停下来看的设计:
- 反向变正向:Riccati 是终端值问题(给 \(P_i(T)\) 倒推),代码用 \(\tau=T-t\) 的换元把它变成从 \(\tau=0\) 正向积分(初值就是终端权重 \(Q_i^f\)),于是能直接喂给标准正向积分器
solve_ivp。这是数值上处理终端值 ODE 的标准技巧。 - 交叉项就是博弈:
deriv里-(P2 S2 P1 + P1 S2 P2)这一项,正是 §1.6 本质洞察里说的"把两人的 \(P\) 纠缠起来"的耦合项。把它删掉,两条方程立刻解耦成各自独立的单人 Riccati——也就退回到了陷阱 1 的错误做法。 - 发散即无解:
if not sol.success那行不是例行检查,而是直接对应 §1.6 陷阱 2——耦合 Riccati 可能在有限时间内发散(finite escape),积分器报错恰好暴露了"解不存在/无界"。 - 验证纳什:拿到
K1, K2后,按练习 1 的方法自检——固定玩家 2 的增益、对修正系统 \(\tilde A=A-B_2K_2\) 重解玩家 1 的**单人** LQR,应当得回同一条K1。得回了,才确认是纳什均衡而非两个各自为政的 LQR。
把"验证纳什"也写成代码,让这块自带检查(对应练习 1 的自检步骤):
from scipy.linalg import solve_continuous_are
def verify_nash(A, B1, B2, R1, R2, K1, K2, Q1):
"""固定玩家 2 的增益 K2,对修正系统 Ã = A - B2 K2 重解玩家 1 的单人 LQR,
应得回耦合解的 K1——吻合才说明是纳什均衡,而非两个各自为政的 LQR。
用收敛段(远离终端、如长时域下 t=0 处)的增益做检验。"""
A_tilde = A - B2 @ K2 # 玩家 1 面对的修正系统(§1.6 推导中的 Ã)
P1_chk = solve_continuous_are(A_tilde, B1, Q1, R1) # 单人 LQR 的 CARE
K1_chk = np.linalg.solve(R1, B1.T @ P1_chk)
return K1_chk, float(np.linalg.norm(K1_chk - K1)) # 与耦合解 K1 之差,应 ≈ 0
# 用法:取长时域、收敛段(t=0,即 K1[-1]/K2[-1])的增益代入
# ts, P1, P2, K1, K2 = coupled_riccati_2p(A, B1, B2, Q1, Q2, R1, R2, Qf1, Qf2, T=20.0)
# _, err = verify_nash(A, B1, B2, R1, R2, K1[-1], K2[-1], Q1)
# assert err < 1e-6, "不是纳什均衡——多半漏了交叉项(陷阱 1)"
这个检验背后的数学正是 §1.6 的推导本身:玩家 1 面对的修正系统 \(\tilde A=A-B_2K_2=A-S_2P_2\),对它解单人 LQR 的代数 Riccati,展开后与耦合方程 (1.5) 的玩家 1 那条**逐项相同**——所以收敛段的 \(K_1\) 必然吻合。
若 err 不接近 0,几乎一定是实现里漏了交叉项 \(-(P_2S_2P_1+P_1S_2P_2)\),退化成了独立 LQR(陷阱 1)。
把代码跑起来:数值对照解析解¶
光有代码不够,跑一遍、和 §1.6 的解析解对上,才算闭环。
取前面那个对称标量例子的具体数值——\(a=0.5,\ b_1=b_2=1,\ q=1,\ r=1\)(故 \(s=1\)),取长时域 \(T=20\) 让 Riccati 收敛——把 coupled_riccati_2p 跑起来,得到收敛段(\(t=0\))的解:
| 量 | 数值结果 | 解析解 |
|---|---|---|
| 耦合 Riccati \(P_1(0)\) | 0.7676 | \(\dfrac{a+\sqrt{a^2+3sq}}{3s}=0.7676\) ✓ |
| 单人 LQR(作对照) | — | \(\dfrac{a+\sqrt{a^2+sq}}{s}=1.6180\) |
| 纳什自检 \(\lVert K_1^{\text{check}}-K_1\rVert\) | \(4.3\times10^{-10}\) | 应 \(\approx 0\) ✓ |
数值解 \(P_1(0)=0.7676\) 与 §1.6 推出的博弈解析解**逐位吻合**,验证了代码; 而它明显小于单人 LQR 的 \(1.6180\),定量印证了 §1.6 那句"博弈里每人比独占系统时更克制"。 纳什自检误差 \(4.3\times10^{-10}\)(机器精度级)确认了得到的确实是反馈纳什均衡,而非两个各自为政的 LQR——交叉项没漏。 顺带,§1.5 那个手写 BRT 求解器同样跑出 \([-3.99,3.99]\),与解析的 \(\{|x|\le 1+T\}=[-4,4]\) 吻合到网格精度。
本质洞察(数值是理论的试金石):这几处数值-解析的吻合不是装饰。 它们把本章三条独立的推导链各验证了一遍:耦合 Riccati 的解析解(§1.6)、纳什均衡的定义(§1.6 自检)、可达管的解析形状(§1.4–§1.5)。 一篇理论文档若只有公式没有可对照的数值,读者无从判断公式抄对没有;反过来,能跑出与解析解吻合的数字,是对推导最硬的检验——这也是为什么本章的关键代码都给了可运行版本并附了对照。
理论–工程桥接(这段代码就是 iLQGames 的内核):这个
coupled_riccati_2p函数,正是 G2 中 iLQGames 每一步迭代反复调用的那块。 iLQGames 处理一般非线性博弈,但它每一步做的事就是:沿名义轨迹把动力学线性化成 \(A_k,B_{i,k}\)、代价二次化成 \(Q_{i,k}\),然后**解一次本函数所做的耦合 Riccati**,拿到反馈增益去更新轨迹。 社区里被称道的 iLQGames.jl"约 70 行核心代码",主体就是这段耦合 Riccati 反向递推(外加自动微分做线性化);C++ 版 ilqgames 的lq_solver.cc(约 200 行 Eigen)做的也是同一件事,只是离散时间、手写求导。 换句话说,读懂这 30 行 NumPy,就读懂了 G2 实时博弈求解器跳动的心脏——G2 的工作是把这颗心脏包进"线性化—求解—更新"的迭代外壳,并解决实时性、收敛与均衡选择。
这一节如何接上 G2¶
理论–工程桥接(→ G2 iLQGames)。 把本节的耦合 Riccati 记牢,因为 G2 的 iLQGames 会反复调用它。 iLQGames 处理的是一般非线性、一般代价的多人博弈,它的每一步迭代做三件事: (1)沿当前名义轨迹把动力学一阶 Taylor 展开成线性 \(A_k,B_{i,k}\)、把代价二阶展开成二次 \(Q_{i,k}\); (2)对这个**局部 LQ 博弈**解 (1.5) 式的耦合 Riccati,得到每人的反馈增益 \(K_{i,k}\) 和前馈项; (3)用新策略前向 rollout 更新名义轨迹,再迭代。 也就是说——iLQGames = 在每个时刻把一般博弈近似成本节的 LQ 博弈,反复解耦合 Riccati 直到收敛。 本节是那个内核;G2 是把内核包进"线性化—求解—更新"的迭代外壳,并解决实时性、收敛性、均衡选择等工程问题。 顺带一提,耦合 Riccati 的反向递推在离散时间下呈块三对角结构,与 SLAM 里因子图的稀疏 Hessian 同构——这条与 v8 SLAM 因子图的联系会在 G2 的代码精读里再用到。
一个重要细节:反馈 Nash vs 开环 Nash¶
(1.5) 解的是**反馈 Nash**均衡——策略是状态的函数 \(u_i=-K_i(t)x\)。 还有另一种解概念叫**开环 Nash**:策略是**时间**的函数 \(u_i(t)\),双方在 \(t=0\) 各自承诺一条完整计划、之后不再看状态。 这俩在博弈里**给出不同的均衡、满足不同的方程**——这是单人最优控制里没有的现象,值得专门点出。
回忆单人确定性最优控制:开环最优解(PMP 得到的 \(u^*(t)\))和反馈最优解(HJB 得到的 \(u^*(x,t)\))沿最优轨迹**完全重合**——确定性、无对手时,"先想好一条路"和"边走边看"结果一样,所以平时不区分。 但一旦进入博弈,区别就实质化了:均衡依赖**每个玩家掌握什么信息**。 开环 Nash 假设双方只在开局看一眼初始状态、之后各按计划走(信息少);反馈 Nash 假设双方时刻都能观测状态、随时调整(信息多)。 信息不同,最优响应不同,于是均衡不同——这正是 §1.2 反复强调的"博弈的解依赖信息结构"在 LQ 世界里的具体化身。
- 反馈 Nash:解耦合 Riccati (1.5),得反馈增益 \(K_i(t)\)。本章与 G2 用的就是它。
- 开环 Nash:解一组耦合的两点边值问题(PMP 式协态方程联立),得开环输入 \(u_i(t)\),方程结构与 (1.5) 不同。
本章为什么用反馈 Nash? 三个理由:其一,反馈策略有扰动拒绝能力(§1.2 已述),机器人实际部署的就是"看状态实时算控制"的反馈律;其二,iLQGames(G2)的输出天然是反馈增益序列,与 (1.5) 对接;其三,反馈 Nash 在多数交互场景里是更现实的建模——交通中没人真会"开局承诺一条路、之后闭眼开"。 所以后续一律默认反馈 Nash;遇到"开环"字样要警觉,它是另一套方程、另一族均衡。
⚠️ 常见陷阱¶
陷阱 1:把多人 LQ 当成各自独立的 LQR - 错误描述:以为"每人线性二次,那就每人各解一个标准 LQR、各取各的增益"。 - 现象/后果:得到的增益组合不是纳什均衡——当别人也用最优反馈时,你的"最优"并非最优响应;仿真里表现为策略不自洽、系统行为与理论预测对不上。 - 根本原因:玩家 \(i\) 面对的系统矩阵 \(\tilde A_i=A-\sum_{j\ne i}B_jK_j\) 含着别人的增益,必须把所有最优性条件联立,才得到 (1.5) 的耦合方程;独立 LQR 等于扔掉了那些交叉项。 - 正确做法:联立求解耦合 Riccati (1.5)(同时反向积分 \(N\) 条方程)。检验方法:算出各 \(K_i\) 后,固定别人、单独重解玩家 \(i\) 的 LQR,看是否得回同一个 \(K_i\)——是,才是纳什均衡。
陷阱 2:默认耦合 Riccati 一定有解 - 错误描述:套用单人 LQR"可镇定就有解"的经验,假设耦合 Riccati 也总能解出有界的 \(P_i\)。 - 现象/后果:反向积分时 \(P_i\) 在有限时间内发散(finite escape),数值爆掉或得到无意义的巨大增益,却找不到原因。 - 根本原因:交叉项 \(P_jS_jP_i\) 破坏了单人 Riccati 的良好性质;即便每个玩家单独的 LQR 都有解,耦合系统仍可能无界解。存在性需要额外条件,不是默认。 - 正确做法:求解后检查 \(P_i\) 是否在整个时域上有界、是否半正定;遇到发散时缩短时域或调整权重。G2 的 iLQGames 用正则化、信赖域等手段处理这一不稳定性。
练习¶
- (累积项目·甲,本章新增模块) 用 Eigen 实现两人 LQ 博弈的耦合 Riccati 反向积分器:给定 \(A,B_1,B_2,Q_1,Q_2,R_{11},R_{22}\) 与终端 \(Q_i^f\),从 \(t=T\) 反向积分 (1.5) 解出 \(P_1(t),P_2(t)\),再由 (1.6) 算反馈增益 \(K_1,K_2\)。在一个 2D 双车 unicycle 线性化模型上验证:用得到的反馈做闭环 rollout,确认两车都无法通过单方面改增益降低自己的代价(即停在纳什均衡)。这个模块是项目甲(自动驾驶交互博弈规划器)的第一块积木,G2 会把它扩成完整 iLQGames。
- (手推 + 对照) 把正文那个对称两人标量例子改成**非对称**:\(s_1\ne s_2\) 或 \(q_1\ne q_2\)。写出两条耦合代数方程,讨论解的存在性(什么参数下判别式失效、解不存在?),并与"两人各自的单人 LQR 解"数值对照,量化耦合带来的差异。
- (概念,连接 G2) 解释为什么"任何光滑微分博弈都能局部近似成 LQ 博弈",以及 iLQGames 每步为什么要解一次本节的耦合 Riccati。如果某一步的耦合 Riccati 无解(陷阱 2),iLQGames 该怎么办?(提示:想想正则化 / 信赖域。)
§1.7 维度诅咒与三条绕行路 ⭐⭐⭐¶
这一节解决什么问题:§1.5 末尾点了名——网格法被维度诅咒卡在约 6 维,可真实系统(多机、高自由度)远不止 6 维。 这一节讲三条主流绕行路:状态解耦、FaSTrack、神经近似(DeepReach),并按"精确性 vs 可扩展性"把它们排清楚,好在工程里按需选型。
动机:6 维天花板与真实世界的落差¶
§1.5 的工程权衡表里那条指数增长的"维数"是 HJI 直接应用的死穴: 网格点数随状态维数 \(d\) 按 \(N^d\) 爆炸,\(N=50\)、\(d=6\) 已是 \(50^6\approx1.5\times10^{10}\) 个点的单机极限。 可真实问题动辄超过 6 维:两架四旋翼的相对追逃就是 6 维起步,三机就 12 维以上;一个带姿态的固定翼是 6–8 维;多机协调更是维数随机器数线性叠加。 所以"HJI 给精确安全证书"这件好事,必须配上能绕过维度诅咒的办法,否则只能停在玩具系统上。 下面三条路代表了三种不同的取舍哲学。
路一:状态解耦与序贯轨迹规划(STP)¶
思想:很多高维系统的状态之间耦合是**稀疏**的——某些子状态只通过少数共享变量与其余部分相连。 Chen 等(IEEE TAC 2018,可达集与可达管的分解)证明:对一类满足解耦结构的非线性系统,可以把高维可达集计算**分解**成若干低维子系统的计算,子系统之间只通过共享的状态/控制/干扰耦合。 在多机追逃/规划里,这条路具体化为**序贯轨迹规划(Sequential Trajectory Planning, STP;早期文献也称序贯路径规划 SPP)**(Chen、Bansal、Tomlin 等系列工作,含对抗入侵者下的鲁棒版本,见延伸阅读): 给多架飞行器排一个优先级,按优先级逐个规划,每架只需在自己的约 6 维相对状态空间里解一个 HJI 子问题,把已规划的高优先级飞行器当作要避让的动态障碍。 这样 \(N\) 架飞行器的 \(6N\) 维联合问题,被拆成 \(N\) 个各约 6 维的子问题,计算量从指数(\(N^{6N}\) 量级)降到随机器数线性叠加。
取舍:在可解耦/可定优先级的结构下,STP 给出的安全保证仍是**严格**的(不是近似)。 代价是它**要求系统具备这种解耦结构或可接受优先级排序**——对状态强耦合、无法分优先级的问题(如真正同时博弈、对称竞速),解耦不适用或会引入保守性。
路二:FaSTrack——把规划与安全分离¶
思想:FaSTrack(Herbert、Chen、Bansal、Fisac、Tomlin,CDC 2017,"快速且保证安全的模块化运动规划框架")换了个角度:不直接对全维系统算 HJI,而是把问题拆成**两层**:
- 规划层:用一个低维、快速的简化模型(planning model)实时规划,比如把无人机当成一个匀速运动的点——快,但不精确。
- 追踪层:用 HJI 离线预计算**一个**追踪误差界(Tracking Error Bound, TEB)——把"简化规划模型"与"全维真实系统"之间的相对动力学建成一个零和追逃博弈(真实系统追规划点、最坏情况干扰当逃跑者),算出真实系统跟踪规划轨迹时误差不会超过的那个有保证的界(一个不变的"误差球/管")。
在线运行时,规划层随便用什么快速规划器都行,只要把规划出的轨迹按 TEB 向外膨胀(给障碍留出误差球的余量),就**保证**真实系统全程安全——HJI 只在离线那一步、且只在低维的相对系统上算一次。
多视角理解(FaSTrack 的 TEB ↔ §1.4 的 BRT / Tube MPC 的 RPI)。 FaSTrack 的追踪误差界,本质又是一根"管"——和 §1.4 的 BRT、Tube MPC 的 RPI 集是同一族思想。 相似之处:都把最坏情况建成对手、算一个有保证的不变/可达管,把"安全"归结为"待在管内"。 不同之处:FaSTrack 算的是"真实系统相对规划模型"的误差管,并把它和一个独立的快速规划器解耦——这就是它能实时的关键。 这条把 §1.4、§1.6(局部近似)、FaSTrack 串起来的线索再次印证:本章反复在做同一件事——用对抗博弈算一根保证安全的管/集,区别只在算的是什么、怎么让它可算。
取舍:FaSTrack 给**严格安全保证**且**在线实时**,是工程上很受欢迎的折中。 代价是:TEB 需要离线预计算(限制了能处理的相对系统维数),且误差界往往**偏保守**(为覆盖最坏情况,膨胀量可能过大,挤掉可行空间)。
路三:DeepReach——用神经网络近似值函数¶
思想:前两条路都还在"精确求解"的框架内(只是巧妙地降维或分层)。 DeepReach(Bansal 与 Tomlin,ICRA 2021)则彻底换赛道:放弃网格,用神经网络直接近似 HJI 值函数 \(V(x,t)\)。 它的关键技术有两点: 其一,用**正弦激活的神经网络**(sinusoidal / 周期激活,源自隐式神经表示 SIREN 的思路)当函数逼近器——这类网络擅长拟合带高频细节(如棱)的函数; 其二,自监督训练:不需要标注数据,直接把 HJI 方程的残差(以及边界/终端条件的误差)当作损失函数,让网络去最小化它,于是网络收敛时就近似满足了 HJI 方程。 由于神经网络的参数量不随状态维数指数增长,DeepReach 能处理**10 维以上**的系统,突破了网格法的 6 维天花板。
把"自监督"拆慢一点:损失函数到底是什么。 "不需要标注数据"听起来神奇,循序渐进看就很自然。 设神经网络 \(V_\theta(x,t)\)(参数 \(\theta\))是对值函数的猜测。 我们不知道真值 \(V\) 长什么样(没法监督),但我们**知道真值必须满足的方程**——HJI (1.2)。 于是不去拟合"标签",而是去逼网络满足那条方程,分两块罚:
- PDE 残差项:在状态-时间空间里随机采一大批点 \((x_k,t_k)\),每个点上算 HJI 方程的左端 \(\big|D_t V_\theta+H(x_k,\nabla V_\theta)\big|^2\)。真解这一项为零,所以把它当损失去最小化,就是在逼网络处处满足方程。其中 \(\nabla V_\theta\)、\(D_t V_\theta\) 都用自动微分对网络直接求出——这正是正弦激活网络的用武之地(它的高阶导数性质好)。
- 边界/终端项:在 \(t=0\) 处罚 \(\big|V_\theta(x,0)-g(x)\big|^2\),把终端条件 \(V(x,0)=g(x)\) 钉住。
把两项加权求和当总损失,用梯度下降训练 \(\theta\)。 "自监督"的含义就在这里:监督信号不是外部标签,而是方程本身——网络自己生成采样点、自己算残差、自己往"满足方程"的方向收敛。 这套"拿 PDE 残差当损失"的思路就是物理信息神经网络(PINN)的范式,DeepReach 是它在 HJI 可达性上的落地。 直觉上,网格法是在每个格点上**精确**解方程(故受 \(N^d\) 之困),DeepReach 是用一个连续函数 \(V_\theta\) 去**近似**满足方程(故能上高维,但只是近似)。
取舍:代价是**丢掉了全局最优/安全保证**。 网格法在收敛时给的是有保证的解,而 DeepReach 是**近似**——网络可能在某些区域偏离真值,导致用它做安全验证时**出现违反**。 (有研究在一个 reach–avoid 任务上报告,直接用 DeepReach 值函数的轨迹只有约 70% 满足安全约束——近似误差会实打实地变成安全漏洞。) 所以 DeepReach 是"用保证换可扩展",需要配合后验证/认证手段使用。
三条路的统一对比¶
系统性分类(按"精确性 vs 可扩展性"排三条绕行路)。 维度诅咒的三条绕行路,不是随意并列,而是沿同一条权衡轴排开的:
| 路线 | 怎么绕 | 安全保证 | 可扩展性 | 前提/代价 |
|---|---|---|---|---|
| 状态解耦 / STP | 把高维拆成低维子问题,只经共享变量耦合 | 严格(在可解耦结构下) | 高(线性叠加) | 要求解耦结构 / 可定优先级 |
| FaSTrack | 低维规划 + 离线 HJI 算追踪误差界 | 严格(保证安全) | 中–高(在线实时) | 离线预计算 + 误差界偏保守 |
| DeepReach | 神经网络自监督近似值函数 | 近似(可能违反) | 高(10D+) | 失全局保证,需后验证 |
一条清晰的取舍:越想保留严格保证,越要依赖系统结构或离线代价(解耦、FaSTrack);越想纯粹地扩展到高维,越要放弃保证(DeepReach)。 没有免费的午餐——这正是 §1.6 那条"退而用局部 LQ 近似"(G2)之所以另辟蹊径的原因:G2 不追求全局可达集,只在每个时刻求一个局部反馈 Nash,用实时性换全局性,是第四种、也是 G2/G3 主打的取舍。
前沿工作与开放问题¶
- 在线更新的值函数:Borquez、Nakamura、Bansal(参数条件可达集,ICRA 2023)让值函数以系统参数为条件,从而能在线适应变化的控制/干扰边界,而不必重算——朝"安全保证随环境在线更新"迈进。
- 值函数即安全滤波器:"One Filter to Deploy Them All"(arXiv 2412.09989,2024)把 HJ 值网络当成一个自适应安全滤波器统一部署到多种系统(该工作较新、临近本资料知识边界,细节以原文为准)。
- 开放问题:如何在**非零和 general-sum** 博弈里做 HJI(本章可达性都建在零和上)?如何在线更新 DeepReach 的值函数以适应未知/变化的对手?如何在保留可扩展性的同时给神经近似补上可证明的安全认证(post-hoc certification)?
最后这个"认证"问题值得多说一句,因为它是神经近似路线能否用在安全关键系统上的命门。 网格法的安全保证为什么硬?因为它在每个网格点上显式算出了值,误差可由网格分辨率控制、可被单调格式的收敛性背书——你能指着可达集说"这个边界差不超过一个格子"。 神经网络没有这种保证:它在训练样本附近拟合得好,但在样本稀疏处可能任意偏离,而你事先不知道哪里稀疏。 于是 DeepReach 的值函数即便平均误差很小,也可能在某个局部把"危险"误判成"安全"——而安全关键系统恰恰输不起这一个点。 目前的认证思路大致两类:事后采样验证(在值函数声称安全的区域大量采样、前向 rollout 看是否真安全,但采样验不了"所有"状态,只能增加信心);形式化误差界(用神经网络验证工具给值函数的逼近误差找一个可证上界,再把这个误差当成额外的"干扰"膨胀进安全裕度,但当前这类工具的可扩展性本身也有限)。 两条路都还不成熟——这就是为什么本章把神经近似定位为"用保证换可扩展",而非网格法的全面替代。
本质洞察(保证的本质是"可控的误差"):网格法和神经近似的根本差别,不在精度高低,而在**误差是否可控、可知**。 网格法的误差有理论上界、随分辨率单调收敛,所以它给的是"保证"; 神经近似的误差分布未知、无处不在又无处可指,所以它只给"近似"。 安全关键系统要的从来不是"平均很准",而是"最坏不差过某条线"——这条线能不能画出来,就是"保证"与"近似"的分水岭。 这也解释了为什么 §1.6 的局部 LQ 近似(G2)走了完全不同的路:它不试图近似全局值函数,而是在每个时刻求一个**精确**的局部反馈 Nash,用"局部精确 + 滚动重规划"换掉"全局近似",从而绕开了认证难题。
⚠️ 常见陷阱¶
陷阱 1:以为 DeepReach(神经近似)总是优于网格法 - 错误描述:"神经网络能上高维、又快,那以后都用 DeepReach、不用网格法了。" - 现象/后果:在需要严格安全保证的场合用近似值函数,出现未被察觉的安全违反(如前述 reach–avoid 只有约 70% 满足);把"近似解"当"有保证的解"用,可能酿成事故。 - 根本原因:网格法在收敛时给有保证的解,DeepReach 是近似,网络在某些区域可能偏离真值——可扩展性是用"丢掉全局保证"换来的。 - 正确做法:分清需求。低维、要严格保证 → 网格法 / FaSTrack / STP;高维、可接受近似 + 后验证 → DeepReach。检验方法:用 DeepReach 时,务必对其值函数做后验证(采样 rollout 验安全、或用认证方法),不要直接信任。
陷阱 2:以为状态解耦 / STP 对任意高维系统都适用 - 错误描述:"维度高就拆成低维子问题嘛,解耦总能用。" - 现象/后果:对状态强耦合、无法分优先级的系统(如真正对称的同时博弈)强行解耦,要么根本拆不开,要么引入巨大保守性,得到的"安全集"过小、没法用。 - 根本原因:解耦/STP 依赖系统的特定结构(子状态间稀疏耦合、可定优先级);不具备这种结构的系统,分解会失真或失效。 - 正确做法:先判断系统是否真的可解耦、能否合理排优先级;不行就转向 FaSTrack(若能离线算低维相对系统)或 DeepReach(若可接受近似),或干脆用 G2 的局部近似路线。
练习¶
- (系统性对比) 给定一个 8 维多机器人安全问题(如 2 架四旋翼相对状态共 8 维),分别论证:用 STP、FaSTrack、DeepReach 各自需要什么前提、能给什么级别的保证、主要代价是什么?你会优先尝试哪条,为什么?
- (辨析保证 vs 近似) 解释为什么"DeepReach 在 reach–avoid 上只有约 70% 满足率"这件事,对安全关键应用是致命的;以及为什么同样的近似误差对"粗略包络估计"这类用途可能无所谓。由此说明"该不该用近似可达性"取决于什么。
- (连接全章) 本章给出了应对维度诅咒的若干思路:§1.6 的局部 LQ 近似(G2 路线)、§1.7 的三条绕行路。把它们统一放到"精确性—可扩展性—实时性"三维权衡里比较,并指出 G2 的 iLQGames 落在这个权衡空间的什么位置、为什么自动驾驶/竞速这类应用会选它。
§1.8 追逃经典问题:Homicidal Chauffeur 与 Air3D ⭐⭐¶
这一节解决什么问题:前七节都在搭理论与方法,这一节用两个标志性的追逃问题把它们落地——给直觉一个锚、给数值实验一个标准靶子,也借此点出 Isaacs 理论里关于值函数"棱"的精细分类。
动机:为什么需要标志性问题¶
抽象的 HJI 方程、可达集、数值格式,都需要一个具体问题来检验理解、调试代码、对比方法。 微分博弈领域有两个几乎人人都从它们入门的经典问题:Isaacs 1965 提出的 Homicidal Chauffeur,和 Mitchell–Tomlin 2005 用作标准基准的 Air3D。 它们都是追逃博弈、都用相对坐标、都能在低维网格上算出可达集——是把前面所有理论"跑起来"的第一站。
Homicidal Chauffeur:转弯受限的追捕者¶
Isaacs 用一个略带黑色幽默的设定命名了这个问题("开车的杀手"): 一个**追捕者是辆车**——速度快,但**转弯半径受限**(不能原地掉头); 一个**逃跑者是个行人**——速度慢,但**全向机动**(可以瞬间改变方向)。 追捕者想把两者的相对距离压到某个捕获半径以下("撞上"),逃跑者想一直躲开。 这是一个零和博弈:同一个"最终相对距离/能否捕获",一方求小、一方求大,正是 §1.2 的设定。
它的精妙在于"快但笨"对"慢但灵"的对抗:追捕者速度占优,但转弯的笨拙给了灵活的行人可乘之机——行人可以在追捕者来不及转向的时刻侧身闪过。 谁占优、从哪些初始相对位形追捕者必胜,正是 HJI 可达性(§1.4)要回答的——捕获集就是那个 BRT。
Isaacs 的奇异面:值函数的"棱"从哪来¶
分析 Homicidal Chauffeur 时,Isaacs 发现最优值函数上存在若干**奇异面(singular surfaces)**——值函数在那里不光滑或最优策略在那里特殊。 本课重点认识三类:
| 奇异面 | 含义 | 与前文的联系 |
|---|---|---|
| 障碍面(barrier) | 捕获区与逃脱区的分界面,跨过它结局定性翻转 | 就是 §1.4 可达集的边界 \(\partial\mathcal{R}\) |
| 散射面(dispersal surface) | 某一方有**多个等价最优选择**的面(如行人向左闪、向右闪一样好) | 正是 §1.3 的"棱"——多条等价最优路径在此打平,值函数不可微 |
| 通用面(universal surface) | 多条最优轨迹**汇入并沿之同行**的面,像一条最优路径的"高速公路" | 反映最优反馈策略的结构 |
本质洞察:§1.3 抽象地说"值函数会因多条等价最优路径而起棱",Homicidal Chauffeur 的散射面就是这句话最具体的样子——行人站在散射面上时,向左闪和向右闪被追上的结局完全一样,于是值函数在那里有一道折痕、协态(最优方向)发生跳变。 Isaacs 的奇异面分类,本质就是在给 HJI 值函数的非光滑结构"分门别类"。 这也再次说明 §1.3 的粘性解为什么不可或缺:经典可微解根本描述不了带散射面的值函数。
Air3D:可达性工具的"Hello World"¶
Air3D(Mitchell–Tomlin 2005)是把两架同型飞行器的追逃写成**三维相对坐标**的标准基准——几乎每个可达性工具(helperOC、optimized_dp、hj_reachability)的第一个示例都是它。 两架飞行器都以固定速度 \(v\) 飞、各有有界转弯率。 把"逃逸机"放到"追捕机"的机体坐标系里,用相对位置 \((x,y)\) 和相对朝向 \(\psi\) 三个量描述,相对动力学为
其中 \(u\) 是追捕机的转弯率(争取捕获)、\(d\) 是逃逸机的转弯率(争取逃脱),二者各在有界区间取值。 碰撞/捕获集是相对距离小于半径 \(R\) 的圆盘 \(\{x^2+y^2\le R^2\}\)。 按 §1.4,从这个圆盘出发反向算 BRT(哈密顿量的 \(\max/\min\) 取法由"追捕争取存在一个捕获策略、逃逸争取存在一个逃脱策略"逐项定出),得到的就是"逃逸机无法避免被捕获"的危险相对位形集合——也就是 §1.8 标志性的那张三维可达集图。
为什么一定要用相对坐标¶
两架飞行器的绝对状态是 \((x_A,y_A,\psi_A,x_B,y_B,\psi_B)\)——六维。 但追逃的结果只取决于二者的**相对**位形,与它们在世界里的绝对位置无关。 把问题改写到相对坐标 \((x,y,\psi)\),维度从 6 维降到 3 维——而 §1.5 告诉我们,3 维网格能轻松算、6 维已逼近极限。
多视角理解(相对坐标 ↔ 降维 / 物理对称性)。 "用相对坐标"不只是记号方便,它是在利用问题的**平移与旋转对称性**把维度砍掉一半。 相似之处:这和物理里"用相对坐标处理两体问题、把质心运动分离出去"是同一种智慧——无关的对称自由度(绝对位置、整体朝向)被消掉。 不同之处:两体问题的相对坐标是为了解析可积,这里是为了让 HJI 网格算得动(直接关系到能不能绕过 §1.5/§1.7 的维度诅咒)。 一句话:处理追逃博弈的标准第一步,永远是先换到相对坐标降维——这是把理论真正算出来的前提。
相对动力学是怎么推出来的¶
上面那个 Air3D 相对动力学 \((\dot x,\dot y,\dot\psi)\) 不是凭空给的,按 R1 的要求把它一步步推出来——这也顺带演示"在动坐标系里求导要带牵连项"这个机器人学反复出现的套路。
设定。 取追捕机(pursuer)为参考,把坐标原点固定在它身上、\(x\) 轴指向它的前进方向。 两机都以固定速率 \(v\) 平移;追捕机转弯率为 \(u\)、逃逸机(evader)转弯率为 \(d\)(这就是双方各自的控制)。 相对状态 \((x,y)\) 是逃逸机在追捕机体坐标系里的位置,\(\psi\) 是逃逸机朝向相对追捕机朝向的夹角。
第一步:写出逃逸机相对追捕机的速度(在世界系里)。 逃逸机以速率 \(v\) 沿自身朝向 \(\psi\)(相对追捕机)运动,在追捕机体系下,它的平移速度分量是 \((v\cos\psi,\ v\sin\psi)\); 追捕机自己以速率 \(v\) 沿体系 \(x\) 轴正向运动,所以"逃逸机相对追捕机"的平移部分要减去追捕机的速度 \((v,0)\)。 只看平移,得到 \((\,v\cos\psi-v,\ \ v\sin\psi\,)\)。
第二步:补上参考系旋转的牵连项。 这一步最容易漏。 追捕机体坐标系本身在以角速度 \(u\) 旋转(追捕机在转弯),而我们要的是在这个**转动坐标系**里观察到的相对位置变化率。 转动坐标系里的求导公式给出一个牵连项 \(-\,\omega\times r\):对平面、角速度 \(u\)、位置 \((x,y)\),这个叉积的分量是 \((\,+u\,y,\ -u\,x\,)\)。 直觉是:哪怕逃逸机在世界里不动,追捕机一转头,逃逸机在它眼里的坐标也会"转过去"——这个视觉上的移动就是牵连项。
第三步:合并。 平移部分(第一步)加牵连部分(第二步):
第四步:相对朝向。 \(\psi\) 是两机朝向之差,其变化率就是两个转弯率之差。 逃逸机朝向以 \(d\) 变化、追捕机以 \(u\) 变化,故
合起来正是前面那组 Air3D 方程。 这个推导里值得记住的是第二步的牵连项 \((uy,-ux)\)——凡是把动力学写到一个**随机器人转动**的坐标系里(机体系、相对系),都会冒出这种 \(\omega\times r\) 形式的项,漏掉它是相对坐标建模最常见的错误(见下面陷阱)。
本质洞察(相对坐标把"绝对运动"消成了"牵连项"):从 6 维绝对坐标降到 3 维相对坐标,省掉的恰好是"两机一起平移、一起旋转"这些对结果无影响的自由度。 代价是动力学里多出了牵连项 \((uy,-ux)\)——绝对坐标里追捕机的转弯本是一条独立的状态方程 \(\dot\psi_A=u\),降维后它"藏"进了相对位置的演化里。 这是降维的普遍规律:维度省下来不是免费的,被消去的自由度会以"耦合项/牵连项"的形式重新出现在保留的方程里。 看懂这一点,就不会奇怪为什么相对动力学比绝对动力学"看起来更复杂"——复杂度没消失,只是换了个地方待着。
Air3D 的哈密顿量与捕获集¶
有了相对动力学,按 §1.4 的套路写 BRT 就水到渠成。 碰撞/捕获集是相对距离小于半径 \(R\) 的圆盘 \(\mathcal{T}=\{x^2+y^2\le R^2\}\),带符号距离 \(g(x,y,\psi)=\sqrt{x^2+y^2}-R\)。 角色:追捕机想进入 \(\mathcal{T}\)(争取存在一个捕获策略,对 \(u\) 取 \(\min\)),逃逸机想避开(对所有逃逸策略都要被捕获才算危险,对 \(d\) 取 \(\max\))。 记协态 \(\lambda=(\lambda_x,\lambda_y,\lambda_\psi)=\nabla V\),哈密顿量
把含 \(u\) 和含 \(d\) 的项分别收拢(二者在动力学里线性出现、可分离,故 Isaacs 条件成立,§1.2):
由于 \(u\in[-\bar u,\bar u]\)、\(d\in[-\bar d,\bar d]\),两个极值都在边界取到:
最优策略是 bang-bang 的(取决于协态的符号)——这与 §1.2 一维追逃 \(u^*=\operatorname{sign}(\lambda)\) 的结构如出一辙,也是零和追逃博弈的普遍特征:在控制约束的盒子里,最优控制总打在角上。 把这个 \(H\) 连同 BRT 冻结项 (1.4b) 喂进 §1.5 的数值格式,反向积分得到的零下水平集,就是那张标志性的三维捕获集——逃逸机一旦初始位形落在里面,无论怎么机动都难逃被捕。
类型博弈与程度博弈在数值上的统一¶
§1.1 提过 Isaacs 区分"类型博弈"(追上没有,布尔)与"程度博弈"(最终距离多少,连续)。 Air3D 表面问的是类型博弈(能不能捕获),但水平集方法把它**变成了程度博弈再求解**:值函数 \(V(x,\psi,t)\) 是个连续量(到捕获的某种"代价裕度"),最后取它的零下水平集 \(\{V\le0\}\) 才还原出布尔的捕获判断。
多视角理解(类型博弈 ↔ 程度博弈,经水平集相连)。 这正是 §1.4 开头"把布尔问题编码成连续值函数"那句话在追逃语境里的完整兑现。 相似之处:两种博弈问的是同一件事的两面——"会不会被捕获"(类型)与"被捕获的临界程度"(程度)。 不同之处:类型博弈直接算布尔结局、难做连续优化;程度博弈算连续值函数、可用 PDE 数值求解,再用零水平集回到布尔。 一句话:水平集方法的威力,就在于它用一个连续的程度博弈,迂回解出了原本难算的类型博弈——这是整个 HJI 可达性领域得以工程化的根基,也把 §1.1 的概念区分、§1.4 的编码技巧、§1.8 的具体问题串成了一条线。
⚠️ 常见陷阱¶
陷阱 1:用绝对坐标建模追逃,导致维度翻倍 - 错误描述:直接用两个智能体各自的绝对状态 \((x_A,y_A,\psi_A,x_B,y_B,\psi_B)\) 去算可达集。 - 现象/后果:状态维数翻倍(如 3+3=6 维),网格点数随之指数暴涨,本可在 3 维轻松算的问题被推到 6 维的计算极限,甚至算不动。 - 根本原因:追逃结果只依赖相对位形,绝对位置/整体朝向是与结果无关的对称自由度;用绝对坐标等于白白多算了这些冗余维度。 - 正确做法:先换到相对坐标(利用平移/旋转对称性),把维度降到最低再算。检验方法:问"我的状态里有没有'整体平移/旋转一下结果不变'的自由度?"——有,就该消掉它。
陷阱 2:把散射面上的不可微当成数值 bug - 错误描述:算 Homicidal Chauffeur / Air3D 时看到值函数有折痕、协态跳变,以为是格式出错或网格太粗。 - 现象/后果:误把物理上真实的散射面当噪声去"修",或反复加密网格试图让它变光滑(徒劳)。 - 根本原因:散射面是值函数**真实的、本质的**非光滑结构(多条等价最优路径打平,§1.3),不是数值假象;粘性解本就允许这种棱。 - 正确做法:识别出它是奇异面而非 bug,用尊重粘性的格式(§1.5 WENO)正确捕捉它即可。检验方法:加密网格后折痕位置稳定、只是更锐利——那就是真实的散射面,不是数值噪声。
练习¶
- (累积项目·乙,本章新增模块) 用 helperOC(或 optimized_dp / hj_reachability)实现 Air3D 追逃的后向可达管计算,可视化三维零下水平集(捕获集)。改变逃逸机的速度或转弯率,观察捕获集如何变化(追捕者更强时它怎么扩张?)。这个 Air3D 可达性验证器是项目乙(离散博弈 + 多机安全工具链)的第一块积木,将作为"安全包络"供项目甲调用。
- (概念,连接 §1.3) 解释 Homicidal Chauffeur 的散射面为什么对应值函数的不可微棱:站在散射面上的一方面临什么样的"等价选择"?为什么这会让协态(最优方向)在该面上跳变?这与 eikonal 例子(§1.3)里 \(1-|x|\) 在 \(x=0\) 的尖有何相似?
- (建模,相对坐标) 对"地面机器人追一个全向移动的目标"这一平面追逃,自己推导相对坐标下的动力学(设追捕者朝向为参考系)。说明你用了哪些对称性把维度从绝对坐标的几维降到了几维。
本章常见误解汇总¶
把全章八节的陷阱与易错点收口成一张表,按"误解 → 正解"对照,便于回头自查。
| 误解 | 正解 | 出处 |
|---|---|---|
| 博弈是"加了对手约束的最优控制" | 博弈求的是**均衡(不动点)**,对手轨迹是它自己优化的解、依赖你的策略,不能当固定约束 | §1.1 |
| 博弈均衡唯一且必然存在 | 纳什均衡可能多个、可能不存在(纯策略下)、可能不稳定;均衡选择是**设计决策**而非数学结果 | §1.1 |
| \(\min_u\max_v=\max_v\min_u\) 总成立 | 普适的只有 \(\max\min\le\min\max\);等号需 Isaacs 条件(可分离 / 凸-凹) | §1.2 |
| 零和博弈只有"一个"值,与信息结构无关 | 值依赖信息结构;安全验证须给干扰非预期策略(瞬时信息优势)取下值,才得保守可信的安全集 | §1.2 |
| HJI 值函数处处可微,可直接用 \(\nabla V\) | 值函数普遍有不可微的**棱**(多条等价最优路径打平),是粘性解而非经典解 | §1.3 |
| "几乎处处满足方程"就是正确解 | a.e. 弱解不唯一;只有**粘性解**(黏性极限)才是唯一物理解 | §1.3 |
| 带 \(\min[0,\cdot]\) 的式子算的是 BRS | 那个冻结项给的是 BRT(管);BRS(集)无冻结项。安全验证要 BRT | §1.4 |
| 哈密顿量 max/min 随便取 | 由角色唯一决定:求存在取 \(\min\)、要对所有取 \(\max\) | §1.4 |
| 中心差分就能解 HJI | 须用尊重粘性的**单调/WENO** 格式 + 数值耗散,否则振荡或收敛到假解 | §1.5 |
| 多人 LQ = 各自独立解 LQR | 必须联立解**耦合 Riccati**;交叉项 \(P_jS_jP_i\) 正是"博弈"的全部增量 | §1.6 |
| 耦合 Riccati 一定有解 | 不保证;交叉项可致 finite escape,即便各自单人 LQR 都有解 | §1.6 |
| 神经近似(DeepReach)总优于网格 | 它用**全局保证**换可扩展;近似误差会变成安全违反,须后验证 | §1.7 |
| 状态解耦对任意系统都适用 | 依赖稀疏耦合/可定优先级的结构,否则失真或过保守 | §1.7 |
| 追逃用绝对坐标建模 | 用**相对坐标**利用平移/旋转对称性降维(如 Air3D 6→3 维) | §1.8 |
本章小结¶
本章回答了开篇那个问题——对抗交互下"最优"是什么。 答案是:不再是"最优",而是"均衡";零和博弈的均衡由 HJI 方程**刻画,它是单人 HJB 把 \(\min_u\) 换成 \(\min_u\max_v\) 的博弈推广(§1.2)。 但 HJI 的解一般不可微,须用**粘性解**才能唯一确定(§1.3);把它用于安全,就是**可达性分析——分清 BRS/BRT/reach–avoid、按角色定 max/min(§1.4);真要算出来得用尊重粘性的 WENO + TVD-RK 网格法(§1.5)。
全章的主线是一条**"从理论最优到可算近似的步步退让": HJI 给全局最优与严格安全证书,却被维度诅咒卡在约 6 维; 于是要么用**局部 LQ 近似(§1.6 的耦合 Riccati,G2 iLQGames 的内核),要么走**绕维度诅咒的三条路**(解耦 / FaSTrack / DeepReach,§1.7),各有"精确性—可扩展性—实时性"的取舍; 最后用两个经典追逃问题(§1.8)把这一切落地。 本章给 G 线打下的两块地基——可达性安全证书(→ G4、↔ U2)与**耦合 Riccati**(→ G2)——会在后续章节反复取用。
符号表¶
本章新引入的符号,全章保持一致:
| 符号 | 含义 |
|---|---|
| \(x,\ f(x,u,v)\) | 状态、动力学(耦合系统的流场) |
| \(u,v\) 或 \(a,b\) | 两玩家的控制(§1.2 用 \(u,v\);§1.4 可达性沿用文献记号 \(a\)=控制、\(b\)=干扰) |
| \(J,\ L,\ g\) | 总代价、运行(瞬时)代价、终端代价 / 目标集的带符号距离 |
| \(V(x,t)\) | 值函数(博弈的值 / 可达性值函数) |
| \(D_t V\) | 值函数对时间的偏导 \(\partial V/\partial t\)(可达性方程中沿用文献记号) |
| \(\lambda=\nabla_x V\) | 协态(值函数对状态的梯度) |
| \(H(x,\lambda)\) | 哈密顿量 \(\min_u\max_v[\lambda\cdot f+L]\)(或按角色的 \(\max_a\min_b\)) |
| \(V^-,\,V^+\) | 博弈的下值、上值;相等 ⟺ Isaacs 条件成立 |
| \(\gamma\) | 非预期策略(可看到对方当前动作再回应、不能预知未来的映射) |
| \(\zeta(s;x,t,a,b)\) | 从 \((x,t)\) 出发、在控制/干扰作用下的状态轨迹在时刻 \(s\) 的取值 |
| \(\mathcal{T},\ \mathcal{R}(t),\ \mathcal{R}_{\text{tube}}(t)\) | 目标集、后向可达集(BRS)、后向可达管(BRT) |
| \(\varepsilon\Delta V\) | 消失黏性项(定义粘性解的正则化扩散) |
| \(A,\ B_i\) | LQ 博弈的系统矩阵、玩家 \(i\) 的输入矩阵 |
| \(Q_i,\ R_{ii}\) | 玩家 \(i\) 的状态、控制代价权重 |
| \(P_i,\ K_i\) | 玩家 \(i\) 的 Riccati 解、反馈增益(\(u_i=-K_ix\)) |
| \(S_j=B_jR_{jj}^{-1}B_j^\top\) | 耦合 Riccati 中的简记(对称半正定) |
| \(\psi,\ R\) | Air3D 相对朝向、捕获半径 |
关键结论速查表¶
| 结论 | 形式 / 要点 | 节 |
|---|---|---|
| 先动者吃亏 | \(\max_v\min_u H\le\min_u\max_v H\)(普适) | §1.2 |
| Isaacs 条件 | \(\min_u\max_v=\max_v\min_u\) ⟺ 博弈有值(可分离 / 凸-凹时成立) | §1.2 |
| HJI 方程 | \(-\partial_t V=\min_u\max_v[\nabla V\cdot f+L]\),\(V(\cdot,T)=g\) | (1.1) |
| 值函数 = 唯一粘性解 | Evans–Souganidis 1984;唯一性由比较原理 | §1.3 |
| BRS 方程 | \(D_tV+H=0\),\(H=\max_a\min_b\lambda\cdot f\),无冻结项 | (1.2)(1.3) |
| max/min 口诀 | 求存在取 \(\min\)、要对所有取 \(\max\) | §1.4 |
| BRT 方程 | (1.2) 加冻结项 \(\min[0,H]\) 或 \(\min\{D_tV+H,\,g-V\}=0\) | (1.4) |
| 耦合 Riccati | \(-\dot P_i=A^\top P_i+P_iA+Q_i-P_iS_iP_i-\sum_{j\ne i}(P_jS_jP_i+P_iS_jP_j)\) | (1.5) |
| 反馈增益 | \(K_i=R_{ii}^{-1}B_i^\top P_i\) | (1.6) |
| 绕维度诅咒三路 | 解耦/STP(严格·要结构)· FaSTrack(严格·离线+保守)· DeepReach(近似·高维) | §1.7 |
知识点总表¶
| 节 | 知识点 | 难度 | 一句话 |
|---|---|---|---|
| §1.1 | 三次认知跨越 | ⭐⭐ | 最优→均衡、预测→预测即均衡、代价已知→代价需推断 |
| §1.2 | Isaacs 方程与条件 | ⭐⭐⭐ | 零和博弈的 HJI;min-max=max-min 才有值 |
| §1.3 | 粘性解 | ⭐⭐⭐ | 值函数有棱,用黏性极限唯一确定弱解 |
| §1.4 | BRS / BRT / reach–avoid | ⭐⭐⭐ | 安全验证 = 可达性;角色定 max/min;安全要 BRT |
| §1.5 | 水平集数值方法 | ⭐⭐⭐ | WENO+TVD-RK+CFL;数值耗散 = 消失黏性 |
| §1.6 | LQ 博弈与耦合 Riccati | ⭐⭐⭐ ★ | 唯一可闭式解的博弈;G2 iLQGames 的内核 |
| §1.7 | 维度诅咒与三条绕行路 | ⭐⭐⭐ | 解耦 / FaSTrack / DeepReach 的精确性-可扩展性权衡 |
| §1.8 | 追逃经典问题 | ⭐⭐ | Homicidal Chauffeur / Air3D;奇异面;相对坐标降维 |
累积项目:本章新增模块¶
本章为两条累积项目各添一块地基(详见 §1.6 练习 1、§1.8 练习 1):
| 项目 | 本章新增模块 | 内容 | 后续如何复用 |
|---|---|---|---|
| 甲(自动驾驶交互博弈规划器) | LQ 耦合 Riccati 求解器 | 用 Eigen 实现 (1.5) 的两人反馈 Nash 反向积分,在双车 unicycle 线性化模型上验证纳什 | G2 把它包进"线性化—解耦合 Riccati—更新"的迭代外壳,扩成完整 iLQGames |
| 乙(离散博弈 + 多机安全工具链) | Air3D 可达性安全验证器 | 用 hj_reachability 算 Air3D 追逃的 BRT,可视化三维捕获集 | 作为"安全包络"供项目甲调用;G4 再接 OpenSpiel/势博弈 |
两块都已在本章给出参考代码或工具调用(§1.5 的 hj_reachability 骨架、§1.6 的耦合 Riccati 参考实现),项目阶段把它们工程化、连成可复用的库。
延伸阅读¶
按难度与角色标注,括号内为定位。
奠基与系统(核心,建议精读其一) - Isaacs, Differential Games, Wiley 1965(⭐⭐⭐⭐ 原典,思想源头,行文古老、选读追逃章节即可) - Başar & Olsder, Dynamic Noncooperative Game Theory, SIAM Classics 1999(⭐⭐⭐ 核心,Ch1 静/动态博弈框架、Ch6 LQ 耦合 Riccati)
可达性(核心,工程入门首选) - Bansal, Chen, Herbert, Tomlin, "Hamilton-Jacobi Reachability: A Brief Overview and Recent Advances," CDC 2017 / arXiv:1709.07523(⭐⭐⭐ 现代综述,BRS/BRT/角色讲得最清楚,最佳入门) - Mitchell, Bayen, Tomlin, "A time-dependent Hamilton-Jacobi formulation of reachable sets for continuous dynamic games," IEEE TAC 50:947–957, 2005(⭐⭐⭐⭐ 可达性奠基,含数值方法) - Margellos & Lygeros, "Hamilton-Jacobi Formulation for Reach–Avoid Differential Games," IEEE TAC 2011(⭐⭐⭐ reach–avoid 表述)
粘性解理论(进阶,想要严格基础) - Crandall & Lions, "Viscosity solutions of Hamilton-Jacobi equations," Trans. AMS, 1983(⭐⭐⭐⭐ 粘性解原典) - Evans & Souganidis, "Differential games and representation formulas for solutions of HJI equations," Indiana Univ. Math. J., 1984(⭐⭐⭐⭐ 博弈值 = 唯一粘性解)
绕维度诅咒(进阶,前沿方法) - Bansal & Tomlin, "DeepReach: A Deep Learning Approach to High-Dimensional Reachability," ICRA 2021(⭐⭐⭐⭐ 神经近似突破维度;arXiv:2011.02082) - Herbert et al., "FaSTrack: A Modular Framework for Fast and Guaranteed Safe Motion Planning," CDC 2017(⭐⭐⭐ 规划与安全分离) - Chen et al., "Decomposition of Reachable Sets and Tubes for a Class of Nonlinear Systems," IEEE TAC 2018(⭐⭐⭐⭐ 状态解耦) - Chen, Bansal, Tomlin et al., 序贯轨迹规划(STP)系列:含对抗入侵者下的鲁棒版本("Robust Sequential Trajectory Planning...", arXiv:1611.08364)与城市无人机路由案例(arXiv:1705.04585)(⭐⭐⭐ STP 的代表性工作)
开源工具(动手) - hj_reachability(JAX,现代、最干净,本章 §1.5 示例用它) - helperOC(MATLAB,经典,教学标准,Air3D 的 Hello World) - optimized_dp(Python/HeteroCL,GPU 加速网格法)
本章与后续章节的关系¶
| 关系 | 章节 | 衔接点 |
|---|---|---|
| 直接前置 | G2 实时博弈求解器 | 本章 (1.5) 耦合 Riccati = iLQGames 每步子问题;反馈 Nash(§1.2)是 iLQGames 的输出形式 |
| 间接前置 | G3 逆博弈 | 可微博弈用隐函数定理对 Nash 解的 KKT 求导——KKT 即本章一阶最优性的推广 |
| 工具复用 | G4 安全证书与 MARL | HJI 安全值函数 ↔ CBF(§1.4 的最小限制滤波器即 CBF 思想);可达性安全集 |
| 跨专题对照 | U2 鲁棒规划 / CBF | BRT ↔ Tube MPC 的 RPI 集(§1.4 已建桥,U2 从 Tube 那侧再讲) |
| 跨专题对照 | U4 POMDP | 不完全信息博弈 ⊆ POMDP 的博弈版(G3 会用) |
| 跨模块对照 | SLAM 因子图 | 耦合 Riccati 离散块三对角 ↔ 因子图稀疏 Hessian(G2 代码精读再用) |
| 跨模块对照 | 数学·李群 | SE(3) 上的追逃博弈(相对位姿在李群上) |
🔧 故障排查手册¶
把本章实践中最常撞的坑整理成"症状 → 可能原因 → 排查步骤 → 相关节"。
| 症状 | 可能原因 | 排查步骤 | 节 |
|---|---|---|---|
| 可达管(BRT)算出来全空 / 方向反了 | reach 与 avoid 的 max/min 取反;动力学方向写错 | 1. 按口诀核对每个玩家是 \(\exists\)(min) 还是 \(\forall\)(max) 2. 确认是否启用 BRT 冻结项 3. 把干扰强度调 0,看是否退化为单人可达集 | §1.4 |
| BRT 边界有毛刺 / 数值振荡 | 用了不带耗散的格式(如中心差分);网格太粗 | 1. 换 WENO / 单调格式 2. 加密网格看是否收敛变光滑 | §1.5 |
| 细化网格后数值发散 / 出现 NaN | 违反 CFL 条件 | 1. 让 \(\Delta t\lesssim\Delta x/\alpha\) 2. 网格加密时同步减小 \(\Delta t\) | §1.5 |
| 耦合 Riccati 反向积分发散 | 解不存在 / 无界(finite escape) | 1. 检查 \(Q_i,R_{ii}\) 是否合理 2. 缩短时域 \(T\) 3. 加正则化(G2 做法) | §1.6 |
| 多人 LQ 增益不对 / 不是纳什 | 当成独立 LQR、漏了交叉项 | 1. 检查 RHS 是否含 \(-\sum_{j\ne i}(P_jS_jP_i+P_iS_jP_j)\) 2. 固定他人增益、重解单人 LQR 对照 | §1.6 |
| Air3D 可达集不对称 / 形状怪 | 相对坐标变换写错;\(\psi\) 维未取周期边界 | 1. 重核相对动力学推导 2. 确认 periodic_dims 含角度维 |
§1.8 |
| DeepReach 值函数导致安全违反 | 神经近似误差,失全局保证 | 1. 对值函数做 rollout 后验证 2. 上认证方法,勿直接信任 | §1.7 |
研究实践建议¶
给新手(先建直觉,再抠理论)。 最快建立 HJI 直觉的路径:先用 hj_reachability 把 §1.5 那段 Air3D BRT 跑起来、可视化捕获集,改改速度/转弯率看它怎么变; 再回头手推一次 §1.6 的两人标量耦合 Riccati,并用 §1.6 参考实现验证。 "先跑通、再推导、再验证"这个顺序,比一上来啃 Isaacs 原典高效得多。 读论文从 Bansal 等 2017 的 overview 入手,它是本领域最友好的现代综述。
给有经验者(往前沿走)。 本章的零和可达性是干净但受限的——前沿在三处: 其一,维度诅咒**仍是主战场,神经近似(DeepReach 路线)是突破方向,但"近似 + 可证明安全认证"如何兼得是开放问题; 其二,**general-sum HJI(非零和的可达性)理论尚不完整,是值得啃的硬骨头; 其三,与学习的结合——逆博弈(从观测推断对手代价,G3)、把 HJI 值函数当 CBF 在线更新(§1.7 的参数条件可达集),都是博弈 + 学习交叉的活跃方向。 工程上,FaSTrack 这类"严格保证 + 实时"的折中最受产业欢迎,值得吃透其离线-在线分工。
G1 完结。 回到开篇的十字路口:我们不再问"我的最优轨迹是什么",而问"在对手也最优的前提下,什么是稳定的均衡"——零和情形由 HJI 方程与可达性回答,并留下了耦合 Riccati 这把钥匙。G2 将带着它,从"理论最优"走进"毫秒级实时",让博弈规划真正跑在车上。