1. 项目场景与整体方案设计最近在整理无人机通信系统仿真这块的工作花了三个多月把一套基于Matlab的无人机基站场景完整跑通了核心链路包括基站与用户的几何分布建模、莱斯信道生成、NOMA下行功率分配、SWIPT能量与信息同传的速率评估最后还加了一层粒子群优化PSO沿着无人机的预定航线逐点寻优功率分配。整体做下来最大的感受是通信算法本身不难难的是把信道-资源分配-优化这条链路串起来让每一层的结果都能对得上。做这个课题之前我要说明一下场景背景。传统的地面基站覆盖范围固定、部署受地形限制无人机作为空中基站能够灵活机动特别适合临时热点覆盖、灾害应急、偏远地区补盲这类场景。但空中基站带来了一个很实际的问题信道特性和地面蜂窝网差别很大。无人机高度一般从几十米到两百米不等对地面用户的仰角变化剧烈视距链路占比高和传统地面信道的瑞利弥散特性完全不同这时候用莱斯信道模型描述空对地链路就比瑞利信道合理得多这是整个仿真的前提。再看为什么要在无人机通信里做NOMA。NOMA的核心思想是允许同一个时频资源块上叠加多个用户信号接收端通过串行干扰消除SIC区分不同用户相比正交多址可以明显提升频谱效率和用户接入数。无人机覆盖范围内的地面用户数量有限但分布不均匀用NOMA做功率域复用很自然。但NOMA的功率分配是一个典型的多约束优化问题信道差异大的用户怎么分配功率直接决定系统速率和公平性这就需要优化算法介入。SWIPT引入是另一个现实需求。无人机基站长期悬停或巡飞功耗是硬约束如果地面用户设备本身电量紧张传数据的同时传能量就很有吸引力。SWIPT允许接收机从射频信号中同时提取能量和信息有三种典型架构时间切换TS、功率分割PS、天线切换AS我在仿真里用的是PS架构。加上SWIPT之后系统模型多了一个能量收集约束速率评估也从只看通信速率变成了通信速率与能量收获的权衡。最后说粒子群优化在这个项目里的角色。沿无人机路径执行资源分配本质上是把路径离散化成若干航点在每个航点位置上重新计算信道、重新分配功率。随着航点变化信道增益、用户间干扰都在变最优功率分配需要实时更新。传统穷举法计算量太大凸优化工具箱在手写约束不友好的时候也麻烦粒子群这类启发式算法处理非凸目标函数非常快实现也简单几个参数调好之后效果很稳定。我在整个项目里沿着模拟生成的一条多边形路径依次跑了300个航点的PSO每个航点都重新初始化种群并寻优整个过程不到十五分钟就能跑完这个效率是凸优化方案比不了的。2. 信道建模与几何结构从坐标到莱斯系数的完整流程2.1 基站与用户的空间几何是怎么搭出来的几何建模是整个仿真的地基。这部分如果画得不对后面信道矩阵、路径损耗全是错的。我的做法是这样地面用户按照实际场景需求生成比如模拟一个街区共20个用户坐标在100米乘以100米的方形区域里均匀随机撒点每个用户高度取1.5米作为接收机高度。无人机作为空中基站初始位置放在区域中心上方高度我取120米加一条预定航线。航线需要体现无人机飞行轨迹对信道的影响我建议直接用参数化曲线生成航点序列最省事也最可控。比如用圆形路径半径80米、飞行高度120米、360度均匀取100个航点或者用多边形折线路径模拟巡检飞行。航点生成之后每个航点上无人机与每个用户之间的距离就是一个三维欧氏距离这个距离会进入路径损耗和莱斯信道计算的仰角估计。这里有一个容易被忽略的关键点路径损耗模型以及莱斯因子K实际上都受仰角影响。仰角越大代表无人机越接近用户头顶正上方视距路径越强莱斯因子越高。我的仿真代码里核心部分就是坐标生成和距离计算。参考设计如下% 用户坐标生成随机均匀分布 N_user 20; users_xy [100*rand(N_user,1), 100*rand(N_user,1)]; users_z 1.5*ones(N_user,1); % 接收机高度 % 全景坐标 user_pos [users_xy, users_z]; % 无人机圆形航线生成 N_waypoint 100; R 80; % 航线半径 h_UAV 120; % 飞行高度 theta linspace(0, 2*pi, N_waypoint1); theta(end) []; d0 [50, 50]; % 圆心 UAV_pos [d0(1)R*cos(theta); d0(2)R*sin(theta); h_UAV*ones(1,N_waypoint)];注意每生成一个航点坐标必须同时更新与所有用户的三维距离矩阵和高低角矩阵这些都会在莱斯信道生成中作为参数使用。关于几何结构还有一点值得专门提用户的密度分布和信道差异直接决定了NOMA的增益大小。如果所有用户挤在一起信道增益差别不大NOMA叠加的增益就很小反过来用户越分散信道差异越大NOMA的功率分层越明显系统增益越显著。所以做性能对比的时候不光要改算法还要改用户分布做敏感性分析这样得到的结论才完整。2.2 莱斯信道视距分量加散射分量的Matlab生成在空对地链路中信道通常建模为莱斯衰落而非瑞利衰落。原因是在高仰角、低高度条件下无人机与地面用户之间存在较强的视距传播路径接收信号中除了大量散射多径分量之外还有明显的直射分量。莱斯K因子就是直射分量功率与散射分量功率之比。莱斯信道在Matlab里有现成的函数比如ricianchan或者通信工具箱中和信道模型相关的一系列函数但我觉得直接用手动构造向量引入K因子的方式写一次还是很有必要的因为能更清楚看到每一路系数是怎么来的。我的实现思路是小尺度衰落信道系数由视距分量和散射分量相加得到散射部分用复高斯随机变量生成视距部分用确定性相位保证LOS路径最后除以根号下1K做功率归一化。信道大尺度部分单独乘路径损耗。参考实现% K因子随仰角变化 K_dB 5 (elev/30)*8; % 仰角0°时K5dB30°以上K13dB线性映射 K 10^(K_dB/10); % 转换为线性值 % 可选方案直接使用固定K值 % K 10; % 10dB典型空对地场景 % 散射分量复高斯 scatter_component (randn(1,1) 1i*randn(1,1))/sqrt(2); % 视距分量确定相位可以随机生成初始相位 q 2*pi*rand(1,1); los_component exp(1i*q); % 归一化莱斯信道系数 h sqrt(K/(K1))*los_component sqrt(1/(K1))*scatter_component; % 加入大尺度路径损耗 pathLoss_dB 20*log10(4*pi*fc*dist/3e8) ... 0.5*(distdist_crossover)*10; % 简化两段式斜率 channel_coeff h / sqrt(10^(pathLoss_dB/10));这里要特别提醒一个很常见也很隐蔽的Bug如果不做归一化也就是漏乘sqrt(K/(K1))之类的缩放因子生成的信道功率既不是K1也不是固定值会直接干扰后面SINR的计算。另外K因子随仰角变化的映射关系也有讲究空对地模型里一般低仰角时K因子介于0到5dB高仰角时可以达到10dB以上如果你用的参数是完全固定的不同航点之间的信道差异就体现不出来PSO寻优得到的功率分配结果会变得很平缓看不出算法的效果。我在仿真里还会做一个关键操作每个航点上都要重新生成一次信道系数。原因在于无人机移动导致空间位置变化信道实现也随之改变。航点间距一般取几米到十几米飞完一个航点后信道的空间相关性其实很强严谨的做法是用相关矩阵处理但简化场景里直接重新采样也合理至少趋势一致。如果想做更严谨的版本可以用包含空间相关性的信道模型比如在生成信道系数时加入相邻航点的相位相关性但我个人觉得在资源分配这个研究目标里逐点独立重采样已经足够说明问题。3. NOMA功率分配与SWIPT速率评估3.1 NOMA叠加编码和SIC解调顺序NOMA在这个系统的设计里并不复杂核心流程是发射端做叠加编码接收端做串行干扰消除。下行NOMA里基站向多个用户发送叠加信号每个用户接收到的都是完整叠加信号SIC解调时用户按信道增益排序信道好的用户后解码先解别人的信号再解自己的信道差的用户先解码因为它的信号功率分配通常更高优先被解出来。SIC顺序必须严格遵守信道增益从小到大解码的原则这是教科书结论但实际仿真里大多数人都会在排序这一步犯迷糊。我写了一个标准的用户排序逻辑% 用户按信道增益降序排列增益高的排在前面 [~, sort_idx] sort(channel_gains, descend); % sorted_idx(1)是信道最好用户 % SIC: 用户1先解用户2,3,...,N的信号并剔除再解自己功率分配这里我给两种不同方案做对比。第一种是固定功率分配FPA按比例因子分给用户简单稳定但没法自适应第二种是优化分配也就是后面PSO要干的事。固定分配里最经典的是逆信道增益规则信道差的用户分配更多功率。比如两个用户信道增益分别是a1和a2其中a1大于a2那么功率分配大致按照P2大于P1来配。用NOMA的SIC约束做检验如果信道好的用户分配的功率过高它先解不出弱用户的信号SIC直接失败速率会变成负值这是仿真里最常见的崩溃点之一。3.2 速率公式推演与含/不含SWIPT的差异不含SWIPT时的NOMA用户速率推演假设用户i在第m个子信道上信道增益为hi系统总带宽分成M个子信道每个子信道功率为P用户i分到的功率系数为αi叠加信号的用户间干扰来自其他用户功率。用户经过SIC后如果把自己前面的用户信号都解调并减掉了面对的干扰只来自信道比自己更差的用户在解码自己时还没有被剔除的那些信号用户的信干噪比计算如下SINR_i αi * P * |hi|^2 / (|hi|^2 * sum(αj*P, j比i差) σ^2)速率则是R_i B * log2(1 SINR_i)加入SWIPT之后接收机不再把所有信号功率都用于信息解码而是按照PS比例ρ把一部分功率分给能量收集电路。也就是说信息解码部分实际得到的功率只有(1-ρ)*P_total。系统速率公式变为R_i(SWIPT) B * log2(1 (1-ρ)*αi*P*|hi|^2 / ((1-ρ)*|hi|^2*sum(αj*P, j比i差) σ^2))能量收集部分收获的功率是E_i η * ρ * (αi*P sum(αj*P, j ≠ i)) * |hi|^2可以看出ρ越大收集的能量越多但信息速率越低这是一个典型的折中。我在仿真中采用PS架构ρ设为0到1之间的值通常取0.3到0.6区间做对比。这里我实际跑出来的结果很直观不含SWIPT时系统总速率最高加入SWIPT后如果ρ设置过大大概率出现某个用户的SINR低于SIC的解码门限系统速率会急剧下滑。我在多组实验里对比了ρ0.1、0.3、0.5三档ρ0.5时最大速率损失大约三成但换来了额外的能量收集。下面这个表是我仿真时的典型结果同一航点PSO优化后的功率分配方案用户1速率(Mbps)用户2速率(Mbps)总速率(Mbps)收集能量(mW)不含SWIPT8.524.1312.650SWIPT ρ0.27.913.7611.6724.3SWIPT ρ0.55.842.528.3657.8从结果可以明显看到ρ增大后总速率下降但能量收集量增加。实际系统设计时ρ的取值和其他参数的耦合是很紧的不能只看总量。比如在某些航点上信道差的用户本来功率占比就高如果ρ再调大SIC解调会直接失败。3.3 SWIPT加入后功率分配约束的变化SWIPT改变了的不只是速率表达式还有整个功率分配的可行性区域。普通NOMA的约束只有功率非负、功率之和受限、满足SIC条件而SWIPT多了一个很实际的问题能量收集电路需要输入的RF功率不低于某个门限才能有效整流。这意味着单个用户分配的功率不能无限低否则能量模块不工作。功率分配优化问题里多了能量约束粒子群寻优时目标函数里必须加入罚函数不然粒子很容易飞出可行域。我这里用的是外点罚函数法把能量约束的违反程度乘一个惩罚系数加到目标函数上。如果目标函数是最大化总速率那么对于违反能量约束的粒子目标函数会减去一个很大惩罚这个粒子在迭代过程中自然会被淘汰。4. 粒子群优化沿无人机路径执行的完整实现4.1 为什么选PSO而不是穷举或凸优化资源分配本质上是一个优化问题。NOMA场景里目标函数关于功率分配系数是非凸的用户间干扰项让问题变得更复杂。常见选择有三条路穷举搜索精度高但复杂度爆炸凸优化需要做变量替换和松弛处理才能套用现成求解器而PSO实现简单、不依赖凸性、收敛速度快在工程仿真里性价比最高。拿具体数据说话两个用户、单信道、功率系数从0到1、步长0.01穷举只需要100次计算还无所谓但用户数到5个一下子变成100的四次方量级搜索完全没法跑。PSO的种群规模设50到100个粒子迭代100到300次就能收敛到不错的解这个复杂度一直是可接受的。4.2 粒子编码与目标函数设计粒子群里的每个粒子的位置就是一组待优化的功率分配系数。我以两个用户为例粒子位置是一个二维向量[α1, α2]分别代表用户1和用户2的功率分配比例系数约束条件是α1α21且α1和α2都大于0。对于更多用户向量维度相应增加约束条件变成所有αi之和等于1。目标函数定义为系统总速率fitness sum(R_all); % 最大化总速率 % 如果含SWIPT还要把能量约束作为罚函数 penalty max(0, E_threshold - E_min_user) * C; % C为惩罚系数 fitness fitness - penalty;我在写目标函数时踩过一次坑就是约束条件的处理方式。一开始我直接在粒子初始化时强制α1α21这没问题但在迭代更新位置和速度之后新粒子的位置不再满足归一化约束这时必须先做投影把所有α除以总和再算适应度否则目标函数的值会失真。这个细节如果不处理PSO跑出来的结果会很不稳定。PSO的标准更新公式如下v_new w*v c1*r1*(pbest - x) c2*r2*(gbest - x); x_new x v_new;其中w是惯性权重c1和c2是学习因子r1和r2是0到1之间的随机数。我这里取w0.8c1c21.5种群数80迭代数200。另外我做了速度钳位限制每个粒子的最大速度不能超过位置的动态范围的一半否则粒子飞得太快容易在起步阶段就错过最优区域。4.3 逐航点执行PSO的实现流程与加速技巧沿路径执行PSO的流程逻辑是这样的for 每个航点: 更新无人机位置 重新生成信道系数 重新计算路径损耗和仰角 初始化粒子群可以沿用上一航点的gbest作为当前初始种群的一个粒子 迭代PSO寻优 记录当前航点的最优功率分配和对应速率 保存结果 end我在测试中发现直接把上一航点的最优解带进当前航点的初始种群收敛速度会有提升大概能减少三成左右的迭代次数。原因是相邻航点的信道相关性让上一航点的解在当前航点依然是一个不错的出发点。为了进一步提升运行效率我做了两个优化。第一个是矩阵化运算所有用户的信道生成、速率计算都写成向量形式避免for循环逐用户逐粒子地算。第二个是提前预算信道因为信道在航点上已经固定PSO的每代迭代中只需要更新功率系数并重新算SINR信道增益部分可以预先存储为常量每次只做乘法和log运算计算量会小很多。整个仿真在普通台式机上100个航点、80个粒子、200次迭代总耗时大约五分钟。如果不做矩阵化用嵌套循环硬算可能要半小时以上。4.4 PSO结果的可视化与趋势分析跑完整个路径之后最重要的一件事是把结果画出来。我画了三张图第一张是系统总速率随航点变化的曲线第二张是PSO最优适应度收敛曲线第三张是单个航点下不同功率分配方案的速率对比柱状图。总速率随航点变化的曲线能直观看到无人机路径中哪些位置信道条件好、哪些位置差这是资源分配算法后验分析的重要依据。收敛曲线的意义在于验证粒子群参数设置是否合理如果收敛很慢甚至不收敛先怀疑惯性权重过大或者种群数太小。柱状图则是把PSO优化结果和固定功率分配、等功率分配拉到一起对比凸显算法的增益。我实测下来在20个用户、2个子信道的场景里PSO相对等功率分配能提升大约18%到25%的系统总速率。5. 常见问题与调试经验那些仿真里反复踩的坑5.1 信道系数维度错误这是Matlab仿真的第一个拦路虎。信道矩阵的维度取决于航点数量、用户数、子信道数量三个因素任何一个维度不匹配后续的功率分配和SINR计算都会报错或者结果错乱。我习惯在最前面用assert函数把尺寸断言写清楚assert(size(H,1)N_user size(H,2)N_subchannel, ... 信道矩阵维度错误);把调试前置远比运行时跟踪维度问题快得多。5.2 SIC解码顺序错误导致速率为负这个问题我调试了整整一个下午才定位。现象是某些用户算出来的SINR为负直接导致log2()的输入变成负数速率输出为NaN。根本原因是SIC解码时用户之间的排序和功率分配顺序不一致。功率分配如果按信道增益升序给功率但SIC逻辑里按降序处理两者一错位必然有个别用户解调失败。解决方式有两个一是严格按信道增益升序排序后给功率解码顺序和功率分配顺序保持一致二是在SINR求出后加一个下限判断低于某个门限的直接判定解调失败速率记0同时给出警告。5.3 粒子群早期收敛和局部最优PSO在这个项目里的最大坑就是早熟收敛。我最初把惯性权重固定为0.9收敛速度快但经常收敛到局部最优。后来改成线性递减策略从0.9降到0.4前30代全局搜索后面局部精化性能提升明显。另外学习因子c1和c2的取值也很关键c1太小会让粒子偏向群体最优多样性不足c2太小会让粒子偏向个人最优收敛缓慢。目前的主流经验值c1c21.5到2.0区间做成参数可调逐个试。5.4 SWIPT能量约束和SINR门限冲突SWIPT加入后最常见的现象是优化结果让信道好的用户几乎不分配功率因为它的干扰谱上总会解出弱用户的信号导致能量收获不足违反了能量约束。这时候我建议在目标函数里把能量不足部分作为罚函数加入但罚函数系数不能取得太大或太小。系数太大粒子会过度偏向满足能量约束而牺牲速率系数太小能量约束被无视。我的经验是罚函数系数至少要比最优速率值的量级高出一个数量级效果比较稳。另外还能在初始化时直接把能量约束作为硬性筛选条件只保留初始化时就能满足能量约束的粒子这种方式比罚函数更干净但如果约束太紧会导致初始种群过小、粒子多样性不足需要配合适当的放宽。5.5 仿真时间过长数据量大、航点多、粒子群体大的时候Matlab跑起来会比较慢。我实测的有效手段有三个第一把循环改成矩阵点运算这是提升最大的一步第二把与迭代无关的信道参数预先算好缓存减少重复计算第三如果不追求完美的实时性要求可以把迭代终止条件改成连续几代适应度变化小于某个阈值就提前终止不用硬跑满200代。5.6 功率归一化的强制约束最后想提醒一个非常隐蔽的问题粒子群迭代过程中粒子位置也就是功率分配系数会脱离所有系数之和为1的约束。如果不做归一化处理目标函数里的功率分配和实际不符结果完全不可信。我在每次迭代计算适应度之前都会强制做一次归一化alpha alpha / sum(alpha);这个操作简单但我见过好几个版本的程序里都漏了这行导致实验结果跟理论推导完全对不上。6. 实测路径结果与扩展方向在最终版本里我让无人机沿着一条包含直线段、转弯、爬升的简易航线飞完整个任务周期航线总长约3.5公里离散成150个航点。每个航点上跑一遍信道生成、PSO寻优、含与不含SWIPT的速率记录。结果趋势符合预期无人机飞越高、离用户群越近时信道条件越好系统速率越高转弯半径小的地方速率波动明显因为无人机大幅度转向时信道方差变大PSO需要更多迭代次数才能收敛到稳定值。还有一个有意思的对比是含SWIPT时最优功率分配结果会自动偏向让信道好的用户多分一点功率用来收集能量而信道差的用户则少分一点因为信道差用户的信息速率对功率更敏感。这个现象我之前没有预期到但跑出来的结果逻辑上很合理。如果后续继续扩展我打算做三个方向的深化第一把当前单无人机扩展成多无人机协作场景粒子群从单目标变成多无人机功率联合分配问题维度翻倍对PSO的适应性是个新挑战第二把PSO和深度强化学习做对比看看在动态信道下谁更稳第三在目标函数里加入用户公平性指标比如最大最小公平性原本只优化总速率加入公平性之后系统设计更贴近实际需求。这几个方向都可以复用现有的信道生成和SIC框架改动成本不大但研究价值能提升不少。最后分享一个我个人的调参心得PSO在这个场景里对初始种群的选择很敏感我试过随机初始化、基于等功率分配的初始化、基于上一航点最优解初始化三种方式最稳定的是第三种也就是把上一航点的最优解注入当前航点初始种群这样每个航点都不是从零开始摸索收敛速度和稳定性都明显改善。如果你也在做沿路径的序列优化任务不妨试试这个技巧。