航天器末端追逃博弈:基于EKF的不完全信息Epsilon纳什均衡策略 看到《不完全信息Epsilon纳什均衡航天器末端追逃博弈策略基于EKF的参数估计与自适应博弈》这个标题我的第一反应是这又是一篇“建模轻轻松松仿真让人头秃”的高门槛论文。等我把Matlab代码跑通、把博弈闭环理顺之后才发现这套方法远比想象中实用——它把末端追逃从“双方底牌互明”的经典假设推到了“不知道对方推力上限、不知道对方机动策略”的真实场景并且用Epsilon纳什均衡给了一个可以被量化的“差不多最优”策略而不是拍拍脑袋设计一条制导律。这篇文章是基于我个人完整复现经验整理出来的适合正在研究航天器制导与控制、想入门微分博弈或者被EKF调参折磨得睡不着觉的同行参考。我先把话说清楚这个项目不是一个可以下载下来直接跑出炫酷轨迹的玩具Demo它是一套完整的“估计—博弈—决策”研究框架。你把它跑起来能看到的不只是追逃轨迹更能看到一套当对手参数未知时如何通过在线估计逐步逼近均衡策略的工程化思路。文章后面所有代码片段、参数设置和调参经验都来自我实际复现时的工程笔记可以直接抄作业但强烈建议你按自己的任务场景重新标定。1. 这个复现项目到底在解决什么问题1.1 一句话讲清楚任务所谓“末端追逃博弈”指的是追踪器追方和逃逸器逃方在交会末端有限时间内围绕某个终端条件展开对抗。项目标题里每个词都不是摆设不完全信息追方并不知道逃方的真实机动能力比如最大推力、控制偏好只能通过观测相对状态和轨迹来判断。Epsilon纳什均衡博弈双方不一定能找到精确的纳什均衡但能找到“偏离收益不超过epsilon”的策略组合当epsilon收敛到足够小时就近似最优。EKF参数估计用扩展卡尔曼滤波把对手的未知参数作为状态变量的一部分实时估计。自适应博弈估计结果反过来实时修正己方的收益函数从而在每个决策时刻重新计算均衡策略。换句话说这套方案的定位是在不知道对手底牌的前提下边猜边打并且保证每一步策略都有博弈论层面的质量下界。1.2 为什么末端追逃值得单独研究航天器末端接近段是整个交会对接、在轨服务、空间碎片清理等任务中最紧张也最危险的阶段。距离近、相对速度快、机动窗口短任何一个错误的推力决策都可能让整个任务失败。传统制导方法通常假设目标运动模型已知或者只考虑单方面的最优控制比如设计一条满足终端约束的标称轨迹。可一旦进入对抗场景对方也在实时优化自己的逃逸策略问题就从“单边最优控制”变成了“双边博弈”。博弈论给这类问题提供了一个非常自然的数学框架双方都在最小化或最大化某个终端指标而均衡解就是双方都不愿意单方面改变策略的那个状态。这个思路和航天器末端交会简直是天生一对——也是为什么这个方向在近十年一直是航天控制领域的热点。1.3 不完全信息到底难在哪在经典微分博弈里状态方程、控制约束和收益函数都是公共知识双方都知道对方的目标函数所以可以用哈密顿—雅可比—伊萨克斯方程求解。但现实中你很难知道对手的最大推力幅值、它的燃料余量、它优先保命还是优先耗时间。这些参数直接影响对手的策略选择可你又观测不到。这里就需要贝叶斯博弈的思路把未知参数看作“类型”用观测数据在线估计类型再基于估计值重新求解博弈。项目标题里的EKF就是在做这件事。它与博弈求解器的关系是EKF负责告诉你对手大概是什么类型博弈求解器负责针对这个类型给出最优响应——两者串起来就是“自适应博弈”的闭环。2. 核心原理拆解从相对运动动力学到Epsilon均衡2.1 末端追逃的相对运动模型怎么建追逃博弈的第一步是建立相对运动模型。大多数复现项目会从经典的圆轨道相对运动方程出发也就是常说的Clohessy-Wiltshire方程CW方程。在二维平面场景下把相对位置和相对速度组成状态向量x [dx, dy, dvx, dvy]^T线性化后的动力学可以写成% 简化的二维CW方程n为参考轨道角速度 function xdot relative_dynamics(t, x, a_p, a_e, n) xdot zeros(4, 1); xdot(1) x(3); xdot(2) x(4); xdot(3) 2 * n * x(4) 3 * n^2 * x(1) a_p(1) a_e(1); xdot(4) -2 * n * x(3) a_p(2) a_e(2); end其中a_p和a_e分别是追方和逃方施加的相对加速度。实际仿真中我一般不会直接用线性方程而是把推进器输出限幅、质量变化、推力方向约束全部加进去再用四阶Runge-Kutta传播。线性CW方程的价值在于给博弈支付函数一个可以解析求导的基础但最终控制量下发前还是要回到较完整的非线性模型里验证。2.2 从纳什均衡到Epsilon纳什均衡先复习一下概念。在双人策略博弈中如果策略组合(s_p, s_e)满足任意一方单方面改变自己的策略都不能让己方收益变得更好那么这就是一个纳什均衡。数学上写成追方J_p(s_p, s_e) ≥ J_p(s_p, s_e)对所有s_p成立逃方J_e(s_p, s_e) ≥ J_e(s_p, s_e)对所有s_e成立。但真实求解时双方的策略空间往往是连续函数空间直接求精确均衡非常困难。于是就有了Epsilon纳什均衡允许每个玩家最多因为“没有做得更好”而损失epsilon。形式化地如果双方偏离均衡后收益改进都不超过epsilon则称这个策略组合是Epsilon纳什均衡。为什么“差不多最优”就够用因为在数值仿真里你的策略本来就不是连续函数而是离散的决策序列控制周期、状态观测误差、积分步长都决定了策略分辨率是有限的。与其追求一个对噪声极端敏感的精确解不如给出一个明确边界的epsilon均衡告诉读者这个策略距离理想均衡的偏差不会超过这么多。2.3 不完全信息下的贝叶斯博弈视角不完全信息博弈的核心是把对手的未知参数θ视为一个随机类型。追方对θ有一个先验分布在博弈过程中通过EKF逐步更新后验估计。这里最关键的一点是参数估计的不确定性必须传导到收益函数里而不是简单地把估计值当成真值。我复现时踩过这个坑如果直接把EKF输出的点估计塞进均衡求解器策略会出现剧烈的抖动因为估计方差大的时候点估计本身就在跳。后来我把估计方差作为收益函数里的鲁棒项比如在终端收益中加上一项“参数不确定度惩罚”效果立刻稳定下来。这也符合自适应博弈的核心思想——不仅要适应参数的变化还要适应“对参数确信程度”的变化。3. EKF参数估计在博弈过程中边打边学3.1 为什么这里必须用EKF线性卡尔曼滤波的适用前提是系统动态和观测方程都是线性的。航天器相对运动虽然可以线性化为CW方程但一旦引入推力方向约束、带限幅的机动指令或者把未知参数乘进状态方程里系统就变成非线性的了。EKF的基本思路很简单在每一步把非线性函数在当前估计点做一阶泰勒展开然后用标准卡尔曼滤波公式做预测与更新。在追逃场景里这个方案特别合适因为每个决策周期的观测样本量不大但时间尺度足够长EKF可以逐步收敛。另一个原因是EKF实现成本低Matlab里几十行就能跑起来不需要像粒子滤波那样维护大量粒子这对在线博弈求解来说很重要——因为博弈迭代本身已经够耗CPU了。3.2 增广状态怎么设计所谓“增广状态”就是把未知参数直接拼到状态向量后面。举个例子如果追方不确定逃方的最大推力幅值a_max_e和逃方在x方向的机动偏好系数λ_e那么增广状态就是x_aug [dx; dy; dvx; dvy; a_max_e; lambda_e];观测模型取相对位置和相对速度或仅相对位置多普勒速度。EKF的状态转移函数里最后两维的导数为0表示参数在博弈过程中是常数或者带一个很小的随机游走噪声便于跟踪时变参数。这个过程用Maple或手推雅可比都可以但我在Matlab里更推荐用符号工具箱算一次雅可比矩阵然后转成函数句柄避免手写几十项偏导数出错。3.3 可观测性与调参经验EKF不是万能的最典型的坑就是参数不可观测——如果你追方始终在一个方向跟踪逃方那么逃方垂直方向的机动能力参数就几乎没有激励EKF对它的估计也不会收敛。这说明末端追逃需要一个“激励性”的轨迹设计或者至少让观测维度覆盖参数影响方向。调参方面直接分享几条我试出来的实用感受P0不能拍脑袋取大。初始协方差如果给得过大EKF前几步增益会大得离谱导致状态跳变。我一般取系统状态量级平方的0.1到1倍参数维取估计范围的1/4平方。Q矩阵的随机游走项不要太贪。参数维的Q噪声取太小跟踪不了时变参数取太大估计结果毛刺很多。我的做法是先固定一个值跑几次蒙特卡洛看轨迹平滑度再微调。R矩阵按观测噪声实测来。如果仿真里观测量是真实值加高斯噪声R就取噪声协方差不要为了“看起来收敛快”而把R调得过小否则滤波会过度相信观测导致震荡。4. 自适应博弈用实时估计更新均衡策略4.1 收益函数与策略空间追逃博弈的收益函数通常包括两部分终端奖惩和控制能量。我复现时选用的是很常见的末端邻域捕获判定如果终端时刻追方与逃方距离小于捕获半径r_c追方“获胜”收益为1同时双方都要为消耗的控制能量付出代价写成二次型形式。策略空间的选择决定了求解难度。如果每个决策时刻都把未来N步的推力序列作为策略变量问题就变成一个带约束的最优控制问题计算量很大。因此我采用的是“参数化策略”把每一步的推力方向角φ和推力幅值系数k作为策略变量这样双方策略都是有限维向量博弈求解器可以复用。4.2 数值求解Epsilon均衡的迭代框架在每轮决策中我使用交替最优响应法求解近似均衡。流程可以概括为% 伪代码迭代最优响应求解Epsilon均衡 s_p s_p_init; % 追方策略 s_e s_e_init; % 逃方策略 for iter 1:max_iter s_p_new best_response_pursuer(s_e, theta_e_hat); s_e_new best_response_evader(s_p_new, theta_p_hat); dev_p max_deviation_pursuer(s_p_new, s_e_new, theta_e_hat); dev_e max_deviation_evader(s_e_new, s_p_new, theta_p_hat); epsilon max(dev_p, dev_e); if epsilon tol break; end % 阻尼更新避免振荡 s_p (1 - alpha) * s_p alpha * s_p_new; s_e (1 - alpha) * s_e alpha * s_e_new; end这里的best_response函数本质上是固定对方策略后用数值优化求解己方的最优策略。因为策略维度不高十几个到几十个变量我用Matlab自带的fmincon就能满足要求。观察dev_p和dev_e的收敛过程会发现前期epsilon下降很快后期会陷入小幅震荡这时阻尼alpha就特别重要。我一般从0.7开始试如果振荡明显就降到0.3。4.3 自适应闭环如何串起来整个自适应博弈在每个决策周期里按下面几步执行用当前EKF估计得到扩张状态x̂和参数θ̂。把θ̂和协方差中的不确定性带入追方收益函数。与逃方策略模拟器交替求解Epsilon均衡得到当前周期追方控制指令。执行控制并采样新的观测数据。用EKF更新估计进入下一周期。可以看到EKF和均衡求解器是串联关系上一环节的输出是下一环节的输入。任何一环的异常都会反映到另一环。比如EKF估计偏差大时均衡求解器会得到一个错误的对手模型追方策略就会往错误方向偏而如果均衡求解迭代不收敛控制指令抖动剧烈观测噪声变大又反过来影响EKF的收敛。这也是我在仿真中把整个闭环写成一个大状态机而不是流水线脚本的原因——每个模块的状态估计方差、迭代次数、epsilon值都要保留方便出问题时回溯。5. Matlab仿真工程拆解与关键代码5.1 文件结构与主流程我建议工程采用模块化结构每个功能单独一个文件主脚本只负责串流程。我复现时的目录大致如下main.m % 主入口设置参数并循环仿真 dynamics/ relative_dynamics.m % 相对运动方程 rk4_step.m % RK4单步传播 estimator/ ekf_predict.m % EKF预测 ekf_update.m % EKF更新 augmented_dynamics.m % 扩维后的状态转移 solver/ equilibrium_solver.m % 迭代最优响应求解 best_response.m % 单方最优响应 payoff_pursuer.m % 追方收益 payoff_evader.m % 逃方收益 plot/ plot_trajectory.m % 轨迹图 plot_parameter_est.m % 参数估计曲线 plot_epsilon.m % epsilon收敛曲线主流程是先用参数结构体初始化所有变量然后进入一个for循环每个决策周期依次执行状态估计、均衡求解、轨迹传播、数据存储最后统一绘图。把参数全部集中到一个params结构体里可以少改很多重复代码。5.2 动力学传播模块实际的动力学我使用的是非线性相对运动模型考虑J2摄动的简化影响但博弈求解器内部用的是线性CW模型——这样能保证求解器速度和终端约束的可导性。这里给出RK4步进的一个实现片段function x_next rk4_step(self, f, t, x, dt, u_p, u_e, params) k1 f(t, x, u_p, u_e, params); k2 f(t dt/2, x dt/2*k1, u_p, u_e, params); k3 f(t dt/2, x dt/2*k2, u_p, u_e, params); k4 f(t dt, x dt*k3, u_p, u_e, params); x_next x dt/6 * (k1 2*k2 2*k3 k4); end注意在末端追逃阶段积分步长要远小于博弈决策周期。我常用的参数是决策周期1秒动力学积分步长0.01秒。如果积分步长和决策周期一样仿真会积累很大的传播误差最终轨迹看起来“发飘”。5.3 EKF估计模块EKF模块的核心是状态转移函数和观测函数的雅可比。对于扩维状态状态转移函数可以写成function [x_next, F] augmented_transition(x_aug, u_p, dt, params) n params.n; % 解包原始状态和参数 state x_aug(1:4); a_max_e x_aug(5); lambda_e x_aug(6); % 用含参数的非线性动力学传播这里用线性化参数项 A [0 0 1 0; 0 0 0 1; 3*n^2 0 0 2*n; 0 0 -2*n 0]; B [0 0; 0 0; 1 0; 0 1]; % 逃方控制受a_max_e和lambda_e调制 u_e [lambda_e * a_max_e * cos(params.phi_e); a_max_e * sin(params.phi_e)]; x_next_state state dt * (A * state B * (u_p u_e)); x_next [x_next_state; a_max_e; lambda_e]; % 雅可比F需要数值求导或符号推导 F calculate_F(x_aug, u_p, dt, params); end实际中F矩阵用符号工具箱求导后会生成一大段代码这里就不全部贴出。雅可比计算是EKF最容易出错的地方我的建议是写一个自动差分函数先用中心差分验证解析雅可比确认一致后再用于滤波。5.4 均衡求解模块均衡求解模块是仿真里最耗时的部分。我把每次决策周期的均衡求解封装成equilibrium_solver输入是对方估计参数与当前相对状态输出是当前周期的双方控制策略和epsilon值。核心是交替调用best_responsefunction [s_p, s_e, epsilon, info] equilibrium_solver(x_cur, theta_e_hat, theta_p_hat, params) % 初始化策略 s_p zeros(params.control_dim, 1); s_e zeros(params.control_dim, 1); for iter 1:params.max_iter s_p_new best_response(s_e, x_cur, theta_e_hat, pursuer, params); s_e_new best_response(s_p_new, x_cur, theta_p_hat, evader, params); dev_p approx_deviation(s_p_new, s_e_new, pursuer, theta_e_hat, params); dev_e approx_deviation(s_e_new, s_p_new, evader, theta_p_hat, params); epsilon max(dev_p, dev_e); if epsilon params.eq_tol, s_p s_p_new; s_e s_e_new; break; end s_p params.alpha * s_p_new (1 - params.alpha) * s_p; s_e params.alpha * s_e_new (1 - params.alpha) * s_e; end info.iter iter; end这个模块的坑在于best_response内部如果调用fmincon每个玩家每次迭代都要跑一次约束优化循环30次就要跑60次优化。仿真跑一个场景可能要几个小时。后来我做了一个折中先把控制方向角离散成36个候选在这个离散空间里找最优响应然后再以这个结果作为fmincon的初值做精化。这样既保证解的质量又大幅减少fmincon的迭代次数。5.5 参数与工况设计仿真参数可以参考近地圆轨道交会末端的典型量级。我用的是轨道高度500km参考角速度n约0.0011 rad/s初始相对距离10km相对速度200m/s。捕获半径设定为500m。追方推力幅值上限取固定值逃方真实最大推力在部分工况里设置为时变用于检验自适应估计的跟踪能力。决策周期、积分步长和观测噪声这几个参数建议放在一个单独的config.m里集中维护。我给出一组可以跑通的基准值参数数值说明参考轨道高度500 km近地圆轨道初始相对距离10 km末端交会起始点相对速度200 m/s追方接近逃方捕获半径500 m终端成功判据决策周期1 s博弈重解频率积分步长0.01 s动力学仿真步长观测噪声标准差10 m位置相对导航精度追方推力上限50 m/s^2量纲为加速度逃方真实推力上限30~55 m/s^2部分工况时变EKF初始位置方差10000 m^2对应10km距离不确定6. 仿真结果与分析从轨迹曲线看策略本质6.1 基准工况固定参数下的博弈结果我先跑了一个“逃方推力上限恒为40”的基准工况。EKF在约5个决策周期后就把a_max_e估计值收敛到38上下稳态误差在5%以内。博弈策略方面追方一开始偏保守轨迹呈现明显的试探性机动随着参数估计稳定追方在末端约20秒时开始实施一个“V”形拦截机动最终在终端时刻把距离压到了480m左右刚好小于捕获半径。逃方则是持续向远离追方方向加速但因为参数被估计出来它的逃逸方向被提前预判难以摆脱。这个工况验证了一个基本逻辑当参数收敛后自适应博弈逐渐退化为一个已知参数博弈均衡策略更接近经典解。6.2 时变参数工况自适应跟踪与策略切换更有意思的是时变工况。我让逃方推力上限在前30秒为3530到50秒线性增长到55再保持在55。EKF的表现比预期好因为推力上限的变化会直接影响逃方轨迹的曲率只要逃方持续机动这个参数就有持续激励。估计曲线滞后约3秒但整体趋势跟踪得不错。追踪策略在这个工况里出现了明显的分段特征第一阶段追方按小推力上限对手设计策略第二阶段随着估计值升高追方开始更早转向、更急的横向机动。这说明自适应机制确实在做“根据对对手能力的判断调整策略”这件事而不是固定一个保守方案打到底。6.3 从Epsilon值变化曲线看均衡质量每次博弈求解都会算出一个epsilon值记录下来后可以得到一条随决策周期变化的曲线。基准工况里epsilon基本稳定在0.02以下说明求解器认为双方偏离收益都不大时变工况里在参数变化剧烈的第30到40秒之间epsilon会突然升到0.15左右随后又降回来。这个峰值很有信息量参数突变时EKF的估计方差变大均衡求解器基于一个“不确信”的对手模型解出的策略实际偏离均衡的程度会增大。这提醒我们评估自适应博弈系统不能只看平均轨迹是否成功还要关注参数剧烈变化时的瞬时均衡质量。7. 复现过程中踩过的坑与排查实录7.1 高频问题速查表现象可能原因排查/解决办法EKF估计值发散P0过大、Q或R不匹配调小P0检查雅可比用中心差分验证估计值长期不收敛参数不可观测激励不足增加逃方机动幅度或调整观测维度博弈迭代不收敛策略初值差、步长过大用离散候选策略粗搜索再做梯度精化追方轨迹振荡均衡求解alpha太大将阻尼alpha降到0.3以下epsilon曲线不降收益函数存在平台区偏差函数求解不准检查最大偏离的近似计算方法增加数值解析度仿真速度过慢fmincon调用过多减少每个周期迭代次数用MEX或并行终端距离卡在捕获半径边缘收益函数终端权重不足增加终端奖惩项的权重系数7.2 几条独家调试心得第一先跑通确定性场景再开EKF。我最初的错误是上来就把完整闭环接好结果问题叠问题根本分不清是滤波发散还是博弈不收敛。正确顺序是固定参数做已知对手博弈再开估计器对比最后才让参数时变。第二步和第三步之间能够清晰看到估计误差对均衡策略的影响。第二把Epsilon均衡的“偏离收益计算”做成独立函数再画出来。很多时候博弈迭代不收敛不是优化器的问题而是你计算最大偏离时用的是同一个近似策略集导致偏差被低估。如果只观察epsilon忽略了这个偏差你会误以为已经收敛。第三EKF的方差要传给收益函数而不是只传均值。我后来在追方收益里加了一项基于协方差的鲁棒惩罚追方在参数不确定时会主动选择更保守的机动方向这比任何调参技巧都更贴合“不完全信息”的本质——你不仅要适应参数本身还要适应自己对参数的无知程度。最后再分享一个实操层面的小技巧如果你要把这套博弈逻辑扩展成实时应用先把所有模块做成函数并且用profiler分析热点。我实测下来均衡求解占了85%以上的耗时而它内部超过一半时间花在重复调用动力学传播上。把公共的传播轨迹缓存下来复用仿真速度能提升近一倍。这种优化思路在其他多智能体对抗仿真里同样适用。跑通这个项目之后我最大的感受是不完全信息博弈真正难的不是数学公式而是如何把估计不确定性合理地纳入策略优化。希望这篇复现笔记能帮你少走一点弯路直接把精力放到更关键的博弈机制设计上。