ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于深度强化学习D3QN的无人机三维路径规划与SNARM联合优化

基于深度强化学习D3QN的无人机三维路径规划与SNARM联合优化 简介面向无人机自主导航与通信测绘交叉研究这份深度学习源码包聚焦三维路径优化难题以双竞争深度Q网络D3QN为基础结合多步学习机制提升训练效率并进一步提出三维同步导航和无线电测绘SNARM框架实现导航与无线环境感知的协同。代码共16个文件其中14个Python脚本覆盖算法主程序、仿真环境生成、无线电地图构建、结果绘图与模型测试另含说明文档与授权码文件压缩包仅92KB轻量易部署。项目已通过测试运行按26方向与14方向两种动作空间分别提供完整实现适合人工智能、通信工程、自动化等专业学生用于毕业设计、课程设计或算法对比实验。目前已有60人学习下载对于希望快速复现DRL无人机路径规划、扩展多步学习或SNARM相关研究的读者这份资料提供了清晰可直接改写的代码基线也便于在此基础上二次开发。1. 无人机3D路径优化为什么绕不开DRL与D3QN在三维环境中给无人机找一条能绕开障碍、又能兼顾无线信号测绘的路径不能只靠A*或RRT这类确定性搜索。基于深度强化学习DRL的方案把路径优化建模成序列决策而D3QN算法——Double DQN与Dueling Network的组合——刚好适合离散3D网格。进一步结合多步学习能缓解奖励延迟三维同步导航和无线电测绘SNARM则将任务从单目标扩展到联合优化。下面按“网络选型 → 训练实现 → 框架扩展 → 验证上线”的顺序把这条技术路线讲成可以直接落地的方案。拿到源码包后建议先定位环境类、网络类、训练循环和评测脚本这四块按这个顺序去读效率最高。2. D3QN在3D网格路径规划中的原理与行动空间设计2.1 从DQN到D3QN为什么同时需要Double DQN和Dueling Network基础DQN的问题在于Q值估计会系统性偏高。训练时在线网络既要选出“看起来最好”的动作又用同一个动作的最大Q值做目标评估误差会通过自身的argmax不断被放大。Double DQN把选择动作拆给在线网络把计算Q值拆给目标网络这样即使在线网络偶尔高估某个动作目标网络给出的估值也不会立刻跟着偏。Dueling Network则是从网络结构上改进同一个state下的所有动作共享一个状态价值输出动作优势分支只负责修正“这个动作比平均水平好多少”。因为三维网格飞行中大部分节点都是“可接受”的只有少数需要急转、避障的节点才是真正的决策点这种分解让价值学习更稳定。D3QN就是把两个改进合进一个网络。forward的最后一层这样组织状态价值V是标量动作优势A是维度等于动作数的向量每个动作的Q值等于V A - mean(A)。减去均值的原因是不减去均值同一个Q值可以由无数种V和A组合生成梯度更新方向会被随机性支配。下面是实现这个结构的最小网络输入是体素化的3D栅格注意这里用的是Conv3d而不是Conv2d。import torch import torch.nn as nn class D3QNNet(nn.Module): def __init__(self, in_channels, num_actions): super().__init__() self.conv nn.Sequential( nn.Conv3d(in_channels, 32, kernel_size3, padding1), nn.ReLU(), nn.Conv3d(32, 64, kernel_size3, padding1), nn.ReLU(), ) self.pool nn.AdaptiveAvgPool3d((4, 4, 4)) self.fc nn.Linear(64 * 4 * 4 * 4, 256) self.value_head nn.Linear(256, 1) self.adv_head nn.Linear(256, num_actions) def forward(self, x): x torch.flatten(self.pool(self.conv(x)), 1) x torch.relu(self.fc(x)) v self.value_head(x) a self.adv_head(x) return v a - a.mean(dim1, keepdimTrue)代码里pool用自适应池化把任意尺寸的输入体素压到4×4×4这样换地图尺寸时不用改网络。输入x的形状是(batch, channels, depth, height, width)通道数由下面要说的栅格图数量决定。num_actions是离散动作数对应无人机每个时间步可选的移动方向数。2.2 3D状态空间、离散动作空间与奖励函数设计先把连续环境体素化。比如把无人机工作空间切成16×16×8的网格每个格子对应真实空间1米。状态输入我通常会堆叠四个通道占据栅格1为障碍、目标方向热力离目标越近值越大、已访问标记记录哪块飞过、无线信号均值估计。如果做SNARM还要把信号估计方差作为第五通道。这样状态张量就是4到5通道的3D数组。动作空间最简单的定义是27邻域移动即从当前格向相邻26格移动或原地停留。动作数就是27。这个空间定义直白缺点是训练初期探索效率低后续再换成分层动作先选方向再选速度优化能耗。奖励函数直接决定了策略风格。我一般用四个分量组合reward 10.0 * done_goal - 1.0 * done_crash - 0.05 * (dist_before - dist_after) 0.02 * coverage_gaindist_before和dist_after是本步开始和结束时与目标的欧氏距离差值大于0说明在靠近给正奖励等于给一个稠密引导避免只有到达目标时才有反馈。coverage_gain是本步新访问的网格数引导无人机扩大巡航范围。这个公式里导航占主要权重测绘只起辅助作用。如果只做纯路径规划可以去掉 coverage_gain 并把信号通道置零。状态通道维度说明占用图1×D×H×W有障碍置1可飞置0目标方向图1×D×H×W到目标距离的倒数越小越远已访问计数1×D×H×W每访问一次加1信号均值/方差2×D×H×W只开SNARM时加入D×H×W是环境网格尺寸。表格里的每个通道都要做归一化尤其是目标方向图建议除以最大距离让数值落在0~1之间否则网络前几层梯度容易爆炸。2.3 训练循环与经验回放的关键细节训练循环可以按标准实验框架来搭但有三个三维环境特有的细节要先处理。第一个是碰撞终止后的transition处理碰撞那一步的done要置为True同时还要保留该transition用于多步学习截断。第二个是目标网络更新硬更新每500步复制一次软更新用0.005系数。第三个是回放池容量3D状态每跳存储量比2D大很多建议先按500 k条设计内存溢出时优先降低batch size而不是池子。Double DQN的目标值计算如下这里online_net选动作target_net估值with torch.no_grad(): next_actions online_net(next_states).argmax(dim1, keepdimTrue) next_q target_net(next_states).gather(1, next_actions).squeeze() target rewards gamma * (1.0 - dones) * next_qrewards是单步奖励gamma取0.95。loss推荐用smooth_l1_loss而不是MSE因为稀疏大奖偶尔会出现大数值Huber损失对这类离群值更平滑。这个循环能跑通之后再接入下一章的多步学习。3. 多步学习在D3QN中的接入方式与参数影响3.1 多步回报为什么适合无人机路径规划无人机路径规划的奖励稀疏性不只体现在“到达目标”还体现在“绕过障碍”这个动作上。无人机在障碍前绕行的收益通常要等绕过障碍后才能看到如果只采样单步transition网络在障碍前那个动作的Q值更新非常微弱。多步学习把连续n步的奖励累计成一次目标值能让这个延迟反馈提前n步传导给决策者。这里n一般取3到5距离短的小地图取3地图大或奖励稀疏取5。n太大时累计回报包括了很多旧策略下的状态目标值方差上升训练曲线容易反复横跳。3.2 在D3QN里实现n-step采样并修正目标值实现多步学习需要在经验回放里保存“连续transition片段”而不是单独保存每个transition。常见做法是给每个episode开一个长度为n的滑动窗口每产生新transition就尝试组装一次样本。组装时需要先算累计回报再判断终点是否有效终止def build_n_step_sample(trajectory_segment, gamma): n len(trajectory_segment) - 1 returns 0.0 for i, trans in enumerate(trajectory_segment[:n]): returns gamma**i * trans.reward if trans.done: return returns, None, True # 提前终止 terminal_trans trajectory_segment[n] return returns, terminal_trans.next_state, False返回的terminal_trans.next_state就是第n步之后的状态用来计算自举项。如果中间有done就不能继续向后自举这也是n-step和普通TD最大的区别。组装好样本后目标值用原来的Double DQN公式只把单步奖励换成累计回报把s_{t1}换成s_{tn}final_state sample[terminal_state] with torch.no_grad(): final_action online_net(final_state).argmax(dim1, keepdimTrue) n_step_target sample[returns] gamma**sample[n] * (1 - sample[done]) * \ target_net(final_state).gather(1, final_action).squeeze()注意这里done是第n步时的终止标记不是样本中间某一步的终止标记。我把提前终止的样本在build_n_step_sample里直接返回doneTrue累计回报也只算到终止步这样不会把障碍物后面的虚拟状态拉进目标值。3.3 n步数、折扣因子和回放缓冲区的配合多步学习有三个超参数要联动调整不是单独调n就行。n增加后累计回报包含的未来步数更多如果再沿用偏大的γ远处的目标影响会被过度放大。所以我的经验是n从3提到5时γ从0.97降到0.93左右。训练震荡时优先降γ不要先动nn是结构性参数改一次要重跑很多实验。参数建议初始值调参优先级n-step4先固定最后调折扣因子 γ0.95震荡时优先降回放池容量500000条按内存上限分配batch size64显存不足时减半目标网络软更新系数0.005多步学习下可降到0.003梯度裁剪max_norm10出现Q值爆炸时开启回放池和多步学习的配合要留意样本陈旧问题。n-step样本是用当前网络采样后过了一段时间才被训练的轨迹里的策略和目标网络的策略可能已经差了一代。这时用优先经验回放会放大陈旧样本的影响。我建议第一版实现用均匀采样确认曲线稳定后再加PER加PER时要给每条样本打上采集时的全局步数按“全局步数越新优先级越高”做一个软衰减。4. SNARM框架三维同步导航与无线电测绘的联合优化4.1 SNARM的联合状态表示与数据流SNARM把“导航”和“无线电测绘”放进了同一个决策闭环。普通路径规划把无线信号观测当成固定的先验地图而SNARM假设信号场完全未知无人机一边飞行一边采样同时更新一张信号均值和方差估计。方差大说明该区域测量少方差小说明已经测过。干扰下无人机的导航策略必须决定是先扫清附近的未测绘区域还是直奔目标点。这一章讲怎么把这个联合决策装进D3QN的状态和奖励里。状态表示在原有四通道基础上加入“信号估计方差”变成五通道。输入网络前占用图和信号图使用不同的编码分支。原因是占用图的结构性很强适合用卷积直接学信号图是连续标量场方差图里含大量不确定性两者如果共用底层卷积信号图的抖动会被误判成障碍物特征。具体实现class SNARMEncoder(nn.Module): def __init__(self): super().__init__() self.geo_encoder nn.Sequential( nn.Conv3d(1, 32, 3, padding1), nn.ReLU(), nn.Conv3d(32, 64, 3, padding1), nn.ReLU(), ) self.rf_encoder nn.Sequential( nn.Conv3d(2, 32, 3, padding1), nn.ReLU(), nn.Conv3d(32, 64, 3, padding1), nn.ReLU(), ) self.fusion_conv nn.Conv3d(128, 128, 3, padding1) def forward(self, occ, rf_mean, rf_var): geo_feat self.geo_encoder(occ) rf_feat self.rf_encoder(torch.cat([rf_mean, rf_var], dim1)) return torch.relu(self.fusion_conv(torch.cat([geo_feat, rf_feat], dim1)))occ是形状(batch, 1, D, H, W)的占用栅格rf_mean和rf_var各自是(batch, 1, D, H, W)二者先在通道维拼接成两通道再进入rf_encoder。双分支输出拼到128通道后用一个融合卷积把几何特征和信号特征合并。模块替换第2章的D3QNNet中的卷积主干时注意最后的AdaptiveAvgPool3d要放在fusion_conv之后。4.2 奖励函数如何同时驱动导航和测绘SNARM的奖励函数是第2章公式的扩展核心改动是把“信号方差下降量”写进奖励。当前步无人机访问的区域集合记为S该区域内每个网格的方差从σ_before[i]降到σ_after[i]测绘增益按所有被访问网格的方差减少量求和。总奖励写成map_gain sum(max(0, sigma_before[i] - sigma_after[i]) for i in visited_cells) reward nav_reward map_weight * map_gainmap_weight取0.1左右导航奖励仍占主导。max(0, ...)防止环境估算误差导致负增益干扰训练。如果方差已经从很大降到很小再访问同一点也不产生收益无人机就自然扩散到未探索区域。奖励分量表达式初始权重作用到达目标1010给出稀疏的目标导向碰撞惩罚-11安全底线距离变化-(dist_before - dist_after)0.05稠密近距离引导覆盖增益visited_cells0.02扩大探索范围测绘增益map_gain0.1SNARM核心引导信号测绘这五个分量一起放进经验回放时绝对值差距很大。10的到达奖励会把其他小奖励淹没训练初期是好事但到了后期距离变化项的作用会被冲淡。我习惯在训练中期把到达奖励从10降为5或者把距离权重从0.05升到0.1让细粒度引导逐渐起作用。调节的时机以“到达率先升到0.5后再开始微调”为准。4.3 SNARM在仿真训练中的评价指标单独看导航到达率不够要同时看测绘质量。下面是一组和SNARM任务强绑定的评价指标每个训练检查点都跑50个episode统计一次。指标计算公式参考合格线到达率到达目标数 / 总episode数0.9简单图、0.6复杂图路径长度比实际飞行网格数 / 最短可行网格数1.3地图重建MAE预测RSSI与真实RSSI差的绝对值平均随信号模型变化只比下降趋势覆盖率访问网格数 / 可行网格总数0.8测绘方差下降率1 - 平均σ_after / 平均σ_before0.7到达率和覆盖率要成对看。如果到达率98%但覆盖率只有40%说明无人机完全不关心测绘SNARM退化了反过来覆盖率90%但路径长度是最短路径的2倍说明它在无脑扫图。真正理想的曲线是早中期覆盖率快速上升后期路径长度比缓慢回落到1.2以内。这两个指标不一致时优先调整map_weight。5. 验证与落地用固定地图回归避免“看起来收敛但实际过拟合”DRL实验里最迷惑人的情况是平均奖励随训练稳步上升换一张地图后立刻现原形。原因通常不是算法不收敛而是模型记住了当前地图的障碍位置和目标点。为了能尽早发现退化我会在一开始就固定三张地图一张开阔图一张密集障碍图一张含无线电站点阴影的SNARM图。训练过程中每隔1000步跑一次离线评测把关键指标写入CSV。python evaluate.py \ --map fixed_urban.npy \ --n_episodes 50 \ --checkpoint runs/best.tar \ --output eval_result.csvevaluate.py必须做三件事把网络切到eval()模式关闭经验回放用epsilon0做贪心决策不让探索动作污染路径长度记录每个episode的轨迹、终止原因和covered_grids。特别注意epsilon0否则验证结果始终带随机性和训练曲线没有办法对齐。回归测试最好和三个基线对比随机策略、RRT在同一栅格地图上的平滑路径长度、去掉多步学习和测绘奖励的纯D3QN。对比RRT时要先把RRT输出路径做线性平滑再计算长度否则栅格步进的锯齿会让长度虚高对比结果不公允。除了统计指标建议每个验证episode都保存轨迹点坐标。只看平均奖励看不出策略是否在几个格子之间振荡画出轨迹后绕圈、抖动、贴着障碍边界频繁转向这些问题一眼就能发现。配合轨迹输出还要单独保存信号估计方差随时间的变化曲线。方差下降太慢说明无人机在过早回避未测绘区域该加重测绘奖励方差下降很快但路径长度飙高则说明测绘项压过了导航项。观察这条曲线比直接看地图重建MAE更能提前发现联合优化失衡。最后仿真环境的无线电站点位置一定要随机化。固定的发射器坐标会让模型最终记住信号场的“标准答案”在SNARM测试里尤其明显。每个训练会话重新生成发射器位置但保留三个固定地图做回归随机环境下到达率如果能稳定爬到90%以上才说明模型学到的是“测绘驱动的导航”而不是死记地图。用这套检查清单替换朴素的loss曲线监控至少能提前一个迭代发现策略退化问题。本文还有配套的精品资源点击获取
返回列表