作为研究航天器近距离任务的开发者,我们组在复现不完全信息Epsilon纳什均衡的航天器末端追逃博弈策略(Matlab代码实现)这篇论文时,最大的感受是:以前觉得博弈论在航天里就是理论推推公式,真正要把“对方参数不知道”这个约束塞进仿真里,难度完全不是一个量级。这个工作既有清晰的博弈建模,也给出了可在Matlab里跑通的数值求解框架,对于做制导控制、空天安全、多智能体决策方向的人,都值得花时间吃透。这篇博文我会按自己的复现主线,把场景设定、模型设计、代码结构、调参踩坑和验证方法整个串一遍,尽量让你看完能直接动手跑。
1. 追逃博弈到底在解决什么问题
1.1 末端追逃的核心场景约束
航天器追逃博弈,远不是“一个追一个跑”这么简单。它通常分成两个阶段:中段交会和末端追逃。中段靠轨道预报和地面测控就能算得差不多,问题不大;真正有意思的是末端阶段——双方相对距离只有几百到几公里,时间窗口可能只有几十秒到几分钟,这时候地面干预的时延太长,航天器必须自己根据相对测量信息实时决策。
末端阶段有几个硬约束必须建模进去。首先是控制量有界,推力器不是无限制的,加速度上限直接决定了能不能追上或者能不能跑掉;其次是终端指标明确,追击方要尽可能把相对距离压到某个阈值以内,逃逸方则要保证相对距离大于某个安全值;第三是测量噪声和参数不确定性叠加,这些不确定性会直接影响最优策略的形态。一个能用的博弈策略,必须同时满足这些约束,而不是在理想公式里自洽。
1.2 为什么一定要引入“不完全信息”
经典追逃博弈基本都是完全信息假设:双方的动力学方程、推力上限、控制成本系数、终端权重全都互相知道。这个假设在理论上很舒服,但工程上基本不成立。比如逃逸航天器的最大加速度是0.2还是0.4,追击方只能通过对轨迹的观测间接估计,不可能从对方卫星说明书里读到。测量本身带噪声,估计结果一定是个分布而不是一个确定值。
这就引出不完全信息建模的必要性。不完全信息的本质是博弈方的“类型”未知,对手只知道类型服从某个概率分布。具体到这个场景,我们把逃逸方的机动能力作为类型参数,追击方不知道该参数确切值,但有先验信念。这个建模方式比强行假设一个“平均推力”要严谨得多。如果你把对方参数错误地定死,仿真里跑出来可能全线崩溃——追击策略按高机动目标设计会过于保守,按低机动目标设计又会在关键时刻失手。
1.3 Epsilon纳什均衡是怎么降低求解门槛的
在不完全信息下求精确纳什均衡,其实非常困难。行动空间连续、状态维度高、动力学非线性、终端时刻还固定,要把每一条可能偏离路径都验证一遍,数值上几乎不可行。而且很多情况下精确纳什均衡根本不存在,或者即使存在,也难以用数值方法稳定逼近。
Epsilon纳什均衡做了关键让步:不再要求“任何单边偏离都不能提高收益”,而是允许单边偏离最多带来ε的收益提升。这个ε是自己设定一个精度阈值,工程上完全可接受——控制系统本来就有误差和扰动,策略收益差个百分之几根本体现不出来。这个让步使得我们可以用迭代数值方法去逼近均衡,而不是去解一个可能无解的偏微分方程组。论文的核心价值也就在这里:给出一个在Matlab里能够收敛到近均衡策略的完整路线。
2. 不完全信息博弈模型怎么建、参数怎么给
2.1 相对运动动力学与状态离散化
末端追逃最常用的坐标系是LVLH,也就是以目标航天器轨道为基准的当地垂直水平坐标系。在这个坐标系里,双方相对位置和相对速度构成6维状态。为了快速求解,我们采用圆轨道下的CW方程做线性化。它的形式简洁,在几十秒到几分钟的末端窗口里精度足够,而且可以直接写出离散状态转移矩阵。
以轨道角速度n为例,低轨大概在0.001 rad/s量级。状态x = [rx, ry, rz, vx, vy, vz] = [相对位置3分量, 相对速度3分量]。连续时间动力学写作x_dot = A x + B u,其中A和B都是常值矩阵。仿真时用时间步长dt离散化:F = expm(A*dt),G = (F-I)A_invB。这种离散方式比简单的欧拉积分稳定得多,大状态矩阵下不会出现数值发散。
这个动力学建模是整个项目的地基。很多复现失败并不是算法问题,而是离散化方式本身不够稳健。CW方程线性化的适用范围是“相对距离远小于轨道半径”,末端追逃完全满足;但如果把仿真时长拉得太长,线性化误差就会累积,所以时间窗口需要控制好。
2.2 类型空间设计与先验信念
不完全信息的关键是把“未知参数”变成“类型”。我们这里的做法是,把逃逸方的最大加速度水平量化成有限个类型,比如类型1对应最大加速度0.2 m/s²,类型2对应0.3,类型3对应0.4。追击方不知道真实类型,但拥有一个先验概率分布,代表它对各类别的信任程度。
类型空间设计有几个要点。一是类型数量不宜多,3到5类足够,因为每一类都对应一组额外的策略计算,类型太多会让数值迭代的规模爆炸。二是类型之间要能拉开差距,若两个类型对应的动态特性几乎一样,均衡解会退化,失去“不完全信息”的意义。三是先验概率不能取0或1,否则会退化成完全信息博弈,也失去了探索意义。
从技术实现角度,每个类型对应一组动力学参数和控制约束。追击方在计算自己的期望收益时,要对所有类型按先验概率加权;逃逸方则知道自己真实类型,按类型对应的最优响应来行动。海萨尼转换的思想在这里非常清晰:把一个“信息不对称的博弈”转化为“带类型依赖的完全信息博弈”,然后我们在转换后的博弈里求均衡。
2.3 收益函数与控制约束的量化
收益函数决定了博弈的“胜负”标准。我们的设定是非严格零和的:追击方的收益J_P由终端相对距离的加权值与累计控制能量组成,逃逸方的收益J_E是终端距离的正向加权再减去自身控制能量。双方都倾向于节省燃料,但追击方想最小化终端距离,而逃逸方想最大化它。
控制约束方面,每个类型都有加速度上限,即||u||_∞ ≤ a_max。在Matlab仿真里,这个约束可以直接通过一个saturation函数施加在控制输出上,但要注意:如果优化算法内部没有建模这个约束,仅靠外部截断,会破坏最优性条件。所以我们在求解策略迭代时,必须把控制量约束明确写入优化步骤,而不是事后截断。
这里有个经验:权值矩阵的选择需要结合物理场景。终端距离权要取得足够大,让“追得上/逃得掉”成为主导指标;控制能量权则决定策略是否保守。一开始可以给一个粗略比例,通过仿真观察策略形态再调整。后面我会具体说怎么调。
3. Matlab代码实现的核心环节
3.1 代码架构与模块职责
整个复现代码我按“参数初始化、模型离散化、策略求解、仿真主循环、结果可视化”五个模块组织。参数初始化模块集中定义轨道角速度、时间步长、仿真时长、类型概率、控制权值等;模型离散化模块负责把CW方程转成离散状态转移矩阵;策略求解模块是最复杂的一块,它完成从初始策略到Epsilon纳什均衡策略的迭代过程;仿真主循环则把策略放进时间推进里,输出状态轨迹和控制曲线;可视化模块负责绘制相对轨迹和收益变化曲线。
这个分层的设计非常重要。我见过不少复现代码把所有内容塞进一个脚本里,变量互相覆盖,迭代策略一跑就出错。模块化的另一个好处是,调试时只需要定位到具体模块,比如策略不收敛就单独调求解模块,不用反复跑整个仿真。
主循环的伪代码结构大致如下:
初始化状态x0,先验概率p,策略π_P, π_E for k = 1 : N 步 计算双方当前控制 u = π(x, k, p) 施加控制量约束 状态推进 x_{k+1} = F*x_k + G*u 记录轨迹与控制 end 计算终端距离与收益3.2 核心求解函数:类型支路迭代与策略合成
策略求解是整个复现的引擎。思路是先固定一组初始策略,然后分别计算双方在给定对手策略下的最优响应,再更新策略,反复迭代直到策略变化量小于阈值。由于存在多个逃逸类型,每个类型都要单独计算逃逸方在该类型下的最优响应,追击方则基于先验概率对所有这些响应做加权,形成自己的期望最优响应。
也就是说,追击方的策略不直接针对某一个类型,而是对所有类型按概率加权的期望策略。这个加权策略就是不完全信息博弈的关键:它不是“赌”某个类型发生,而是对整体不确定性的最优应对。逃逸方呢,它知道自己的类型,所以直接用对应类型的最优响应。
在代码实现层面,每个响应优化我采用梯度投影法加线性搜索。梯度方向由一个近似的目标函数梯度给出,然后投影到控制可行集上,再沿方向用回溯法确定步长。这个方案对凹目标函数效果不错,而且实现起来比复杂的高级求解器更可控。初始的迭代步长不宜取太大,我一般从0.05开始,随着迭代次数递减。
初始化策略 π_P, π_E 为平衡策略(全速度方向或零控制) for iter = 1 : maxIter 计算类型t对应的逃逸最优响应 π_E^t 计算追击方期望最优响应 π_P = Σ_t p(t) * BR_P(π_E^t) 计算所有逃逸类型的期望收益与单边偏离增益 若最大偏离增益 ≤ ε,跳出循环 否则更新策略并进入下一轮迭代 end迭代收敛后,我们得到的不只是两条策略曲线,而是一组“互不单方偏离过度”的策略组合。如果算法在设计时注意到收益梯度的平滑性,整个迭代过程通常能在几十轮内稳定下来。
3.3 仿真主循环与结果可视化
在策略迭代完成后,我们把它嵌入仿真主循环,观察真实的相对轨迹。仿真时要做的第一件事就是把初始相对状态设得有意思一些:比如相对位置从[2000, 300, 0]米开始,相对速度合适地指向对方,模拟追击方从后方接近的场景。
主循环里每个时间步都要做控制约束截断和状态更新。这里有个容易忽略的点,控制截断不是简单clip一下就行,要在策略求解阶段就体现约束,否则仿真结果和理论策略之间会不一致。我们最终绘制的典型曲线包括:相对距离随时间的变化、双方加速度的剖面、以及追击方对不同类型的信念变化。相对距离曲线能直观告诉你博弈是否到达了“拦截区”或“逃逸区”。
可视化模块我特别建议增加一张“收敛过程图”,直接画出迭代过程中单边偏离增益的衰减曲线。这张图是复现论文成果的硬证据,也是审稿人和读者判断你的解是否真正逼近均衡的核心依据。通过这条曲线,你能清晰看到ε阈值在哪里被突破,以及策略是否真的趋于稳定。
4. 仿真里最折磨人的问题与排查心得
4.1 迭代不收敛与ε取值的关系
我们第一次跑完整流程时,迭代曲线后半段一直小幅震荡,单边偏离增益下降到0.1后就再也下不去。查了很久才意识到,问题出在ε的设定节奏上。一上来就把阈值设成0.01,会让算法在远离均衡的时候追求过于苛刻的精度,这时收益梯度的估计误差反而会引发策略抖动,像是在陡坡上刹车还要求轨迹绝对平滑。
解决办法是分层收敛:先以较大阈值(比如ε=0.5)跑粗迭代,把策略大致稳定下来,再逐步收紧到目标精度;每步切换阈值时,以上一步的策略为初值重新迭代。这个技巧看似简单,但能让迭代速度提升一个量级,也避免了震荡。另一个细节是类型概率不能过于极端,某个类型概率接近0会让它对期望收益失去影响,但对应策略支路仍然参与迭代,浪费算力还干扰收敛。
4.2 终端条件设计的几个坑
终端时间固定还是可变,会深刻影响策略形态。我们一开始用的是固定仿真时长,这样求解方便,但也导致末端容易出现“冲刺式”机动——双方都把剩余燃料全部压到最后几步,控制剖面看起来像bang-bang控制,尾段非常抖。这个现象物理上合理,但在数值仿真里有隐患:固定时间步长下最后几步的收益梯度会被放大,导致策略对时间步长极其敏感。
减小采样时间能缓解,但不是所有场景都允许你把步长压到很小。另一个更实际的办法是把仿真时长分成“常规划段”和“末端段”,末端段用小步长精细推进,常规段用大步长节省算力。这种变步长方案和固定步长完全兼容,只要保证状态转移矩阵按对应步长重新计算即可,别复用同一组F和G。
4.3 怎么确认解真的是Epsilon纳什均衡
验证均衡是最容易被带偏的一步。很多人跑完迭代,看到策略曲线稳定就觉得完成了,其实不够。真正要做的是单边偏离测试:固定对手策略不变,让一方在可行控制空间内尝试偏离策略,计算收益变化。这个偏离不是随便试几个方向,而是要在可行域内做充分的采样或再做一次优化搜索,确认没有偏离能带来超过ε的收益提升。
我们的做法是,对每方做多组不同初值的偏离优化,再结合蒙特卡洛随机采样,取最大收益改进作为验证指标。如果这个最大改进值小于设定ε,基本可以确认我们得到的是ε-纳什均衡。这个验证过程还要区分开训练用的样本和不参与训练的样本,避免过拟合到特定初始状态或噪声序列上。
4.4 从结果曲线里读出的几个经验
相对距离曲线如果出现终端小范围反复穿越阈值的情况,不要急着判定策略失效,先看是不是因为数值振荡。真实现象的频率不会那么高,模型里能产生几千赫兹控制切换的,大概率是步长不够导致的高频伪振荡。适当增加终端段的步长精度就能消除。
另外,追击方的期望策略在不同类型下的形态差异,可以作为观察不完全信息价值的窗口。如果最终策略在三种类型下的控制差异很小,说明这个博弈类型设计没有真正影响解,概率权重可能设置过于集中。相反,若差异明显,说明不完全信息在策略层面得到了体现,这才是论文方法真正的意义所在。
我个人在复现过程里体验最深的一点是,Epsilon纳什均衡给工程实践留出了“可计算”的空间。精确均衡是理论理想,ε设置得越小,你付出的计算代价越高;工程中需要的不是一个数学上完美但算不出来的解,而是一个有界误差、可复现、可验证的实用策略。这个项目让我对博弈论在航天制导里的应用多了很多实感,也希望这篇复现笔记能帮你少走一段弯路。如果后续要做扩展,从固定终端时间改成可变终端时间、把类型概率更新成实时贝叶斯估计、或者把平面问题推广到多航天器协同场景,代码的主干都可以继续沿这套框架加支路。