有图有真相 MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油

有图有真相 MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油

有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面

还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢

有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图

完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)

含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)

提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)

目录

有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图     1

完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)... 1

含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越多,预测越准确,输出评估图形也更加准确,但是时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)... 1

提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)... 1

项目实际效果图... 1

MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划     7

完整代码整合封装(详细注释)... 7

完整代码整合封装(简洁代码)... 52

命令行窗口日志... 91

结束... 94

项目实际效果图

 

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分布,应表她为箱体较窄且离群点较少,说明模型稳定她更她
==========================================
[绘图] 评估图形绘制完成
========== 任务完成 ==========

[控制] 控制窗关闭:已触发停止标志

>>

结束

更多详细内容请访问

http://【无人机路径规划】有图有真相MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释)资源-ZEEKLOG下载 https://download.ZEEKLOG.net/download/xiaoxingkongyuxi/92570528

http://【无人机路径规划】有图有真相MATLAB实现基于GWO-RRT灰狼优化算法(GWO)结合快速搜索随机树算法(RRT)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释)资源-ZEEKLOG下载 https://download.ZEEKLOG.net/download/xiaoxingkongyuxi/92570528

 

Read more

Java 大视界 -- Java 大数据在智能医疗影像数据压缩与传输优化中的技术应用

Java 大视界 -- Java 大数据在智能医疗影像数据压缩与传输优化中的技术应用

Java 大视界 -- Java 大数据在智能医疗影像数据压缩与传输优化中的技术应用 * 引言: * 正文: * 一、智能医疗影像数据的「三重困境」 * 1.1 数据洪流:存储成本的指数级增长 * 1.2 实时枷锁:远程医疗的传输瓶颈 * 1.3 质量红线:压缩与保真的矛盾 * 二、Java 大数据:医疗影像压缩的「智能引擎」 * 2.1 算法精研:从传统到智能的跨越 * 2.2 动态优化:基于 AI 的智能压缩策略 * 三、Java 大数据:医疗影像传输的「加速引擎」 * 3.1 分布式架构:突破传输带宽限制 * 3.2 边缘计算:构建「

By Ne0inhk
【015】Java中如何使用wait()和notify()方法?

【015】Java中如何使用wait()和notify()方法?

文章目录 * 📢 外卖催单催早了?wait () 和 notify () 教你给线程 “发暗号” * 零、引入 * 一、wait () 和 notify ():线程间的 “后厨喊号系统” * 二、正确用法:3 个核心规则 + 完整可运行代码 * 三、进阶:notify () 和 notifyAll () 的区别,别喊错人 * 四、真实使用场景:生产者 - 消费者模式 * 五、总结:5 分钟上手的核心要点 * 六、最后说句实在的 在Java中使用wait()和notify()方法的方式: 1、wait(): 调用wait()使当前线程等待,直到其他线程调用此对象的notify()或notifyAll()方法。 2、notify(

By Ne0inhk

Trae java项目配置全局maven和jdk

** Trae java项目配置全局maven和jdk ** 依次打开:设置-开发环境-Maven-for-Java(或全局搜索Maven-for-Java配置) 找到以下设置,点击在settings.json中编辑 在出现的配置文件中,填入以下配置: {"maven.excludedFolders":["**/.*","**/node_modules","**/target","**/bin","**/archetype-resources"],"maven.settingsFile":"你本地文件地址,例如:E:\\****\\apache-maven-3.8.4\\conf\\settings.xml","workbench.colorTheme":"Default

By Ne0inhk
【Java 开发日记】我们来说一下 MySQL 的慢查询日志

【Java 开发日记】我们来说一下 MySQL 的慢查询日志

目录 一、什么是慢查询日志 二、核心作用 三、配置参数详解 四、开启和配置 1. 临时开启(重启失效) 2. 永久开启(修改配置文件) 五、慢查询日志格式分析 典型日志条目: 关键字段解释: 六、慢查询分析工具 1. mysqldumpslow(MySQL 自带) 2. pt-query-digest(Percona Toolkit) 3. mysqlslow(第三方工具) 七、慢查询日志表模式 启用表模式存储: 表结构: 八、最佳实践和优化建议 1. 阈值设置建议 2. 日志轮转配置 3. 定期分析计划 九、性能监控和告警 1. 监控慢查询数量 2. 慢查询告警脚本

By Ne0inhk