无人机通信场景里一旦牵扯上“博弈论”“边缘计算”“抗干扰”这几个词,很多同学第一反应就是头大。我最早看到这个项目标题时,心里也在犯嘀咕:Stackelberg博弈不是经济学里的东西吗?怎么跑到信道分配来了?后来真正把模型跑通、把Matlab代码一行行调出来之后,才发现这条路其实是有清晰逻辑可循的。这篇东西,我想把整个项目的来龙去脉、建模思路、仿真实现和踩坑记录一次性讲清楚,给正在做无人机通信方向毕业设计或者课题研究的同学一个可以直接参考的完整路线。
这项目解决的核心问题,说直白点就是:一架无人机给地面多个用户提供边缘计算服务的时候,环境里存在干扰源,信道资源又有限,怎么给每个用户分配信道,才能让“用户获得的服务质量”和“无人机自身的开销”之间达到一个平衡。传统做法要么是纯随机分配,要么是简单轮询,效果都比较粗糙。这里引入Stackelberg博弈,就是让博弈双方有一个先后决策的顺序,无人机作为主导者先定信道价格,用户作为跟随者根据价格决定买多少信道资源,最后达到一个双方都能接受的稳定状态。
这篇内容适合正在做无人机通信、边缘计算、资源分配方向课题的本硕学生,也适合想快速上手Matlab仿真的研究者参考。下面我会从建模思路、数学推导、代码实现到调试避坑,把整个项目完整拆开来讲。
1. 项目到底在做什么:拆解标题背后的真实需求
1.1 三个关键词的分工理解
先把这个标题拆成三块来看,每块解决一个独立的问题。
第一块是“无人机边缘计算”。传统边缘计算是把服务器放在地面基站旁边,无人机边缘计算说白了就是把算力搬到天上去。为什么要这么干?因为很多场景下地面基础设施是缺失的,比如灾区救援、临时赛事保障、偏远地区巡检,地面根本没有基站可用。无人机飞过去,本身就是一个移动的边缘节点,既能通信又能计算。
第二块是“抗干扰”。无人机通信链路是开放空间传播的,非常容易被干扰源影响。这个干扰源可能是恶意的,比如有人故意发射同频干扰;也可能是非恶意的,比如其他通信系统的同频信号。干扰一强,信噪比就掉,传输速率就崩。所以信道分配必须把干扰因素考虑进去,不能只盯着信道本身的带宽。
第三块是“信道分配”。资源是有限的,无人机可用的信道就那么几个,用户却可能有几十个。分配策略的好坏直接决定了用户的体验质量和无人机的资源利用率。分配得不好,有的用户饿死,有的信道闲着,整体性能自然上不去。
1.2 这题的核心矛盾:利益冲突
如果只有一个用户,信道分配问题就没什么好研究的,把最好的信道给他就行。麻烦就麻烦在多用户场景下,每个用户都想要好信道、多信道,但无人机手里的资源是有限的。
更麻烦的是,无人机自己也有开销。信道给用户用,无人机就要消耗发射功率、处理资源,还要承受干扰带来的性能损失。如果每个用户都想要最多的信道,无人机就会因为开销过大而吃不消。
这就是典型的利益冲突。用户站在自己的角度希望信道越多越好,无人机站在自己的角度希望收益尽量大、开销尽量小。这种多方决策、利益互相牵制的场景,天然就是博弈论的用武之地。
1.3 为什么不能拍脑袋直接分配
有同学可能会问:我直接按用户数量均分信道不行吗?或者按照用户离无人机的距离来分配,远的用户多分点信道,行不行?
这两种直观思路在实际场景里都会出问题。均分方案完全没有考虑用户的实际需求差异,有的用户只需要传个小指令,给一堆信道纯属浪费;有的用户在传高清视频,需求大,给少了直接卡顿。按距离分倒是考虑了信道质量差异,但干扰这个因素没有进来——一个距离近但被干扰严重的用户,和一个距离远但干扰很小的用户,到底谁该多分信道?这账不好算。
这些问题靠直觉解决不了,必须建立一个数学模型,把用户需求、信道质量、干扰强度、无人机开销这些因素全部折进一个统一的框架里来优化。Stackelberg博弈就是这个框架。
2. 为什么偏偏是Stackelberg博弈:建模思路的来龙去脉
2.1 博弈论解决了什么层面的问题
很多人一听“博弈论”三个字就发怵,觉得是高深的经济学理论。其实博弈论的核心思想非常朴素:当多个决策者的利益互相影响时,每个决策者做决定的时候,都必须考虑别人会怎么反应。
用在信道分配里就是:无人机决定信道价格的时候,必须意识到用户会根据这个价格调整自己的信道需求;反过来,用户决定买多少信道的时候,也会猜测无人机的定价策略。双方在这个互动过程中不断调整,最后稳定在某个状态上。
这个过程跟菜市场买菜特别像。菜贩子定价高了,买的人就少;定价低了,利润又薄。买菜的人呢,也会根据价格决定买多买少。摊主和顾客之间就是一个典型的博弈关系。
2.2 Stackelberg博弈 vs 普通博弈:决策顺序的价值
博弈论里面学问很多,但这里用Stackelberg博弈是有明确原因的。它最大的特点是决策有先后次序:一方先行动,另一方观察到对方的行动后再做自己的决策。
这个先后次序不是随便定的,它对应了实际场景里无人机和用户之间的真实关系。无人机是网络的管理者,它先公布信道价格和分配规则,这符合管理者的角色;用户是服务的接受者,根据价格调整自己的需求,这符合用户的行为逻辑。
如果用普通纳什博弈来建模,相当于假设无人机和用户同时做决策,这不符合实际场景,算出来的结果也很难对应到真实系统中去。所以这里选Stackelberg博弈,本质上是让数学模型跟物理场景严格对应起来。
2.3 谁是领导者,谁是跟随者
在这个项目里,无人机是领导者,用户是跟随者。这个关系确立之后,后面的推导逻辑就清楚了:无人机先宣布一个信道单位价格,用户看到价格后,会以自身效用最大化为目标决定购买多少信道资源。
然后无人机再做第二轮优化,根据用户的需求反馈,调整自己的定价策略,让自己的收益最大化。这个过程反复迭代,直到价格和需求量都收敛到稳定值,这个稳定值就是Stackelberg均衡点。
有个细节值得注意:有些类似项目里会让用户当领导者,无人机当跟随者。那适用于用户有更强议价能力或者用户需求起主导作用的场景。这个项目里无人机是服务提供方,更有主导权,所以让无人机当领导者更合理。
建模顺序决定了解题难度。选对了谁先动、谁后动,后面的数学推导会顺很多;选反了,整个求解过程可能急转直下。我在另一个类似项目里就吃过这个亏,当时没有想清楚角色的主从关系,模型建出来怎么推都不收敛。
3. 系统模型与数学表达:从物理场景到公式
3.1 网络角色和拓扑结构
先把系统的角色理清楚。这个项目里一共有三类节点:一架无人机、多个地面用户、一个或多个干扰源。
无人机的位置可以假设是固定的,悬停在某个高度,这个高度要能覆盖所有地面用户。用户分布在一个区域内,每个用户和无人机之间的距离不同,信道增益自然也不同。干扰源位置固定,向无人机方向发射干扰信号。
整个系统的通信链路是这样的:用户把数据传到无人机,无人机做边缘计算后再把结果回传给用户。这个过程需要上行信道和下行信道。为了简化模型,很多项目里只考虑上行传输这一段,把问题聚焦在用户到无人机的信道分配上。
每个用户的需求不同,有的计算任务重,需要传的数据量大,对信道需求就高;有的只是传个控制信号,需求低。系统建模的时候,要用一个数值把这些需求差异表达出来,比如每个用户的“计算任务数据量”,或者“最小传输速率需求”。
3.2 信道模型怎么建
信道模型是整个仿真里最基础的部分,模型选得不好,后面所有数据都不靠谱。
常见的做法是把信道增益分解成两部分:大尺度衰落和小尺度衰落。大尺度衰落跟距离相关,距离越远,信号衰减越厉害。小尺度衰落是快衰落,可以用瑞利分布或者莱斯分布来模拟。
在无人机场景里,视距传播是主要的传输模式,所以莱斯信道模型通常比瑞利信道更贴近实际。但很多论文为了简化,直接用自由空间路径损耗模型加一个随机衰落因子,效果也足够。
干扰建模部分,干扰源对接收端的干扰功率取决于干扰源的发射功率和干扰源到无人机之间的距离。干扰源的位置可以假设是固定的,但发射功率可以动态变化,这样能模拟不同强度的干扰环境。
核心数学模型可以写成:
% 信道增益计算(包含路径损耗和小尺度衰落) path_loss_dB = 20*log10(distance) + 20*log10(frequency) + 32.44; small_scale_fading = (randn(1,1)^2 + randn(1,1)^2) / 2; % 瑞利衰落 channel_gain = 10^(-path_loss_dB/10) * small_scale_fading; % 信干噪比计算 SINR = (user_power * channel_gain) / (noise_power + jammer_power * jammer_gain);3.3 效用函数的设计逻辑
建模的核心是设计效用函数。用户的效用函数要反映两件事:获得数据速率带来的收益,和购买信道资源付出的代价。
用户的数据速率可以通过香农公式计算:
rate = bandwidth * log2(1 + SINR);用户的效用 = 速率带来的满意度 - 信道成本。这个满意度可以用对数函数来表示,因为对数函数的特性是:速率低的时候,提升一点速率带来的满意度提升很大;速率已经很高的时候,再增加速率,满意度提升就变缓了。这符合边际效用递减的规律。
无人机的效用函数包含两块:向用户收取信道资源费用的收益,和信道分配所消耗的功率成本以及干扰带来的性能损失。
3.4 Stackelberg均衡的定义与求解路线
Stackelberg均衡的定义是:在这个状态下,领导者的策略在考虑跟随者的最优反应后是最优的,跟随者的策略也是对领导者策略的最优反应,任何一方单方面改变策略都无法提高自己的效用。
求解方法用的是逆向归纳法。先从跟随者开始,在给定信道价格的情况下,把用户的效用函数对信道需求量求导,令导数等于零,解出用户的最优需求量表达式。
这个表达式是信道价格的函数。然后把这个函数代回到无人机的效用函数里,无人机的最优化问题就从二维问题变成一维问题——只要求出最优价格。
求解无人机的最优价格可以用KKT条件。构造拉格朗日函数,对价格求偏导,结合约束条件的对偶变量,解出最优价格的闭式解。
如果闭式解推不出来,也可以用数值方法,比如梯度下降或者黄金分割搜索,在代码里迭代逼近最优值。
4. Matlab实现与仿真细节
4.1 代码整体架构安排
拿到一个Matlab仿真项目,千万不能上来就埋头写代码。先把代码的模块划分想清楚,后面调试和维护都会省很多力气。
我建议按这五个模块来组织代码结构:
第一个模块是参数初始化。所有用到的参数都集中放在这个模块里,包括用户数量、信道数量、干扰源功率、噪声功率、频谱带宽、无人机的功率上限、迭代次数上限等。把这些参数统一放在文件头部,后面要改仿真条件,直接改这里就行,不用满文件找参数。
第二个模块是信道生成。按照第3节说的方法,生成所有用户到无人机的信道增益矩阵。这里注意,信道矩阵的维度是用户数乘以信道数,每个元素代表一个用户在一个信道上的信道增益。
第三个模块是博弈迭代的核心循环。这个循环负责执行Stackelberg博弈的迭代过程:初始化价格,计算用户最优需求,更新无人机价格,检查收敛条件。
第四个模块是性能计算。迭代收敛之后,计算每个用户的速率、效用,无人机的总效用,以及整个系统的平均吞吐量等指标。
第五个模块是画图。把仿真结果可视化,包括收敛曲线、不同参数下的性能对比图等。
4.2 关键参数怎么设置
参数设置是整个仿真里最容易被忽略但又最重要的一环。参数设置不合理,轻则仿真结果不好看,重则算法根本不收敛。
下面这组参数来自我实际调试过的配置,可以作为起点参考:
% 系统基本参数 num_users = 8; % 用户数量 num_channels = 6; % 可用信道数量 total_bandwidth = 10e6; % 总带宽 10 MHz noise_power = 1e-12; % 噪声功率 jammer_power = 0.5; % 干扰源功率 0.5 W % 信道模型参数 carrier_frequency = 2e9; % 载波频率 2 GHz drone_height = 100; % 无人机高度 100 m % 博弈迭代参数 price_initial = 0.1; % 信道初始价格 learning_rate = 0.05; % 价格更新步长 max_iterations = 200; % 最大迭代次数 convergence_threshold = 1e-4; % 收敛阈值初学的时候很容易犯一个错误:把干扰源功率设得特别大或者特别小。设得太大,所有用户的信干噪比全被压到很低,速率几乎为零,整个系统就没法看了;设得太小,干扰对系统的影响微乎其微,抗干扰算法的优势也体现不出来。
我自己的经验是先把干扰源功率设在跟用户发射功率同一个数量级,比如用户发射功率是0.1W到1W之间,干扰功率先取0.5W左右,看效果再调整。
4.3 博弈迭代核心函数实现
博弈迭代部分是整个代码的核心,逻辑说白了就是三层循环:外层是价格更新,中间层是用户需求计算,内层是每个用户自己的最优需求求解。
核心代码框架可以写成:
%% Stackelberg博弈主循环 price = price_initial; history_price = zeros(max_iterations, 1); history_demand = zeros(max_iterations, num_users); for iter = 1:max_iterations % 跟随者问题:给定价格,用户计算最优信道需求 for u = 1:num_users % 用户的效用函数对需求量的导数,令其等于零 % 用数值求解方式,例如fzero demand_func = @(x) get_user_utility_deriv(x, price, channel_gain(u,:), jammer_gain(u,:)); demand(u) = fzero(demand_func, 1); end % 领导者问题:无人机根据用户需求更新价格 % 目标函数为无人机效用,用数值优化求解最优价格 price_new = fminbnd(@(p) -get_uav_utility(p, demand, channel_gain), price_initial_range(1), price_initial_range(2)); % 记录历史,判断收敛 history_price(iter) = price_new; history_demand(iter, :) = demand; if abs(price_new - price) < convergence_threshold disp(['迭代收敛于第 ', num2str(iter), ' 次']); break; end price = price_new; end这里用了fzero和fminbnd这两个Matlab内置函数。fzero用来解用户的效用函数导数为零的方程,fminbnd用来在给定区间内找无人机效用的最大值。这两个函数是Matlab最基础的数值求解工具,对于这种一维问题非常稳定,不需要自己去写复杂的梯度下降逻辑。
编程实现里有两种路线可选:一种是把数学推导做完,得到闭式解,然后代码里直接代入公式求值,速度快且结果准;另一种是像上面这样直接用数值方法求解,代码写起来简单,但每次迭代都要调优化函数,速度会慢一些。如果数学功底比较好,强烈建议走闭式解的路线,仿真效率会高一个数量级。
4.4 仿真流程和结果分析
整个仿真的流程是这样的:先生成信道,然后跑博弈迭代,得到收敛的信道分配结果,再算各种性能指标,最后画图。
画图部分一般至少需要四张图:
第一张是价格迭代收敛曲线,横轴是迭代次数,纵轴是信道价格。这张图能直观看到价格从初值逐步收敛到稳定值的过程,一眼就能判断算法是否收敛。
第二张是用户信道分配柱状图,横轴是用户编号,纵轴是分配到的信道数,可以看到不同用户之间信道需求的差异。
第三张是用户速率分布图,对比不同算法(比如Stackelberg博弈算法 vs 随机分配 vs 平均分配)下每个用户获得的数据速率。
第四张是无人机收益和干扰源功率的关系曲线,横轴是干扰源功率,纵轴是无人机总效用,可以看到随着干扰增强,无人机的收益如何变化。
我实际跑出来的结果有一个很明显的特点:Stackelberg博弈得到的系统总效用,要明显高于随机分配和平均分配,而且用户之间的速率更均匀,不会出现有的用户速率特别高、有的用户几乎没法用的情况。
这背后的道理是:博弈过程会撮合出一个价格信号,这个价格信号自动调节了供需关系。信道条件好的用户,愿意出更高的价格获得更多信道;信道条件差的用户,也不会花冤枉钱去抢那些被干扰很严重的信道。整个系统的资源就这样被价格机制自然配置到了最合理的位置。
5. 常见问题与调试心得:实战避坑记录
5.1 迭代不收敛怎么办
这是被问得最多的问题。运行完代码,发现价格一直在震荡,就是不收敛,或者干脆数值越变越大,直接溢出报错。
这个问题九成以上出在两个地方。
第一个地方是价格更新步长没调好。最直接的解决方法是缩小步长,比如从0.05改到0.01,或者在代码里加一个衰减因子,让步长随着迭代次数逐渐变小,这样即使在最优解附近有震荡,振幅也会越来越小,最终落下去。
第二个更隐蔽的原因是用户的信道需求函数没有唯一解。比如某个用户在某个价格下,买一个信道和买三个信道获得的效用一样大,这时候fzero可能返回一个随机解,导致整个系统震荡。解决办法是检查效用函数的设计,确保用户的需求函数在可行域内是严格凹函数,这样才能保证有唯一的极值点。
5.2 信道增益矩阵的随机性问题
信道增益矩阵每次运行都是随机生成的,这就导致一个现象:代码明明没改,两次运行结果差异却很大。有的同学以为程序出了bug,急得不行。
这不是bug,是信道随机性的自然结果。解决办法也简单:做仿真对比的时候,固定随机种子。在代码最开头加一行:
rng(42); % 固定随机数种子这样每次跑出来的信道都一样,结果就可复现了。做算法对比的时候,尤其要注意这一点,否则你没法确定性能差异是算法带来的还是信道随机性带来的。
5.3 算法对比必须控制变量
写论文的时候,光有Stackelberg博弈的结果是不够的,必须跟其他算法做对比,才能体现这个方法的优越性。常见的对比算法有:随机信道分配、平均分配、贪心算法、以及多用户均衡博弈。
对比实验最需要注意的是控制变量。所有算法必须在完全相同的信道条件和参数条件下运行。最好写一个通用的仿真框架,把信道生成和参数初始化放在主文件里,三个算法分别做成不同的子函数,主文件里统一调用。
数据整理上有一个经验:不要只比最终指标,还要比迭代时间。有时候一个算法效果好但计算时间特别长,在真实系统里可能根本用不了。用Matlab的tic和toc函数记录每个算法的运行时间,对比结果会更有说服力。
5.4 画图细节让结果更专业
Matlab画图默认的样式比较朴素,直接用于论文或报告,视觉效果不够好。我习惯在画图前统一设置一下图形参数:
set(0, 'DefaultAxesFontSize', 12); set(0, 'DefaultLineLineWidth', 1.5); set(0, 'DefaultAxesFontName', 'Times New Roman');这样设置之后,图里的字体、线宽都会自动变得规范,不用每次画图都手动调整。
此外,几张图放在一起对比时,配色和线型要注意区分。比如Stackelberg博弈用红色实线,随机分配用蓝色虚线,平均分配用黑色点线,一眼看过去就分得清清楚楚。
5.5 从仿真走向论文:几点核心经验
项目跑通之后,接下来就是把这套工作整理成论文或者报告。这里分享几个我认为最关键的写作经验。
第一,系统模型图一定要画好。评审专家拿到论文第一眼看的往往就是模型图,模型图信息密度高、逻辑清晰,整篇文章的可信度立刻就能上一个台阶。画图推荐用Visio或者Matlab自带的绘图工具,务必把无人机、用户、干扰源、通信链路、干扰链路全部画清楚。
第二,数学公式的推导过程要写完整。从系统模型到效用函数,从效用函数到Stackelberg均衡,中间的推导一步都不能省。很多人在写论文的时候直接从模型跳到结果,中间的博弈均衡推导全都省略了,这是大忌。评审专家最关注的就是这个推导过程,这是整个工作的理论支撑。
第三,仿真部分要提供复现条件。论文里要把参数设置表格列清楚,每个参数什么含义、取什么值、依据是什么,都要写明白。这一步既方便评审专家判断仿真结果的可信度,也方便其他研究者在你的基础上接着做工作。
补充一个很多初学者不会注意的小地方:仿真结果图和理论推导最好能够互相印证。比如你的理论推导得到均衡价格跟干扰功率成正比,那仿真结果曲线上就应该到处呈现这个趋势。如果理论上推出来是这个趋势,仿真结果却对不上,那就要回去查模型了,这是找建模错误非常有效的一种方式。
6. 项目进一步扩展的方向
这套模型跑通之后,可以扩展的方向其实不少。如果时间充裕,在原有基础上做几个扩展点,项目的工作量和创新性可以显著提升。
一个方向是多无人机协同。这个项目里只有一架无人机,真实场景往往需要多架无人机协同覆盖一片区域。多无人机场景下,问题就复杂了:用户不仅要选择信道,还要选择接入哪架无人机,这变成了一个双重决策问题,博弈的层次也会多一层。
另一个方向是动态干扰场景。当前模型里干扰源功率是固定的,真实环境中干扰源很可能是移动的,或者是功率可变的,甚至干扰策略跟无人机之间有对抗关系。把干扰源也建模成一个博弈参与者,构成一个三层博弈,这样整个模型的层次会更丰富,也更有学术价值。
再一个方向是把其他因素加进来,比如无人机自身的移动性。无人机边缘计算里,无人机不是一直悬停不动的,它可能要沿着一条路径飞行,给沿途的用户提供服务。飞行轨迹优化跟信道分配联合起来做,又是一个新的优化问题。
这些扩展方向虽然看起来工作量很大,但核心方法论跟现在这个项目是一样的:建立博弈模型、设计效用函数、求解均衡点、仿真验证。基础打牢了,往上加东西就是量变到质变的过程。
我个人的体会是,做这种带博弈论的项目,最重要的不是代码技术有多牛,而是建模思路上能不能把物理场景跟数学模型对应起来。很多人的代码写得挺顺畅,但模型不对,跑出来的结果再怎么分析都没意义。反过来,模型想清楚了,代码就是水到渠成的事情。这套思路不管是拿来做毕设还是发论文,都值得你沉下心来把它吃透。