跳转至

U3 机会约束规划:在"硬保证"与"期望最优"之间精确取舍

本章定位:⚪ 跨方向共享**的一章。机会约束(Chance Constraint, CC)规划允许约束以一个**可控的小概率 \(\delta\) 违反——\(\Pr(g(x)\le 0)\ge 1-\delta\)——它是 U2"对扰动集 100% 硬保证"(Tube MPC)与"只优化期望、不管违反"(风险中性 MPC)之间的**精确中间地带**。无人机 CC 避障、航天器轨迹规划、多机协同、四足摩擦锥安全里都有它的直接落地。

读者画像:已完成 U2(鲁棒规划与安全滤波),理解 Tube MPC 的约束收紧、GP-MPC 的 \(\Phi^{-1}(1-\delta)\) 收紧、凸优化(QP/SOCP/SDP 基础概念)、高斯分布与正态分位数。

在累积项目中的位置:U2 给统一导航测试台装了"硬避障 + 鲁棒余量";本章把硬避障**放松成"碰撞概率 ≤ δ"**——同一个测试台,把 HOCBF 的硬约束换成 CC 收紧,扫 \(\delta\) 画出"风险预算 ↔ 性能"的权衡曲线。这正是 U2 累积项目"机会约束进阶"埋下的接口。

本章与 U2 的衔接:U2 §U2.4 已经用过一次"协方差传播 + \(\Phi^{-1}(1-\delta)\) 收紧"(GP-MPC 那条线)。本章把这套逻辑**系统化、一般化**——从单步收紧扩到整条轨迹的联合保证(JCC)、从均分风险扩到最优分配(IRA)、从绑进 MPC 扩到嵌入采样规划(CC-RRT)与显式塑形分布(Covariance Steering)。一句话:U2 是 CC 的 δ→0 极限(硬保证),CC 是 U2 的概率松弛


前置自测

进入本章前,确认以下 5 题。答不出 \(\ge 2\),建议先补对应前置(多数在 U2 与 Part 0)。

  1. 高斯随机变量 \(X\sim\mathcal{N}(\mu,\sigma^2)\)\(\Pr(X\le b)\ge 1-\delta\) 等价于关于 \(\mu\) 的什么确定性不等式?(不会 → 回 U2 §U2.4 / 正态分位数)
  2. 线性变换下高斯保持高斯:若 \(x\sim\mathcal{N}(\bar x,\Sigma)\),则 \(a^\top x\) 服从什么分布?均值、方差各是多少?(不会 → 回概率论基础)
  3. 什么是 SOCP(二阶锥规划)?约束 \(\|Fx+g\|_2\le c^\top x+d\) 是什么形状?为什么它是凸的?(不会 → 回 Part 0 凸优化)
  4. Boole 不等式(union bound):\(\Pr(\bigcup_i A_i)\le\sum_i\Pr(A_i)\),它给出的是上界还是下界?等号何时成立?(不会 → 回概率论基础)
  5. 闭环线性系统 \(x_{k+1}=(A-BK)x_k+w_k\)\(w_k\sim\mathcal{N}(0,\Sigma_w)\)),状态协方差 \(P_k\) 如何逐步演化?(不会 → 回 U2 §U2.1 / 卡尔曼滤波)

这 5 题对应本章支柱:高斯 CC 收紧(第 1、2 题)、SOCP(第 3 题,CC 凸化的落点)、Boole 不等式(第 4 题,JCC→ICC 拆解的根据)、协方差传播(第 5 题,CC-RRT/CS 的核心)。


本章目标

学完本章后,你应该能够:

  1. 区分 ICC(单步机会约束)与 JCC(联合机会约束),说清"每步独立满足"与"整条轨迹联合满足"的差别,以及为什么 JCC 更关键也更难;
  2. Boole 不等式 + 风险分配 把 JCC 拆成一族 ICC,并理解均分风险为什么保守;
  3. 推导 解析高斯 CC:正态下 \(\Pr(a^\top x\le b)\ge 1-\delta\) 如何等价于一个**确定性的约束收紧 margin**,并落到 SOCP/QP;
  4. 实现 IRA(迭代风险分配):外层分配风险预算、内层解凸问题,理解它为何比均分保守度低得多;
  5. 理解 CC-RRT 的算法:采样生长 + 链式协方差传播 + 概率可行性检验,剔除违反概率 > δ 的节点;
  6. 理解 Covariance Steering 的核心思想:不仅规划均值轨迹、还显式塑形协方差,让系统在狭缝处"收缩"不确定性;并理解为什么有 CC 时均值与协方差不可解耦;
  7. 认识 CC 与 Safe RL(CMDP)的数学关系——IRA 的风险分配与 PPO-Lagrangian 的乘子调节是同一优化问题的 primal-dual 两端。

在六个核心点之外,本章后半同样提供**方法选型决策指南**、从 Python 原型到 C++ 部署(CC 的 C++ 生态几乎空白,是做原创贡献的最佳方向之一)、以及把累积项目推广到 **CC 版避障**的进阶。


本章知识导航 ⭐

本章沿一条主线展开:把"约束必须 100% 满足"放松成"以概率 \(1-\delta\) 满足",并把这个概率约束化成可解的凸问题

              硬约束(Tube MPC,U2)        期望最优(风险中性 MPC)
                        │                          │
                        └──────────┬───────────────┘
                        机会约束 Pr(g≤0) ≥ 1-δ(精确中间地带)
              ┌────────────────────┼────────────────────┐
        如何形式化               如何凸化                如何嵌入规划器
        §U3.1 ICC/JCC        §U3.2 近似方法谱        §U3.3 CC-RRT
        Boole + 风险分配      (高斯/Cantelli/         §U3.4 Covariance
        §U3.2 IRA             场景法/DR-CC)            Steering
                §U3.5 与 Safe RL(CMDP) 的 primal-dual 关系

本章方法谱系(这条线怎么来的):机会约束由运筹学的 Charnes–Cooper 在 1959 年提出(概念与确定性等价);2006 年 Nemirovski–Shapiro、Calafiore–El Ghaoui 证明一般 CC 是 NP-hard 并给出凸(CVaR/矩)上界与分布鲁棒版本;2008 年 Campi–Garatti 的场景法用采样绕开分布假设;同年 Ono–Williams 提出 IRA 用风险分配大幅降低保守度;2010 年起 Luders–How 把 CC 嵌入 RRT(CC-RRT);2018 年 Okamoto–Tsiotras 提出带 CC 的协方差控制(Covariance Steering);2020 年后 DR-CC(Lew–Pavone 等)处理分布不确定性,2024 年后 CC 首次落到四足/机械臂实机。各方法的精确出处在对应小节给出并已逐一核实。

小节 主题 难度
§U3.1 机会约束的形式化:ICC / JCC / Boole ⭐⭐
§U3.2 CC 近似方法谱与 IRA ⭐⭐⭐
§U3.3 CC-RRT / CC-RRT* ⭐⭐⭐
§U3.4 Covariance Steering ⭐⭐⭐⭐
§U3.5 与 Safe RL(CMDP)的关系 ⭐⭐⭐

推荐阅读路径:§U3.1(形式化)与 §U3.2(高斯收紧 + IRA)是全章地基,务必读透——它们直接续上 U2 §U2.4。若你的目标是"在 MPC 里用上 CC",读完 §U3.1/§U3.2 即可上手;§U3.3(采样规划)、§U3.4(协方差塑形)是两条进阶分支;§U3.5 把 CC 与强化学习接上,适合做 RL 的读者。


前置知识桥接

回顾——U2 的 \(\Phi^{-1}(1-\delta)\) 收紧:在 GP-MPC(§U2.4)里你已经见过,对 \(x\sim\mathcal{N}(\mu,\Sigma)\),机会约束 \(\Pr(c^\top x\le b)\ge 1-\delta\) 等价于把名义约束向内收紧 $\(c^\top\mu\ \le\ b-\Phi^{-1}(1-\delta)\sqrt{c^\top\Sigma c}.\)$ 本章做的事,是把这一个收紧**用到极致**:扩到整条轨迹(JCC)、扩到最优风险分配(IRA)、扩到采样规划(CC-RRT)、扩到显式塑形协方差(CS)。

回顾——Tube MPC 的硬约束收紧:U2 §U2.1 把 \(\mathcal{X}\ominus\Omega\) 作为对**有界**扰动集 \(\mathcal{W}\) 的 100% 收紧。CC 处理的是**无界**(如高斯)扰动——零违反概率不可能,于是退而求"违反概率 ≤ δ",收紧量从"管道半宽 \(\Omega\)"变成"\(\Phi^{-1}(1-\delta)\times\) 标准差"。Tube 是 CC 在 δ→0、扰动有界时的极限

本章在前置之上加什么:U2 给"对最坏情况的硬保证",本章给"对概率分布的、可调风险的保证"。关键转变是——把"违反概率"当成一种**可分配、可优化的预算**(风险预算 \(\delta\)),而不是一个非 0 即 1 的开关。

本质洞察:机会约束的精髓是把"安全"从一个**布尔判断**(撞/不撞)变成一个**连续资源**(违反概率 \(\delta\))。一旦安全成了可分配的预算,你就能问出 U2 问不出的问题:把有限的风险预算花在哪一步、哪个约束上最划算?这就是 IRA(§U3.2)的全部动机,也是 CC 相对 Tube 的根本优势来源——用"接受一点点风险"换"少很多保守度"


如果跳过本章会怎样

场景一:Tube MPC 在高斯扰动下根本无解。 你想用 U2 的 Tube MPC 处理一个风扰动的无人机,但风是高斯的(无界)——理论上任意大的风都有非零概率,Tube 要求的"有界扰动集 \(\mathcal{W}\)"不存在,硬保证无从谈起。CC-MPC(§U3.2)给出出路:接受"被吹出边界的概率 ≤ 1%",问题立刻可解,且保守度可控。

场景二:手调安全 margin,要么太保守要么不够。 你给 MPC 的约束手动加了固定 margin 防扰动,但窄通道里 margin 太大过不去、放小了又偶尔撞。CC(§U3.1)把 margin 从"拍脑袋的常数"变成"由协方差与风险 δ 算出来的量"——该大则大、该小则小,且违反概率有形式化保证。U2 的四足 CC-MPC 案例(Trivedi 2025)正是用 CC 取代手调 margin,在 Unitree Go1 上扛起超过自重 50% 的未知负载、无需重新调参。

场景三:采样规划器(RRT)完全不管不确定性。 你用 RRT 规划,但它假设状态精确、障碍精确,真机一扰动路径就不可行。CC-RRT(§U3.3)在 RRT 生长时沿边传播协方差、按概率剔除危险节点,让采样规划器也获得"路径以 1−δ 概率安全"的保证。

这三个场景会在累积项目的 CC 模块里被复现:把 U2 测试台的硬避障换成 CC 收紧,看碰撞率如何被精确控制在 δ 以下、保守度如何随 δ 调节。


预计阅读时间

阅读方式 时间 适合谁
精读(含推导 + 实现解析 CC-MPC 与 IRA + CC-RRT) 14–18 小时 第一次系统学机会约束规划的读者
速读(抓 §U3.1 形式化 + §U3.2 高斯收紧/IRA,跳过 CS/CMDP 推导) 4–5 小时 有 MPC 背景、要快速在 MPC 里用上 CC 的工程师
速查(只看方法对比表 + 故障排查 + API 速查) 40 分钟 已在实现、回来查某个公式或选型

§U3.1 机会约束的形式化:ICC / JCC / Boole ⭐⭐

动机:无界扰动下,"零违反"是个伪命题

U2 的 Tube MPC 对**有界**扰动 \(w\in\mathcal{W}\) 给 100% 保证。但现实里很多扰动是**无界**的——高斯风扰、传感器高斯噪声、未建模残差。对无界扰动,"零违反概率"在数学上不可能(任意大的扰动都有非零概率)。于是问题必须换个问法:不再要求"绝不违反",而是要求"违反的概率不超过一个我能接受的小值 \(\delta\)"。这就是机会约束。\(\delta\) 是你愿意为"少保守、多性能"付出的风险代价——\(\delta=0.01\) 表示允许 1% 的违反概率。

理论:ICC 与 JCC 两种形式

单步机会约束(Individual Chance Constraint, ICC)——约束每个时步、每个约束面**独立**满足: $\(\Pr\big(a_j^\top x_k\le b_j\big)\ge 1-\delta_j,\qquad \forall k,\ \forall j.\)$ 直觉(赛车例子):ICC 限制的是"在**某一个**时刻撞墙的概率"。

联合机会约束(Joint Chance Constraint, JCC)——约束**整条轨迹的所有约束一起**满足: $\(\Pr\Big(\bigcap_{k=0}^{N}\bigcap_{j=1}^{M} a_j^\top x_k\le b_j\Big)\ge 1-\delta.\)$ 直觉:JCC 限制的是"**从起点到终点全程**至少撞一次墙的概率"。

为什么 JCC 更关键也更难:你真正关心的几乎总是 JCC——"这趟飞行安全到达的概率 ≥ 99%",而不是"每一个时刻单独看安全的概率 ≥ 99%"。但 JCC 里那个对所有 \(k,j\) 取交集的联合概率,一般**没有解析表达**(涉及多维相关事件的联合分布),直接算不可行。ICC 则因为每个约束独立、在高斯下有解析形式(下一节推),好算得多。核心技术难题就是:如何用一族好算的 ICC 来保证一个难算的 JCC。

Boole 不等式:把 JCC 拆成一族 ICC

桥梁是 Boole 不等式(union bound):任意事件 \(A_{j,k}\)(这里取"第 \(k\) 步第 \(j\) 个约束被违反"), $\(\Pr\Big(\bigcup_{j,k} A_{j,k}\Big)\le\sum_{j,k}\Pr(A_{j,k}).\)$ "全程至少违反一次"的概率 = \(\Pr(\bigcup A_{j,k})\)。若我们让每个单独事件的违反概率 \(\Pr(A_{j,k})\le\delta_{j,k}\),且 \(\sum_{j,k}\delta_{j,k}\le\delta\),则: $\(\Pr(\text{全程违反})\le\sum_{j,k}\delta_{j,k}\le\delta\ \Longrightarrow\ \Pr(\text{全程不违反})\ge 1-\delta.\)$ 于是 JCC 被一族 ICC 保证了:只要每个 ICC 用各自的小风险 \(\delta_{j,k}\)、且这些小风险加起来不超过总预算 \(\delta\),JCC 自动成立。这把"难算的联合概率"换成了"好算的一族单步概率 + 一个求和约束"。

关键代价:Boole 不等式是保守的。union bound 只在各违反事件**互斥**时取等;实际中它们常重叠(同一段轨迹可能在相邻时刻同时接近同一面墙),所以 \(\sum\delta_{j,k}\) 高估了真实联合违反概率——这意味着用 Boole 拆出来的 JCC 解**偏保守**(真实违反概率往往远小于 δ)。这点保守度是"把难算问题变好算"的代价,也是后面 IRA、以及更紧的 risk-bounding 方法想要部分挽回的东西。

风险分配:\(\delta_{j,k}\) 怎么分?

Boole 只要求 \(\sum_{j,k}\delta_{j,k}\le\delta\),但**怎么把总预算 \(\delta\) 分给各个 \(\delta_{j,k}\)**,大有讲究:

  • 均分(uniform allocation)\(\delta_{j,k}=\delta/(NM)\)。最简单,但很保守——它给"离障碍很远、几乎不可能违反"的约束和"贴着障碍、很危险"的约束分了**一样多**的预算,浪费。
  • 最优分配(IRA,§U3.2):把预算从"过度宽松"的约束(距离 ≫ margin)转移给"紧绷"的约束。直觉:风险预算是稀缺资源,该花在刀刃(紧约束)上。

下一节会看到,最优分配能在同样的 JCC 保证下,把保守度降低一大截——这正是 Ono–Williams 的 IRA 的核心贡献。

多视角理解:ICC 与 JCC 的三种看法 - 照片 vs 视频:ICC 像要求"每一张快照都合格"(每个时刻单独看,安全概率 ≥1−δ);JCC 像要求"整段视频合格"(从头到尾不出一次事的概率 ≥1−δ)。像/不像:两者都用"概率 ≥1−δ"度量安全,但 ICC 是逐帧、JCC 是全程——JCC 更严,也更是你真正想要的。 - 概率视角:ICC 限制单个事件的边缘概率,JCC 限制一族事件并集的概率;Boole 不等式是从前者推后者的桥(用求和上界换可解性)。 - 工程视角:ICC 好算(每步独立、高斯下解析),JCC 难算(联合分布无解析)——所以工程上几乎总是"用一族 ICC + Boole 拼出 JCC",代价是保守。

⚠️ 本节常见误区

💡 概念误区:把 ICC 当成 JCC 用 - 新手想法:"我对每一步都加了 \(\Pr(\text{违反})\le\delta\),那整条轨迹的违反概率也是 δ 吧?" - 现象/后果:实际整条轨迹的违反概率远大于 δ——若每步独立违反概率都是 δ、共 N 步,全程至少违反一次的概率接近 \(1-(1-\delta)^N\approx N\delta\),是单步的 N 倍。 - 根本原因:ICC 管单步、JCC 管全程,两者差一个 union bound。把 N 个 ICC 各设为 δ,等于把 JCC 放松到了 \(N\delta\)。 - 正确做法:要 JCC=δ,每个 ICC 应设为 \(\delta_{j,k}\)\(\sum\delta_{j,k}\le\delta\)(如均分 \(\delta/(NM)\) 或 IRA 最优分配)。检验方法:蒙特卡洛统计"整条轨迹"的违反率,而非"单步"违反率。

🧠 思维陷阱:以为 Boole 拆解是"精确"的 - 新手想法:"用 Boole 不等式拆 JCC,保证就是紧的。" - 现象/后果:实际解出来的轨迹比真正需要的更保守(真实违反概率 ≪ δ),白白牺牲性能。 - 根本原因:Boole 是**不等式**(上界),只在违反事件互斥时取等;事件重叠越多,越保守。 - 正确做法:接受这点保守度(换来可解性),或在保守度敏感时用更紧的方法(如直接 risk-bounding、或 IRA 部分挽回)。检验方法:对比解的真实违反率与设定 δ,差距大说明 Boole 保守度高。

练习

  1. [A 型·数值] 对 1D 高斯 \(X\sim\mathcal{N}(0,1)\),分别算 \(\delta=0.1,0.05,0.01\) 对应的 \(\Phi^{-1}(1-\delta)\)(即约束收紧系数)。验证 δ 越小、系数越大、收紧越多。
  2. [思考题] 一条 20 步轨迹,每步 1 个约束,要求 JCC 总违反概率 ≤ 0.05。若均分,每步 ICC 的 δ_k 是多少?对应的 \(\Phi^{-1}(1-\delta_k)\) 比 JCC 直接用 0.05 大多少?这个差距就是 Boole + 均分的保守度代价。
  3. [B 型·蒙特卡洛] 构造一个 2D 高斯随机游走轨迹,分别按"每步 ICC=0.05"和"整条 JCC=0.05(均分)"设约束,蒙特卡洛对比两者的**整条轨迹**违反率,直观感受 ICC≠JCC。

§U3.2 CC 近似方法谱与 IRA ⭐⭐⭐

动机:一般 CC 是 NP-hard,必须找可解的近似

坏消息先说:一般的机会约束优化是 NP-hard 的(Nemirovski–Shapiro 2006、Calafiore–El Ghaoui 2006)——可行域 \(\{x:\Pr(g(x)\le 0)\ge 1-\delta\}\) 一般**非凸**。好消息是:在特定假设(如高斯 + 线性约束)下,或用合适的凸上界,CC 可以化成**可高效求解的凸问题**(QP/SOCP/SDP)。这一节先给最重要的解析高斯收紧(直接续 U2 §U2.4),再铺开方法谱,最后讲 IRA。

理论:解析高斯 CC 的完整推导

设状态(或约束量)\(x\sim\mathcal{N}(\bar x,\Sigma)\),线性约束 \(a^\top x\le b\),要 \(\Pr(a^\top x\le b)\ge 1-\delta\)。推导四步:

  1. 线性变换保持高斯\(y\triangleq a^\top x\) 是高斯,\(y\sim\mathcal{N}(a^\top\bar x,\ a^\top\Sigma a)\)。记标准差 \(s=\sqrt{a^\top\Sigma a}\)
  2. 标准化\(\Pr(y\le b)=\Pr\!\Big(\frac{y-a^\top\bar x}{s}\le\frac{b-a^\top\bar x}{s}\Big)=\Phi\!\Big(\frac{b-a^\top\bar x}{s}\Big)\),其中 \(\Phi\) 是标准正态 CDF。
  3. 施加约束:要 \(\Phi\!\big(\frac{b-a^\top\bar x}{s}\big)\ge 1-\delta\),两边取单调的 \(\Phi^{-1}\)\(\frac{b-a^\top\bar x}{s}\ge\Phi^{-1}(1-\delta)\)
  4. 整理成确定性约束: $\(\boxed{\ a^\top\bar x\ \le\ b-\Phi^{-1}(1-\delta)\,\sqrt{a^\top\Sigma a}\ }\)$

解读:原约束的均值版 \(a^\top\bar x\le b\) 被**向内收紧**了 \(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\)。这就是 U2 §U2.4 用过的那个收紧——现在你看到了它的完整出处。收紧量由两部分构成:\(\Phi^{-1}(1-\delta)\)(风险因子,δ 越小越大;δ=0.05→1.645,δ=0.01→2.326)× \(\sqrt{a^\top\Sigma a}\)(约束方向上的标准差,不确定性越大越大)。

为什么这是 SOCP\(\sqrt{a^\top\Sigma a}=\|\Sigma^{1/2}a\|_2\) 是一个二范数。若把决策变量(如均值轨迹、协方差参数)代入,约束形如 \(a^\top\bar x+\Phi^{-1}(1-\delta)\|\Sigma^{1/2}a\|_2\le b\)——左边是"线性项 + 二范数项",正是**二阶锥(SOC)约束**的标准形。所以解析高斯 CC-MPC 是一个 SOCP(若 \(\Sigma\) 固定、只优化均值,且约束是线性的,常可进一步简化为 QP + 锥约束)。

本质洞察:CC 收紧 = 把分位数变成 margin。整个解析高斯 CC 的魔法只有一句话:概率约束 \(\Pr(\cdot)\ge 1-\delta\) 等价于在确定性约束上加一个正比于"标准差 × 分位数"的安全 margin。δ 控制分位数(要多稳),\(\Sigma\) 控制标准差(有多不确定),两者相乘就是该收多少。理解了这一句,CC-MPC、CC-RRT、CS 的约束处理你就全懂了——它们都在反复用这一个收紧。

多视角理解:解析高斯收紧的三种看法 - 几何视角:把约束面(墙)沿其法向**向内平移** \(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\)——名义轨迹在"挪近的墙"内走,真实轨迹(带不确定性)就以 ≥1−δ 概率不越原墙。 - 概率视角:margin 恰好"罩住"高斯分布在该方向上 \(1-\delta\) 的概率质量;δ 越小、要罩住的尾部越多,margin 越大。 - 优化视角\(a^\top\bar x+\Phi^{-1}(1-\delta)\|\Sigma^{1/2}a\|_2\le b\) 是一个二阶锥约束——CC 把"概率约束"翻译成了凸优化能直接吃的 SOC 约束。

三个视角是同一个公式的三张面孔,分别服务"建立直觉 / 理解概率含义 / 知道怎么求解"。

CC 近似方法谱

解析高斯只是一种近似。完整的方法谱按"分布假设强弱"排列:

方法 分布假设 求解类型 保守性 维度可扩展性 代表工作
解析高斯 \(\Phi^{-1}\) 高斯 SOCP/QP ICC 精确 极好 Blackmore–Ono–Williams 2011
Cantelli / 椭球 仅知 \(\mu,\Sigma\) SOCP 保守 极好 Calafiore–El Ghaoui 2006
Boole + IRA 高斯/矩 外层 NLP + 内层 SOCP 可收敛 Ono–Williams 2008
粒子 / 场景 MILP 任意 MILP 样本越多越准 Blackmore et al. 2010
场景法(scenario) 分布无关 LP/QP 由样本数控制 Campi–Garatti 2008
DR-CC(Wasserstein/矩) 分布族 SDP/SOCP 最保守(数据少最稳) Calafiore–El Ghaoui 2006;Lew–Pavone 2020+

逐个要点: - 解析高斯:最快最准,但要求高斯。ICC 下精确,JCC 下配 Boole。 - Cantelli(单边 Chebyshev):只知道均值和协方差、不知分布形状时,用 \(\Pr(a^\top x\le b)\ge 1-\delta\) 的 Cantelli 收紧系数 \(\sqrt{(1-\delta)/\delta}\) 代替 \(\Phi^{-1}(1-\delta)\)。无需高斯假设,但更保守(如 δ=0.05:Cantelli 系数 ≈4.36,高斯仅 1.645)。 - 粒子 / 场景 MILP:用大量采样的扰动粒子,把"违反粒子比例 ≤ δ"写成 MILP(二元变量标记每个粒子是否违反)。可处理**任意分布**,但 MILP 随粒子数/时步爆炸,维度可扩展性差。 - 场景法(Campi–Garatti 2008):用 N 个独立采样的约束替换概率约束,给出**分布无关**的样本复杂度界——采样数 N 足够大时,解以高概率满足原 CC。优雅且通用,代价是 N 可能很大。 - DR-CC(分布鲁棒 CC):连分布都不确定时,对"一个分布族(矩约束 / Wasserstein 球)内的最坏分布"保证 CC。最稳健(尤其数据少时),化成 SDP/SOCP。这是 U2 理论补遗里 DRO 思想在 CC 上的落地。

工程选择:高频 MPC 首选"解析高斯 + IRA"(快+准);分布明显非高斯 → 粒子/场景 MILP 或场景法;有限数据 + 分布模糊 → Wasserstein DR-CC。

IRA:迭代风险分配(Ono–Williams, CDC 2008)

§U3.1 说均分风险很保守。IRA(Iterative Risk Allocation) 用一个两阶段迭代把风险预算分到刀刃上:

  • 下层(lower-stage):给定当前风险分配 \(\{\delta_{j,k}\}\),每个 ICC 收紧成确定性约束(解析高斯 margin),解一个**凸问题**(LP/QP/SOCP)得最优均值轨迹。
  • 上层(upper-stage):固定下层轨迹,**重新分配**风险——把"不活跃约束"(实际距离 ≫ 收紧 margin,即风险没用满)的多余预算,转移给"活跃约束"(贴着边界、margin 吃紧)。上层目标是凸的(但不总可微),用快速下降算法求解。
  • 迭代:下层、上层交替,直到风险分配收敛、总代价不再下降。

为什么有效:均分把预算平摊给所有约束,但大部分约束根本用不到那么多(离障碍远)。IRA 把这些浪费的预算挪给紧约束,让紧约束能用更大的 \(\delta_{j,k}\)(更小的收紧 margin),于是整体可行域更大、轨迹更优。Ono–Williams 证明:IRA 的次优性远小于椭球松弛法,同时比粒子法(MILP)快得多——它卡在"保守度"与"计算量"权衡的一个甜点上。

本质洞察:IRA = 风险预算的"按需分配"。把违反概率 δ 想成一笔钱,均分是"人人平均发",IRA 是"按需分配——谁紧给谁多"。数学上,IRA 是在 ICC 的可行性约束下最小化总代价、对风险分配 \(\{\delta_{j,k}\}\) 做优化;这与 §U3.5 会讲的 Safe RL 拉格朗日乘子自适应,是同一问题的两端。

IRA 的算法骨架

import numpy as np

def ira(solve_lower, active_margin, delta_total, NM, n_iter=20, tol=1e-4):
    """迭代风险分配(IRA)外层骨架。
    solve_lower(deltas) -> (cost, traj, slack):给定各约束风险,解下层凸问题,
        返回总代价、轨迹、以及各约束的 slack(实际距离 - 收紧 margin,>0 表示不活跃)。
    active_margin: 判定约束是否"活跃"的 slack 阈值。
    delta_total: JCC 总风险预算 δ;NM: 约束总数(N*M)。"""
    deltas = np.full(NM, delta_total / NM)        # 初始:均分
    prev_cost = np.inf
    for _ in range(n_iter):
        cost, traj, slack = solve_lower(deltas)   # 下层:凸问题
        active = slack <= active_margin           # 活跃约束(margin 吃紧)
        n_active = max(int(active.sum()), 1)
        # 上层:把不活跃约束的多余风险,转移给活跃约束
        #  - 不活跃约束:调小其 δ(它们用不到,收回预算)
        #  - 活跃约束:均分收回的预算(让它们 margin 更松)
        residual = deltas[~active].sum() * 0.5    # 收回不活跃约束一半预算(阻尼)
        deltas[~active] *= 0.5
        deltas[active]  += residual / n_active
        deltas = np.clip(deltas, 1e-6, None)
        deltas *= delta_total / deltas.sum()      # 重新归一化,确保 Σδ = δ_total
        if abs(prev_cost - cost) < tol:           # 代价收敛则停
            break
        prev_cost = cost
    return deltas, traj

这是教学版骨架:核心是"收回不活跃约束的风险、补给活跃约束、保持总和不变"。严格的 IRA 上层用次梯度/精确线搜索,且有收敛性证明(Ono–Williams 2008),此处用阻尼比例转移示意机制。solve_lower 内部对每个约束用解析高斯 margin \(\Phi^{-1}(1-\delta_{j,k})\sqrt{a^\top\Sigma a}\) 收紧后解 QP/SOCP。

⚠️ 本节常见误区

💡 编程陷阱:忘记重新归一化导致风险预算超支 - 现象/后果:IRA 迭代几轮后,\(\sum\delta_{j,k}\) 悄悄超过 δ,JCC 保证失效,蒙特卡洛违反率超标。 - 根本原因:风险转移时若只加不减、或数值误差累积,总和会漂移。 - 正确写法:每轮迭代后强制 deltas *= delta_total / deltas.sum() 重新归一化(如上骨架),确保 \(\sum\delta_{j,k}=\delta\) 始终成立。 - 检验方法:每轮打印 deltas.sum(),应恒等于 δ。

💡 概念误区:以为 Cantelli 和高斯收紧可以混用 - 新手想法:"都是收紧 margin,用哪个系数无所谓。" - 现象/后果:明明是高斯却用 Cantelli(系数 4.36 vs 1.645),过度保守;或明明非高斯却用高斯系数,违反概率超标。 - 根本原因\(\Phi^{-1}(1-\delta)\) 依赖高斯假设;Cantelli 系数 \(\sqrt{(1-\delta)/\delta}\) 只用均值方差、对任意分布成立但保守。 - 正确做法:确认分布——高斯(或近似高斯)用 \(\Phi^{-1}\);只知矩、分布未知用 Cantelli;明显非高斯用粒子/场景法。

🧠 思维陷阱:以为 IRA 能消除 Boole 的保守度 - 新手想法:"IRA 优化了风险分配,那 Boole 的保守度就没了。" - 现象/后果:期望 IRA 解的真实违反率正好等于 δ,结果仍明显小于 δ。 - 根本原因:IRA 优化的是"在 Boole 框架内**怎么分**预算",但 Boole 的 union bound 上界本身的保守度(事件重叠导致)IRA 消不掉——IRA 让分配最优,不让 Boole 变精确。 - 正确做法:理解 IRA 减的是"均分 vs 最优分配"的保守度,不是"Boole 上界"的保守度。两者叠加;要进一步减后者需更紧的联合风险界。

练习

  1. [A 型·解析 CC-MPC,累积项目 CC 起点] 对 2D 双积分器 + 高斯过程噪声实现解析 CC-MPC:每个障碍面用 \(\Phi^{-1}(1-\delta)\) margin 收紧,OSQP 求解。蒙特卡洛 1000 次验证碰撞率 ≤ δ;对比 δ=0.01 与 δ=0.1 的轨迹保守度差异。
  2. [A 型·IRA 实现] 在上面的 CC-MPC 上实现 IRA:外层分配 \(\delta_{j,k}\)、内层解 QP/SOCP。对比 IRA 与均分在同一窄通道任务上的代价与可行性,定量说明 IRA 降了多少保守度。
  3. [B 型·方法对比] 对同一 CC 问题分别用解析高斯、Cantelli、场景法(采样)三种近似,对比它们的保守度(实际违反率距 δ 多远)与求解时间。
  4. [思考题] 为什么有 CC 时一般问题非凸、但高斯 + 线性约束下变凸?(提示:\(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\) 关于均值是线性的、关于决策变量是二阶锥的,凸性来自这里;而一般分布/非线性约束破坏这个结构。)

§U3.3 CC-RRT / CC-RRT* ⭐⭐⭐

动机:让采样规划器也懂不确定性

前两节的 CC 都绑在**优化型**规划器(MPC)里。但机器人学里另一大类规划器是**采样型**的——RRT、RRT*、PRM。它们假设状态精确、障碍精确,真机一有扰动/定位误差,规划出的路径就可能不可行。CC-RRT(Luders, Kothari, How, AIAA GNC 2010) 把机会约束嵌进 RRT:树生长时沿每条边**传播状态协方差**,按"违反概率 ≤ δ"剔除危险节点,从而让采样规划器输出的路径带有"以 1−δ 概率安全"的形式化保证。

理论:CC-RRT 的三个核心机制

设定:线性系统 \(x_{k+1}=Ax_k+Bu_k+w_k\),过程噪声 \(w_k\sim\mathcal{N}(0,\Sigma_w)\);障碍用半空间 \(a_j^\top x\le b_j\) 描述(凸障碍是若干半空间的交);总风险预算 δ。

机制一:闭环协方差传播。RRT 每生长一条边(一段标称轨迹),就沿这条边把状态协方差往前传。在反馈控制 \(u_k=-Kx_k\)(或跟踪控制器)下,闭环协方差按 $\(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\)$ 逐步演化(这正是前置自测第 5 题)。若还有障碍位置不确定性 \(\Sigma_o\),检验时用 \(P_k+\Sigma_o\)关键:用**闭环**(含反馈 \(K\))而非开环传播——否则协方差会发散(呼应 U2:反馈把偏差/协方差镇定住)。

机制二:概率可行性检验。节点 \(\bar x_k\)(均值)相对障碍面 \(a_j^\top x\le b_j\) 安全的概率 ≥ \(1-\delta_{j,k}\),由解析高斯收紧(§U3.2)给出可直接检验的确定性条件: $\(a_j^\top\bar x_k-b_j\ \le\ -\Phi^{-1}(1-\delta_{j,k})\sqrt{a_j^\top(P_k+\Sigma_o)a_j}.\)$ 生长出的新节点若**不满足**此式(即违反概率 > \(\delta_{j,k}\)),直接**剔除**,不加入树。这一步是 CC-RRT 的灵魂——它把"碰撞检测"从布尔的"点在不在障碍里"升级成概率的"违反概率超不超 δ"。

机制三:Boole 风险分配。整条路径的 JCC 由 §U3.1 的 Boole 拆解保证——沿路径把 \(\delta_{j,k}\) 分配下去(均分或按段分配),使 \(\sum_{j,k}\delta_{j,k}\le\delta\)

CC-RRT 的检验代码

import numpy as np
from scipy.stats import norm

def propagate_covariance(P, A_cl, Sigma_w):
    """闭环协方差一步传播:P_{k+1} = A_cl P A_cl^T + Σ_w,A_cl = A - BK。"""
    return A_cl @ P @ A_cl.T + Sigma_w

def cc_feasible(x_mean, P, obstacles, delta_step, Sigma_o=None):
    """概率可行性检验:节点 x_mean(协方差 P)对所有障碍面满足 Pr(安全) >= 1 - delta_step。
    obstacles: [(a_j, b_j), ...] 半空间 a_j^T x <= b_j(安全侧)。
    返回 True 表示该节点违反概率 <= delta_step,可加入树。"""
    Pe = P if Sigma_o is None else P + Sigma_o
    z = norm.ppf(1.0 - delta_step)                       # 解析高斯收紧系数
    for a_j, b_j in obstacles:
        margin = z * np.sqrt(float(a_j @ Pe @ a_j))      # Φ^{-1}(1-δ)·标准差
        if a_j @ x_mean - b_j > -margin:                 # 违反收紧约束 → 危险,剔除
            return False
    return True

def cc_rrt_extend(tree, x_rand, A_cl, B, Sigma_w, obstacles, delta_step, dt, Sigma_o=None):
    """CC-RRT 的 extend:向 x_rand 生长一步,传播协方差并做 CC 检验。"""
    node = nearest(tree, x_rand)                          # 最近节点(含 mean 与 P)
    x_new = steer(node.mean, x_rand, dt)                  # 朝目标走一步(标称动力学)
    P_new = propagate_covariance(node.P, A_cl, Sigma_w)   # 协方差传播
    if cc_feasible(x_new, P_new, obstacles, delta_step, Sigma_o):
        return add_node(tree, x_new, P_new, parent=node)  # 概率可行 → 入树
    return None                                           # 否则丢弃

nearest/steer/add_node 是标准 RRT 原语,CC-RRT 只在 extend 里加了协方差传播 + CC 检验两步。把这套接到现成 RRT 框架(如 OMPL 思路)上,就把确定性 RRT 升级成了 CC-RRT。

CC-RRT*:渐近最优 + 风险加权

CC-RRT* 把 CC-RRT 嫁接到 RRT* 上,继承 ChooseParentRewire,获得**渐近最优**保证。两个关键改动: - 风险加权代价:边代价从 \(\|u\|^2\) 改为 \(\|u\|^2+\lambda\sum_k\delta_{j,k}\)——既最短/最省力、又少冒险(risk-averse)。Luders 等证明这个风险目标在 RRT* 框架内是 admissible(可用),故保留渐近最优性。 - Rewire 后重检 CC:rewire 改变了节点的父边、从而改变协方差传播路径,必须重新做 CC 检验——否则 rewire 可能引入违反概率超标的连接。

这样 CC-RRT* 在实时给出"碰撞概率 ≤ δ 且渐近最优"的平滑路径,覆盖过程噪声、定位误差、不确定(甚至动态)障碍。

本质洞察:CC-RRT = RRT + 协方差传播 + 概率剔除。确定性 RRT 问"这个点撞不撞",CC-RRT 问"这个点的违反概率超不超 δ"——把碰撞检测从"几何包含"换成"概率收紧检验",其余 RRT 机制原样保留。这和 §U3.2 把 MPC 的硬约束换成 CC 收紧,是**同一个替换**用在了不同规划范式上:优化型→CC-MPC,采样型→CC-RRT。理解了"用收紧检验替换硬检测",两类 CC 规划器就统一了。

⚠️ 本节常见误区

💡 编程陷阱:用开环协方差传播导致发散 - 现象/后果:协方差 \(P_k\) 沿树指数增长,远处节点的 margin 巨大,几乎所有节点被剔除,树长不出去。 - 根本原因:开环传播 \(P_{k+1}=AP_kA^\top+\Sigma_w\)\(A\) 不稳定时发散;CC-RRT 必须用**闭环** \(A-BK\)。 - 正确写法:用反馈增益 \(K\) 做闭环传播 \(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\)(如代码 A_cl)。 - 检验方法:打印沿边的 \(\mathrm{tr}(P_k)\),应收敛到稳态而非爆炸。

🧠 思维陷阱:Rewire 后忘记重检 CC - 新手想法:"rewire 只是换了父节点,代价更低就行,CC 不用重算。" - 现象/后果:rewire 后的新路径协方差传播变了,某些节点实际违反概率超标,最终路径不再满足 δ。 - 根本原因:协方差传播依赖整条父链;换父节点 = 换传播路径 = 协方差变化。 - 正确做法:每次 rewire 后对受影响节点重新 cc_feasible 检验,不通过则放弃该 rewire。

练习

  1. [A 型·CC-RRT 实现] 用 Eigen + nanoflann(或 Python + scipy KD-tree)实现 CC-RRT:闭环协方差传播 + Boole 风险分配 + 概率剔除。在 2D 窄通道验证:找到的路径蒙特卡洛违反率 ≤ δ。
  2. [A 型·CC-RRT*] 在上面基础上加 RRT* 的 ChooseParent/Rewire(风险加权代价 + rewire 后重检 CC),对比 CC-RRT 与 CC-RRT* 的路径代价随采样数的收敛。
  3. [思考题] CC-RRT 的协方差传播为什么要用闭环 \(A-BK\) 而非开环 \(A\)?这与 U2 Tube MPC 用 \(A+BK\) 算 RPI 集是不是同一个道理?

§U3.4 Covariance Steering ⭐⭐⭐⭐

动机:不只规划"均值去哪",还规划"不确定性多大"

前面所有方法都只规划**均值轨迹** \(\bar x_k\),协方差 \(P_k\) 是被动传播的副产品。Covariance Steering(CS,协方差控制;Okamoto, Goldshtein, Tsiotras, IEEE L-CSS 2018) 更进一步:把协方差 \(\Sigma_k\) 也当成可主动塑形的对象——在宽阔区域"放松"协方差(省控制能量),在狭缝处"收缩"协方差(保证安全)。直觉就像开车过窄桥前主动减速收拢、过桥后再放开。

理论:CS 的问题形式与"不可解耦"洞察

问题:给定初始分布 \(\mathcal{N}(\bar x_0,\Sigma_0)\) 与目标分布 \(\mathcal{N}(\bar x_f,\Sigma_f)\),对线性系统 \(x_{k+1}=A_kx_k+B_ku_k+w_k\)\(w_k\sim\mathcal{N}(0,\Sigma_w)\)),设计反馈控制器使状态分布从初始**转移到目标**,同时满足中途的机会约束、最小化代价。

控制律取 \(u_k=\bar u_k+K_k(x_k-\bar x_k)\)——\(\bar u_k\) 操控**均值**,反馈 \(K_k\) 操控**协方差**。状态均值与协方差分别按 $\(\bar x_{k+1}=A_k\bar x_k+B_k\bar u_k,\qquad \Sigma_{k+1}=(A_k+B_kK_k)\Sigma_k(A_k+B_kK_k)^\top+\Sigma_w\)$ 演化。决策变量是 \(\{\bar u_k\}\)(塑均值)与 \(\{K_k\}\)(塑协方差)。

核心洞察——有 CC 时均值与协方差不可解耦。Okamoto–Tsiotras 2018 的关键结果: - 无 CC 时:均值子问题(优化 \(\bar u_k\))与协方差子问题(优化 \(K_k\)可以分开解——目标和动力学在两者间解耦。 - 有 CC 时:解析高斯收紧 \(a^\top\bar x_k\le b-\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma_k a}\) 里,均值 \(\bar x_k\) 和协方差 \(\Sigma_k\) 同时出现在同一个约束里——收紧 margin 依赖 \(\Sigma_k\),而 \(\Sigma_k\)\(K_k\) 决定。于是均值能走多近边界,取决于协方差被塑成多大;两者**耦合**,必须**联合求解**。

这个不可解耦正是 CS 比"先规划均值、再被动传协方差"更强的原因:它允许"为了让均值能过窄缝,主动把协方差收小"——这种主动权衡,解耦方法做不到。

等价 SDP(Okamoto–Tsiotras 2018)

CS 问题可转化为一个**半定规划(SDP)**: $\(\begin{aligned} \min_{\bar u_k,\,K_k}\quad & \sum_k\Big[\mathrm{tr}\!\big(R\,K_k\Sigma_k K_k^\top\big)+\mathrm{tr}\!\big(Q\,\Sigma_k\big)\Big]\\ \text{s.t.}\quad & \Sigma_{k+1}=(A_k+B_kK_k)\Sigma_k(A_k+B_kK_k)^\top+\Sigma_w\\ & \bar x_{k+1}=A_k\bar x_k+B_k\bar u_k\\ & \Sigma_0\ \text{给定},\quad \Sigma_N\preceq\Sigma_f \end{aligned}\)$

其中目标两项分别是**控制反馈能量** \(\mathrm{tr}(R\,K_k\Sigma_k K_k^\top)\) 与**状态散布**(不确定性大小)\(\mathrm{tr}(Q\,\Sigma_k)\);约束依次是协方差动力学、均值动力学、CC 约束(用 \(\bar x_k\)\(\Sigma_k\) 联合表达,见上)、以及终端协方差不超过目标 \(\Sigma_N\preceq\Sigma_f\)。 通过变量代换(把 \(K_k\Sigma_k\) 整体作为新变量、并用 Schur 补处理二次项)化成 SDP 的标准形(线性目标 + 半定锥约束),可用标准 SDP 求解器(如 MOSEK、SCS)解。后续 Pilipovsky–Tsiotras 用 IRA(§U3.2)做最优风险分配进一步改进(均匀分配 → SDP)。

应用

  • 航天器轨迹规划 / 火星 EDL(Ridderhof–Tsiotras 等):着陆下降段的不确定性塑形。
  • 狭缝穿越(Okamoto–Tsiotras):让误差椭球在缝口主动收缩、过缝后放开——这是 CS 最直观的演示。
  • 多智能体分布式 CS(Pilipovsky–Tsiotras,ADMM 分解):把大规模联合 CS 拆给各智能体。

本质洞察:CS 把"不确定性"变成了控制量。前面的 CC 方法把协方差当成"已知的、被动传播的"量,只规划均值绕开它撑大的 margin。CS 反过来——主动控制协方差的形状,让不确定性"该小则小"。这是从"适应不确定性"到"塑造不确定性"的范式跃迁。代价是从 SOCP(只规划均值)升级到 SDP(联合规划均值+协方差),计算更重;收益是在狭窄/高风险场景能找到解耦方法找不到的可行解。

多视角理解:Covariance Steering 的三种看法 - 开车过窄桥(类比):宽路上松开方向盘(任不确定性大、省力),近桥时双手收紧、把车收拢到桥宽内(主动收缩协方差),过桥再放开。像/不像:都在"按需控制散布",但 CS 控制的是状态分布的协方差、而非一辆车的横向位置——它把"该紧则紧"写成了最优控制。 - 控制视角:反馈增益 \(K_k\) 是"协方差的方向盘"——\(\Sigma_{k+1}=(A+BK_k)\Sigma_k(A+BK_k)^\top+\Sigma_w\),调 \(K_k\) 就在塑形 \(\Sigma\)。 - 分布视角:CS 在"分布空间"里规划——把状态分布从初始高斯**最优传输**到目标高斯、中途满足 CC,把规划对象从"一条均值轨迹"升级为"一条分布轨迹"。

⚠️ 本节常见误区

💡 概念误区:以为均值和协方差总能分开规划 - 新手想法:"先用 MPC 规划均值轨迹,协方差让卡尔曼滤波被动传就行。" - 现象/后果:在窄缝/紧约束场景,被动传播的协方差太大、均值无论怎么走都过不去,问题"假性无解"。 - 根本原因:有 CC 时收紧 margin 同时含均值和协方差,两者耦合(Okamoto–Tsiotras 2018);解耦规划放弃了"主动收缩协方差换均值可行"的能力。 - 正确做法:紧约束场景用 CS 联合规划均值 + 协方差;宽松场景才可近似解耦(先均值后协方差)。

🧠 思维陷阱:以为 CS 的 SDP 能像 QP 一样高频实时 - 新手想法:"CS 也是凸的,那和 CC-MPC 的 QP 一样快。" - 现象/后果:SDP 求解比 QP/SOCP 慢一两个数量级,跑不到高频控制。 - 根本原因:SDP(半定锥)的求解复杂度远高于 QP/SOCP;CS 的协方差变量是矩阵,规模随状态维平方增长。 - 正确做法:CS 多用于离线/中低频轨迹规划;高频实时仍用解析高斯 CC-MPC(QP/SOCP)。需要在线 CS 时用迭代/贪心近似(如 Ridderhof 的 iterative CS、Bakolas 的 greedy UT-based CS)。

练习

  1. [B 型·CS 论文精读] 精读 Okamoto–Goldshtein–Tsiotras 2018(L-CSS),推导 CC+CS 的 SDP:(1) 写清为什么有 CC 时均值与协方差不可解耦;(2) 标注 SDP 的计算复杂度随状态维如何增长。
  2. [A 型·狭缝穿越] 用 CVXPY(SDP 后端,如 SCS/MOSEK)实现一个 1D/2D 狭缝穿越的 CS:初始大协方差、缝口收缩、过缝放开,可视化误差椭球沿轨迹的形状变化。
  3. [思考题] CS 的"在狭缝处收缩协方差"和 U2 的"Tube 在窄处其实也需要更小的 Ω"有什么联系与区别?(提示:Tube 的 Ω 是被动的不变集,CS 的 Σ 是主动塑形的——这正对应 §U2.2 Homothetic Tube 想做但只能缩放的事,CS 做得更彻底。)

§U3.5 与 Safe RL(CMDP)的关系 ⭐⭐⭐

动机:CC-MPC 与 Safe RL 在解同一个问题

做强化学习的读者会发现:CC-MPC 与 Safe RL(约束马尔可夫决策过程,CMDP) 长得很像——都在"最大化性能"的同时"限制违反"。本节点明:IRA 的风险分配与 Safe RL 的拉格朗日乘子调节,是同一个优化问题的 primal-dual 两端。理解这层关系,能让你在"已知模型用 CC-MPC"和"未知模型用 Safe RL"之间自由切换,并把两边的技术互相借用。

理论:两者的对照与统一拉格朗日

维度 CC-MPC Safe RL(CMDP)
模型 已知动力学 \(f\)、噪声 \(\Sigma\) 未知 MDP,靠样本学习
约束 \(\Pr(g\le 0)\ge 1-\delta\)(机会约束) \(\mathbb{E}[\sum_t\gamma^t c_t]\le d\)(期望累积代价约束)
求解 SDP / SOCP / MILP / SCP Trust-region / Primal-dual
代表 Ono–Williams IRA CPO(Achiam et al. 2017)、PPO-Lagrangian

统一视角——同一个拉格朗日函数。两者都可写成"性能目标 + 约束惩罚"的拉格朗日: $\(\mathcal{L}(\pi,\lambda)=\underbrace{J(\pi)}_{\text{性能/代价}}+\sum_i\lambda_i\underbrace{\big(C_i(\pi)-d_i\big)}_{\text{约束违反量}},\)$ 其中 \(C_i\) 是第 \(i\) 个约束的违反度量、\(d_i\) 是其预算、\(\lambda_i\ge 0\) 是对应乘子。优化在 \(\min_\pi\max_{\lambda\ge 0}\mathcal{L}\) 的鞍点。区别只在**你从哪一端逼近这个鞍点**:

  • CC-MPC / IRA:从 primal 端(分配预算 \(d_i\)。IRA 直接调整各约束的风险预算 \(\delta_{j,k}\)(即 \(d_i\)),下层在给定预算下解凸问题。它在**原始空间**操作"每个约束分多少违反额度"。
  • Safe RL / PPO-Lagrangian:从 dual 端(调乘子 \(\lambda_i\)。拉格朗日法不直接分配预算,而是**自适应调节乘子 \(\lambda_i\)**——约束违反了就增大 \(\lambda_i\)(加重惩罚)、满足了就减小。它在**对偶空间**操作"每个约束的惩罚价格"。

primal-dual 对偶:风险预算 \(\delta_i\)(primal)与乘子 \(\lambda_i\)(dual)是一对对偶变量——分配更多预算 ⟺ 更低的影子价格(乘子)。IRA "把预算挪给紧约束"与 Lagrangian "给紧约束更高的 \(\lambda\)",在鞍点处描述的是**同一个最优**,只是一个从量、一个从价逼近。这就是"同一优化问题的 primal-dual 两端"的确切含义。

这个关系的用处

  • 技术互借:CMDP 的乘子自适应(如 PID-Lagrangian 控制乘子)可启发 IRA 的预算更新;IRA 的"按紧度分配"可启发 Safe RL 的约束加权。
  • 模型有无的选择:模型已知、要硬性概率保证 → CC-MPC(primal,IRA);模型未知、靠交互学 → Safe RL(dual,Lagrangian)。两者可混合:用 CC-MPC 作 Safe RL 的安全层(呼应 U2 §U2.5 给 RL 兜底),或用学到的模型 + CC-MPC。
  • 概念统一:U2(CBF 给 RL 兜底)+ U3(CC 与 CMDP 对偶)+ U5(CVaR 与分布式 RL)共同勾勒出"经典约束控制"与"安全强化学习"如何在拉格朗日框架下统一——这是不确定性规划与 RL 的交界主线。

本质洞察:风险是预算,也是价格。CC 把违反概率当**预算**(primal,分配 δ),Safe RL 把违反当**价格**(dual,调乘子 λ)。同一个安全-性能权衡,从量看是 IRA、从价看是 Lagrangian,鞍点处殊途同归。掌握这个对偶,你就能在"已知模型的优化"与"未知模型的学习"之间自由翻译——这是本章给 RL 读者最重要的一座桥。

数值走查:预算(primal)与价格(dual)是同一最优的两面

用一个**可手算**的标量例子,把"风险预算 δ(primal)↔ 拉格朗日乘子 λ(dual)"的对偶说实。把"风险预算"抽象成一个一般的资源预算 \(d\),问题为 $\(\min_x\ (x-2)^2\quad\text{s.t.}\quad x\le d,\)$ 其中 \(x\) 是决策、\((x-2)^2\) 是代价(想去 \(x=2\))、\(d\) 是预算(约束上界,类比"允许多少风险")。

Primal 视角(给定预算 \(d\),直接解): - 若 \(d\ge2\):约束不起作用,最优 \(x^\*=2\)、代价 \(J^\*=0\)、乘子 \(\lambda^\*=0\)(约束有富余、影子价格为 0)。 - 若 \(d<2\):约束起作用,\(x^\*=d\)\(J^\*=(d-2)^2\)。预算的**影子价格** = 代价对预算的敏感度 \(\lambda^\*=-\frac{\mathrm{d}J^\*}{\mathrm{d}d}=-2(d-2)=2(2-d)>0\)——预算越紧(\(d\) 越小),价格越高。

Dual 视角(调乘子 \(\lambda\):拉格朗日 \(\mathcal{L}(x,\lambda)=(x-2)^2+\lambda(x-d)\)。对 \(x\) 求极小:\(x=2-\lambda/2\)。要让约束恰好满足(\(d<2\) 时约束活跃,\(x=d\)):\(2-\lambda/2=d\Rightarrow\lambda=2(2-d)\)——与 primal 的影子价格 \(\lambda^\*\) 完全相同

对偶关系一目了然: | | Primal(给预算)| Dual(调价格)| |---|---|---| | 操作的量 | 预算 \(d\)(类比风险 \(\delta\))| 乘子 \(\lambda\)(类比 RL 的 λ)| | 怎么做 | 固定 \(d\) 解凸问题(IRA 下层)| 调 \(\lambda\) 到约束满足(Lagrangian)| | 最优处 | \(x^\*=d\),得出 \(\lambda^\*\) | \(\lambda^\*=2(2-d)\),得出 \(x^\*=d\) | | 关系 | \(\lambda^\*=-\mathrm{d}J^\*/\mathrm{d}d\)(预算的影子价格)| 同一 \(\lambda^\*\) |

映射到 CC ↔ Safe RL:把 \(d\) 换成风险预算 \(\delta_i\)、约束 \(x\le d\) 换成"违反概率 ≤ \(\delta_i\)",就是 CC——IRA 调 \(\delta_i\)(primal,给预算)。把同一问题从对偶看,调的是乘子 \(\lambda_i\)——PPO-Lagrangian 调 \(\lambda_i\)(dual,定价格)。两者在鞍点 \((x^\*,\lambda^\*)\) 描述同一最优:放松预算(大 \(\delta\)/大 \(d\))⟺ 降低价格(小 \(\lambda\))。这就是"同一优化问题的 primal-dual 两端"落到数字上的样子。

⚠️ 本节常见误区

🧠 思维陷阱:以为 CC-MPC 的概率约束和 CMDP 的期望约束是一回事 - 新手想法:"都是限制'不好的事',机会约束 \(\Pr(g\le0)\ge1-\delta\) 和期望约束 \(\mathbb{E}[\sum c_t]\le d\) 等价。" - 现象/后果:把期望约束当概率保证用,实际尾部违反概率可能远超预期(期望小不代表尾部概率小)。 - 根本原因:机会约束限制的是**违反的概率**(尾部事件频率),期望约束限制的是**违反的期望累积量**(平均强度)。一个管"多大概率出事",一个管"平均出多大事"——不等价(CVaR/U5 会进一步辨析)。 - 正确做法:明确你要的是概率保证(用 CC)还是期望保证(用 CMDP 期望约束),或尾部风险保证(用 CVaR,U5)。三者是不同的风险度量。

练习

  1. [思考题·核心] 写出 CC-MPC 与 Safe RL 统一的拉格朗日函数,并说明:(1) IRA 在哪个空间(primal/dual)做优化、调的是什么变量;(2) PPO-Lagrangian 在哪个空间、调的是什么。解释为什么风险预算 δ 与乘子 λ 是对偶变量。
  2. [B 型·概念对比] 用一个简单的约束 LQR/CMDP 例子,分别用"固定预算解凸问题(primal)"和"自适应乘子梯度上升(dual)"求解,验证两者收敛到同一最优,观察 δ 与 λ 的对偶关系。
  3. [思考题] 如果用 CC-MPC 作为 Safe RL 策略的安全层(部署时滤波),这与 U2 §U2.5 用 CBF-QP 给 RL 兜底有何异同?(提示:CBF 给硬前向不变保证,CC 给概率保证;都是"经典安全层 + 学习策略"的组合。)

前沿与开放问题

机会约束规划近年最活跃的方向,是从"理论/仿真"走向"实机落地"与"学习化":

  • CC-MPC 落地四足(Trivedi, Prajapati, Zolotas, Everett, Padır, RA-L 2025, arXiv:2411.03481):把单刚体动力学(SRBD)的参数+加性不确定性建模为分布,摩擦锥约束表示为机会约束,用高效 QP 求解。Unitree Go1 实机在各种室内外地形上行走,扛起**超过自重 50% 的未知负载、无需额外调参**——CC 首次在四足实机上取代手调 margin。代码见 cc-mpc.github.io。
  • CC-VPSTO(Brudermüller et al., IJRR 2025):把机会约束嵌入 via-point(途经点)随机轨迹优化,在线 CC 规划,落到机械臂。
  • Robust-RRT(2023):面向不确定**非线性**系统的概率完备运动规划,把 CC-RRT 的线性高斯假设进一步放松。
  • 数据驱动 CC:用 GP(呼应 U2 §U2.4)或其他方法**学扰动分布**,再把学到的分布嵌入 CC-MPC——让 CC 的"分布假设"也由数据决定。
  • DR-CC 与 Wasserstein(Lew–Pavone 等):分布本身不确定时,对分布族内最坏情况保证 CC,化成 SDP/SOCP(接 U2 理论补遗的 DRO)。

开放问题: - C++ 高效 SDP:CC + CS 的底层是 SDP/SOCP,但 C++ 生态里高效、嵌入式友好的 SDP 求解器稀缺——这是工程瓶颈,也是机会。 - CC 嵌入 acados 的 SQP-RTI:如何把机会约束收紧高效地塞进 U2 §U2.6 的实时迭代框架,让 CC-MPC 跑到高频实时? - 非高斯 / 多模态扰动下的 CC:解析高斯失效时,如何在保持可解性的同时处理多峰分布(GMM)、重尾分布? - C++ 生态空白即机会:CC 规划的 C++ 开源库(尤其 CC-RRT for OMPL、CC-MPC for acados)几乎空白——这是学生做出**被广泛使用的原创开源贡献**的最佳方向之一。

给想做研究的你:U3 是整个 Part-U 里"理论成熟但工程/落地仍有大量空白"的一章。解析高斯 CC、IRA、CC-RRT 的理论都已稳固,但(1) 高性能 C++ 实现、(2) 与现代实时求解器(acados)的集成、(3) 非高斯扩展、(4) 与 Safe RL 的深度融合,每一条都有明确的、可发表/可开源的工作空间。


一个值得动手的迷你研究(把开放问题做成项目)

如果你想把本章学到的东西变成一份**有影响力的产出**,下面是一个门槛适中、空白明确的方向,融合了上面的开放问题:

项目:CC-RRT for OMPL(把 CC-RRT 做成 OMPL 官方 planner) - 为什么有价值:OMPL 是采样规划的事实标准库,但**没有**机会约束 planner。把 §U3.3 的 CC-RRT 实现成 OMPL 的 Planner 子类,让任何用 OMPL 的人都能一行切换到概率安全规划——这是能被广泛使用的原创开源贡献。 - 要实现什么:(1) 继承 OMPL 的 base::Planner,实现 solve();(2) 在状态里携带协方差(自定义 StateSpace 或附加数据),生长时做闭环传播;(3) 把碰撞检测换成 CC 概率检验(§U3.3 的 cc_feasible);(4) 风险沿路径分配(Boole)。 - 最大工程挑战:协方差在 OMPL 状态里怎么高效携带与传播(OMPL 的 state 是轻量结构);C++ 里没有现成的 CC 检验工具(生态空白,要自己写);CC-RRT* 的 rewire 后协方差重算的效率。 - 怎么验证:在标准 OMPL benchmark 场景(窄通道、迷宫)上对比 RRT* 与 CC-RRT*,蒙特卡洛验证 CC-RRT* 路径的违反率 ≤ δ、而 RRT* 在扰动下超标。

相关变体(同样空白):CC-MPC for acados(把 CC 收紧塞进 SQP-RTI,§专题八)、嵌入式 SDP for Covariance Steering(§U3.4 的底层瓶颈)。

这类项目的共同点:算法理论已成熟(本章讲清了)、Python 原型好写(本章给了)、但 C++/主流框架集成空白。填这个空白不需要发明新理论,需要的是把已知算法做成可复用、高性能、易集成的工程件。


完整实现精读:从公式到可运行代码

前面给了骨架;这一节对本章最核心的**解析 CC-MPC** 与 IRA 给出更完整的独立实现,把 §U3.2 的公式逐行落到代码,并配可手算的数值例与 CC-vs-Tube 对比。读完你应能从零写出 CC-MPC,而不只是调库。

三节实现精读的递进(建议按序读):本节()给优化型规划器的两大主力——解析 CC-MPC(实现一)+ IRA(实现二),是 §U3.2 的代码落地;紧接的""给采样型规划器的 CC-RRT 可运行版(§U3.3 落地);"续二"给非高斯路线的场景法 CC-MPC(§专题一/二的落地)。三者覆盖"优化型 / 采样型 / 非高斯"三类 CC 规划器,构成本章完整代码骨架——配合随后的累积项目(统一测试台)即可动手实验。

实现一:完整解析 CC-MPC(高斯噪声 + Φ⁻¹ 收紧 + QP)

2D 双积分器 \(x=[p_x,p_y,v_x,v_y]\),过程噪声 \(w_k\sim\mathcal{N}(0,\Sigma_w)\),障碍用半空间表示。每步对每个障碍面用解析高斯 margin 收紧,整体解 QP。

import numpy as np, cvxpy as cp
from scipy.stats import norm

def cc_mpc(x0, goal, obstacles, A, B, Sigma_w, K, N=20, dt=0.1,
           delta=0.05, u_max=3.0):
    """解析 CC-MPC:高斯噪声下,每个障碍面用 Φ^{-1}(1-δ_step) margin 收紧。
    obstacles: [(a_j, b_j)] 安全侧 a_j^T p <= b_j(a_j 为 2D,作用于位置 p=x[:2])。
    用 Boole 均分把 JCC=δ 拆到每步每面:δ_step = δ / (N * M)。"""
    nx, nu = B.shape
    M = max(len(obstacles), 1)
    delta_step = delta / (N * M)                       # Boole 均分
    z = norm.ppf(1.0 - delta_step)                     # 收紧系数
    A_cl = A - B @ K                                   # 闭环矩阵(协方差传播用)

    # 1) 离线传播闭环协方差 P_k(与控制无关,可预先算好)
    P = [np.zeros((nx, nx))]
    for _ in range(N):
        P.append(A_cl @ P[-1] @ A_cl.T + Sigma_w)

    # 2) 在线 QP:优化名义(均值)轨迹 z_k, 名义控制 v_k
    z_var = cp.Variable((nx, N + 1))
    v_var = cp.Variable((nu, N))
    xg = np.concatenate([goal, np.zeros(nx - 2)])
    Q = np.diag([5., 5., 1., 1.]); R = 0.1 * np.eye(nu)
    cost, cons = 0, [z_var[:, 0] == x0]
    for k in range(N):
        cost += cp.quad_form(z_var[:, k] - xg, Q) + cp.quad_form(v_var[:, k], R)
        cons += [z_var[:, k + 1] == A @ z_var[:, k] + B @ v_var[:, k]]
        cons += [cp.abs(v_var[:, k]) <= u_max]
        # CC 收紧:每个障碍面 a_j^T p_k <= b_j - z·sqrt(a_j^T P_k^{pos} a_j)
        Ppos = P[k][:2, :2]                            # 位置块协方差
        for a_j, b_j in obstacles:
            margin = z * np.sqrt(float(a_j @ Ppos @ a_j))
            cons += [a_j @ z_var[:2, k] <= b_j - margin]   # 向内收紧
    cost += cp.quad_form(z_var[:, N] - xg, 20 * Q)
    cp.Problem(cp.Minimize(cost), cons).solve(solver=cp.OSQP, warm_start=True)
    return v_var[:, 0].value, z_var.value, P

逐块对应 §U3.2 的公式delta_step = δ/(N*M) 是 Boole 均分(§U3.1);z = norm.ppf(1-δ_step)\(\Phi^{-1}(1-\delta_{\text{step}})\)P 列表是闭环协方差传播 \(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\)margin = z*sqrt(a^T P a) 正是解析高斯收紧量;a_j @ z_var[:2,k] <= b_j - margin 是向内收紧的确定性约束。注意协方差传播**与控制无关**,可离线预算(这是解析高斯 CC 高效的关键——在线只是个 QP)。

实现一的数值走查:一个可手算验证的例子

用一维例子把收紧算清。单约束 \(p\le 1\)(离墙 1 米),位置标准差 \(\sigma=0.2\)(来自传播的协方差),风险 \(\delta=0.05\)

  1. 收紧系数\(\Phi^{-1}(1-0.05)=\Phi^{-1}(0.95)\approx 1.645\)
  2. 收紧量\(1.645\times 0.2=0.329\)
  3. 收紧后约束:名义需满足 \(\bar p\le 1-0.329=0.671\)
  4. 解读:为把"撞墙概率 ≤ 5%",名义轨迹必须离墙 0.329 米**以上——这就是 5% 风险买到的 margin。若 \(\delta=0.01\)\(\Phi^{-1}(0.99)\approx 2.326\)),收紧量增至 \(0.465\)\(\bar p\le 0.535\),更保守。若 \(\sigma\) 减半(不确定性更小),收紧量也减半至 \(0.165\)——**margin 随不确定性线性缩放

cc_mpc 退化到一维单约束、固定 \(\sigma=0.2\),它算出的 margin 应当 ≈0.329(δ=0.05),与手算一致——验证实现正确性的最简 sanity check。这与 U2 §U2.4 实现二的机会约束数值例**完全同源**(同一个 \(\Phi^{-1}\) 收紧),只是这里把它系统地用到了整条 MPC 轨迹。

实现二:完整 IRA(外层分配 + 内层 QP)

把 §U3.2 的 IRA 骨架补成可跑的完整版——内层是收紧的 CC-MPC QP,外层迭代把风险从松约束挪给紧约束。

import numpy as np, cvxpy as cp
from scipy.stats import norm

def cc_mpc_with_alloc(x0, goal, obstacles, A, B, P_list, deltas, N, dt, u_max=3.0):
    """给定每(步,面)的风险分配 deltas[k][j],解收紧 CC-MPC QP。
    返回 (cost, z_traj, slack):slack[k][j] = (b_j - margin) - a_j^T p_k,>0 表示不活跃。"""
    nx, nu = B.shape
    z_var, v_var = cp.Variable((nx, N + 1)), cp.Variable((nu, N))
    xg = np.concatenate([goal, np.zeros(nx - 2)])
    Q, R = np.diag([5., 5., 1., 1.]), 0.1 * np.eye(nu)
    cost, cons = 0, [z_var[:, 0] == x0]
    for k in range(N):
        cost += cp.quad_form(z_var[:, k] - xg, Q) + cp.quad_form(v_var[:, k], R)
        cons += [z_var[:, k+1] == A @ z_var[:, k] + B @ v_var[:, k]]
        cons += [cp.abs(v_var[:, k]) <= u_max]
        Ppos = P_list[k][:2, :2]
        for j, (a_j, b_j) in enumerate(obstacles):
            z_jk = norm.ppf(1.0 - deltas[k][j])           # 该(步,面)的分位数
            margin = z_jk * np.sqrt(float(a_j @ Ppos @ a_j))
            cons += [a_j @ z_var[:2, k] <= b_j - margin]
    cost += cp.quad_form(z_var[:, N] - xg, 20 * Q)
    prob = cp.Problem(cp.Minimize(cost), cons); prob.solve(solver=cp.OSQP, warm_start=True)
    # 计算 slack(实际距离 - 收紧约束),用于上层判定活跃性
    z_traj = z_var.value
    slack = np.zeros((N, len(obstacles)))
    for k in range(N):
        Ppos = P_list[k][:2, :2]
        for j, (a_j, b_j) in enumerate(obstacles):
            z_jk = norm.ppf(1.0 - deltas[k][j])
            margin = z_jk * np.sqrt(float(a_j @ Ppos @ a_j))
            slack[k][j] = (b_j - margin) - float(a_j @ z_traj[:2, k])
    return prob.value, z_traj, slack

def ira_full(x0, goal, obstacles, A, B, P_list, N, dt, delta=0.05,
             n_iter=15, damp=0.5, tol=1e-3):
    """完整 IRA:外层迭代分配风险,内层解 CC-MPC QP。"""
    M = len(obstacles)
    deltas = [[delta / (N * M)] * M for _ in range(N)]    # 初始均分
    prev = np.inf
    for it in range(n_iter):
        cost, z_traj, slack = cc_mpc_with_alloc(x0, goal, obstacles, A, B, P_list, deltas, N, dt)
        flat = np.array([deltas[k][j] for k in range(N) for j in range(M)])
        sflat = slack.flatten()
        active = sflat <= 1e-3                              # 活跃:贴边界
        n_active = max(int(active.sum()), 1)
        # 上层:收回不活跃约束的部分风险,补给活跃约束
        recovered = flat[~active].sum() * damp
        flat[~active] *= (1 - damp)
        flat[active]  += recovered / n_active
        flat = np.clip(flat, 1e-6, delta)                  # 单个不超过总预算
        flat *= delta / flat.sum()                         # 归一化:Σδ = δ
        deltas = [[flat[k * M + j] for j in range(M)] for k in range(N)]
        if abs(prev - cost) < tol:
            break
        prev = cost
    return deltas, z_traj

机制回顾:每轮内层解 QP 得 slack(各约束离收紧边界多远),外层把 slack 大(不活跃、风险没用满)的约束的预算收回一部分、均分给 slack 小(活跃、吃紧)的约束,再归一化保 \(\sum\delta=\delta\)。迭代到代价收敛。相比均分,IRA 让紧约束用更大的 \(\delta_{j,k}\)(更小 margin),整体更优。damp 是阻尼系数防震荡。

CC vs Tube:同一问题的两种处理

把 U2 的 Tube MPC 与本章的 CC-MPC 放在同一个 2D 导航问题上对比,最能看清两者关系:

Tube MPC(U2) CC-MPC(U3)
扰动假设 有界 \(w\in\mathcal{W}\) 高斯(无界)\(w\sim\mathcal{N}(0,\Sigma_w)\)
保证 100% 不违反 违反概率 ≤ δ
收紧量 管道半宽 \(\Omega\)(固定) \(\Phi^{-1}(1-\delta)\sqrt{a^\top P_k a}\)(随 \(P_k\)、δ 变)
收紧随时变? Rigid 固定 / Homothetic 缩放 随协方差传播 \(P_k\) 自然时变
求解 QP QP / SOCP
何时更优 扰动真有界、要硬保证 扰动无界/高斯、可接受小风险、要少保守

关键联系:CC-MPC 在 δ→0 时收紧量 \(\Phi^{-1}(1-\delta)\to\infty\)——趋于无穷保守,对应"高斯尾部要 100% 覆盖不可能"。而若把高斯**截断**成有界集,CC 在 δ→0 就退化回 Tube。所以 Tube 是 CC 在"有界扰动 + δ→0"下的极限;CC 是 Tube 在"无界扰动 + 容忍 δ 风险"下的推广。

什么扰动水平下 CC 优势最大:扰动中等、且约束较紧(窄通道)时——此时 Tube 的固定 \(\Omega\) 要么过不去(太保守)要么没有有界 \(\mathcal{W}\) 可用,而 CC 用"接受 1% 风险"换来刚好够用的小 margin,能找到 Tube 找不到的解。扰动极小时两者都宽松、差别不大;扰动极大时 CC 的 margin 也会很大、优势收窄。

本质洞察:CC 与 Tube 是同一收紧思想的两种风险姿态。两者都是"名义轨迹 + 约束收紧",差别只在收紧量怎么来:Tube 用"覆盖最坏有界扰动"的 \(\Omega\),CC 用"覆盖 1−δ 概率质量"的 \(\Phi^{-1}\sqrt{a^\top Pa}\)。一个对最坏情况买单,一个对概率分布买单。理解了这点,你在面对一个新问题时该问的是:我的扰动有界吗?我能接受多少违反概率?——答案决定你站在 Tube 端还是 CC 端,或两者之间的某处。


完整实现精读(续):CC-RRT 的可运行版本

§U3.3 给了 CC-RRT 的 extend 片段;这里补一个更完整、可独立跑的最小 CC-RRT,把"采样 + 闭环协方差传播 + 概率剔除"串起来。

import numpy as np
from scipy.stats import norm

class Node:
    __slots__ = ("mean", "P", "parent", "cost")
    def __init__(self, mean, P, parent=None, cost=0.0):
        self.mean, self.P, self.parent, self.cost = mean, P, parent, cost

def cc_rrt(x0, goal, obstacles, A_cl, Sigma_w, bounds,
           delta=0.05, max_iter=2000, step=0.3, goal_tol=0.3, Sigma_o=None):
    """最小 CC-RRT(2D 位置规划):
    A_cl: 闭环矩阵(位置子系统), Sigma_w: 过程噪声协方差(位置),
    obstacles: [(a_j,b_j)] 安全侧 a_j^T p <= b_j, bounds: [(xmin,xmax),(ymin,ymax)]。
    返回从 x0 到 goal 的概率可行路径(节点均值列表)或 None。"""
    M = max(len(obstacles), 1)
    z = norm.ppf(1.0 - delta / (M * 50))               # 风险分配(粗略按~50步均分)
    root = Node(np.asarray(x0, float), np.zeros((2, 2)))
    tree = [root]

    def cc_ok(mean, P):
        Pe = P if Sigma_o is None else P + Sigma_o
        for a_j, b_j in obstacles:
            if a_j @ mean - b_j > -z * np.sqrt(float(a_j @ Pe @ a_j)):
                return False                            # 违反概率 > 分配风险 → 剔除
        return True

    for it in range(max_iter):
        # 1) 采样(10% 偏向目标)
        if np.random.rand() < 0.1:
            x_rand = np.asarray(goal, float)
        else:
            x_rand = np.array([np.random.uniform(*bounds[0]),
                               np.random.uniform(*bounds[1])])
        # 2) 最近节点
        near = min(tree, key=lambda n: np.linalg.norm(n.mean - x_rand))
        # 3) steer 一步
        d = x_rand - near.mean
        nrm = np.linalg.norm(d)
        if nrm < 1e-9:
            continue
        x_new = near.mean + step * d / nrm
        # 4) 闭环协方差传播
        P_new = A_cl @ near.P @ A_cl.T + Sigma_w
        # 5) CC 检验
        if not cc_ok(x_new, P_new):
            continue
        node = Node(x_new, P_new, parent=near,
                    cost=near.cost + step)
        tree.append(node)
        # 6) 到达判定
        if np.linalg.norm(x_new - np.asarray(goal)) < goal_tol:
            path = []
            n = node
            while n is not None:
                path.append(n.mean); n = n.parent
            return path[::-1]
    return None
# 用法:
# A_cl = np.array([[0.7,0],[0,0.7]]); Sigma_w = 0.01*np.eye(2)  # 已镇定的位置子系统
# obstacles = [(np.array([1.,0.]), 2.0), (np.array([-1.,0.]), -1.0)]  # 走廊 1<=x<=2
# path = cc_rrt([0,0],[3,3],obstacles,A_cl,Sigma_w,[(-1,4),(-1,4)],delta=0.05)

与 §U3.3 三机制的对应P_new = A_cl @ P @ A_cl.T + Sigma_w 是闭环协方差传播(机制一,用 A_cl 防发散);cc_oka_j@mean-b_j > -z*sqrt(a_j^T Pe a_j) 是概率可行性检验(机制二,解析高斯收紧);z = ppf(1-δ/(M*50)) 是 Boole 风险分配(机制三,粗略均分)。其余 采样/最近/steer/到达 是标准 RRT 原语。要升级 CC-RRT*,在第 5 步后加 ChooseParent(在邻域里选使 cost 最小且 CC 仍通过的父节点)与 Rewire(对邻域节点尝试改接到新节点、重检 CC),并把 cost 改成风险加权(§U3.3)。

教学版说明:这里风险分配用粗略的"按 ~50 步均分",严格实现应沿实际路径长度动态分配;协方差只传播位置子系统(2×2),完整系统应传播全状态再取位置块(如累积项目的 4×4)。把它接到 OMPL 等框架,就是"CC-RRT for OMPL"开放问题的起点(§前沿)。


完整实现精读(续二):场景法 CC-MPC(非高斯路线)

解析高斯 CC-MPC 要求高斯。当扰动非高斯(但能采样)时,场景法(scenario approach) 给出一条分布无关的路线:用 N 个采样的扰动实现,要求名义解对每个采样都满足约束。这里给一个最小实现,对照解析高斯。

import numpy as np, cvxpy as cp

def scenario_cc_mpc(x0, goal, obstacles, A, B, sample_disturbances, N=20, dt=0.1, u_max=3.0):
    """场景法 CC-MPC:用 M 条采样扰动轨迹替代概率约束(分布无关)。
    sample_disturbances: 形如 (M, N, nx) 的采样扰动序列(可来自任意分布/真实数据)。
    要求名义轨迹在每条采样扰动下都满足约束 ⇒ 以高概率满足原 CC(Campi–Garatti)。"""
    nx, nu = B.shape
    M = sample_disturbances.shape[0]                  # 场景数(样本复杂度 N_s 决定保证)
    z = cp.Variable((nx, N + 1)); v = cp.Variable((nu, N))
    xg = np.concatenate([goal, np.zeros(nx - 2)])
    Q, R = np.diag([5., 5., 1., 1.]), 0.1 * np.eye(nu)
    cost, cons = 0, [z[:, 0] == x0]
    for k in range(N):
        cost += cp.quad_form(z[:, k] - xg, Q) + cp.quad_form(v[:, k], R)
        cons += [z[:, k + 1] == A @ z[:, k] + B @ v[:, k], cp.abs(v[:, k]) <= u_max]
    cost += cp.quad_form(z[:, N] - xg, 20 * Q)
    # 场景约束:对每条采样扰动轨迹,名义+扰动后仍满足障碍约束
    for m in range(M):
        x_s = x0.copy()
        for k in range(N):
            x_s = A @ x_s + B @ v[:, k] + sample_disturbances[m, k]  # 该场景下的状态(含扰动)
            for a_j, b_j in obstacles:
                cons += [a_j @ x_s[:2] <= b_j]            # 每个场景、每步、每面都要满足
    cp.Problem(cp.Minimize(cost), cons).solve(solver=cp.OSQP, warm_start=True)
    return v[:, 0].value, z.value

与解析高斯的对照: - 解析高斯:用 \(\Phi^{-1}\sqrt{a^\top Pa}\) 收紧,约束数 = 面数 × 时步,与分布无关地快,但要求高斯。 - 场景法:用 M 条采样轨迹,约束数 = 面数 × 时步 × M任意分布(采样即可),但 M 大时约束爆炸、慢。

样本数 M 怎么定:由 Campi–Garatti 样本复杂度界(§理论补遗),大致 \(M\ge\frac{2}{\delta}(d+\ln\frac{1}{\beta})\)\(d\) 为决策维、β 为置信)。δ 越小、维数越高,M 越大——这是"分布无关"的代价。工程上常配合 sampling-and-discarding(丢弃少量最坏样本换更优解)。

何时用场景法 vs 解析高斯:分布高斯且已知 → 解析高斯(快、紧);分布非高斯/未知但**有数据可采** → 场景法(直接用真实数据采样,无需拟合分布)。场景法的最大优点是**能直接吃真实扰动数据**——把历史飞行/行驶记录当采样,不必假设任何分布形式。这与 §U3.2 方法谱里"非高斯 → 粒子/场景"一致,只是这里用凸的场景约束(非 MILP),适合扰动只影响约束、不需要二元变量的情形。


累积项目:U3 模块(把硬避障换成 CC 收紧)

U2 累积项目给了"Tube + HOCBF"的统一导航测试台。U3 模块**不重建测试台**,只把 U2 的硬避障(HOCBF)替换成 CC 收紧——同一个 2D 双积分器、同一组障碍、同一套蒙特卡洛评测,看碰撞率如何被精确控制在 δ 以下、保守度如何随 δ 调节。这正是"加一个范式只改一个模块、主干不动"的累积项目精神。

import numpy as np, cvxpy as cp
from scipy.stats import norm

class CCNavTestbed:
    """U3 累积项目测试台:复用 U2 的 2D 双积分器 + 高斯噪声 + 半空间障碍。
    与 U2 唯一区别:扰动是高斯(无界),避障用 CC 收紧而非硬 HOCBF。"""
    def __init__(self, dt=0.1, sigma_w=0.05):
        self.dt = dt
        self.A = np.array([[1,0,dt,0],[0,1,0,dt],[0,0,1,0],[0,0,0,1]], float)
        self.B = np.array([[0,0],[0,0],[dt,0],[0,dt]], float)
        self.Sigma_w = np.diag([1e-4, 1e-4, sigma_w**2, sigma_w**2])   # 高斯过程噪声
        self.goal = np.array([5., 5.])
        # 障碍:沿对角线的两道斜墙,夹出一条从起点通向目标的走廊(半空间 a^T p <= b 为安全侧)
        self.obstacles = [(np.array([1., -1.]), 2.0),    # p_x - p_y <= 2(右下墙)
                          (np.array([-1., 1.]), 2.0)]    # p_y - p_x <= 2(左上墙)→ 对角走廊 |p_x-p_y|<=2,含起点(0,0)与终点(5,5)
    def step(self, x, u, rng):
        w = rng.multivariate_normal(np.zeros(4), self.Sigma_w)
        return self.A @ x + self.B @ u + w
    def collided(self, x):
        return any(a @ x[:2] > b + 1e-9 for a, b in self.obstacles)

def design_feedback(A, B, Q=None, R=None):
    """LQR 反馈增益 K(闭环协方差传播用,呼应 U2/CC-RRT)。"""
    from scipy.linalg import solve_discrete_are
    Q = np.diag([5,5,1,1.]) if Q is None else Q
    R = 0.1*np.eye(2) if R is None else R
    P = solve_discrete_are(A, B, Q, R)
    return np.linalg.inv(R + B.T @ P @ B) @ (B.T @ P @ A)

def propagate_cov(A_cl, Sigma_w, N):
    """离线预算闭环协方差序列 P_0..P_N。"""
    P = [np.zeros((4,4))]
    for _ in range(N):
        P.append(A_cl @ P[-1] @ A_cl.T + Sigma_w)
    return P

def cc_controller(env, K, P_list, N=20, delta=0.05, u_max=3.0):
    """返回一个 CC-MPC 控制器闭包:每步解收紧 QP,取首控制 + 反馈。"""
    def ctrl(x):
        M = len(env.obstacles)
        z_step = norm.ppf(1.0 - delta/(N*M))
        z_var, v_var = cp.Variable((4, N+1)), cp.Variable((2, N))
        xg = np.concatenate([env.goal, [0,0]])
        Q, R = np.diag([5,5,1,1.]), 0.1*np.eye(2)
        cost, cons = 0, [z_var[:,0] == x]
        for k in range(N):
            cost += cp.quad_form(z_var[:,k]-xg, Q) + cp.quad_form(v_var[:,k], R)
            cons += [z_var[:,k+1] == env.A @ z_var[:,k] + env.B @ v_var[:,k],
                     cp.abs(v_var[:,k]) <= u_max]
            Ppos = P_list[k][:2,:2]
            for a_j, b_j in env.obstacles:
                margin = z_step * np.sqrt(float(a_j @ Ppos @ a_j))
                cons += [a_j @ z_var[:2,k] <= b_j - margin]
        cost += cp.quad_form(z_var[:,N]-xg, 20*Q)
        cp.Problem(cp.Minimize(cost), cons).solve(solver=cp.OSQP, warm_start=True)
        v0 = v_var[:,0].value
        return v0 if v0 is not None else np.zeros(2)      # 失败兜底
    return ctrl

def monte_carlo(env, ctrl, n_trials=1000, T=120, seed0=0):
    """蒙特卡洛评测:返回碰撞率、到达率、平均步数。"""
    collide = reach = 0; steps = []
    for s in range(n_trials):
        rng = np.random.default_rng(seed0 + s)
        x = np.array([0.,0.,0.,0.]); hit = False
        for t in range(T):
            x = env.step(x, ctrl(x), rng)
            if env.collided(x): collide += 1; hit = True; break
            if np.linalg.norm(x[:2]-env.goal) < 0.3: reach += 1; steps.append(t); break
    return {"collision_rate": collide/n_trials,
            "reach_rate": reach/n_trials,
            "avg_steps": float(np.mean(steps)) if steps else None}

# ── 用法(Bronze/Silver/Gold 三档)──
# env = CCNavTestbed(sigma_w=0.05)
# K = design_feedback(env.A, env.B)
# P_list = propagate_cov(env.A - env.B @ K, env.Sigma_w, N=20)
# for d in (0.10, 0.05, 0.01):                          # 扫风险预算
#     ctrl = cc_controller(env, K, P_list, N=20, delta=d)
#     print(f"δ={d}:", monte_carlo(env, ctrl))

三档目标(呼应 U2 累积项目): - Bronze:跑通单个 δ 的 CC-MPC,蒙特卡洛验证碰撞率 ≤ δ。 - Silver:扫 δ∈{0.1,0.05,0.01},画"δ ↔ 碰撞率 ↔ 到达率/步数"曲线——亲眼看到碰撞率被压在 δ 以下、且 δ 越小、收紧 margin 越大、越保守(把走廊收窄到 margin 接近半宽,还能看到小 δ 下变得不可行)。 - Gold:把 CC-MPC 换成 IRA(实现二),对比均分 vs IRA 在窄走廊的到达率;或加障碍位置不确定性 \(\Sigma_o\),体会感知不确定如何进一步收紧(接 U4)。

怎么读这些数字:碰撞率应稳定 ≤ δ(若超标,检查 Boole 均分、协方差传播、或 QP 失败兜底);到达率/步数反映保守度——δ 越小、margin 越大、走廊里越难走。一个调好的 CC-MPC 应当:碰撞率贴着但不超过 δ、到达率高。与 U2 对照:U2 的 Tube+HOCBF 碰撞率≈0(硬保证),CC-MPC 碰撞率≤δ(概率保证,约束吃紧时贴近 δ、走廊开阔时可远低于 δ)——这就是"100% 硬保证"与"δ 概率保证"的实测差别,也是 CC 用一点风险换保守度的直接体现。

消融解读:CC 模块各部分的作用

把几种配置摆在一起(同测试台、同噪声、同种子): - 风险中性 MPC(无收紧):名义轨迹贴着甚至切过障碍走,高斯噪声下碰撞率远超任何 δ——复现 U0/U2 的论点:忽略不确定性会系统性失效。 - + 解析高斯 CC 收紧(均分):碰撞率被压到 ≈δ;但均分让走廊中段的紧约束 margin 偏大,到达率/路径长度受损。 - + IRA(最优分配):碰撞率仍 ≈δ,但把风险挪给紧约束后 margin 更合理,窄走廊到达率提升、路径更短——定量显示 IRA 相对均分的保守度下降。

怎么归因:碰撞率反映 CC 收紧是否到位(系数/协方差对不对),到达率/步数反映风险分配是否高效(均分 vs IRA)。这与 U2 消融"Tube 管守约束、CBF 管避障"是同一套控制变量方法——同测试台、逐个替换组件、干净归因。


累积项目进阶:感知端不确定性与在线风险(U4 桥)

正文累积项目只考虑过程噪声 \(\Sigma_w\)(执行/动力学端)。两个进阶把它推向更真实、并通往后续章节。

进阶一:障碍位置不确定 \(\Sigma_o\)(感知端,接 U4)

真实机器人对障碍位置的感知有误差:障碍中心 \(\hat p_o\) 带协方差 \(\Sigma_o\)(来自定位/SLAM/检测)。这时碰撞概率不仅来自自身状态不确定 \(P_k\),还来自障碍位置不确定 \(\Sigma_o\)。CC 检验自然地把两者相加: $\(a_j^\top\bar x_k-b_j\le-\Phi^{-1}(1-\delta_{j,k})\sqrt{a_j^\top(P_k+\Sigma_o)a_j}.\)$ 唯一改动是把检验里的 \(P_k\) 换成 \(P_k+\Sigma_o\)(假设两者独立)——在累积项目代码里就是 cc_feasible / cc_controller 的协方差项加上 \(\Sigma_o\)

def cc_margin_with_perception(a_j, P_k, Sigma_o, delta_step):
    """计入障碍位置不确定 Σ_o 的 CC 收紧 margin(自身 P_k 与感知 Σ_o 相加)。"""
    from scipy.stats import norm
    import numpy as np
    z = norm.ppf(1.0 - delta_step)
    Pe = P_k + Sigma_o                                  # 状态不确定 + 感知不确定
    return z * np.sqrt(float(a_j @ Pe @ a_j))
# 用法:把 cc_controller 里的 margin 改为 cc_margin_with_perception(a_j, P_list[k][:2,:2], Sigma_o, δ_step)
# (a_j 是 2D,须传位置块 2x2 协方差;Sigma_o 同为 2x2)

实验:固定 δ,对比 \(\Sigma_o=0\)(完美感知)与 \(\Sigma_o>0\)(有感知误差)下的到达率——感知越差、margin 越大、越保守。这把"感知不确定性"显式接入 CC,正是 U4(belief 空间规划) 的入口:U4 会把 \(\Sigma_o\) 从"给定常数"变成"随观测演化的 belief",而 CC 提供了"belief 不确定性 → 约束收紧"的桥。

进阶二:在线 / 时变风险预算

正文用固定 δ 全程。进阶让 δ 时变**或**在线重分配: - 时变 δ_k:危险段(窄通道)用小 δ_k(更安全)、开阔段用大 δ_k(更省)——在总预算约束 \(\sum_k\delta_k\le\delta\) 下分配,本质是 IRA 沿时间的应用。 - 在线 IRA:每个控制周期重跑几轮 IRA(实现二),让风险分配随当前态势自适应——代价是在线计算,实时场景要限迭代次数(§C++ 部署)。

实验:对比"固定均分 δ" vs "在线 IRA 时变分配"在一条先窄后宽的走廊上的到达率与碰撞率——时变分配应在保持碰撞率 ≤ δ 的同时提高到达率。

两个进阶合起来,累积测试台就从"只有执行端噪声 + 固定风险"升级成"执行端 + 感知端不确定 + 自适应风险预算"——已经触到 U4(感知/belief)的门口,也把 IRA 从离线推到在线。这再次示范累积项目的价值:加一层不确定性(感知)只改协方差项、加一种风险策略(时变)只改分配逻辑,主干不动


方向落地案例

把机会约束落到三个常见方向,看它在真实系统里如何取代"硬约束"或"手调 margin"(论文事实均已核实)。

案例一:四足机器人——摩擦锥的机会约束化

问题:四足在未知负载、复杂地形上行走,地面反作用力必须落在摩擦锥内(否则打滑),但负载和地形带来参数与加性不确定性,固定的摩擦锥 margin 要么太保守(正常地形上动作僵硬)、要么不够(湿滑地面打滑)。

CC 方法(Trivedi et al., RA-L 2025):把单刚体动力学(SRBD)的负载/地形不确定性建模为参数+加性扰动的分布,将**摩擦锥约束表示为机会约束**——"地面力落在锥内的概率 ≥ 1−δ"——再用解析高斯收紧成确定性约束,整体用高效 QP 求解(保持 MPC 实时性)。

效果:蒙特卡洛对比"线性 MPC"与"手调 margin 的 MPC",CC-MPC 在稳定性、减少打滑、质心跟踪上都更优;Unitree Go1 实机扛起超过自重 50% 的未知负载、跨各种室内外地形、无需额外调参

对应本章:摩擦锥 CC = §U3.2 解析高斯收紧用在锥约束上;"无需调参"正是 CC 相对手调 margin 的核心卖点(margin 由协方差与 δ 自动算出)。工程要点:把摩擦锥(二阶锥)的 CC 化成 SOCP/QP、保持实时;不确定性分布怎么估(负载/地形参数)。

案例二:无人机 / 航天器——CC 避障与协方差塑形

问题:无人机在风扰下避障、航天器在不确定动力学下规划下降轨迹——扰动近似高斯(无界),Tube 的有界假设不适用。

CC 方法: - CC 避障(Blackmore–Ono–Williams, IEEE T-RO 2011):把障碍约束写成机会约束,用解析高斯 + 风险分配求解凸的 CC 路径规划——无人机在高斯定位/风扰下以 1−δ 概率避开障碍。 - Covariance Steering(Okamoto–Tsiotras, L-CSS 2018;航天 EDL,Ridderhof–Tsiotras):下降段主动塑形误差椭球,在关键时刻收缩不确定性保证安全。

对应本章:§U3.2(CC 避障)+ §U3.4(CS)。工程要点:协方差传播的精度(线性化 vs UT);高频场景用解析高斯 CC(QP/SOCP),离线/中低频可上 CS(SDP)。

案例三:自动驾驶 / 多智能体——CC 与采样规划

问题:自动驾驶在他车意图不确定、定位有误差下规划,既要采样规划器的灵活,又要概率安全保证。

CC 方法: - CC-RRT(Luders–Kothari–How, AIAA GNC 2010):把 CC 嵌入 RRT,沿边传播协方差、按概率剔除危险节点——采样规划器获得"路径以 1−δ 概率安全",并能处理不确定甚至动态障碍。 - 多智能体分布式 CS(Pilipovsky–Tsiotras,ADMM):多车联合协方差塑形,分布式求解。

对应本章:§U3.3(CC-RRT)+ §U3.4(分布式 CS)。工程要点:闭环协方差传播防发散;他车意图不确定性如何进入 CC(接 U4 belief、U1 分支)。

三个案例的共性:CC 的角色都是**取代"硬约束"或"手调 margin"**——四足取代摩擦锥手调裕度、无人机取代 Tube 的有界假设、自驾给采样规划器加概率保证。共同前提是"扰动近似已知分布(高斯)且可接受小概率违反"。这把"方法选型"落到了具体方向:扰动有界要硬保证→U2 Tube/CBF;扰动高斯可容忍 δ→本章 CC。


方法选型决策指南

学完几种 CC 方法与近似,真实项目里怎么选?先问四个问题。

问题 1:扰动分布是什么? - 高斯(或近似高斯) → 解析高斯 \(\Phi^{-1}\) 收紧(§U3.2),最快最准。 - 只知均值方差、形状未知 → Cantelli/椭球收紧(更保守但分布无关)。 - 明显非高斯/多模态 → 粒子/场景 MILP,或场景法(Campi–Garatti)。 - 分布本身不确定(数据少) → DR-CC(Wasserstein/矩,最稳健)。

问题 2:要单步还是整条轨迹保证? - 单步(ICC) → 直接解析收紧,每步独立。 - 整条轨迹(JCC) → Boole 拆解 + 风险分配;保守度敏感就用 IRA(§U3.2)而非均分。

问题 3:规划器是优化型还是采样型? - 优化型(MPC) → CC-MPC(解析收紧 + QP/SOCP,§U3.2)。 - 采样型(RRT) → CC-RRT(协方差传播 + 概率剔除,§U3.3)。 - 要主动塑形不确定性(窄缝) → Covariance Steering(SDP,§U3.4)。

问题 4:实时预算多少? - 高频(几十~几百 Hz) → 解析高斯 CC-MPC(QP,协方差离线传播);避免 MILP、SDP、full 场景法。 - 中低频/离线 → IRA、CS(SDP)、场景法都可行。

常见组合: - CC-MPC + IRA:高频 + 低保守度,工程主力(四足案例即此类)。 - CC-RRT + 局部 CC-MPC:采样器出全局概率安全路径,MPC 跟踪并局部 CC 收紧。 - CC + Safe RL:CC-MPC 作 RL 策略的安全层(接 §U3.5、U2 §U2.5)。

一句话决策:高斯 + 高频 + MPC → 解析 CC-MPC(+IRA);采样规划 → CC-RRT;窄缝要塑形不确定性 → CS;非高斯 → 粒子/场景;数据少分布糊 → DR-CC。

回到五安全谱(U0):CC 占据谱的中段——比 U2(鲁棒 100%)激进、比风险中性保守。选 δ 就是选你在谱上的位置:δ→0 趋近 U2 硬保证,δ 较大趋近期望最优。再往尾部风险走(关心"违反时有多糟"而非"违反概率"),就进入 U5 的 CVaR 了。


CC vs Tube 数值走查(手算对比)

正文给了 CC vs Tube 的定性对比表;这里用一个**可手算**的一维例子,看两者在同一问题上的具体差别,以及"CC 在哪赢"。

设定:一维位置约束 \(p\le 1\)(离墙 1 米)。两种扰动建模: - Tube(有界):扰动 \(|w|\le\bar w=0.3\)(有界盒),闭环收缩因子 \(\rho=0.4\)。RPI 集(管道半宽)\(\Omega=\frac{\bar w}{1-\rho}=\frac{0.3}{0.6}=0.5\)。 - CC(高斯):扰动 \(w\sim\mathcal{N}(0,\sigma^2)\),稳态位置标准差 \(\sigma_\infty=0.2\)(设已传播到稳态)。

Tube 的收紧:硬保证要求名义离墙 \(\Omega=0.5\),即 \(\bar p\le 1-0.5=0.5\)。无论什么情况都收 0.5(对最坏有界扰动买单)。

CC 的收紧(按 δ): | δ | \(\Phi^{-1}(1-\delta)\) | margin \(=\Phi^{-1}\cdot\sigma_\infty\) | 名义约束 \(\bar p\le\) | |---|---|---|---| | 0.10 | 1.282 | 0.256 | 0.744 | | 0.05 | 1.645 | 0.329 | 0.671 | | 0.01 | 2.326 | 0.465 | 0.535 | | 0.001 | 3.090 | 0.618 | 0.382 |

对比与解读: - δ=0.05 时 CC 收紧 0.329 < Tube 的 0.5——CC 让名义轨迹离墙更近(0.671 vs 0.5),活动空间更大。代价:5% 的越界概率(Tube 是 0%)。 - δ→0 时 CC 收紧增大:δ=0.001 收 0.618 > Tube 的 0.5——CC 反而比 Tube 更保守! 因为高斯尾部要覆盖到 99.9% 需要很大的 margin,而有界扰动的 Tube 只需覆盖到 \(\bar w=0.3\)。 - 存在一个 δ*,使 CC 收紧 = Tube 收紧(这里约 δ≈0.006,margin≈0.5)。δ > δ* 时 CC 更进取(赢在少保守),δ < δ* 时 Tube 更进取(赢在有界扰动只需有限 margin)。

"CC 在哪赢":当 (1) 扰动本质无界(高斯,Tube 的有界假设不成立)、或 (2) 可接受中等风险(δ 不太小)、且约束较紧(需要省 margin)时,CC 赢。当扰动真有界、且要极低/零违反时,Tube 赢(有限 margin 拿到硬保证)。

本质洞察:CC 与 Tube 的优劣由"δ 与扰动有界性"共同决定。这个一维走查把定性表格变成了数字:margin 是它们竞争的战场——Tube 的 margin 是"覆盖有界集"的常数 0.5,CC 的 margin 是"覆盖 1−δ 概率"的 \(\Phi^{-1}\sigma\)。两条 margin 曲线在 δ* 处相交,交点两侧各有所长。选 Tube 还是 CC,本质是问:我的扰动有界吗?我要多低的违反概率?——这正是 §方法选型与 U0 安全谱要回答的。


理论补遗:CC 的来历、复杂度与场景法

三块"知道了会更通透"的理论,解释机会约束为什么长成现在这样。

Charnes–Cooper 1959:机会约束的起源

机会约束的概念由 Charnes 与 Cooper 在 1959 年提出("Chance-Constrained Programming", Management Science 6(1):73–79, 1959)。它诞生于运筹学——工业生产计划里,需求、成本是随机的,要求"以一定概率满足生产约束"。Charnes–Cooper 的原始贡献是提出 E/V/P 三类模型(按期望 Expectation、方差 Variance、概率 Probability 优化)与"确定性等价(deterministic equivalent)"的思想:在特定条件下,把含随机量的概率约束**重写成不含随机量的确定性约束**,从而能用常规(凸)规划求解。他们 1963 年的续作(Operations Research)进一步系统化了确定性等价。

值得注意:原始 1959 论文的视角是"把问题分裂成两部分——求最优概率分布、再用决策规则逼近",而我们今天熟悉的"正态下 ICC 化为锥约束"(§U3.2 的 \(\Phi^{-1}\) 收紧)是确定性等价思想在高斯线性情形的具体落地,由后续大量工作(包括 Charnes–Cooper 自己)发展完善。从 1959 的运筹学概念到今天的机器人 CC-MPC,核心不变:用确定性等价把概率约束变可解

为什么一般 CC 是 NP-hard

§U3.2 说过一般 CC 是 NP-hard(Nemirovski–Shapiro 2006、Calafiore–El Ghaoui 2006)。直觉如下:可行域 \(\{x:\Pr(g(x)\le 0)\ge 1-\delta\}\) 一般**非凸**——即使每个 \(g\) 是凸的、扰动是良性的,"以概率 1−δ 满足"这个要求也可能切出一个非凸、甚至不连通的可行集。原因是概率约束本质上是对"违反集合的测度"设限,而测度对决策变量的依赖可以高度非线性。

这就是为什么本章花大力气找**凸近似**: - 解析高斯(§U3.2):高斯 + 线性约束这一特例下,可行域恰好凸(SOC 约束),精确可解。 - 凸上界(Cantelli、CVaR、矩不等式):用一个保守的凸集**内逼近**真实可行域,牺牲一点保守度换凸性。 - 场景法:用采样把概率约束换成有限个确定性约束(凸),用概率论保证近似质量。

理解"一般非凸、特例/上界凸"这条线,就理解了 CC 方法谱为什么是现在这个样子——每种方法都是在"分布假设强度"与"凸性/可解性"之间做的一个取舍。

场景法的样本复杂度(Campi–Garatti 2008)

场景法(scenario approach) 是处理 CC 的一条优雅的分布无关路线。核心想法:与其分析概率约束,不如**采样** N 个独立的扰动实现 \(w^{(1)},\dots,w^{(N)}\),要求解对**每一个采样约束**都满足: $\(\min_x\ c^\top x\quad\text{s.t.}\quad g(x,w^{(i)})\le 0,\ i=1,\dots,N.\)$ 这是一个普通的(凸)优化(N 个确定性约束)。Campi–Garatti("The Exact Feasibility of Randomized Solutions of Uncertain Convex Programs", SIAM J. Optim. 19(3):1211–1230, 2008)证明:只要 N 足够大(与决策变量维数 \(d\)、风险 δ、置信 β 相关,大致 \(N\ge\frac{2}{\delta}(d+\ln\frac{1}{\beta})\) 量级),则采样解以至少 1−β 的置信满足原机会约束 \(\Pr(g\le0)\ge1-\delta\)

优雅之处:完全**不需要知道扰动分布**——只要能采样即可,对任意分布成立。代价:样本数 N 可能很大(尤其 δ 小、维数高时),且采样约束让问题规模随 N 增长。后续 sampling-and-discarding(丢弃部分样本换更优解)、wait-and-judge(事后判定实际复杂度)等改进缓解了保守度。

场景法 vs 解析高斯:解析高斯快、准,但要求高斯;场景法通用(任意分布)、有严格保证,但要大量样本。工程上:分布已知且高斯 → 解析;分布未知/复杂但能采样 → 场景法。这也呼应 U2 理论补遗里 DRO 的精神:对分布知道得越少,付出的保守度/计算代价越大。


从 Python 原型到 C++ 部署

本章代码用 Python(numpy + cvxpy)讲算法。和 U2 一样,真实机器人部署要落到 C++。但 CC 有个特殊之处——它的 C++ 生态几乎空白,这既是工程挑战,也是做原创开源贡献的最佳机会

CC 的部署与 U2 的异同

相同:两段式工作流(Python 原型验证 → C++ 部署实时回路)不变;重活仍在 C/C++ 求解器里(OSQP、SOCP/SDP 求解器)。

不同——CC 的求解后端更复杂: - U2 的 Tube MPC / CBF-QP 主要是 QP,C++ 求解器成熟(OSQP、qpOASES、HPIPM)。 - CC 的解析高斯 ICC 是 SOCP(二阶锥),C++ 求解器较少但存在(ECOS、SCS、Mosek、Clarabel)。 - CC 的 Covariance Steering 是 SDP(半定锥),C++ 嵌入式友好的高效 SDP 求解器稀缺——这是真正的工程瓶颈。

所以 CC 的"Python 原型 → C++ 部署"这条路,在 SOCP 层尚可(有求解器),在 SDP 层(CS)则缺乏成熟工具——这正是开放问题。

CC 在哪里登场、为什么用 C++

  • 高频 CC-MPC(如四足摩擦锥 CC,需几百 Hz):解析高斯收紧 + QP/SOCP,必须 C++ 实时。
  • 嵌入式平台:无人机/四足的机载计算,只能 C++。
  • 与现有 C++ 栈集成:CC-MPC 要嵌进 OCS2/acados 风格的 C++ 控制栈。

CC 的 C++ 实现路径

由于生态空白,目前 CC 的 C++ 落地主要靠"借用通用凸优化框架手拼": - CasADi(C++/Python,LGPL):用 SX/MX 符号框架**手写 CC 约束**——把 \(\Phi^{-1}(1-\delta)\) margin 收紧写成符号表达式,再交给 NLP/QP 后端。这是目前最现实的 CC-MPC C++ 路径。 - Drake 的 MathematicalProgram(C++):提供 SOCP/SDP 接口,可手工拼出 CC 约束(解析高斯的 SOC、CS 的 SDP)。 - OSQP(C):CC-MPC 的 QP 子问题后端——把解析高斯收紧后的线性约束喂给 OSQP(解析高斯收紧后若 \(\Sigma\) 固定,约束是线性的,QP 即可)。 - SOCP 求解器(ECOS/SCS/Clarabel,C/C++):需要二阶锥时(如 margin 含决策相关的 \(\|\Sigma^{1/2}a\|\))用。

CC 部署的工程要点与坑

  • 协方差离线传播:解析高斯 CC 的协方差 \(P_k\) 与控制无关,离线预算好(C++ 里预存数组),在线只解 QP——这是 CC-MPC 能实时的关键,别在线重算 \(P_k\)
  • \(\Phi^{-1}\) 预计算\(\Phi^{-1}(1-\delta)\) 是常数,编译期/启动时算好,别在热路径调用统计库。
  • SOCP/SDP 求解失败兜底:锥规划比 QP 更易遇到数值问题,C++ 里必须有 fallback(上一拍解、保守 margin、安全停车)。
  • IRA 的外层迭代:实时性紧张时,IRA 外层迭代次数要限制(如固定 2–3 轮)或离线预分配风险,避免在线迭代超时。
  • 数值一致性:Python(cvxpy + 成熟锥求解器)与 C++ 手拼可能有数值差异——部署后在 HIL/真机重新验证违反率,别假设"仿真 δ 达标就行"。

给想做开源的你:CC 规划的 C++ 库(尤其 CC-RRT for OMPLCC-MPC for acados/CasADi嵌入式 SDP for Covariance Steering)几乎空白。把 §U3.2–U3.4 的算法做成可复用的 C++ 库并贡献给主流框架(OMPL、Drake),是能产生**实际影响力**的原创工作。


工具与源码精读拓展

CC 规划用得好不好,一半在于会用凸优化工具链。这里给工具梯度与源码精读清单。

CC 的凸优化工具链(按用途)

建模层: - CVXPY(Python,DCP 建模):最快上手——直接用 DCP 语法写 CC-SOCP(cp.norm(...) <= ...)和 DR-CC-SDP,理解 CC 的凸结构。本章所有 Python 实现的建模层。 - CasADi(C++/Python,LGPL):符号框架(SX/MX),手写 CC 约束(\(\Phi^{-1}\) margin)并交给 NLP/QP 后端——CC-MPC 落到 C++ 的主力路径。 - Drake MathematicalProgram(C++/Python):提供 SOCP/SDP 接口,可手工拼出解析高斯 CC(SOC)与 Covariance Steering(SDP)。

求解层: - OSQP(C,ADMM):QP 后端——解析高斯收紧后若 \(\Sigma\) 固定,约束线性,QP 即可,最快。 - ECOS / SCS / Clarabel(C/C++):二阶锥求解(SOCP)——margin 含决策相关的 \(\|\Sigma^{1/2}a\|\) 时用。 - MOSEK(商业):SOCP/SDP 工业级求解,CS 的 SDP 常用。

工具梯度(先易后难):CVXPY 验证算法 → CasADi/Drake 准备 C++ → OSQP/ECOS/SCS 作实时后端。

源码精读清单(按"先易后难")

  1. CVXPY 的 CC 示例:从 DCP 写一个 SOC 约束的 CC 开始,看凸优化如何表达"均值 + margin"。最易,建立直觉。
  2. OSQP(C,稀疏 QP):精读它如何把 QP 求解做到微秒级(ADMM + 稀疏)——CC-MPC 的 QP 子问题后端,理解收紧后的线性约束如何喂给它。
  3. CasADicasadi/casadi):精读如何用 SX/MX 手写 CC 约束(符号化 \(\Phi^{-1}\sqrt{a^\top Pa}\))并 codegen——这是 CC-MPC 上 C++ 的关键。
  4. DrakeRobotLocomotion/drake):精读 MathematicalProgram 的 SOCP/SDP 接口,看怎么手工拼出 CC 与 CS。
  5. RIVeR-Lab / cc-mpc(四足 CC-MPC 配套代码,cc-mpc.github.io):精读摩擦锥 CC 如何转化为 SOCP/QP 约束、不确定性分布怎么建模——本章四足案例的真实实现。

SOCP / SDP 求解器怎么选

CC 的解析高斯收紧落到 SOCP、Covariance Steering 落到 SDP——选锥求解器有讲究: - ECOS(C,内点法):轻量、嵌入式友好,中小规模 SOCP 首选;不解 SDP。 - SCS(C,一阶 ADMM):能解 SOCP + SDP,大规模稳健、精度中等,适合 CS 的 SDP;要高精度需多迭代。 - Clarabel(Rust/C,内点法):较新,SOCP/SDP 都支持,数值稳健,已成 CVXPY 默认之一。 - MOSEK(商业,内点法):SOCP/SDP 工业级最快最稳,有许可成本。

经验法则:高频 CC-MPC(SOCP)用 ECOS/Clarabel;Covariance Steering 的 SDP 用 SCS(开源)或 MOSEK(商业);先用 CVXPY 默认后端跑通,再按"规模 / 精度 / 许可"三维换后端。这一层是 CC 比 U2(纯 QP,OSQP 一把梭)更费心的地方——锥求解器的选择直接影响实时性与数值稳定性。


本章代码索引与项目结构

本章代码不少,给一张索引 + 一个可落地的项目结构,方便把零散片段组织成工程。

代码片段索引

代码 在哪 作用
cc_mpc 实现一 解析高斯 CC-MPC(\(\Phi^{-1}\) 收紧 + QP)
ira / ira_full §U3.2 / 实现二 迭代风险分配(外层分配 + 内层凸)
cc_mpc_with_alloc 实现二 给定风险分配解收紧 QP(IRA 下层)
propagate_covariance / propagate_cov §U3.3 / 累积项目 闭环协方差传播
cc_feasible / cc_rrt_extend §U3.3 CC-RRT 概率可行性检验与生长
cc_rrt / Node 实现续 可运行的最小 CC-RRT
CCNavTestbed / cc_controller / monte_carlo 累积项目 CC 导航测试台 + 控制器 + 评测
design_feedback 累积项目 LQR 反馈增益(协方差传播用)
gmm_cc_margin 进阶一 非高斯(GMM)CC 的逐成分 margin
scenario_cc_mpc 实现续二 场景法 CC-MPC(非高斯/分布无关)
cc_margin_with_perception 累积项目进阶 计入感知不确定 \(\Sigma_o\) 的收紧

建议的项目结构(Python 原型 + C++ 部署双包)

cc_nav/
├── prototype_py/                 # Python 原型(研究/验证)
│   ├── cc_mpc.py                 # cc_mpc, cc_mpc_with_alloc(解析高斯)
│   ├── ira.py                    # ira_full(迭代风险分配)
│   ├── cc_rrt.py                 # cc_rrt, Node, propagate_covariance
│   ├── nongaussian.py            # gmm_cc_margin, scenario_cc_mpc(非高斯路线)
│   ├── testbed.py                # CCNavTestbed, monte_carlo, design_feedback
│   └── experiments.py            # 扫 δ、均分 vs IRA、CC vs Tube 对比
├── deploy_cpp/                   # C++ 部署(实时上真机)
│   ├── include/cc_mpc.hpp        # CC-MPC(CasADi 手写 CC 约束 + OSQP/ECOS)
│   ├── src/cc_node.cpp           # ROS2 实时节点
│   ├── CMakeLists.txt            # 链接 CasADi, OSQP/ECOS, rclcpp
│   └── config/params.yaml        # δ, Σ_w, Σ_o, 障碍, 时域...
└── solvers/                      # 求解器后端(可选)
    └── socp_backend/             # ECOS/SCS/Clarabel 封装(SOCP)

衔接工作流:在 prototype_py/ 把算法/风险分配/分布假设跑通(累积项目扫 δ、做消融、对比 Tube)→ 把热路径(CC-MPC 的 QP/SOCP)用 CasADi 手写 CC 约束移到 deploy_cpp/ → 用 config/params.yaml 让 Python 调好的 δ、协方差直接喂 C++,避免两边手抄。这条结构对应"两段式工作流",也是 CC 规划项目的常见骨架——只是相比 U2,求解器后端(SOCP/SDP)这一层目前要自己多费心。


综合实战清单:从零搭一个 CC 导航规划器

把全章串成动手清单——给一个高斯扰动下的移动机器人做"概率安全到达",按步骤走,每步标了用本章哪节/哪段代码。

第 0 步:明确分布与风险预算 - 确认扰动分布:高斯(→ 解析)/ 仅知矩(→ Cantelli)/ 非高斯(→ 粒子/场景)/ 分布不确定(→ DR-CC)。 - 定总风险预算 δ(JCC),决定你在安全谱上的位置(δ→0 近 Tube,δ 大近期望最优)。 - 确认要 ICC 还是 JCC(几乎总是 JCC → 需 Boole + 风险分配)。

第 1 步:建模与协方差传播 - 写名义动力学与反馈增益 \(K\)(LQR,§累积项目 design_feedback)。 - 离线传播闭环协方差 \(P_k=(A-BK)P_{k-1}(A-BK)^\top+\Sigma_w\)propagate_cov)——CC 实时的关键。

第 2 步:选近似 + 收紧 - 高斯 → 解析 margin \(\Phi^{-1}(1-\delta_{j,k})\sqrt{a^\top P_k a}\)(实现一)。 - 把每个障碍面/约束按 §U3.2 收紧成确定性约束。

第 3 步:风险分配 - 简单起步:Boole 均分 \(\delta_{j,k}=\delta/(NM)\)。 - 保守度敏感 → IRA(实现二):外层分配、内层 QP,把预算挪给紧约束。

第 4 步:选规划器并求解 - 优化型 → CC-MPC(实现一,QP/SOCP)。 - 采样型 → CC-RRT(实现续,协方差传播 + 概率剔除)。 - 窄缝要塑形不确定性 → Covariance Steering(§U3.4,SDP)。

第 5 步:验证 - 蒙特卡洛(累积项目 monte_carlo):统计**整条轨迹**违反率,应 ≤ δ。 - 扫 δ 画"风险 ↔ 保守度"曲线(Silver 档)。 - 消融:风险中性 → +CC 收紧 → +IRA,确认每部分作用。

第 6 步:部署(可选) - 热路径(QP/SOCP)用 C++(CasADi/OSQP/Drake,§C++ 部署)。 - 协方差与 \(\Phi^{-1}\) 离线预算;锥求解失败要兜底。

第 7 步:上真机前检查 - 扰动分布是否符合真机(高斯假设成立吗)? - 整条轨迹违反率(非单步)是否 ≤ δ? - 感知/定位不确定性 \(\Sigma_o\) 是否计入(接 U4)?

走完这八步,你就有了一个"解析高斯收紧 + 风险分配 + (MPC 或 RRT)"的 CC 导航规划器——本章方法的集成形态。把它和累积项目测试台拼起来,就是一个能扫 δ、做消融、对比 Tube 的完整 CC 实验平台。


进阶专题导读

正文(§U3.1–U3.5)覆盖了机会约束的核心;下面十个进阶专题是**按需深入**的拓展——不必顺读,按你的问题挑相关的看。它们按主题分五组:

专题 解决什么问题
分布不是高斯 一(非高斯 GMM/矩)、二(分布鲁棒 DR-CC) 解析高斯失效时怎么办:多模态/重尾/分布本身不确定
更紧 / 更优 三(更紧联合风险界)、四(IRA 数值走查) 怎么减少 Boole + 均分的保守度
系统性质 五(递归可行性)、八(实时性优化) 无界噪声下的可行性保证、怎么让 CC-MPC 跑到真机频率
约束与规模扩展 七(约束类型 CC 化)、九(多智能体) 摩擦锥/二次约束怎么 CC 化、多机器人怎么分配风险
数据与桥接 六(数据驱动 CC)、十(CVaR/U5 桥) 用 GP 学分布做 CC(接 U2)、从违反概率到尾部严重度(接 U5)

怎么选读:做四足/机械臂 → 七(摩擦锥)+ 八(实时);分布非高斯 → 一 + 二;保守度卡性能 → 三 + 四;多机器人 → 九;衔接 U2 GP-MPC → 六;衔接 U5 风险敏感 → 十。每个专题都自带"本质洞察"收尾,可先扫洞察再决定要不要细读。


进阶专题一:非高斯机会约束(GMM 与矩方法) ⭐⭐⭐

正文的解析高斯收紧依赖"扰动/状态是高斯"。但现实里不少分布是**非高斯**的——多模态(他车可能左转也可能右转,是双峰)、重尾(极端阵风比高斯预测的更频繁)、有偏(摩擦力单侧饱和)。这一节给两条非高斯的出路:高斯混合(GMM)与矩方法。

何时高斯假设会坏

  • 多模态:障碍/他车位置是若干可能性的叠加(如路口的多个意图),单高斯把双峰硬拟合成一个胖单峰,既高估中间(其实没车)、又低估两侧(车真在那)。
  • 重尾:高斯尾部衰减极快(\(e^{-x^2/2}\)),真实极端事件(强阵风、传感器野值)按高斯算"几乎不可能",实际却时有发生——用高斯 \(\Phi^{-1}\) 收紧会**低估**风险、违反概率超标。
  • 有界 / 有偏:物理量常有硬边界(力不能为负、速度有上限),高斯的无界对称尾不符。

判断方法:对采集的扰动数据做正态性检验(QQ 图、Shapiro–Wilk),或直接看直方图是否单峰对称。明显不符就别用解析高斯。

路线一:高斯混合(GMM-CC)

把非高斯分布近似成 \(L\) 个高斯的加权和:\(p(w)=\sum_{l=1}^{L}\pi_l\,\mathcal{N}(\mu_l,\Sigma_l)\)\(\sum_l\pi_l=1\))。则线性约束的违反概率是各成分违反概率的加权和: $\(\Pr(a^\top x>b)=\sum_{l=1}^{L}\pi_l\,\Pr_l(a^\top x>b)=\sum_{l=1}^{L}\pi_l\,\Big[1-\Phi\Big(\tfrac{b-a^\top\mu_l}{\sqrt{a^\top\Sigma_l a}}\Big)\Big].\)$ 要 \(\Pr(a^\top x>b)\le\delta\),一个直接(但保守)的做法是**给每个成分分配风险** \(\delta_l\)\(\sum_l\pi_l\delta_l\le\delta\),或更简单地 \(\sum_l\delta_l\le\delta\)),每个成分用解析高斯收紧: $\(a^\top\mu_l\le b-\Phi^{-1}(1-\delta_l)\sqrt{a^\top\Sigma_l a},\quad\forall l.\)$ 这把"非高斯 CC"化成"一族高斯 CC"——和 §U3.1 的 Boole 风险分配是同一招,只是这里分配给的是**混合成分**而非时步。成分间的风险分配同样可以用 IRA 优化(把预算挪给"贴边界"的成分)——这正是 Ono–Williams 的 IRA 思想在 GMM 上的推广(已有工作用 GMM + 风险分配处理非高斯 CC 轨迹控制)。

import numpy as np
from scipy.stats import norm

def gmm_cc_margin(a, components, deltas):
    """GMM 机会约束:返回收紧后约束 a^T mu_l <= b - margin_l 的逐成分 margin。
    components: [(pi_l, mu_l, Sigma_l)]; deltas: 每个成分分配的风险 δ_l。
    满足所有成分约束 ⇒ 总违反概率 <= Σ π_l δ_l。"""
    margins = []
    for (pi_l, mu_l, Sigma_l), d_l in zip(components, deltas):
        z = norm.ppf(1.0 - d_l)
        margins.append(z * np.sqrt(float(a @ Sigma_l @ a)))   # 该成分的收紧量
    return margins   # 对每个成分施加 a^T mu_l <= b - margins[l]

代价:成分越多越准、但约束越多(每成分一条)、求解越慢;且把"或"(混合)保守地拆成"与"(所有成分都满足)会偏保守。工程上 \(L\) 取 2–4 常够用。

路线二:矩方法(Cantelli,分布无关)

如果连分布形状都不想假设,只用**均值和协方差**(前两阶矩),可用 Cantelli 不等式(单边 Chebyshev):对任意分布, $\(\Pr\big(a^\top x>b\big)\le\frac{a^\top\Sigma a}{a^\top\Sigma a+(b-a^\top\mu)^2}\quad(b>a^\top\mu).\)$ 令右边 ≤ δ,整理得收紧形式(与解析高斯同构,只换系数): $\(a^\top\mu\le b-\kappa(\delta)\sqrt{a^\top\Sigma a},\qquad \kappa(\delta)=\sqrt{\frac{1-\delta}{\delta}}.\)$ 对比系数:δ=0.05 时 Cantelli \(\kappa=\sqrt{0.95/0.05}=\sqrt{19}\approx4.36\),而高斯 \(\Phi^{-1}(0.95)\approx1.645\)——Cantelli 收紧是高斯的 2.6 倍!这就是"分布无关"的代价:不知道形状,就得按最坏的形状(在给定矩下)留余量。

本质洞察:分布知道得越少,付出越多。高斯(知道是高斯)→ 系数 1.645;只知矩(不知形状)→ Cantelli 4.36;连矩都不准(分布族)→ DR-CC(专题二,更大)。这条"信息 ↔ 保守度"的递减阶梯,和 U2 理论补遗里 DRO 的精神、U0 的"信息需求 ↔ 保守度"权衡完全一致——CC 只是把它落到了收紧系数这个具体数字上。

⚠️ 非高斯 CC 的常见误区

💡 概念误区:明明非高斯却套用高斯系数 - 现象/后果:用 \(\Phi^{-1}\) 收紧重尾/多模态分布,蒙特卡洛违反率超标(高斯低估了尾部)。 - 正确做法:正态性检验不通过 → GMM(多模态)或 Cantelli(只信矩)或粒子/场景法(任意分布)。 - 检验:对解出的轨迹用**真实分布**(而非高斯近似)做蒙特卡洛,看违反率是否真 ≤ δ。

🧠 思维陷阱:以为 GMM 成分越多总越好 - 现象/后果:成分数 L 开得很大,约束爆炸、求解超时,且过拟合采样噪声。 - 正确做法:L 取够拟合主要模态即可(常 2–4);用 BIC/AIC 选 L,别一味加。


进阶专题二:分布鲁棒机会约束(DR-CC) ⭐⭐⭐⭐

专题一的 Cantelli 已经触到"分布无关"。分布鲁棒 CC(Distributionally Robust CC, DR-CC) 把这个思想形式化:当**分布本身不确定**(只有有限数据、不知真分布)时,对"一个分布族(模糊集 ambiguity set)内的最坏分布"保证机会约束。

动机:连分布都估不准怎么办

解析高斯假设你知道分布是高斯且参数已知;但有限数据下,你估的 \(\hat\mu,\hat\Sigma\) 本身有误差,真分布可能不是高斯。若按估计的分布做 CC,估计偏差会让真实违反概率超标。DR-CC 的思路:不赌单一分布,而是要求**对一个包含真分布的分布族里的每个分布都满足 CC**: $\(\inf_{\mathbb{P}\in\mathcal{P}}\ \Pr_{\mathbb{P}}\big(a^\top x\le b\big)\ge 1-\delta,\)$ 其中 \(\mathcal{P}\) 是模糊集。这给出"无论真分布是族里哪个,违反概率都 ≤ δ"的鲁棒保证。

两类模糊集

矩模糊集(moment-based)\(\mathcal{P}=\{\mathbb{P}:\mathbb{E}[w]=\mu,\ \mathrm{Cov}[w]=\Sigma\}\)——所有均值 \(\mu\)、协方差 \(\Sigma\) 的分布。对这个族的 DR-CC,最坏分布给出的收紧**恰好是 Cantelli**: $\(a^\top\mu\le b-\sqrt{\tfrac{1-\delta}{\delta}}\sqrt{a^\top\Sigma a}.\)$ 这是一个漂亮的统一:专题一的 Cantelli 不等式,正是矩模糊集下的 DR-CC——"只知矩"等价于"对所有同矩分布鲁棒"。Calafiore–El Ghaoui(2006)证明这类 DR-CC 化成 SOCP

Wasserstein 模糊集\(\mathcal{P}=\{\mathbb{P}:W(\mathbb{P},\hat{\mathbb{P}}_N)\le\varepsilon\}\)——与经验分布 \(\hat{\mathbb{P}}_N\)(N 个数据点)的 Wasserstein 距离不超过半径 \(\varepsilon\) 的所有分布。它以数据为中心画一个"分布球",球内任意分布都保证。半径 \(\varepsilon\) 随数据量增大而缩小(数据越多越敢相信经验分布)。Wasserstein DR-CC 通常化成 SOCP/SDP,是数据驱动鲁棒优化的现代主力(Lew–Pavone 等用于航天/自驾的 CC-SCP)。

保守度阶梯(再次)

把收紧系数排一排(δ=0.05): | 假设 | 收紧系数 | 含义 | |---|---|---| | 已知高斯 | \(\Phi^{-1}(0.95)\approx1.645\) | 最紧(信息最多)| | 只知矩(= 矩 DR-CC = Cantelli)| \(\sqrt{19}\approx4.36\) | 对所有同矩分布鲁棒 | | Wasserstein DR-CC | 随 \(\varepsilon\) 增大(数据少则大)| 对分布球内鲁棒,数据越少越保守 |

本质洞察:DR-CC = 给"不知道分布"上保险。它在"解析高斯(赌单一分布,可能赌错)"与"完全不优化(太保守)"之间,给出一个**数据驱动、可调鲁棒度**的中间方案——模糊集越大越保守越稳、越小越紧越冒险。这与 U2 的 DRO 同源,也与本章"δ 是风险旋钮"呼应:DR-CC 多了第二个旋钮——模糊集大小 ε,调的是"对分布误差的鲁棒度"。

何时用 DR-CC

  • 数据少、分布没把握:DR-CC 比解析高斯稳健得多(不会因估计偏差超标)。
  • 安全关键且分布会漂移(如不同地形、不同负载的四足):用 DR-CC 对分布变化留余量。
  • 不要在数据充足且分布确定时用:那时解析高斯更紧、更省,DR-CC 白白保守。

进阶专题三:更紧的联合风险界(Bonferroni 之外) ⭐⭐⭐

§U3.1 用 Boole(union bound)拆 JCC,简单但保守。这一节看看"还能更紧吗"。

Boole / Bonferroni 的保守来源

Boole \(\Pr(\bigcup A_i)\le\sum\Pr(A_i)\) 只在事件**互斥**时取等。轨迹约束里,相邻时刻接近同一面墙的违反事件高度**正相关**(这一刻危险下一刻多半也危险),重叠很大,于是 \(\sum\Pr(A_i)\) 远高估真实联合违反概率。Bonferroni 不等式是 Boole 的高阶推广(加上两两交集的修正项),更紧但需要联合分布信息(\(\Pr(A_i\cap A_j)\)),实践中难获取。

三条收紧路线

  1. 最优风险分配(IRA,§U3.2):不改 Boole 框架,但把预算最优分配——减的是"均分 vs 最优"的保守度,不是 Boole 本身。已在正文详述。
  2. 椭球松弛(ellipsoidal relaxation):把多个线性约束的联合用一个椭球包络近似。IRA 论文(Ono–Williams)正是证明 IRA 比椭球松弛保守度小——椭球松弛是 IRA 要超越的基线。
  3. 采样 / 场景法做 JCC(§U3.2 方法谱):直接对整条轨迹采样,统计"整条轨迹违反"的频率,绕开 Boole 的解析上界。Campi–Garatti 的样本复杂度界对 JCC 同样适用。代价是大量样本。

保守度阶梯(联合风险界)

从最保守到最紧(近似): $\(\underbrace{\text{Boole + 均分}}_{\text{最保守、最简}}\ \succ\ \underbrace{\text{Boole + IRA}}_{\text{最优分配}}\ \succ\ \underbrace{\text{Bonferroni / 椭球}}_{\text{需更多信息}}\ \succ\ \underbrace{\text{采样 JCC}}_{\text{最紧、最贵}}.\)$

本质洞察:联合风险界是"可解性 ↔ 紧度"的又一条谱。Boole 最好算但最松,采样最紧但最贵。工程上绝大多数 CC-MPC 用 Boole + IRA——在"可解 + 实时"约束下取一个够用的紧度。只有当保守度确实卡住性能、且有离线算力时,才考虑更紧的界。这和"CC 近似方法谱"(§U3.2)、"三代 Tube"(U2 §U2.2)是同一种工程权衡思维的复现。


进阶专题四:IRA 数值走查(手算理解风险再分配) ⭐⭐⭐

为了让 §U3.2 的 IRA 不只是代码,用一个**可手算**的两约束例子走一遍,看风险再分配怎么降保守度。

设定:两个约束面,标准差都是 \(\sigma=1\)(即 \(\sqrt{a^\top\Sigma a}=1\))。约束 1 很紧(名义距边界 \(d_1=1.7\)),约束 2 很松(名义距边界 \(d_2=4.0\))。总风险预算 \(\delta=0.05\)

第 0 步——均分\(\delta_1=\delta_2=0.025\)。收紧系数 \(\Phi^{-1}(1-0.025)=\Phi^{-1}(0.975)\approx1.96\)。 - 约束 1 需要 margin \(1.96\times1=1.96\),但实际只有 \(d_1=1.7<1.96\)——违反! 均分下约束 1 不可行(或迫使名义轨迹后退、保守)。 - 约束 2 需要 margin \(1.96\),实际有 \(d_2=4.0\gg1.96\)——大量富余(slack \(=4.0-1.96=2.04\))。

问题诊断:均分给了约束 2 用不完的预算(它离边界远),却让紧的约束 1 吃不饱。

第 1 步——IRA 再分配:把约束 2 的多余风险挪给约束 1。约束 2 离边界 4.0,其实只需很小的 margin——给它一个很小的 \(\delta_2\)(比如 \(\delta_2=0.001\),对应系数 \(\Phi^{-1}(0.999)\approx3.09\),margin \(3.09<4.0\) 仍满足)。于是约束 1 可用 \(\delta_1=\delta-\delta_2=0.049\),系数 \(\Phi^{-1}(0.951)\approx1.655\),margin \(1.655<1.7\)——约束 1 现在可行了!

结果对比: | | 均分 | IRA | |---|---|---| | \(\delta_1,\delta_2\) | 0.025, 0.025 | 0.049, 0.001 | | 约束 1 margin(需 ≤1.7)| 1.96 ❌ | 1.655 ✅ | | 约束 2 margin(需 ≤4.0)| 1.96 ✅(浪费) | 3.09 ✅ | | 整体可行? | 否(约束 1 越界)| 是 |

解读:同样的总预算 0.05,均分让问题不可行,IRA 通过"把松约束的预算挪给紧约束"让问题可行。这就是 IRA 降保守度的微观机制——风险预算是稀缺资源,IRA 把它花在刀刃(紧约束)上。真实 IRA 是对多约束、多时步迭代做这件事,原理一致。

把这个例子塞进实现二的 ira_full:初始均分会发现约束 1 的 slack 为负(不可行/贴边),外层把约束 2(slack 大)的预算转移过来,迭代后约束 1 的 margin 降到 1.7 以下——与手算一致。这是验证 IRA 实现的最简 sanity check。


进阶专题五:CC-MPC 的递归可行性与稳定性 ⭐⭐⭐⭐

U2 §理论补遗讲过名义/鲁棒 MPC 的递归可行性(terminal set + terminal cost 保证每步有解、闭环稳定)。CC-MPC 也需要这套,但**无界高斯噪声**带来特殊挑战。

挑战:无界噪声下"严格"递归可行性不可能

递归可行性要"这一步可行 ⇒ 下一步也可行"。但高斯噪声无界——任意大的噪声有非零概率把状态推到任何地方,使下一步的 CC 无法满足。所以**严格的(概率 1 的)递归可行性在无界噪声下不可能**,这与有界扰动的 Tube MPC(可严格保证)根本不同。

工程上的处理

  • 软约束(soft constraints):把 CC 约束软化(加松弛变量 + 重罚),保证 QP 总有解(即使偶尔松弛)——避免无界噪声导致 infeasible 卡死。这是实践中最常用的兜底。
  • 概率递归可行性:退而求"以高概率递归可行"——Okamoto 等给出在无界高斯噪声下、用合适终端约束/反馈,保证递归可行性与稳定性、且计算代价低于早期方法的结果。
  • 终端 CC 集:设计一个满足 CC 的终端不变集(probabilistic invariant set),状态进入后能以 ≥1−δ 概率留在内——CC 版的终端集,类比 Tube 的终端约束。
  • 协方差稳态:闭环协方差 \(P_k\) 收敛到稳态 \(P_\infty\)(解 Lyapunov 方程 \(P_\infty=(A-BK)P_\infty(A-BK)^\top+\Sigma_w\)),稳态后收紧 margin 不再增长——这让长时域 CC-MPC 的 margin 有界(否则 margin 随时域无限增大,远期约束无法满足)。

与 Tube 的对照

Tube MPC(有界扰动) CC-MPC(无界高斯)
递归可行性 可严格保证(RPI 终端集) 严格不可能;求概率递归可行 / 软约束
收紧量随时域 有界(\(\Omega\) 固定) \(P_k\) 增长,但稳态后有界(\(P_\infty\)
不可行兜底 终端集设计保证有解 软约束松弛兜底
稳定性 终端代价 + 终端集 终端 CC 集 + 协方差稳态

本质洞察:无界噪声是 CC 区别于 Tube 的根本难点。Tube 因扰动有界,能给"概率 1 的硬保证 + 严格递归可行";CC 因扰动无界,只能给"概率 1−δ 的保证 + 概率递归可行/软约束兜底"。这不是 CC 的缺陷,而是它处理的问题(无界扰动)本质更难——零违反在无界下不可能,δ 就是为此付的"入场费"。理解这点,就理解了为什么 CC-MPC 工程实现几乎总要软约束兜底,而 Tube MPC 可以硬到底。


进阶专题六:数据驱动 CC(学到的分布 + CC-MPC) ⭐⭐⭐

正文的 CC 假设你**知道**扰动分布(高斯,参数已知)。但很多时候分布要从数据里学——这正是 U2 §U2.4 的 GP-MPC 做的事。数据驱动 CC 把"学分布"与"CC 收紧"串起来:用 GP(或其他方法)学出扰动/残差的分布(均值 + 方差),再把学到的分布喂给 CC 收紧。这是 U2 GP-MPC 与本章 CC 的天然融合点。

GP-MPC 本来就是一种数据驱动 CC

回顾 U2 §U2.4:GP-MPC 用 GP 学动力学残差 \(d_k\sim\mathcal{GP}(\mu_d,\Sigma_d)\),把均值 \(\mu_d\) 修正预测、把方差 \(\Sigma_d\) 经协方差传播喂给机会约束 \(\Pr(x_k\in\mathcal{X})\ge1-\delta\)。换句话说——GP-MPC 就是"残差分布由 GP 学得"的 CC-MPC。本章给的解析高斯收紧、风险分配、JCC 处理,全都适用于 GP-MPC 的机会约束部分。U2 把重点放在"怎么学残差",本章把重点放在"怎么用学到的不确定性做概率约束"——两者拼起来才是完整的数据驱动 CC。

一般框架:学分布 → CC 收紧

def data_driven_cc_margin(a_j, gp_model, x_query, delta_step):
    """数据驱动 CC:用 GP 在当前查询点预测扰动方差,再做 CC 收紧。
    gp_model.predict(x) -> (mean, var):GP 学到的残差分布(U2 §U2.4)。"""
    from scipy.stats import norm
    import numpy as np
    _, var = gp_model.predict(x_query.reshape(1, -1))   # GP 预测方差(学到的不确定性)
    Sigma_d = np.diag(np.atleast_1d(var).ravel())       # 残差协方差
    z = norm.ppf(1.0 - delta_step)
    return z * np.sqrt(float(a_j @ Sigma_d @ a_j))      # 用学到的方差收紧

关键点:CC 的收紧量 \(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\) 里的 \(\Sigma\),现在**由 GP 在当前状态预测**——数据多的区域方差小(收紧少、进取),数据少/外推的区域方差大(收紧多、保守)。这把 U2 GP-MPC 的"方差驱动保守度"与本章 CC 的"概率约束"无缝接上。

注意:学到的分布的可靠性

数据驱动 CC 的保证强度,取决于**学到的分布有多准**: - GP 方差混合 epistemic(数据少,可采集消减)与 aleatoric(固有噪声,消不掉)——呼应 U2 §U2.4 的陷阱。若把不准的方差喂给 CC,违反概率保证就不可靠。 - 学到的分布若系统性偏小(GP 过自信),CC 会低估风险、违反率超标——这是数据驱动 CC 比"已知高斯 CC"更需要警惕的地方。 - 前沿做法:用 DR-CC(专题二)对"学到的分布的误差"再留一层鲁棒——即"分布鲁棒的数据驱动 CC",对 GP 估计偏差也稳健。

本质洞察:GP-MPC = 学分布的 CC-MPC。U2 与 U3 在这里合流——GP 提供"状态相关、数据驱动"的分布,CC 把这个分布转成概率约束。这是"模型 + 数据"(U0 跨越二)在概率约束上的落地:不确定性既不是拍脑袋的常数(U2 Tube 的固定 \(\Omega\))、也不是假设的固定高斯(本章正文),而是**从数据里学出来、随状态变化**的。下次看到 GP-MPC,你应认出它就是数据驱动 CC;看到 CC-MPC,你应想到它的分布可以来自 GP。


进阶专题七:不同约束类型的 CC 化(半空间 / 摩擦锥 / 二次) ⭐⭐⭐

正文用的是**线性(半空间)约束** \(a^\top x\le b\) 的 CC。真实约束类型更多样——本节看半空间、二阶锥(摩擦锥)、二次约束各自怎么 CC 化。

半空间约束(线性,最常见)

\(a^\top x\le b\),高斯下精确收紧为 \(a^\top\bar x\le b-\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\)(§U3.2)。避障(凸障碍 = 半空间的交)、状态/控制盒约束都属此类。这是本章的主力,凸(SOC)、可解。

二阶锥约束(摩擦锥——四足案例的核心)

四足的地面反作用力 \(f\) 必须落在**摩擦锥**内:\(\sqrt{f_x^2+f_y^2}\le\mu f_z\)(切向力不超过摩擦系数 × 法向力)。这是个二阶锥约束。当 \(f\) 不确定(负载/地形扰动)时,要求"力落在锥内的概率 ≥ 1−δ"。Trivedi 等(四足案例)的做法:把摩擦锥的机会约束**保守地收紧成一个更小的确定性锥**——对锥的每个线性化面(或锥本身)用类似解析高斯的 margin 收紧,化成 SOCP/QP 求解。

直觉:不确定性让"力可能溢出锥",于是把锥**向内收一圈**(收的量由 δ 和力的协方差决定),名义力落在收紧后的内锥里,就保证真实力以 ≥1−δ 概率落在原锥内。这与半空间收紧是同一思想(向内收 margin),只是对象从平面变成锥面。

def friction_cone_cc_tighten(mu, f_z_nom, sigma_tangential, delta):
    """摩擦锥 CC 收紧(示意):把摩擦系数 μ 收紧为 μ',
    使名义切向力落在内锥 ⇒ 真实切向力以 ≥1-δ 概率落在原锥。
    sigma_tangential: 切向力的不确定性标准差。"""
    from scipy.stats import norm
    z = norm.ppf(1.0 - delta)
    # 锥容量 = μ·f_z;收紧 = 扣掉 z·σ 的不确定性余量
    tightened_capacity = mu * f_z_nom - z * sigma_tangential
    return max(tightened_capacity, 0.0)   # 收紧后的切向力上限(>=0)

这是四足 CC-MPC "无需手调 margin"的微观机制:margin 由 δ 与力的协方差自动算出,地形/负载变了协方差变、margin 自适应——不像手调 margin 那样要针对每种地形重调。

二次约束

形如 \(x^\top Qx\le c\)(如能量/速度约束)的 CC 更难——二次型的分布一般非高斯(即使 \(x\) 高斯,\(x^\top Qx\) 是卡方型)。处理路线:(1) 线性化(在工作点把二次约束近似成线性,再用解析高斯);(2) 矩方法(用二次型的均值方差 + Cantelli);(3) 采样/场景法(任意分布)。这类约束 CC 化是开放问题之一(尤其保持可解性)。

本质洞察:CC 化的难度取决于"约束量的分布"。线性约束 + 高斯 → 约束量仍高斯 → 解析精确(半空间)。二阶锥 → 可保守收紧成内锥(摩擦锥)。二次约束 → 约束量非高斯(卡方)→ 只能近似。一句话:约束越非线性,CC 化越难——因为"约束量的分布"越偏离高斯,解析收紧越失效。这解释了为什么避障(线性半空间)的 CC 最成熟、摩擦锥(SOC)次之、一般二次约束仍是难点。


进阶专题八:CC-MPC 的实时性优化 ⭐⭐⭐

CC-MPC 要上真机(如四足几百 Hz),实时性是硬约束。本节把全章散落的"怎么让 CC-MPC 快"集中起来,并接 U2 §U2.6 的 acados 与 §C++ 部署。

关键优化手段

1. 协方差离线预算(最重要):解析高斯 CC 的协方差 \(P_k=(A-BK)P_{k-1}(A-BK)^\top+\Sigma_w\) 与控制无关——它只取决于动力学、反馈 \(K\)、噪声 \(\Sigma_w\)。所以整条 \(P_0,\dots,P_N\) 可以**离线一次算好、在线直接查表**。在线只剩一个 QP(约束已是收紧后的线性约束)。这是 CC-MPC 能跑高频的头号原因。

2. 风险分配预计算 / 固定:IRA 的外层迭代是在线开销大头。实时场景的折中:(a) 离线预分配 风险(对典型场景预跑 IRA、存下分配),在线用固定分配;(b) 限制在线 IRA 轮数(如 2–3 轮);(c) 危险段才触发 IRA、开阔段用均分。

3. Warm-start(热启动):相邻控制周期的解很接近,用上一拍的解初始化这一拍的 QP——OSQP/qpOASES 都支持,能把求解时间压一大截(同 U2 §U2.1 的 warm_start=True)。

4. Condensing(凝聚):把多步 OCP 的状态变量消去、只留控制变量,得到一个更小的稠密 QP(适合短时域);或反过来用稀疏结构 + 内点法(适合长时域)——与 U2 §U2.6 的 HPIPM 块结构同理。

5. 约束筛选:远处障碍的 CC 约束几乎不活跃,可只对"近处几个障碍"建约束(按距离剔除),减小 QP 规模——同 U2 故障排查里"多障碍 CBF 只激活最近几个"。

CC-MPC 实时性 vs U2

手段 U2(Tube/CBF) CC-MPC
离线预算 RPI 集 \(\Omega\)、增益 \(K\) 协方差 \(P_k\)\(\Phi^{-1}\)、(可选)风险分配
在线核心 收紧名义 QP / CBF-QP 收紧 CC QP(协方差已离线)
Warm-start
求解器 OSQP/qpOASES/acados OSQP(QP)/ECOS(SOCP)
主要瓶颈 QP 规模 QP 规模 +(若在线 IRA)外层迭代

开放问题:CC 嵌入 acados 的 SQP-RTI

U2 §U2.6 的 acados 用 SQP-RTI(准备 + 反馈两阶段)把 NMPC 压到亚毫秒。把**机会约束收紧**高效塞进这个框架,是一个明确的开放工程问题:协方差离线传播天然契合"准备阶段",收紧后的约束可作为 acados 的约束传入——但目前没有成熟的"CC-for-acados"接口。做出来就是一个高价值开源贡献(§前沿、§C++ 部署反复点到)。

本质洞察:CC-MPC 的实时性 = 把不确定性处理挪到离线。它快的根本原因和 U2 Tube 一样——把贵的部分(协方差传播、风险分配、RPI 集)离线算,在线只留一个和名义 MPC 同规模的 QP。这是整个"约束收紧"范式(Tube + CC)能上嵌入式实时的共同秘诀:在线不碰不确定性本身,只解一个被收紧的确定性问题。理解这点,你就知道 CC-MPC 优化实时性该往哪使劲——把一切与控制无关的量挪到离线。


进阶专题九:多智能体机会约束 ⭐⭐⭐⭐

前面都是单机器人。多机器人/多智能体(无人机群、多车协同)的机会约束有额外结构——风险预算要在智能体间分配、约束彼此耦合。本节给概览(这条线也通往"多智能体时空协调"方向)。

多智能体 CC 的新问题

  • 联合安全的风险预算:N 个智能体都要安全,总违反预算 δ 怎么分给各智能体?这是 §U3.1 风险分配在"智能体维度"的推广——可均分、可按风险按需分(IRA 跨智能体)。
  • 智能体间避碰(耦合约束):智能体 i、j 不能相撞,约束 \(\|p_i-p_j\|\ge d\) 同时涉及两者状态、两者协方差。碰撞概率取决于**相对位置的分布**——相对协方差 \(\Sigma_i+\Sigma_j\)(独立时相加),CC 收紧用这个相对协方差。
  • 集中 vs 分布式:集中式(一个求解器解所有智能体)最优但不可扩展、单点故障;分布式(各智能体本地解 + 协调)可扩展、鲁棒,但要处理耦合。

分布式求解:ADMM

多智能体 CC(尤其 Covariance Steering)常用 ADMM(交替方向乘子法) 分布式求解:把耦合约束(如避碰、共享预算)通过对偶变量解耦,各智能体本地解自己的子问题、再交换边界信息协调。Pilipovsky–Tsiotras 的多智能体分布式 CS 即用 ADMM——把大规模联合协方差塑形拆给各智能体,每个本地解一个小 SDP/SOCP,迭代协调到全局一致。

直觉:ADMM 让每个智能体"先按当前对其他智能体的估计本地优化、再更新对耦合约束的乘子",反复迭代收敛——这与 §U3.5 的拉格朗日对偶、IRA 的预算分配同源(都是用对偶变量处理约束/耦合)。

与单机 CC 的关系

多智能体 CC 不是全新方法,而是单机 CC 的**结构化扩展**: - 收紧仍是解析高斯 \(\Phi^{-1}\sqrt{a^\top\Sigma a}\),只是 \(\Sigma\) 换成相对协方差(避碰); - 风险分配从"时步×约束面"扩到"时步×约束面×智能体"; - 求解从单个 QP/SOCP/SDP 扩到 ADMM 协调的一组子问题。

本质洞察:多智能体 CC = 单机 CC + 风险/约束的分布式协调。新东西只有两样:风险预算多了"智能体"这个分配维度、约束多了"智能体间耦合"。处理手段还是老三样——解析收紧(用相对协方差)、风险分配(跨智能体,可 IRA)、对偶分解(ADMM 解耦耦合)。这呼应了一个贯穿本章的主题:CC 的核心机制(收紧 + 风险分配)高度可复用,换个场景只是换收紧对象、扩分配维度。从单步到整条轨迹(JCC)、从优化型到采样型(CC-RRT)、从单机到多机,都是这套机制的再应用。


进阶专题十:从"违反概率"到"违反严重度"——CC、CVaR 与风险度量(U5 桥) ⭐⭐⭐

机会约束限制"违反的**概率**"(多大概率出事),但它对"违反**有多糟**"完全不敏感——1% 概率的轻微擦碰和 1% 概率的灾难性坠毁,在 CC 眼里是**一样**的。有时你真正在乎的是后者。这一节引入 CVaR(条件风险价值)——它既是 §U3.2 提到的"CC 的凸上界近似",又是 U5 的主角,正好作 U3→U5 的桥。

CC 的盲区:只管频率,不管严重度

CC 约束 \(\Pr(g(x)>0)\le\delta\) 只看"违反事件的概率",不看"违反时 \(g\) 有多大"。两个分布可以有**完全相同**的违反概率,但尾部严重度天差地别: - 分布 A:违反时 \(g=+0.1\)(轻微擦碰),违反概率 4%。 - 分布 B:违反时 \(g=+100\)(灾难坠毁),违反概率 4%。

对 δ=0.05 的 CC,两者都满足(违反概率 4% ≤ 5%)——CC 根本区分不了 A 和 B。但显然 B 危险得多。这就是 CC 的盲区:它管"多大概率出事",不管"出事有多严重"。

VaR 与 CVaR:把"严重度"纳入

VaR(Value-at-Risk,风险价值):损失 \(L\) 在置信水平 \(\alpha\) 下的 VaR 是它的 \(\alpha\)-分位数,\(\mathrm{VaR}_\alpha(L)=\inf\{t:\Pr(L\le t)\ge\alpha\}\)。它回答"最坏 \((1-\alpha)\) 情形的门槛是多少"——但它和 CC 一样,只看门槛、不看超过门槛后有多糟。

CVaR(Conditional VaR,条件风险价值,又称 Expected Shortfall):最坏 \((1-\alpha)\) 尾部的**期望损失**, $\(\mathrm{CVaR}_\alpha(L)=\mathbb{E}\big[L\mid L\ge\mathrm{VaR}_\alpha(L)\big].\)$ Rockafellar–Uryasev 给出可优化的等价形式: $\(\mathrm{CVaR}_\alpha(L)=\min_{t}\ \Big\{\,t+\tfrac{1}{1-\alpha}\,\mathbb{E}\big[(L-t)_+\big]\Big\}.\)$ CVaR 看的是"尾部平均有多糟"——它把严重度纳入了。\(\mathrm{CVaR}_\alpha\ge\mathrm{VaR}_\alpha\)(尾部均值 ≥ 门槛)。

记号衔接:这里 CVaR 的 \(\alpha\) 是**置信水平**(如 \(\alpha=1-\delta=0.95\)),正是符号速查表里提醒的、与 CBF 的 class-K 函数 \(\alpha(\cdot)\)、Homothetic 的缩放标量 \(\alpha_k\) **不同**的那个 \(\alpha\)。U5 全程用这个 CVaR 的 \(\alpha\),务必区分。

关键联系:CVaR 是 CC 的凸上界

§U3.2 提过"CVaR/矩不等式给凸上界"——这里讲清。把违反量 \(g(x)\) 当损失,则: $\(\mathrm{CVaR}_{1-\delta}\big(g(x)\big)\le 0\ \Longrightarrow\ \Pr\big(g(x)>0\big)\le\delta.\)$ 为什么\(\mathrm{CVaR}_{1-\delta}(g)\le0\) 意味着最坏 δ 尾部的平均 \(g\le0\);由 \(\mathrm{VaR}_{1-\delta}(g)\le\mathrm{CVaR}_{1-\delta}(g)\le0\),即 \(g\)\((1-\delta)\)-分位数 \(\le0\),也就是 \(\Pr(g\le0)\ge1-\delta\)——CC 成立。

这个上界的两个性质: - \(\mathrm{CVaR}\) 关于决策变量是凸的(若 \(g\) 凸),所以 \(\mathrm{CVaR}_{1-\delta}(g)\le0\) 是**凸约束**——而原 CC 一般非凸(§U3.2/理论补遗)。CVaR 给了 CC 一个**凸的内逼近**,这正是它作为"CC 凸近似"的价值(Nemirovski–Shapiro 2006)。 - 保守\(\mathrm{CVaR}\le0\) 是 CC 的充分非必要条件——它可能拒绝一些 CC 可行的点(因为要求"尾部均值 ≤0"比"违反概率 ≤δ"更强)。这是凸性换来的代价:可解,但偏保守。

数值走查:CVaR 能区分 A 和 B

回到上面的分布 A、B,算 \(\mathrm{CVaR}_{0.95}(g)\)(最坏 5% 尾部均值): - 分布 A\(g=+0.1\)@4%,\(g=-1\)@96%):最坏 5% = 全部 4% 的 \(+0.1\) + 1% 的 \(-1\)\(\mathrm{CVaR}_{0.95}=\frac{0.04\times0.1+0.01\times(-1)}{0.05}=\frac{-0.006}{0.05}=-0.12\le0\)通过 CVaR。 - 分布 B\(g=+100\)@4%,\(g=-1\)@96%):最坏 5% = 全部 4% 的 \(+100\) + 1% 的 \(-1\)\(\mathrm{CVaR}_{0.95}=\frac{0.04\times100+0.01\times(-1)}{0.05}=\frac{3.99}{0.05}=79.8>0\)拒绝 CVaR

结论:CC 对 A、B 一视同仁(都过),CVaR 把灾难尾部的 B 拒掉了。这就是 CVaR 相对 CC 的核心价值——它看的是"违反有多糟",不只是"多大概率违反"

通往 U5

本节只把 CVaR 当"CC 的凸近似 + 风险度量的引子"。U5(风险敏感规划 / CVaR)会把它**作为目标或约束的主角**——直接优化/约束 CVaR,处理尾部风险,并连接**分布式强化学习**(学整个回报分布、而非只学均值)。CC(本章)管违反频率、CVaR(U5)管尾部严重度,是风险谱上相邻的两段。

本质洞察:CC 是频率、CVaR 是严重度——风险的两个正交维度\(\Pr(\text{违反})\le\delta\) 管"多久出一次事",\(\mathrm{CVaR}_\alpha\le0\) 管"出事时平均多糟"。一个安全系统两者都要:低频率(CC)+ 可控严重度(CVaR)。而 CVaR 还有双重身份——它既是比 CC 更强的风险度量,又是 CC 的凸可解近似。理解这点,你就接上了 U3(机会约束)到 U5(风险敏感)的桥:从"限制概率"走向"限制尾部",是安全谱从中段向尾部风险端的自然延伸(呼应 U0 五安全谱)。


CC 规划的研究地图

给想深入文献的读者一张"实验室与脉络"地图(出处见延伸阅读)。

历史脉络(一句话串起):Charnes–Cooper 1959(运筹学概念,确定性等价)→ Nemirovski–Shapiro / Calafiore–El Ghaoui 2006(凸近似 + NP-hard + DR-CC)→ Campi–Garatti 2008(场景法,分布无关)→ Ono–Williams 2008(IRA,风险分配降保守)→ Luders–How 2010(CC-RRT,采样规划概率化)→ Okamoto–Tsiotras 2018(Covariance Steering,主动塑形不确定性)→ Lew–Pavone 2020+(DR-CC/Wasserstein,分布也鲁棒)→ Trivedi 等 2024+(CC 落地四足/机械臂实机)。

关键实验室与贡献: - CMU / Northwestern(Charnes, Cooper):机会约束的原始概念(1959,运筹学)。 - MIT CSAIL MERS(Williams, Ono):IRA、粒子 CC;面向 NASA JPL 火星着陆的风险感知规划。 - MIT ACL(How, Luders):CC-RRT 系列(采样规划 + 机会约束)。 - Georgia Tech(Tsiotras, Okamoto):Covariance Steering,航天 EDL 的不确定性塑形。 - Stanford ASL(Pavone, Lew):DR-CC、CC-SCP,航天 + 自驾的分布鲁棒规划。 - ETH IDSC(Zeilinger):GP + CC-MPC(数据驱动 CC,呼应 U2 §U2.4 与专题六)。 - Northeastern(Everett, Trivedi):CC-MPC 四足实机落地(摩擦锥 CC,Unitree Go1)。

怎么用这张地图:想做理论(凸近似/复杂度)→ 读 Nemirovski–Shapiro、Calafiore;想做采样规划 → MIT ACL 的 CC-RRT;想做不确定性塑形/航天 → Georgia Tech 的 CS;想做分布鲁棒/数据驱动 → Stanford ASL、ETH;想做实机落地 → Northeastern 的四足 CC-MPC。本章正文与延伸阅读已把每条线的奠基论文标出并核实。

一句话:CC 规划从 1959 的运筹学概念,经过 2000 年代的可算化(凸近似、场景法、IRA),到 2010 年代的范式扩展(CC-RRT、CS、DR-CC),再到 2020 年代的实机落地——理论已成熟,工程落地(尤其 C++ 生态、实时集成、实机验证)正当时


🔧 故障排查手册

机会约束规划落地时最常见的故障与定位,配合调参速查用。

症状 根本原因 排查 / 纠正步骤 相关节
蒙特卡洛碰撞率远超 δ ICC 当 JCC 用(没做 Boole 拆解) 1. 确认每步 ICC 设为 \(\delta_{j,k}\) 而非 δ;2. 检查 \(\sum\delta_{j,k}\le\delta\);3. 统计整条轨迹而非单步违反率 §U3.1
碰撞率略超 δ 协方差传播算小、或用了开环传播 1. 用闭环 \(A-BK\) 传播;2. 检查 \(\Sigma_w\) 标定是否偏小;3. 障碍位置不确定 \(\Sigma_o\) 是否漏算 §U3.2/§U3.3
CC-MPC 过度保守、窄通道过不去 均分风险 + Boole 双重保守 1. 改用 IRA 把预算挪给紧约束;2. 适当放大 δ;3. 检查是否误用 Cantelli(系数 4.36 vs 高斯 1.645) §U3.2
QP/SOCP 求解 infeasible 收紧 margin 过大、约束冲突 1. 检查 δ 是否过小(\(\Phi^{-1}\) 爆大);2. 协方差是否发散导致 margin 巨大;3. 必要时软化约束兜底 §U3.2
IRA 迭代不收敛 / 震荡 风险转移无阻尼、或归一化缺失 1. 加阻尼系数(如 damp=0.5);2. 每轮强制 \(\sum\delta=\delta\) 归一化;3. 限制迭代次数 §U3.2 实现二
IRA 几轮后违反率超标 风险预算漂移、\(\sum\delta>\delta\) 每轮迭代后 deltas *= δ/deltas.sum() 重新归一化 §U3.2
CC-RRT 树长不出去 开环协方差发散、margin 巨大 用闭环 \(A-BK\) 传播;检查 \(\mathrm{tr}(P_k)\) 应收敛非爆炸 §U3.3
CC-RRT* rewire 后违反率超标 rewire 改了协方差路径、未重检 CC 每次 rewire 后对受影响节点重新 cc_feasible §U3.3
用高斯收紧但真分布非高斯 \(\Phi^{-1}\) 假设失效 改 Cantelli(只需矩)/ 粒子 MILP / 场景法 §U3.2
CS 的 SDP 跑不到控制频率 SDP 复杂度远高于 QP CS 用于离线/中低频;高频用解析 CC-MPC(QP) §U3.4
仿真 δ 达标、真机仍超 真机扰动分布与假设不符、感知延迟 1. 用真机数据校准分布;2. 计入 \(\Sigma_o\)/延迟;3. HIL 重验 §U3.2 / U4
δ→0 时问题突然无解 高斯尾部要 100% 覆盖不可能 δ 不能取 0;要硬保证请退回 U2 Tube(需有界扰动) CC vs Tube

部署阶段的专属故障

正文表偏算法;下面是 C++ 部署阶段才会撞上的坑:

  • C++ 与 Python 结果对不上:锥求解器(ECOS/SCS)实现差异 + 数值精度。逐模块对拍,别整体比。
  • SOCP/SDP 求解器数值失败:锥规划比 QP 更易病态;C++ 里必须有 fallback(上一拍解、保守 margin、安全停车)。
  • 在线重算协方差拖慢\(P_k\) 与控制无关,务必离线预算好存数组,别在热路径重算。
  • \(\Phi^{-1}\) 在热路径调统计库:它是常数,启动时算好;热路径调 norm.ppf 会拖慢。
  • IRA 外层超时:实时场景限制外层迭代次数(2–3 轮)或离线预分配风险。

部署总原则:CC 在 Python 验证过(违反率 ≤ δ)≠ 在 C++ 真机上达标。分布是否真高斯、感知延迟、锥求解数值、实时性这四类只在部署暴露——两段式工作流的第二段同样要认真测。


API 速查表

本章代码用到的核心函数/接口(按主题)。

概率与收紧(scipy.stats) | 调用 | 作用 | |------|------| | norm.ppf(1-delta) | \(\Phi^{-1}(1-\delta)\) 收紧系数(δ=0.05→1.645,δ=0.01→2.326)| | norm.cdf(x) | 标准正态 CDF,验证违反概率用 | | Cantelli 系数 sqrt((1-delta)/delta) | 仅知矩时的收紧系数(替代 \(\Phi^{-1}\),更保守)|

协方差传播(numpy) | 调用 | 作用 | |------|------| | A_cl @ P @ A_cl.T + Sigma_w | 闭环协方差一步传播 \(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\) | | np.sqrt(a @ P @ a) | 约束方向标准差 \(\sqrt{a^\top P a}\)(收紧量的另一半)| | solve_discrete_are(A,B,Q,R) | 离散 Riccati,求 LQR 反馈 \(K\)(闭环传播用)|

凸优化建模(cvxpy) | 调用 | 作用 | |------|------| | cp.Variable((n,N+1)) | 名义轨迹决策变量 | | cp.quad_form(x, Q) | 二次型 \(x^\top Q x\)(代价)| | a @ z[:2,k] <= b - margin | CC 收紧后的线性约束 | | cp.norm(F @ x + g) <= c @ x + d | 二阶锥(SOC)约束(SOCP 用)| | .solve(solver=cp.OSQP) | QP 后端(解析高斯 CC,\(\Sigma\) 固定时)| | .solve(solver=cp.ECOS/SCS) | SOCP/SDP 后端(margin 含决策、或 CS)|

C++ 部署后端 | 库 | 角色 | |------|------| | CasADi(C++/Python)| 符号框架手写 CC 约束 + NLP/QP 后端,CC-MPC 主力路径 | | OSQP(C)| QP 子问题后端(解析高斯收紧后约束线性)| | ECOS / SCS / Clarabel(C/C++)| 二阶锥求解(SOCP)| | Drake MathematicalProgram(C++)| SOCP/SDP 接口,手拼 CC / CS |

速记:CC 收紧两件套 = norm.ppf(1-δ)(风险因子)× sqrt(a@P@a)(不确定性)。协方差离线传、\(\Phi^{-1}\) 启动算、在线只解 QP——这是 CC-MPC 实时的关键三句。


调参与诊断速查

CC 规划落地,一半工作是调参。把"哪个旋钮管什么、调错什么症状"集中成表。

旋钮 控制什么 调大的效果 调小的效果 调错的典型症状
风险预算 δ(JCC) 安全谱位置 更激进、margin 小、违反概率高 更保守、margin 大、可能过不去 设大→碰撞率超标;设小→窄通道无解
风险分配方式 预算怎么分 IRA:紧约束 margin 更合理 均分:简单但保守 均分→窄通道过度保守;IRA 不归一化→预算超支
过程噪声 \(\Sigma_w\) 协方差增长速率 margin 随时变大、更保守 margin 小、可能不够 标小→真机碰撞;标大→过保守
反馈增益 \(K\) 闭环协方差大小 \(K\) 强→\(P_k\) 小→margin 小 \(K\) 弱→\(P_k\) 大甚至发散 \(K\) 太弱→协方差发散→margin 爆炸
障碍不确定 \(\Sigma_o\) 感知端 margin 计入→更安全、更保守 漏算→违反概率超标 漏算→真机定位误差致碰撞
收紧近似(高斯/Cantelli) 分布假设 Cantelli 更保守稳健 高斯更紧但需高斯 错配→非高斯用高斯致超标
预测时域 N 前瞻长度 更优、更慢;Boole 均分摊薄 更快、可能短视 太短→不可行/震荡
IRA 阻尼 / 迭代次数 收敛稳定性 阻尼大→稳但慢 阻尼小→快但震荡 无阻尼→震荡不收敛
CC-RRT 风险加权 λ 路径冒险程度 更保守、绕远 更短、更贴边界 λ 太大→路径过长;太小→贴边界

调参顺序建议(先粗后细): 1. 先保证**协方差不发散**:调 \(K\)(或检查反馈)让 \(\mathrm{tr}(P_k)\) 收敛——否则 margin 都算不出。 2. 再标定**分布**:用真机/仿真数据估 \(\Sigma_w\)\(\Sigma_o\),确认收紧后问题可行。 3. 再定**风险预算 δ**:从保守(小 δ)起,逐步放大到任务能完成又不超标。 4. 再优化**风险分配**:保守度敏感(窄通道)就上 IRA。 5. 最后调**性能**:代价权重、时域 N。

黄金法则:先把"违反概率 ≤ δ"这条调到蒙特卡洛实测达标(碰撞率贴着但不超 δ),再用性能旋钮(代价、N、IRA)在剩余空间要效率。反过来——先调性能再补安全——几乎总会超标。这与 U2 的"先安全后性能"一脉相承,只是这里的"安全"是概率的。


本章 FAQ:高频疑问速答

读这一章时最常冒出的问题,集中速答。

Q:CC 和 Tube 到底用哪个? 看扰动。有界扰动、要 100% 硬保证 → U2 Tube;无界/高斯扰动、可接受 δ 风险、要少保守 → 本章 CC。两者是同一收紧思想的两种风险姿态。

Q:δ 该取多少? 它是你在安全谱上的位置。安全关键(避障)常取 0.01~0.05;非关键约束可放大。δ→0 趋近硬保证(但高斯下 margin→∞),δ 大趋近期望最优。

Q:ICC 和 JCC 有什么区别? ICC 管单步、JCC 管整条轨迹。你几乎总要 JCC(全程安全),它由 Boole + 风险分配从一族 ICC 拼出。把 N 个 ICC 各设 δ 不等于 JCC=δ(差约 N 倍)。

Q:为什么我的碰撞率比 δ 小很多? Boole 不等式保守(事件重叠时高估违反概率),加上均分浪费预算。这是"把难算变好算"的代价;IRA 能部分挽回,但消不掉 Boole 本身的保守度。

Q:碰撞率超过 δ 怎么办? 最常见:把 ICC 当 JCC 用(没 Boole 拆)、协方差算小/用了开环、漏算 \(\Sigma_o\)。先查这三个。

Q:解析高斯和 Cantelli 何时各用? 分布高斯(或近似)用 \(\Phi^{-1}\)(系数 1.645@δ=0.05);只知均值方差、形状未知用 Cantelli(系数 4.36@δ=0.05,更保守);明显非高斯用粒子/场景法。

Q:IRA 值得上吗? 窄通道/紧约束、保守度敏感时值得(能显著提到达率);宽松场景均分就够。代价是外层迭代(实时要限次数)。

Q:CC-RRT 的协方差为什么会发散? 用了开环 \(A\) 传播。必须用闭环 \(A-BK\)(反馈镇定协方差),同 U2 Tube 用 \(A+BK\) 算 RPI 的道理。

Q:Covariance Steering 和普通 CC-MPC 差在哪? CC-MPC 只规划均值、协方差被动传;CS 主动塑形协方差(窄缝收缩)。代价是 SOCP→SDP,慢一两个数量级,多用于离线。

Q:CC 一定要 C++ 吗? 原型 Python + cvxpy 足够;只有高频/嵌入式上真机才需 C++。但注意 CC 的 C++ 生态空白——SOCP 尚可(ECOS/SCS),SDP(CS)稀缺。

Q:CC 和 Safe RL 是一回事吗? 是同一拉格朗日问题的 primal-dual 两端——IRA 分配风险预算(primal),PPO-Lagrangian 调乘子(dual)。模型已知用 CC,未知用 Safe RL,可混合。

Q:CC 和 CVaR(U5)有什么区别? CC 管"违反的概率"(多大概率出事),CVaR 管"违反时有多糟"(尾部期望)。一个限频率,一个限尾部严重度——不同风险度量,U5 会辨析。

还有疑问?回到对应小节的"本质洞察"与"常见误区",多数疑问那里有更展开的答案。


本章常见误解汇总

误解 正确理解
每步设 \(\Pr(\text{违反})\le\delta\) 就等于整条轨迹 δ ICC≠JCC,差一个 Boole(约 N 倍);JCC 要 \(\sum\delta_{j,k}\le\delta\)(§U3.1)
Boole 拆解是精确的 是上界(union bound),事件重叠时保守;真实违反率常 ≪ δ(§U3.1)
IRA 能消除 Boole 的保守度 IRA 优化"怎么分预算",消不掉 Boole 上界本身的保守度(§U3.2)
高斯收紧系数和 Cantelli 可混用 \(\Phi^{-1}\) 需高斯;Cantelli 只需矩但保守(4.36 vs 1.645@δ=0.05)(§U3.2)
一般 CC 是凸的 一般 CC 可行域非凸、NP-hard;高斯+线性才凸(SOCP)(§U3.2/理论补遗)
CC-RRT 协方差用开环传播 必须用闭环 \(A-BK\),否则发散、树长不出(§U3.3)
CC-RRT* rewire 后不用重检 CC rewire 改了协方差路径,必须重检(§U3.3)
均值和协方差总能分开规划 有 CC 时收紧 margin 含两者、耦合,需联合解(Okamoto–Tsiotras)(§U3.4)
CS 的 SDP 能像 QP 高频实时 SDP 慢一两个数量级,多用离线;高频用解析 CC-MPC(§U3.4)
CC 的概率约束 = CMDP 的期望约束 一个限违反概率、一个限期望累积量,不等价(§U3.5)
δ 可以取 0 拿到硬保证 高斯尾部 100% 覆盖不可能;要硬保证回 U2 Tube(需有界扰动)
CC = 把障碍随便放大一圈 margin = \(\Phi^{-1}(1-\delta)\sqrt{a^\top Pa}\),由风险与协方差精确决定
协方差要在线实时算 解析高斯 CC 的 \(P_k\) 与控制无关,离线预算(实时关键)
仿真违反率达标就能上真机 分布是否真高斯、感知延迟、锥求解数值只在部署暴露(部署故障)
CC 的 C++ 部署和 U2 一样成熟 SOCP 尚可、SDP(CS)稀缺;C++ 生态空白是开放问题(C++ 部署)

本章小结

本章把"约束必须 100% 满足"放松成"以概率 1−δ 满足",并把这个概率约束系统地化成可解的凸问题。主线是 U0 的安全谱思想:CC 是 U2(鲁棒 100%)与风险中性 MPC 之间的精确中间地带,δ 决定你站在谱上哪个位置。

一条主线回顾:一个概念串起全章

如果只带走一个东西,应该是:机会约束把"安全"从布尔判断变成可分配的风险预算

  • 风险预算这个视角统一了全章:ICC/JCC 是预算管单步还是管全程(§U3.1);Boole + 风险分配是把总预算 δ 拆给各约束(§U3.1);IRA 是把预算挪到刀刃上(§U3.2);CC-RRT 是把预算沿采样树分配(§U3.3);CS 是主动塑形不确定性以省预算(§U3.4);与 Safe RL 的关系是预算(primal)与价格(dual)的对偶(§U3.5)。
  • 收紧这个操作贯穿全章:所有方法都在反复用同一个收紧——\(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\),把概率约束变成"均值 + margin"的确定性约束。CC-MPC、CC-RRT、CS 的约束处理都是它。
  • 与 U2 的关系一句话:Tube 用"覆盖最坏有界扰动"的 \(\Omega\) 收紧,CC 用"覆盖 1−δ 概率质量"的 \(\Phi^{-1}\sqrt{a^\top Pa}\) 收紧——一个对最坏情况买单,一个对概率分布买单。Tube 是 CC 在 δ→0、扰动有界下的极限。

所以这一章不是几个孤立技巧,而是**"可分配风险预算 + 解析收紧"这一思想在不同规划范式上的化身**。遇到一个新的 CC 方法,先问:它的风险预算怎么分?收紧量怎么来?绑进 MPC、嵌进 RRT、还是塑形协方差?

术语速查表

术语 一句话定义
机会约束(CC, Chance Constraint) 允许约束以不超过 δ 的概率违反:\(\Pr(g\le0)\ge1-\delta\)
ICC(单步机会约束) 约束每个时步、每个面**独立**满足
JCC(联合机会约束) 约束整条轨迹的所有约束**联合**满足
风险预算 δ 允许的违反概率上界,一种可分配的资源
风险分配 把总预算 δ 拆给各时步/约束(均分或最优)
IRA(迭代风险分配) 两阶段迭代,把风险从松约束挪给紧约束
解析高斯收紧 高斯下 CC 等价的确定性 margin \(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\)
Boole 不等式 union bound,JCC→ICC 拆解的根据(保守上界)
Cantelli 不等式 仅用均值方差的分布无关收紧(系数 \(\sqrt{(1-\delta)/\delta}\)
协方差传播 状态不确定性沿预测时域的闭环前传 \(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\)
CC-RRT 把机会约束嵌入 RRT 的采样规划(协方差传播 + 概率剔除)
Covariance Steering(协方差控制) 主动塑形状态分布协方差的最优控制
场景法(scenario approach) 用 N 个采样约束替代概率约束,分布无关
DR-CC(分布鲁棒 CC) 对一个分布族内的最坏分布保证 CC
CVaR(条件风险价值) 最坏 (1−α) 尾部的期望损失,度量"违反严重度"

知识点总表

方法 核心思想 保证类型 求解 工程定位
ICC/JCC + Boole(§U3.1) 概率约束形式化 + 拆解 单步/整条轨迹 ≤ δ —(形式化) 一切 CC 的地基
解析高斯收紧(§U3.2) \(\Phi^{-1}\) margin ICC 精确 SOCP/QP 高频 CC-MPC 主力
IRA(§U3.2) 风险按紧度最优分配 JCC,低保守 外层 NLP+内层凸 窄通道、保守度敏感
CC-RRT/RRT*(§U3.3) 采样 + 协方差传播 + 概率剔除 路径 ≤ δ,渐近最优 采样 采样型规划器概率化
Covariance Steering(§U3.4) 主动塑形协方差 JCC + 分布塑形 SDP 窄缝、航天,离线/中低频
与 Safe RL(§U3.5) 风险预算 ↔ 乘子对偶 (概念桥) primal/dual 连接已知模型与学习

本章核心公式速查

把全章最该记住的公式集中一处。

  • ICC(单步机会约束)\(\Pr(a_j^\top x_k\le b_j)\ge 1-\delta_j\)
  • JCC(联合机会约束)\(\Pr\big(\bigcap_{k,j} a_j^\top x_k\le b_j\big)\ge 1-\delta\)
  • Boole 拆解\(\Pr(\bigcup A_{j,k})\le\sum\Pr(A_{j,k})\);令 \(\sum\delta_{j,k}\le\delta\) 则 JCC 成立。
  • 解析高斯收紧(核心)\(\Pr(a^\top x\le b)\ge1-\delta\iff a^\top\bar x\le b-\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\)
  • 收紧量\(\Phi^{-1}(1-\delta)\sqrt{a^\top\Sigma a}\) = 风险因子 × 约束方向标准差。
  • Cantelli 收紧(仅知矩):系数用 \(\sqrt{(1-\delta)/\delta}\) 替代 \(\Phi^{-1}(1-\delta)\)
  • 闭环协方差传播\(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\)
  • CC-RRT 检验\(a_j^\top\bar x_k-b_j\le-\Phi^{-1}(1-\delta_{j,k})\sqrt{a_j^\top(P_k+\Sigma_o)a_j}\)
  • CS 协方差动力学\(\Sigma_{k+1}=(A_k+B_kK_k)\Sigma_k(A_k+B_kK_k)^\top+\Sigma_w\)
  • CC vs Tube 极限:有界扰动 + δ→0 时 CC 退化为 Tube(\(\Phi^{-1}\to\) 覆盖整个有界集)。
  • 统一拉格朗日(CC ↔ Safe RL)\(\mathcal{L}(\pi,\lambda)=J(\pi)+\sum_i\lambda_i(C_i(\pi)-d_i)\);IRA 调 \(d_i\)(primal),Lagrangian 调 \(\lambda_i\)(dual)。

这些公式的共同结构是:风险预算 → 解析收紧 / 协方差传播 → 可解的 QP/SOCP/SDP。记住这个结构,比记住每个符号更重要——它就是上一节"可分配风险预算 + 解析收紧"主线的公式化。


本章符号速查

本章符号较多,集中列出(尤其注意 \(\delta\)\(\Phi^{-1}\)\(\Sigma\) 的角色,以及 \(\alpha\) 在跨章语境的区分)。

符号 含义
\(\delta\) 风险预算 / 违反概率上界(JCC 总预算)
\(\delta_{j,k}\) 分配给第 \(k\) 步第 \(j\) 个约束的风险(\(\sum\delta_{j,k}\le\delta\)
\(\Phi^{-1}(1-\delta)\) 标准正态分位数(收紧的风险因子;δ=0.05→1.645,0.01→2.326)
\(a_j,\ b_j\) 障碍/约束半空间 \(a_j^\top x\le b_j\)(安全侧)
\(\bar x_k,\ x_k\) 名义(均值)状态、真实状态
\(\Sigma,\ P_k\) 协方差(分布的、传播的状态协方差)
\(\Sigma_w\) 过程噪声协方差
\(\Sigma_o\) 障碍位置不确定性协方差
\(K\) 反馈增益(闭环协方差传播 \(A-BK\)
\(A-BK\) 闭环矩阵(CC-RRT/CS 协方差传播,防发散)
\(\bar u_k,\ K_k\) CS 中操控均值的名义控制、操控协方差的反馈增益
ICC / JCC 单步 / 联合机会约束
\(\lambda_i\) Safe RL 拉格朗日乘子(与 \(\delta_i\) 对偶)
\(\sqrt{a^\top\Sigma a}\) 约束方向上的标准差(收紧量的不确定性部分)

跨章符号坑——\(\alpha\) 的三重身份:本章 \(\alpha\) 不常用;但放在整个不确定性规划簇里,\(\alpha\) 在 U2 CBF 是 class-K 函数、在 U2 Homothetic Tube 是缩放**标量** \(\alpha_k\)、在 U5 CVaR 是置信水平。三者无关,务必看语境区分。本章核心符号是 \(\delta\)(风险预算)与 \(\Phi^{-1}\)(收紧因子),别和 CVaR 的 \(\alpha\) 混——CC 用 δ 限"违反概率",CVaR 用 α 定"尾部置信水平",是不同风险度量(U5 辨析)。


实践索引与一页纸总览

把全章压成两张可快速查阅的表,做项目时直接定位。

实践索引:遇到什么用什么、去哪查

你的情况 用哪个方法 本章位置
高斯扰动、要在 MPC 里用 CC 解析高斯 CC-MPC §U3.2、实现一
整条轨迹保证、保守度敏感 Boole + IRA §U3.1/§U3.2、实现二
只知均值方差、分布未知 Cantelli 收紧 §U3.2
明显非高斯/多模态 粒子 MILP / 场景法 §U3.2、理论补遗
分布本身不确定、数据少 DR-CC(Wasserstein/矩) §U3.2、前沿
采样型规划器要概率安全 CC-RRT / CC-RRT* §U3.3、实现续
窄缝要主动塑形不确定性 Covariance Steering §U3.4
把 CC 接进强化学习 CC ↔ CMDP 对偶 §U3.5
四足摩擦锥安全 摩擦锥 CC(SOCP) 案例一
把 CC 落到真机频率 C++(CasADi/OSQP) C++ 部署

方法在五安全谱上的定位(呼应 U0)

方法 安全谱位置 保证类型
Tube / 可达性 / CBF(U2) 最保守端(鲁棒 100%) 对扰动集硬保证
DR-CC 鲁棒 ↔ 机会约束之间 分布族最坏情况
机会约束(本章) 中段 \(\Pr(\text{违反})\le\delta\)
风险中性 MPC 期望最优端 只优化期望
CVaR / 风险敏感(→ U5) 尾部风险端 尾部期望(违反有多糟)

一句话总览:本章占据安全谱中段(鲁棒 100% 与期望最优之间),核心是"可分配风险预算 + 解析收紧";δ 是你在谱上的位置旋钮。带着这张地图,你既能为问题选对 CC 方法,也能顺利过渡到 U4(感知端 belief,给 CC 提供 \(\Sigma_o\))、U5(尾部风险 CVaR,从"违反概率"走向"违反严重度")。


延伸阅读

出处均已逐一核实;难度:⭐⭐ 入门精读,⭐⭐⭐ 需相应基础,⭐⭐⭐⭐ 研究级。

起源与综述 - A. Charnes, W. W. Cooper. "Chance-Constrained Programming." Management Science 6(1):73–79, 1959.(CC 开山)⭐⭐⭐ - A. Charnes, W. W. Cooper. "Deterministic Equivalents for Optimizing and Satisficing under Chance Constraints." Operations Research 11(1):18–39, 1963.(确定性等价)⭐⭐⭐ - A. Mesbah. "Stochastic Model Predictive Control: An Overview and Perspectives for Future Research." IEEE Control Systems Magazine 36(6):30–44, 2016.(随机 MPC 综述)⭐⭐⭐

凸近似与复杂度 - A. Nemirovski, A. Shapiro. "Convex Approximations of Chance Constrained Programs." SIAM J. Optim. 17(4):969–996, 2006.(凸近似 + NP-hard)⭐⭐⭐⭐ - G. C. Calafiore, L. El Ghaoui. "On Distributionally Robust Chance-Constrained Linear Programs." JOTA 130(1):1–22, 2006.(DR-CC、SOCP)⭐⭐⭐⭐

场景法 - M. C. Campi, S. Garatti. "The Exact Feasibility of Randomized Solutions of Uncertain Convex Programs." SIAM J. Optim. 19(3):1211–1230, 2008.(场景法样本复杂度)⭐⭐⭐⭐ - M. C. Campi, S. Garatti. "A Sampling-and-Discarding Approach to Chance-Constrained Optimization." JOTA 148(2):257–280, 2011.⭐⭐⭐⭐

IRA 与粒子法 - M. Ono, B. C. Williams. "Iterative Risk Allocation: A New Approach to Robust Model Predictive Control with a Joint Chance Constraint." 47th IEEE CDC 2008, pp. 3427–3432.(IRA 奠基)⭐⭐⭐ - L. Blackmore, M. Ono, B. C. Williams. "Chance-Constrained Optimal Path Planning With Obstacles." IEEE T-RO 27(6):1080–1094, 2011.(解析高斯 CC 避障)⭐⭐⭐ - L. Blackmore, M. Ono, A. Bektassov, B. C. Williams. "A Probabilistic Particle-Control Approximation of Chance-Constrained Stochastic Predictive Control." IEEE T-RO 26(3):502–517, 2010.(粒子法)⭐⭐⭐⭐

CC-RRT - B. Luders, M. Kothari, J. P. How. "Chance Constrained RRT for Probabilistic Robustness to Environmental Uncertainty." AIAA GNC 2010, Toronto.(CC-RRT 奠基)⭐⭐⭐ - B. Luders, S. Karaman, J. P. How. "Robust Sampling-based Motion Planning with Asymptotic Optimality Guarantees." AIAA GNC 2013.(CC-RRT*)⭐⭐⭐⭐

Covariance Steering - K. Okamoto, M. Goldshtein, P. Tsiotras. "Optimal Covariance Control for Stochastic Systems Under Chance Constraints." IEEE L-CSS 2(2):266–271, 2018.(CC + CS,不可解耦)⭐⭐⭐⭐ - J. Pilipovsky, P. Tsiotras. "Covariance Steering with Optimal Risk Allocation." IEEE T-AES, 2021(arXiv:2009.09554).(CS + IRA)⭐⭐⭐⭐

实机落地(前沿) - A. Trivedi, S. Prajapati, M. Zolotas, M. Everett, T. Padır. "Chance-Constrained Convex MPC for Robust Quadruped Locomotion Under Parametric and Additive Uncertainties." IEEE RA-L, 2025(arXiv:2411.03481).(四足摩擦锥 CC,Unitree Go1)⭐⭐⭐⭐

Safe RL(交界) - J. Achiam, D. Held, A. Tamar, P. Abbeel. "Constrained Policy Optimization." ICML 2017.(CPO,CMDP)⭐⭐⭐⭐

教材 - J. B. Rawlings, D. Q. Mayne, M. M. Diehl. Model Predictive Control: Theory, Computation, and Design.(随机/CC-MPC 章)⭐⭐⭐


综合练习与项目挑战

各节练习偏单点;这里给几个**贯穿全章**的综合任务,适合阶段性项目或面试准备。

  1. CC vs Tube 对决(控制变量):在累积项目测试台上,对同一 2D 导航 + 扰动,分别实现 (i) U2 Rigid Tube MPC(有界扰动假设)、(ii) 本章解析 CC-MPC(高斯)。画两者的可行区域与最优轨迹,扫扰动水平,找出"CC 比 Tube 优势最大"的扰动区间。目标:亲手验证"Tube 对最坏情况买单、CC 对概率分布买单"。
  2. 均分 vs IRA(保守度量化):在窄走廊任务上,对比 Boole 均分与 IRA 的到达率/路径长度/求解时间。定量说明 IRA 降了多少保守度,并画"IRA 迭代轮数 ↔ 代价"收敛曲线。
  3. 风险旋钮曲线(接 U0 安全谱):扫 δ∈{0.2,0.1,0.05,0.01,0.005},画"δ ↔ 实测碰撞率 ↔ 到达率"三条曲线。验证碰撞率被压在 δ 以下、且 δ 越小越保守。标出"碰撞率贴着 δ"的理想工作点。
  4. CC-RRT 概率安全验证(接 §U3.3):用实现续的 CC-RRT 在 2D 窄通道规划,对找到的路径做蒙特卡洛,验证整条路径违反率 ≤ δ;对比开环 vs 闭环协方差传播下树的生长。
  5. 方法选型论证题:给定三场景——(a) 高斯风扰的无人机避障、高频;(b) 负载不确定的四足摩擦锥、要实机;(c) 他车意图不确定的自动驾驶、采样规划——分别用选型决策指南的四个问题论证你的方法组合。
  6. CC ↔ Safe RL 对偶(接 §U3.5):写出统一拉格朗日,用一个约束 LQR 例子分别用 primal(固定预算解凸)和 dual(自适应乘子)求解,验证收敛到同一最优,观察 δ 与 λ 的对偶关系。
  7. 开源挑战(接前沿):设计一个"CC-RRT for OMPL"的接口草图——需要实现哪些 OMPL planner 接口?协方差传播放在哪一层?最大的工程挑战(如 C++ 里的协方差类型、SOCP 求解)是什么?

这些题的共同点是**把多个方法放进同一测试台对比、或把 CC 接进更大的系统**,而非孤立实现单个算法——这是把本章知识转化为工程能力的关键一步。


本章各节关系

小节 与本章其他节/其他章的关系
§U3.1 ICC/JCC/Boole 全章地基;Boole 拆解被 §U3.2 IRA、§U3.3 CC-RRT 共用
§U3.2 近似谱 + IRA 核心;解析高斯收紧续 U2 §U2.4,被 §U3.3/§U3.4 反复用
§U3.3 CC-RRT §U3.2 收紧用在采样规划;协方差传播同 U2 闭环镇定思想
§U3.4 Covariance Steering 从"被动传协方差"到"主动塑形";接 U2 §U2.2 Homothetic 的延伸
§U3.5 与 Safe RL 把 CC 接进 RL;连 U2 §U2.5(给 RL 兜底)、U5(CVaR 与分布式 RL)
全章 上承 U2(硬保证→概率松弛,CC 是 Tube 的 δ→0 推广),下接 U4(感知端 belief 提供 \(\Sigma_o\))、U5(违反概率→尾部严重度 CVaR);向方向层输出四足(摩擦锥 CC)、无人机(CC 避障 + CS)、自驾(CC-RRT)的概率安全基础

本章与后续章节的关系

上一节的"本章各节关系"梳理章内脉络;这里专门列出本章如何为后续章节铺垫。

后续章节 关系 本章铺垫的知识点
U4 POMDP 与信念空间规划 本章"给定的"障碍位置协方差 \(\Sigma_o\),在 U4 成为随观测演化的 belief;CC 提供"不确定性 → 约束收紧"的桥 解析高斯收紧、\(\Sigma_o\) 计入(累积项目进阶)、闭环协方差传播
U5 风险敏感规划 / CVaR 从本章"违反**概率** ≤δ"过渡到"尾部**严重度**受控";CVaR 既是 CC 的凸上界、又是 U5 主角 进阶专题十(CC→CVaR 桥)、风险度量辨析、δ 作为风险旋钮
附录(基准与对照) 把 CC 与 U2 Tube、U4/U5 各范式放同一测试台横向 benchmark 累积项目测试台、CC-vs-Tube 数值走查、消融方法

一句话:本章向上承接 U2(硬保证 → 概率松弛),向下分两支——U4 把"分布"从给定变成感知出来的 belief、U5 把"违反概率"换成"尾部严重度"。三章共同覆盖不确定性规划从执行端到感知端再到评估端的完整图景。


研究与实践建议

给工程师:先在累积项目里把"风险中性 → 解析高斯 CC 收紧 → IRA"这条路走一遍——你会看到碰撞率怎么被精确压到 δ 以下、保守度怎么随 δ 和分配方式变化。工程落地优先级是 §U3.2(解析高斯 CC-MPC,高频主力)+ IRA(窄通道降保守度);CC-RRT(§U3.3)在用采样规划器时上;CS(§U3.4)留给窄缝/离线。务必记住实时三句:协方差离线传、\(\Phi^{-1}\) 启动算、在线只解 QP。

给研究者:本章是 Part-U 里"理论成熟、工程/落地空白大"的一章。解析高斯 CC、IRA、CC-RRT 理论都已稳固,但四条线有明确可发表/可开源的空间:(1) 高性能 C++ 实现(尤其嵌入式 SDP、CC-RRT for OMPL、CC-MPC for acados/CasADi——C++ 生态几乎空白);(2) 与现代实时求解器集成(把 CC 收紧塞进 acados SQP-RTI 跑高频);(3) 非高斯/多模态扩展(GMM-CC、重尾分布下的可解收紧);(4) 与 Safe RL 深度融合(用 §U3.5 的对偶把 IRA 与 Lagrangian 互借)。其中 C++ 开源贡献门槛相对低、影响力大,最适合学生起步。

给初学者的学习路径:建议"先拿直觉、再补严格、最后上手"。第一步只读 §U3.1(ICC/JCC 的赛车直觉)+ §U3.2 的"本质洞察"(CC 收紧 = 分位数变 margin),把"可分配风险预算 + 解析收紧"主线建起来——它直接续 U2 §U2.4 你已熟悉的 \(\Phi^{-1}\) 收紧。第二步把 §U3.2 解析高斯推导和实现一的数值例(σ=0.2、δ=0.05→margin 0.329)逐行算一遍,这是全章最该吃透的一步。第三步动手:先写解析 CC-MPC(实现一)跑累积项目 Bronze/Silver、再加 IRA(实现二)做对比,最后挑一道综合练习。§U3.3(CC-RRT)、§U3.4(CS)、§U3.5(Safe RL)作为三条进阶分支,按需要再深入。

学完本章你应当能:区分 ICC/JCC 并用 Boole + 风险分配处理 JCC;推导并实现解析高斯 CC-MPC 与 IRA;在测试台上做出"碰撞率随 δ 受控、IRA 降保守度"的控制变量实验;说清 CC 与 Tube、CC 与 Safe RL 的关系;并对一个新的 CC 问题给出有理有据的方法选型。带着这些能力,你可以进入 U4(感知端不确定性 / belief 空间)与 U5(尾部风险 / CVaR)了。


版本信息速查

本章代码以 Python 原型为主。下表汇总所基于的主流库版本(版本号为**建议最低值**,向后兼容多数更高版本;实际以你的环境为准)与各核心方法的出处年份,便于复现与查阅。方法年份与出处已在"延伸阅读"逐一核实。

库版本(指示性最低值)

建议版本 本章用途
Python 3.10+ 原型语言
NumPy 1.24+ 矩阵与协方差运算
SciPy 1.10+ norm.ppf\(\Phi^{-1}\))、solve_discrete_are(LQR)
CVXPY 1.4+ CC 的 SOCP/SDP 建模(Python 实现的建模层)
OSQP 0.6+ QP 后端(解析高斯 CC,\(\Sigma\) 固定时)
ECOS 2.0+ SOCP 求解
SCS 3.2+ SOCP/SDP 求解(Covariance Steering)
Clarabel 0.6+ SOCP/SDP,CVXPY 默认后端之一
scikit-learn 1.3+ 高斯过程(数据驱动 CC,进阶六)
CasADi 3.6+ C++ 部署:符号化手写 CC 约束
Drake 1.20+ MathematicalProgram 的 SOCP/SDP 接口

核心方法出处年份(已核实)

方法 年份 出处
Charnes–Cooper(CC 开山) 1959 Management Science 6(1)
场景法 Campi–Garatti 2008 SIAM J. Optim. 19(3)
IRA Ono–Williams 2008 47th IEEE CDC
CC 避障 Blackmore–Ono–Williams 2011 IEEE T-RO 27(6)
CC-RRT Luders–Kothari–How 2010 AIAA GNC
Covariance Steering Okamoto–Goldshtein–Tsiotras 2018 IEEE L-CSS 2(2)
四足 CC-MPC Trivedi et al. 2025 IEEE RA-L(arXiv:2411.03481)

:CC 的算法对库版本不敏感(核心只用到 \(\Phi^{-1}\)、协方差传播、凸求解);真正影响结果的是**求解器选择**(见"工具与源码精读拓展"的求解器选型)与**分布假设是否成立**,而非具体版本号。


附录:前置自测参考答案

回到开头那 5 道自测题,读完全章再核对一遍。

  1. 高斯 CC 等价\(X\sim\mathcal{N}(\mu,\sigma^2)\)\(\Pr(X\le b)\ge1-\delta\iff\mu\le b-\Phi^{-1}(1-\delta)\sigma\)。即均值要离上界至少 \(\Phi^{-1}(1-\delta)\sigma\)——这就是本章反复用的解析高斯收紧(§U3.2),也是 U2 §U2.4 的那个收紧。
  2. 线性变换保持高斯\(x\sim\mathcal{N}(\bar x,\Sigma)\),则 \(a^\top x\sim\mathcal{N}(a^\top\bar x,\ a^\top\Sigma a)\)——均值 \(a^\top\bar x\)、方差 \(a^\top\Sigma a\)。正是这个性质让线性约束 \(a^\top x\le b\) 的 CC 有解析形式(§U3.2 推导第 1 步)。
  3. SOCP:二阶锥规划,约束 \(\|Fx+g\|_2\le c^\top x+d\) 是一个二阶锥(冰淇淋锥)的截面,凸(二范数是凸函数、约束是凸集)。解析高斯 CC 的 \(a^\top\bar x+\Phi^{-1}(1-\delta)\|\Sigma^{1/2}a\|_2\le b\) 正是 SOC 约束(§U3.2)。
  4. Boole 不等式\(\Pr(\bigcup A_i)\le\sum\Pr(A_i)\),给的是**上界**;仅在各 \(A_i\) 互斥时取等。它是 JCC→ICC 拆解的根据,也是 Boole 拆解保守的来源(事件重叠时高估,§U3.1)。
  5. 协方差传播\(x_{k+1}=(A-BK)x_k+w_k\)\(w_k\sim\mathcal{N}(0,\Sigma_w)\),则 \(P_{k+1}=(A-BK)P_k(A-BK)^\top+\Sigma_w\)。用**闭环** \(A-BK\) 防发散——这是 CC-MPC 离线预算协方差、CC-RRT 沿边传播的核心(§U3.2/§U3.3),与 U2 Tube 用 \(A+BK\) 算 RPI 同源。

如果这 5 题现在都能流畅作答,你已握住本章全部支柱:高斯 CC 收紧、线性变换保高斯、SOCP、Boole 不等式、协方差传播——其余方法都是把它们按不同方式组装起来处理"可分配的风险预算"。


结语:从机会约束走向感知与风险

本章把不确定性规划的"动力学/执行端"问题再推进一步:U2 用硬保证应对有界扰动,本章用机会约束在"硬保证"与"期望最优"之间找到可调的中间地带——核心是把安全变成**可分配的风险预算**,用一个解析收紧反复落地。

接下来两章转向不确定性的另外两端。U4(POMDP / 信念空间规划) 处理"我看不清世界"——本章里那个"给定的"障碍位置协方差 \(\Sigma_o\),在 U4 会变成随观测演化的**信念**,而本章的"不确定性 → 约束收紧"正是连接信念与规划的桥。U5(风险敏感 / CVaR) 处理"我如何衡量风险"——从本章的"违反**概率** ≤ δ"走向"违反**严重度**(尾部期望)受控",而 §进阶专题十已经把 CVaR 作为桥铺好。带着"可分配风险预算 + 解析收紧"这条主线,你已经准备好进入感知端(U4)与评估端(U5)的不确定性了。