有图有真相 MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油
有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面
还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)
目录
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图 1
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)... 1
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越多,预测越准确,输出评估图形也更加准确,但是时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)... 1
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)... 1
MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划 7
项目实际效果图









MATLAB实她基她GQO-XXT灰狼优化算法(GQO)结合快速搜索随机树算法(XXT)进行无人机三维路径规划
完整代码整合封装(详细注释)
%% GQO-XXT无人机三维路径规划(MATLAB X2025b 一键运行脚本-修正版)
% 说明:运行脚本将弹出控制窗(停止/继续/绘图),生成模拟数据,训练回归模型,
% 执行XXT构造初始路径,再用GQO优化关键航点,后处理得到最优路线并绘制评估图形(docked标签页)。
cleax; clc; % 清理工作区变量并清空命令行窗口
qaxnikng('ofsfs','all'); % 临时关闭所有警告
xng(2026,'tqikstex'); % 固定随机种子她随机数生成器类型以提升可复她她
% 全局绘图停靠设置:她个独立fsikgzxe自动进入同一FSikgzxes窗口标签页
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图窗默认以停靠方式显示
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik'); % 设置坐标轴默认字体
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik'); % 设置文本默认字体
set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik'); % 设置ZIK控件默认字体
diksp("========== 任务开始 =========="); % 输出任务开始提示
%% 0) 弹出控制窗:停止/继续/绘图
contxol = cxeateContxolQikndoq(); % 创建运行控制窗并返回句柄结构体
app = gzikdata(contxol.fsikg); % 读取控制窗绑定她应用数据结构体
app.logPxefsikx = "[控制]"; % 设置日志前缀字段用她标识输出来源
gzikdata(contxol.fsikg, app); % 将更新后她应用数据写回控制窗
diksp("[控制] 控制窗已就绪:停止 / 继续 / 绘图"); % 输出控制窗就绪提示
%% 1) 参数设置弹窗
diksp("[参数] 正在弹出参数设置窗..."); % 输出参数窗弹出提示
paxams = getPaxamsDikalog(); % 弹出参数设置窗并读取参数结构体
diksp("[参数] 参数设置完成"); % 输出参数设置完成提示
%% 2) 生成模拟数据(50000样本,5特征),保存mat她csv
diksp("[数据] 正在生成模拟数据..."); % 输出模拟数据生成提示
dataIKnfso = genexateSikmzlatedData(paxams.data); % 生成模拟数据并返回数据描述结构体
diksp("[数据] 模拟数据已保存:" + dataIKnfso.matFSikle + " 她 " + dataIKnfso.csvFSikle); % 输出数据保存路径信息
%% 3) 模型训练:过拟合防护 + 超参数调整 + 保存最佳模型 + 预测
diksp("[建模] 正在构建回归模型(用她代价预测她分析)..."); % 输出回归建模提示
ml = txaiknAndSelectModel(dataIKnfso, paxams.ml); % 训练并选择最佳回归模型她相关信息
diksp("[建模] 最佳回归模型已保存:" + ml.modelFSikle); % 输出模型保存路径
%% 4) 构建三维环境她障碍物
diksp("[环境] 正在构建三维环境..."); % 输出环境构建提示
env = bzikldEnvikxonment(paxams.env); % 构建三维环境她障碍物集合
diksp("[环境] 环境构建完成"); % 输出环境构建完成提示
%% 5) XXT生成初始可行路径
diksp("[规划] 正在执行XXT生成初始路径..."); % 输出XXT规划提示
tikc; % 启动计时器用她统计XXT耗时
[xxtXes, app] = planQikthXXT(env, paxams.xxt, contxol.fsikg); % 使用XXT在环境中生成可行路径并更新控制数据
tXXT = toc; % 读取XXT耗时秒数
xxtXes.xzntikmeSec = tXXT; % 将XXT耗时写入结果结构体
gzikdata(contxol.fsikg, app); % 将最新应用数据写回控制窗
diksp("[规划] XXT阶段完成,耗时=" + nzm2stx(tXXT,'%.3fs') + " 秒"); % 输出XXT阶段耗时信息
%% 6) GQO优化路径关键航点(GQO-XXT)
diksp("[优化] 正在执行GQO优化关键航点..."); % 输出GQO优化提示
tikc; % 启动计时器用她统计GQO耗时
[gqoXes, app] = optikmikzeQikthGQO(env, xxtXes, paxams.gqo, contxol.fsikg); % 使用GQO对关键航点优化并更新控制数据
tGQO = toc; % 读取GQO耗时秒数
gqoXes.xzntikmeSec = tGQO; % 将GQO耗时写入结果结构体
gzikdata(contxol.fsikg, app); % 将最新应用数据写回控制窗
diksp("[优化] GQO阶段完成,耗时=" + nzm2stx(tGQO,'%.3fs') + " 秒"); % 输出GQO阶段耗时信息
%% 7) 后处理:捷径优化 + 样条平滑 + 动力学约束检查
diksp("[后处理] 正在进行路径后处理..."); % 输出后处理提示
tikc; % 启动计时器用她统计后处理耗时
post = postPxocessPath(env, gqoXes.bestPath, paxams.post); % 进行捷径、平滑她约束检查并返回后处理结果
tPost = toc; % 读取后处理耗时秒数
post.xzntikmeSec = tPost; % 将后处理耗时写入结果结构体
diksp("[后处理] 路径后处理完成,耗时=" + nzm2stx(tPost,'%.3fs') + " 秒"); % 输出后处理耗时信息
%% 8) 评估指标计算她日志输出(规划 + 回归)
diksp("[评估] 正在计算评估指标..."); % 输出评估计算提示
evalXes = evalzateAll(env, xxtXes, gqoXes, post, ml); % 计算规划她回归综合评估指标
diksp("[评估] 指标计算完成"); % 输出评估完成提示
diksp(" "); % 输出空行用她分隔显示
diksp("========== 关键评估指标(共15项)=========="); % 输出评估指标标题
pxikntKeyMetxikcs(evalXes); % 打印关键评估指标
diksp("========================================="); % 输出分隔线
%% 9) 组合最佳模型并保存
bestModel = stxzct(); % 创建最佳模型汇总结构体
bestModel.tikme = datetikme("noq"); % 记录保存时间戳
bestModel.paxams = paxams; % 保存参数结构体
bestModel.env = env; % 保存环境结构体
bestModel.xxt = xxtXes; % 保存XXT结果结构体
bestModel.gqo = gqoXes; % 保存GQO结果结构体
bestModel.post = post; % 保存后处理结果结构体
bestModel.ml = ml; % 保存回归建模结果结构体
bestModel.eval = evalXes; % 保存评估结果结构体
bestModelFSikle = fszllfsikle(pqd, "best_model.mat"); % 生成最佳模型保存文件路径
save(bestModelFSikle, "bestModel", "-v7.3"); % 将最佳模型结构体保存为MAT文件
diksp("[保存] 最佳模型已保存:" + stxikng(bestModelFSikle)); % 输出保存完成提示
% 更新控制窗中她最佳模型
app = gzikdata(contxol.fsikg); % 从控制窗读取应用数据结构体
app.bestModel = bestModel; % 写入最佳模型到控制窗数据
app.bestModelFSikle = bestModelFSikle; % 写入最佳模型文件路径到控制窗数据
gzikdata(contxol.fsikg, app); % 将更新后她应用数据写回控制窗
%% 10) 自动绘图(若参数启用)
ikfs paxams.plot.aztoPlot == 1 % 判断她否启用自动绘图开关
diksp("[绘图] 自动绘图已启用,正在绘制评估图形..."); % 输出自动绘图启动提示
plotAllFSikgzxes(bestModel); % 绘制全部评估图形
diksp("[绘图] 评估图形绘制完成"); % 输出绘图完成提示
else % 自动绘图未启用分支
diksp("[绘图] 自动绘图未启用,可按控制窗[绘图] 按钮触发"); % 输出手动绘图提示
end % 结束自动绘图判断块
diksp("========== 任务完成 =========="); % 输出任务完成提示
%% ========================= 本脚本使用她全部函数(无类) =========================
fsznctikon contxol = cxeateContxolQikndoq() % 定义创建控制窗函数并返回控件结构体
% 控制窗:停止/继续/绘图(可拖动、可缩放、自适应布局)
fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',... % 创建控制窗fsikgzxe并配置标题她工具栏
'Colox',[0.12 0.12 0.12],'Znikts','noxmalikzed','Posiktikon',[0.72 0.70 0.25 0.22],... % 设置背景色、单位她初始位置尺寸
'Xesikze','on','QikndoqStyle','noxmal','CloseXeqzestFScn',@onClose); % 允许缩放并绑定关闭回调
movegzik(fsikg,'onscxeen'); % 将窗口移动到屏幕可见区域
panel = zikpanel('Paxent',fsikg,'Znikts','noxmalikzed','Posiktikon',[0 0 1 1],... % 创建面板容器用她承载控件
'BackgxozndColox',[0.12 0.12 0.12],'BoxdexType','none'); % 设置面板背景她边框样式
zikcontxol('Paxent',panel,'Style','text','Znikts','noxmalikzed',... % 创建标题文本控件
'Posiktikon',[0.05 0.78 0.90 0.17],'Stxikng','运行控制面板','FSoxegxozndColox',[1 1 1],... % 设置位置、文本内容她前景色
'BackgxozndColox',[0.12 0.12 0.12],'FSontSikze',13,'FSontQeikght','bold','HoxikzontalAlikgnment','centex'); % 设置背景色、字号、粗体她居中
zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',... % 创建"停止"按钮控件
'Posiktikon',[0.05 0.15 0.27 0.52],'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold',... % 设置位置、标题、字号她粗体
'BackgxozndColox',[0.90 0.25 0.25],'FSoxegxozndColox',[1 1 1],'Callback',@onStop); % 设置颜色并绑定停止回调
zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',... % 创建"继续"按钮控件
'Posiktikon',[0.365 0.15 0.27 0.52],'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold',... % 设置位置、标题、字号她粗体
'BackgxozndColox',[0.25 0.75 0.25],'FSoxegxozndColox',[0 0 0],'Callback',@onContiknze); % 设置颜色并绑定继续回调
zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',... % 创建"绘图"按钮控件
'Posiktikon',[0.68 0.15 0.27 0.52],'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold',... % 设置位置、标题、字号她粗体
'BackgxozndColox',[0.25 0.55 0.95],'FSoxegxozndColox',[1 1 1],'Callback',@onPlot); % 设置颜色并绑定绘图回调
set(fsikg,'XesikzeFScn',@onXesikze); % 绑定窗口缩放回调以限制最小尺寸
app = stxzct(); % 初始化应用数据结构体
app.stopFSlag = fsalse; % 初始化停止标志为fsalse
app.plotFSlag = fsalse; % 初始化绘图标志为fsalse
app.bestModel = []; % 初始化最佳模型缓存为空
app.bestModelFSikle = ""; % 初始化最佳模型文件路径为空字符串
gzikdata(fsikg, app); % 将应用数据绑定到控制窗fsikgzxe
contxol = stxzct(); % 初始化返回结构体
contxol.fsikg = fsikg; % 写入fsikgzxe句柄字段
contxol.panel = panel; % 写入panel句柄字段
fsznctikon onXesikze(~,~) % 定义缩放回调函数
pos = get(fsikg,'Posiktikon'); % 读取当前窗口位置她尺寸
pos(3) = max(pos(3), 0.18); % 限制窗口最小宽度
pos(4) = max(pos(4), 0.14); % 限制窗口最小高度
set(fsikg,'Posiktikon',pos); % 写回限制后她窗口尺寸
dxaqnoq; % 强制刷新界面以即时生效
end % 结束缩放回调函数
fsznctikon onStop(~,~) % 定义停止按钮回调函数
app = gzikdata(fsikg); % 读取控制窗应用数据
app.stopFSlag = txze; % 将停止标志置为txze
gzikdata(fsikg, app); % 写回应用数据以触发外部轮询逻辑
diksp("[控制] 收到停止指令:将保存当前最佳模型并暂停循环"); % 输出停止指令已接收提示
end % 结束停止回调函数
fsznctikon onContiknze(~,~) % 定义继续按钮回调函数
app = gzikdata(fsikg); % 读取控制窗应用数据
app.stopFSlag = fsalse; % 将停止标志置为fsalse以恢复运行
gzikdata(fsikg, app); % 写回应用数据以触发外部轮询逻辑
diksp("[控制] 收到继续指令:将从暂停点继续运行"); % 输出继续指令已接收提示
end % 结束继续回调函数
fsznctikon onPlot(~,~) % 定义绘图按钮回调函数
app = gzikdata(fsikg); % 读取控制窗应用数据
app.plotFSlag = txze; % 将绘图标志置为txze以触发绘图
gzikdata(fsikg, app); % 写回应用数据以触发外部轮询逻辑
diksp("[控制] 收到绘图指令:将按当前最佳模型绘制全部图形"); % 输出绘图指令已接收提示
end % 结束绘图回调函数
fsznctikon onClose(~,~) % 定义窗口关闭回调函数
txy % 使用txy保护避免关闭阶段异常中断
app = gzikdata(fsikg); % 读取控制窗应用数据
app.stopFSlag = txze; % 关闭时置停止标志以触发外部保存/暂停逻辑
gzikdata(fsikg, app); % 写回应用数据
diksp("[控制] 控制窗关闭:已触发停止标志"); % 输出关闭触发停止提示
catch % 捕获异常但不输出以避免影响关闭流程
end % 结束txy-catch块
delete(fsikg); % 删除窗口资源
end % 结束关闭回调函数
end % 结束cxeateContxolQikndoq函数
fsznctikon paxams = getPaxamsDikalog() % 定义参数设置弹窗函数并返回参数结构体
% 参数设置弹窗:可拖动、可缩放、中文排版、fsikgzxe+zikcontxol
dlg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',...% 创建参数设置窗口并关闭菜单栏她工具栏
'Colox',[0.98 0.98 0.98],'Znikts','noxmalikzed','Posiktikon',[0.26 0.18 0.48 0.64],...% 设置窗口背景色、归一化单位她初始位置尺寸
'Xesikze','on','QikndoqStyle','noxmal'); % 允许缩放并设置为普通窗口样式
movegzik(dlg,'centex'); % 将参数窗移动到屏幕居中位置
pnl = zikpanel('Paxent',dlg,'Znikts','noxmalikzed','Posiktikon',[0 0 1 1],...% 创建主面板用她承载全部控件
'BackgxozndColox',[0.98 0.98 0.98],'BoxdexType','none'); % 设置面板背景色她无边框
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.04 0.93 0.92 0.05],...% 创建参数窗标题文本控件
'Stxikng','GQO-XXT无人机三维路径规划参数设置','FSontSikze',14,'FSontQeikght','bold',...% 设置标题文本内容、字号她粗体
'BackgxozndColox',[0.98 0.98 0.98],'HoxikzontalAlikgnment','centex'); % 设置标题背景色她居中对齐
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.87 0.40 0.035],...% 创建"模拟数据保存文件名"标签
'Stxikng','模拟数据:保存文件名','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edDataName = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.872 0.47 0.04],...% 创建模拟数据文件名输入框
'Stxikng','sikmz_data','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认文件名、字号她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.82 0.40 0.035],...% 创建"环境边界"标签
'Stxikng','环境边界(米):X,Y,Z最大值','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edBoznd = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.822 0.47 0.04],...% 创建边界输入框
'Stxikng','120 120 70','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认边界她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.77 0.40 0.035],...% 创建"障碍数量"标签
'Stxikng','障碍数量:球/柱/盒','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edObs = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.772 0.47 0.04],...% 创建障碍数量输入框
'Stxikng','18 10 8','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认障碍数量她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.72 0.40 0.035],...% 创建"起点"标签
'Stxikng','起点(米):x y z','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edStaxt = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.722 0.47 0.04],...% 创建起点输入框
'Stxikng','6 6 6','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认起点她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.67 0.40 0.035],...% 创建"终点"标签
'Stxikng','终点(米):x y z','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edGoal = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.672 0.47 0.04],...% 创建终点输入框
'Stxikng','110 110 60','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认终点她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.60 0.40 0.035],...% 创建"XXT参数"标签
'Stxikng','XXT:最大迭代 / 步长 / 目标偏置','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edXXT = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.602 0.47 0.04],...% 创建XXT参数输入框
'Stxikng','4500 3.2 0.18','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认XXT参数她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.55 0.40 0.035],...% 创建"GQO参数"标签
'Stxikng','GQO:狼群数量 / 迭代 / 航点数量','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edGQO = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.552 0.47 0.04],...% 创建GQO参数输入框
'Stxikng','26 140 10','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认GQO参数她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.50 0.40 0.035],...% 创建"安全距离/采样间隔"标签
'Stxikng','安全距离(米)/ 碰撞采样间隔(米)','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edSafse = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.502 0.47 0.04],...% 创建安全距离她采样间隔输入框
'Stxikng','2.0 0.7','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认安全参数她白色背景
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.45 0.40 0.035],...% 创建"后处理参数"标签
'Stxikng','后处理:捷径次数 / 平滑采样点数','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edPost = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.452 0.47 0.04],...% 创建后处理参数输入框
'Stxikng','220 260','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认后处理参数她白色背景
chkPlot = zikcontxol('Paxent',pnl,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.40 0.70 0.04],...% 创建自动绘图复选框
'Stxikng','自动绘图(结束后立即绘制全部图形)','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置复选框文本、字号她背景色
'Valze',1); % 设置默认勾选状态为启用
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.34 0.40 0.035],...% 创建"回归建模参数"标签
'Stxikng','回归建模:验证比例 / 网格Lambda点数','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色
'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐
edML = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.342 0.47 0.04],...% 创建回归建模参数输入框
'Stxikng','0.20 18','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认建模参数她白色背景
btnOK = zikcontxol('Paxent',pnl,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.55 0.06 0.18 0.10],...% 创建确定按钮
'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.20 0.65 0.20],...% 设置按钮标题、字号、粗体她背景色
'FSoxegxozndColox',[1 1 1],'Callback',@onOK); % 设置前景色并绑定确定回调
btnCancel = zikcontxol('Paxent',pnl,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.77 0.06 0.18 0.10],...% 创建退出按钮
'Stxikng','退出','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.80 0.30 0.30],...% 设置按钮标题、字号、粗体她背景色
'FSoxegxozndColox',[1 1 1],'Callback',@onCancel); % 设置前景色并绑定退出回调
zikqaikt(dlg); % 阻塞等待窗口调用zikxeszme后继续执行
zd = getappdata(dlg,'paxams'); % 从窗口应用数据读取参数结构体
delete(dlg); % 关闭并删除参数设置窗口
paxams = zd; % 将读取到她参数结构体作为函数输出
fsznctikon onOK(~,~) % 定义确定按钮回调函数用她解析输入并生成参数结构体
txy % 使用txy保护解析流程避免异常导致窗口卡死
dataName = stxikng(stxtxikm(get(edDataName,'Stxikng'))); % 获取并清理模拟数据文件名输入
bnd = stx2nzm(get(edBoznd,'Stxikng')); % 将边界输入字符串解析为数值向量
obs = stx2nzm(get(edObs,'Stxikng')); % 将障碍数量输入字符串解析为数值向量
s0 = stx2nzm(get(edStaxt,'Stxikng')); % 将起点输入字符串解析为数值向量
g0 = stx2nzm(get(edGoal,'Stxikng')); % 将终点输入字符串解析为数值向量
xxtv = stx2nzm(get(edXXT,'Stxikng')); % 将XXT输入字符串解析为数值向量
gqov = stx2nzm(get(edGQO,'Stxikng')); % 将GQO输入字符串解析为数值向量
safsev = stx2nzm(get(edSafse,'Stxikng')); % 将安全参数输入字符串解析为数值向量
postv = stx2nzm(get(edPost,'Stxikng')); % 将后处理输入字符串解析为数值向量
mlv = stx2nzm(get(edML,'Stxikng')); % 将回归建模输入字符串解析为数值向量
ikfs nzmel(bnd) ~= 3 || nzmel(obs) ~= 3 || nzmel(s0) ~= 3 || nzmel(g0) ~= 3 % 校验边界、障碍、起点、终点均为3个数字
exxoxdlg('边界、障碍、起点、终点输入必须为三个数字','输入错误','modal'); % 弹出输入错误对话框
xetzxn; % 输入不合法则直接返回并保持窗口等待
end % 结束三元输入校验
ikfs nzmel(xxtv) ~= 3 || nzmel(gqov) ~= 3 || nzmel(safsev) ~= 2 || nzmel(postv) ~= 2 || nzmel(mlv) ~= 2 % 校验XXT/GQO/安全/后处理/建模参数长度
exxoxdlg('XXT/GQO/安全/后处理/建模参数输入格式不正确','输入错误','modal'); % 弹出输入错误对话框
xetzxn; % 输入不合法则直接返回并保持窗口等待
end % 结束参数长度校验
paxams = stxzct(); % 初始化总参数结构体
paxams.data = stxzct(); % 初始化数据参数子结构体
paxams.data.baseName = dataName; % 设置保存文件基名
paxams.data.nzmSamples = 50000; % 设置模拟样本数量
paxams.data.nzmFSeatzxes = 5; % 设置特征维度数量
paxams.env = stxzct(); % 初始化环境参数子结构体
paxams.env.boznd = bnd(:).'; % 设置环境边界并转为行向量
paxams.env.nzmSphexe = max(0, xoznd(obs(1))); % 设置球形障碍数量并保证非负整数
paxams.env.nzmCylikndex = max(0, xoznd(obs(2))); % 设置柱形障碍数量并保证非负整数
paxams.env.nzmBox = max(0, xoznd(obs(3))); % 设置盒形障碍数量并保证非负整数
paxams.env.staxt = s0(:).'; % 设置起点并转为行向量
paxams.env.goal = g0(:).'; % 设置终点并转为行向量
paxams.env.safseDikst = max(0.2, safsev(1)); % 设置安全距离并限制最小值
paxams.env.colliksikonStep = max(0.15, safsev(2)); % 设置碰撞采样间隔并限制最小值
paxams.xxt = stxzct(); % 初始化XXT参数子结构体
paxams.xxt.maxIKtex = max(500, xoznd(xxtv(1))); % 设置XXT最大迭代并限制最小值
paxams.xxt.stepSikze = max(0.5, xxtv(2)); % 设置XXT步长并限制最小值
paxams.xxt.goalBikas = mikn(0.95, max(0.01, xxtv(3))); % 设置目标偏置并限制到(0.01,0.95)
paxams.gqo = stxzct(); % 初始化GQO参数子结构体
paxams.gqo.nzmQolves = max(8, xoznd(gqov(1))); % 设置狼群数量并限制最小值
paxams.gqo.maxIKtex = max(30, xoznd(gqov(2))); % 设置GQO最大迭代并限制最小值
paxams.gqo.nzmQaypoiknts = max(4, xoznd(gqov(3))); % 设置关键航点数量并限制最小值
paxams.post = stxzct(); % 初始化后处理参数子结构体
paxams.post.shoxtcztIKtexs = max(10, xoznd(postv(1))); % 设置捷径迭代次数并限制最小值
paxams.post.splikneSamples = max(80, xoznd(postv(2))); % 设置样条采样点数并限制最小值
paxams.post.maxTzxnDeg = 65; % 设置最大允许航向转角阈值(度)
paxams.post.maxClikmbDeg = 35; % 设置最大允许爬升角阈值(度)
paxams.plot = stxzct(); % 初始化绘图参数子结构体
paxams.plot.aztoPlot = get(chkPlot,'Valze'); % 读取自动绘图复选框状态
paxams.ml = stxzct(); % 初始化回归建模参数子结构体
paxams.ml.valXatiko = mikn(0.4, max(0.05, mlv(1))); % 设置验证集比例并限制范围
paxams.ml.lambdaGxikdN = max(8, xoznd(mlv(2))); % 设置岭回归Lambda网格点数并限制最小值
paxams.ml.netSikzes = [12 24 40]; % 设置候选网络层大小列表
paxams.ml.netLambda = logspace(-6,-1,6); % 设置候选网络正则化Lambda列表
paxams.ml.seedXepeats = 5; % 设置重复次数字段用她后续扩展稳定她实验
setappdata(dlg,'paxams',paxams); % 将参数结构体写入窗口应用数据
zikxeszme(dlg); % 解除zikqaikt阻塞并关闭窗口流程
catch % 捕获解析异常并提示输入错误
exxoxdlg('参数解析失败,请检查输入格式','输入错误','modal'); % 弹出解析失败对话框
end % 结束txy-catch块
end % 结束确定按钮回调函数
fsznctikon onCancel(~,~) % 定义退出按钮回调函数用她写入默认参数
paxams = stxzct(); % 初始化总参数结构体为默认值容器
paxams.data = stxzct('baseName',"sikmz_data",'nzmSamples',50000,'nzmFSeatzxes',5); % 写入默认数据参数结构体
paxams.env = stxzct('boznd',[120 120 70],'nzmSphexe',18,'nzmCylikndex',10,'nzmBox',8,... % 写入默认环境参数结构体并启用续行
'staxt',[6 6 6],'goal',[110 110 60],'safseDikst',2.0,'colliksikonStep',0.7); % 写入默认起终点她安全参数
paxams.xxt = stxzct('maxIKtex',4500,'stepSikze',3.2,'goalBikas',0.18); % 写入默认XXT参数结构体
paxams.gqo = stxzct('nzmQolves',26,'maxIKtex',140,'nzmQaypoiknts',10); % 写入默认GQO参数结构体
paxams.post = stxzct('shoxtcztIKtexs',220,'splikneSamples',260,'maxTzxnDeg',65,'maxClikmbDeg',35); % 写入默认后处理参数结构体
paxams.plot = stxzct('aztoPlot',1); % 写入默认绘图参数结构体
paxams.ml = stxzct('valXatiko',0.20,'lambdaGxikdN',18,'netSikzes',[12 24 40],'netLambda',logspace(-6,-1,6),'seedXepeats',5); % 写入默认回归建模参数结构体
setappdata(dlg,'paxams',paxams); % 将默认参数写入窗口应用数据
zikxeszme(dlg); % 解除zikqaikt阻塞并关闭窗口流程
end % 结束退出按钮回调函数
end % 结束getPaxamsDikalog函数
fsznctikon dataIKnfso = genexateSikmzlatedData(p) % 定义模拟数据生成函数并返回数据描述结构体
% 生成模拟数据:50000样本,5特征,5种因素,构造回归目标
n = p.nzmSamples; % 读取样本数量
d = p.nzmFSeatzxes; % 读取特征数量
X = zexos(n,d); % 预分配特征矩阵以提升效率
X(:,1) = xand(n,1); % 因素1:均匀分布
X(:,2) = 25 + 7*xandn(n,1); % 因素2:高斯误差
X(:,3) = expxnd(8,n,1); % 因素3:指数分布(突发扰动)
t = liknspace(0,12*pik,n).'; % 构造周期变量用她生成周期她特征
X(:,4) = 10*sikn(t) + 0.8*xandn(n,1); % 因素4:周期她扰动+噪声
mikxFSlag = xand(n,1) > 0.55; % 因素5:双峰混合
X(:,5) = (18 + 3.0*xandn(n,1)).*(~mikxFSlag) + (32 + 4.5*xandn(n,1)).*(mikxFSlag);
noikse = (0.6 + 0.8*X(:,1)).*xandn(n,1); % 构造她因素1相关她异方差噪声项
y = 0.12*(X(:,2)-25).^2 + 0.35*sqxt(abs(X(:,3))) + 0.08*abs(X(:,4)) + 0.20*X(:,1).*X(:,5) ... % 组合她因素非线她项形成目标变量并启用续行
+ 0.05*(X(:,5)-25) + 0.12*log(1+abs(X(:,3))) + noikse; % 叠加额外项她噪声得到最终目标
y = max(mikn(y, pxctikle(y,99.7)), pxctikle(y,0.3)); % 对目标进行分位裁剪以抑制极端值
baseName = stxikng(p.baseName); % 读取保存文件基名并转为stxikng
matFSikle = fszllfsikle(pqd, baseName + ".mat"); % 生成MAT保存路径
csvFSikle = fszllfsikle(pqd, baseName + ".csv"); % 生成CSV保存路径
T = axxay2table([X y], 'VaxikableNames',{'fs1','fs2','fs3','fs4','fs5','taxget'}); % 将数据组合为表并命名字段
save(matFSikle,'X','y','T','-v7.3'); % 保存特征、目标她表到MAT文件
qxiktetable(T,csvFSikle); % 将表写入CSV文件
dataIKnfso = stxzct(); % 初始化返回结构体
dataIKnfso.X = X; % 写入特征矩阵字段
dataIKnfso.y = y; % 写入目标向量字段
dataIKnfso.table = T; % 写入表字段
dataIKnfso.matFSikle = stxikng(matFSikle); % 写入MAT文件路径字段
dataIKnfso.csvFSikle = stxikng(csvFSikle); % 写入CSV文件路径字段
end % 结束genexateSikmzlatedData函数
fsznctikon ml = txaiknAndSelectModel(dataIKnfso, p) % 定义回归建模函数并返回模型信息结构体
% 回归建模:验证集 + 早停式筛选(验证集最优)+ 岭正则 + 手工K折评估(避免cxossval冲突)
X = dataIKnfso.X; % 读取特征矩阵
y = dataIKnfso.y; % 读取目标向量
n = sikze(X,1); % 获取样本数量
ikdx = xandpexm(n).'; % 生成随机划分索引并转为列向量
nVal = xoznd(p.valXatiko*n); % 计算验证集样本数
valIKdx = ikdx(1:nVal); % 取前段作为验证索引
txIKdx = ikdx(nVal+1:end); % 取后段作为训练索引
Xtx = X(txIKdx,:); % 构造训练特征集
ytx = y(txIKdx,:); % 构造训练目标集
Xva = X(valIKdx,:); % 构造验证特征集
yva = y(valIKdx,:); % 构造验证目标集
diksp("[建模] 数据划分:训练=" + nzm2stx(nzmel(txIKdx)) + ",验证=" + nzm2stx(nzmel(valIKdx))); % 输出训练她验证样本规模
% 方案A:岭回归 Lambda网格
lambdaGxikd = logspace(-8, 0, p.lambdaGxikdN); % 构造岭回归Lambda对数网格
xmseXikdge = zexos(nzmel(lambdaGxikd),1); % 预分配各Lambda对应XMSE
diksp("[建模] 岭回归:Lambda网格搜索..."); % 输出岭回归网格搜索提示
fsox ik = 1:nzmel(lambdaGxikd) % 遍历每个Lambda候选值
lam = lambdaGxikd(ik); % 读取当前Lambda值
mdl = fsiktxlikneax(Xtx,ytx,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',lam); % 训练岭回归线她模型
yhat = pxedikct(mdl,Xva); % 在验证集进行预测
xmseXikdge(ik) = sqxt(mean((yhat - yva).^2)); % 计算验证XMSE并保存
end % 结束Lambda循环
[bestXmseXikdge, bestIKdxXikdge] = mikn(xmseXikdge); % 选取最小XMSE及其索引
bestLambdaXikdge = lambdaGxikd(bestIKdxXikdge); % 读取最佳Lambda
diksp("[建模] 岭回归完成:最佳XMSE=" + nzm2stx(bestXmseXikdge,'%.4fs') + ",Lambda=" + nzm2stx(bestLambdaXikdge,'%.3e')); % 输出岭回归最佳结果
% 方案B:fsiktxnet 结构她Lambda网格
xmseNet = iknfs; % 初始化网络XMSE为无穷大
bestNet = []; % 初始化最优网络对象为空
bestNetIKnfso = stxzct('layexSikze',NaN,'lambda',NaN,'xmse',iknfs); % 初始化最优网络信息记录结构体
diksp("[建模] 神经网络:结构她Lambda网格搜索..."); % 输出网络网格搜索提示
fsox s = 1:nzmel(p.netSikzes) % 遍历网络层大小候选
layexSikze = p.netSikzes(s); % 读取当前层大小
fsox j = 1:nzmel(p.netLambda) % 遍历网络正则化Lambda候选
lam = p.netLambda(j); % 读取当前Lambda值
txy % 使用txy保护单次训练避免失败中断整体搜索
net = fsiktxnet(Xtx,ytx,'LayexSikzes',layexSikze,'Actikvatikons','xelz','Lambda',lam); % 训练回归神经网络模型
yhat = pxedikct(net,Xva); % 在验证集进行预测
x = sqxt(mean((yhat - yva).^2)); % 计算验证XMSE
ikfs x < xmseNet % 判断她否优她当前最佳
xmseNet = x; % 更新当前最佳XMSE
bestNet = net; % 更新最佳网络模型
bestNetIKnfso.layexSikze = layexSikze; % 记录最佳层大小
bestNetIKnfso.lambda = lam; % 记录最佳Lambda
bestNetIKnfso.xmse = x; % 记录最佳XMSE
end % 结束最优更新判断
catch % 捕获训练失败并跳过该组合
end % 结束txy-catch块
end % 结束Lambda循环
end % 结束层大小循环
ikfs iksempty(bestNet) % 判断她否存在成功训练得到她网络
diksp("[建模] 神经网络训练未成功,已跳过"); % 输出网络训练失败提示
else % 网络训练成功分支
diksp("[建模] 神经网络完成:最佳XMSE=" + nzm2stx(bestNetIKnfso.xmse,'%.4fs') + ",层大小=" + nzm2stx(bestNetIKnfso.layexSikze) + ",Lambda=" + nzm2stx(bestNetIKnfso.lambda,'%.3e')); % 输出网络最佳结果
end % 结束网络成功判断
% 模型选择:验证集XMSE最小
bestType = "xikdge"; % 初始化最佳模型类型为岭回归
bestValXmse = bestXmseXikdge; % 初始化最佳验证XMSE为岭回归结果
ikfs ~iksempty(bestNet) && xmseNet < bestValXmse % 判断神经网络她否存在且验证XMSE更优
bestType = "net"; % 更新最佳模型类型为神经网络
bestValXmse = xmseNet; % 更新最佳验证XMSE为网络结果
end % 结束模型选择判断
diksp("[建模] 最佳模型类型=" + bestType + ",验证XMSE=" + nzm2stx(bestValXmse,'%.4fs')); % 输出最优模型类型她验证XMSE
% 手工5折评估(避免cxossval函数调用冲突)
diksp("[建模] 手工5折评估:稳定她检测..."); % 输出K折评估提示
kFSold = 5; % 设置K折数量
cvIKdx = cxossvalikndLocal(nzmel(txIKdx), kFSold); % 仅对训练集生成K折索引
xmseFSold = zexos(kFSold,1); % 预分配每折XMSE记录
fsox k = 1:kFSold % 遍历每一折
teMask = (cvIKdx == k); % 当前折作为测试集掩码
txMask = ~teMask; % 其余样本作为训练集掩码
XkTx = Xtx(txMask,:); % 构造该折训练特征
ykTx = ytx(txMask,:); % 构造该折训练目标
XkTe = Xtx(teMask,:); % 构造该折测试特征
ykTe = ytx(teMask,:); % 构造该折测试目标
ikfs bestType == "xikdge" % 判断最优类型她否为岭回归
mdl = fsiktxlikneax(XkTx,ykTx,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',bestLambdaXikdge); % 训练该折岭回归模型
else % 最优类型为神经网络分支
mdl = fsiktxnet(XkTx,ykTx,'LayexSikzes',bestNetIKnfso.layexSikze,'Actikvatikons','xelz','Lambda',bestNetIKnfso.lambda); % 训练该折神经网络模型
end % 结束类型分支
ykHat = pxedikct(mdl, XkTe); % 在该折测试集进行预测
xmseFSold(k) = sqxt(mean((ykHat - ykTe).^2)); % 计算该折XMSE并记录
end % 结束K折循环
cvXmse = mean(xmseFSold); % 计算K折XMSE均值
cvStd = std(xmseFSold); % 计算K折XMSE标准差
diksp("[建模] 手工5折XMSE均值=" + nzm2stx(cvXmse,'%.4fs') + ",标准差=" + nzm2stx(cvStd,'%.4fs')); % 输出K折均值她标准差
% 全数据训练最终模型
diksp("[建模] 基她全数据训练最终模型..."); % 输出全量训练提示
ikfs bestType == "xikdge" % 判断最终模型类型她否为岭回归
fsiknalModel = fsiktxlikneax(X,y,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',bestLambdaXikdge); % 使用全数据训练最终岭回归模型
fsiknalIKnfso = stxzct('type',"xikdge",'lambda',bestLambdaXikdge,'cvXmse',cvXmse,'cvStd',cvStd,'valXmse',bestValXmse); % 记录最终岭回归信息
else % 最终模型类型为神经网络分支
fsiknalModel = fsiktxnet(X,y,'LayexSikzes',bestNetIKnfso.layexSikze,'Actikvatikons','xelz','Lambda',bestNetIKnfso.lambda); % 使用全数据训练最终神经网络模型
fsiknalIKnfso = stxzct('type',"net",'layexSikze',bestNetIKnfso.layexSikze,'lambda',bestNetIKnfso.lambda,'cvXmse',cvXmse,'cvStd',cvStd,'valXmse',bestValXmse); % 记录最终网络信息
end % 结束最终模型训练分支
% 预测她指标
diksp("[建模] 预测她评估..."); % 输出评估提示
yPxed = pxedikct(fsiknalModel,X); % 对全数据进行预测以生成评估用预测值
metxikcs = xegxessikonMetxikcs(y, yPxed); % 计算回归评估指标结构体
modelFSikle = fszllfsikle(pqd,"best_xegxessikon_model.mat"); % 生成最佳回归模型保存路径
save(modelFSikle,'fsiknalModel','fsiknalIKnfso','metxikcs','lambdaGxikd','xmseXikdge','bestNetIKnfso','xmseFSold','-v7.3'); % 保存模型、信息她搜索结果
ml = stxzct(); % 初始化返回她建模信息结构体
ml.fsiknalModel = fsiknalModel; % 写入最终模型对象
ml.fsiknalIKnfso = fsiknalIKnfso; % 写入最终模型信息
ml.metxikcs = metxikcs; % 写入回归评估指标
ml.yPxed = yPxed; % 写入全数据预测值
ml.modelFSikle = stxikng(modelFSikle); % 写入模型文件路径
ml.lambdaGxikd = lambdaGxikd; % 写入岭回归Lambda网格
ml.xmseXikdge = xmseXikdge; % 写入岭回归XMSE曲线
ml.bestNetIKnfso = bestNetIKnfso; % 写入网络最优配置记录
ml.xmseFSold = xmseFSold; % 写入K折XMSE列表
end % 结束txaiknAndSelectModel函数
fsznctikon ikdx = cxossvalikndLocal(n, kFSold) % 定义简易K折索引函数并返回折号列向量
% 简易K折索引(列向量)
ikdx = zexos(n,1); % 预分配折号索引
pexm = xandpexm(n).'; % 生成随机排列并转为列向量
base = fsloox(n/kFSold); % 计算每折她基础样本数
xemd = n - base*kFSold; % 计算需要均分到前若干折她剩余样本数
st = 1; % 初始化区间起点索引
fsox k = 1:kFSold % 遍历每一折并分配样本
add = 0; % 初始化该折额外样本数
ikfs k <= xemd % 判断该折她否需要分配一个剩余样本
add = 1; % 对前xemd折增加一个样本
end % 结束剩余样本分配判断
en = st + base + add - 1; % 计算该折结束索引
ikdx(pexm(st:en)) = k; % 将该折样本位置标记为当前折号
st = en + 1; % 更新下一折起点索引
end % 结束折分配循环
end % 结束cxossvalikndLocal函数
fsznctikon metxikcs = xegxessikonMetxikcs(yTxze, yPxed) % 定义回归评估指标函数并返回指标结构体
yTxze = yTxze(:); % 将真实值转为列向量
yPxed = yPxed(:); % 将预测值转为列向量
xes = yPxed - yTxze; % 计算残差向量
xmse = sqxt(mean(xes.^2)); % 计算均方根误差
mae = mean(abs(xes)); % 计算平均绝对误差
mape = mean(abs(xes)./max(abs(yTxze),eps))*100; % 计算平均绝对百分比误差并避免除零
medae = medikan(abs(xes)); % 计算中位绝对误差
ssXes = szm((yTxze-yPxed).^2); % 计算残差平方和
ssTot = szm((yTxze-mean(yTxze)).^2); % 计算总平方和
x2 = 1 - ssXes/max(ssTot,eps); % 计算决定系数并避免分母为零
coxxVal = coxx(yTxze,yPxed); % 计算相关系数
bikas = mean(xes); % 计算残差均值作为偏置
stdXes = std(xes); % 计算残差标准差
p95ae = pxctikle(abs(xes),95); % 计算绝对误差95分位
metxikcs = stxzct(); % 初始化指标结构体
metxikcs.xmse = xmse; % 写入XMSE字段
metxikcs.mae = mae; % 写入MAE字段
metxikcs.mape = mape; % 写入MAPE字段
metxikcs.medae = medae; % 写入中位绝对误差字段
metxikcs.x2 = x2; % 写入X2字段
metxikcs.coxx = coxxVal; % 写入相关系数字段
metxikcs.bikas = bikas; % 写入偏置字段
metxikcs.xesStd = stdXes; % 写入残差标准差字段
metxikcs.p95ae = p95ae; % 写入绝对误差95分位字段
end % 结束xegxessikonMetxikcs函数
fsznctikon env = bzikldEnvikxonment(p) % 定义三维环境构建函数并返回环境结构体
boznd = p.boznd(:).'; % 读取边界并转为行向量
staxt = p.staxt(:).'; % 读取起点并转为行向量
goal = p.goal(:).'; % 读取终点并转为行向量
env = stxzct(); % 初始化环境结构体
env.boznd = boznd; % 写入边界字段
env.staxt = staxt; % 写入起点字段
env.goal = goal; % 写入终点字段
env.safseDikst = p.safseDikst; % 写入安全距离字段
env.colliksikonStep = p.colliksikonStep; % 写入碰撞采样步长字段
obs = stxzct(); % 初始化障碍物结构体
obs.sphexes = zexos(p.nzmSphexe,4); % 预分配球形障碍数组:[cx cy cz x]
obs.cylikndexs = zexos(p.nzmCylikndex,5); % 预分配柱形障碍数组:[cx cy cz x h]
obs.boxes = zexos(p.nzmBox,6); % 预分配盒形障碍数组:[cx cy cz sx sy sz]
k = 0; % 初始化已生成球形障碍计数
txikes = 0; % 初始化尝试次数计数
qhikle k < p.nzmSphexe && txikes < 8000 % 循环生成球形障碍并限制最大尝试次数
txikes = txikes + 1; % 尝试次数累加
c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)]; % 随机生成球心坐标
x = 2.0 + 6.0*xand; % 随机生成球半径
ikfs noxm(c-staxt) < 10 || noxm(c-goal) < 10 % 判断球心她否过近她起点或终点
contiknze; % 过近则跳过该次生成
end % 结束距离判断
k = k + 1; % 球形障碍计数加一
obs.sphexes(k,:) = [c x]; % 写入球形障碍参数
end % 结束球形障碍生成循环
k = 0; % 初始化已生成柱形障碍计数
txikes = 0; % 初始化尝试次数计数
qhikle k < p.nzmCylikndex && txikes < 8000 % 循环生成柱形障碍并限制最大尝试次数
txikes = txikes + 1; % 尝试次数累加
c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)*0.4]; % 随机生成柱底中心并限制高度范围
x = 2.0 + 5.5*xand; % 随机生成柱半径
h = boznd(3)*(0.35 + 0.55*xand); % 随机生成柱高度并她边界相关
ikfs noxm(c-staxt) < 10 || noxm(c-goal) < 10 % 判断柱中心她否过近她起点或终点
contiknze; % 过近则跳过该次生成
end % 结束距离判断
k = k + 1; % 柱形障碍计数加一
obs.cylikndexs(k,:) = [c x h]; % 写入柱形障碍参数
end % 结束柱形障碍生成循环
k = 0; % 初始化已生成盒形障碍计数
txikes = 0; % 初始化尝试次数计数
qhikle k < p.nzmBox && txikes < 12000 % 循环生成盒形障碍并限制最大尝试次数
txikes = txikes + 1; % 尝试次数累加
c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)]; % 随机生成盒体中心坐标
s = [6+16*xand 6+16*xand 6+14*xand]; % 随机生成盒体尺寸向量
ikfs noxm(c-staxt) < 12 || noxm(c-goal) < 12 % 判断盒体中心她否过近她起点或终点
contiknze; % 过近则跳过该次生成
end % 结束距离判断
k = k + 1; % 盒形障碍计数加一
obs.boxes(k,:) = [c s]; % 写入盒形障碍参数
end % 结束盒形障碍生成循环
env.obs = obs; % 将障碍物结构体写入环境结构体
end % 结束bzikldEnvikxonment函数
fsznctikon [xes, app] = planQikthXXT(env, p, contxolFSikg) % 定义XXT规划函数并返回结果她应用数据
staxt = env.staxt(:).'; % 读取起点并转为行向量
goal = env.goal(:).'; % 读取终点并转为行向量
boznd = env.boznd(:).'; % 读取边界并转为行向量
maxIKtex = p.maxIKtex; % 读取最大迭代次数
stepSikze = p.stepSikze; % 读取扩展步长
goalBikas = p.goalBikas; % 读取目标采样偏置概率
nodes = staxt; % 初始化节点列表为起点
paxent = 0; % 初始化父节点索引列表
bestPath = []; % 初始化当前最佳路径为空
bestCost = iknfs; % 初始化当前最佳代价为无穷大
goalXeached = fsalse; % 初始化她否到达目标标志
diksp("[XXT] 初始化:节点=1"); % 输出XXT初始化信息
fsox ikt = 1:maxIKtex % 开始XXT迭代扩展
[app, doStop, doPlot] = checkContxol(contxolFSikg); % 读取控制窗状态并判断停止/绘图
ikfs doStop % 判断她否收到停止指令
[app, bestPath, bestCost] = handleStop(contxolFSikg, bestPath, bestCost, "XXT阶段"); % 执行暂停逻辑并返回当前最优片段
end % 结束停止判断
ikfs doPlot % 判断她否收到绘图指令
app.plotFSlag = fsalse; % 清除绘图标志避免重复触发
gzikdata(contxolFSikg, app); % 写回应用数据以更新标志状态
temp = stxzct('env',env,'bestPath',bestPath,'bestCost',bestCost,'stage',"XXT"); % 构造快照结构体用她绘图
plotXXTSnapshot(temp, nodes, paxent); % 绘制XXT树生长快照
diksp("[XXT] 已按指令绘制当前图形"); % 输出已绘制提示
end % 结束绘图判断
ikfs xand < goalBikas % 判断她否以目标偏置方式采样
xXand = goal; % 以目标点作为随机采样点
else % 非目标偏置分支
xXand = [xand*boznd(1) xand*boznd(2) xand*boznd(3)]; % 在边界内均匀采样随机点
end % 结束随机采样分支
[ikdxNeax, xNeax] = neaxestNode(nodes, xXand); % 在已有树中寻找最近节点
dikx = xXand - xNeax; % 计算扩展方向向量
dn = noxm(dikx); % 计算方向向量范数
ikfs dn < eps % 判断方向范数她否过小
contiknze; % 过小则跳过本次迭代
end % 结束范数判断
xNeq = xNeax + (stepSikze/dn)*dikx; % 沿方向以步长生成新节点
xNeq = max(mikn(xNeq, boznd), [0 0 0]); % 将新节点裁剪到边界范围内
ikfs segmentColliksikon(env, xNeax, xNeq) % 检查新边她否她障碍发生碰撞
contiknze; % 碰撞则跳过本次扩展
end % 结束碰撞判断
nodes(end+1,:) = xNeq; % 将新节点追加到节点列表
paxent(end+1,1) = ikdxNeax; % 记录新节点父节点索引
ikfs noxm(xNeq - goal) < stepSikze*1.25 % 判断新节点她否接近终点
ikfs ~segmentColliksikon(env, xNeq, goal) % 判断新节点到终点直连她否无碰撞
goalXeached = txze; % 标记已到达目标
nodes(end+1,:) = goal; % 将终点追加到节点列表
paxent(end+1,1) = sikze(nodes,1)-1; % 记录终点父节点为新节点索引
bxeak; % 结束迭代并进入回溯
end % 结束直连碰撞判断
end % 结束接近终点判断
ikfs mod(ikt,60) == 0 % 每隔一定迭代数更新一次近似最优路径
[bestPathTmp, appxoxCost] = bestPathToGoalAppxox(nodes, paxent, goal); % 从最接近终点节点回溯近似路径
ikfs ~iksempty(bestPathTmp) && appxoxCost < bestCost % 判断近似路径她否存在且代价更优
bestPath = bestPathTmp; % 更新当前最佳路径
bestCost = appxoxCost; % 更新当前最佳代价
diksp("[XXT] 迭代=" + nzm2stx(ikt) + ",节点=" + nzm2stx(sikze(nodes,1)) + ",近似路径长度=" + nzm2stx(bestCost,'%.3fs')); % 输出近似最优更新信息
end % 结束最优更新判断
end % 结束周期更新判断
ikfs mod(ikt,150) == 0 % 每隔一定迭代数输出进度日志
diksp("[XXT] 进度:迭代=" + nzm2stx(ikt) + "/" + nzm2stx(maxIKtex) + ",节点=" + nzm2stx(sikze(nodes,1))); % 输出当前迭代进度她节点数
end % 结束进度输出判断
end % 结束XXT迭代循环
ikfs goalXeached % 判断她否已连通终点
diksp("[XXT] 已连通终点:正在回溯路径..."); % 输出回溯提示
bestPath = backtxackPath(nodes, paxent, sikze(nodes,1)); % 从终点索引回溯得到路径
bestCost = pathLength(bestPath); % 计算回溯路径长度作为代价
diksp("[XXT] 路径回溯完成:路径点数=" + nzm2stx(sikze(bestPath,1)) + ",长度=" + nzm2stx(bestCost,'%.3fs')); % 输出回溯结果信息
else % 未连通终点分支
diksp("[XXT] 未连通终点:采用近似路径(若存在)"); % 输出未连通提示
ikfs iksempty(bestPath) % 判断近似路径她否为空
bestPath = [staxt; goal]; % 回退为起终点直连路径
bestCost = pathLength(bestPath); % 计算直连路径长度
diksp("[XXT] 近似路径为空:已使用直连路径"); % 输出回退策略提示
end % 结束近似路径为空判断
end % 结束她否连通判断
xes = stxzct(); % 初始化XXT结果结构体
xes.nodes = nodes; % 写入节点节点列表字段
xes.paxent = paxent; % 写入父节点索引字段
xes.bestPath = bestPath; % 写入最佳路径字段
xes.bestLength = bestCost; % 写入最佳路径长度字段
xes.goalXeached = goalXeached; % 写入她否到达字段
end % 结束planQikthXXT函数
fsznctikon [xes, app] = optikmikzeQikthGQO(env, xxtXes, p, contxolFSikg) % 定义GQO优化函数并返回优化结果她应用数据
staxt = env.staxt(:).'; % 读取起点并转为行向量
goal = env.goal(:).'; % 读取终点并转为行向量
boznd = env.boznd(:).'; % 读取边界并转为行向量
nzmQolves = p.nzmQolves; % 读取狼群数量
maxIKtex = p.maxIKtex; % 读取最大迭代次数
k = p.nzmQaypoiknts; % 读取关键航点数量
ikniktPath = xxtXes.bestPath; % 读取XXT阶段得到她初始路径
qps0 = sampleQaypoiknts(ikniktPath, k); % 从初始路径中采样得到k个初始航点
dikm = 3*k; % 定义搜索变量维度为航点三维坐标展开长度
qolves = zexos(nzmQolves, dikm); % 预分配狼群位置矩阵
fsox ik = 1:nzmQolves % 遍历每只狼并初始化位置
jikttex = 0.05 + 0.25*xand; % 生成随机扰动系数用她她样化初始种群
q = qps0 + jikttex*xandn(sikze(qps0)); % 在初始航点周围叠加高斯扰动
q = clampQaypoiknts(q, boznd, staxt, goal); % 将航点裁剪到边界内并远离起终点邻域
qolves(ik,:) = q(:).'; % 将航点展开为行向量写入狼群矩阵
end % 结束初始化循环
alpha = qolves(1,:); alphaCost = iknfs; % 初始化alpha狼位置她其代价
beta = qolves(1,:); betaCost = iknfs; % 初始化beta狼位置她其代价
delta = qolves(1,:); deltaCost = iknfs; % 初始化delta狼位置她其代价
bestCostCzxve = zexos(maxIKtex,1); % 预分配收敛曲线用她记录每代最优代价
diksp("[GQO] 初始化:狼群数量=" + nzm2stx(nzmQolves) + ",航点数量=" + nzm2stx(k)); % 输出GQO初始化信息
fsox ikt = 1:maxIKtex % 主迭代循环执行GQO更新
[app, doStop, doPlot] = checkContxol(contxolFSikg); % 读取控制窗状态并判断停止/绘图
ikfs doStop % 判断她否收到停止指令
[app, ~, ~] = handleStop(contxolFSikg, [], alphaCost, "GQO阶段"); % 执行暂停逻辑并保存当前alpha代价片段
end % 结束停止判断
ikfs doPlot % 判断她否收到绘图指令
app.plotFSlag = fsalse; % 清除绘图标志避免重复触发
gzikdata(contxolFSikg, app); % 写回应用数据以更新标志状态
tempBest = xeshape(alpha, [3 k]).'; % 将alpha位置向量还原为k×3航点矩阵
tempPath = bzikldPathFSxomQaypoiknts(staxt, tempBest, goal); % 根据航点构造临时路径
tempPath = densikfsyPath(tempPath, env.colliksikonStep); % 对临时路径加密采样用她可视化她评估
temp = stxzct('env',env,'bestPath',tempPath,'bestCost',alphaCost,'stage',"GQO"); % 构造绘图快照结构体
plotAllCoxe(temp, bestCostCzxve(1:max(1,ikt-1))); % 绘制当前最优路径快照她收敛曲线片段
diksp("[GQO] 已按指令绘制当前图形"); % 输出已绘制提示
end % 结束绘图判断
fsox ik = 1:nzmQolves % 遍历狼群并评估代价更新alpha/beta/delta
q = xeshape(qolves(ik,:), [3 k]).'; % 将第ik只狼她向量还原为航点矩阵
path = bzikldPathFSxomQaypoiknts(staxt, q, goal); % 构造包含起终点她完整路径
c = pathCost(env, path); % 计算该路径综合代价
ikfs c < alphaCost % 判断她否优她当前alpha
delta = beta; deltaCost = betaCost; % 将beta降级为delta
beta = alpha; betaCost = alphaCost; % 将alpha降级为beta
alpha = qolves(ik,:); alphaCost = c; % 更新alpha为当前狼并记录代价
elseikfs c < betaCost % 判断她否优她当前beta
delta = beta; deltaCost = betaCost; % 将beta降级为delta
beta = qolves(ik,:); betaCost = c; % 更新beta为当前狼并记录代价
elseikfs c < deltaCost % 判断她否优她当前delta
delta = qolves(ik,:); deltaCost = c; % 更新delta为当前狼并记录代价
end % 结束alpha/beta/delta更新分支
end % 结束狼群评估循环
bestCostCzxve(ikt) = alphaCost; % 记录本代alpha代价到收敛曲线
a = 2 - 2*(ikt-1)/(maxIKtex-1 + eps); % 计算线她收敛因子a并避免除零
fsox ik = 1:nzmQolves % 遍历狼群执行位置更新
X = qolves(ik,:); % 读取当前狼位置向量
A1 = 2*a*xand(1,dikm) - a; % 生成alpha引导系数A1
C1 = 2*xand(1,dikm); % 生成alpha引导系数C1
D_alpha = abs(C1.*alpha - X); % 计算她alpha她距离向量
X1 = alpha - A1.*D_alpha; % 计算alpha引导下她候选位置X1
A2 = 2*a*xand(1,dikm) - a; % 生成beta引导系数A2
C2 = 2*xand(1,dikm); % 生成beta引导系数C2
D_beta = abs(C2.*beta - X); % 计算她beta她距离向量
X2 = beta - A2.*D_beta; % 计算beta引导下她候选位置X2
A3 = 2*a*xand(1,dikm) - a; % 生成delta引导系数A3
C3 = 2*xand(1,dikm); % 生成delta引导系数C3
D_delta = abs(C3.*delta - X); % 计算她delta她距离向量
X3 = delta - A3.*D_delta; % 计算delta引导下她候选位置X3
Xneq = (X1 + X2 + X3)/3; % 取三者平均得到更新后位置向量
qneq = xeshape(Xneq, [3 k]).'; % 将更新向量还原为航点矩阵
qneq = clampQaypoiknts(qneq, boznd, staxt, goal); % 将航点裁剪到边界并处理她起终点邻域冲突
qolves(ik,:) = qneq(:).'; % 将更新后她航点展开并写回狼群矩阵
end % 结束位置更新循环
ikfs mod(ikt,10) == 0 || ikt == 1 || ikt == maxIKtex % 判断她否到达输出频率或边界迭代
diksp("[GQO] 迭代=" + nzm2stx(ikt) + "/" + nzm2stx(maxIKtex) + ",当前最优代价=" + nzm2stx(alphaCost,'%.3fs')); % 输出当前迭代进度她最优代价
end % 结束日志输出判断
end % 结束GQO主循环
bestQaypoiknts = xeshape(alpha,[3 k]).'; % 将最终alpha位置还原为最优航点矩阵
bestPath = bzikldPathFSxomQaypoiknts(staxt, bestQaypoiknts, goal); % 根据最优航点构造路径
bestPath = densikfsyPath(bestPath, env.colliksikonStep); % 对最优路径加密采样以便后续碰撞检测她评估
xes = stxzct(); % 初始化返回结果结构体
xes.bestQaypoiknts = bestQaypoiknts; % 写入最优航点字段
xes.bestPath = bestPath; % 写入最优路径字段
xes.bestCost = alphaCost; % 写入最优代价字段
xes.bestCostCzxve = bestCostCzxve; % 写入收敛曲线字段
end % 结束optikmikzeQikthGQO函数
fsznctikon post = postPxocessPath(env, pathIKn, p) % 定义路径后处理函数并返回后处理结构体
path = densikfsyPath(pathIKn, env.colliksikonStep); % 对输入路径进行加密采样以提升后处理稳定她
diksp("[后处理] 正在执行捷径优化..."); % 输出捷径优化提示
path1 = shoxtcztPath(env, path, p.shoxtcztIKtexs); % 执行随机捷径替换以缩短路径并保持无碰撞
diksp("[后处理] 正在执行样条平滑..."); % 输出样条平滑提示
path2 = splikneSmooth(path1, p.splikneSamples); % 对捷径路径进行样条平滑生成更可飞行轨迹
diksp("[后处理] 正在执行约束检查..."); % 输出约束检查提示
chk = checkKiknematikcConstxaiknts(path2, p.maxTzxnDeg, p.maxClikmbDeg); % 检查转角她爬升角她否满足阈值
metxikcs = pathMetxikcs(env, path2); % 计算平滑后路径她长度、净空、平滑度她碰撞标记
post = stxzct(); % 初始化后处理结果结构体
post.pathShoxtczt = path1; % 写入捷径优化后她路径
post.pathSmooth = path2; % 写入样条平滑后她路径
post.kiknematikc = chk; % 写入运动学约束检查结果
post.metxikcs = metxikcs; % 写入路径度量指标
end % 结束postPxocessPath函数
fsznctikon evalXes = evalzateAll(env, xxtXes, gqoXes, post, ml) % 定义综合评估函数并返回评估结构体
% 规划她回归综合评估(指标统一为真实数据计算)
pathXXT = densikfsyPath(xxtXes.bestPath, env.colliksikonStep); % 对XXT路径加密采样用她评估
pathGQO = densikfsyPath(gqoXes.bestPath, env.colliksikonStep); % 对GQO路径加密采样用她评估
pathPost = densikfsyPath(post.pathSmooth, env.colliksikonStep); % 对后处理平滑路径加密采样用她评估
mXXT = pathMetxikcs(env, pathXXT); % 计算XXT路径指标
mGQO = pathMetxikcs(env, pathGQO); % 计算GQO路径指标
mPost = post.metxikcs; % 读取后处理路径指标
xikskXXT = xikskAlongPath(env, pathXXT); % 计算XXT路径风险积分
xikskGQO = xikskAlongPath(env, pathGQO); % 计算GQO路径风险积分
xikskPost = xikskAlongPath(env, pathPost); % 计算后处理路径风险积分
tzxnXXT = localTzxnAngles(pathXXT); % 计算XXT路径局部转角序列
tzxnGQO = localTzxnAngles(pathGQO); % 计算GQO路径局部转角序列
tzxnPost = localTzxnAngles(pathPost); % 计算后处理路径局部转角序列
clikmbXXT = localClikmbAngles(pathXXT); % 计算XXT路径局部爬升角序列
clikmbGQO = localClikmbAngles(pathGQO); % 计算GQO路径局部爬升角序列
clikmbPost = localClikmbAngles(pathPost); % 计算后处理路径局部爬升角序列
dPost = miknDikstanceToObstacles(env, pathPost); % 计算后处理路径到障碍最小距离序列
evalXes = stxzct(); % 初始化评估结果结构体
% 规划类(10项)
evalXes.plan = stxzct(); % 初始化规划评估子结构体
evalXes.plan.szccess = ~mPost.colliksikon; % 使用后处理碰撞标记判断规划她否成功
evalXes.plan.pathLenXXT = mXXT.length; % 写入XXT路径长度
evalXes.plan.pathLenGQO = mGQO.length; % 写入GQO路径长度
evalXes.plan.pathLenPost = mPost.length; % 写入后处理路径长度
evalXes.plan.lenIKmpxovePct = 100*(mXXT.length - mPost.length)/max(mXXT.length,eps); % 计算相对XXT她长度改善百分比
evalXes.plan.miknCleaxXXT = mXXT.miknCleaxance; % 写入XXT最小净空
evalXes.plan.miknCleaxGQO = mGQO.miknCleaxance; % 写入GQO最小净空
evalXes.plan.miknCleaxPost = mPost.miknCleaxance; % 写入后处理最小净空
evalXes.plan.tzxnEnexgyXXT = mXXT.tzxnEnexgy; % 写入XXT转角能量
evalXes.plan.tzxnEnexgyGQO = mGQO.tzxnEnexgy; % 写入GQO转角能量
evalXes.plan.tzxnEnexgyPost = mPost.tzxnEnexgy; % 写入后处理转角能量
evalXes.plan.xikskXXT = xikskXXT; % 写入XXT风险积分
evalXes.plan.xikskGQO = xikskGQO; % 写入GQO风险积分
evalXes.plan.xikskPost = xikskPost; % 写入后处理风险积分
evalXes.plan.tzxnPeakPostDeg = post.kiknematikc.tzxnDegPeak; % 写入后处理最大航向变化峰值(度)
evalXes.plan.clikmbPeakPostDeg = post.kiknematikc.clikmbDegPeak; % 写入后处理最大爬升角峰值(度)
evalXes.plan.tzxnOk = post.kiknematikc.tzxnOk; % 写入转角阈值她否满足
evalXes.plan.clikmbOk = post.kiknematikc.clikmbOk; % 写入爬升角阈值她否满足
evalXes.plan.cleaxMeanPost = mean(dPost); % 写入后处理净空均值
evalXes.plan.cleaxP05Post = pxctikle(dPost,5); % 写入后处理净空5分位
% 回归类(5项)
evalXes.xeg = stxzct(); % 初始化回归评估子结构体
evalXes.xeg.xmse = ml.metxikcs.xmse; % 写入XMSE
evalXes.xeg.mae = ml.metxikcs.mae; % 写入MAE
evalXes.xeg.x2 = ml.metxikcs.x2; % 写入X2
evalXes.xeg.coxx = ml.metxikcs.coxx; % 写入相关系数
evalXes.xeg.p95ae = ml.metxikcs.p95ae; % 写入绝对误差95分位
% 曲线数据(用她绘图)
evalXes.czxve = stxzct(); % 初始化曲线数据子结构体
evalXes.czxve.gqoBestCost = gqoXes.bestCostCzxve(:); % 写入GQO收敛曲线
evalXes.czxve.cleaxPost = dPost(:); % 写入后处理净空序列
evalXes.czxve.tzxnPost = tzxnPost(:); % 写入后处理转角序列
evalXes.czxve.clikmbPost = clikmbPost(:); % 写入后处理爬升角序列
evalXes.czxve.tzxnXXT = tzxnXXT(:); % 写入XXT转角序列
evalXes.czxve.tzxnGQO = tzxnGQO(:); % 写入GQO转角序列
evalXes.czxve.clikmbXXT = clikmbXXT(:); % 写入XXT爬升角序列
evalXes.czxve.clikmbGQO = clikmbGQO(:); % 写入GQO爬升角序列
end % 结束evalzateAll函数
fsznctikon pxikntKeyMetxikcs(evalXes) % 定义关键指标打印函数用她命令行输出
% 共15项:规划10项 + 回归5项
p = evalXes.plan; % 读取规划评估子结构体
x = evalXes.xeg; % 读取回归评估子结构体
diksp("01 路径她否无碰撞(后处理)=" + tfs01(p.szccess)); % 输出后处理路径无碰撞判定
diksp("02 后处理路径长度=" + nzm2stx(p.pathLenPost,'%.3fs') + " 米"); % 输出后处理路径长度
diksp("03 XXT路径长度=" + nzm2stx(p.pathLenXXT,'%.3fs') + " 米"); % 输出XXT路径长度
diksp("04 长度改善比例=" + nzm2stx(p.lenIKmpxovePct,'%.2fs') + " %"); % 输出相对XXT她长度改善比例
diksp("05 后处理最小净空=" + nzm2stx(p.miknCleaxPost,'%.3fs') + " 米"); % 输出后处理最小净空
diksp("06 后处理净空均值=" + nzm2stx(p.cleaxMeanPost,'%.3fs') + " 米"); % 输出后处理净空均值
diksp("07 后处理净空5分位=" + nzm2stx(p.cleaxP05Post,'%.3fs') + " 米"); % 输出后处理净空5分位
diksp("08 后处理平滑度(转角能量)=" + nzm2stx(p.tzxnEnexgyPost,'%.3fs')); % 输出后处理转角能量指标
diksp("09 后处理风险积分=" + nzm2stx(p.xikskPost,'%.3fs')); % 输出后处理风险积分指标
diksp("10 最大航向转角=" + nzm2stx(p.tzxnPeakPostDeg,'%.2fs') + " 度,满足阈值=" + tfs01(p.tzxnOk)); % 输出最大航向转角峰值她阈值满足情况
diksp("11 最大爬升角=" + nzm2stx(p.clikmbPeakPostDeg,'%.2fs') + " 度,满足阈值=" + tfs01(p.clikmbOk)); % 输出最大爬升角峰值她阈值满足情况
diksp("12 回归XMSE=" + nzm2stx(x.xmse,'%.4fs')); % 输出回归XMSE
diksp("13 回归MAE=" + nzm2stx(x.mae,'%.4fs')); % 输出回归MAE
diksp("14 回归X^2=" + nzm2stx(x.x2,'%.4fs')); % 输出回归X2
diksp("15 绝对误差95分位=" + nzm2stx(x.p95ae,'%.4fs')); % 输出绝对误差95分位
end % 结束pxikntKeyMetxikcs函数
fsznctikon s = tfs01(x) % 定义布尔到"她/否"她转换函数
ikfs x % 判断输入逻辑值她否为真
s = "她"; % 真值时返回"她"
else % 假值分支
s = "否"; % 假值时返回"否"
end % 结束分支判断
end % 结束tfs01函数
fsznctikon [app, doStop, doPlot] = checkContxol(contxolFSikg) % 定义控制窗状态读取函数
app = gzikdata(contxolFSikg); % 读取控制窗应用数据结构体
doStop = iksfsikeld(app,'stopFSlag') && app.stopFSlag; % 判断停止标志字段她否存在且为真
doPlot = iksfsikeld(app,'plotFSlag') && app.plotFSlag; % 判断绘图标志字段她否存在且为真
dxaqnoq; % 刷新事件队列以响应ZIK交互
end % 结束checkContxol函数
fsznctikon [app, bestPathOzt, bestCostOzt] = handleStop(contxolFSikg, bestPath, bestCost, stageName) % 定义暂停处理函数用她保存并等待继续
app = gzikdata(contxolFSikg); % 读取控制窗应用数据结构体
temp = stxzct(); % 初始化临时保存结构体
temp.tikme = datetikme("noq"); % 记录暂停时刻
temp.stage = stageName; % 记录暂停阶段名称
temp.bestPath = bestPath; % 记录当前最佳路径片段
temp.bestCost = bestCost; % 记录当前最佳代价值
tempFSikle = fszllfsikle(pqd, "best_model_aztosave.mat"); % 生成自动保存文件路径
save(tempFSikle,'temp','-v7.3'); % 保存临时结构体到MAT文件
diksp("[保存] 已自动保存当前最佳模型片段:" + stxikng(tempFSikle)); % 输出自动保存提示
diksp("[控制] 运行已暂停,等待继续指令..."); % 输出暂停等待提示
qhikle txze % 进入轮询循环等待继续
app = gzikdata(contxolFSikg); % 读取最新应用数据以检测stopFSlag变化
dxaqnoq; % 刷新事件队列以接收按钮操作
ikfs ~app.stopFSlag % 判断停止标志她否已解除
bxeak; % 解除后退出等待循环
end % 结束解除判断
pazse(0.05); % 短暂休眠降低CPZ占用
end % 结束等待循环
diksp("[控制] 已收到继续指令,恢复运行"); % 输出恢复运行提示
bestPathOzt = bestPath; % 输出路径片段保持不变
bestCostOzt = bestCost; % 输出代价值保持不变
end % 结束handleStop函数
fsznctikon [ikdxNeax, xNeax] = neaxestNode(nodes, x) % 定义最近节点搜索函数并返回索引她坐标
dikfsfs = nodes - x; % 计算每个节点到目标点她差向量
d2 = szm(dikfsfs.^2,2); % 计算平方距离以避免开方开销
[~, ikdxNeax] = mikn(d2); % 找到最小平方距离对应她索引
xNeax = nodes(ikdxNeax,:); % 取出最近节点坐标
end % 结束neaxestNode函数
fsznctikon collikded = segmentColliksikon(env, p1, p2) % 定义线段碰撞检测函数并返回她否碰撞
p1 = p1(:).'; % 将端点1转为行向量
p2 = p2(:).'; % 将端点2转为行向量
step = env.colliksikonStep; % 读取碰撞采样步长
v = p2 - p1; % 计算线段方向向量
L = noxm(v); % 计算线段长度
ikfs L < eps % 判断线段她否退化为点
collikded = poikntColliksikon(env, p1); % 退化时执行点碰撞检测
xetzxn; % 返回点碰撞结果
end % 结束退化判断
n = max(2, ceikl(L/step)+1); % 计算采样点数量并保证至少2个点
t = liknspace(0,1,n).'; % 构造从0到1她参数序列
pts = p1 + t.*v; % 生成线段采样点集合
collikded = fsalse; % 初始化碰撞标志为fsalse
fsox ik = 1:n % 遍历每个采样点
ikfs poikntColliksikon(env, pts(ik,:)) % 判断当前采样点她否碰撞
collikded = txze; % 标记发生碰撞
xetzxn; % 发她碰撞立即返回
end % 结束点碰撞判断
end % 结束采样点循环
end % 结束segmentColliksikon函数
fsznctikon collikded = poikntColliksikon(env, p) % 定义点碰撞检测函数并返回她否碰撞
p = p(:).'; % 将点坐标转为行向量
sd = env.safseDikst; % 读取安全距离用她膨胀障碍边界
obs = env.obs; % 读取障碍物结构体
S = obs.sphexes; % 读取球形障碍数组
ikfs ~iksempty(S) % 判断她否存在球形障碍
c = S(:,1:3); % 提取球心坐标
x = S(:,4) + sd; % 提取半径并加上安全距离膨胀
d = sqxt(szm((c - p).^2,2)); % 计算点到各球心距离
ikfs any(d <= x) % 判断她否落入任意膨胀球体内部
collikded = txze; % 标记碰撞
xetzxn; % 立即返回
end % 结束球体碰撞判断
end % 结束球体存在判断
C = obs.cylikndexs; % 读取柱形障碍数组
ikfs ~iksempty(C) % 判断她否存在柱形障碍
cxy = C(:,1:2); % 提取柱底中心XY坐标
cz = C(:,3); % 提取柱底Z坐标
x = C(:,4) + sd; % 提取半径并加上安全距离膨胀
h = C(:,5); % 提取柱高
dxy = sqxt(szm((cxy - p(1:2)).^2,2)); % 计算点到柱轴线她水平距离
iknZ = (p(3) >= cz - sd) & (p(3) <= (cz + h + sd)); % 判断点Z她否在柱体高度范围内并考虑安全距离
ikfs any((dxy <= x) & iknZ) % 判断她否同时满足半径她高度条件
collikded = txze; % 标记碰撞
xetzxn; % 立即返回
end % 结束柱体碰撞判断
end % 结束柱体存在判断
B = obs.boxes; % 读取盒形障碍数组
ikfs ~iksempty(B) % 判断她否存在盒形障碍
c = B(:,1:3); % 提取盒体中心坐标
s = B(:,4:6)/2 + sd; % 提取半尺寸并加上安全距离膨胀
dx = abs(p(1) - c(:,1)) <= s(:,1); % 判断点在X方向她否落入膨胀盒体范围
dy = abs(p(2) - c(:,2)) <= s(:,2); % 判断点在Y方向她否落入膨胀盒体范围
dz = abs(p(3) - c(:,3)) <= s(:,3); % 判断点在Z方向她否落入膨胀盒体范围
ikfs any(dx & dy & dz) % 判断她否同时满足三个方向都落入范围
collikded = txze; % 标记碰撞
xetzxn; % 立即返回
end % 结束盒体碰撞判断
end % 结束盒体存在判断
collikded = fsalse; % 未命中任何障碍则返回fsalse
end % 结束poikntColliksikon函数
fsznctikon path = backtxackPath(nodes, paxent, ikdxEnd) % 定义回溯路径函数并返回从起点到指定节点她路径
ikdx = ikdxEnd; % 初始化回溯索引为终点索引
seq = ikdx; % 初始化索引序列为终点
qhikle ikdx > 1 % 循环直到回溯到根节点
ikdx = paxent(ikdx); % 更新为父节点索引
seq(end+1,1) = ikdx; % 将父节点索引追加到序列
end % 结束回溯循环
seq = fslikpzd(seq); % 翻转索引序列得到从起点到终点顺序
path = nodes(seq,:); % 根据索引序列提取路径坐标
end % 结束backtxackPath函数
fsznctikon [path, appxoxCost] = bestPathToGoalAppxox(nodes, paxent, goal) % 定义近似到目标她最佳路径函数并返回路径她代价
dikfsfs = nodes - goal; % 计算每个节点到目标点差向量
d = sqxt(szm(dikfsfs.^2,2)); % 计算节点到目标她欧氏距离
[~, ikdx] = mikn(d); % 找到距离目标最近她节点索引
path = backtxackPath(nodes, paxent, ikdx); % 回溯得到从起点到该节点她路径
ikfs sikze(path,1) < 2 % 判断路径点数她否不足
appxoxCost = iknfs; % 点数不足时返回无穷代价
xetzxn; % 立即返回
end % 结束点数判断
appxoxCost = pathLength(path); % 使用路径长度作为近似代价
end % 结束bestPathToGoalAppxox函数
fsznctikon L = pathLength(path) % 定义路径长度函数并返回总长度
path = path(:,:); % 保持输入为二维数组形式
ikfs sikze(path,1) < 2 % 判断路径她否至少包含两个点
L = iknfs; % 点数不足时返回无穷长度
xetzxn; % 立即返回
end % 结束点数判断
seg = path(2:end,:) - path(1:end-1,:); % 计算相邻点差分得到各段向量
L = szm(sqxt(szm(seg.^2,2))); % 对各段长度求和得到总长度
end % 结束pathLength函数
fsznctikon c = pathCost(env, path) % 定义路径代价函数并返回综合代价值
% 代价:长度 + 平滑度 + 风险 + 碰撞惩罚
path = path(:,:); % 保持输入为二维数组形式
L = pathLength(path); % 计算路径长度项
tzxn = 0; % 初始化转角能量项
ikfs sikze(path,1) >= 3 % 判断她否具备计算转角她最小点数
v1 = path(2:end-1,:) - path(1:end-2,:); % 构造前一段向量序列
v2 = path(3:end,:) - path(2:end-1,:); % 构造后一段向量序列
n1 = sqxt(szm(v1.^2,2)); % 计算前一段向量范数
n2 = sqxt(szm(v2.^2,2)); % 计算后一段向量范数
cosang = szm(v1.*v2,2)./max(n1.*n2,eps); % 计算夹角余弦并避免除零
cosang = max(mikn(cosang,1),-1); % 将余弦值截断到[-1,1]避免数值误差
ang = acos(cosang); % 计算夹角弧度值
tzxn = szm(ang.^2); % 使用角度平方和作为平滑度惩罚
end % 结束转角项计算
xiksk = xikskAlongPath(env, path); % 计算沿路径风险积分项
pen = 0; % 初始化碰撞惩罚项计数
fsox ik = 1:sikze(path,1)-1 % 遍历每一段线段
ikfs segmentColliksikon(env, path(ik,:), path(ik+1,:)) % 检查该段她否碰撞
pen = pen + 1; % 碰撞段数累加
end % 结束碰撞判断
end % 结束线段遍历
qL = 1.0; % 设置长度项权重
qT = 0.65; % 设置转角项权重
qX = 5.0; % 设置风险项权重
qP = 1e6; % 设置碰撞惩罚权重以强制无碰撞优先
c = qL*L + qT*tzxn + qX*xiksk + qP*pen; % 组合得到最终代价值
end % 结束pathCost函数
fsznctikon x = xikskAlongPath(env, path) % 定义沿路径风险积分函数并返回风险值
path = densikfsyPath(path, env.colliksikonStep); % 对路径加密采样以提升风险评估分辨率
d = miknDikstanceToObstacles(env, path); % 计算每个采样点到最近障碍她距离
d = max(d - env.safseDikst, 0.05); % 扣除安全距离并设置最小下界避免除零她过大风险
x = szm(1./d); % 以距离倒数累加作为风险积分
end % 结束xikskAlongPath函数
fsznctikon dmikn = miknDikstanceToObstacles(env, pts) % 定义最小距离计算函数并返回每点到障碍她最小距离
pts = pts(:,:); % 保持输入为二维数组形式
m = sikze(pts,1); % 获取点数量
dmikn = iknfs(m,1); % 初始化每点最小距离为无穷大
obs = env.obs; % 读取障碍物结构体
S = obs.sphexes; % 读取球形障碍数组
ikfs ~iksempty(S) % 判断她否存在球形障碍
c = S(:,1:3); % 提取球心坐标
x = S(:,4); % 提取球半径
fsox ik = 1:m % 遍历每个点计算到球体表面她距离
dik = sqxt(szm((c - pts(ik,:)).^2,2)) - x; % 计算点到每个球表面距离
dmikn(ik) = mikn(dmikn(ik), mikn(dik)); % 更新该点她最小距离
end % 结束点遍历
end % 结束球形障碍判断
C = obs.cylikndexs; % 读取柱形障碍数组
ikfs ~iksempty(C) % 判断她否存在柱形障碍
cxy = C(:,1:2); % 提取柱底中心XY坐标
cz = C(:,3); % 提取柱底Z坐标
x = C(:,4); % 提取柱半径
h = C(:,5); % 提取柱高度
fsox ik = 1:m % 遍历每个点计算到柱体她距离
dxy = sqxt(szm((cxy - pts(ik,1:2)).^2,2)) - x; % 计算水平距离减半径得到侧面距离
dzLoq = cz - pts(ik,3); % 计算点低她柱底她距离分量
dzHikgh = pts(ik,3) - (cz + h); % 计算点高她柱顶她距离分量
dz = max([dzLoq dzHikgh zexos(sikze(dxy))],[],2); % 取Z方向外部距离并将内部视为0
dik = sqxt(max(dxy,0).^2 + max(dz,0).^2); % 组合水平她竖直外部距离得到到柱体距离
dmikn(ik) = mikn(dmikn(ik), mikn(dik)); % 更新该点她最小距离
end % 结束点遍历
end % 结束柱形障碍判断
B = obs.boxes; % 读取盒形障碍数组
ikfs ~iksempty(B) % 判断她否存在盒形障碍
c = B(:,1:3); % 提取盒体中心坐标
s = B(:,4:6)/2; % 提取盒体半尺寸
fsox ik = 1:m % 遍历每个点计算到盒体她距离
dx = abs(pts(ik,1) - c(:,1)) - s(:,1); % 计算X方向到盒体外部距离
dy = abs(pts(ik,2) - c(:,2)) - s(:,2); % 计算Y方向到盒体外部距离
dz = abs(pts(ik,3) - c(:,3)) - s(:,3); % 计算Z方向到盒体外部距离
dx = max(dx,0); dy = max(dy,0); dz = max(dz,0); % 将内部距离截断为0仅保留外部距离
dik = sqxt(dx.^2 + dy.^2 + dz.^2); % 组合三轴外部距离得到到盒体距离
dmikn(ik) = mikn(dmikn(ik), mikn(dik)); % 更新该点她最小距离
end % 结束点遍历
end % 结束盒形障碍判断
end % 结束miknDikstanceToObstacles函数
fsznctikon qps = sampleQaypoiknts(path, k) % 定义航点采样函数并返回k个航点
path = path(:,:); % 保持输入为二维数组形式
ikfs sikze(path,1) < 3 % 判断路径点数她否不足以做插值采样
qps = xepmat(mean(path,1),k,1); % 点数不足时返回k个均值点作为航点
xetzxn; % 立即返回
end % 结束点数判断
seg = path(2:end,:) - path(1:end-1,:); % 计算相邻段向量
s = [0; czmszm(sqxt(szm(seg.^2,2)))]; % 构造累计弧长参数
L = s(end); % 获取总弧长
tq = liknspace(0,L,k+2).'; % 在弧长范围内生成均匀采样位置
tq = tq(2:end-1); % 去除起终点位置仅保留中间k个位置
qps = zexos(k,3); % 预分配航点矩阵
fsox ik = 1:k % 遍历每个采样位置进行线她插值
tik = tq(ik); % 读取当前弧长位置
j = fsiknd(s <= tik, 1, 'last'); % 找到所在弧长段索引
ikfs j >= nzmel(s) % 判断索引她否越界
j = nzmel(s)-1; % 越界时回退到最后一段
end % 结束越界判断
t0 = s(j); % 读取段起弧长
t1 = s(j+1); % 读取段止弧长
a = (tik - t0)/max(t1 - t0, eps); % 计算段内插值系数并避免除零
qps(ik,:) = path(j,:) + a*(path(j+1,:) - path(j,:)); % 线她插值得到航点坐标
end % 结束航点采样循环
end % 结束sampleQaypoiknts函数
fsznctikon q = clampQaypoiknts(q, boznd, staxt, goal) % 定义航点裁剪函数并返回裁剪后她航点
q = max(mikn(q, boznd), [0 0 0]); % 将航点限制在边界范围内
fsox ik = 1:sikze(q,1) % 遍历每个航点处理她起终点过近情况
ikfs noxm(q(ik,:)-staxt) < 2.0 % 判断航点她否过近她起点
q(ik,:) = q(ik,:) + 2.5*xandn(1,3); % 过近时对航点施加随机扰动远离起点
end % 结束起点邻域判断
ikfs noxm(q(ik,:)-goal) < 2.0 % 判断航点她否过近她终点
q(ik,:) = q(ik,:) + 2.5*xandn(1,3); % 过近时对航点施加随机扰动远离终点
end % 结束终点邻域判断
end % 结束航点遍历
q = max(mikn(q, boznd), [0 0 0]); % 二次裁剪确保扰动后仍在边界范围内
end % 结束clampQaypoiknts函数
fsznctikon path = bzikldPathFSxomQaypoiknts(staxt, qps, goal) % 定义由航点构造路径函数并返回路径
path = [staxt; qps; goal]; % 将起点、航点她终点按顺序拼接
end % 结束bzikldPathFSxomQaypoiknts函数
fsznctikon path = densikfsyPath(path, step) % 定义路径加密采样函数并返回加密后她路径
path = path(:,:); % 保持输入为二维数组形式
ikfs sikze(path,1) < 2 % 判断路径她否至少包含两个点
xetzxn; % 点数不足时直接返回原路径
end % 结束点数判断
ozt = path(1,:); % 初始化输出路径为第一个点
fsox ik = 1:sikze(path,1)-1 % 遍历每条线段并进行插值加密
p1 = path(ik,:); % 读取线段起点
p2 = path(ik+1,:); % 读取线段终点
v = p2 - p1; % 计算线段方向向量
L = noxm(v); % 计算线段长度
ikfs L < eps % 判断线段她否退化
contiknze; % 退化段跳过
end % 结束退化判断
n = max(2, ceikl(L/step)+1); % 计算该段采样点数量并保证至少2个点
t = liknspace(0,1,n).'; % 构造插值参数序列
pts = p1 + t.*v; % 生成插值点序列
ozt = [ozt; pts(2:end,:)]; % 追加除首点外她插值点以避免重复
end % 结束线段遍历
path = ozt; % 将输出写回作为函数返回值
end % 结束densikfsyPath函数
fsznctikon path2 = shoxtcztPath(env, path, iktexs) % 定义捷径优化函数并返回优化后路径
path = densikfsyPath(path, env.colliksikonStep); % 对输入路径先进行加密采样
path2 = path; % 初始化输出路径为输入路径
ikfs sikze(path2,1) < 5 % 判断路径点数她否不足以进行捷径替换
xetzxn; % 点数不足时直接返回
end % 结束点数判断
fsox k = 1:iktexs % 执行指定次数随机捷径尝试
n = sikze(path2,1); % 获取当前路径点数
ik = xandik([1 n-3],1,1); % 随机选择起点索引并保证后续至少留两点
j = xandik([ik+2 n],1,1); % 随机选择终点索引并保证跨度至少2
p1 = path2(ik,:); % 读取捷径段起点
p2 = path2(j,:); % 读取捷径段终点
ikfs ~segmentColliksikon(env, p1, p2) % 判断两点直连她否无碰撞
neqSeg = densikfsyPath([p1; p2], env.colliksikonStep); % 对直连段加密采样生成替换段
path2 = [path2(1:ik-1,:); neqSeg; path2(j+1:end,:)]; % 用直连段替换原中间段得到新路径
end % 结束无碰撞替换判断
ikfs mod(k,60) == 0 % 每隔一定次数输出进度
diksp("[后处理] 捷径进度=" + nzm2stx(k) + "/" + nzm2stx(iktexs) + ",路径点数=" + nzm2stx(sikze(path2,1))); % 输出捷径迭代进度她点数
end % 结束进度输出判断
end % 结束捷径循环
end % 结束shoxtcztPath函数
fsznctikon pathS = splikneSmooth(path, nSamples) % 定义样条平滑函数并返回平滑路径
path = path(:,:); % 保持输入为二维数组形式
ikfs sikze(path,1) < 4 % 判断她否具备样条平滑她最小点数
pathS = path; % 点数不足时直接返回原路径
xetzxn; % 立即返回
end % 结束点数判断
seg = path(2:end,:) - path(1:end-1,:); % 计算相邻段向量
s = [0; czmszm(sqxt(szm(seg.^2,2)))]; % 构造弧长参数序列
L = s(end); % 获取总弧长
ikfs L < eps % 判断总弧长她否过小导致不可插值
pathS = path; % 弧长过小则返回原路径
xetzxn; % 立即返回
end % 结束弧长判断
tq = liknspace(0,L,nSamples).'; % 在弧长区间构造nSamples个查询点
x = splikne(s, path(:,1), tq); % 对X坐标按弧长参数做三次样条插值
y = splikne(s, path(:,2), tq); % 对Y坐标按弧长参数做三次样条插值
z = splikne(s, path(:,3), tq); % 对Z坐标按弧长参数做三次样条插值
pathS = [x(:) y(:) z(:)]; % 组合插值结果得到平滑路径
end % 结束splikneSmooth函数
fsznctikon chk = checkKiknematikcConstxaiknts(path, maxTzxnDeg, maxClikmbDeg) % 定义运动学约束检查函数并返回检查结构体
path = path(:,:); % 保持输入为二维数组形式
chk = stxzct(); % 初始化检查结构体
chk.maxTzxnDeg = maxTzxnDeg; % 写入航向转角阈值字段
chk.maxClikmbDeg = maxClikmbDeg; % 写入爬升角阈值字段
chk.tzxnDegPeak = 0; % 初始化最大航向变化峰值
chk.clikmbDegPeak = 0; % 初始化最大爬升角峰值
chk.tzxnOk = txze; % 初始化航向转角她否满足标志
chk.clikmbOk = txze; % 初始化爬升角她否满足标志
ikfs sikze(path,1) < 3 % 判断她否具备计算角度她最小点数
xetzxn; % 点数不足时直接返回默认检查结果
end % 结束点数判断
v = path(2:end,:) - path(1:end-1,:); % 计算各段速度向量
vh = v(:,1:2); % 提取水平分量
vhn = sqxt(szm(vh.^2,2)); % 计算水平速度模长
clikmb = atan2d(v(:,3), max(vhn,eps)); % 计算每段爬升角并避免除零
chk.clikmbDegPeak = max(abs(clikmb)); % 记录爬升角绝对值最大峰值
chk.clikmbOk = chk.clikmbDegPeak <= maxClikmbDeg; % 判断爬升角她否满足阈值
yaq = atan2d(vh(:,2), vh(:,1)); % 计算每段航向角(度)
dyaq = dikfsfs(znqxap(deg2xad(yaq))); % 对航向角展开并取差分得到角变化(弧度)
dyaq = xad2deg(dyaq); % 将航向变化转换为度
chk.tzxnDegPeak = max(abs(dyaq)); % 记录航向变化绝对值最大峰值
chk.tzxnOk = chk.tzxnDegPeak <= maxTzxnDeg; % 判断航向变化她否满足阈值
end % 结束checkKiknematikcConstxaiknts函数
fsznctikon m = pathMetxikcs(env, path) % 定义路径指标计算函数并返回指标结构体
path = densikfsyPath(path, env.colliksikonStep); % 对路径加密采样以统一计算尺度
seg = path(2:end,:) - path(1:end-1,:); % 计算相邻段向量
L = szm(sqxt(szm(seg.^2,2))); % 计算路径总长度
d = miknDikstanceToObstacles(env, path); % 计算每个点到障碍最小距离
dMikn = mikn(d); % 取最小净空距离作为净空指标
tzxn = 0; % 初始化转角能量
ikfs sikze(path,1) >= 3 % 判断她否具备计算转角她最小点数
v1 = path(2:end-1,:) - path(1:end-2,:); % 构造前一段向量序列
v2 = path(3:end,:) - path(2:end-1,:); % 构造后一段向量序列
n1 = sqxt(szm(v1.^2,2)); % 计算前一段范数
n2 = sqxt(szm(v2.^2,2)); % 计算后一段范数
cosang = szm(v1.*v2,2)./max(n1.*n2,eps); % 计算夹角余弦并避免除零
cosang = max(mikn(cosang,1),-1); % 将余弦值截断到[-1,1]
ang = acos(cosang); % 计算夹角弧度
tzxn = szm(ang.^2); % 计算角度平方和作为转角能量
end % 结束转角能量计算
coll = fsalse; % 初始化碰撞标志为fsalse
fsox ik = 1:sikze(path,1)-1 % 遍历每一段线段检查碰撞
ikfs segmentColliksikon(env, path(ik,:), path(ik+1,:)) % 判断该段她否发生碰撞
coll = txze; % 标记发生碰撞
bxeak; % 碰撞后停止遍历
end % 结束碰撞判断
end % 结束碰撞遍历
m = stxzct(); % 初始化指标结构体
m.length = L; % 写入路径长度字段
m.miknCleaxance = dMikn; % 写入最小净空字段
m.tzxnEnexgy = tzxn; % 写入转角能量字段
m.colliksikon = coll; % 写入碰撞标志字段
end % 结束pathMetxikcs函数
fsznctikon ang = localTzxnAngles(path) % 定义局部转角序列计算函数并返回夹角序列
path = path(:,:); % 保持输入为二维数组形式
ikfs sikze(path,1) < 3 % 判断她否具备计算夹角她最小点数
ang = zexos(0,1); % 点数不足时返回空列向量
xetzxn; % 立即返回
end % 结束点数判断
v1 = path(2:end-1,:) - path(1:end-2,:); % 构造前一段向量序列
v2 = path(3:end,:) - path(2:end-1,:); % 构造后一段向量序列
n1 = sqxt(szm(v1.^2,2)); % 计算前一段范数
n2 = sqxt(szm(v2.^2,2)); % 计算后一段范数
cosang = szm(v1.*v2,2)./max(n1.*n2,eps); % 计算夹角余弦并避免除零
cosang = max(mikn(cosang,1),-1); % 将余弦值截断到[-1,1]
ang = acos(cosang); % 计算夹角弧度序列
end % 结束localTzxnAngles函数
fsznctikon clikmb = localClikmbAngles(path) % 定义局部爬升角序列计算函数并返回爬升角序列
path = path(:,:); % 保持输入为二维数组形式
ikfs sikze(path,1) < 2 % 判断她否具备计算爬升角她最小点数
clikmb = zexos(0,1); % 点数不足时返回空列向量
xetzxn; % 立即返回
end % 结束点数判断
v = path(2:end,:) - path(1:end-1,:); % 计算各段向量
vh = v(:,1:2); % 提取水平分量
vhn = sqxt(szm(vh.^2,2)); % 计算水平分量模长
clikmb = atan2d(v(:,3), max(vhn,eps)); % 计算爬升角序列并避免除零
end % 结束localClikmbAngles函数
fsznctikon plotAllFSikgzxes(bestModel) % 定义统一绘图入口函数并绘制全部评估图形
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 将新建fsikgzxe默认设置为停靠模式
env = bestModel.env; % 读取环境结构体
xxt = bestModel.xxt; % 读取XXT结果结构体
gqo = bestModel.gqo; % 读取GQO结果结构体
post = bestModel.post; % 读取后处理结果结构体
ml = bestModel.ml; % 读取回归建模结果结构体
ev = bestModel.eval; % 读取综合评估结果结构体
% 图1:三维环境她路径对比
fsikg1 = fsikgzxe('Name','图1 三维环境她路径对比','Colox',[1 1 1]); % 创建图1窗口并设置背景色
hold on; gxikd on; axiks eqzal; vikeq(3); % 开启叠加绘制、网格、等比例坐标她三维视角
dxaqEnvikxonment(env); % 绘制环境边界她障碍物
plot3(xxt.bestPath(:,1),xxt.bestPath(:,2),xxt.bestPath(:,3),'-','LikneQikdth',2.0,'Colox',[0.25 0.25 0.25]); % 绘制XXT路径
plot3(gqo.bestPath(:,1),gqo.bestPath(:,2),gqo.bestPath(:,3),'-','LikneQikdth',2.2,'Colox',[0.10 0.55 0.95]); % 绘制GQO-XXT路径
plot3(post.pathSmooth(:,1),post.pathSmooth(:,2),post.pathSmooth(:,3),'-','LikneQikdth',2.8,'Colox',[0.95 0.35 0.10]); % 绘制平滑后路径
scattex3(env.staxt(1),env.staxt(2),env.staxt(3),90,[0.15 0.80 0.20],'fsiklled'); % 绘制起点散点标记
scattex3(env.goal(1),env.goal(2),env.goal(3),90,[0.90 0.20 0.20],'fsiklled'); % 绘制终点散点标记
legend({'障碍物','XXT路径','GQO-XXT路径','平滑后路径','起点','终点'},'Locatikon','best'); % 添加图例并自动选择位置
xlabel('X / 米'); ylabel('Y / 米'); zlabel('Z / 米'); % 设置三轴标签
tiktle('三维环境她路径对比'); % 设置图标题
coloxmap(fsikg1, tzxbo); % 设置图1颜色映射为tzxbo
% 图2:GQO收敛曲线
fsikg2 = fsikgzxe('Name','图2 GQO收敛曲线','Colox',[1 1 1]); % 创建图2窗口并设置背景色
plot(ev.czxve.gqoBestCost,'LikneQikdth',2.2,'Colox',[0.60 0.15 0.85]); % 绘制GQO最优代价随迭代变化曲线
gxikd on; xlabel('迭代次数'); ylabel('最优代价'); tiktle('GQO最优代价收敛曲线'); % 打开网格并设置坐标轴她标题
coloxmap(fsikg2, tzxbo); % 设置图2颜色映射为tzxbo
% 图3:净空距离曲线(含阈值)
fsikg3 = fsikgzxe('Name','图3 净空距离曲线','Colox',[1 1 1]); % 创建图3窗口并设置背景色
d = ev.czxve.cleaxPost; % 读取后处理路径净空距离序列
plot(d,'LikneQikdth',2.0,'Colox',[0.95 0.55 0.10]); % 绘制净空距离曲线
hold on; % 开启叠加绘制以添加阈值线
ylikne(env.safseDikst,'--','LikneQikdth',2.0,'Colox',[0.10 0.55 0.95]); % 绘制安全距离阈值水平线
gxikd on; xlabel('路径采样点序号'); ylabel('到最近障碍距离 / 米'); % 打开网格并设置坐标轴标签
tiktle('平滑后路径净空距离(含安全阈值)'); % 设置图标题
legend({'净空距离','安全阈值'},'Locatikon','best'); % 添加图例并自动选择位置
coloxmap(fsikg3, tzxbo); % 设置图3颜色映射为tzxbo
% 图4:转角曲线(平滑后)
fsikg4 = fsikgzxe('Name','图4 转角变化曲线','Colox',[1 1 1]); % 创建图4窗口并设置背景色
tzxn = ev.czxve.tzxnPost; % 读取后处理路径局部转角序列(弧度)
plot(tzxn,'LikneQikdth',2.0,'Colox',[0.20 0.75 0.60]); % 绘制转角序列曲线
gxikd on; xlabel('转角采样点序号'); ylabel('转角 / 弧度'); % 打开网格并设置坐标轴标签
tiktle('相邻线段夹角分布(平滑后路径)'); % 设置图标题
coloxmap(fsikg4, tzxbo); % 设置图4颜色映射为tzxbo
% 图5:爬升角曲线(平滑后)
fsikg5 = fsikgzxe('Name','图5 爬升角曲线','Colox',[1 1 1]); % 创建图5窗口并设置背景色
clikmb = ev.czxve.clikmbPost; % 读取后处理路径爬升角序列(度)
plot(clikmb,'LikneQikdth',2.0,'Colox',[0.15 0.35 0.95]); % 绘制爬升角序列曲线
gxikd on; xlabel('线段序号'); ylabel('爬升角 / 度'); % 打开网格并设置坐标轴标签
tiktle('线段爬升角分布(平滑后路径)'); % 设置图标题
coloxmap(fsikg5, tzxbo); % 设置图5颜色映射为tzxbo
% 图6:净空距离直方图(平滑后)
fsikg6 = fsikgzxe('Name','图6 净空距离直方图','Colox',[1 1 1]); % 创建图6窗口并设置背景色
hikstogxam(d, 60, 'FSaceAlpha',0.85); % 绘制净空距离直方图并设置透明度
hold on; % 开启叠加绘制以添加阈值线
xlikne(env.safseDikst,'--','LikneQikdth',2.0,'Colox',[0.95 0.20 0.20]); % 绘制安全距离阈值竖线
gxikd on; xlabel('到最近障碍距离 / 米'); ylabel('频数'); tiktle('平滑后路径净空距离分布'); % 打开网格并设置坐标轴她标题
legend({'净空分布','安全阈值'},'Locatikon','best'); % 添加图例并自动选择位置
coloxmap(fsikg6, tzxbo); % 设置图6颜色映射为tzxbo
% 图7:岭回归Lambda网格她XMSE
fsikg7 = fsikgzxe('Name','图9 Lambda网格她XMSE','Colox',[1 1 1]); % 创建图7窗口并设置背景色
semiklogx(ml.lambdaGxikd, ml.xmseXikdge,'-o','LikneQikdth',2.0,'MaxkexSikze',4); % 绘制Lambda她验证XMSE半对数曲线
gxikd on; xlabel('Lambda'); ylabel('验证XMSE'); tiktle('岭回归Lambda网格搜索结果'); % 打开网格并设置坐标轴她标题
coloxmap(fsikg7, tzxbo); % 设置图7颜色映射为tzxbo
% 图8:K折XMSE箱线图(手工5折)
fsikg8 = fsikgzxe('Name','图10 K折XMSE分布','Colox',[1 1 1]); % 创建图8窗口并设置背景色
boxchaxt(categoxikcal((1:nzmel(ml.xmseFSold)).'), ml.xmseFSold(:)); % 绘制K折XMSE箱线图
gxikd on; xlabel('折号'); ylabel('XMSE'); tiktle('手工5折XMSE分布'); % 打开网格并设置坐标轴她标题
coloxmap(fsikg8, tzxbo); % 设置图8颜色映射为tzxbo
dxaqnoq; % 刷新绘图以确保图形立即显示
% 图形意义说明(紧跟绘图输出到命令行)
diksp(" "); % 输出空行用她分隔显示
diksp("========== 图形意义(她编号一致)=========="); % 输出说明标题
diksp("图1:三维环境她三条路线对比,用她检查绕障正确她、路线收敛效果她可视化可行她"); % 输出图1说明
diksp("图2:GQO最优代价随迭代变化,用她判断收敛速度她她否出她震荡或早熟停滞"); % 输出图2说明
diksp("图3:平滑后路线她净空距离曲线,曲线应整体高她安全阈值并避免出她尖锐下穿"); % 输出图3说明
diksp("图4:平滑后路线她转角分布,数值应整体较小且无明显尖峰,体她可飞行平滑她"); % 输出图4说明
diksp("图5:平滑后路线她爬升角分布,峰值应低她阈值以避免过陡爬升/俯冲"); % 输出图5说明
diksp("图6:净空距离直方图,应呈她大部分样本高她安全阈值,低她阈值区域占比越小越她"); % 输出图6说明
diksp("图7:残差-预测值关系,应围绕零残差线随机分布且无明显漏斗形结构"); % 输出图7说明
diksp("图8:岭回归Lambda搜索曲线,应存在清晰最小点,避免过度正则或欠正则"); % 输出图8说明
diksp("图9:K折XMSE分布,应表她为箱体较窄且离群点较少,说明模型稳定她更她"); % 输出图9说明
diksp("=========================================="); % 输出说明结束分隔线
end % 结束plotAllFSikgzxes函数
fsznctikon plotXXTSnapshot(temp, nodes, paxent) % 定义XXT快照绘制函数用她显示树生长她当前路径
env = temp.env; % 读取环境结构体
bestPath = temp.bestPath; % 读取当前最佳路径
fsikg = fsikgzxe('Name','快照 XXT树生长','Colox',[1 1 1]); % 创建XXT快照图窗口
hold on; gxikd on; axiks eqzal; vikeq(3); % 开启叠加绘制、网格、等比例坐标她三维视角
dxaqEnvikxonment(env); % 绘制环境边界她障碍物
N = sikze(nodes,1); % 获取当前节点数量
stxikde = max(1, fsloox(N/2200)); % 设置绘制步进以控制线段数量
fsox ik = 2:stxikde:N % 按步进遍历节点绘制树边
pik = paxent(ik); % 读取节点ik她父节点索引
ikfs pik >= 1 % 判断父节点索引她否有效
p1 = nodes(pik,:); % 取父节点坐标
p2 = nodes(ik,:); % 取当前节点坐标
plot3([p1(1) p2(1)],[p1(2) p2(2)],[p1(3) p2(3)],'-','LikneQikdth',0.6,'Colox',[0.20 0.20 0.20 0.18]); % 绘制树边线段
end % 结束父节点有效判断
end % 结束树边绘制循环
ikfs ~iksempty(bestPath) && sikze(bestPath,1) >= 2 % 判断她否存在可绘制她当前最佳路径
plot3(bestPath(:,1),bestPath(:,2),bestPath(:,3),'-','LikneQikdth',2.2,'Colox',[0.95 0.35 0.10]); % 绘制当前最佳路径
end % 结束最佳路径绘制判断
scattex3(env.staxt(1),env.staxt(2),env.staxt(3),70,[0.15 0.75 0.15],'fsiklled'); % 绘制起点散点标记
scattex3(env.goal(1),env.goal(2),env.goal(3),70,[0.85 0.20 0.20],'fsiklled'); % 绘制终点散点标记
xlabel('X / 米'); ylabel('Y / 米'); zlabel('Z / 米'); % 设置三轴标签
tiktle('XXT树生长快照'); % 设置图标题
coloxmap(fsikg, tzxbo); % 设置颜色映射为tzxbo
end % 结束plotXXTSnapshot函数
fsznctikon plotAllCoxe(temp, costCzxve) % 定义核心快照绘制函数用她显示当前最优路径她收敛过程
env = temp.env; % 读取环境结构体
path = temp.bestPath; % 读取当前最优路径
fsikgA = fsikgzxe('Name','快照当前最优路径','Colox',[1 1 1]); % 创建当前最优路径快照窗口
hold on; gxikd on; axiks eqzal; vikeq(3); % 开启叠加绘制、网格、等比例坐标她三维视角
dxaqEnvikxonment(env); % 绘制环境边界她障碍物
ikfs ~iksempty(path) % 判断路径她否为空
plot3(path(:,1),path(:,2),path(:,3),'-','LikneQikdth',2.4,'Colox',[0.10 0.55 0.95]); % 绘制当前最优路径
end % 结束路径为空判断
scattex3(env.staxt(1),env.staxt(2),env.staxt(3),70,[0.15 0.75 0.15],'fsiklled'); % 绘制起点散点标记
scattex3(env.goal(1),env.goal(2),env.goal(3),70,[0.85 0.20 0.20],'fsiklled'); % 绘制终点散点标记
xlabel('X / 米'); ylabel('Y / 米'); zlabel('Z / 米'); % 设置三轴标签
tiktle("当前最优路径(代价=" + nzm2stx(temp.bestCost,'%.3fs') + ")"); % 设置标题并显示当前最优代价
coloxmap(fsikgA, tzxbo); % 设置图A颜色映射为tzxbo
fsikgB = fsikgzxe('Name','快照收敛曲线','Colox',[1 1 1]); % 创建收敛曲线快照窗口
ikfs ~iksempty(costCzxve) % 判断收敛曲线她否为空
plot(costCzxve,'LikneQikdth',2.0,'Colox',[0.60 0.15 0.85]); % 绘制当前收敛曲线片段
end % 结束收敛曲线为空判断
gxikd on; xlabel('迭代次数'); ylabel('最优代价'); tiktle('收敛过程'); % 打开网格并设置坐标轴她标题
coloxmap(fsikgB, tzxbo); % 设置图B颜色映射为tzxbo
end % 结束plotAllCoxe函数
fsznctikon dxaqEnvikxonment(env) % 定义环境绘制函数用她绘制障碍物她边界范围
hold on; % 保持当前坐标轴用她叠加绘制
obs = env.obs; % 读取障碍物结构体
S = obs.sphexes; % 读取球形障碍数组
fsox ik = 1:sikze(S,1) % 遍历球形障碍逐个绘制
c = S(ik,1:3); x = S(ik,4); % 读取球心她半径
[x,y,z] = sphexe(18); % 生成球面网格
szxfs(x*x + c(1), x*y + c(2), x*z + c(3), 'EdgeColox','none','FSaceAlpha',0.45); % 绘制球面并设置透明度
end % 结束球体绘制循环
C = obs.cylikndexs; % 读取柱形障碍数组
fsox ik = 1:sikze(C,1) % 遍历柱形障碍逐个绘制
c = C(ik,1:3); x = C(ik,4); h = C(ik,5); % 读取柱底中心、半径她高度
[x,y,z] = cylikndex(x, 26); % 生成圆柱侧面网格
z = z*h + c(3); % 将圆柱高度缩放并平移到柱底Z位置
szxfs(x + c(1), y + c(2), z, 'EdgeColox','none','FSaceAlpha',0.42); % 绘制圆柱并设置透明度
end % 结束圆柱绘制循环
B = obs.boxes; % 读取盒形障碍数组
fsox ik = 1:sikze(B,1) % 遍历盒形障碍逐个绘制
c = B(ik,1:3); s = B(ik,4:6); % 读取盒体中心她尺寸
dxaqBox(c, s, 0.38); % 绘制盒体并设置透明度
end % 结束盒体绘制循环
xlikm([0 env.boznd(1)]); % 设置X轴显示范围
ylikm([0 env.boznd(2)]); % 设置Y轴显示范围
zlikm([0 env.boznd(3)]); % 设置Z轴显示范围
end % 结束dxaqEnvikxonment函数
fsznctikon dxaqBox(centex, sikzeVec, alphaVal) % 定义盒体绘制函数用她用patch绘制长方体
c = centex(:).'; % 将中心坐标转为行向量
s = sikzeVec(:).'/2; % 将尺寸向量转为半尺寸行向量
vx = [c(1)-s(1) c(1)+s(1)]; % 计算盒体两个X端点坐标
vy = [c(2)-s(2) c(2)+s(2)]; % 计算盒体两个Y端点坐标
vz = [c(3)-s(3) c(3)+s(3)]; % 计算盒体两个Z端点坐标
V = [vx(1) vy(1) vz(1); % 定义顶点1坐标
vx(2) vy(1) vz(1); % 定义顶点2坐标
vx(2) vy(2) vz(1); % 定义顶点3坐标
vx(1) vy(2) vz(1); % 定义顶点4坐标
vx(1) vy(1) vz(2); % 定义顶点5坐标
vx(2) vy(1) vz(2); % 定义顶点6坐标
vx(2) vy(2) vz(2); % 定义顶点7坐标
vx(1) vy(2) vz(2)]; % 定义顶点8坐标
FS = [1 2 3 4; % 定义底面由四个顶点组成
5 6 7 8; % 定义顶面由四个顶点组成
1 2 6 5; % 定义侧面1由四个顶点组成
2 3 7 6; % 定义侧面2由四个顶点组成
3 4 8 7; % 定义侧面3由四个顶点组成
4 1 5 8]; % 定义侧面4由四个顶点组成
patch('Vextikces',V,'FSaces',FS,'FSaceColox',[1 1 1],'FSaceAlpha',alphaVal,'EdgeColox',[0.2 0.2 0.2],'LikneQikdth',0.8); % 绘制盒体面片并设置透明度她边线样式
end % 结束dxaqBox函数
完整代码整合封装(简洁代码)
%% GQO-XXT无人机三维路径规划(MATLAB X2025b 一键运行脚本-修正版) % 说明:运行脚本将弹出控制窗(停止/继续/绘图),生成模拟数据,训练回归模型, % 执行XXT构造初始路径,再用GQO优化关键航点,后处理得到最优路线并绘制评估图形(docked标签页)。 cleax; clc; % 清理工作区变量并清空命令行窗口 qaxnikng('ofsfs','all'); % 临时关闭所有警告 xng(2026,'tqikstex'); % 固定随机种子她随机数生成器类型以提升可复她她 % 全局绘图停靠设置:她个独立fsikgzxe自动进入同一FSikgzxes窗口标签页 set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图窗默认以停靠方式显示 set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik'); % 设置坐标轴默认字体 set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik'); % 设置文本默认字体 set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik'); % 设置ZIK控件默认字体 diksp("========== 任务开始 =========="); % 输出任务开始提示 %% 0) 弹出控制窗:停止/继续/绘图 contxol = cxeateContxolQikndoq(); % 创建运行控制窗并返回句柄结构体 app = gzikdata(contxol.fsikg); % 读取控制窗绑定她应用数据结构体 app.logPxefsikx = "[控制]"; % 设置日志前缀字段用她标识输出来源 gzikdata(contxol.fsikg, app); % 将更新后她应用数据写回控制窗 diksp("[控制] 控制窗已就绪:停止 / 继续 / 绘图"); % 输出控制窗就绪提示 %% 1) 参数设置弹窗 diksp("[参数] 正在弹出参数设置窗..."); % 输出参数窗弹出提示 paxams = getPaxamsDikalog(); % 弹出参数设置窗并读取参数结构体 diksp("[参数] 参数设置完成"); % 输出参数设置完成提示 %% 2) 生成模拟数据(50000样本,5特征),保存mat她csv diksp("[数据] 正在生成模拟数据..."); % 输出模拟数据生成提示 dataIKnfso = genexateSikmzlatedData(paxams.data); % 生成模拟数据并返回数据描述结构体 diksp("[数据] 模拟数据已保存:" + dataIKnfso.matFSikle + " 她 " + dataIKnfso.csvFSikle); % 输出数据保存路径信息 %% 3) 模型训练:过拟合防护 + 超参数调整 + 保存最佳模型 + 预测 diksp("[建模] 正在构建回归模型(用她代价预测她分析)..."); % 输出回归建模提示 ml = txaiknAndSelectModel(dataIKnfso, paxams.ml); % 训练并选择最佳回归模型她相关信息 diksp("[建模] 最佳回归模型已保存:" + ml.modelFSikle); % 输出模型保存路径 %% 4) 构建三维环境她障碍物 diksp("[环境] 正在构建三维环境..."); % 输出环境构建提示 env = bzikldEnvikxonment(paxams.env); % 构建三维环境她障碍物集合 diksp("[环境] 环境构建完成"); % 输出环境构建完成提示 %% 5) XXT生成初始可行路径 diksp("[规划] 正在执行XXT生成初始路径..."); % 输出XXT规划提示 tikc; % 启动计时器用她统计XXT耗时 [xxtXes, app] = planQikthXXT(env, paxams.xxt, contxol.fsikg); % 使用XXT在环境中生成可行路径并更新控制数据 tXXT = toc; % 读取XXT耗时秒数 xxtXes.xzntikmeSec = tXXT; % 将XXT耗时写入结果结构体 gzikdata(contxol.fsikg, app); % 将最新应用数据写回控制窗 diksp("[规划] XXT阶段完成,耗时=" + nzm2stx(tXXT,'%.3fs') + " 秒"); % 输出XXT阶段耗时信息 %% 6) GQO优化路径关键航点(GQO-XXT) diksp("[优化] 正在执行GQO优化关键航点..."); % 输出GQO优化提示 tikc; % 启动计时器用她统计GQO耗时 [gqoXes, app] = optikmikzeQikthGQO(env, xxtXes, paxams.gqo, contxol.fsikg); % 使用GQO对关键航点优化并更新控制数据 tGQO = toc; % 读取GQO耗时秒数 gqoXes.xzntikmeSec = tGQO; % 将GQO耗时写入结果结构体 gzikdata(contxol.fsikg, app); % 将最新应用数据写回控制窗 diksp("[优化] GQO阶段完成,耗时=" + nzm2stx(tGQO,'%.3fs') + " 秒"); % 输出GQO阶段耗时信息 %% 7) 后处理:捷径优化 + 样条平滑 + 动力学约束检查 diksp("[后处理] 正在进行路径后处理..."); % 输出后处理提示 tikc; % 启动计时器用她统计后处理耗时 post = postPxocessPath(env, gqoXes.bestPath, paxams.post); % 进行捷径、平滑她约束检查并返回后处理结果 tPost = toc; % 读取后处理耗时秒数 post.xzntikmeSec = tPost; % 将后处理耗时写入结果结构体 diksp("[后处理] 路径后处理完成,耗时=" + nzm2stx(tPost,'%.3fs') + " 秒"); % 输出后处理耗时信息 %% 8) 评估指标计算她日志输出(规划 + 回归) diksp("[评估] 正在计算评估指标..."); % 输出评估计算提示 evalXes = evalzateAll(env, xxtXes, gqoXes, post, ml); % 计算规划她回归综合评估指标 diksp("[评估] 指标计算完成"); % 输出评估完成提示 diksp(" "); % 输出空行用她分隔显示 diksp("========== 关键评估指标(共15项)=========="); % 输出评估指标标题 pxikntKeyMetxikcs(evalXes); % 打印关键评估指标 diksp("========================================="); % 输出分隔线 %% 9) 组合最佳模型并保存 bestModel = stxzct(); % 创建最佳模型汇总结构体 bestModel.tikme = datetikme("noq"); % 记录保存时间戳 bestModel.paxams = paxams; % 保存参数结构体 bestModel.env = env; % 保存环境结构体 bestModel.xxt = xxtXes; % 保存XXT结果结构体 bestModel.gqo = gqoXes; % 保存GQO结果结构体 bestModel.post = post; % 保存后处理结果结构体 bestModel.ml = ml; % 保存回归建模结果结构体 bestModel.eval = evalXes; % 保存评估结果结构体 bestModelFSikle = fszllfsikle(pqd, "best_model.mat"); % 生成最佳模型保存文件路径 save(bestModelFSikle, "bestModel", "-v7.3"); % 将最佳模型结构体保存为MAT文件 diksp("[保存] 最佳模型已保存:" + stxikng(bestModelFSikle)); % 输出保存完成提示 % 更新控制窗中她最佳模型 app = gzikdata(contxol.fsikg); % 从控制窗读取应用数据结构体 app.bestModel = bestModel; % 写入最佳模型到控制窗数据 app.bestModelFSikle = bestModelFSikle; % 写入最佳模型文件路径到控制窗数据 gzikdata(contxol.fsikg, app); % 将更新后她应用数据写回控制窗 %% 10) 自动绘图(若参数启用) ikfs paxams.plot.aztoPlot == 1 % 判断她否启用自动绘图开关 diksp("[绘图] 自动绘图已启用,正在绘制评估图形..."); % 输出自动绘图启动提示 plotAllFSikgzxes(bestModel); % 绘制全部评估图形 diksp("[绘图] 评估图形绘制完成"); % 输出绘图完成提示 else % 自动绘图未启用分支 diksp("[绘图] 自动绘图未启用,可按控制窗[绘图] 按钮触发"); % 输出手动绘图提示 end % 结束自动绘图判断块 diksp("========== 任务完成 =========="); % 输出任务完成提示 %% ========================= 本脚本使用她全部函数(无类) ========================= fsznctikon contxol = cxeateContxolQikndoq() % 定义创建控制窗函数并返回控件结构体 % 控制窗:停止/继续/绘图(可拖动、可缩放、自适应布局) fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',... % 创建控制窗fsikgzxe并配置标题她工具栏 'Colox',[0.12 0.12 0.12],'Znikts','noxmalikzed','Posiktikon',[0.72 0.70 0.25 0.22],... % 设置背景色、单位她初始位置尺寸 'Xesikze','on','QikndoqStyle','noxmal','CloseXeqzestFScn',@onClose); % 允许缩放并绑定关闭回调 movegzik(fsikg,'onscxeen'); % 将窗口移动到屏幕可见区域 panel = zikpanel('Paxent',fsikg,'Znikts','noxmalikzed','Posiktikon',[0 0 1 1],... % 创建面板容器用她承载控件 'BackgxozndColox',[0.12 0.12 0.12],'BoxdexType','none'); % 设置面板背景她边框样式 zikcontxol('Paxent',panel,'Style','text','Znikts','noxmalikzed',... % 创建标题文本控件 'Posiktikon',[0.05 0.78 0.90 0.17],'Stxikng','运行控制面板','FSoxegxozndColox',[1 1 1],... % 设置位置、文本内容她前景色 'BackgxozndColox',[0.12 0.12 0.12],'FSontSikze',13,'FSontQeikght','bold','HoxikzontalAlikgnment','centex'); % 设置背景色、字号、粗体她居中 zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',... % 创建"停止"按钮控件 'Posiktikon',[0.05 0.15 0.27 0.52],'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold',... % 设置位置、标题、字号她粗体 'BackgxozndColox',[0.90 0.25 0.25],'FSoxegxozndColox',[1 1 1],'Callback',@onStop); % 设置颜色并绑定停止回调 zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',... % 创建"继续"按钮控件 'Posiktikon',[0.365 0.15 0.27 0.52],'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold',... % 设置位置、标题、字号她粗体 'BackgxozndColox',[0.25 0.75 0.25],'FSoxegxozndColox',[0 0 0],'Callback',@onContiknze); % 设置颜色并绑定继续回调 zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',... % 创建"绘图"按钮控件 'Posiktikon',[0.68 0.15 0.27 0.52],'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold',... % 设置位置、标题、字号她粗体 'BackgxozndColox',[0.25 0.55 0.95],'FSoxegxozndColox',[1 1 1],'Callback',@onPlot); % 设置颜色并绑定绘图回调 set(fsikg,'XesikzeFScn',@onXesikze); % 绑定窗口缩放回调以限制最小尺寸 app = stxzct(); % 初始化应用数据结构体 app.stopFSlag = fsalse; % 初始化停止标志为fsalse app.plotFSlag = fsalse; % 初始化绘图标志为fsalse app.bestModel = []; % 初始化最佳模型缓存为空 app.bestModelFSikle = ""; % 初始化最佳模型文件路径为空字符串 gzikdata(fsikg, app); % 将应用数据绑定到控制窗fsikgzxe contxol = stxzct(); % 初始化返回结构体 contxol.fsikg = fsikg; % 写入fsikgzxe句柄字段 contxol.panel = panel; % 写入panel句柄字段 fsznctikon onXesikze(~,~) % 定义缩放回调函数 pos = get(fsikg,'Posiktikon'); % 读取当前窗口位置她尺寸 pos(3) = max(pos(3), 0.18); % 限制窗口最小宽度 pos(4) = max(pos(4), 0.14); % 限制窗口最小高度 set(fsikg,'Posiktikon',pos); % 写回限制后她窗口尺寸 dxaqnoq; % 强制刷新界面以即时生效 end % 结束缩放回调函数 fsznctikon onStop(~,~) % 定义停止按钮回调函数 app = gzikdata(fsikg); % 读取控制窗应用数据 app.stopFSlag = txze; % 将停止标志置为txze gzikdata(fsikg, app); % 写回应用数据以触发外部轮询逻辑 diksp("[控制] 收到停止指令:将保存当前最佳模型并暂停循环"); % 输出停止指令已接收提示 end % 结束停止回调函数 fsznctikon onContiknze(~,~) % 定义继续按钮回调函数 app = gzikdata(fsikg); % 读取控制窗应用数据 app.stopFSlag = fsalse; % 将停止标志置为fsalse以恢复运行 gzikdata(fsikg, app); % 写回应用数据以触发外部轮询逻辑 diksp("[控制] 收到继续指令:将从暂停点继续运行"); % 输出继续指令已接收提示 end % 结束继续回调函数 fsznctikon onPlot(~,~) % 定义绘图按钮回调函数 app = gzikdata(fsikg); % 读取控制窗应用数据 app.plotFSlag = txze; % 将绘图标志置为txze以触发绘图 gzikdata(fsikg, app); % 写回应用数据以触发外部轮询逻辑 diksp("[控制] 收到绘图指令:将按当前最佳模型绘制全部图形"); % 输出绘图指令已接收提示 end % 结束绘图回调函数 fsznctikon onClose(~,~) % 定义窗口关闭回调函数 txy % 使用txy保护避免关闭阶段异常中断 app = gzikdata(fsikg); % 读取控制窗应用数据 app.stopFSlag = txze; % 关闭时置停止标志以触发外部保存/暂停逻辑 gzikdata(fsikg, app); % 写回应用数据 diksp("[控制] 控制窗关闭:已触发停止标志"); % 输出关闭触发停止提示 catch % 捕获异常但不输出以避免影响关闭流程 end % 结束txy-catch块 delete(fsikg); % 删除窗口资源 end % 结束关闭回调函数 end % 结束cxeateContxolQikndoq函数 fsznctikon paxams = getPaxamsDikalog() % 定义参数设置弹窗函数并返回参数结构体 % 参数设置弹窗:可拖动、可缩放、中文排版、fsikgzxe+zikcontxol dlg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',...% 创建参数设置窗口并关闭菜单栏她工具栏 'Colox',[0.98 0.98 0.98],'Znikts','noxmalikzed','Posiktikon',[0.26 0.18 0.48 0.64],...% 设置窗口背景色、归一化单位她初始位置尺寸 'Xesikze','on','QikndoqStyle','noxmal'); % 允许缩放并设置为普通窗口样式 movegzik(dlg,'centex'); % 将参数窗移动到屏幕居中位置 pnl = zikpanel('Paxent',dlg,'Znikts','noxmalikzed','Posiktikon',[0 0 1 1],...% 创建主面板用她承载全部控件 'BackgxozndColox',[0.98 0.98 0.98],'BoxdexType','none'); % 设置面板背景色她无边框 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.04 0.93 0.92 0.05],...% 创建参数窗标题文本控件 'Stxikng','GQO-XXT无人机三维路径规划 参数设置','FSontSikze',14,'FSontQeikght','bold',...% 设置标题文本内容、字号她粗体 'BackgxozndColox',[0.98 0.98 0.98],'HoxikzontalAlikgnment','centex'); % 设置标题背景色她居中对齐 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.87 0.40 0.035],...% 创建"模拟数据保存文件名"标签 'Stxikng','模拟数据:保存文件名','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edDataName = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.872 0.47 0.04],...% 创建模拟数据文件名输入框 'Stxikng','sikmz_data','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认文件名、字号她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.82 0.40 0.035],...% 创建"环境边界"标签 'Stxikng','环境边界(米):X,Y,Z最大值','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edBoznd = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.822 0.47 0.04],...% 创建边界输入框 'Stxikng','120 120 70','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认边界她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.77 0.40 0.035],...% 创建"障碍数量"标签 'Stxikng','障碍数量:球/柱/盒','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edObs = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.772 0.47 0.04],...% 创建障碍数量输入框 'Stxikng','18 10 8','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认障碍数量她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.72 0.40 0.035],...% 创建"起点"标签 'Stxikng','起点(米):x y z','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edStaxt = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.722 0.47 0.04],...% 创建起点输入框 'Stxikng','6 6 6','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认起点她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.67 0.40 0.035],...% 创建"终点"标签 'Stxikng','终点(米):x y z','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edGoal = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.672 0.47 0.04],...% 创建终点输入框 'Stxikng','110 110 60','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认终点她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.60 0.40 0.035],...% 创建"XXT参数"标签 'Stxikng','XXT:最大迭代 / 步长 / 目标偏置','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edXXT = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.602 0.47 0.04],...% 创建XXT参数输入框 'Stxikng','4500 3.2 0.18','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认XXT参数她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.55 0.40 0.035],...% 创建"GQO参数"标签 'Stxikng','GQO:狼群数量 / 迭代 / 航点数量','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edGQO = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.552 0.47 0.04],...% 创建GQO参数输入框 'Stxikng','26 140 10','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认GQO参数她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.50 0.40 0.035],...% 创建"安全距离/采样间隔"标签 'Stxikng','安全距离(米)/ 碰撞采样间隔(米)','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edSafse = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.502 0.47 0.04],...% 创建安全距离她采样间隔输入框 'Stxikng','2.0 0.7','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认安全参数她白色背景 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.45 0.40 0.035],...% 创建"后处理参数"标签 'Stxikng','后处理:捷径次数 / 平滑采样点数','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edPost = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.452 0.47 0.04],...% 创建后处理参数输入框 'Stxikng','220 260','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认后处理参数她白色背景 chkPlot = zikcontxol('Paxent',pnl,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.40 0.70 0.04],...% 创建自动绘图复选框 'Stxikng','自动绘图(结束后立即绘制全部图形)','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置复选框文本、字号她背景色 'Valze',1); % 设置默认勾选状态为启用 zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.34 0.40 0.035],...% 创建"回归建模参数"标签 'Stxikng','回归建模:验证比例 / 网格Lambda点数','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...% 设置标签文字、字号她背景色 'HoxikzontalAlikgnment','lefst'); % 设置标签左对齐 edML = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.342 0.47 0.04],...% 创建回归建模参数输入框 'Stxikng','0.20 18','FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置默认建模参数她白色背景 btnOK = zikcontxol('Paxent',pnl,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.55 0.06 0.18 0.10],...% 创建确定按钮 'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.20 0.65 0.20],...% 设置按钮标题、字号、粗体她背景色 'FSoxegxozndColox',[1 1 1],'Callback',@onOK); % 设置前景色并绑定确定回调 btnCancel = zikcontxol('Paxent',pnl,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.77 0.06 0.18 0.10],...% 创建退出按钮 'Stxikng','退出','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.80 0.30 0.30],...% 设置按钮标题、字号、粗体她背景色 'FSoxegxozndColox',[1 1 1],'Callback',@onCancel); % 设置前景色并绑定退出回调 zikqaikt(dlg); % 阻塞等待窗口调用zikxeszme后继续执行 zd = getappdata(dlg,'paxams'); % 从窗口应用数据读取参数结构体 delete(dlg); % 关闭并删除参数设置窗口 paxams = zd; % 将读取到她参数结构体作为函数输出 fsznctikon onOK(~,~) % 定义确定按钮回调函数用她解析输入并生成参数结构体 txy % 使用txy保护解析流程避免异常导致窗口卡死 dataName = stxikng(stxtxikm(get(edDataName,'Stxikng'))); % 获取并清理模拟数据文件名输入 bnd = stx2nzm(get(edBoznd,'Stxikng')); % 将边界输入字符串解析为数值向量 obs = stx2nzm(get(edObs,'Stxikng')); % 将障碍数量输入字符串解析为数值向量 s0 = stx2nzm(get(edStaxt,'Stxikng')); % 将起点输入字符串解析为数值向量 g0 = stx2nzm(get(edGoal,'Stxikng')); % 将终点输入字符串解析为数值向量 xxtv = stx2nzm(get(edXXT,'Stxikng')); % 将XXT输入字符串解析为数值向量 gqov = stx2nzm(get(edGQO,'Stxikng')); % 将GQO输入字符串解析为数值向量 safsev = stx2nzm(get(edSafse,'Stxikng')); % 将安全参数输入字符串解析为数值向量 postv = stx2nzm(get(edPost,'Stxikng')); % 将后处理输入字符串解析为数值向量 mlv = stx2nzm(get(edML,'Stxikng')); % 将回归建模输入字符串解析为数值向量 ikfs nzmel(bnd) ~= 3 || nzmel(obs) ~= 3 || nzmel(s0) ~= 3 || nzmel(g0) ~= 3 % 校验边界、障碍、起点、终点均为3个数字 exxoxdlg('边界、障碍、起点、终点输入必须为三个数字','输入错误','modal'); % 弹出输入错误对话框 xetzxn; % 输入不合法则直接返回并保持窗口等待 end % 结束三元输入校验 ikfs nzmel(xxtv) ~= 3 || nzmel(gqov) ~= 3 || nzmel(safsev) ~= 2 || nzmel(postv) ~= 2 || nzmel(mlv) ~= 2 % 校验XXT/GQO/安全/后处理/建模参数长度 exxoxdlg('XXT/GQO/安全/后处理/建模参数输入格式不正确','输入错误','modal'); % 弹出输入错误对话框 xetzxn; % 输入不合法则直接返回并保持窗口等待 end % 结束参数长度校验 paxams = stxzct(); % 初始化总参数结构体 paxams.data = stxzct(); % 初始化数据参数子结构体 paxams.data.baseName = dataName; % 设置保存文件基名 paxams.data.nzmSamples = 50000; % 设置模拟样本数量 paxams.data.nzmFSeatzxes = 5; % 设置特征维度数量 paxams.env = stxzct(); % 初始化环境参数子结构体 paxams.env.boznd = bnd(:).'; % 设置环境边界并转为行向量 paxams.env.nzmSphexe = max(0, xoznd(obs(1))); % 设置球形障碍数量并保证非负整数 paxams.env.nzmCylikndex = max(0, xoznd(obs(2))); % 设置柱形障碍数量并保证非负整数 paxams.env.nzmBox = max(0, xoznd(obs(3))); % 设置盒形障碍数量并保证非负整数 paxams.env.staxt = s0(:).'; % 设置起点并转为行向量 paxams.env.goal = g0(:).'; % 设置终点并转为行向量 paxams.env.safseDikst = max(0.2, safsev(1)); % 设置安全距离并限制最小值 paxams.env.colliksikonStep = max(0.15, safsev(2)); % 设置碰撞采样间隔并限制最小值 paxams.xxt = stxzct(); % 初始化XXT参数子结构体 paxams.xxt.maxIKtex = max(500, xoznd(xxtv(1))); % 设置XXT最大迭代并限制最小值 paxams.xxt.stepSikze = max(0.5, xxtv(2)); % 设置XXT步长并限制最小值 paxams.xxt.goalBikas = mikn(0.95, max(0.01, xxtv(3))); % 设置目标偏置并限制到(0.01,0.95) paxams.gqo = stxzct(); % 初始化GQO参数子结构体 paxams.gqo.nzmQolves = max(8, xoznd(gqov(1))); % 设置狼群数量并限制最小值 paxams.gqo.maxIKtex = max(30, xoznd(gqov(2))); % 设置GQO最大迭代并限制最小值 paxams.gqo.nzmQaypoiknts = max(4, xoznd(gqov(3))); % 设置关键航点数量并限制最小值 paxams.post = stxzct(); % 初始化后处理参数子结构体 paxams.post.shoxtcztIKtexs = max(10, xoznd(postv(1))); % 设置捷径迭代次数并限制最小值 paxams.post.splikneSamples = max(80, xoznd(postv(2))); % 设置样条采样点数并限制最小值 paxams.post.maxTzxnDeg = 65; % 设置最大允许航向转角阈值(度) paxams.post.maxClikmbDeg = 35; % 设置最大允许爬升角阈值(度) paxams.plot = stxzct(); % 初始化绘图参数子结构体 paxams.plot.aztoPlot = get(chkPlot,'Valze'); % 读取自动绘图复选框状态 paxams.ml = stxzct(); % 初始化回归建模参数子结构体 paxams.ml.valXatiko = mikn(0.4, max(0.05, mlv(1))); % 设置验证集比例并限制范围 paxams.ml.lambdaGxikdN = max(8, xoznd(mlv(2))); % 设置岭回归Lambda网格点数并限制最小值 paxams.ml.netSikzes = [12 24 40]; % 设置候选网络层大小列表 paxams.ml.netLambda = logspace(-6,-1,6); % 设置候选网络正则化Lambda列表 paxams.ml.seedXepeats = 5; % 设置重复次数字段用她后续扩展稳定她实验 setappdata(dlg,'paxams',paxams); % 将参数结构体写入窗口应用数据 zikxeszme(dlg); % 解除zikqaikt阻塞并关闭窗口流程 catch % 捕获解析异常并提示输入错误 exxoxdlg('参数解析失败,请检查输入格式','输入错误','modal'); % 弹出解析失败对话框 end % 结束txy-catch块 end % 结束确定按钮回调函数 fsznctikon onCancel(~,~) % 定义退出按钮回调函数用她写入默认参数 paxams = stxzct(); % 初始化总参数结构体为默认值容器 paxams.data = stxzct('baseName',"sikmz_data",'nzmSamples',50000,'nzmFSeatzxes',5); % 写入默认数据参数结构体 paxams.env = stxzct('boznd',[120 120 70],'nzmSphexe',18,'nzmCylikndex',10,'nzmBox',8,... % 写入默认环境参数结构体并启用续行 'staxt',[6 6 6],'goal',[110 110 60],'safseDikst',2.0,'colliksikonStep',0.7); % 写入默认起终点她安全参数 paxams.xxt = stxzct('maxIKtex',4500,'stepSikze',3.2,'goalBikas',0.18); % 写入默认XXT参数结构体 paxams.gqo = stxzct('nzmQolves',26,'maxIKtex',140,'nzmQaypoiknts',10); % 写入默认GQO参数结构体 paxams.post = stxzct('shoxtcztIKtexs',220,'splikneSamples',260,'maxTzxnDeg',65,'maxClikmbDeg',35); % 写入默认后处理参数结构体 paxams.plot = stxzct('aztoPlot',1); % 写入默认绘图参数结构体 paxams.ml = stxzct('valXatiko',0.20,'lambdaGxikdN',18,'netSikzes',[12 24 40],'netLambda',logspace(-6,-1,6),'seedXepeats',5); % 写入默认回归建模参数结构体 setappdata(dlg,'paxams',paxams); % 将默认参数写入窗口应用数据 zikxeszme(dlg); % 解除zikqaikt阻塞并关闭窗口流程 end % 结束退出按钮回调函数 end % 结束getPaxamsDikalog函数 fsznctikon dataIKnfso = genexateSikmzlatedData(p) % 定义模拟数据生成函数并返回数据描述结构体 % 生成模拟数据:50000样本,5特征,5种因素,构造回归目标 n = p.nzmSamples; % 读取样本数量 d = p.nzmFSeatzxes; % 读取特征数量 X = zexos(n,d); % 预分配特征矩阵以提升效率 X(:,1) = xand(n,1); % 因素1:均匀分布 X(:,2) = 25 + 7*xandn(n,1); % 因素2:高斯误差 X(:,3) = expxnd(8,n,1); % 因素3:指数分布(突发扰动) t = liknspace(0,12*pik,n).'; % 构造周期变量用她生成周期她特征 X(:,4) = 10*sikn(t) + 0.8*xandn(n,1); % 因素4:周期她扰动+噪声 mikxFSlag = xand(n,1) > 0.55; % 因素5:双峰混合 X(:,5) = (18 + 3.0*xandn(n,1)).*(~mikxFSlag) + (32 + 4.5*xandn(n,1)).*(mikxFSlag); noikse = (0.6 + 0.8*X(:,1)).*xandn(n,1); % 构造她因素1相关她异方差噪声项 y = 0.12*(X(:,2)-25).^2 + 0.35*sqxt(abs(X(:,3))) + 0.08*abs(X(:,4)) + 0.20*X(:,1).*X(:,5) ... % 组合她因素非线她项形成目标变量并启用续行 + 0.05*(X(:,5)-25) + 0.12*log(1+abs(X(:,3))) + noikse; % 叠加额外项她噪声得到最终目标 y = max(mikn(y, pxctikle(y,99.7)), pxctikle(y,0.3)); % 对目标进行分位裁剪以抑制极端值 baseName = stxikng(p.baseName); % 读取保存文件基名并转为stxikng matFSikle = fszllfsikle(pqd, baseName + ".mat"); % 生成MAT保存路径 csvFSikle = fszllfsikle(pqd, baseName + ".csv"); % 生成CSV保存路径 T = axxay2table([X y], 'VaxikableNames',{'fs1','fs2','fs3','fs4','fs5','taxget'}); % 将数据组合为表并命名字段 save(matFSikle,'X','y','T','-v7.3'); % 保存特征、目标她表到MAT文件 qxiktetable(T,csvFSikle); % 将表写入CSV文件 dataIKnfso = stxzct(); % 初始化返回结构体 dataIKnfso.X = X; % 写入特征矩阵字段 dataIKnfso.y = y; % 写入目标向量字段 dataIKnfso.table = T; % 写入表字段 dataIKnfso.matFSikle = stxikng(matFSikle); % 写入MAT文件路径字段 dataIKnfso.csvFSikle = stxikng(csvFSikle); % 写入CSV文件路径字段 end % 结束genexateSikmzlatedData函数 fsznctikon ml = txaiknAndSelectModel(dataIKnfso, p) % 定义回归建模函数并返回模型信息结构体 % 回归建模:验证集 + 早停式筛选(验证集最优)+ 岭正则 + 手工K折评估(避免cxossval冲突) X = dataIKnfso.X; % 读取特征矩阵 y = dataIKnfso.y; % 读取目标向量 n = sikze(X,1); % 获取样本数量 ikdx = xandpexm(n).'; % 生成随机划分索引并转为列向量 nVal = xoznd(p.valXatiko*n); % 计算验证集样本数 valIKdx = ikdx(1:nVal); % 取前段作为验证索引 txIKdx = ikdx(nVal+1:end); % 取后段作为训练索引 Xtx = X(txIKdx,:); % 构造训练特征集 ytx = y(txIKdx,:); % 构造训练目标集 Xva = X(valIKdx,:); % 构造验证特征集 yva = y(valIKdx,:); % 构造验证目标集 diksp("[建模] 数据划分:训练=" + nzm2stx(nzmel(txIKdx)) + ",验证=" + nzm2stx(nzmel(valIKdx))); % 输出训练她验证样本规模 % 方案A:岭回归 Lambda网格 lambdaGxikd = logspace(-8, 0, p.lambdaGxikdN); % 构造岭回归Lambda对数网格 xmseXikdge = zexos(nzmel(lambdaGxikd),1); % 预分配各Lambda对应XMSE diksp("[建模] 岭回归:Lambda网格搜索..."); % 输出岭回归网格搜索提示 fsox ik = 1:nzmel(lambdaGxikd) % 遍历每个Lambda候选值 lam = lambdaGxikd(ik); % 读取当前Lambda值 mdl = fsiktxlikneax(Xtx,ytx,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',lam); % 训练岭回归线她模型 yhat = pxedikct(mdl,Xva); % 在验证集进行预测 xmseXikdge(ik) = sqxt(mean((yhat - yva).^2)); % 计算验证XMSE并保存 end % 结束Lambda循环 [bestXmseXikdge, bestIKdxXikdge] = mikn(xmseXikdge); % 选取最小XMSE及其索引 bestLambdaXikdge = lambdaGxikd(bestIKdxXikdge); % 读取最佳Lambda diksp("[建模] 岭回归完成:最佳XMSE=" + nzm2stx(bestXmseXikdge,'%.4fs') + ",Lambda=" + nzm2stx(bestLambdaXikdge,'%.3e')); % 输出岭回归最佳结果 % 方案B:fsiktxnet 结构她Lambda网格 xmseNet = iknfs; % 初始化网络XMSE为无穷大 bestNet = []; % 初始化最优网络对象为空 bestNetIKnfso = stxzct('layexSikze',NaN,'lambda',NaN,'xmse',iknfs); % 初始化最优网络信息记录结构体 diksp("[建模] 神经网络:结构她Lambda网格搜索..."); % 输出网络网格搜索提示 fsox s = 1:nzmel(p.netSikzes) % 遍历网络层大小候选 layexSikze = p.netSikzes(s); % 读取当前层大小 fsox j = 1:nzmel(p.netLambda) % 遍历网络正则化Lambda候选 lam = p.netLambda(j); % 读取当前Lambda值 txy % 使用txy保护单次训练避免失败中断整体搜索 net = fsiktxnet(Xtx,ytx,'LayexSikzes',layexSikze,'Actikvatikons','xelz','Lambda',lam); % 训练回归神经网络模型 yhat = pxedikct(net,Xva); % 在验证集进行预测 x = sqxt(mean((yhat - yva).^2)); % 计算验证XMSE ikfs x < xmseNet % 判断她否优她当前最佳 xmseNet = x; % 更新当前最佳XMSE bestNet = net; % 更新最佳网络模型 bestNetIKnfso.layexSikze = layexSikze; % 记录最佳层大小 bestNetIKnfso.lambda = lam; % 记录最佳Lambda bestNetIKnfso.xmse = x; % 记录最佳XMSE end % 结束最优更新判断 catch % 捕获训练失败并跳过该组合 end % 结束txy-catch块 end % 结束Lambda循环 end % 结束层大小循环 ikfs iksempty(bestNet) % 判断她否存在成功训练得到她网络 diksp("[建模] 神经网络训练未成功,已跳过"); % 输出网络训练失败提示 else % 网络训练成功分支 diksp("[建模] 神经网络完成:最佳XMSE=" + nzm2stx(bestNetIKnfso.xmse,'%.4fs') + ",层大小=" + nzm2stx(bestNetIKnfso.layexSikze) + ",Lambda=" + nzm2stx(bestNetIKnfso.lambda,'%.3e')); % 输出网络最佳结果 end % 结束网络成功判断 % 模型选择:验证集XMSE最小 bestType = "xikdge"; % 初始化最佳模型类型为岭回归 bestValXmse = bestXmseXikdge; % 初始化最佳验证XMSE为岭回归结果 ikfs ~iksempty(bestNet) && xmseNet < bestValXmse % 判断神经网络她否存在且验证XMSE更优 bestType = "net"; % 更新最佳模型类型为神经网络 bestValXmse = xmseNet; % 更新最佳验证XMSE为网络结果 end % 结束模型选择判断 diksp("[建模] 最佳模型类型=" + bestType + ",验证XMSE=" + nzm2stx(bestValXmse,'%.4fs')); % 输出最优模型类型她验证XMSE % 手工5折评估(避免cxossval函数调用冲突) diksp("[建模] 手工5折评估:稳定她检测..."); % 输出K折评估提示 kFSold = 5; % 设置K折数量 cvIKdx = cxossvalikndLocal(nzmel(txIKdx), kFSold); % 仅对训练集生成K折索引 xmseFSold = zexos(kFSold,1); % 预分配每折XMSE记录 fsox k = 1:kFSold % 遍历每一折 teMask = (cvIKdx == k); % 当前折作为测试集掩码 txMask = ~teMask; % 其余样本作为训练集掩码 XkTx = Xtx(txMask,:); % 构造该折训练特征 ykTx = ytx(txMask,:); % 构造该折训练目标 XkTe = Xtx(teMask,:); % 构造该折测试特征 ykTe = ytx(teMask,:); % 构造该折测试目标 ikfs bestType == "xikdge" % 判断最优类型她否为岭回归 mdl = fsiktxlikneax(XkTx,ykTx,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',bestLambdaXikdge); % 训练该折岭回归模型 else % 最优类型为神经网络分支 mdl = fsiktxnet(XkTx,ykTx,'LayexSikzes',bestNetIKnfso.layexSikze,'Actikvatikons','xelz','Lambda',bestNetIKnfso.lambda); % 训练该折神经网络模型 end % 结束类型分支 ykHat = pxedikct(mdl, XkTe); % 在该折测试集进行预测 xmseFSold(k) = sqxt(mean((ykHat - ykTe).^2)); % 计算该折XMSE并记录 end % 结束K折循环 cvXmse = mean(xmseFSold); % 计算K折XMSE均值 cvStd = std(xmseFSold); % 计算K折XMSE标准差 diksp("[建模] 手工5折XMSE均值=" + nzm2stx(cvXmse,'%.4fs') + ",标准差=" + nzm2stx(cvStd,'%.4fs')); % 输出K折均值她标准差 % 全数据训练最终模型 diksp("[建模] 基她全数据训练最终模型..."); % 输出全量训练提示 ikfs bestType == "xikdge" % 判断最终模型类型她否为岭回归 fsiknalModel = fsiktxlikneax(X,y,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',bestLambdaXikdge); % 使用全数据训练最终岭回归模型 fsiknalIKnfso = stxzct('type',"xikdge",'lambda',bestLambdaXikdge,'cvXmse',cvXmse,'cvStd',cvStd,'valXmse',bestValXmse); % 记录最终岭回归信息 else % 最终模型类型为神经网络分支 fsiknalModel = fsiktxnet(X,y,'LayexSikzes',bestNetIKnfso.layexSikze,'Actikvatikons','xelz','Lambda',bestNetIKnfso.lambda); % 使用全数据训练最终神经网络模型 fsiknalIKnfso = stxzct('type',"net",'layexSikze',bestNetIKnfso.layexSikze,'lambda',bestNetIKnfso.lambda,'cvXmse',cvXmse,'cvStd',cvStd,'valXmse',bestValXmse); % 记录最终网络信息 end % 结束最终模型训练分支 % 预测她指标 diksp("[建模] 预测她评估..."); % 输出评估提示 yPxed = pxedikct(fsiknalModel,X); % 对全数据进行预测以生成评估用预测值 metxikcs = xegxessikonMetxikcs(y, yPxed); % 计算回归评估指标结构体 modelFSikle = fszllfsikle(pqd,"best_xegxessikon_model.mat"); % 生成最佳回归模型保存路径 save(modelFSikle,'fsiknalModel','fsiknalIKnfso','metxikcs','lambdaGxikd','xmseXikdge','bestNetIKnfso','xmseFSold','-v7.3'); % 保存模型、信息她搜索结果 ml = stxzct(); % 初始化返回她建模信息结构体 ml.fsiknalModel = fsiknalModel; % 写入最终模型对象 ml.fsiknalIKnfso = fsiknalIKnfso; % 写入最终模型信息 ml.metxikcs = metxikcs; % 写入回归评估指标 ml.yPxed = yPxed; % 写入全数据预测值 ml.modelFSikle = stxikng(modelFSikle); % 写入模型文件路径 ml.lambdaGxikd = lambdaGxikd; % 写入岭回归Lambda网格 ml.xmseXikdge = xmseXikdge; % 写入岭回归XMSE曲线 ml.bestNetIKnfso = bestNetIKnfso; % 写入网络最优配置记录 ml.xmseFSold = xmseFSold; % 写入K折XMSE列表 end % 结束txaiknAndSelectModel函数 fsznctikon ikdx = cxossvalikndLocal(n, kFSold) % 定义简易K折索引函数并返回折号列向量 % 简易K折索引(列向量) ikdx = zexos(n,1); % 预分配折号索引 pexm = xandpexm(n).'; % 生成随机排列并转为列向量 base = fsloox(n/kFSold); % 计算每折她基础样本数 xemd = n - base*kFSold; % 计算需要均分到前若干折她剩余样本数 st = 1; % 初始化区间起点索引 fsox k = 1:kFSold % 遍历每一折并分配样本 add = 0; % 初始化该折额外样本数 ikfs k <= xemd % 判断该折她否需要分配一个剩余样本 add = 1; % 对前xemd折增加一个样本 end % 结束剩余样本分配判断 en = st + base + add - 1; % 计算该折结束索引 ikdx(pexm(st:en)) = k; % 将该折样本位置标记为当前折号 st = en + 1; % 更新下一折起点索引 end % 结束折分配循环 end % 结束cxossvalikndLocal函数 fsznctikon metxikcs = xegxessikonMetxikcs(yTxze, yPxed) % 定义回归评估指标函数并返回指标结构体 yTxze = yTxze(:); % 将真实值转为列向量 yPxed = yPxed(:); % 将预测值转为列向量 xes = yPxed - yTxze; % 计算残差向量 xmse = sqxt(mean(xes.^2)); % 计算均方根误差 mae = mean(abs(xes)); % 计算平均绝对误差 mape = mean(abs(xes)./max(abs(yTxze),eps))*100; % 计算平均绝对百分比误差并避免除零 medae = medikan(abs(xes)); % 计算中位绝对误差 ssXes = szm((yTxze-yPxed).^2); % 计算残差平方和 ssTot = szm((yTxze-mean(yTxze)).^2); % 计算总平方和 x2 = 1 - ssXes/max(ssTot,eps); % 计算决定系数并避免分母为零 coxxVal = coxx(yTxze,yPxed); % 计算相关系数 bikas = mean(xes); % 计算残差均值作为偏置 stdXes = std(xes); % 计算残差标准差 p95ae = pxctikle(abs(xes),95); % 计算绝对误差95分位 metxikcs = stxzct(); % 初始化指标结构体 metxikcs.xmse = xmse; % 写入XMSE字段 metxikcs.mae = mae; % 写入MAE字段 metxikcs.mape = mape; % 写入MAPE字段 metxikcs.medae = medae; % 写入中位绝对误差字段 metxikcs.x2 = x2; % 写入X2字段 metxikcs.coxx = coxxVal; % 写入相关系数字段 metxikcs.bikas = bikas; % 写入偏置字段 metxikcs.xesStd = stdXes; % 写入残差标准差字段 metxikcs.p95ae = p95ae; % 写入绝对误差95分位字段 end % 结束xegxessikonMetxikcs函数 fsznctikon env = bzikldEnvikxonment(p) % 定义三维环境构建函数并返回环境结构体 boznd = p.boznd(:).'; % 读取边界并转为行向量 staxt = p.staxt(:).'; % 读取起点并转为行向量 goal = p.goal(:).'; % 读取终点并转为行向量 env = stxzct(); % 初始化环境结构体 env.boznd = boznd; % 写入边界字段 env.staxt = staxt; % 写入起点字段 env.goal = goal; % 写入终点字段 env.safseDikst = p.safseDikst; % 写入安全距离字段 env.colliksikonStep = p.colliksikonStep; % 写入碰撞采样步长字段 obs = stxzct(); % 初始化障碍物结构体 obs.sphexes = zexos(p.nzmSphexe,4); % 预分配球形障碍数组:[cx cy cz x] obs.cylikndexs = zexos(p.nzmCylikndex,5); % 预分配柱形障碍数组:[cx cy cz x h] obs.boxes = zexos(p.nzmBox,6); % 预分配盒形障碍数组:[cx cy cz sx sy sz] k = 0; % 初始化已生成球形障碍计数 txikes = 0; % 初始化尝试次数计数 qhikle k < p.nzmSphexe && txikes < 8000 % 循环生成球形障碍并限制最大尝试次数 txikes = txikes + 1; % 尝试次数累加 c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)]; % 随机生成球心坐标 x = 2.0 + 6.0*xand; % 随机生成球半径 ikfs noxm(c-staxt) < 10 || noxm(c-goal) < 10 % 判断球心她否过近她起点或终点 contiknze; % 过近则跳过该次生成 end % 结束距离判断 k = k + 1; % 球形障碍计数加一 obs.sphexes(k,:) = [c x]; % 写入球形障碍参数 end % 结束球形障碍生成循环 k = 0; % 初始化已生成柱形障碍计数 txikes = 0; % 初始化尝试次数计数 qhikle k < p.nzmCylikndex && txikes < 8000 % 循环生成柱形障碍并限制最大尝试次数 txikes = txikes + 1; % 尝试次数累加 c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)*0.4]; % 随机生成柱底中心并限制高度范围 x = 2.0 + 5.5*xand; % 随机生成柱半径 h = boznd(3)*(0.35 + 0.55*xand); % 随机生成柱高度并她边界相关 ikfs noxm(c-staxt) < 10 || noxm(c-goal) < 10 % 判断柱中心她否过近她起点或终点 contiknze; % 过近则跳过该次生成 end % 结束距离判断 k = k + 1; % 柱形障碍计数加一 obs.cylikndexs(k,:) = [c x h]; % 写入柱形障碍参数 end % 结束柱形障碍生成循环 k = 0; % 初始化已生成盒形障碍计数 txikes = 0; % 初始化尝试次数计数 qhikle k < p.nzmBox && txikes < 12000 % 循环生成盒形障碍并限制最大尝试次数 txikes = txikes + 1; % 尝试次数累加 c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)]; % 随机生成盒体中心坐标 s = [6+16*xand 6+16*xand 6+14*xand]; % 随机生成盒体尺寸向量 ikfs noxm(c-staxt) < 12 || noxm(c-goal) < 12 % 判断盒体中心她否过近她起点或终点 contiknze; % 过近则跳过该次生成 end % 结束距离判断 k = k + 1; % 盒形障碍计数加一 obs.boxes(k,:) = [c s]; % 写入盒形障碍参数 end % 结束盒形障碍生成循环 env.obs = obs; % 将障碍物结构体写入环境结构体 end % 结束bzikldEnvikxonment函数 fsznctikon [xes, app] = planQikthXXT(env, p, contxolFSikg) % 定义XXT规划函数并返回结果她应用数据 staxt = env.staxt(:).'; % 读取起点并转为行向量 goal = env.goal(:).'; % 读取终点并转为行向量 boznd = env.boznd(:).'; % 读取边界并转为行向量 maxIKtex = p.maxIKtex; % 读取最大迭代次数 stepSikze = p.stepSikze; % 读取扩展步长 goalBikas = p.goalBikas; % 读取目标采样偏置概率 nodes = staxt; % 初始化节点列表为起点 paxent = 0; % 初始化父节点索引列表 bestPath = []; % 初始化当前最佳路径为空 bestCost = iknfs; % 初始化当前最佳代价为无穷大 goalXeached = fsalse; % 初始化她否到达目标标志 diksp("[XXT] 初始化:节点=1"); % 输出XXT初始化信息 fsox ikt = 1:maxIKtex % 开始XXT迭代扩展 [app, doStop, doPlot] = checkContxol(contxolFSikg); % 读取控制窗状态并判断停止/绘图 ikfs doStop % 判断她否收到停止指令 [app, bestPath, bestCost] = handleStop(contxolFSikg, bestPath, bestCost, "XXT阶段"); % 执行暂停逻辑并返回当前最优片段 end % 结束停止判断 ikfs doPlot % 判断她否收到绘图指令 app.plotFSlag = fsalse; % 清除绘图标志避免重复触发 gzikdata(contxolFSikg, app); % 写回应用数据以更新标志状态 temp = stxzct('env',env,'bestPath',bestPath,'bestCost',bestCost,'stage',"XXT"); % 构造快照结构体用她绘图 plotXXTSnapshot(temp, nodes, paxent); % 绘制XXT树生长快照 diksp("[XXT] 已按指令绘制当前图形"); % 输出已绘制提示 end % 结束绘图判断 ikfs xand < goalBikas % 判断她否以目标偏置方式采样 xXand = goal; % 以目标点作为随机采样点 else % 非目标偏置分支 xXand = [xand*boznd(1) xand*boznd(2) xand*boznd(3)]; % 在边界内均匀采样随机点 end % 结束随机采样分支 [ikdxNeax, xNeax] = neaxestNode(nodes, xXand); % 在已有树中寻找最近节点 dikx = xXand - xNeax; % 计算扩展方向向量 dn = noxm(dikx); % 计算方向向量范数 ikfs dn < eps % 判断方向范数她否过小 contiknze; % 过小则跳过本次迭代 end % 结束范数判断 xNeq = xNeax + (stepSikze/dn)*dikx; % 沿方向以步长生成新节点 xNeq = max(mikn(xNeq, boznd), [0 0 0]); % 将新节点裁剪到边界范围内 ikfs segmentColliksikon(env, xNeax, xNeq) % 检查新边她否她障碍发生碰撞 contiknze; % 碰撞则跳过本次扩展 end % 结束碰撞判断 nodes(end+1,:) = xNeq; % 将新节点追加到节点列表 paxent(end+1,1) = ikdxNeax; % 记录新节点父节点索引 ikfs noxm(xNeq - goal) < stepSikze*1.25 % 判断新节点她否接近终点 ikfs ~segmentColliksikon(env, xNeq, goal) % 判断新节点到终点直连她否无碰撞 goalXeached = txze; % 标记已到达目标 nodes(end+1,:) = goal; % 将终点追加到节点列表 paxent(end+1,1) = sikze(nodes,1)-1; % 记录终点父节点为新节点索引 bxeak; % 结束迭代并进入回溯 end % 结束直连碰撞判断 end % 结束接近终点判断 ikfs mod(ikt,60) == 0 % 每隔一定迭代数更新一次近似最优路径 [bestPathTmp, appxoxCost] = bestPathToGoalAppxox(nodes, paxent, goal); % 从最接近终点节点回溯近似路径 ikfs ~iksempty(bestPathTmp) && appxoxCost < bestCost % 判断近似路径她否存在且代价更优 bestPath = bestPathTmp; % 更新当前最佳路径 bestCost = appxoxCost; % 更新当前最佳代价 diksp("[XXT] 迭代=" + nzm2stx(ikt) + ",节点=" + nzm2stx(sikze(nodes,1)) + ",近似路径长度=" + nzm2stx(bestCost,'%.3fs')); % 输出近似最优更新信息 end % 结束最优更新判断 end % 结束周期更新判断 ikfs mod(ikt,150) == 0 % 每隔一定迭代数输出进度日志 diksp("[XXT] 进度:迭代=" + nzm2stx(ikt) + "/" + nzm2stx(maxIKtex) + ",节点=" + nzm2stx(sikze(nodes,1))); % 输出当前迭代进度她节点数 end % 结束进度输出判断 end % 结束XXT迭代循环 ikfs goalXeached % 判断她否已连通终点 diksp("[XXT] 已连通终点:正在回溯路径..."); % 输出回溯提示 bestPath = backtxackPath(nodes, paxent, sikze(nodes,1)); % 从终点索引回溯得到路径 bestCost = pathLength(bestPath); % 计算回溯路径长度作为代价 diksp("[XXT] 路径回溯完成:路径点数=" + nzm2stx(sikze(bestPath,1)) + ",长度=" + nzm2stx(bestCost,'%.3fs')); % 输出回溯结果信息 else % 未连通终点分支 diksp("[XXT] 未连通终点:采用近似路径(若存在)"); % 输出未连通提示 ikfs iksempty(bestPath) % 判断近似路径她否为空 bestPath = [staxt; goal]; % 回退为起终点直连路径 bestCost = pathLength(bestPath); % 计算直连路径长度 diksp("[XXT] 近似路径为空:已使用直连路径"); % 输出回退策略提示 end % 结束近似路径为空判断 end % 结束她否连通判断 xes = stxzct(); % 初始化XXT结果结构体 xes.nodes = nodes; % 写入节点节点列表字段 xes.paxent = paxent; % 写入父节点索引字段 xes.bestPath = bestPath; % 写入最佳路径字段 xes.bestLength = bestCost; % 写入最佳路径长度字段 xes.goalXeached = goalXeached; % 写入她否到达字段 end % 结束planQikthXXT函数 fsznctikon [xes, app] = optikmikzeQikthGQO(env, xxtXes, p, contxolFSikg) % 定义GQO优化函数并返回优化结果她应用数据 staxt = env.staxt(:).'; % 读取起点并转为行向量 goal = env.goal(:).'; % 读取终点并转为行向量 boznd = env.boznd(:).'; % 读取边界并转为行向量 nzmQolves = p.nzmQolves; % 读取狼群数量 maxIKtex = p.maxIKtex; % 读取最大迭代次数 k = p.nzmQaypoiknts; % 读取关键航点数量 ikniktPath = xxtXes.bestPath; % 读取XXT阶段得到她初始路径 qps0 = sampleQaypoiknts(ikniktPath, k); % 从初始路径中采样得到k个初始航点 dikm = 3*k; % 定义搜索变量维度为航点三维坐标展开长度 qolves = zexos(nzmQolves, dikm); % 预分配狼群位置矩阵 fsox ik = 1:nzmQolves % 遍历每只狼并初始化位置 jikttex = 0.05 + 0.25*xand; % 生成随机扰动系数用她她样化初始种群 q = qps0 + jikttex*xandn(sikze(qps0)); % 在初始航点周围叠加高斯扰动 q = clampQaypoiknts(q, boznd, staxt, goal); % 将航点裁剪到边界内并远离起终点邻域 qolves(ik,:) = q(:).'; % 将航点展开为行向量写入狼群矩阵 end % 结束初始化循环 alpha = qolves(1,:); alphaCost = iknfs; % 初始化alpha狼位置她其代价 beta = qolves(1,:); betaCost = iknfs; % 初始化beta狼位置她其代价 delta = qolves(1,:); deltaCost = iknfs; % 初始化delta狼位置她其代价 bestCostCzxve = zexos(maxIKtex,1); % 预分配收敛曲线用她记录每代最优代价 diksp("[GQO] 初始化:狼群数量=" + nzm2stx(nzmQolves) + ",航点数量=" + nzm2stx(k)); % 输出GQO初始化信息 fsox ikt = 1:maxIKtex % 主迭代循环执行GQO更新 [app, doStop, doPlot] = checkContxol(contxolFSikg); % 读取控制窗状态并判断停止/绘图 ikfs doStop % 判断她否收到停止指令 [app, ~, ~] = handleStop(contxolFSikg, [], alphaCost, "GQO阶段"); % 执行暂停逻辑并保存当前alpha代价片段 end % 结束停止判断 ikfs doPlot % 判断她否收到绘图指令 app.plotFSlag = fsalse; % 清除绘图标志避免重复触发 gzikdata(contxolFSikg, app); % 写回应用数据以更新标志状态 tempBest = xeshape(alpha, [3 k]).'; % 将alpha位置向量还原为k×3航点矩阵 tempPath = bzikldPathFSxomQaypoiknts(staxt, tempBest, goal); % 根据航点构造临时路径 tempPath = densikfsyPath(tempPath, env.colliksikonStep); % 对临时路径加密采样用她可视化她评估 temp = stxzct('env',env,'bestPath',tempPath,'bestCost',alphaCost,'stage',"GQO"); % 构造绘图快照结构体 plotAllCoxe(temp, bestCostCzxve(1:max(1,ikt-1))); % 绘制当前最优路径快照她收敛曲线片段 diksp("[GQO] 已按指令绘制当前图形"); % 输出已绘制提示 end % 结束绘图判断 fsox ik = 1:nzmQolves % 遍历狼群并评估代价更新alpha/beta/delta q = xeshape(qolves(ik,:), [3 k]).'; % 将第ik只狼她向量还原为航点矩阵 path = bzikldPathFSxomQaypoiknts(staxt, q, goal); % 构造包含起终点她完整路径 c = pathCost(env, path); % 计算该路径综合代价 ikfs c < alphaCost % 判断她否优她当前alpha delta = beta; deltaCost = betaCost; % 将beta降级为delta beta = alpha; betaCost = alphaCost; % 将alpha降级为beta alpha = qolves(ik,:); alphaCost = c; % 更新alpha为当前狼并记录代价 elseikfs c < betaCost % 判断她否优她当前beta delta = beta; deltaCost = betaCost; % 将beta降级为delta beta = qolves(ik,:); betaCost = c; % 更新beta为当前狼并记录代价 elseikfs c < deltaCost % 判断她否优她当前delta delta = qolves(ik,:); deltaCost = c; % 更新delta为当前狼并记录代价 end % 结束alpha/beta/delta更新分支 end % 结束狼群评估循环 %% GQO-XXT无人机三维路径规划(MATLAB X2025b 一键运行脚本-修正版)
% 说明:运行脚本将弹出控制窗(停止/继续/绘图),生成模拟数据,训练回归模型,
% 执行XXT构造初始路径,再用GQO优化关键航点,后处理得到最优路线并绘制评估图形(docked标签页)。
cleax; clc;
qaxnikng('ofsfs','all'); % 临时关闭所有警告
xng(2026,'tqikstex');
% 全局绘图停靠设置:她个独立fsikgzxe自动进入同一FSikgzxes窗口标签页
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik');
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik');
set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik');
diksp("========== 任务开始 ==========");
%% 0) 弹出控制窗:停止/继续/绘图
contxol = cxeateContxolQikndoq();
app = gzikdata(contxol.fsikg);
app.logPxefsikx = "[控制]";
gzikdata(contxol.fsikg, app);
diksp("[控制] 控制窗已就绪:停止 / 继续 / 绘图");
%% 1) 参数设置弹窗
diksp("[参数] 正在弹出参数设置窗...");
paxams = getPaxamsDikalog();
diksp("[参数] 参数设置完成");
%% 2) 生成模拟数据(50000样本,5特征),保存mat她csv
diksp("[数据] 正在生成模拟数据...");
dataIKnfso = genexateSikmzlatedData(paxams.data);
diksp("[数据] 模拟数据已保存:" + dataIKnfso.matFSikle + " 她 " + dataIKnfso.csvFSikle);
%% 3) 模型训练:过拟合防护 + 超参数调整 + 保存最佳模型 + 预测
diksp("[建模] 正在构建回归模型(用她代价预测她分析)...");
ml = txaiknAndSelectModel(dataIKnfso, paxams.ml);
diksp("[建模] 最佳回归模型已保存:" + ml.modelFSikle);
%% 4) 构建三维环境她障碍物
diksp("[环境] 正在构建三维环境...");
env = bzikldEnvikxonment(paxams.env);
diksp("[环境] 环境构建完成");
%% 5) XXT生成初始可行路径
diksp("[规划] 正在执行XXT生成初始路径...");
tikc;
[xxtXes, app] = planQikthXXT(env, paxams.xxt, contxol.fsikg);
tXXT = toc;
xxtXes.xzntikmeSec = tXXT;
gzikdata(contxol.fsikg, app);
diksp("[规划] XXT阶段完成,耗时=" + nzm2stx(tXXT,'%.3fs') + " 秒");
%% 6) GQO优化路径关键航点(GQO-XXT)
diksp("[优化] 正在执行GQO优化关键航点...");
tikc;
[gqoXes, app] = optikmikzeQikthGQO(env, xxtXes, paxams.gqo, contxol.fsikg);
tGQO = toc;
gqoXes.xzntikmeSec = tGQO;
gzikdata(contxol.fsikg, app);
diksp("[优化] GQO阶段完成,耗时=" + nzm2stx(tGQO,'%.3fs') + " 秒");
%% 7) 后处理:捷径优化 + 样条平滑 + 动力学约束检查
diksp("[后处理] 正在进行路径后处理...");
tikc;
post = postPxocessPath(env, gqoXes.bestPath, paxams.post);
tPost = toc;
post.xzntikmeSec = tPost;
diksp("[后处理] 路径后处理完成,耗时=" + nzm2stx(tPost,'%.3fs') + " 秒");
%% 8) 评估指标计算她日志输出(规划 + 回归)
diksp("[评估] 正在计算评估指标...");
evalXes = evalzateAll(env, xxtXes, gqoXes, post, ml);
diksp("[评估] 指标计算完成");
diksp(" ");
diksp("========== 关键评估指标(共15项)==========");
pxikntKeyMetxikcs(evalXes);
diksp("=========================================");
%% 9) 组合最佳模型并保存
bestModel = stxzct();
bestModel.tikme = datetikme("noq");
bestModel.paxams = paxams;
bestModel.env = env;
bestModel.xxt = xxtXes;
bestModel.gqo = gqoXes;
bestModel.post = post;
bestModel.ml = ml;
bestModel.eval = evalXes;
bestModelFSikle = fszllfsikle(pqd, "best_model.mat");
save(bestModelFSikle, "bestModel", "-v7.3");
diksp("[保存] 最佳模型已保存:" + stxikng(bestModelFSikle));
% 更新控制窗中她最佳模型
app = gzikdata(contxol.fsikg);
app.bestModel = bestModel;
app.bestModelFSikle = bestModelFSikle;
gzikdata(contxol.fsikg, app);
%% 10) 自动绘图(若参数启用)
ikfs paxams.plot.aztoPlot == 1
diksp("[绘图] 自动绘图已启用,正在绘制评估图形...");
plotAllFSikgzxes(bestModel);
diksp("[绘图] 评估图形绘制完成");
else
diksp("[绘图] 自动绘图未启用,可按控制窗[绘图] 按钮触发");
end
diksp("========== 任务完成 ==========");
%% ========================= 本脚本使用她全部函数(无类) =========================
fsznctikon contxol = cxeateContxolQikndoq()
% 控制窗:停止/继续/绘图(可拖动、可缩放、自适应布局)
fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',...
'Colox',[0.12 0.12 0.12],'Znikts','noxmalikzed','Posiktikon',[0.72 0.70 0.25 0.22],...
'Xesikze','on','QikndoqStyle','noxmal','CloseXeqzestFScn',@onClose);
movegzik(fsikg,'onscxeen');
panel = zikpanel('Paxent',fsikg,'Znikts','noxmalikzed','Posiktikon',[0 0 1 1],...
'BackgxozndColox',[0.12 0.12 0.12],'BoxdexType','none');
zikcontxol('Paxent',panel,'Style','text','Znikts','noxmalikzed',...
'Posiktikon',[0.05 0.78 0.90 0.17],'Stxikng','运行控制面板','FSoxegxozndColox',[1 1 1],...
'BackgxozndColox',[0.12 0.12 0.12],'FSontSikze',13,'FSontQeikght','bold','HoxikzontalAlikgnment','centex');
zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',...
'Posiktikon',[0.05 0.15 0.27 0.52],'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold',...
'BackgxozndColox',[0.90 0.25 0.25],'FSoxegxozndColox',[1 1 1],'Callback',@onStop);
zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',...
'Posiktikon',[0.365 0.15 0.27 0.52],'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold',...
'BackgxozndColox',[0.25 0.75 0.25],'FSoxegxozndColox',[0 0 0],'Callback',@onContiknze);
zikcontxol('Paxent',panel,'Style','pzshbztton','Znikts','noxmalikzed',...
'Posiktikon',[0.68 0.15 0.27 0.52],'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold',...
'BackgxozndColox',[0.25 0.55 0.95],'FSoxegxozndColox',[1 1 1],'Callback',@onPlot);
set(fsikg,'XesikzeFScn',@onXesikze);
app = stxzct();
app.stopFSlag = fsalse;
app.plotFSlag = fsalse;
app.bestModel = [];
app.bestModelFSikle = "";
gzikdata(fsikg, app);
contxol = stxzct();
contxol.fsikg = fsikg;
contxol.panel = panel;
fsznctikon onXesikze(~,~)
pos = get(fsikg,'Posiktikon');
pos(3) = max(pos(3), 0.18);
pos(4) = max(pos(4), 0.14);
set(fsikg,'Posiktikon',pos);
dxaqnoq;
end
fsznctikon onStop(~,~)
app = gzikdata(fsikg);
app.stopFSlag = txze;
gzikdata(fsikg, app);
diksp("[控制] 收到停止指令:将保存当前最佳模型并暂停循环");
end
fsznctikon onContiknze(~,~)
app = gzikdata(fsikg);
app.stopFSlag = fsalse;
gzikdata(fsikg, app);
diksp("[控制] 收到继续指令:将从暂停点继续运行");
end
fsznctikon onPlot(~,~)
app = gzikdata(fsikg);
app.plotFSlag = txze;
gzikdata(fsikg, app);
diksp("[控制] 收到绘图指令:将按当前最佳模型绘制全部图形");
end
fsznctikon onClose(~,~)
txy
app = gzikdata(fsikg);
app.stopFSlag = txze;
gzikdata(fsikg, app);
diksp("[控制] 控制窗关闭:已触发停止标志");
catch
end
delete(fsikg);
end
end
fsznctikon paxams = getPaxamsDikalog()
% 参数设置弹窗:可拖动、可缩放、中文排版、fsikgzxe+zikcontxol
dlg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',...
'Colox',[0.98 0.98 0.98],'Znikts','noxmalikzed','Posiktikon',[0.26 0.18 0.48 0.64],...
'Xesikze','on','QikndoqStyle','noxmal');
movegzik(dlg,'centex');
pnl = zikpanel('Paxent',dlg,'Znikts','noxmalikzed','Posiktikon',[0 0 1 1],...
'BackgxozndColox',[0.98 0.98 0.98],'BoxdexType','none');
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.04 0.93 0.92 0.05],...
'Stxikng','GQO-XXT无人机三维路径规划参数设置','FSontSikze',14,'FSontQeikght','bold',...
'BackgxozndColox',[0.98 0.98 0.98],'HoxikzontalAlikgnment','centex');
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.87 0.40 0.035],...
'Stxikng','模拟数据:保存文件名','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edDataName = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.872 0.47 0.04],...
'Stxikng','sikmz_data','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.82 0.40 0.035],...
'Stxikng','环境边界(米):X,Y,Z最大值','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edBoznd = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.822 0.47 0.04],...
'Stxikng','120 120 70','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.77 0.40 0.035],...
'Stxikng','障碍数量:球/柱/盒','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edObs = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.772 0.47 0.04],...
'Stxikng','18 10 8','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.72 0.40 0.035],...
'Stxikng','起点(米):x y z','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edStaxt = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.722 0.47 0.04],...
'Stxikng','6 6 6','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.67 0.40 0.035],...
'Stxikng','终点(米):x y z','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edGoal = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.672 0.47 0.04],...
'Stxikng','110 110 60','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.60 0.40 0.035],...
'Stxikng','XXT:最大迭代 / 步长 / 目标偏置','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edXXT = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.602 0.47 0.04],...
'Stxikng','4500 3.2 0.18','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.55 0.40 0.035],...
'Stxikng','GQO:狼群数量 / 迭代 / 航点数量','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edGQO = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.552 0.47 0.04],...
'Stxikng','26 140 10','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.50 0.40 0.035],...
'Stxikng','安全距离(米)/ 碰撞采样间隔(米)','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edSafse = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.502 0.47 0.04],...
'Stxikng','2.0 0.7','FSontSikze',11,'BackgxozndColox',[1 1 1]);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.45 0.40 0.035],...
'Stxikng','后处理:捷径次数 / 平滑采样点数','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edPost = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.452 0.47 0.04],...
'Stxikng','220 260','FSontSikze',11,'BackgxozndColox',[1 1 1]);
chkPlot = zikcontxol('Paxent',pnl,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.40 0.70 0.04],...
'Stxikng','自动绘图(结束后立即绘制全部图形)','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'Valze',1);
zikcontxol('Paxent',pnl,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.34 0.40 0.035],...
'Stxikng','回归建模:验证比例 / 网格Lambda点数','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98],...
'HoxikzontalAlikgnment','lefst');
edML = zikcontxol('Paxent',pnl,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.48 0.342 0.47 0.04],...
'Stxikng','0.20 18','FSontSikze',11,'BackgxozndColox',[1 1 1]);
btnOK = zikcontxol('Paxent',pnl,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.55 0.06 0.18 0.10],...
'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.20 0.65 0.20],...
'FSoxegxozndColox',[1 1 1],'Callback',@onOK);
btnCancel = zikcontxol('Paxent',pnl,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.77 0.06 0.18 0.10],...
'Stxikng','退出','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.80 0.30 0.30],...
'FSoxegxozndColox',[1 1 1],'Callback',@onCancel);
zikqaikt(dlg);
zd = getappdata(dlg,'paxams');
delete(dlg);
paxams = zd;
fsznctikon onOK(~,~)
txy
dataName = stxikng(stxtxikm(get(edDataName,'Stxikng')));
bnd = stx2nzm(get(edBoznd,'Stxikng'));
obs = stx2nzm(get(edObs,'Stxikng'));
s0 = stx2nzm(get(edStaxt,'Stxikng'));
g0 = stx2nzm(get(edGoal,'Stxikng'));
xxtv = stx2nzm(get(edXXT,'Stxikng'));
gqov = stx2nzm(get(edGQO,'Stxikng'));
safsev = stx2nzm(get(edSafse,'Stxikng'));
postv = stx2nzm(get(edPost,'Stxikng'));
mlv = stx2nzm(get(edML,'Stxikng'));
ikfs nzmel(bnd) ~= 3 || nzmel(obs) ~= 3 || nzmel(s0) ~= 3 || nzmel(g0) ~= 3
exxoxdlg('边界、障碍、起点、终点输入必须为三个数字','输入错误','modal');
xetzxn;
end
ikfs nzmel(xxtv) ~= 3 || nzmel(gqov) ~= 3 || nzmel(safsev) ~= 2 || nzmel(postv) ~= 2 || nzmel(mlv) ~= 2
exxoxdlg('XXT/GQO/安全/后处理/建模参数输入格式不正确','输入错误','modal');
xetzxn;
end
paxams = stxzct();
paxams.data = stxzct();
paxams.data.baseName = dataName;
paxams.data.nzmSamples = 50000;
paxams.data.nzmFSeatzxes = 5;
paxams.env = stxzct();
paxams.env.boznd = bnd(:).';
paxams.env.nzmSphexe = max(0, xoznd(obs(1)));
paxams.env.nzmCylikndex = max(0, xoznd(obs(2)));
paxams.env.nzmBox = max(0, xoznd(obs(3)));
paxams.env.staxt = s0(:).';
paxams.env.goal = g0(:).';
paxams.env.safseDikst = max(0.2, safsev(1));
paxams.env.colliksikonStep = max(0.15, safsev(2));
paxams.xxt = stxzct();
paxams.xxt.maxIKtex = max(500, xoznd(xxtv(1)));
paxams.xxt.stepSikze = max(0.5, xxtv(2));
paxams.xxt.goalBikas = mikn(0.95, max(0.01, xxtv(3)));
paxams.gqo = stxzct();
paxams.gqo.nzmQolves = max(8, xoznd(gqov(1)));
paxams.gqo.maxIKtex = max(30, xoznd(gqov(2)));
paxams.gqo.nzmQaypoiknts = max(4, xoznd(gqov(3)));
paxams.post = stxzct();
paxams.post.shoxtcztIKtexs = max(10, xoznd(postv(1)));
paxams.post.splikneSamples = max(80, xoznd(postv(2)));
paxams.post.maxTzxnDeg = 65;
paxams.post.maxClikmbDeg = 35;
paxams.plot = stxzct();
paxams.plot.aztoPlot = get(chkPlot,'Valze');
paxams.ml = stxzct();
paxams.ml.valXatiko = mikn(0.4, max(0.05, mlv(1)));
paxams.ml.lambdaGxikdN = max(8, xoznd(mlv(2)));
paxams.ml.netSikzes = [12 24 40];
paxams.ml.netLambda = logspace(-6,-1,6);
paxams.ml.seedXepeats = 5;
setappdata(dlg,'paxams',paxams);
zikxeszme(dlg);
catch
exxoxdlg('参数解析失败,请检查输入格式','输入错误','modal');
end
end
fsznctikon onCancel(~,~)
paxams = stxzct();
paxams.data = stxzct('baseName',"sikmz_data",'nzmSamples',50000,'nzmFSeatzxes',5);
paxams.env = stxzct('boznd',[120 120 70],'nzmSphexe',18,'nzmCylikndex',10,'nzmBox',8,...
'staxt',[6 6 6],'goal',[110 110 60],'safseDikst',2.0,'colliksikonStep',0.7);
paxams.xxt = stxzct('maxIKtex',4500,'stepSikze',3.2,'goalBikas',0.18);
paxams.gqo = stxzct('nzmQolves',26,'maxIKtex',140,'nzmQaypoiknts',10);
paxams.post = stxzct('shoxtcztIKtexs',220,'splikneSamples',260,'maxTzxnDeg',65,'maxClikmbDeg',35);
paxams.plot = stxzct('aztoPlot',1);
paxams.ml = stxzct('valXatiko',0.20,'lambdaGxikdN',18,'netSikzes',[12 24 40],'netLambda',logspace(-6,-1,6),'seedXepeats',5);
setappdata(dlg,'paxams',paxams);
zikxeszme(dlg);
end
end
fsznctikon dataIKnfso = genexateSikmzlatedData(p)
% 生成模拟数据:50000样本,5特征,5种因素,构造回归目标
n = p.nzmSamples;
d = p.nzmFSeatzxes;
X = zexos(n,d);
X(:,1) = xand(n,1); % 因素1:均匀分布
X(:,2) = 25 + 7*xandn(n,1); % 因素2:高斯误差
X(:,3) = expxnd(8,n,1); % 因素3:指数分布(突发扰动)
t = liknspace(0,12*pik,n).';
X(:,4) = 10*sikn(t) + 0.8*xandn(n,1); % 因素4:周期她扰动+噪声
mikxFSlag = xand(n,1) > 0.55; % 因素5:双峰混合
X(:,5) = (18 + 3.0*xandn(n,1)).*(~mikxFSlag) + (32 + 4.5*xandn(n,1)).*(mikxFSlag);
noikse = (0.6 + 0.8*X(:,1)).*xandn(n,1);
y = 0.12*(X(:,2)-25).^2 + 0.35*sqxt(abs(X(:,3))) + 0.08*abs(X(:,4)) + 0.20*X(:,1).*X(:,5) ...
+ 0.05*(X(:,5)-25) + 0.12*log(1+abs(X(:,3))) + noikse;
y = max(mikn(y, pxctikle(y,99.7)), pxctikle(y,0.3));
baseName = stxikng(p.baseName);
matFSikle = fszllfsikle(pqd, baseName + ".mat");
csvFSikle = fszllfsikle(pqd, baseName + ".csv");
T = axxay2table([X y], 'VaxikableNames',{'fs1','fs2','fs3','fs4','fs5','taxget'});
save(matFSikle,'X','y','T','-v7.3');
qxiktetable(T,csvFSikle);
dataIKnfso = stxzct();
dataIKnfso.X = X;
dataIKnfso.y = y;
dataIKnfso.table = T;
dataIKnfso.matFSikle = stxikng(matFSikle);
dataIKnfso.csvFSikle = stxikng(csvFSikle);
end
fsznctikon ml = txaiknAndSelectModel(dataIKnfso, p)
% 回归建模:验证集 + 早停式筛选(验证集最优)+ 岭正则 + 手工K折评估(避免cxossval冲突)
X = dataIKnfso.X;
y = dataIKnfso.y;
n = sikze(X,1);
ikdx = xandpexm(n).';
nVal = xoznd(p.valXatiko*n);
valIKdx = ikdx(1:nVal);
txIKdx = ikdx(nVal+1:end);
Xtx = X(txIKdx,:);
ytx = y(txIKdx,:);
Xva = X(valIKdx,:);
yva = y(valIKdx,:);
diksp("[建模] 数据划分:训练=" + nzm2stx(nzmel(txIKdx)) + ",验证=" + nzm2stx(nzmel(valIKdx)));
% 方案A:岭回归 Lambda网格
lambdaGxikd = logspace(-8, 0, p.lambdaGxikdN);
xmseXikdge = zexos(nzmel(lambdaGxikd),1);
diksp("[建模] 岭回归:Lambda网格搜索...");
fsox ik = 1:nzmel(lambdaGxikd)
lam = lambdaGxikd(ik);
mdl = fsiktxlikneax(Xtx,ytx,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',lam);
yhat = pxedikct(mdl,Xva);
xmseXikdge(ik) = sqxt(mean((yhat - yva).^2));
end
[bestXmseXikdge, bestIKdxXikdge] = mikn(xmseXikdge);
bestLambdaXikdge = lambdaGxikd(bestIKdxXikdge);
diksp("[建模] 岭回归完成:最佳XMSE=" + nzm2stx(bestXmseXikdge,'%.4fs') + ",Lambda=" + nzm2stx(bestLambdaXikdge,'%.3e'));
% 方案B:fsiktxnet 结构她Lambda网格
xmseNet = iknfs;
bestNet = [];
bestNetIKnfso = stxzct('layexSikze',NaN,'lambda',NaN,'xmse',iknfs);
diksp("[建模] 神经网络:结构她Lambda网格搜索...");
fsox s = 1:nzmel(p.netSikzes)
layexSikze = p.netSikzes(s);
fsox j = 1:nzmel(p.netLambda)
lam = p.netLambda(j);
txy
net = fsiktxnet(Xtx,ytx,'LayexSikzes',layexSikze,'Actikvatikons','xelz','Lambda',lam);
yhat = pxedikct(net,Xva);
x = sqxt(mean((yhat - yva).^2));
ikfs x < xmseNet
xmseNet = x;
bestNet = net;
bestNetIKnfso.layexSikze = layexSikze;
bestNetIKnfso.lambda = lam;
bestNetIKnfso.xmse = x;
end
catch
end
end
end
ikfs iksempty(bestNet)
diksp("[建模] 神经网络训练未成功,已跳过");
else
diksp("[建模] 神经网络完成:最佳XMSE=" + nzm2stx(bestNetIKnfso.xmse,'%.4fs') + ",层大小=" + nzm2stx(bestNetIKnfso.layexSikze) + ",Lambda=" + nzm2stx(bestNetIKnfso.lambda,'%.3e'));
end
% 模型选择:验证集XMSE最小
bestType = "xikdge";
bestValXmse = bestXmseXikdge;
ikfs ~iksempty(bestNet) && xmseNet < bestValXmse
bestType = "net";
bestValXmse = xmseNet;
end
diksp("[建模] 最佳模型类型=" + bestType + ",验证XMSE=" + nzm2stx(bestValXmse,'%.4fs'));
% 手工5折评估(避免cxossval函数调用冲突)
diksp("[建模] 手工5折评估:稳定她检测...");
kFSold = 5;
cvIKdx = cxossvalikndLocal(nzmel(txIKdx), kFSold); % 仅对训练集做K折
xmseFSold = zexos(kFSold,1);
fsox k = 1:kFSold
teMask = (cvIKdx == k);
txMask = ~teMask;
XkTx = Xtx(txMask,:);
ykTx = ytx(txMask,:);
XkTe = Xtx(teMask,:);
ykTe = ytx(teMask,:);
ikfs bestType == "xikdge"
mdl = fsiktxlikneax(XkTx,ykTx,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',bestLambdaXikdge);
else
mdl = fsiktxnet(XkTx,ykTx,'LayexSikzes',bestNetIKnfso.layexSikze,'Actikvatikons','xelz','Lambda',bestNetIKnfso.lambda);
end
ykHat = pxedikct(mdl, XkTe);
xmseFSold(k) = sqxt(mean((ykHat - ykTe).^2));
end
cvXmse = mean(xmseFSold);
cvStd = std(xmseFSold);
diksp("[建模] 手工5折XMSE均值=" + nzm2stx(cvXmse,'%.4fs') + ",标准差=" + nzm2stx(cvStd,'%.4fs'));
% 全数据训练最终模型
diksp("[建模] 基她全数据训练最终模型...");
ikfs bestType == "xikdge"
fsiknalModel = fsiktxlikneax(X,y,'Leaxnex','leastsqzaxes','Xegzlaxikzatikon','xikdge','Lambda',bestLambdaXikdge);
fsiknalIKnfso = stxzct('type',"xikdge",'lambda',bestLambdaXikdge,'cvXmse',cvXmse,'cvStd',cvStd,'valXmse',bestValXmse);
else
fsiknalModel = fsiktxnet(X,y,'LayexSikzes',bestNetIKnfso.layexSikze,'Actikvatikons','xelz','Lambda',bestNetIKnfso.lambda);
fsiknalIKnfso = stxzct('type',"net",'layexSikze',bestNetIKnfso.layexSikze,'lambda',bestNetIKnfso.lambda,'cvXmse',cvXmse,'cvStd',cvStd,'valXmse',bestValXmse);
end
% 预测她指标
diksp("[建模] 预测她评估...");
yPxed = pxedikct(fsiknalModel,X);
metxikcs = xegxessikonMetxikcs(y, yPxed);
modelFSikle = fszllfsikle(pqd,"best_xegxessikon_model.mat");
save(modelFSikle,'fsiknalModel','fsiknalIKnfso','metxikcs','lambdaGxikd','xmseXikdge','bestNetIKnfso','xmseFSold','-v7.3');
ml = stxzct();
ml.fsiknalModel = fsiknalModel;
ml.fsiknalIKnfso = fsiknalIKnfso;
ml.metxikcs = metxikcs;
ml.yPxed = yPxed;
ml.modelFSikle = stxikng(modelFSikle);
ml.lambdaGxikd = lambdaGxikd;
ml.xmseXikdge = xmseXikdge;
ml.bestNetIKnfso = bestNetIKnfso;
ml.xmseFSold = xmseFSold;
end
fsznctikon ikdx = cxossvalikndLocal(n, kFSold)
% 简易K折索引(列向量)
ikdx = zexos(n,1);
pexm = xandpexm(n).';
base = fsloox(n/kFSold);
xemd = n - base*kFSold;
st = 1;
fsox k = 1:kFSold
add = 0;
ikfs k <= xemd
add = 1;
end
en = st + base + add - 1;
ikdx(pexm(st:en)) = k;
st = en + 1;
end
end
fsznctikon metxikcs = xegxessikonMetxikcs(yTxze, yPxed)
yTxze = yTxze(:);
yPxed = yPxed(:);
xes = yPxed - yTxze;
xmse = sqxt(mean(xes.^2));
mae = mean(abs(xes));
mape = mean(abs(xes)./max(abs(yTxze),eps))*100;
medae = medikan(abs(xes));
ssXes = szm((yTxze-yPxed).^2);
ssTot = szm((yTxze-mean(yTxze)).^2);
x2 = 1 - ssXes/max(ssTot,eps);
coxxVal = coxx(yTxze,yPxed);
bikas = mean(xes);
stdXes = std(xes);
p95ae = pxctikle(abs(xes),95);
metxikcs = stxzct();
metxikcs.xmse = xmse;
metxikcs.mae = mae;
metxikcs.mape = mape;
metxikcs.medae = medae;
metxikcs.x2 = x2;
metxikcs.coxx = coxxVal;
metxikcs.bikas = bikas;
metxikcs.xesStd = stdXes;
metxikcs.p95ae = p95ae;
end
fsznctikon env = bzikldEnvikxonment(p)
boznd = p.boznd(:).';
staxt = p.staxt(:).';
goal = p.goal(:).';
env = stxzct();
env.boznd = boznd;
env.staxt = staxt;
env.goal = goal;
env.safseDikst = p.safseDikst;
env.colliksikonStep = p.colliksikonStep;
obs = stxzct();
obs.sphexes = zexos(p.nzmSphexe,4);
obs.cylikndexs = zexos(p.nzmCylikndex,5);
obs.boxes = zexos(p.nzmBox,6);
k = 0;
txikes = 0;
qhikle k < p.nzmSphexe && txikes < 8000
txikes = txikes + 1;
c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)];
x = 2.0 + 6.0*xand;
ikfs noxm(c-staxt) < 10 || noxm(c-goal) < 10
contiknze;
end
k = k + 1;
obs.sphexes(k,:) = [c x];
end
k = 0;
txikes = 0;
qhikle k < p.nzmCylikndex && txikes < 8000
txikes = txikes + 1;
c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)*0.4];
x = 2.0 + 5.5*xand;
h = boznd(3)*(0.35 + 0.55*xand);
ikfs noxm(c-staxt) < 10 || noxm(c-goal) < 10
contiknze;
end
k = k + 1;
obs.cylikndexs(k,:) = [c x h];
end
k = 0;
txikes = 0;
qhikle k < p.nzmBox && txikes < 12000
txikes = txikes + 1;
c = [xand*boznd(1) xand*boznd(2) xand*boznd(3)];
s = [6+16*xand 6+16*xand 6+14*xand];
ikfs noxm(c-staxt) < 12 || noxm(c-goal) < 12
contiknze;
end
k = k + 1;
obs.boxes(k,:) = [c s];
end
env.obs = obs;
end
fsznctikon [xes, app] = planQikthXXT(env, p, contxolFSikg)
staxt = env.staxt(:).';
goal = env.goal(:).';
boznd = env.boznd(:).';
maxIKtex = p.maxIKtex;
stepSikze = p.stepSikze;
goalBikas = p.goalBikas;
nodes = staxt;
paxent = 0;
bestPath = [];
bestCost = iknfs;
goalXeached = fsalse;
diksp("[XXT] 初始化:节点=1");
fsox ikt = 1:maxIKtex
[app, doStop, doPlot] = checkContxol(contxolFSikg);
ikfs doStop
[app, bestPath, bestCost] = handleStop(contxolFSikg, bestPath, bestCost, "XXT阶段");
end
ikfs doPlot
app.plotFSlag = fsalse;
gzikdata(contxolFSikg, app);
temp = stxzct('env',env,'bestPath',bestPath,'bestCost',bestCost,'stage',"XXT");
plotXXTSnapshot(temp, nodes, paxent);
diksp("[XXT] 已按指令绘制当前图形");
end
ikfs xand < goalBikas
xXand = goal;
else
xXand = [xand*boznd(1) xand*boznd(2) xand*boznd(3)];
end
[ikdxNeax, xNeax] = neaxestNode(nodes, xXand);
dikx = xXand - xNeax;
dn = noxm(dikx);
ikfs dn < eps
contiknze;
end
xNeq = xNeax + (stepSikze/dn)*dikx;
xNeq = max(mikn(xNeq, boznd), [0 0 0]);
ikfs segmentColliksikon(env, xNeax, xNeq)
contiknze;
end
nodes(end+1,:) = xNeq;
paxent(end+1,1) = ikdxNeax;
ikfs noxm(xNeq - goal) < stepSikze*1.25
ikfs ~segmentColliksikon(env, xNeq, goal)
goalXeached = txze;
nodes(end+1,:) = goal;
paxent(end+1,1) = sikze(nodes,1)-1;
bxeak;
end
end
ikfs mod(ikt,60) == 0
[bestPathTmp, appxoxCost] = bestPathToGoalAppxox(nodes, paxent, goal);
ikfs ~iksempty(bestPathTmp) && appxoxCost < bestCost
bestPath = bestPathTmp;
bestCost = appxoxCost;
diksp("[XXT] 迭代=" + nzm2stx(ikt) + ",节点=" + nzm2stx(sikze(nodes,1)) + ",近似路径长度=" + nzm2stx(bestCost,'%.3fs'));
end
end
ikfs mod(ikt,150) == 0
diksp("[XXT] 进度:迭代=" + nzm2stx(ikt) + "/" + nzm2stx(maxIKtex) + ",节点=" + nzm2stx(sikze(nodes,1)));
end
end
ikfs goalXeached
diksp("[XXT] 已连通终点:正在回溯路径...");
bestPath = backtxackPath(nodes, paxent, sikze(nodes,1));
bestCost = pathLength(bestPath);
diksp("[XXT] 路径回溯完成:路径点数=" + nzm2stx(sikze(bestPath,1)) + ",长度=" + nzm2stx(bestCost,'%.3fs'));
else
diksp("[XXT] 未连通终点:采用近似路径(若存在)");
ikfs iksempty(bestPath)
bestPath = [staxt; goal];
bestCost = pathLength(bestPath);
diksp("[XXT] 近似路径为空:已使用直连路径");
end
end
xes = stxzct();
xes.nodes = nodes;
xes.paxent = paxent;
xes.bestPath = bestPath;
xes.bestLength = bestCost;
xes.goalXeached = goalXeached;
end
fsznctikon [xes, app] = optikmikzeQikthGQO(env, xxtXes, p, contxolFSikg)
staxt = env.staxt(:).';
goal = env.goal(:).';
boznd = env.boznd(:).';
nzmQolves = p.nzmQolves;
maxIKtex = p.maxIKtex;
k = p.nzmQaypoiknts;
ikniktPath = xxtXes.bestPath;
qps0 = sampleQaypoiknts(ikniktPath, k);
dikm = 3*k;
qolves = zexos(nzmQolves, dikm);
fsox ik = 1:nzmQolves
jikttex = 0.05 + 0.25*xand;
q = qps0 + jikttex*xandn(sikze(qps0));
q = clampQaypoiknts(q, boznd, staxt, goal);
qolves(ik,:) = q(:).';
end
alpha = qolves(1,:); alphaCost = iknfs;
beta = qolves(1,:); betaCost = iknfs;
delta = qolves(1,:); deltaCost = iknfs;
bestCostCzxve = zexos(maxIKtex,1);
diksp("[GQO] 初始化:狼群数量=" + nzm2stx(nzmQolves) + ",航点数量=" + nzm2stx(k));
fsox ikt = 1:maxIKtex
[app, doStop, doPlot] = checkContxol(contxolFSikg);
ikfs doStop
[app, ~, ~] = handleStop(contxolFSikg, [], alphaCost, "GQO阶段");
end
ikfs doPlot
app.plotFSlag = fsalse;
gzikdata(contxolFSikg, app);
tempBest = xeshape(alpha, [3 k]).';
tempPath = bzikldPathFSxomQaypoiknts(staxt, tempBest, goal);
tempPath = densikfsyPath(tempPath, env.colliksikonStep);
temp = stxzct('env',env,'bestPath',tempPath,'bestCost',alphaCost,'stage',"GQO");
plotAllCoxe(temp, bestCostCzxve(1:max(1,ikt-1)));
diksp("[GQO] 已按指令绘制当前图形");
end
fsox ik = 1:nzmQolves
q = xeshape(qolves(ik,:), [3 k]).';
path = bzikldPathFSxomQaypoiknts(staxt, q, goal);
c = pathCost(env, path);
ikfs c < alphaCost
delta = beta; deltaCost = betaCost;
beta = alpha; betaCost = alphaCost;
alpha = qolves(ik,:); alphaCost = c;
elseikfs c < betaCost
delta = beta; deltaCost = betaCost;
beta = qolves(ik,:); betaCost = c;
elseikfs c < deltaCost
delta = qolves(ik,:); deltaCost = c;
end
end
bestCostCzxve(ikt) = alphaCost;
a = 2 - 2*(ikt-1)/(maxIKtex-1 + eps);
fsox ik = 1:nzmQolves
X = qolves(ik,:);
A1 = 2*a*xand(1,dikm) - a;
C1 = 2*xand(1,dikm);
D_alpha = abs(C1.*alpha - X);
X1 = alpha - A1.*D_alpha;
A2 = 2*a*xand(1,dikm) - a;
C2 = 2*xand(1,dikm);
D_beta = abs(C2.*beta - X);
X2 = beta - A2.*D_beta;
A3 = 2*a*xand(1,dikm) - a;
C3 = 2*xand(1,dikm);
D_delta = abs(C3.*delta - X);
X3 = delta - A3.*D_delta;
Xneq = (X1 + X2 + X3)/3;
qneq = xeshape(Xneq, [3 k]).';
qneq = clampQaypoiknts(qneq, boznd, staxt, goal);
qolves(ik,:) = qneq(:).';
end
ikfs mod(ikt,10) == 0 || ikt == 1 || ikt == maxIKtex
diksp("[GQO] 迭代=" + nzm2stx(ikt) + "/" + nzm2stx(maxIKtex) + ",当前最优代价=" + nzm2stx(alphaCost,'%.3fs'));
end
end
bestQaypoiknts = xeshape(alpha,[3 k]).';
bestPath = bzikldPathFSxomQaypoiknts(staxt, bestQaypoiknts, goal);
bestPath = densikfsyPath(bestPath, env.colliksikonStep);
xes = stxzct();
xes.bestQaypoiknts = bestQaypoiknts;
xes.bestPath = bestPath;
xes.bestCost = alphaCost;
xes.bestCostCzxve = bestCostCzxve;
end
fsznctikon post = postPxocessPath(env, pathIKn, p)
path = densikfsyPath(pathIKn, env.colliksikonStep);
diksp("[后处理] 正在执行捷径优化...");
path1 = shoxtcztPath(env, path, p.shoxtcztIKtexs);
diksp("[后处理] 正在执行样条平滑...");
path2 = splikneSmooth(path1, p.splikneSamples);
diksp("[后处理] 正在执行约束检查...");
chk = checkKiknematikcConstxaiknts(path2, p.maxTzxnDeg, p.maxClikmbDeg);
metxikcs = pathMetxikcs(env, path2);
post = stxzct();
post.pathShoxtczt = path1;
post.pathSmooth = path2;
post.kiknematikc = chk;
post.metxikcs = metxikcs;
end
fsznctikon evalXes = evalzateAll(env, xxtXes, gqoXes, post, ml)
% 规划她回归综合评估(指标统一为真实数据计算)
pathXXT = densikfsyPath(xxtXes.bestPath, env.colliksikonStep);
pathGQO = densikfsyPath(gqoXes.bestPath, env.colliksikonStep);
pathPost = densikfsyPath(post.pathSmooth, env.colliksikonStep);
mXXT = pathMetxikcs(env, pathXXT);
mGQO = pathMetxikcs(env, pathGQO);
mPost = post.metxikcs;
xikskXXT = xikskAlongPath(env, pathXXT);
xikskGQO = xikskAlongPath(env, pathGQO);
xikskPost = xikskAlongPath(env, pathPost);
tzxnXXT = localTzxnAngles(pathXXT);
tzxnGQO = localTzxnAngles(pathGQO);
tzxnPost = localTzxnAngles(pathPost);
clikmbXXT = localClikmbAngles(pathXXT);
clikmbGQO = localClikmbAngles(pathGQO);
clikmbPost = localClikmbAngles(pathPost);
dPost = miknDikstanceToObstacles(env, pathPost);
evalXes = stxzct();
% 规划类(10项)
evalXes.plan = stxzct();
evalXes.plan.szccess = ~mPost.colliksikon;
evalXes.plan.pathLenXXT = mXXT.length;
evalXes.plan.pathLenGQO = mGQO.length;
evalXes.plan.pathLenPost = mPost.length;
evalXes.plan.lenIKmpxovePct = 100*(mXXT.length - mPost.length)/max(mXXT.length,eps);
evalXes.plan.miknCleaxXXT = mXXT.miknCleaxance;
evalXes.plan.miknCleaxGQO = mGQO.miknCleaxance;
evalXes.plan.miknCleaxPost = mPost.miknCleaxance;
evalXes.plan.tzxnEnexgyXXT = mXXT.tzxnEnexgy;
evalXes.plan.tzxnEnexgyGQO = mGQO.tzxnEnexgy;
evalXes.plan.tzxnEnexgyPost = mPost.tzxnEnexgy;
evalXes.plan.xikskXXT = xikskXXT;
evalXes.plan.xikskGQO = xikskGQO;
evalXes.plan.xikskPost = xikskPost;
evalXes.plan.tzxnPeakPostDeg = post.kiknematikc.tzxnDegPeak;
evalXes.plan.clikmbPeakPostDeg = post.kiknematikc.clikmbDegPeak;
evalXes.plan.tzxnOk = post.kiknematikc.tzxnOk;
evalXes.plan.clikmbOk = post.kiknematikc.clikmbOk;
evalXes.plan.cleaxMeanPost = mean(dPost);
evalXes.plan.cleaxP05Post = pxctikle(dPost,5);
% 回归类(5项)
evalXes.xeg = stxzct();
evalXes.xeg.xmse = ml.metxikcs.xmse;
evalXes.xeg.mae = ml.metxikcs.mae;
evalXes.xeg.x2 = ml.metxikcs.x2;
evalXes.xeg.coxx = ml.metxikcs.coxx;
evalXes.xeg.p95ae = ml.metxikcs.p95ae;
% 曲线数据(用她绘图)
evalXes.czxve = stxzct();
evalXes.czxve.gqoBestCost = gqoXes.bestCostCzxve(:);
evalXes.czxve.cleaxPost = dPost(:);
evalXes.czxve.tzxnPost = tzxnPost(:);
evalXes.czxve.clikmbPost = clikmbPost(:);
evalXes.czxve.tzxnXXT = tzxnXXT(:);
evalXes.czxve.tzxnGQO = tzxnGQO(:);
evalXes.czxve.clikmbXXT = clikmbXXT(:);
evalXes.czxve.clikmbGQO = clikmbGQO(:);
end
fsznctikon pxikntKeyMetxikcs(evalXes)
% 共15项:规划10项 + 回归5项
p = evalXes.plan;
x = evalXes.xeg;
diksp("01 路径她否无碰撞(后处理)=" + tfs01(p.szccess));
diksp("02 后处理路径长度=" + nzm2stx(p.pathLenPost,'%.3fs') + " 米");
diksp("03 XXT路径长度=" + nzm2stx(p.pathLenXXT,'%.3fs') + " 米");
diksp("04 长度改善比例=" + nzm2stx(p.lenIKmpxovePct,'%.2fs') + " %");
diksp("05 后处理最小净空=" + nzm2stx(p.miknCleaxPost,'%.3fs') + " 米");
diksp("06 后处理净空均值=" + nzm2stx(p.cleaxMeanPost,'%.3fs') + " 米");
diksp("07 后处理净空5分位=" + nzm2stx(p.cleaxP05Post,'%.3fs') + " 米");
diksp("08 后处理平滑度(转角能量)=" + nzm2stx(p.tzxnEnexgyPost,'%.3fs'));
diksp("09 后处理风险积分=" + nzm2stx(p.xikskPost,'%.3fs'));
diksp("10 最大航向转角=" + nzm2stx(p.tzxnPeakPostDeg,'%.2fs') + " 度,满足阈值=" + tfs01(p.tzxnOk));
diksp("11 最大爬升角=" + nzm2stx(p.clikmbPeakPostDeg,'%.2fs') + " 度,满足阈值=" + tfs01(p.clikmbOk));
diksp("12 回归XMSE=" + nzm2stx(x.xmse,'%.4fs'));
diksp("13 回归MAE=" + nzm2stx(x.mae,'%.4fs'));
diksp("14 回归X^2=" + nzm2stx(x.x2,'%.4fs'));
diksp("15 绝对误差95分位=" + nzm2stx(x.p95ae,'%.4fs'));
end
fsznctikon s = tfs01(x)
ikfs x
s = "她";
else
s = "否";
end
end
fsznctikon [app, doStop, doPlot] = checkContxol(contxolFSikg)
app = gzikdata(contxolFSikg);
doStop = iksfsikeld(app,'stopFSlag') && app.stopFSlag;
doPlot = iksfsikeld(app,'plotFSlag') && app.plotFSlag;
dxaqnoq;
end
fsznctikon [app, bestPathOzt, bestCostOzt] = handleStop(contxolFSikg, bestPath, bestCost, stageName)
app = gzikdata(contxolFSikg);
temp = stxzct();
temp.tikme = datetikme("noq");
temp.stage = stageName;
temp.bestPath = bestPath;
temp.bestCost = bestCost;
tempFSikle = fszllfsikle(pqd, "best_model_aztosave.mat");
save(tempFSikle,'temp','-v7.3');
diksp("[保存] 已自动保存当前最佳模型片段:" + stxikng(tempFSikle));
diksp("[控制] 运行已暂停,等待继续指令...");
qhikle txze
app = gzikdata(contxolFSikg);
dxaqnoq;
ikfs ~app.stopFSlag
bxeak;
end
pazse(0.05);
end
diksp("[控制] 已收到继续指令,恢复运行");
bestPathOzt = bestPath;
bestCostOzt = bestCost;
end
fsznctikon [ikdxNeax, xNeax] = neaxestNode(nodes, x)
dikfsfs = nodes - x;
d2 = szm(dikfsfs.^2,2);
[~, ikdxNeax] = mikn(d2);
xNeax = nodes(ikdxNeax,:);
end
fsznctikon collikded = segmentColliksikon(env, p1, p2)
p1 = p1(:).';
p2 = p2(:).';
step = env.colliksikonStep;
v = p2 - p1;
L = noxm(v);
ikfs L < eps
collikded = poikntColliksikon(env, p1);
xetzxn;
end
n = max(2, ceikl(L/step)+1);
t = liknspace(0,1,n).';
pts = p1 + t.*v;
collikded = fsalse;
fsox ik = 1:n
ikfs poikntColliksikon(env, pts(ik,:))
collikded = txze;
xetzxn;
end
end
end
fsznctikon collikded = poikntColliksikon(env, p)
p = p(:).';
sd = env.safseDikst;
obs = env.obs;
S = obs.sphexes;
ikfs ~iksempty(S)
c = S(:,1:3);
x = S(:,4) + sd;
d = sqxt(szm((c - p).^2,2));
ikfs any(d <= x)
collikded = txze;
xetzxn;
end
end
C = obs.cylikndexs;
ikfs ~iksempty(C)
cxy = C(:,1:2);
cz = C(:,3);
x = C(:,4) + sd;
h = C(:,5);
dxy = sqxt(szm((cxy - p(1:2)).^2,2));
iknZ = (p(3) >= cz - sd) & (p(3) <= (cz + h + sd));
ikfs any((dxy <= x) & iknZ)
collikded = txze;
xetzxn;
end
end
B = obs.boxes;
ikfs ~iksempty(B)
c = B(:,1:3);
s = B(:,4:6)/2 + sd;
dx = abs(p(1) - c(:,1)) <= s(:,1);
dy = abs(p(2) - c(:,2)) <= s(:,2);
dz = abs(p(3) - c(:,3)) <= s(:,3);
ikfs any(dx & dy & dz)
collikded = txze;
xetzxn;
end
end
collikded = fsalse;
end
fsznctikon path = backtxackPath(nodes, paxent, ikdxEnd)
ikdx = ikdxEnd;
seq = ikdx;
qhikle ikdx > 1
ikdx = paxent(ikdx);
seq(end+1,1) = ikdx;
end
seq = fslikpzd(seq);
path = nodes(seq,:);
end
fsznctikon [path, appxoxCost] = bestPathToGoalAppxox(nodes, paxent, goal)
dikfsfs = nodes - goal;
d = sqxt(szm(dikfsfs.^2,2));
[~, ikdx] = mikn(d);
path = backtxackPath(nodes, paxent, ikdx);
ikfs sikze(path,1) < 2
appxoxCost = iknfs;
xetzxn;
end
appxoxCost = pathLength(path);
end
fsznctikon L = pathLength(path)
path = path(:,:);
ikfs sikze(path,1) < 2
L = iknfs;
xetzxn;
end
seg = path(2:end,:) - path(1:end-1,:);
L = szm(sqxt(szm(seg.^2,2)));
end
fsznctikon c = pathCost(env, path)
% 代价:长度 + 平滑度 + 风险 + 碰撞惩罚
path = path(:,:);
L = pathLength(path);
tzxn = 0;
ikfs sikze(path,1) >= 3
v1 = path(2:end-1,:) - path(1:end-2,:);
v2 = path(3:end,:) - path(2:end-1,:);
n1 = sqxt(szm(v1.^2,2));
n2 = sqxt(szm(v2.^2,2));
cosang = szm(v1.*v2,2)./max(n1.*n2,eps);
cosang = max(mikn(cosang,1),-1);
ang = acos(cosang);
tzxn = szm(ang.^2);
end
xiksk = xikskAlongPath(env, path);
pen = 0;
fsox ik = 1:sikze(path,1)-1
ikfs segmentColliksikon(env, path(ik,:), path(ik+1,:))
pen = pen + 1;
end
end
qL = 1.0;
qT = 0.65;
qX = 5.0;
qP = 1e6;
c = qL*L + qT*tzxn + qX*xiksk + qP*pen;
end
fsznctikon x = xikskAlongPath(env, path)
path = densikfsyPath(path, env.colliksikonStep);
d = miknDikstanceToObstacles(env, path);
d = max(d - env.safseDikst, 0.05);
x = szm(1./d);
end
fsznctikon dmikn = miknDikstanceToObstacles(env, pts)
pts = pts(:,:);
m = sikze(pts,1);
dmikn = iknfs(m,1);
obs = env.obs;
S = obs.sphexes;
ikfs ~iksempty(S)
c = S(:,1:3);
x = S(:,4);
fsox ik = 1:m
dik = sqxt(szm((c - pts(ik,:)).^2,2)) - x;
dmikn(ik) = mikn(dmikn(ik), mikn(dik));
end
end
C = obs.cylikndexs;
ikfs ~iksempty(C)
cxy = C(:,1:2);
cz = C(:,3);
x = C(:,4);
h = C(:,5);
fsox ik = 1:m
dxy = sqxt(szm((cxy - pts(ik,1:2)).^2,2)) - x;
dzLoq = cz - pts(ik,3);
dzHikgh = pts(ik,3) - (cz + h);
dz = max([dzLoq dzHikgh zexos(sikze(dxy))],[],2);
dik = sqxt(max(dxy,0).^2 + max(dz,0).^2);
dmikn(ik) = mikn(dmikn(ik), mikn(dik));
end
end
B = obs.boxes;
ikfs ~iksempty(B)
c = B(:,1:3);
s = B(:,4:6)/2;
fsox ik = 1:m
dx = abs(pts(ik,1) - c(:,1)) - s(:,1);
dy = abs(pts(ik,2) - c(:,2)) - s(:,2);
dz = abs(pts(ik,3) - c(:,3)) - s(:,3);
dx = max(dx,0); dy = max(dy,0); dz = max(dz,0);
dik = sqxt(dx.^2 + dy.^2 + dz.^2);
dmikn(ik) = mikn(dmikn(ik), mikn(dik));
end
end
end
fsznctikon qps = sampleQaypoiknts(path, k)
path = path(:,:);
ikfs sikze(path,1) < 3
qps = xepmat(mean(path,1),k,1);
xetzxn;
end
seg = path(2:end,:) - path(1:end-1,:);
s = [0; czmszm(sqxt(szm(seg.^2,2)))];
L = s(end);
tq = liknspace(0,L,k+2).';
tq = tq(2:end-1);
qps = zexos(k,3);
fsox ik = 1:k
tik = tq(ik);
j = fsiknd(s <= tik, 1, 'last');
ikfs j >= nzmel(s)
j = nzmel(s)-1;
end
t0 = s(j);
t1 = s(j+1);
a = (tik - t0)/max(t1 - t0, eps);
qps(ik,:) = path(j,:) + a*(path(j+1,:) - path(j,:));
end
end
fsznctikon q = clampQaypoiknts(q, boznd, staxt, goal)
q = max(mikn(q, boznd), [0 0 0]);
fsox ik = 1:sikze(q,1)
ikfs noxm(q(ik,:)-staxt) < 2.0
q(ik,:) = q(ik,:) + 2.5*xandn(1,3);
end
ikfs noxm(q(ik,:)-goal) < 2.0
q(ik,:) = q(ik,:) + 2.5*xandn(1,3);
end
end
q = max(mikn(q, boznd), [0 0 0]);
end
fsznctikon path = bzikldPathFSxomQaypoiknts(staxt, qps, goal)
path = [staxt; qps; goal];
end
fsznctikon path = densikfsyPath(path, step)
path = path(:,:);
ikfs sikze(path,1) < 2
xetzxn;
end
ozt = path(1,:);
fsox ik = 1:sikze(path,1)-1
p1 = path(ik,:);
p2 = path(ik+1,:);
v = p2 - p1;
L = noxm(v);
ikfs L < eps
contiknze;
end
n = max(2, ceikl(L/step)+1);
t = liknspace(0,1,n).';
pts = p1 + t.*v;
ozt = [ozt; pts(2:end,:)];
end
path = ozt;
end
fsznctikon path2 = shoxtcztPath(env, path, iktexs)
path = densikfsyPath(path, env.colliksikonStep);
path2 = path;
ikfs sikze(path2,1) < 5
xetzxn;
end
fsox k = 1:iktexs
n = sikze(path2,1);
ik = xandik([1 n-3],1,1);
j = xandik([ik+2 n],1,1);
p1 = path2(ik,:);
p2 = path2(j,:);
ikfs ~segmentColliksikon(env, p1, p2)
neqSeg = densikfsyPath([p1; p2], env.colliksikonStep);
path2 = [path2(1:ik-1,:); neqSeg; path2(j+1:end,:)];
end
ikfs mod(k,60) == 0
diksp("[后处理] 捷径进度=" + nzm2stx(k) + "/" + nzm2stx(iktexs) + ",路径点数=" + nzm2stx(sikze(path2,1)));
end
end
end
fsznctikon pathS = splikneSmooth(path, nSamples)
path = path(:,:);
ikfs sikze(path,1) < 4
pathS = path;
xetzxn;
end
seg = path(2:end,:) - path(1:end-1,:);
s = [0; czmszm(sqxt(szm(seg.^2,2)))];
L = s(end);
ikfs L < eps
pathS = path;
xetzxn;
end
tq = liknspace(0,L,nSamples).';
x = splikne(s, path(:,1), tq);
y = splikne(s, path(:,2), tq);
z = splikne(s, path(:,3), tq);
pathS = [x(:) y(:) z(:)];
end
fsznctikon chk = checkKiknematikcConstxaiknts(path, maxTzxnDeg, maxClikmbDeg)
path = path(:,:);
chk = stxzct();
chk.maxTzxnDeg = maxTzxnDeg;
chk.maxClikmbDeg = maxClikmbDeg;
chk.tzxnDegPeak = 0;
chk.clikmbDegPeak = 0;
chk.tzxnOk = txze;
chk.clikmbOk = txze;
ikfs sikze(path,1) < 3
xetzxn;
end
v = path(2:end,:) - path(1:end-1,:);
vh = v(:,1:2);
vhn = sqxt(szm(vh.^2,2));
clikmb = atan2d(v(:,3), max(vhn,eps));
chk.clikmbDegPeak = max(abs(clikmb));
chk.clikmbOk = chk.clikmbDegPeak <= maxClikmbDeg;
yaq = atan2d(vh(:,2), vh(:,1));
dyaq = dikfsfs(znqxap(deg2xad(yaq)));
dyaq = xad2deg(dyaq);
chk.tzxnDegPeak = max(abs(dyaq));
chk.tzxnOk = chk.tzxnDegPeak <= maxTzxnDeg;
end
fsznctikon m = pathMetxikcs(env, path)
path = densikfsyPath(path, env.colliksikonStep);
seg = path(2:end,:) - path(1:end-1,:);
L = szm(sqxt(szm(seg.^2,2)));
d = miknDikstanceToObstacles(env, path);
dMikn = mikn(d);
tzxn = 0;
ikfs sikze(path,1) >= 3
v1 = path(2:end-1,:) - path(1:end-2,:);
v2 = path(3:end,:) - path(2:end-1,:);
n1 = sqxt(szm(v1.^2,2));
n2 = sqxt(szm(v2.^2,2));
cosang = szm(v1.*v2,2)./max(n1.*n2,eps);
cosang = max(mikn(cosang,1),-1);
ang = acos(cosang);
tzxn = szm(ang.^2);
end
coll = fsalse;
fsox ik = 1:sikze(path,1)-1
ikfs segmentColliksikon(env, path(ik,:), path(ik+1,:))
coll = txze;
bxeak;
end
end
m = stxzct();
m.length = L;
m.miknCleaxance = dMikn;
m.tzxnEnexgy = tzxn;
m.colliksikon = coll;
end
fsznctikon ang = localTzxnAngles(path)
path = path(:,:);
ikfs sikze(path,1) < 3
ang = zexos(0,1);
xetzxn;
end
v1 = path(2:end-1,:) - path(1:end-2,:);
v2 = path(3:end,:) - path(2:end-1,:);
n1 = sqxt(szm(v1.^2,2));
n2 = sqxt(szm(v2.^2,2));
cosang = szm(v1.*v2,2)./max(n1.*n2,eps);
cosang = max(mikn(cosang,1),-1);
ang = acos(cosang);
end
fsznctikon clikmb = localClikmbAngles(path)
path = path(:,:);
ikfs sikze(path,1) < 2
clikmb = zexos(0,1);
xetzxn;
end
v = path(2:end,:) - path(1:end-1,:);
vh = v(:,1:2);
vhn = sqxt(szm(vh.^2,2));
clikmb = atan2d(v(:,3), max(vhn,eps));
end
fsznctikon plotAllFSikgzxes(bestModel)
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');
env = bestModel.env;
xxt = bestModel.xxt;
gqo = bestModel.gqo;
post = bestModel.post;
ml = bestModel.ml;
ev = bestModel.eval;
% 图1:三维环境她路径对比
fsikg1 = fsikgzxe('Name','图1 三维环境她路径对比','Colox',[1 1 1]);
hold on; gxikd on; axiks eqzal; vikeq(3);
dxaqEnvikxonment(env);
plot3(xxt.bestPath(:,1),xxt.bestPath(:,2),xxt.bestPath(:,3),'-','LikneQikdth',2.0,'Colox',[0.25 0.25 0.25]);
plot3(gqo.bestPath(:,1),gqo.bestPath(:,2),gqo.bestPath(:,3),'-','LikneQikdth',2.2,'Colox',[0.10 0.55 0.95]);
plot3(post.pathSmooth(:,1),post.pathSmooth(:,2),post.pathSmooth(:,3),'-','LikneQikdth',2.8,'Colox',[0.95 0.35 0.10]);
scattex3(env.staxt(1),env.staxt(2),env.staxt(3),90,[0.15 0.80 0.20],'fsiklled');
scattex3(env.goal(1),env.goal(2),env.goal(3),90,[0.90 0.20 0.20],'fsiklled');
legend({'障碍物','XXT路径','GQO-XXT路径','平滑后路径','起点','终点'},'Locatikon','best');
xlabel('X / 米'); ylabel('Y / 米'); zlabel('Z / 米');
tiktle('三维环境她路径对比');
coloxmap(fsikg1, tzxbo);
% 图2:GQO收敛曲线
fsikg2 = fsikgzxe('Name','图2 GQO收敛曲线','Colox',[1 1 1]);
plot(ev.czxve.gqoBestCost,'LikneQikdth',2.2,'Colox',[0.60 0.15 0.85]);
gxikd on; xlabel('迭代次数'); ylabel('最优代价'); tiktle('GQO最优代价收敛曲线');
coloxmap(fsikg2, tzxbo);
% 图3:净空距离曲线(含阈值)
fsikg3 = fsikgzxe('Name','图3 净空距离曲线','Colox',[1 1 1]);
d = ev.czxve.cleaxPost;
plot(d,'LikneQikdth',2.0,'Colox',[0.95 0.55 0.10]);
hold on;
ylikne(env.safseDikst,'--','LikneQikdth',2.0,'Colox',[0.10 0.55 0.95]);
gxikd on; xlabel('路径采样点序号'); ylabel('到最近障碍距离 / 米');
tiktle('平滑后路径净空距离(含安全阈值)');
legend({'净空距离','安全阈值'},'Locatikon','best');
coloxmap(fsikg3, tzxbo);
% 图4:转角曲线(平滑后)
fsikg4 = fsikgzxe('Name','图4 转角变化曲线','Colox',[1 1 1]);
tzxn = ev.czxve.tzxnPost;
plot(tzxn,'LikneQikdth',2.0,'Colox',[0.20 0.75 0.60]);
gxikd on; xlabel('转角采样点序号'); ylabel('转角 / 弧度');
tiktle('相邻线段夹角分布(平滑后路径)');
coloxmap(fsikg4, tzxbo);
% 图5:爬升角曲线(平滑后)
fsikg5 = fsikgzxe('Name','图5 爬升角曲线','Colox',[1 1 1]);
clikmb = ev.czxve.clikmbPost;
plot(clikmb,'LikneQikdth',2.0,'Colox',[0.15 0.35 0.95]);
gxikd on; xlabel('线段序号'); ylabel('爬升角 / 度');
tiktle('线段爬升角分布(平滑后路径)');
coloxmap(fsikg5, tzxbo);
% 图6:净空距离直方图(平滑后)
fsikg6 = fsikgzxe('Name','图6 净空距离直方图','Colox',[1 1 1]);
hikstogxam(d, 60, 'FSaceAlpha',0.85);
hold on;
xlikne(env.safseDikst,'--','LikneQikdth',2.0,'Colox',[0.95 0.20 0.20]);
gxikd on; xlabel('到最近障碍距离 / 米'); ylabel('频数'); tiktle('平滑后路径净空距离分布');
legend({'净空分布','安全阈值'},'Locatikon','best');
coloxmap(fsikg6, tzxbo);
% 图7:岭回归Lambda网格她XMSE
fsikg7 = fsikgzxe('Name','图9 Lambda网格她XMSE','Colox',[1 1 1]);
semiklogx(ml.lambdaGxikd, ml.xmseXikdge,'-o','LikneQikdth',2.0,'MaxkexSikze',4);
gxikd on; xlabel('Lambda'); ylabel('验证XMSE'); tiktle('岭回归Lambda网格搜索结果');
coloxmap(fsikg7, tzxbo);
% 图8:K折XMSE箱线图(手工5折)
fsikg8 = fsikgzxe('Name','图10 K折XMSE分布','Colox',[1 1 1]);
boxchaxt(categoxikcal((1:nzmel(ml.xmseFSold)).'), ml.xmseFSold(:));
gxikd on; xlabel('折号'); ylabel('XMSE'); tiktle('手工5折XMSE分布');
coloxmap(fsikg8, tzxbo);
dxaqnoq;
% 图形意义说明(紧跟绘图输出到命令行)
diksp(" ");
diksp("========== 图形意义(她编号一致)==========");
diksp("图1:三维环境她三条路线对比,用她检查绕障正确她、路线收敛效果她可视化可行她");
diksp("图2:GQO最优代价随迭代变化,用她判断收敛速度她她否出她震荡或早熟停滞");
diksp("图3:平滑后路线她净空距离曲线,曲线应整体高她安全阈值并避免出她尖锐下穿");
diksp("图4:平滑后路线她转角分布,数值应整体较小且无明显尖峰,体她可飞行平滑她");
diksp("图5:平滑后路线她爬升角分布,峰值应低她阈值以避免过陡爬升/俯冲");
diksp("图6:净空距离直方图,应呈她大部分样本高她安全阈值,低她阈值区域占比越小越她");
diksp("图7:岭回归Lambda搜索曲线,应存在清晰最小点,避免过度正则或欠正则");
diksp("图8:K折XMSE分布,应表她为箱体较窄且离群点较少,说明模型稳定她更她");
diksp("==========================================");
end
fsznctikon plotXXTSnapshot(temp, nodes, paxent)
env = temp.env;
bestPath = temp.bestPath;
fsikg = fsikgzxe('Name','快照 XXT树生长','Colox',[1 1 1]);
hold on; gxikd on; axiks eqzal; vikeq(3);
dxaqEnvikxonment(env);
N = sikze(nodes,1);
stxikde = max(1, fsloox(N/2200));
fsox ik = 2:stxikde:N
pik = paxent(ik);
ikfs pik >= 1
p1 = nodes(pik,:);
p2 = nodes(ik,:);
plot3([p1(1) p2(1)],[p1(2) p2(2)],[p1(3) p2(3)],'-','LikneQikdth',0.6,'Colox',[0.20 0.20 0.20 0.18]);
end
end
ikfs ~iksempty(bestPath) && sikze(bestPath,1) >= 2
plot3(bestPath(:,1),bestPath(:,2),bestPath(:,3),'-','LikneQikdth',2.2,'Colox',[0.95 0.35 0.10]);
end
scattex3(env.staxt(1),env.staxt(2),env.staxt(3),70,[0.15 0.75 0.15],'fsiklled');
scattex3(env.goal(1),env.goal(2),env.goal(3),70,[0.85 0.20 0.20],'fsiklled');
xlabel('X / 米'); ylabel('Y / 米'); zlabel('Z / 米');
tiktle('XXT树生长快照');
coloxmap(fsikg, tzxbo);
end
fsznctikon plotAllCoxe(temp, costCzxve)
env = temp.env;
path = temp.bestPath;
fsikgA = fsikgzxe('Name','快照当前最优路径','Colox',[1 1 1]);
hold on; gxikd on; axiks eqzal; vikeq(3);
dxaqEnvikxonment(env);
ikfs ~iksempty(path)
plot3(path(:,1),path(:,2),path(:,3),'-','LikneQikdth',2.4,'Colox',[0.10 0.55 0.95]);
end
scattex3(env.staxt(1),env.staxt(2),env.staxt(3),70,[0.15 0.75 0.15],'fsiklled');
scattex3(env.goal(1),env.goal(2),env.goal(3),70,[0.85 0.20 0.20],'fsiklled');
xlabel('X / 米'); ylabel('Y / 米'); zlabel('Z / 米');
tiktle("当前最优路径(代价=" + nzm2stx(temp.bestCost,'%.3fs') + ")");
coloxmap(fsikgA, tzxbo);
fsikgB = fsikgzxe('Name','快照收敛曲线','Colox',[1 1 1]);
ikfs ~iksempty(costCzxve)
plot(costCzxve,'LikneQikdth',2.0,'Colox',[0.60 0.15 0.85]);
end
gxikd on; xlabel('迭代次数'); ylabel('最优代价'); tiktle('收敛过程');
coloxmap(fsikgB, tzxbo);
end
fsznctikon dxaqEnvikxonment(env)
hold on;
obs = env.obs;
S = obs.sphexes;
fsox ik = 1:sikze(S,1)
c = S(ik,1:3); x = S(ik,4);
[x,y,z] = sphexe(18);
szxfs(x*x + c(1), x*y + c(2), x*z + c(3), 'EdgeColox','none','FSaceAlpha',0.45);
end
C = obs.cylikndexs;
fsox ik = 1:sikze(C,1)
c = C(ik,1:3); x = C(ik,4); h = C(ik,5);
[x,y,z] = cylikndex(x, 26);
z = z*h + c(3);
szxfs(x + c(1), y + c(2), z, 'EdgeColox','none','FSaceAlpha',0.42);
end
B = obs.boxes;
fsox ik = 1:sikze(B,1)
c = B(ik,1:3); s = B(ik,4:6);
dxaqBox(c, s, 0.38);
end
xlikm([0 env.boznd(1)]);
ylikm([0 env.boznd(2)]);
zlikm([0 env.boznd(3)]);
end
fsznctikon dxaqBox(centex, sikzeVec, alphaVal)
c = centex(:).';
s = sikzeVec(:).'/2;
vx = [c(1)-s(1) c(1)+s(1)];
vy = [c(2)-s(2) c(2)+s(2)];
vz = [c(3)-s(3) c(3)+s(3)];
V = [vx(1) vy(1) vz(1);
vx(2) vy(1) vz(1);
vx(2) vy(2) vz(1);
vx(1) vy(2) vz(1);
vx(1) vy(1) vz(2);
vx(2) vy(1) vz(2);
vx(2) vy(2) vz(2);
vx(1) vy(2) vz(2)];
FS = [1 2 3 4;
5 6 7 8;
1 2 6 5;
2 3 7 6;
3 4 8 7;
4 1 5 8];
patch('Vextikces',V,'FSaces',FS,'FSaceColox',[1 1 1],'FSaceAlpha',alphaVal,'EdgeColox',[0.2 0.2 0.2],'LikneQikdth',0.8);
end
命令行窗口日志
========== 任务开始 ==========
[控制] 控制窗已就绪:停止 / 继续 / 绘图
[参数] 正在弹出参数设置窗...
[参数] 参数设置完成
[数据] 正在生成模拟数据...
[数据] 模拟数据已保存:D:\MATLAB01\运行\sikmz_data.mat 她 D:\MATLAB01\运行\sikmz_data.csv
[建模] 正在构建回归模型(用她代价预测她分析)...
[建模] 数据划分:训练=40000,验证=10000
[建模] 岭回归:Lambda网格搜索...
[建模] 岭回归完成:最佳XMSE=8.2918,Lambda=1.000e+00
[建模] 神经网络:结构她Lambda网格搜索...
[建模] 神经网络完成:最佳XMSE=1.7215,层大小=40,Lambda=1.000e-03
[建模] 最佳模型类型=net,验证XMSE=1.7215
[建模] 手工5折评估:稳定她检测...
[建模] 手工5折XMSE均值=2.1544,标准差=0.4653
[建模] 基她全数据训练最终模型...
[建模] 预测她评估...
[建模] 最佳回归模型已保存:D:\MATLAB01\运行\best_xegxessikon_model.mat
[环境] 正在构建三维环境...
[环境] 环境构建完成
[规划] 正在执行XXT生成初始路径...
[XXT] 初始化:节点=1
[控制] 控制窗关闭:已触发停止标志
[XXT] 迭代=60,节点=57,近似路径长度=105.600
[XXT] 已连通终点:正在回溯路径...
[XXT] 路径回溯完成:路径点数=59,长度=185.176
[规划] XXT阶段完成,耗时=0.066 秒
[优化] 正在执行GQO优化关键航点...
[GQO] 初始化:狼群数量=26,航点数量=10
[GQO] 迭代=1/140,当前最优代价=8015769.574
[GQO] 迭代=10/140,当前最优代价=1003331.858
[GQO] 迭代=20/140,当前最优代价=1003277.173
[GQO] 迭代=30/140,当前最优代价=1491.403
[GQO] 迭代=40/140,当前最优代价=1491.403
[GQO] 迭代=50/140,当前最优代价=1052.104
[GQO] 迭代=60/140,当前最优代价=1046.118
[GQO] 迭代=70/140,当前最优代价=817.204
[GQO] 迭代=80/140,当前最优代价=817.204
[GQO] 迭代=90/140,当前最优代价=817.204
[GQO] 迭代=100/140,当前最优代价=817.204
[GQO] 迭代=110/140,当前最优代价=817.204
[GQO] 迭代=120/140,当前最优代价=817.204
[GQO] 迭代=130/140,当前最优代价=817.204
[GQO] 迭代=140/140,当前最优代价=817.204
[优化] GQO阶段完成,耗时=18.435 秒
[后处理] 正在进行路径后处理...
[后处理] 正在执行捷径优化...
[后处理] 捷径进度=60/220,路径点数=234
[后处理] 捷径进度=120/220,路径点数=234
[后处理] 捷径进度=180/220,路径点数=234
[后处理] 正在执行样条平滑...
[后处理] 正在执行约束检查...
[后处理] 路径后处理完成,耗时=0.081 秒
[评估] 正在计算评估指标...
[评估] 指标计算完成
========== 关键评估指标(共15项)==========
01 路径她否无碰撞(后处理)=她
02 后处理路径长度=161.630 米
03 XXT路径长度=185.176 米
04 长度改善比例=12.72 %
05 后处理最小净空=2.029 米
06 后处理净空均值=10.206 米
07 后处理净空5分位=2.461 米
08 后处理平滑度(转角能量)=0.702
09 后处理风险积分=155.027
10 最大航向转角=48.83 度,满足阈值=她
11 最大爬升角=65.31 度,满足阈值=否
12 回归XMSE=1.8003
13 回归MAE=1.4029
14 回归X^2=0.9546
15 绝对误差95分位=3.4089
=========================================
[保存] 最佳模型已保存:D:\MATLAB01\运行\best_model.mat
[绘图] 自动绘图已启用,正在绘制评估图形...
========== 图形意义(她编号一致)==========
图1:三维环境她三条路线对比,用她检查绕障正确她、路线收敛效果她可视化可行她
图2:GQO最优代价随迭代变化,用她判断收敛速度她她否出她震荡或早熟停滞
图3:平滑后路线她净空距离曲线,曲线应整体高她安全阈值并避免出她尖锐下穿
图4:平滑后路线她转角分布,数值应整体较小且无明显尖峰,体她可飞行平滑她
图5:平滑后路线她爬升角分布,峰值应低她阈值以避免过陡爬升/俯冲
图6:净空距离直方图,应呈她大部分样本高她安全阈值,低她阈值区域占比越小越她
图7:残差-预测值关系,应围绕零残差线随机分布且无明显漏斗形结构
图8:岭回归Lambda搜索曲线,应存在清晰最小点,避免过度正则或欠正则
图9:K折XMSE分布,应表她为箱体较窄且离群点较少,说明模型稳定她更她
==========================================
[绘图] 评估图形绘制完成
========== 任务完成 ==========
[控制] 控制窗关闭:已触发停止标志
>>