做无人机通信的强化学习课题,尤其是双机协同加NOMA这种组合,最容易卡住的地方不是算法本身,而是整个仿真体系怎么搭。网上能搜到的资料大多停留在概念层面,真正把状态、动作、奖励、信道模型、SIC解调顺序这些细节串起来跑通的代码并不多。这篇文章就拿一个我实际打磨过的“基于中心化Q-Learning的双无人机NOMA通信系统路径优化”Matlab仿真来拆解,讲清楚每一个设计决策背后为什么要这么做,以及调试时最容易踩的坑。
这套场景适合正在做无人机通信、移动边缘计算、强化学习路径规划这类方向的人参考,尤其是手头有个具体任务但不知道从哪下手搭仿真的人。看完你应该能自己复现一个可运行的框架,并且知道怎么往里面加自己的东西。
1. 从问题场景出发:为什么两架无人机要做NOMA路径规划
1.1 双无人机空中基站能解决什么实际问题
单无人机覆盖地面用户的方案有一个天然短板:当用户分布在较大范围内,或者地形遮挡比较明显时,无人机离某一组用户近了,另一组用户的信道质量就会往下掉。无人机的飞行速度、转弯半径、续航时间都有限,不可能同时照顾到所有用户。这时候双无人机就有了存在的价值:两架飞机一左一右、一前一后分区域覆盖,或者一架做主覆盖、另一架做补盲覆盖,整个系统的覆盖范围和用户速率都会有明显提升。
但问题也跟着来了:两架无人机怎么飞?如果各自只顾自己区域的用户,完全不管对方的存在,那两架飞机飞得太近的时候会产生强干扰,飞得太远又会有覆盖空洞。这不是简单的“每架飞机单独优化轨迹”就能解决的,因为两架飞机之间是耦合的——它们在同一个空域里共享频谱资源,彼此的信号会互相影响。
1.2 NOMA在这个场景里的角色
NOMA(非正交多址接入)解决的是频谱资源不够分的问题。传统正交多址(比如OFDMA)把不同的用户分到不同的时频资源块上,互不干扰但资源利用率低。NOMA允许两个用户共用同一个资源块,通过功率域的区分来叠加传输——一个用户用大功率,一个用户用小功率,接收端用SIC(串行干扰消除)逐级解码。
放在双无人机场景里,NOMA的意义就非常实际:两架无人机覆盖的用户组里,同一时刻可能有多用户需要调度。如果都用正交资源,系统容量上限会被锁死;用NOMA把信道条件差异较大的两个用户配成一对,叠加在一个资源块上传输,系统总速率立刻就能上来。信道好的用户用低功率也能解出自己信号,信道差的用户用高功率保证服务质量,接收端先解强信号、再解弱信号,这就是最经典的功率域NOMA思路。
1.3 路径规划为什么不能靠“飞得越近越好”
很多人第一反应是:无人机离用户越近,信道越好,速率自然越高,路径规划不就变成了一个“追着用户飞”的问题吗?实际完全不是这样。
第一,无人机追着一个用户飞,会离另一个用户越来越远,NOMA配对里的两个用户速率会失衡。第二,无人机飞行本身耗能,飞来飞去的时间越长、机动越多,留在服务状态的时间就越短。第三,两架无人机如果都被同一个“最优位置”吸引,可能在空中撞到一起,或者互相干扰。路径规划本质上是在多个互相冲突的目标之间找平衡:总速率要高、用户公平性不能太差、飞行能耗要可控、NOMA配对要稳定。
这个问题用传统凸优化方法很难解,因为非凸、非平滑、而且跟用户的动态分布耦合在一起。所以强化学习——具体说是Q-Learning——就成了一个非常自然的选择。
2. 选型推演:为什么用中心化Q-Learning而不是其他方案
2.1 和深度强化学习的对比
现在的论文里一提到强化学习就是PPO、DDPG、TD3这些深度算法,但很多场景其实用不上那么重的工具。Q-Learning是表格型方法,维护一张状态-动作Q表,不需要神经网络,不依赖GPU,训练速度快,收敛过程可视化程度极高。对双无人机这个规模来说,状态空间虽然不小,但离散化之后是可控的,完全没必要上深度网络。
深度强化学习确实能处理连续动作空间,但代价是训练不稳定、超参数多、调参恶心。DDPG一类的算法在无人机路径规划里经常出现训练崩掉的情况,奖励稍微设计得不合理,网络就学歪了。Q-Learning的优势在于每一步更新都是显式的Q值迭代,你能看得清清楚楚它学到哪了、学没学会,这对教学和科研初期的验证更有价值。
2.2 和分布式学习的对比
不用Q-Learning的话,还有一条路是每架无人机各跑一个独立的Q-Learning,各学各的。这看起来更简单,但有个致命问题:非平稳性。无人机A学到的策略会影响无人机B的观测结果,因为环境对B来说包含A的行为。B的策略一变,A面对的环境转移概率实际上就变了。两边都在变,两边都很难收敛。
中心化Q-Learning就不同了:两架无人机的联合状态和联合动作放在同一个Q表里,中心节点统一做决策。Q函数的输入是全球状态,输出是两架飞机的联合动作,学习目标完全一致,不存在“对手策略变化导致环境漂移”的问题。代价是Q表规模会变大,但双智能体、离散化动作的情况下这个代价完全能接受。
2.3 中心化方案的适用边界
中心化Q-Learning不是万能的。如果无人机数量达到五架、十架,联合动作空间会指数爆炸,Q表根本存不下。不过在两架无人机、每架4到5个动作的情况下,联合动作空间也就是16到25个,状态空间如果设计得克制一点,整个Q表可以控制在百万量级以内,Matlab跑起来没有任何压力。
另外中心化方案要求有可靠的通信链路把两架无人机的状态汇总到决策节点。在现实系统里这确实是个限制,但在仿真里默认中心节点完全可靠,先把这个核心算法架构验证清楚再说,这是做科研的标准路径。
3. 仿真系统的顶层设计:状态、动作、奖励怎么定
3.1 系统模型和信道建模
先明确仿真场景的基本设定。我采用的模型是:两架无人机在固定高度飞行,服务若干个地面用户。用户位置在每次训练episode开始时随机生成,模拟用户分布变化。无人机每个时隙按动作移动一格,覆盖区域是一个离散网格地图。
信道建模采用经典的无人机-地面视距/非视距(LoS/NLoS)概率模型。无人机和地面用户之间的路径损耗由距离决定,同时叠加LoS概率加权的额外衰减。这里有一个非常关键的细节:LoS/NLoS模型中,视距概率本身跟无人机和用户的仰角有关,所以无人机飞的高度变化会影响信道特性。在离散网格里高度是固定的,简化了模型,但也意味着你的结论只在固定高度下成立,扩展的时候要注意。
信道增益的计算公式要统一写好,后面速率计算全部复用。大尺度衰落用路径损耗,小尺度衰落用瑞利或莱斯分布采样。这一层写不好,后面所有Q-Learning的奖励都是错的——输入数据错了,再怎么强化学习都学不出有意义的结果。
3.2 状态空间的离散化与Q表规模估算
这是很多初学者第一个翻车的地方:状态设计得太大,Q表直接爆掉。假设地图是10×10的网格,地面有4个用户,如果你把每个用户的坐标都作为状态的一部分,那就是10^8个组合,再加无人机位置,Q表根本没法收敛。
正确的做法是只保留决策真正需要的状态信息。我的设计是三部分:
- 两架无人机的离散网格坐标:各100种,联合起来10^4种
- NOMA配对后的用户连接状态:比如两架无人机各自服务的用户编号组合
- 当前时隙的系统吞吐量等级:用粗粒度区间离散化
整体状态数控制在10万量级以内,联合动作空间16个,Q表规模大概160万条左右,Matlab用单精度矩阵存大概6MB多,完全可行。
所以说状态设计不是“信息越多越好”,而是“够用就好”。你要思考的是:无人机做路径决策时真正依赖什么信息?用户绝对坐标其实没那么重要,重要的是相对距离或者信道状态等级。
3.3 动作空间设计:联合动作与飞行约束
每架无人机的动作定义为网格上的移动方向,经典四方向加一个悬停:上、下、左、右、原地不动。两架无人机联合起来就是5×5=25个动作。如果地图不大,网格较粗,可以用四方向不加悬停,联合动作16个。
动作空间设计里最容易被忽略的是飞行约束。网格移动隐含了一个速度假设:一个时隙无人机只能移动一个网格,对应实际飞行速度约为网格边长除以时隙长度。如果你网格边长是200米,时隙长度是1秒,那无人机速度是200m/s,明显不合理。所以网格设计和时隙长度要匹配现实参数,仿真里虽然默认无人机可以任意移动,但约束始终要存在。
我建议初始化时把地图大小、网格边长、时隙长度、飞行速度这几个参数放在一起计算,保证从位置A移动到位置B的动作在时间上是可行的。
3.4 奖励函数:从单指标到多指标权衡
奖励设计决定了Q-Learning学出来的策略是什么样的。如果你只奖励系统总速率,学出来的策略很可能牺牲掉远距离用户,把所有资源倾向近处用户,导致“用户公平性崩塌”。如果你只奖励最小用户速率,总速率又会受限。我的设计是三个项的加权求和:
第一项是当前时隙NOMA配对下的系统总吞吐量,归一化处理;第二项是用户间的最小速率,用指数函数或对数函数压缩后加入,保证公平性;第三项是惩罚项——无人机飞出地图边界、两架无人机距离过近(可能碰撞或互扰)、能耗过高都要扣分。
奖励加权的系数需要手动调整,没有通用最优值。一个可行的调法:先把总吞吐量单项跑通,记录奖励平均值;再加入公平性项,看最小用户速率有没有上升;最后加惩罚项,看有没有减少边界越界。逐项加,比一上来就设计复杂奖励函数更容易定位问题。
4. Matlab代码实现:从信道函数到Q-Learning主循环
4.1 信道与速率计算的底层函数
Matlab的实现核心是模块化。我最开始写的时候所有逻辑塞在一个脚本里,改一个参数要找半天,后来拆成函数文件,调试效率直线上升。信道函数这部分我建议独立写,输入是无人机坐标和用户坐标,输出是信道增益特征,包括LoS概率、路径损耗和最终的信道增益值。
function [g, LoS_prob] = uav_channel(uav_pos, user_pos, fc, h_uav) d = norm(uav_pos - user_pos); theta = atan2(h_uav, sqrt(sum((uav_pos(1:2) - user_pos(1:2)).^2))); LoS_prob = 1 ./ (1 + 28*exp(-11.2*theta)); PL_LoS = 20*log10(4*pi*d*fc/3e8) + 22.7 + 20*log10(fc/3e8); PL_NLoS = 20*log10(4*pi*d*fc/3e8) + 35.1 + 20*log10(fc/3e8); PL = LoS_prob*PL_LoS + (1-LoS_prob)*PL_NLoS; g = db2pow(-PL); end这段代码只是个框架,具体参数你要按自己的频段和场景调。它有个问题:小尺度衰落没加。实际仿真建议在信道增益上叠加瑞利衰落系数,否则结果偏乐观。瑞利衰落可以每次计算时用随机数重新采样,模拟快衰落。
4.2 NOMA配对与SIC解调顺序的实现
NOMA配对算法直接决定了速率的计算方式。配对的经典原则是“信道差异大的用户配在一起”效果更好,但实际上简单实现时也可以按固定规则配对,比如每架无人机服务的用户里选信道最好和最差的配对。SIC解调顺序记住一句话:先解强用户,后解弱用户。也就是说,接收机解码时首先解出信道质量好的用户的信号,解码成功后从叠加信号中抵消掉它,再解信道质量差的用户。
速率计算必须严格按SIC顺序来。弱用户的速率公式里,分母要包含强用户的功率作为干扰;强用户的速率公式里,弱用户的信号已经被消除,分母只有噪声。
function R = noma_rate(g_w, g_s, P_w, P_s, sigma2, B) % g_w: 弱用户信道增益, g_s: 强用户信道增益 % P_w, P_s: 两用户发射功率 % 强用户先通过SIC解码弱用户信号,再解码自己 R_weak = B * log2(1 + P_w*g_w / (P_s*g_s + sigma2)); R_strong = B * log2(1 + P_s*g_s / sigma2); R = [R_weak, R_strong]; end这里有个隐藏的坑:NOMA的总功率约束。两架无人机各自有功率预算,NOMA叠加传输时两用户的功率之和不能超过无人机总功率。如果你算完速率发现不管怎么飞都是低速率子用户拖后腿,先检查是不是功率分配系数根本没约束好。
4.3 Q-Learning训练主循环
主循环框架分两层:外层是训练episode循环,内层是时隙步进循环。每个episode开始时重置用户位置和无人机位置,然后逐步执行动作、计算奖励、更新Q表。
for episode = 1:max_episodes % 重置环境 users = generate_users(num_users); uav1_pos = randi([1, grid_size], 1, 2); uav2_pos = randi([1, grid_size], 1, 2); state = get_state(uav1_pos, uav2_pos, users); total_reward = 0; for t = 1:max_steps action = select_action(state, Q, epsilon); [next_state, reward] = step_environment(state, action, users); % Q-Learning更新 best_next = max(Q(next_state, :)); Q(state, action) = Q(state, action) + alpha * (reward + gamma * best_next - Q(state, action)); state = next_state; total_reward = total_reward + reward; end end这个框架对应中心化Q-Learning的核心:select_action返回的是联合动作索引,Q表存储的是联合状态、联合动作下的Q值。很多初学者在这写错,把它拆成两个独立的Q表分表,那就变成分布式了,问题回到前面说的非平稳陷阱。
4.4 ε-greedy与Q表更新的关键代码结构
探索策略用经典的ε-greedy,前期多探索、后期多利用。我建议ε的衰减设计成两段式:前20%的训练轮次保持ε=0.5到0.6,快速覆盖状态空间;之后按指数衰减到0.05以下。另外,矩阵索引访问Q表时,Matlab默认按列存储,Q表维度是[状态数, 动作数],Q(state, :)取当前状态的所有动作Q值,这个方向不要弄反。
Q表更新公式里的alpha学习率也值得注意。表格型Q-Learning一般是步长参数,通常在0.1到0.5之间。如果你的奖励数值比较大,可以先把奖励归一化到[-1, 1]区间,这样Q值的数值范围稳定,训练过程更平滑。gamma是折扣因子,一般取0.9上下,取太大会让算法只看远期收益,收敛变慢;取太小又变成近视策略,只关注当前时隙的吞吐量。
下面给一个更完整的ε-greedy动作选择函数示例:
function action = select_action(Q, state, epsilon) if rand < epsilon action = randi(size(Q, 2)); % 探索 else [~, action] = max(Q(state, :)); % 利用 end end5. 训练调试中的坑和实验结果
5.1 收敛性排查:奖励震荡、Q值爆炸
Q-Learning训练中最常见的问题是训练到后面奖励曲线一直在波动,没有丝毫收敛迹象。我在调试过程中遇到过一个非常隐蔽的错误:计算奖励时不小心把NOMA功率参数写反了,导致奖励和动作之间没有任何一致性,算法自然学不到东西。排查顺序建议是:先固定决策策略多跑几轮,看看奖励的计算是否稳定;再检查状态转移是否正确;最后才怀疑Q-Learning参数。
Q值爆炸通常是奖励设计的问题——某个动作产生的奖励数值太大,或者奖励存在循环区域导致Q值持续累加。解决办法是给Q值设置边界,或者对奖励做clip。另外如果你发现Q表里有大量条目的数值完全没更新,说明这些状态根本没被探索到,这时应该提高探索概率,而不是增加训练次数。
5.2 与贪婪算法的对比实验
路径优化方案的效果要有参照物才能说明问题。我做的对比实验包括三种方案:随机飞行、贪婪决策(每时隙选择让当前总吞吐量最大的位置)、中心化Q-Learning。评价指标是平均总吞吐量和最差用户吞吐量。
实测下来,中心化Q-Learning在迭代几轮之后,平均总吞吐量比随机飞行高30%到40%,比贪婪策略高10%到15%。贪婪策略的问题是“短视”——它只关心当前时隙的吞吐量,经常会飞到某个局部最优位置然后停在那里,当用户分布的加权质心变化时会错过更好的全局路径。Q-Learning因为有折扣因子的存在,会把未来时隙的收益也考虑进去,所以路径整体更平滑。
公平性指标的对比差距更大。贪婪策略几乎必然牺牲远处的小用户,中心化Q-Learning则能在奖励函数公平性项的引导下平衡远近用户的服务质量。这也印证了奖励函数里公平性项的必要性。
5.3 参数调试经验
几个关键参数我实测过一轮,总结成表:
| 参数 | 推荐范围 | 影响 |
|---|---|---|
| 学习率alpha | 0.1~0.3 | 太大易发散,太小收敛慢 |
| 折扣因子gamma | 0.85~0.95 | 大小决定策略前瞻性 |
| 探索系数epsilon初始 | 0.5~0.7 | 前期探索覆盖率 |
| 网格边长 | 100~250米 | 影响飞行约束和信道模型 |
| 奖励权重系数 | 扭距法逐项调 | 需根据指标曲线反复调整 |
| 用户数 | 4~8 | 增多会压缩Q表可用状态 |
这里面最花时间的还是奖励权重。我采用的做法是固定其他权重单独调一个,观察对应指标曲线变化。调总速率项权重时看总吞吐量,调公平性项权重时看最差用户吞吐量,调边界惩罚项时看越界次数统计。单个调好后再组合,最后微调。
5.4 代码可扩展方向
如果你的目标是基于这个话题发论文或做项目,有两条扩展路径很自然。一条是把Q-Learning换成DQN,把离散状态映射成连续输入,这样用户坐标就不用离散化了,状态表达精度会高很多,代价是训练时间明显增加。另一条是把中心化改成集中训练、分散执行(CTDE)框架,训练时用全局状态,执行时每架无人机只用局部观测,这样更接近真实系统的应用场景。
另外NOMA配对和功率分配也可以动态优化而不固定。当前代码里功率分配系数是预设的,你完全可以把它作为一个连续变量同时优化,或者用一个简单的贪心策略动态调整。这些扩展都会提升效果上线,但核心框架仍然是这套状态-动作-奖励的建模思路。
6. 最后再说几句项目里学到的体会
仿真做完整个人对强化学习的认识比看书深刻太多。Q-Learning虽然简单,但它把强化学习的核心逻辑展示得非常清楚:状态怎么抽象、动作怎么定义、奖励怎么设计,三者加起来几乎决定了算法的上限。算法本身反而是最不值钱的部分,一个标准Q-Learning更新公式五行就写完了,真正花时间的是对问题的建模和对环境写错的排查。
这套代码给更多人复现时遇到最多的反馈是“奖励不收敛”,绝大部分都是信道模型写错或者NOMA速率公式里SIC顺序弄反。我自己的排查建议是:先把每一步的奖励值打印出来,手工算一遍几个典型状态下的预期速率,对照代码输出。对上了再训练,对不上就先别急着跑训练。
后续如果有机会,我打算把这套框架扩展到三架无人机的场景,顺便换成CTDE结构,用DQN当策略网络。两架飞机的中心化Q-Learning是特别好的起步训练场——规模不大,可控性强,踩坑成本低,往哪个方向扩展都有路。