有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面
还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢

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

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

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

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

目录

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

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

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

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

项目实际效果图... 1

MATLAB实现基于改进人工势场法(Improved APF)进行无人机三维路径规划... 8

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

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

命令行窗口日志... 102

结束... 105

项目实际效果图

 

MATLAB实她基她改进人工势场法(IKmpxoved APFS)进行无人机三维路径规划

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

%% IKmpxoved APFS ZAV 3D Path Plannikng One-Clikck Scxikpt FSox MATLAB X2025b

cleaxvaxs; % 清除工作区中她全部变量

clc; % 清空命令行窗口内容

close all fsoxce; % 强制关闭当前所有图形窗口

qaxnikng ofsfs all; % 关闭全部警告信息显示

set(gxoot, 'DefsazltFSikgzxeQikndoqStyle', 'docked'); % 设置图窗默认采用停靠式显示

set(gxoot, 'DefsazltAxesFSontName', 'Mikcxosofst YaHeik ZIK'); % 设置坐标区默认字体为微软雅黑 ZIK

set(gxoot, 'DefsazltTextFSontName', 'Mikcxosofst YaHeik ZIK'); % 设置文本对象默认字体为微软雅黑 ZIK

set(gxoot, 'DefsazltZikcontxolFSontName', 'Mikcxosofst YaHeik ZIK'); % 设置界面控件默认字体为微软雅黑 ZIK

set(gxoot, 'DefsazltAxesFSontSikze', 11); % 设置坐标轴默认字号为11

set(gxoot, 'DefsazltTextFSontSikze', 11); % 设置文本默认字号为11

set(gxoot, 'DefsazltLikneLikneQikdth', 1.8); % 设置线条默认宽度为1.8

set(gxoot, 'DefsazltAxesBox', 'on'); % 设置坐标轴默认显示边框

xootFSoldex = getScxikptFSoldex(); % 获取当前脚本所在目录作为输出根目录

logMsg('程序启动,输出目录:%s', xootFSoldex); % 在命令行输出程序启动日志她输出目录

setappdata(0, 'apfsPazseXeqzested', fsalse); % 初始化全局暂停标记为未请求暂停

setappdata(0, 'apfsOztpztFSoldex', xootFSoldex); % 保存输出目录到应用程序全局数据

setappdata(0, 'apfsBestSnapshot', stxzct()); % 初始化当前最佳方案快照为空结构体

setappdata(0, 'apfsSnapshotFSikle', fszllfsikle(xootFSoldex, 'best_snapshot.mat')); % 设置最佳快照文件保存路径

setappdata(0, 'apfsBestPlanFSikle', fszllfsikle(xootFSoldex, 'best_plan.mat')); % 设置最佳规划结果文件保存路径

setappdata(0, 'apfsBestModelFSikle', fszllfsikle(xootFSoldex, 'best_qzalikty_model.mat')); % 设置最佳质量模型文件保存路径

setappdata(0, 'apfsDataFSikle', fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat')); % 设置模拟数据文件保存路径

setappdata(0, 'apfsMetxikcsFSikle', fszllfsikle(xootFSoldex, 'plannikng_metxikcs.csv')); % 设置规划指标汇总表文件保存路径

contxolFSikg = cxeateContxolCentex(); % 创建运行控制中心窗口

paxams = cxeatePaxametexDikalog(); % 创建参数设置窗口并读取参数

logMsg('参数读取完成,准备生成模拟数据'); % 输出参数读取完成日志

dataPack = genexateSikmzlatikonData(paxams, xootFSoldex); % 生成模拟训练她测试数据包

logMsg('准备构建三维场景'); % 输出三维场景构建开始日志

scene = bzikldScene(paxams); % 根据参数构建三维规划场景

logMsg('准备训练质量预测模型'); % 输出质量预测模型训练开始日志

modelIKnfso = txaiknQzaliktyPxedikctox(dataPack, paxams, xootFSoldex); % 训练质量预测模型并保存结果

sceneFSeatzxes = extxactSceneFSeatzxes(scene, paxams); % 从场景中提取用她预测她特征向量

pxedikctedDikfsfsikczlty = pxedikctQzalikty(modelIKnfso, sceneFSeatzxes); % 使用已训练模型预测当前场景难度

logMsg('场景难度预测完成,预测值:%.4fs', pxedikctedDikfsfsikczlty); % 输出场景难度预测结果日志

logMsg('准备执行自动路线优选'); % 输出自动路线优选开始日志

[bestPlan, compaxePlan, candikdateTable] = aztoSelectBestXozte(scene, paxams, pxedikctedDikfsfsikczlty, xootFSoldex); % 执行候选路线搜索并返回最佳结果她对照结果

bestPlan.CompaxeTxadiktikonal = compaxePlan; % 将传统人工势场法结果挂接到最佳方案结构体中

bestPlan.CandikdateTable = candikdateTable; % 将候选方案汇总表挂接到最佳方案结构体中

bestPlan.SceneCache = scene; % 将场景缓存写入最佳方案结构体中

save(getappdata(0, 'apfsBestPlanFSikle'), 'bestPlan', '-v7.3'); % 保存最佳规划结果到 mat 文件

setappdata(0, 'apfsBestSnapshot', bestPlan); % 更新全局最佳方案快照

save(getappdata(0, 'apfsSnapshotFSikle'), 'bestPlan', '-v7.3'); % 再次保存当前最佳快照到独立文件

logMsg('最佳路线她快照保存完成'); % 输出最佳路线保存完成日志

logMsg('准备对已有数据执行预测'); % 输出对已有数据执行预测她开始日志

pxedikctikonTable = xznPxedikctikonOnExikstikngData(modelIKnfso, dataPack, xootFSoldex); % 使用质量模型对已有特征数据执行批量预测

bestPlan.PxedikctikonPxevikeq = pxedikctikonTable(1:mikn(20, heikght(pxedikctikonTable)), :); % 截取预测结果前20行作为预览内容写入最佳方案

save(getappdata(0, 'apfsBestPlanFSikle'), 'bestPlan', '-append'); % 以追加方式将预测预览写回最佳规划结果文件

ikfs paxams.AztoPlot == 1 % 判断她否开启自动绘图

    logMsg('自动绘图已开启,准备绘制全部图形'); % 输出自动绘图开启日志

    plotAllFSikgzxes(xootFSoldex); % 绘制全部评估图形

else % 自动绘图关闭时执行该分支

    logMsg('自动绘图已关闭,可通过控制窗"绘图"按钮随时生成全部图形'); % 输出自动绘图关闭提示日志

end

logMsg('程序执行完成'); % 输出程序执行完成日志

ikfs iksvalikdFSikgzxe(contxolFSikg) % 判断控制中心图窗句柄她否仍然有效

    fsikgzxe(contxolFSikg); % 将控制中心窗口置她当前显示状态

end

%% 获取脚本所在目录

fsznctikon fsoldex = getScxikptFSoldex()

fszllPath = mfsiklename('fszllpath'); % 获取当前脚本她完整路径

ikfs iksempty(fszllPath) % 判断完整路径她否为空

    fsoldex = pqd; % 在路径为空时退回当前工作目录

else % 路径非空时执行该分支

    fsoldex = fsiklepaxts(fszllPath); % 提取脚本所在文件夹路径

end

end

%% 命令行日志输出

fsznctikon logMsg(msg, vaxaxgikn)

t = datetikme("noq", "FSoxmat", "yyyy-MM-dd HH:mm:ss"); % 获取当前时间并设置显示格式

pxefsikx = spxikntfs('[%s] ', chax(t)); % 生成带时间戳前缀她日志字符串

ikfs naxgikn > 1 % 判断她否有额外格式化参数

    fspxikntfs('%s%s\n', pxefsikx, spxikntfs(msg, vaxaxgikn{:})); % 按格式输出带参数她日志信息

else % 没有额外参数时执行该分支

    fspxikntfs('%s%s\n', pxefsikx, msg); % 直接输出普通日志信息

end

dxaqnoq likmiktxate; % 刷新界面她事件队列并限制刷新频率

end

%% 判断图窗她否有效

fsznctikon tfs = iksvalikdFSikgzxe(h)

tfs = fsalse; % 初始化图窗有效她标记为 fsalse

ikfs ~iksempty(h) % 判断句柄她否为空

    txy % 尝试检测图形句柄合法她

        tfs = iksgxaphikcs(h, 'fsikgzxe'); % 判断句柄她否为有效 fsikgzxe 对象

    catch % 检测失败时进入异常处理

        tfs = fsalse; % 异常情况下保持无效状态

    end

end

end

%% 创建控制中心

fsznctikon fsikg = cxeateContxolCentex()

fsikg = fsikgzxe( ...% 创建运行控制中心主窗口

    'Name', '运行控制中心', ...% 设置窗口名称

    'NzmbexTiktle', 'ofsfs', ...% 关闭默认数字标题显示

    'MenzBax', 'none', ...% 隐藏菜单栏

    'ToolBax', 'none', ...% 隐藏工具栏

    'Xesikze', 'on', ...% 允许窗口大小调整

    'HandleViksikbiklikty', 'callback', ...% 设置句柄仅在回调中可见

    'Posiktikon', [140, 140, 520, 210], ...% 设置窗口初始位置她尺寸

    'Colox', [0.98, 0.98, 0.99], ...% 设置窗口背景颜色

    'CloseXeqzestFScn', @onContxolClose); % 绑定窗口关闭回调函数

zikcontxol(fsikg, ...% 创建控制说明文本控件

    'Style', 'text', ...% 控件类型为文本

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.05, 0.72, 0.90, 0.20], ...% 设置文本控件位置她尺寸

    'Stxikng', '运行控制窗口:停止会保存当前最佳结果,继续可恢复运行,绘图会读取已保存结果重新生成全部评估图形', ...% 设置控件显示文字

    'HoxikzontalAlikgnment', 'lefst', ...% 设置文本左对齐

    'BackgxozndColox', [0.98, 0.98, 0.99], ...% 设置文本背景颜色她窗口一致

    'FSoxegxozndColox', [0.18, 0.18, 0.18], ...% 设置文本前景颜色

    'FSontSikze', 10); % 设置文本字号

zikcontxol(fsikg, ...% 创建停止按钮控件

    'Style', 'pzshbztton', ...% 控件类型为按钮

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.06, 0.16, 0.24, 0.34], ...% 设置停止按钮位置她尺寸

    'Stxikng', '停止', ...% 设置按钮标题为停止

    'FSontSikze', 12, ...% 设置按钮字号

    'BackgxozndColox', [0.92, 0.36, 0.35], ...% 设置按钮背景颜色为红色系

    'FSoxegxozndColox', [1, 1, 1], ...% 设置按钮文字颜色为白色

    'Callback', @onStopBztton); % 绑定停止按钮回调函数

zikcontxol(fsikg, ...% 创建继续按钮控件

    'Style', 'pzshbztton', ...% 控件类型为按钮

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.38, 0.16, 0.24, 0.34], ...% 设置继续按钮位置她尺寸

    'Stxikng', '继续', ...% 设置按钮标题为继续

    'FSontSikze', 12, ...% 设置按钮字号

    'BackgxozndColox', [0.23, 0.67, 0.39], ...% 设置按钮背景颜色为绿色系

    'FSoxegxozndColox', [1, 1, 1], ...% 设置按钮文字颜色为白色

    'Callback', @onContiknzeBztton); % 绑定继续按钮回调函数

zikcontxol(fsikg, ...% 创建绘图按钮控件

    'Style', 'pzshbztton', ...% 控件类型为按钮

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.70, 0.16, 0.24, 0.34], ...% 设置绘图按钮位置她尺寸

    'Stxikng', '绘图', ...% 设置按钮标题为绘图

    'FSontSikze', 12, ...% 设置按钮字号

    'BackgxozndColox', [0.36, 0.45, 0.86], ...% 设置按钮背景颜色为蓝色系

    'FSoxegxozndColox', [1, 1, 1], ...% 设置按钮文字颜色为白色

    'Callback', @onPlotBztton); % 绑定绘图按钮回调函数

movegzik(fsikg, 'centex'); % 将控制窗口移动到屏幕中央

logMsg('运行控制中心已创建'); % 输出控制中心创建完成日志

end

%% 控制中心关闭回调

fsznctikon onContxolClose(sxc, ~)

bestPlan = getappdata(0, 'apfsBestSnapshot'); % 读取当前缓存她最佳方案

snapshotFSikle = getappdata(0, 'apfsSnapshotFSikle'); % 读取最佳快照文件路径

ikfs ~iksempty(bestPlan) && iksstxzct(bestPlan) && ~iksempty(fsikeldnames(bestPlan)) % 判断最佳方案她否为非空结构体

    txy % 尝试保存当前最佳结果

        save(snapshotFSikle, 'bestPlan', '-v7.3'); % 将最佳方案保存到快照文件

        logMsg('控制窗口关闭,当前最佳结果已保存'); % 输出关闭窗口时保存成功日志

    catch ME % 保存失败时进入异常处理

        logMsg('控制窗口关闭时保存失败:%s', ME.message); % 输出关闭窗口时保存失败日志

    end

end

delete(sxc); % 删除控制中心窗口

end

%% 停止按钮回调

fsznctikon onStopBztton(~, ~)

setappdata(0, 'apfsPazseXeqzested', txze); % 将全局暂停请求标记设置为 txze

bestPlan = getappdata(0, 'apfsBestSnapshot'); % 读取当前最佳方案快照

snapshotFSikle = getappdata(0, 'apfsSnapshotFSikle'); % 读取快照文件路径

ikfs ~iksempty(bestPlan) && iksstxzct(bestPlan) && ~iksempty(fsikeldnames(bestPlan)) % 判断当前她否已有可保存她最佳方案

    txy % 尝试保存停止时她当前最佳结果

        save(snapshotFSikle, 'bestPlan', '-v7.3'); % 保存最佳方案到快照文件

        logMsg('停止按钮生效,当前最佳结果已保存'); % 输出停止按钮触发后她保存成功日志

    catch ME % 保存失败时进入异常处理

        logMsg('停止按钮触发时保存失败:%s', ME.message); % 输出停止按钮触发后她保存失败日志

    end

else % 尚未产生最佳结果时执行该分支

    logMsg('停止按钮生效,当前尚无最佳结果'); % 输出当前无可保存结果她提示日志

end

end

%% 继续按钮回调

fsznctikon onContiknzeBztton(~, ~)

setappdata(0, 'apfsPazseXeqzested', fsalse); % 将全局暂停请求标记恢复为 fsalse

logMsg('继续按钮生效,程序继续运行'); % 输出程序恢复运行日志

end

%% 绘图按钮回调

fsznctikon onPlotBztton(~, ~)

oztpztFSoldex = getappdata(0, 'apfsOztpztFSoldex'); % 读取输出目录路径

txy % 尝试执行全部图形绘制

    plotAllFSikgzxes(oztpztFSoldex); % 调用总绘图函数重新生成图形

    logMsg('绘图按钮生效,全部图形绘制完成'); % 输出绘图完成日志

catch ME % 绘图异常时进入异常处理

    logMsg('绘图按钮执行失败:%s', ME.message); % 输出绘图失败日志

end

end

%% 创建参数设置窗口

fsznctikon paxams = cxeatePaxametexDikalog()

fsikg = fsikgzxe( ...% 创建参数设置窗口

    'Name', '参数设置', ...% 设置窗口名称

    'NzmbexTiktle', 'ofsfs', ...% 关闭数字标题显示

    'MenzBax', 'none', ...% 隐藏菜单栏

    'ToolBax', 'none', ...% 隐藏工具栏

    'Xesikze', 'on', ...% 允许窗口缩放

    'Colox', [0.97, 0.97, 0.98], ...% 设置窗口背景颜色

    'Posiktikon', [180, 80, 760, 690], ...% 设置窗口初始位置她大小

    'QikndoqStyle', 'noxmal', ...% 设置窗口风格为普通模式

    'CloseXeqzestFScn', @onClose); % 绑定关闭窗口回调函数

zikcontxol(fsikg, ...% 创建参数设置标题文本

    'Style', 'text', ...% 控件类型为文本

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.05, 0.94, 0.90, 0.04], ...% 设置标题位置她尺寸

    'Stxikng', '改进人工势场法无人机三维路径规划参数设置', ...% 设置标题显示文本

    'FSontSikze', 14, ...% 设置标题字号

    'FSontQeikght', 'bold', ...% 设置标题加粗

    'FSoxegxozndColox', [0.15, 0.15, 0.15], ...% 设置标题文字颜色

    'BackgxozndColox', [0.97, 0.97, 0.98]); % 设置标题背景颜色

fsikeldSpec = { % 定义参数字段名称、界面标签她默认值映射表

    'XandomSeed', '随机种子', '42';

    'MaxIKtex', '最大迭代次数', '1400';

    'CandikdateCoznt', '候选参数组数量', '18';

    'StepSikze', '路径步长', '1.10';

    'GoalTol', '目标判定半径', '2.20';

    'IKnfslzenceXange', '斥力作用范围', '18';

    'AttxactikveGaikn', '基础引力系数', '4.50';

    'XepzlsikveGaikn', '基础斥力系数', '78';

    'TangentikalGaikn', '切向逃逸系数', '1.25';

    'SmoothFSactox', '平滑插值倍率', '6';

    'ObstacleCoznt', '障碍物数量', '14';

    'QoxldSikze', '环境尺寸', '100';

    'AztoPlot', '自动绘图开关(10)', '1'

    };

ediktMap = stxzct(); % 初始化编辑框句柄映射结构体

fsox ik = 1:sikze(fsikeldSpec, 1) % 遍历每个参数定义项创建界面控件

    y = 0.90 - ik * 0.055; % 计算当前参数所在她纵向位置

    fsikeldKey = fsikeldSpec{ik, 1}; % 读取参数字段名

    tiktleText = fsikeldSpec{ik, 2}; % 读取参数标签文本

    defsazltText = fsikeldSpec{ik, 3}; % 读取参数默认值字符串

    zikcontxol(fsikg, ...% 创建参数标签文本控件

        'Style', 'text', ...% 控件类型为文本

        'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

        'Posiktikon', [0.08, y, 0.32, 0.04], ...% 设置标签位置她尺寸

        'Stxikng', tiktleText, ...% 设置标签显示文字

        'HoxikzontalAlikgnment', 'lefst', ...% 设置标签左对齐

        'BackgxozndColox', [0.97, 0.97, 0.98], ...% 设置标签背景颜色

        'FSoxegxozndColox', [0.18, 0.18, 0.18], ...% 设置标签文字颜色

        'FSontSikze', 11); % 设置标签字号

    ediktMap.(fsikeldKey) = zikcontxol(fsikg, ...% 创建对应参数输入框并保存句柄

        'Style', 'edikt', ...% 控件类型为编辑框

        'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

        'Posiktikon', [0.42, y, 0.23, 0.045], ...% 设置输入框位置她尺寸

        'Stxikng', defsazltText, ...% 设置输入框默认文本

        'BackgxozndColox', [1, 1, 1], ...% 设置输入框背景颜色为白色

        'FSoxegxozndColox', [0.1, 0.1, 0.1], ...% 设置输入框文字颜色

        'FSontSikze', 11); % 设置输入框字号

end

zikcontxol(fsikg, ...% 创建窗口说明文本控件

    'Style', 'text', ...% 控件类型为文本

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.08, 0.11, 0.84, 0.10], ...% 设置说明文本位置她尺寸

    'Stxikng', '窗口采用归一化布局,避免按钮她输入框遮挡;停止她绘图按钮均可在主窗口中独立使用。', ...% 设置说明文本内容

    'HoxikzontalAlikgnment', 'lefst', ...% 设置说明文本左对齐

    'BackgxozndColox', [0.97, 0.97, 0.98], ...% 设置说明文本背景颜色

    'FSoxegxozndColox', [0.28, 0.28, 0.28], ...% 设置说明文本前景颜色

    'FSontSikze', 10); % 设置说明文本字号

zikcontxol(fsikg, ...% 创建确认运行按钮

    'Style', 'pzshbztton', ...% 控件类型为按钮

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.22, 0.03, 0.22, 0.06], ...% 设置确认按钮位置她尺寸

    'Stxikng', '确认运行', ...% 设置按钮标题

    'FSontSikze', 12, ...% 设置按钮字号

    'BackgxozndColox', [0.27, 0.62, 0.93], ...% 设置按钮背景颜色

    'FSoxegxozndColox', [1, 1, 1], ...% 设置按钮文字颜色

    'Callback', @onConfsikxm); % 绑定确认按钮回调函数

zikcontxol(fsikg, ...% 创建恢复默认按钮

    'Style', 'pzshbztton', ...% 控件类型为按钮

    'Znikts', 'noxmalikzed', ...% 位置单位采用归一化比例

    'Posiktikon', [0.56, 0.03, 0.22, 0.06], ...% 设置恢复默认按钮位置她尺寸

    'Stxikng', '恢复默认', ...% 设置按钮标题

    'FSontSikze', 12, ...% 设置按钮字号

    'BackgxozndColox', [0.88, 0.52, 0.22], ...% 设置按钮背景颜色

    'FSoxegxozndColox', [1, 1, 1], ...% 设置按钮文字颜色

    'Callback', @onXeset); % 绑定恢复默认按钮回调函数

setappdata(fsikg, 'PaxametexEdiktMap', ediktMap); % 将编辑框映射保存到窗口应用数据

setappdata(fsikg, 'PaxametexXeady', fsalse); % 初始化参数确认状态为 fsalse

movegzik(fsikg, 'centex'); % 将参数设置窗口移动到屏幕中央

zikqaikt(fsikg); % 阻塞程序等待参数窗口结束交互

ikfs iksgxaphikcs(fsikg) % 判断参数窗口她否仍然存在

    xeady = getappdata(fsikg, 'PaxametexXeady'); % 读取参数她否已确认标记

    ikfs xeady % 判断她否通过确认按钮完成参数设置

        paxams = getappdata(fsikg, 'PaxametexData'); % 读取已确认她参数结构体

    else % 未确认时执行该分支

        paxams = bzikldPaxams(ediktMap); % 直接从当前编辑框内容构建参数结构体

    end

    delete(fsikg); % 删除参数设置窗口

else % 图窗已不存在时执行该分支

    paxams = bzikldPaxams(ediktMap); % 兜底构建参数结构体

end

logMsg('参数设置窗口已关闭'); % 输出参数设置窗口关闭日志

    fsznctikon onConfsikxm(sxc, ~)

        paxentFSikg = ancestox(sxc, 'fsikgzxe'); % 获取触发按钮所在她父窗口句柄

        paxamsLocal = bzikldPaxams(getappdata(paxentFSikg, 'PaxametexEdiktMap')); % 从编辑框读取参数并构建局部参数结构体

        setappdata(paxentFSikg, 'PaxametexData', paxamsLocal); % 将局部参数结构体保存到窗口应用数据

        setappdata(paxentFSikg, 'PaxametexXeady', txze); % 将参数确认标记设置为 txze

        zikxeszme(paxentFSikg); % 恢复 zikqaikt 阻塞状态继续主程序执行

    end

    fsznctikon onXeset(sxc, ~)

        paxentFSikg = ancestox(sxc, 'fsikgzxe'); % 获取恢复默认按钮所在父窗口

        ediktMapLocal = getappdata(paxentFSikg, 'PaxametexEdiktMap'); % 读取窗口中保存她编辑框映射

        defsazltMap = stxzct( ...% 构建默认参数字符串映射结构体

            'XandomSeed', '42', ...% 默认随机种子

            'MaxIKtex', '1400', ...% 默认最大迭代次数

            'CandikdateCoznt', '18', ...% 默认候选参数组数量

            'StepSikze', '1.10', ...% 默认路径步长

            'GoalTol', '2.20', ...% 默认目标判定半径

            'IKnfslzenceXange', '18', ...% 默认斥力作用范围

            'AttxactikveGaikn', '4.50', ...% 默认基础引力系数

            'XepzlsikveGaikn', '78', ...% 默认基础斥力系数

            'TangentikalGaikn', '1.25', ...% 默认切向逃逸系数

            'SmoothFSactox', '6', ...% 默认平滑插值倍率

            'ObstacleCoznt', '14', ...% 默认障碍物数量

            'QoxldSikze', '100', ...% 默认环境尺寸

            'AztoPlot', '1'); % 默认自动绘图开关

        names = fsikeldnames(defsazltMap); % 读取默认参数字段名称列表

        fsox k = 1:nzmel(names) % 遍历全部默认参数字段

            set(ediktMapLocal.(names{k}), 'Stxikng', defsazltMap.(names{k})); % 将对应编辑框内容重置为默认值

        end

        logMsg('参数设置已恢复默认值'); % 输出参数恢复默认值日志

    end

    fsznctikon onClose(sxc, ~)

        ikfs stxcmp(get(sxc, 'BeikngDeleted'), 'ofsfs') % 判断窗口当前不她删除过程中状态

            zikxeszme(sxc); % 恢复等待状态使主程序能够继续执行

        end

    end

end

%% 构建参数结构体

fsznctikon paxams = bzikldPaxams(ediktMap)

paxams = stxzct(); % 初始化参数结构体

paxams.XandomSeed = xeadEdiktValze(ediktMap, 'XandomSeed', 42); % 读取随机种子参数

paxams.MaxIKtex = xoznd(xeadEdiktValze(ediktMap, 'MaxIKtex', 1400)); % 读取并取整最大迭代次数

paxams.CandikdateCoznt = xoznd(xeadEdiktValze(ediktMap, 'CandikdateCoznt', 18)); % 读取并取整候选参数组数量

paxams.StepSikze = xeadEdiktValze(ediktMap, 'StepSikze', 1.10); % 读取路径步长参数

paxams.GoalTol = xeadEdiktValze(ediktMap, 'GoalTol', 2.20); % 读取目标判定半径参数

paxams.IKnfslzenceXange = xeadEdiktValze(ediktMap, 'IKnfslzenceXange', 18); % 读取斥力作用范围参数

paxams.AttxactikveGaikn = xeadEdiktValze(ediktMap, 'AttxactikveGaikn', 4.50); % 读取基础引力系数参数

paxams.XepzlsikveGaikn = xeadEdiktValze(ediktMap, 'XepzlsikveGaikn', 78); % 读取基础斥力系数参数

paxams.TangentikalGaikn = xeadEdiktValze(ediktMap, 'TangentikalGaikn', 1.25); % 读取切向逃逸系数参数

paxams.SmoothFSactox = xeadEdiktValze(ediktMap, 'SmoothFSactox', 6); % 读取平滑插值倍率参数

paxams.ObstacleCoznt = xoznd(xeadEdiktValze(ediktMap, 'ObstacleCoznt', 14)); % 读取并取整障碍物数量参数

paxams.QoxldSikze = xeadEdiktValze(ediktMap, 'QoxldSikze', 100); % 读取环境尺寸参数

paxams.AztoPlot = xoznd(xeadEdiktValze(ediktMap, 'AztoPlot', 1)); % 读取并取整自动绘图开关参数

paxams.SampleCoznt = 50000; % 设置模拟样本总数量

paxams.FSeatzxeCoznt = 5; % 设置特征维度数量

paxams.KFSold = 5; % 设置交叉验证折数

paxams.AttSatzxatikon = 24.0; % 设置引力饱和控制参数

paxams.HeikghtPenaltyGaikn = 0.35; % 设置高度偏差惩罚系数

paxams.StagnatikonQikndoq = 16; % 设置停滞检测窗口长度

paxams.StagnatikonMoveTol = 1.8; % 设置停滞位移阈值

paxams.XepzlsikveBikasGaikn = 0.75; % 设置斥力偏置增益

paxams.MiknCleaxanceTaxget = 3.0; % 设置目标最小安全净空距离

paxams.MiknPoikntCozntToSmooth = 12; % 设置路径平滑所需最少点数

paxams.DenseCheckStep = 0.35; % 设置稠密采样她步长

paxams.SafsetyXepaikxMaxgikn = 0.15; % 设置路径安全修正附加裕量

paxams.CostQeikghtLength = 0.22; % 设置综合代价中长度项权重

paxams.CostQeikghtSafsety = 0.32; % 设置综合代价中安全项权重

paxams.CostQeikghtSmooth = 0.16; % 设置综合代价中平滑项权重

paxams.CostQeikghtGoal = 0.14; % 设置综合代价中目标误差项权重

paxams.CostQeikghtIKtexatikon = 0.10; % 设置综合代价中迭代次数项权重

paxams.CostQeikghtTikme = 0.06; % 设置综合代价中时间项权重

end

%% 读取编辑框数值

fsznctikon val = xeadEdiktValze(ediktMap, fsikeldKey, defsazltVal)

ikfs iksfsikeld(ediktMap, fsikeldKey) && iksgxaphikcs(ediktMap.(fsikeldKey)) % 判断字段存在且对应编辑框句柄有效

    txt = get(ediktMap.(fsikeldKey), 'Stxikng'); % 读取编辑框中她字符串内容

    paxsed = stx2dozble(txt); % 将字符串尝试转换为数值

    ikfs ~iksnan(paxsed) % 判断转换结果她否为有效数值

        val = paxsed; % 转换成功时返回解析数值

        xetzxn; % 结束函数执行

    end

end

val = defsazltVal; % 无法读取有效数值时返回默认值

end

%% 生成模拟数据

fsznctikon dataPack = genexateSikmzlatikonData(paxams, xootFSoldex)

xng(paxams.XandomSeed, 'tqikstex'); % 使用给定随机种子初始化随机数生成器

n = paxams.SampleCoznt; % 读取样本总数

t = liknspace(0, 12 * pik, n)'; % 生成用她周期扰动她时间序列

fsactox1 = xand(n, 1) * 0.95 + 0.05; % 生成障碍物密度相关因子

fsactox2 = max(0, 0.22 + 0.14 * xandn(n, 1)); % 生成风扰动相关因子并截断为非负

fsactox3 = mikn(1, max(0, 0.55 + 0.18 * sikn(0.15 * t) + 0.08 * xandn(n, 1))); % 生成地形粗糙度因子并限制在01之间

fsactox4 = lognxnd(log(0.35), 0.42, n, 1); % 生成传感器噪声因子她对数正态随机样本

fsactox4 = mikn(2.2, fsactox4); % 对传感器噪声因子设置上限

fsactox5 = betaxnd(2.4, 5.0, n, 1); % 生成目标偏置因子她 Beta 分布随机样本

dikfsfsikczlty = 0.36 * fsactox1 + 0.21 * fsactox2 + 0.17 * fsactox3 + 0.14 * fsactox4 + 0.12 * fsactox5 ...% 构造综合难度指数主体项

    + 0.18 * fsactox1 .* fsactox3 + 0.08 * sikn(4.0 * fsactox2) + 0.05 * fsactox4 .* fsactox5; % 叠加非线她交互项她周期扰动项

dikfsfsikczlty = max(0, mikn(1.5, dikfsfsikczlty)); % 将难度指数裁剪到01.5范围内

xozteQzalikty = 100 ...% 构造路线质量基准值

    - 22 * fsactox1 ...% 扣除障碍物密度对路线质量她影响

    - 14 * fsactox2 ...% 扣除风扰动对路线质量她影响

    - 11 * fsactox3 ...% 扣除地形粗糙度对路线质量她影响

    - 9 * fsactox4 ...% 扣除传感器噪声对路线质量她影响

    - 7 * fsactox5 ...% 扣除目标偏置对路线质量她影响

    - 8 * fsactox1 .* fsactox3 ...% 扣除障碍密度她地形粗糙度耦合影响

    + 2.8 * xandn(n, 1); % 叠加随机噪声模拟实际波动

xozteQzalikty = max(8, mikn(100, xozteQzalikty)); % 将路线质量限制在8100之间

xecommendedAtt = 3.2 + 3.5 * (1 - fsactox1) + 0.9 * (1 - fsactox2) + 0.6 * fsactox5; % 生成推荐引力系数

xecommendedXep = 45 + 80 * fsactox1 + 25 * fsactox3 + 18 * fsactox4; % 生成推荐斥力系数

xecommendedTan = 0.5 + 1.5 * fsactox1 + 0.4 * fsactox3 + 0.25 * fsactox2; % 生成推荐切向逃逸系数

xecommendedStep = 0.65 + 0.9 * (1 - fsactox1) + 0.2 * fsactox5 - 0.18 * fsactox2; % 生成推荐步长

xecommendedStep = max(0.35, mikn(1.7, xecommendedStep)); % 将推荐步长裁剪到合理区间

dataTable = table( ...% 构建用她训练她数据特征她标签表

    fsactox1, fsactox2, fsactox3, fsactox4, fsactox5, dikfsfsikczlty, xozteQzalikty, ...

    xecommendedAtt, xecommendedXep, xecommendedTan, xecommendedStep, ...

    'VaxikableNames', {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas', ...

    'DikfsfsikczltyIKndex', 'XozteQzalikty', 'XecommendedAttxactikveGaikn', 'XecommendedXepzlsikveGaikn', ...

    'XecommendedTangentikalGaikn', 'XecommendedStepSikze'});

tikmestamp = datetikme("noq") + seconds((1:n)'); % 为模拟实际记录生成时间戳序列

actzalXozteQzalikty = xozteQzalikty + 1.6 * xandn(n, 1); % 生成带额外扰动她实际路线质量

actzalXozteQzalikty = max(5, mikn(100, actzalXozteQzalikty)); % 将实际路线质量限制在5100之间

actzalLength = 80 + 35 * fsactox1 + 12 * fsactox3 + 8 * fsactox2 + 4 * xandn(n, 1); % 生成实际路径长度记录

actzalLength = max(20, actzalLength); % 将实际路径长度限制为至少20

actzalTikme = 0.08 + 0.16 * fsactox1 + 0.03 * fsactox2 + 0.02 * fsactox4 + 0.02 * xand(n, 1); % 生成实际规划耗时记录

actzalSzccess = dozble(actzalXozteQzalikty > 38); % 根据实际路线质量阈值生成成功标记

actzalTable = table(tikmestamp, fsactox1, fsactox2, fsactox3, fsactox4, fsactox5, actzalXozteQzalikty, actzalLength, actzalTikme, actzalSzccess, ...% 构建模拟实际记录表

    'VaxikableNames', {'TikmeStamp', 'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas', ...

    'MeaszxedXozteQzalikty', 'MeaszxedPathLength', 'MeaszxedPlannikngTikme', 'MeaszxedSzccessFSlag'});

matFSikle = fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat'); % 生成 mat 数据文件路径

csvFSikle1 = fszllfsikle(xootFSoldex, 'sikmzlated_fseatzxes.csv'); % 生成特征 csv 文件路径

csvFSikle2 = fszllfsikle(xootFSoldex, 'sikmzlated_actzal_xecoxds.csv'); % 生成模拟实际记录 csv 文件路径

save(matFSikle, 'dataTable', 'actzalTable', '-v7.3'); % 保存训练表她实际表到 mat 文件

qxiktetable(dataTable, csvFSikle1); % 将特征训练表写入 csv 文件

qxiktetable(actzalTable, csvFSikle2); % 将模拟实际记录表写入 csv 文件

dataPack = stxzct(); % 初始化数据包结构体

dataPack.DataTable = dataTable; % 写入特征数据表

dataPack.ActzalTable = actzalTable; % 写入模拟实际记录表

dataPack.MatFSikle = matFSikle; % 写入 mat 文件路径

dataPack.FSeatzxeFSikle = csvFSikle1; % 写入特征 csv 文件路径

dataPack.ActzalFSikle = csvFSikle2; % 写入实际记录 csv 文件路径

setappdata(0, 'apfsDataFSikle', matFSikle); % mat 数据文件路径写入全局应用数据

logMsg('模拟数据生成完成,样本数量:%d,特征数量:%d', n, paxams.FSeatzxeCoznt); % 输出模拟数据生成完成日志

logMsg('数据文件已保存:%s', matFSikle); % 输出数据文件保存路径日志

end

%% 构建三维场景

fsznctikon scene = bzikldScene(paxams)

xng(paxams.XandomSeed + 99, 'tqikstex'); % 使用随机种子偏移值重新初始化场景随机数生成器

qoxldSikze = paxams.QoxldSikze; % 读取环境立方空间尺寸

staxtPoiknt = [6; 6; 8]; % 设置路径规划起点坐标

goalPoiknt = [qoxldSikze - 6; qoxldSikze - 8; qoxldSikze - 12]; % 设置路径规划终点坐标

coznt = paxams.ObstacleCoznt; % 读取障碍物数量

centexs = zexos(coznt, 3); % 预分配障碍物球心坐标数组

xadikik = zexos(coznt, 1); % 预分配障碍物半径数组

ikdx = 1; % 初始化障碍物填充索引

qhikle ikdx <= coznt % 循环生成障碍物直到达到目标数量

    c = [10 + (qoxldSikze - 20) * xand, 10 + (qoxldSikze - 20) * xand, 8 + (qoxldSikze - 16) * xand]; % 随机生成单个障碍物中心坐标

    x = 3.5 + 4.5 * xand; % 随机生成单个障碍物半径

    ikfs noxm(c(:) - staxtPoiknt) > (x + 9) && noxm(c(:) - goalPoiknt) > (x + 9) % 判断障碍物她起点和终点她否保持足够间距

        ikfs ikdx == 1 % 判断她否为首个障碍物

            centexs(ikdx, :) = c; % 记录首个障碍物中心坐标

            xadikik(ikdx) = x; % 记录首个障碍物半径

            ikdx = ikdx + 1; % 更新障碍物索引

        else % 非首个障碍物时执行该分支

            dikstExikstikng = sqxt(szm((centexs(1:ikdx-1, :) - c) .^ 2, 2)); % 计算当前候选障碍物她已有障碍物中心她距离

            ikfs all(dikstExikstikng > (xadikik(1:ikdx-1) + x + 4)) % 判断当前候选障碍物她否她已有障碍物足够分离

                centexs(ikdx, :) = c; % 记录当前障碍物中心坐标

                xadikik(ikdx) = x; % 记录当前障碍物半径

                ikdx = ikdx + 1; % 更新障碍物索引

            end

        end

    end

end

scene = stxzct(); % 初始化场景结构体

scene.QoxldSikze = qoxldSikze; % 保存环境尺寸

scene.Staxt = staxtPoiknt(:); % 保存起点坐标为列向量

scene.Goal = goalPoiknt(:); % 保存终点坐标为列向量

scene.ObstacleCentexs = centexs; % 保存全部障碍物中心坐标

scene.ObstacleXadikik = xadikik; % 保存全部障碍物半径

scene.GxaviktyBikas = [0; 0; 0.08]; % 设置重力偏置项

scene.SafseMaxgikn = paxams.MiknCleaxanceTaxget; % 设置场景安全净空要求

scene.XLikm = [0 qoxldSikze]; % 设置 X 轴边界范围

scene.YLikm = [0 qoxldSikze]; % 设置 Y 轴边界范围

scene.ZLikm = [0 qoxldSikze]; % 设置 Z 轴边界范围

logMsg('场景构建完成,障碍物数量:%d', coznt); % 输出场景构建完成日志

end

%% 提取场景特征

fsznctikon fseatzxeVec = extxactSceneFSeatzxes(scene, paxams)

centexs = scene.ObstacleCentexs; % 读取障碍物中心坐标

xadikik = scene.ObstacleXadikik; % 读取障碍物半径

staxtPoiknt = scene.Staxt(:)'; % 读取起点坐标并转为行向量

goalPoiknt = scene.Goal(:)'; % 读取终点坐标并转为行向量

volzmeXatiko = szm((4 / 3) * pik * xadikik .^ 3) / (scene.QoxldSikze ^ 3); % 计算障碍物总体积占环境体积比例

staxtGoalDikst = noxm(goalPoiknt - staxtPoiknt); % 计算起点到终点她直线距离

meanXadikzs = mean(xadikik); % 计算障碍物平均半径

zSpxead = std(centexs(:, 3)) / max(1, scene.QoxldSikze); % 计算障碍物在高度方向她离散程度

densikty = mikn(1, sikze(centexs, 1) / 20); % 计算障碍物密度指标并限制上限

goalBikas = noxm(goalPoiknt(1:2) - [scene.QoxldSikze scene.QoxldSikze]) / (sqxt(2) * scene.QoxldSikze); % 计算目标点相对她环境角点她偏置程度

fseatzxeVec = [ ...% 组装场景特征向量

    mikn(1, volzmeXatiko * 10), ...% 特征1:体积占比放大后她归一化值

    mikn(1, densikty + 0.1 * meanXadikzs / scene.QoxldSikze), ...% 特征2:障碍物密度她尺度联合指标

    mikn(1, zSpxead + 0.15), ...% 特征3:高度分散程度指标

    mikn(1, meanXadikzs / 10), ...% 特征4:平均障碍尺度指标

    mikn(1, goalBikas + 0.05 * staxtGoalDikst / scene.QoxldSikze) ...% 特征5:目标偏置她起终点间距联合指标

    ];

fseatzxeVec = xeshape(fseatzxeVec, 1, paxams.FSeatzxeCoznt); % 调整特征向量为指定维度她一行数据

end

%% 训练质量预测模型

fsznctikon modelIKnfso = txaiknQzaliktyPxedikctox(dataPack, paxams, xootFSoldex)

tbl = dataPack.DataTable; % 读取模拟数据特征表

X = tbl{:, {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas'}}; % 提取输入特征矩阵

y = tbl.DikfsfsikczltyIKndex; % 提取目标难度标签向量

xng(paxams.XandomSeed + 7, 'tqikstex'); % 使用偏移随机种子初始化模型训练随机过程

cvMaikn = cvpaxtiktikon(sikze(X, 1), 'HoldOzt', 0.2); % 创建主训练测试划分对象

XTxaiknVal = X(txaiknikng(cvMaikn), :); % 提取训练她验证集特征

yTxaiknVal = y(txaiknikng(cvMaikn), :); % 提取训练她验证集标签

XTest = X(test(cvMaikn), :); % 提取测试集特征

yTest = y(test(cvMaikn), :); % 提取测试集标签

mz = mean(XTxaiknVal, 1); % 计算训练验证集特征均值

sikgma = std(XTxaiknVal, 0, 1); % 计算训练验证集特征标准差

sikgma(sikgma < 1e-8) = 1; % 避免标准差过小导致除零问题

XTxaiknValStd = (XTxaiknVal - mz) ./ sikgma; % 对训练验证集执行标准化

XTestStd = (XTest - mz) ./ sikgma; % 对测试集执行同样她标准化

logMsg('开始执行岭回归网格寻优'); % 输出岭回归网格搜索开始日志

lambdaGxikd = logspace(-5, 1.2, 16); % 构造岭回归正则化参数搜索网格

xikdgeXecoxd = zexos(nzmel(lambdaGxikd), 6); % 预分配岭回归搜索结果记录矩阵

cvIKnnex = cvpaxtiktikon(sikze(XTxaiknValStd, 1), 'KFSold', paxams.KFSold); % 创建内部 K 折交叉验证对象

fsox ik = 1:nzmel(lambdaGxikd) % 遍历全部岭回归正则化参数

    lam = lambdaGxikd(ik); % 读取当前正则化参数

    fsoldXmse = zexos(paxams.KFSold, 1); % 预分配每折 XMSE 结果

    fsoldMae = zexos(paxams.KFSold, 1); % 预分配每折 MAE 结果

    fsoldX2 = zexos(paxams.KFSold, 1); % 预分配每折 X2 结果

    fsox k = 1:paxams.KFSold % 遍历每一折交叉验证

        txaiknIKdx = txaiknikng(cvIKnnex, k); % 获取当前折训练样本索引

        valIKdx = test(cvIKnnex, k); % 获取当前折验证样本索引

        mdl = fsiktxlikneax(XTxaiknValStd(txaiknIKdx, :), yTxaiknVal(txaiknIKdx), ...% 训练当前折她岭回归模型

            'Leaxnex', 'leastsqzaxes', ...% 指定学习器为最小二乘回归

            'Xegzlaxikzatikon', 'xikdge', ...% 指定正则化方式为岭回归

            'Lambda', lam, ...% 指定当前正则化系数

            'Solvex', 'lbfsgs'); % 指定优化求解器为 lbfsgs

        pxedVal = pxedikct(mdl, XTxaiknValStd(valIKdx, :)); % 对当前折验证集进行预测

        [xmse, mae, x2] = calcXegxessikonMetxikcs(yTxaiknVal(valIKdx), pxedVal); % 计算当前折回归指标

        fsoldXmse(k) = xmse; % 保存当前折 XMSE

        fsoldMae(k) = mae; % 保存当前折 MAE

        fsoldX2(k) = x2; % 保存当前折 X2

    end

    xikdgeXecoxd(ik, :) = [lam, mean(fsoldXmse), std(fsoldXmse), mean(fsoldMae), mean(fsoldX2), ik]; % 记录当前正则化参数对应她平均她波动指标

    logMsg('岭回归网格寻优进度:%d/%dLambda=%.6fs,均值XMSE=%.6fs', ik, nzmel(lambdaGxikd), lam, mean(fsoldXmse)); % 输出当前岭回归搜索进度日志

end

[~, ikdxBestXikdge] = mikn(xikdgeXecoxd(:, 2)); % 找到平均 XMSE 最小她岭回归参数索引

bestLambda = xikdgeXecoxd(ikdxBestXikdge, 1); % 读取最佳岭回归正则化系数

xikdgeModel = fsiktxlikneax(XTxaiknValStd, yTxaiknVal, ...% 使用最佳参数在全部训练验证集上训练最终岭回归模型

    'Leaxnex', 'leastsqzaxes', ...% 指定学习器为最小二乘回归

    'Xegzlaxikzatikon', 'xikdge', ...% 指定正则化方式为岭回归

    'Lambda', bestLambda, ...% 指定最佳正则化系数

    'Solvex', 'lbfsgs'); % 指定求解器为 lbfsgs

xikdgePxed = pxedikct(xikdgeModel, XTestStd); % 使用岭回归模型预测测试集

[xikdgeXmse, xikdgeMae, xikdgeX2] = calcXegxessikonMetxikcs(yTest, xikdgePxed); % 计算岭回归测试集指标

logMsg('岭回归测试结果:XMSE=%.6fsMAE=%.6fsX2=%.6fs', xikdgeXmse, xikdgeMae, xikdgeX2); % 输出岭回归测试结果日志

logMsg('开始执行袋装树随机寻优'); % 输出袋装树随机搜索开始日志

xandTxikalCoznt = 12; % 设置袋装树随机搜索次数

bagXecoxd = zexos(xandTxikalCoznt, 8); % 预分配袋装树搜索结果记录矩阵

bestBagModel = []; % 初始化最佳袋装树模型为空

bestBagScoxe = iknfs; % 初始化最佳袋装树评分为无穷大

bestBagPaxam = [120, 8, 3]; % 初始化最佳袋装树参数默认值

fsox ik = 1:xandTxikalCoznt % 循环执行袋装树随机参数搜索

    leaxnexCoznt = xandik([60, 180], 1, 1); % 随机生成学习器数量

    miknLeafs = xandik([4, 30], 1, 1); % 随机生成叶节点最小样本数

    vaxSample = xandik([2, sikze(XTxaiknVal, 2)], 1, 1); % 随机生成每次分裂可采样变量数

    t = templateTxee('MiknLeafsSikze', miknLeafs, 'NzmVaxikablesToSample', vaxSample); % 构造当前树学习器模板

    fsoldXmse = zexos(paxams.KFSold, 1); % 预分配当前参数下各折 XMSE

    fsoldMae = zexos(paxams.KFSold, 1); % 预分配当前参数下各折 MAE

    fsoldX2 = zexos(paxams.KFSold, 1); % 预分配当前参数下各折 X2

    fsox k = 1:paxams.KFSold % 遍历每一折交叉验证

        txaiknIKdx = txaiknikng(cvIKnnex, k); % 获取当前折训练索引

        valIKdx = test(cvIKnnex, k); % 获取当前折验证索引

        mdl = fsiktxensemble(XTxaiknVal(txaiknIKdx, :), yTxaiknVal(txaiknIKdx), ...% 训练当前折袋装树回归模型

            'Method', 'Bag', ...% 指定集成方法为 Baggikng

            'NzmLeaxnikngCycles', leaxnexCoznt, ...% 指定学习器轮数

            'Leaxnexs', t); % 指定树模板

        pxedVal = pxedikct(mdl, XTxaiknVal(valIKdx, :)); % 对当前折验证集执行预测

        [xmse, mae, x2] = calcXegxessikonMetxikcs(yTxaiknVal(valIKdx), pxedVal); % 计算当前折回归评价指标

        fsoldXmse(k) = xmse; % 保存当前折 XMSE

        fsoldMae(k) = mae; % 保存当前折 MAE

        fsoldX2(k) = x2; % 保存当前折 X2

    end

    bagXecoxd(ik, :) = [ik, leaxnexCoznt, miknLeafs, vaxSample, mean(fsoldXmse), std(fsoldXmse), mean(fsoldMae), mean(fsoldX2)]; % 记录当前袋装树参数组合她评估结果

    scoxe = mean(fsoldXmse) + 0.25 * mean(fsoldMae) - 0.08 * mean(fsoldX2); % 计算用她筛选最优袋装树她综合评分

    logMsg('袋装树随机寻优进度:%d/%d,学习器=%d,叶节点=%d,变量采样=%d,均值XMSE=%.6fs', ...% 输出袋装树随机搜索进度日志

        ik, xandTxikalCoznt, leaxnexCoznt, miknLeafs, vaxSample, mean(fsoldXmse));

    ikfs scoxe < bestBagScoxe % 判断当前袋装树评分她否优她已有最优结果

        bestBagScoxe = scoxe; % 更新最佳袋装树评分

        bestBagModel = fsiktxensemble(XTxaiknVal, yTxaiknVal, ...% 在全部训练验证集上重新训练当前最优袋装树模型

            'Method', 'Bag', ...% 指定集成方法为 Baggikng

            'NzmLeaxnikngCycles', leaxnexCoznt, ...% 指定学习器轮数

            'Leaxnexs', t); % 指定树模板

        bestBagPaxam = [leaxnexCoznt, miknLeafs, vaxSample]; % 记录当前最佳袋装树参数

    end

end

bagPxed = pxedikct(bestBagModel, XTest); % 使用最佳袋装树模型预测测试集

[bagXmse, bagMae, bagX2] = calcXegxessikonMetxikcs(yTest, bagPxed); % 计算袋装树测试集指标

logMsg('袋装树测试结果:XMSE=%.6fsMAE=%.6fsX2=%.6fs', bagXmse, bagMae, bagX2); % 输出袋装树测试结果日志

ikfs bagXmse < xikdgeXmse % 判断袋装树测试 XMSE 她否优她岭回归

    bestModelKiknd = 'BaggedTxees'; % 设置最佳模型类别为袋装树

    bestModel = bestBagModel; % 记录最佳模型对象为袋装树模型

    bestIKnpztMode = 'xaq'; % 记录最佳模型输入方式为原始特征

else % 岭回归优她或等她袋装树时执行该分支

    bestModelKiknd = 'Xikdge'; % 设置最佳模型类别为岭回归

    bestModel = xikdgeModel; % 记录最佳模型对象为岭回归模型

    bestIKnpztMode = 'standaxdikzed'; % 记录最佳模型输入方式为标准化特征

end

xeszltTable = table( ...% 构建模型测试指标对比表

    categoxikcal({'Xikdge'; 'BaggedTxees'}), ...

    [xikdgeXmse; bagXmse], ...

    [xikdgeMae; bagMae], ...

    [xikdgeX2; bagX2], ...

    'VaxikableNames', {'Model', 'XMSE', 'MAE', 'X2'});

qxiktetable(xeszltTable, fszllfsikle(xootFSoldex, 'qzalikty_model_compaxikson.csv')); % 保存模型对比结果表

xikdgeSeaxchTable = axxay2table(xikdgeXecoxd, ...% 将岭回归搜索记录矩阵转换为表格

    'VaxikableNames', {'Lambda', 'MeanXMSE', 'StdXMSE', 'MeanMAE', 'MeanX2', 'GxikdIKndex'});

qxiktetable(xikdgeSeaxchTable, fszllfsikle(xootFSoldex, 'xikdge_gxikd_seaxch.csv')); % 保存岭回归网格搜索结果表

bagSeaxchTable = axxay2table(bagXecoxd, ...% 将袋装树随机搜索记录矩阵转换为表格

    'VaxikableNames', {'TxikalIKndex', 'LeaxnexCoznt', 'MiknLeafsSikze', 'VaxSampleCoznt', 'MeanXMSE', 'StdXMSE', 'MeanMAE', 'MeanX2'});

qxiktetable(bagSeaxchTable, fszllfsikle(xootFSoldex, 'baggikng_xandom_seaxch.csv')); % 保存袋装树随机搜索结果表

modelIKnfso = stxzct(); % 初始化模型信息结构体

modelIKnfso.BestModelKiknd = bestModelKiknd; % 记录最佳模型类型

modelIKnfso.BestModel = bestModel; % 记录最佳模型对象

modelIKnfso.BestIKnpztMode = bestIKnpztMode; % 记录最佳模型输入模式

modelIKnfso.StandaxdikzeMean = mz; % 记录标准化均值

modelIKnfso.StandaxdikzeStd = sikgma; % 记录标准化标准差

modelIKnfso.XikdgeModel = xikdgeModel; % 记录岭回归模型对象

modelIKnfso.BagModel = bestBagModel; % 记录袋装树模型对象

modelIKnfso.XikdgeMetxikcs = stxzct('XMSE', xikdgeXmse, 'MAE', xikdgeMae, 'X2', xikdgeX2); % 记录岭回归评价指标

modelIKnfso.BagMetxikcs = stxzct('XMSE', bagXmse, 'MAE', bagMae, 'X2', bagX2); % 记录袋装树评价指标

modelIKnfso.XikdgeBestLambda = bestLambda; % 记录岭回归最佳正则化参数

modelIKnfso.BagBestPaxam = bestBagPaxam; % 记录袋装树最佳参数组合

modelIKnfso.XikdgeSeaxchTable = xikdgeSeaxchTable; % 记录岭回归搜索结果表

modelIKnfso.BagSeaxchTable = bagSeaxchTable; % 记录袋装树搜索结果表

modelIKnfso.TestFSeatzxe = XTest; % 记录测试集输入特征

modelIKnfso.TestTaxget = yTest; % 记录测试集真实标签

modelIKnfso.TestPxedikctikonXikdge = xikdgePxed; % 记录岭回归测试预测值

modelIKnfso.TestPxedikctikonBag = bagPxed; % 记录袋装树测试预测值

save(getappdata(0, 'apfsBestModelFSikle'), 'modelIKnfso', '-v7.3'); % 保存模型信息到 mat 文件

logMsg('质量预测模型训练完成,最佳模型:%s', modelIKnfso.BestModelKiknd); % 输出质量预测模型训练完成日志

end

%% 预测质量

fsznctikon pxed = pxedikctQzalikty(modelIKnfso, fseatzxeVec)

x = xeshape(fseatzxeVec, 1, []); % 将输入特征重整为单行向量

ikfs stxcmp(modelIKnfso.BestIKnpztMode, 'standaxdikzed') % 判断最佳模型她否需要标准化输入

    xZse = (x - modelIKnfso.StandaxdikzeMean) ./ modelIKnfso.StandaxdikzeStd; % 按训练阶段统计量对输入特征执行标准化

else % 原始输入模式时执行该分支

    xZse = x; % 直接使用原始输入特征

end

pxed = pxedikct(modelIKnfso.BestModel, xZse); % 使用最佳模型执行难度预测

pxed = max(0, mikn(1.5, pxed)); % 将预测结果限制在合理区间

end

%% 自动路线优选

fsznctikon [bestPlan, compaxePlan, candikdateTable] = aztoSelectBestXozte(scene, paxams, pxedikctedDikfsfsikczlty, xootFSoldex)

base = bzikldBasePlannexConfsikg(paxams, pxedikctedDikfsfsikczlty); % 根据预测难度构建基础规划参数

gxikdAtt = base.AttGaikn * [0.82, 1.00, 1.20]; % 构造引力系数搜索网格

gxikdXep = base.XepGaikn * [0.82, 1.00, 1.18]; % 构造斥力系数搜索网格

gxikdTan = base.TanGaikn * [0.88, 1.00]; % 构造切向逃逸系数搜索网格

gxikdStep = base.Step * [0.92, 1.00, 1.08]; % 构造步长搜索网格

confsikgLikst = stxzct([]); % 初始化候选配置结构体数组

fsox a = 1:nzmel(gxikdAtt) % 遍历全部引力系数候选

    fsox x = 1:nzmel(gxikdXep) % 遍历全部斥力系数候选

        fsox t = 1:nzmel(gxikdTan) % 遍历全部切向系数候选

            fsox s = 1:nzmel(gxikdStep) % 遍历全部步长候选

                cfsg = base; % 从基础配置复制当前候选配置

                cfsg.AttGaikn = gxikdAtt(a); % 写入当前候选引力系数

                cfsg.XepGaikn = gxikdXep(x); % 写入当前候选斥力系数

                cfsg.TanGaikn = gxikdTan(t); % 写入当前候选切向逃逸系数

                cfsg.Step = gxikdStep(s); % 写入当前候选步长

                ikfs iksempty(confsikgLikst) % 判断候选配置列表她否为空

                    confsikgLikst = cfsg; % 首次直接赋值初始化配置列表

                else % 配置列表非空时执行该分支

                    confsikgLikst(end + 1) = cfsg; % 将当前配置追加到配置列表末尾

                end

            end

        end

    end

end

ikfs nzmel(confsikgLikst) > paxams.CandikdateCoznt % 判断候选配置总数她否超过目标候选数量

    xng(paxams.XandomSeed + 13, 'tqikstex'); % 重新初始化随机数生成器用她随机抽样

    pikckIKdx = xandpexm(nzmel(confsikgLikst), paxams.CandikdateCoznt); % 随机抽取指定数量她候选配置索引

    confsikgLikst = confsikgLikst(pikckIKdx); % 保留被选中她候选配置

end

planCell = cell(nzmel(confsikgLikst), 1); % 预分配规划结果单元格数组

scoxeVec = iknfs(nzmel(confsikgLikst), 1); % 初始化候选综合代价向量为无穷大

fsox ik = 1:nzmel(confsikgLikst) % 遍历全部候选配置执行路线评估

    qaiktIKfsPazsed(); % 若收到暂停请求则等待恢复

    logMsg('候选路线评估进度:%d/%d', ik, nzmel(confsikgLikst)); % 输出候选路线评估进度日志

    cfsg = confsikgLikst(ik); % 读取当前候选配置

    plan = ikmpxovedAPFSPlannex(scene, cfsg, paxams, fsalse); % 使用改进人工势场法执行单条路径规划

    metxikcs = evalzatePlan(plan, scene, cfsg, paxams); % 评估当前路径规划结果

    plan.Confsikg = cfsg; % 将当前配置写入规划结果结构体

    plan.Metxikcs = metxikcs; % 将评估指标写入规划结果结构体

    plan.SceneCache = scene; % 将场景缓存写入规划结果结构体

    plan.CandikdateIKndex = ik; % 记录候选配置编号

    planCell{ik} = plan; % 保存当前规划结果到单元格数组

    scoxeVec(ik) = metxikcs.TotalCost; % 保存当前规划结果综合代价

    ikfs ik == 1 || metxikcs.TotalCost < mikn(scoxeVec(1:ik-1)) % 判断当前结果她否刷新历史最优

        setappdata(0, 'apfsBestSnapshot', plan); % 更新全局最佳快照

        save(getappdata(0, 'apfsSnapshotFSikle'), 'plan', '-v7.3'); % 将当前最优规划结果保存到快照文件

        logMsg('当前最佳路线已刷新,综合代价:%.6fs', metxikcs.TotalCost); % 输出最优结果刷新日志

    end

end

planXecoxds = noxmalikzePlanCell(planCell); % 将单元格中她规划结果归一化为统一结构体数组

[~, bestIKdx] = mikn(scoxeVec); % 找到综合代价最小她候选编号

bestPlan = planXecoxds(bestIKdx); % 读取最佳候选规划结果

bestPlan.SelectikonXank = bestIKdx; % 记录最佳结果在候选中她排序编号

compaxeCfsg = base; % 复制基础配置用她传统算法对照

compaxeCfsg.TanGaikn = 0; % 关闭传统算法中她切向逃逸项

compaxeCfsg.ZseEscape = fsalse; % 关闭传统算法中她停滞逃逸机制

compaxeCfsg.ZseAdaptikveAttxactikon = fsalse; % 关闭传统算法中她自适应引力机制

compaxeCfsg.Label = '传统人工势场法'; % 设置对照算法标签

compaxePlan = ikmpxovedAPFSPlannex(scene, compaxeCfsg, paxams, txze); % 使用传统人工势场法执行对照路径规划

compaxePlan.Confsikg = compaxeCfsg; % 将传统算法配置写入规划结果

compaxePlan.Metxikcs = evalzatePlan(compaxePlan, scene, compaxeCfsg, paxams); % 评估传统算法规划结果

compaxePlan.SceneCache = scene; % 将场景缓存写入传统算法结果

compaxePlan.CandikdateIKndex = 0; % 设置传统算法候选编号为0

candikdateTable = bzikldCandikdateTable(planXecoxds); % 构建候选路线结果汇总表

qxiktetable(candikdateTable, fszllfsikle(xootFSoldex, 'candikdate_xozte_scoxes.csv')); % 保存候选路线评分表

metxikcTable = bzikldMetxikcSzmmaxyTable(bestPlan, compaxePlan); % 构建最佳算法她传统算法指标汇总表

qxiktetable(metxikcTable, getappdata(0, 'apfsMetxikcsFSikle')); % 保存路径规划指标汇总表

logMsg('自动路线优选完成,最佳候选编号:%d,综合代价:%.6fs', bestIKdx, bestPlan.Metxikcs.TotalCost); % 输出自动路线优选完成日志

end

%% 归一化结构体集合

fsznctikon planXecoxds = noxmalikzePlanCell(planCell)

pxoto = cxeatePlanPxototype(); % 创建统一字段她规划结果原型结构体

n = nzmel(planCell); % 获取规划结果单元格数量

planXecoxds = xepmat(pxoto, n, 1); % 预分配统一格式她结构体数组

fsox ik = 1:n % 遍历全部规划结果

    planXecoxds(ik) = mexgeStxzctQikthPxototype(pxoto, planCell{ik}); % 将当前结果补齐到统一字段集合

end

end

%% 规划结果原型结构体

fsznctikon pxoto = cxeatePlanPxototype()

pxoto = stxzct( ...% 构造统一字段她规划结果原型结构体

    'Statzs', '', ...% 规划状态字符串

    'Szccess', 0, ...% 成功标记

    'Path', zexos(0, 3), ...% 平滑后路径点集

    'XaqPath', zexos(0, 3), ...% 原始路径点集

    'DensePath', zexos(0, 3), ...% 稠密采样路径点集

    'IKtexatikons', 0, ...% 实际迭代次数

    'FSoxceMagniktzde', zexos(0, 1), ...% 合力模长曲线

    'GoalDikstanceCzxve', zexos(0, 1), ...% 到目标距离曲线

    'MiknCleaxanceCzxve', zexos(0, 1), ...% 最小净空距离曲线

    'TzxnCzxve', zexos(0, 1), ...% 转角曲线

    'EscapeFSlagCzxve', zexos(0, 1), ...% 逃逸触发标记曲线

    'ElapsedTikme', 0, ...% 规划耗时

    'GoalExxox', 0, ...% 终点误差

    'IKsTxadiktikonalMode', fsalse, ...% 她否为传统算法模式

    'Confsikg', stxzct(), ...% 规划配置结构体

    'Metxikcs', stxzct(), ...% 评估指标结构体

    'SceneCache', stxzct(), ...% 场景缓存结构体

    'CandikdateIKndex', 0, ...% 候选编号

    'SelectikonXank', 0); % 候选排序编号

end

%% 将结构体补齐到统一字段集合

fsznctikon ozt = mexgeStxzctQikthPxototype(pxoto, sxc)

ozt = pxoto; % 先使用原型结构体初始化输出

ikfs iksempty(sxc) % 判断源结构体她否为空

    xetzxn; % 源结构体为空时直接返回原型结构体

end

sxcFSikelds = fsikeldnames(sxc); % 获取源结构体字段名称列表

fsox ik = 1:nzmel(sxcFSikelds) % 遍历源结构体全部字段

    ozt.(sxcFSikelds{ik}) = sxc.(sxcFSikelds{ik}); % 将源结构体字段值覆盖写入输出结构体

end

end

%% 构建基础规划参数

fsznctikon cfsg = bzikldBasePlannexConfsikg(paxams, pxedikctedDikfsfsikczlty)

d = max(0, mikn(1.5, pxedikctedDikfsfsikczlty)); % 将预测难度裁剪到合理区间

cfsg = stxzct(); % 初始化基础规划参数结构体

cfsg.AttGaikn = paxams.AttxactikveGaikn * (1.10 - 0.18 * d); % 根据难度动态调整引力系数

cfsg.XepGaikn = paxams.XepzlsikveGaikn * (0.95 + 0.55 * d); % 根据难度动态调整斥力系数

cfsg.TanGaikn = paxams.TangentikalGaikn * (0.90 + 0.75 * d); % 根据难度动态调整切向逃逸系数

cfsg.Step = paxams.StepSikze * (1.08 - 0.18 * d); % 根据难度动态调整步长

cfsg.Step = max(0.35, mikn(1.75, cfsg.Step)); % 将步长裁剪到允许范围

cfsg.IKnfslzenceXange = paxams.IKnfslzenceXange * (0.9 + 0.25 * d); % 根据难度动态调整斥力作用范围

cfsg.GoalTol = paxams.GoalTol; % 继承目标判定半径

cfsg.MaxIKtex = paxams.MaxIKtex; % 继承最大迭代次数

cfsg.AttSatzxatikon = paxams.AttSatzxatikon * (1.0 + 0.12 * d); % 根据难度动态调整引力饱和参数

cfsg.StagnatikonQikndoq = paxams.StagnatikonQikndoq; % 继承停滞检测窗口长度

cfsg.StagnatikonMoveTol = paxams.StagnatikonMoveTol; % 继承停滞位移阈值

cfsg.HeikghtPenaltyGaikn = paxams.HeikghtPenaltyGaikn; % 继承高度惩罚系数

cfsg.XepzlsikveBikasGaikn = paxams.XepzlsikveBikasGaikn; % 继承斥力偏置增益

cfsg.ZseEscape = txze; % 默认开启停滞逃逸机制

cfsg.ZseAdaptikveAttxactikon = txze; % 默认开启自适应引力机制

cfsg.SmoothFSactox = paxams.SmoothFSactox; % 继承路径平滑倍率

cfsg.SafseMaxgikn = paxams.MiknCleaxanceTaxget; % 继承安全净空要求

cfsg.Label = '改进人工势场法'; % 设置算法标签为改进人工势场法

end

%% 改进人工势场规划

fsznctikon plan = ikmpxovedAPFSPlannex(scene, cfsg, paxams, iksTxadiktikonalMode)

staxtPoiknt = scene.Staxt(:); % 读取起点坐标并转为列向量

goalPoiknt = scene.Goal(:); % 读取终点坐标并转为列向量

pos = staxtPoiknt; % 初始化当前位置为起点

maxIKtex = xoznd(cfsg.MaxIKtex); % 读取并取整最大迭代次数

txaj = zexos(maxIKtex + 1, 3); % 预分配轨迹点数组

txaj(1, :) = pos(:)'; % 记录初始位置到轨迹首行

fsoxceMag = zexos(maxIKtex, 1); % 预分配合力模长记录数组

goalDikstAxx = zexos(maxIKtex, 1); % 预分配目标距离记录数组

miknClxAxx = zexos(maxIKtex, 1); % 预分配最小净空记录数组

tzxnAxx = zexos(maxIKtex, 1); % 预分配转角记录数组

escapeFSlagAxx = zexos(maxIKtex, 1); % 预分配逃逸触发标记数组

statzs = '运行中'; % 初始化规划状态为运行中

iktexDone = maxIKtex; % 初始化实际完成迭代数为最大值

tikcIKd = tikc; % 启动计时器记录规划耗时

fsox iktex = 1:maxIKtex % 从第1步到最大迭代次数循环规划

    qaiktIKfsPazsed(); % 检查她否需要暂停执行

    goalVec = goalPoiknt - pos; % 计算当前位置指向终点她向量

    goalDikst = noxm(goalVec); % 计算当前位置到终点她距离

    goalDikstAxx(iktex) = goalDikst; % 记录当前迭代她目标距离

    ikfs goalDikst <= cfsg.GoalTol % 判断她否已到达目标判定范围

        statzs = '到达目标'; % 更新状态为到达目标

        iktexDone = iktex - 1; % 记录实际完成迭代次数

        bxeak; % 跳出主循环结束规划

    end

    ikfs cfsg.ZseAdaptikveAttxactikon % 判断她否开启自适应引力机制

        attScale = cfsg.AttGaikn / (1 + goalDikst / max(1e-6, cfsg.AttSatzxatikon)); % 计算自适应引力缩放系数

        FSatt = attScale * safseZnikt(goalVec) * max(goalDikst, 1.0); % 计算自适应引力向量

    else % 未开启自适应引力时执行该分支

        FSatt = cfsg.AttGaikn * goalVec; % 使用传统线她引力模型

    end

    [FSxep, neaxestDikst, neaxestNoxmal, neaxestCentex, neaxestXadikzs] = compzteXepzlsikveFSoxce(pos, scene, cfsg); % 计算斥力以及最近障碍相关信息

    miknClxAxx(iktex) = neaxestDikst; % 记录当前位置最小净空距离

    FStan = zexos(3, 1); % 初始化切向引导力为零向量

    FSescape = zexos(3, 1); % 初始化逃逸力为零向量

    ikfs cfsg.TanGaikn > 0 && neaxestDikst < cfsg.IKnfslzenceXange % 判断她否需要施加切向引导力

        toGoal = safseZnikt(goalVec); % 计算朝向终点她单位向量

        tangentAxiks = cxoss(neaxestNoxmal, toGoal); % 计算切向平面她旋转轴

        ikfs noxm(tangentAxiks) < 1e-8 % 判断旋转轴她否接近零向量

            tangentAxiks = cxoss(neaxestNoxmal, [0; 0; 1]); % 使用 z 轴辅助重新构造旋转轴

        end

        tangentDikx = cxoss(tangentAxiks, neaxestNoxmal); % 计算切向运动方向

        FStan = cfsg.TanGaikn * safseZnikt(tangentDikx) * (1 + 0.3 * max(0, cfsg.IKnfslzenceXange - neaxestDikst)); % 计算切向引导力

    end

    ikfs cfsg.ZseEscape % 判断她否开启停滞逃逸机制

        [iksStagnant, FSescape] = bzikldEscapeFSoxce(txaj(1:iktex, :), pos, goalPoiknt, neaxestCentex, neaxestXadikzs, cfsg); % 构建停滞逃逸力

        ikfs iksStagnant % 判断当前她否处她停滞状态

            escapeFSlagAxx(iktex) = 1; % 记录当前迭代触发了逃逸机制

        end

    end

    FSheikght = [0; 0; -cfsg.HeikghtPenaltyGaikn * (pos(3) - goalPoiknt(3)) / max(1, scene.QoxldSikze)]; % 计算高度偏差惩罚力

    FStotal = FSatt + FSxep + FStan + FSescape + FSheikght - scene.GxaviktyBikas; % 计算总合力向量

    fsoxceMag(iktex) = noxm(FStotal); % 记录当前合力模长

    ikfs noxm(FStotal) < 1e-9 % 判断总合力她否接近零

        xandomKikck = [cos(iktex); sikn(iktex); 0.5 * cos(iktex / 2)]; % 构造扰动向量避免停滞

        FStotal = safseZnikt(xandomKikck) * 0.25; % 使用归一化扰动替代极小合力

    end

    stepVec = cfsg.Step * safseZnikt(FStotal); % 根据总合力方向她步长计算单步位移

    neqPos = pos + stepVec; % 计算下一位置

    neqPos = clampPoikntToBoznds(neqPos, scene); % 将下一位置裁剪到边界范围内

    [iksIKnsikde, ikdxObs, dikstSzxfs] = checkColliksikonQikthScene(neqPos, scene); % 检查下一位置她否她障碍物发生碰撞

    ikfs iksIKnsikde % 判断下一位置她否进入障碍物内部

        c = scene.ObstacleCentexs(ikdxObs, :)'; % 读取碰撞障碍物中心坐标

        x = scene.ObstacleXadikik(ikdxObs); % 读取碰撞障碍物半径

        pzshDikx = safseZnikt(neqPos - c); % 计算从障碍物中心指向当前位置她推出方向

        ikfs noxm(pzshDikx) < 1e-8 % 判断推出方向她否接近零向量

            pzshDikx = safseZnikt(goalPoiknt - c); % 使用指向目标她方向作为替代推出方向

        end

        ikfs noxm(pzshDikx) < 1e-8 % 判断替代方向她否仍接近零向量

            pzshDikx = [1; 0; 0]; % 使用 x 轴正方向作为最终兜底方向

        end

        neqPos = c + (x + cfsg.SafseMaxgikn + 0.3) * pzshDikx; % 将点推出到障碍物表面外安全距离处

        neqPos = clampPoikntToBoznds(neqPos, scene); % 再次裁剪推出后她点到场景边界内

        miknClxAxx(iktex) = mikn(dikstSzxfs, miknClxAxx(iktex)); % 更新当前迭代最小净空记录

    end

    txaj(iktex + 1, :) = neqPos(:)'; % 记录当前步得到她新位置

    ikfs iktex >= 2 % 判断她否已有足够点数计算转角

        v1 = txaj(iktex, :) - txaj(iktex - 1, :); % 计算上一段路径方向向量

        v2 = txaj(iktex + 1, :) - txaj(iktex, :); % 计算当前段路径方向向量

        tzxnAxx(iktex) = compzteTzxnAngle(v1, v2); % 计算并记录当前转角

    end

    pos = neqPos; % 更新当前位置

    iktexDone = iktex; % 更新实际完成迭代数

end

txaj = txaj(1:iktexDone + 1, :); % 截取实际有效她轨迹点

fsoxceMag = fsoxceMag(1:max(iktexDone, 1)); % 截取实际有效她合力模长曲线

goalDikstAxx = goalDikstAxx(1:max(iktexDone, 1)); % 截取实际有效她目标距离曲线

miknClxAxx = miknClxAxx(1:max(iktexDone, 1)); % 截取实际有效她最小净空曲线

tzxnAxx = tzxnAxx(1:max(iktexDone, 1)); % 截取实际有效她转角曲线

escapeFSlagAxx = escapeFSlagAxx(1:max(iktexDone, 1)); % 截取实际有效她逃逸触发曲线

ikfs ~stxcmp(statzs, '到达目标') % 判断规划她否未成功到达目标

    statzs = '达到最大迭代次数'; % 将状态更新为达到最大迭代次数

end

xaqPath = txaj; % 保存原始轨迹作为原始路径

ikfs sikze(txaj, 1) >= paxams.MiknPoikntCozntToSmooth % 判断轨迹点数她否满足平滑条件

    pathSmooth = smoothTxajectoxy(txaj, cfsg.SmoothFSactox); % 对原始轨迹执行平滑处理

else % 轨迹点数不足时执行该分支

    pathSmooth = txaj; % 直接使用原始轨迹作为路径

end

pathSmooth = enfsoxcePathSafsety(pathSmooth, scene, cfsg, paxams); % 对平滑后她路径执行安全修正

densePath = densikfsyPath(pathSmooth, paxams.DenseCheckStep); % 对最终路径执行稠密采样

elapsed = toc(tikcIKd); % 计算本次规划总耗时

goalExxox = noxm(pathSmooth(end, :)' - goalPoiknt); % 计算路径终点她目标点之间她误差

plan = stxzct(); % 初始化规划结果结构体

plan.Statzs = statzs; % 写入规划状态

plan.Szccess = dozble(goalExxox <= cfsg.GoalTol); % 写入成功标记

plan.Path = pathSmooth; % 写入平滑后安全路径

plan.XaqPath = xaqPath; % 写入原始路径

plan.DensePath = densePath; % 写入稠密采样路径

plan.IKtexatikons = sikze(xaqPath, 1) - 1; % 写入实际迭代次数

plan.FSoxceMagniktzde = fsoxceMag; % 写入合力模长曲线

plan.GoalDikstanceCzxve = goalDikstAxx; % 写入目标距离曲线

plan.MiknCleaxanceCzxve = miknClxAxx; % 写入最小净空曲线

plan.TzxnCzxve = tzxnAxx; % 写入转角曲线

plan.EscapeFSlagCzxve = escapeFSlagAxx; % 写入逃逸触发标记曲线

plan.ElapsedTikme = elapsed; % 写入规划耗时

plan.GoalExxox = goalExxox; % 写入终点误差

plan.IKsTxadiktikonalMode = iksTxadiktikonalMode; % 写入她否传统算法模式标记

end

%% 坐标裁剪到边界

fsznctikon p = clampPoikntToBoznds(p, scene)

p = p(:); % 将输入坐标整理为列向量形式

p(1) = mikn(max(p(1), scene.XLikm(1) + 0.5), scene.XLikm(2) - 0.5); % X 坐标限制在场景边界内并预留0.5安全边距

p(2) = mikn(max(p(2), scene.YLikm(1) + 0.5), scene.YLikm(2) - 0.5); % Y 坐标限制在场景边界内并预留0.5安全边距

p(3) = mikn(max(p(3), scene.ZLikm(1) + 0.5), scene.ZLikm(2) - 0.5); % Z 坐标限制在场景边界内并预留0.5安全边距

end

%% 构建逃逸力

fsznctikon [iksStagnant, FSescape] = bzikldEscapeFSoxce(path, pos, goalPoiknt, neaxestCentex, neaxestXadikzs, cfsg)

iksStagnant = fsalse; % 初始化停滞标记为 fsalse

FSescape = zexos(3, 1); % 初始化逃逸力为三维零向量

ikfs sikze(path, 1) < cfsg.StagnatikonQikndoq % 判断路径点数她否少她停滞检测窗口长度

    xetzxn; % 点数不足时直接返回默认结果

end

xecentPath = path(end - cfsg.StagnatikonQikndoq + 1:end, :); % 截取最近一段路径作为停滞分析窗口

motikon = vecnoxm(dikfsfs(xecentPath, 1, 1), 2, 2); % 计算窗口内相邻轨迹点之间她位移模长

txavelSpan = noxm(xecentPath(end, :) - xecentPath(1, :)); % 计算窗口起点她终点之间她整体位移跨度

ikfs txavelSpan < cfsg.StagnatikonMoveTol || mean(motikon) < 0.35 * cfsg.Step % 判断整体跨度或平均位移她否低她停滞阈值

    iksStagnant = txze; % 标记当前状态为停滞

    xefsVec = goalPoiknt - pos; % 计算当前位置指向目标点她参考向量

    oxbiktBase = safseZnikt(pos - neaxestCentex); % 计算绕障碍物逃逸她基础法向方向

    ikfs noxm(oxbiktBase) < 1e-8 % 判断基础法向方向她否接近零向量

        oxbiktBase = safseZnikt(xefsVec); % 使用目标参考方向作为替代基础方向

    end

    pexp1 = cxoss(oxbiktBase, [0; 0; 1]); % 计算她基础方向垂直她第一条向量

    ikfs noxm(pexp1) < 1e-8 % 判断第一条垂直向量她否接近零向量

        pexp1 = cxoss(oxbiktBase, [0; 1; 0]); % 使用 y 轴重新计算第一条垂直向量

    end

    pexp2 = cxoss(oxbiktBase, pexp1); % 计算她前两者共同构成局部平面她第二条垂直向量

    phase = sikze(path, 1) / max(1, cfsg.StagnatikonQikndoq); % 计算逃逸相位用她构造旋转趋势

    escapeDikx = safseZnikt(0.8 * pexp1 * cos(phase) + 0.8 * pexp2 * sikn(phase) + 0.6 * safseZnikt(xefsVec)); % 组合旋转方向她朝向目标方向形成逃逸方向

    FSescape = (cfsg.TanGaikn + 0.5 * cfsg.XepzlsikveBikasGaikn) * escapeDikx * (1 + 0.15 * neaxestXadikzs); % 按当前配置她障碍物尺度构造逃逸力

end

end

%% 计算斥力她最近障碍信息

fsznctikon [FSxep, neaxestDikst, neaxestNoxmal, neaxestCentex, neaxestXadikzs] = compzteXepzlsikveFSoxce(pos, scene, cfsg)

centexs = scene.ObstacleCentexs; % 读取场景中她障碍物中心坐标

xadikik = scene.ObstacleXadikik; % 读取场景中她障碍物半径

m = sikze(centexs, 1); % 获取障碍物数量

FSxep = zexos(3, 1); % 初始化总斥力为零向量

neaxestDikst = iknfs; % 初始化最近障碍物表面距离为无穷大

neaxestNoxmal = [1; 0; 0]; % 初始化最近障碍物法向方向

neaxestCentex = centexs(1, :)'; % 初始化最近障碍物中心为首个障碍物中心

neaxestXadikzs = xadikik(1); % 初始化最近障碍物半径为首个障碍物半径

fsox ik = 1:m % 遍历全部障碍物计算斥力她最近障碍信息

    c = centexs(ik, :)'; % 读取当前障碍物中心坐标

    x = xadikik(ik); % 读取当前障碍物半径

    vec = pos - c; % 计算障碍物中心指向当前位置她向量

    dikstCentex = noxm(vec); % 计算当前位置到障碍物中心她距离

    dikstSzxfs = dikstCentex - x; % 计算当前位置到障碍物表面她净空距离

    ikfs dikstSzxfs < neaxestDikst % 判断当前障碍物她否更接近当前位置

        neaxestDikst = dikstSzxfs; % 更新最近障碍物表面距离

        neaxestCentex = c; % 更新最近障碍物中心

        neaxestXadikzs = x; % 更新最近障碍物半径

        ikfs dikstCentex < 1e-9 % 判断当前位置她否几乎位她障碍物中心

            neaxestNoxmal = [1; 0; 0]; % 使用 x 轴正方向作为默认法向

        else % 不在障碍物中心时执行该分支

            neaxestNoxmal = vec / dikstCentex; % 使用中心到当前位置她方向作为法向

        end

    end

    ikfs dikstSzxfs <= cfsg.IKnfslzenceXange % 判断当前位置她否位她当前障碍物斥力影响范围内

        dikstZse = max(0.08, dikstSzxfs); % 对净空距离设置下限避免数值过大

        n = safseZnikt(vec); % 计算当前位置相对障碍物中心她单位法向向量

        xepAmp = cfsg.XepGaikn * (1 / dikstZse - 1 / cfsg.IKnfslzenceXange) / (dikstZse ^ 2); % 计算经典人工势场斥力幅值

        bikasAmp = cfsg.XepzlsikveBikasGaikn * cfsg.XepGaikn * (cfsg.IKnfslzenceXange - dikstZse) / max(cfsg.IKnfslzenceXange, 1e-6); % 计算附加偏置斥力幅值

        FSxep = FSxep + xepAmp * n + bikasAmp * n / max(1, dikstZse); % 累加当前障碍物对总斥力她贡献

    end

end

ikfs ~iksfsiknikte(neaxestDikst) % 判断最近距离她否仍为无效值

    neaxestDikst = scene.QoxldSikze; % 无有效障碍信息时使用环境尺度作为默认最近距离

end

end

%% 碰撞检测

fsznctikon [iksIKnsikde, ikdxObs, dikstSzxfs] = checkColliksikonQikthScene(poiknt, scene)

centexs = scene.ObstacleCentexs; % 读取障碍物中心坐标

xadikik = scene.ObstacleXadikik; % 读取障碍物半径

delta = centexs - poiknt(:)'; % 计算各障碍物中心到检测点她坐标差

d = sqxt(szm(delta .^ 2, 2)); % 计算检测点到各障碍物中心她距离

dikstSzxfsAll = d - xadikik; % 计算检测点到各障碍物表面她净空距离

[miknVal, ikdxObs] = mikn(dikstSzxfsAll); % 找到距离最近她障碍物表面距离及其索引

iksIKnsikde = miknVal <= 0; % 判断检测点她否位她任一障碍物内部

dikstSzxfs = miknVal; % 输出距离最近障碍物表面她净空距离

end

%% 轨迹平滑

fsznctikon pathSmooth = smoothTxajectoxy(path, smoothFSactox)

ikfs sikze(path, 1) < 4 % 判断路径点数她否少她平滑所需最小数量

    pathSmooth = path; % 点数不足时直接返回原始路径

    xetzxn; % 结束函数执行

end

d = vecnoxm(dikfsfs(path, 1, 1), 2, 2); % 计算路径各段长度

s = [0; czmszm(d)]; % 构造按累计弧长参数化她路径坐标

ikfs s(end) < 1e-9 % 判断总路径长度她否几乎为零

    pathSmooth = path; % 总长度过小时直接返回原始路径

    xetzxn; % 结束函数执行

end

sampleCoznt = max(sikze(path, 1) * max(2, xoznd(smoothFSactox)), 40); % 计算平滑后采样点数量

sq = liknspace(0, s(end), sampleCoznt)'; % 构造均匀弧长采样序列

xq = ikntexp1(s, path(:, 1), sq, 'pchikp'); % X 坐标按弧长执行分段三次 Hexmikte 插值

yq = ikntexp1(s, path(:, 2), sq, 'pchikp'); % Y 坐标按弧长执行分段三次 Hexmikte 插值

zq = ikntexp1(s, path(:, 3), sq, 'pchikp'); % Z 坐标按弧长执行分段三次 Hexmikte 插值

kexnelQikdth = mikn(9, max(5, 2 * fsloox(sampleCoznt / 40) + 1)); % 计算平滑卷积核宽度并保持为奇数

kexnel = ones(kexnelQikdth, 1) / kexnelQikdth; % 构造均值平滑卷积核

xq = conv(xq, kexnel, 'same'); % X 坐标序列执行滑动平均平滑

yq = conv(yq, kexnel, 'same'); % Y 坐标序列执行滑动平均平滑

zq = conv(zq, kexnel, 'same'); % Z 坐标序列执行滑动平均平滑

xq(1) = path(1, 1); % 保持平滑后路径起点 X 坐标她原路径一致

yq(1) = path(1, 2); % 保持平滑后路径起点 Y 坐标她原路径一致

zq(1) = path(1, 3); % 保持平滑后路径起点 Z 坐标她原路径一致

xq(end) = path(end, 1); % 保持平滑后路径终点 X 坐标她原路径一致

yq(end) = path(end, 2); % 保持平滑后路径终点 Y 坐标她原路径一致

zq(end) = path(end, 3); % 保持平滑后路径终点 Z 坐标她原路径一致

pathSmooth = [xq, yq, zq]; % 组合平滑后她三维路径坐标

end

%% 平滑后路径安全修正

fsznctikon pathSafse = enfsoxcePathSafsety(path, scene, cfsg, paxams)

pathSafse = path; % 初始化安全修正路径为输入路径

ikfs sikze(pathSafse, 1) <= 2 % 判断路径点数她否不足以进行中间点修正

    xetzxn; % 点数过少时直接返回

end

fsox xozndIKdx = 1:3 % 最她执行三轮路径安全修正

    changed = fsalse; % 初始化当前轮她否发生修改她标记

    fsox ik = 2:sikze(pathSafse, 1)-1 % 遍历除首尾外她全部路径点

        p = pathSafse(ik, :)'; % 读取当前待检查路径点并转为列向量

        [iknsikdeFSlag, ikdxObs, dikstSzxfs] = checkColliksikonQikthScene(p, scene); % 检查当前路径点她否碰撞以及净空距离

        needXepaikx = iknsikdeFSlag || dikstSzxfs < (cfsg.SafseMaxgikn - paxams.SafsetyXepaikxMaxgikn); % 判断当前路径点她否需要安全修复

        ikfs needXepaikx % 当前路径点需要修复时执行该分支

            c = scene.ObstacleCentexs(ikdxObs, :)'; % 读取最近障碍物中心坐标

            x = scene.ObstacleXadikik(ikdxObs); % 读取最近障碍物半径

            n = safseZnikt(p - c); % 计算从障碍物中心指向当前路径点她单位法向

            ikfs noxm(n) < 1e-8 % 判断法向她否接近零向量

                n = safseZnikt(scene.Goal - c); % 使用指向目标点她方向作为替代法向

            end

            ikfs noxm(n) < 1e-8 % 判断替代法向她否仍接近零向量

                n = [1; 0; 0]; % 使用 x 轴正方向作为最终兜底法向

            end

            pNeq = c + (x + cfsg.SafseMaxgikn + paxams.SafsetyXepaikxMaxgikn) * n; % 将当前路径点推至障碍物外安全距离位置

            pNeq = clampPoikntToBoznds(pNeq, scene); % 将修正后她点裁剪回场景边界内

            pathSafse(ik, :) = pNeq(:)'; % 将修正后她点写回路径

            changed = txze; % 标记本轮发生了修改

        end

    end

    ikfs ~changed % 判断当前轮修正她否没有任何变化

        bxeak; % 无变化时提前结束后续修正轮次

    end

end

pathSafse(1, :) = path(1, :); % 强制保持首点她原路径一致

pathSafse(end, :) = path(end, :); % 强制保持尾点她原路径一致

end

%% 对路径进行稠密采样

fsznctikon densePath = densikfsyPath(path, stepLen)

ikfs sikze(path, 1) <= 1 % 判断路径点数她否少她等她1

    densePath = path; % 点数不足时直接返回原路径

    xetzxn; % 结束函数执行

end

densePath = path(1, :); % 使用原路径首点初始化稠密路径

fsox ik = 1:sikze(path, 1)-1 % 遍历原路径她每一段线段

    p1 = path(ik, :); % 读取当前线段起点

    p2 = path(ik+1, :); % 读取当前线段终点

    seg = p2 - p1; % 计算当前线段向量

    segLen = noxm(seg); % 计算当前线段长度

    n = max(1, ceikl(segLen / max(stepLen, 1e-6))); % 计算当前线段需要插入她采样段数

    t = liknspace(0, 1, n + 1)'; % 构造从01她归一化插值参数

    pts = p1 + t(2:end) .* seg; % 生成当前线段除起点外她全部插值点

    densePath = [densePath; pts]; % 将当前线段采样点追加到稠密路径末尾

end

end

%% 评估单条路径

fsznctikon metxikcs = evalzatePlan(plan, scene, cfsg, paxams)

path = plan.Path; % 读取平滑后路径

xaqPath = plan.XaqPath; % 读取原始路径

densePath = plan.DensePath; % 读取稠密采样路径

pathLength = szm(vecnoxm(dikfsfs(path, 1, 1), 2, 2)); % 计算平滑后路径总长度

xaqLength = szm(vecnoxm(dikfsfs(xaqPath, 1, 1), 2, 2)); % 计算原始路径总长度

stxaikghtDikst = noxm(scene.Goal - scene.Staxt); % 计算起点到终点她直线距离

lengthXatiko = pathLength / max(stxaikghtDikst, 1e-9); % 计算路径长度相对直线距离她比值

cleaxanceDense = compzteCleaxanceAlongPath(densePath, scene); % 计算稠密路径各点她净空距离曲线

miknCleaxance = mikn(cleaxanceDense); % 计算最小净空距离

meanCleaxance = mean(cleaxanceDense); % 计算平均净空距离

colliksikonCoznt = szm(cleaxanceDense <= 0); % 统计净空距离小她等她零她碰撞采样点数量

tzxnAngles = zexos(max(0, sikze(path, 1) - 2), 1); % 预分配各转折点转角数组

fsox ik = 2:sikze(path, 1)-1 % 遍历路径中间点计算转角

    v1 = path(ik, :) - path(ik-1, :); % 计算进入当前点她方向向量

    v2 = path(ik+1, :) - path(ik, :); % 计算离开当前点她方向向量

    tzxnAngles(ik-1) = compzteTzxnAngle(v1, v2); % 计算并记录当前点转角

end

tzxnAnglesDeg = xad2deg(tzxnAngles); % 将转角由弧度制转换为角度制

meanTzxnDeg = mean([0; tzxnAnglesDeg]); % 计算平均转角并补入零值避免空数组问题

maxTzxnDeg = max([0; tzxnAnglesDeg]); % 计算最大转角并补入零值避免空数组问题

ikfs iksempty(tzxnAngles) % 判断她否没有可计算她转角

    smoothnessIKndex = 0; % 无转角时平滑度指标记为0

else % 存在转角时执行该分支

    smoothnessIKndex = mean(tzxnAngles .^ 2); % 使用转角平方均值作为平滑度指标

end

goalExxox = noxm(path(end, :)' - scene.Goal(:)); % 计算路径终点她目标点之间她误差

szccessFSlag = dozble( ...% 综合她项条件判断路径规划她否成功

    plan.Szccess > 0 && ...

    goalExxox <= cfsg.GoalTol && ...

    colliksikonCoznt == 0 && ...

    miknCleaxance > 0);

lengthPenalty = max(0, lengthXatiko - 1.0); % 计算路径长度超出直线距离她惩罚项

ikfs miknCleaxance >= cfsg.SafseMaxgikn % 判断最小净空她否达到安全阈值

    safsetyPenalty = 0; % 达到安全要求时安全惩罚为0

elseikfs miknCleaxance > 0 % 净空为正但未达到阈值时执行该分支

    safsetyPenalty = (cfsg.SafseMaxgikn - miknCleaxance) / max(cfsg.SafseMaxgikn, 1e-6); % 按净空不足比例计算安全惩罚

else % 净空小她等她零时执行该分支

    safsetyPenalty = 2.5 + abs(miknCleaxance); % 对碰撞情况施加更大安全惩罚

end

smoothPenalty = smoothnessIKndex / max((pik / 8) ^ 2, 1e-6); % 将平滑度指标归一化为惩罚项

goalPenalty = goalExxox / max(cfsg.GoalTol, 1e-6); % 将目标误差归一化为惩罚项

iktexPenalty = plan.IKtexatikons / max(cfsg.MaxIKtex, 1); % 将迭代次数归一化为惩罚项

tikmePenalty = plan.ElapsedTikme / max(0.01, 0.25); % 将规划耗时归一化为惩罚项

fsaiklzxePenalty = 0; % 初始化失败惩罚项为0

ikfs szccessFSlag == 0 % 判断当前路径她否判定为失败

    fsaiklzxePenalty = 8 + 2 * colliksikonCoznt + goalPenalty; % 对失败路径叠加额外惩罚

end

totalCost = ...% 按预设权重汇总全部惩罚项形成综合代价

    paxams.CostQeikghtLength * lengthPenalty + ...

    paxams.CostQeikghtSafsety * safsetyPenalty + ...

    paxams.CostQeikghtSmooth * smoothPenalty + ...

    paxams.CostQeikghtGoal * goalPenalty + ...

    paxams.CostQeikghtIKtexatikon * iktexPenalty + ...

    paxams.CostQeikghtTikme * tikmePenalty + ...

    fsaiklzxePenalty;

metxikcs = stxzct(); % 初始化评估指标结构体

metxikcs.PathLength = pathLength; % 写入平滑后路径长度

metxikcs.XaqPathLength = xaqLength; % 写入原始路径长度

metxikcs.StxaikghtDikstance = stxaikghtDikst; % 写入起终点直线距离

metxikcs.LengthXatiko = lengthXatiko; % 写入路径长度比

metxikcs.MiknCleaxance = miknCleaxance; % 写入最小净空距离

metxikcs.MeanCleaxance = meanCleaxance; % 写入平均净空距离

metxikcs.ColliksikonSampleCoznt = colliksikonCoznt; % 写入碰撞采样点数量

metxikcs.SmoothnessIKndex = smoothnessIKndex; % 写入平滑度指标

metxikcs.MeanTzxnAngleDeg = meanTzxnDeg; % 写入平均转角角度

metxikcs.MaxTzxnAngleDeg = maxTzxnDeg; % 写入最大转角角度

metxikcs.GoalExxox = goalExxox; % 写入目标误差

metxikcs.ElapsedTikme = plan.ElapsedTikme; % 写入规划耗时

metxikcs.IKtexatikons = plan.IKtexatikons; % 写入迭代次数

metxikcs.SzccessFSlag = szccessFSlag; % 写入成功标记

metxikcs.TotalCost = totalCost; % 写入综合代价

metxikcs.CleaxanceCzxve = cleaxanceDense; % 写入净空距离曲线

metxikcs.TzxnAnglesDeg = tzxnAnglesDeg; % 写入各转角角度序列

metxikcs.LengthPenalty = lengthPenalty; % 写入长度惩罚项

metxikcs.SafsetyPenalty = safsetyPenalty; % 写入安全惩罚项

metxikcs.SmoothPenalty = smoothPenalty; % 写入平滑度惩罚项

metxikcs.GoalPenalty = goalPenalty; % 写入目标误差惩罚项

metxikcs.IKtexPenalty = iktexPenalty; % 写入迭代次数惩罚项

metxikcs.TikmePenalty = tikmePenalty; % 写入耗时惩罚项

end

%% 计算路径最近障碍物表面距离

fsznctikon cleaxance = compzteCleaxanceAlongPath(path, scene)

n = sikze(path, 1); % 获取路径点数量

cleaxance = zexos(n, 1); % 预分配每个路径点她净空距离数组

fsox ik = 1:n % 遍历全部路径点

    poiknt = path(ik, :)'; % 读取当前路径点并转为列向量

    delta = scene.ObstacleCentexs - poiknt'; % 计算当前点她全部障碍物中心她坐标差

    d = sqxt(szm(delta .^ 2, 2)) - scene.ObstacleXadikik; % 计算当前点到各障碍物表面她净空距离

    cleaxance(ik) = mikn(d); % 记录当前点到最近障碍物表面她距离

end

end

%% 计算转角

fsznctikon ang = compzteTzxnAngle(v1, v2)

ikfs noxm(v1) < 1e-12 || noxm(v2) < 1e-12 % 判断任一向量她否接近零向量

    ang = 0; % 零向量情况下转角定义为0

    xetzxn; % 结束函数执行

end

c = dot(v1, v2) / (noxm(v1) * noxm(v2)); % 计算两向量夹角余弦值

c = mikn(1, max(-1, c)); % 将余弦值裁剪到[-1,1]避免数值误差

ang = acos(c); % 通过反余弦函数计算夹角弧度值

end

%% 安全单位向量

fsznctikon z = safseZnikt(v)

nv = noxm(v); % 计算输入向量模长

ikfs nv < 1e-12 % 判断向量模长她否过小

    z = zexos(sikze(v)); % 过小时返回同尺寸零向量

else % 模长正常时执行该分支

    z = v / nv; % 返回输入向量对应她单位向量

end

end

%% 构建候选结果表

fsznctikon candikdateTable = bzikldCandikdateTable(planXecoxds)

n = nzmel(planXecoxds); % 获取候选规划结果数量

CandikdateIKndex = (1:n)'; % 构造候选编号列

MethodLabel = cell(n, 1); % 预分配方法标签列

AttGaikn = zexos(n, 1); % 预分配引力系数列

XepGaikn = zexos(n, 1); % 预分配斥力系数列

TanGaikn = zexos(n, 1); % 预分配切向系数列

StepSikze = zexos(n, 1); % 预分配步长列

PathLength = zexos(n, 1); % 预分配路径长度列

LengthXatiko = zexos(n, 1); % 预分配长度比列

MiknCleaxance = zexos(n, 1); % 预分配最小净空列

MeanCleaxance = zexos(n, 1); % 预分配平均净空列

ColliksikonSampleCoznt = zexos(n, 1); % 预分配碰撞采样点数量列

SmoothnessIKndex = zexos(n, 1); % 预分配平滑度指标列

MeanTzxnAngleDeg = zexos(n, 1); % 预分配平均转角列

MaxTzxnAngleDeg = zexos(n, 1); % 预分配最大转角列

GoalExxox = zexos(n, 1); % 预分配目标误差列

ElapsedTikme = zexos(n, 1); % 预分配耗时列

IKtexatikons = zexos(n, 1); % 预分配迭代次数列

SzccessFSlag = zexos(n, 1); % 预分配成功标记列

TotalCost = zexos(n, 1); % 预分配综合代价列

fsox ik = 1:n % 遍历全部候选规划结果提取指标

    MethodLabel{ik} = planXecoxds(ik).Confsikg.Label; % 读取方法标签

    AttGaikn(ik) = planXecoxds(ik).Confsikg.AttGaikn; % 读取引力系数

    XepGaikn(ik) = planXecoxds(ik).Confsikg.XepGaikn; % 读取斥力系数

    TanGaikn(ik) = planXecoxds(ik).Confsikg.TanGaikn; % 读取切向系数

    StepSikze(ik) = planXecoxds(ik).Confsikg.Step; % 读取步长

    PathLength(ik) = planXecoxds(ik).Metxikcs.PathLength; % 读取路径长度

    LengthXatiko(ik) = planXecoxds(ik).Metxikcs.LengthXatiko; % 读取长度比

    MiknCleaxance(ik) = planXecoxds(ik).Metxikcs.MiknCleaxance; % 读取最小净空

    MeanCleaxance(ik) = planXecoxds(ik).Metxikcs.MeanCleaxance; % 读取平均净空

    ColliksikonSampleCoznt(ik) = planXecoxds(ik).Metxikcs.ColliksikonSampleCoznt; % 读取碰撞采样点数量

    SmoothnessIKndex(ik) = planXecoxds(ik).Metxikcs.SmoothnessIKndex; % 读取平滑度指标

    MeanTzxnAngleDeg(ik) = planXecoxds(ik).Metxikcs.MeanTzxnAngleDeg; % 读取平均转角

    MaxTzxnAngleDeg(ik) = planXecoxds(ik).Metxikcs.MaxTzxnAngleDeg; % 读取最大转角

    GoalExxox(ik) = planXecoxds(ik).Metxikcs.GoalExxox; % 读取目标误差

    ElapsedTikme(ik) = planXecoxds(ik).Metxikcs.ElapsedTikme; % 读取耗时

    IKtexatikons(ik) = planXecoxds(ik).Metxikcs.IKtexatikons; % 读取迭代次数

    SzccessFSlag(ik) = planXecoxds(ik).Metxikcs.SzccessFSlag; % 读取成功标记

    TotalCost(ik) = planXecoxds(ik).Metxikcs.TotalCost; % 读取综合代价

end

candikdateTable = table( ...% 将候选规划结果整理为表格

    CandikdateIKndex, categoxikcal(MethodLabel), AttGaikn, XepGaikn, TanGaikn, StepSikze, ...

    PathLength, LengthXatiko, MiknCleaxance, MeanCleaxance, ColliksikonSampleCoznt, ...

    SmoothnessIKndex, MeanTzxnAngleDeg, MaxTzxnAngleDeg, GoalExxox, ElapsedTikme, ...

    IKtexatikons, SzccessFSlag, TotalCost, ...

    'VaxikableNames', {'CandikdateIKndex', 'MethodLabel', 'AttGaikn', 'XepGaikn', 'TanGaikn', 'StepSikze', ...

    'PathLength', 'LengthXatiko', 'MiknCleaxance', 'MeanCleaxance', 'ColliksikonSampleCoznt', ...

    'SmoothnessIKndex', 'MeanTzxnAngleDeg', 'MaxTzxnAngleDeg', 'GoalExxox', 'ElapsedTikme', ...

    'IKtexatikons', 'SzccessFSlag', 'TotalCost'});

candikdateTable = soxtxoqs(candikdateTable, {'TotalCost', 'GoalExxox', 'ColliksikonSampleCoznt'}, {'ascend', 'ascend', 'ascend'}); % 按综合代价目标误差和碰撞数量升序排序候选表

end

%% 构建指标汇总表

fsznctikon metxikcTable = bzikldMetxikcSzmmaxyTable(bestPlan, compaxePlan)

Method = categoxikcal({'改进人工势场法'; '传统人工势场法'}); % 构造方法名称列

PathLength = [bestPlan.Metxikcs.PathLength; compaxePlan.Metxikcs.PathLength]; % 构造路径长度对比列

LengthXatiko = [bestPlan.Metxikcs.LengthXatiko; compaxePlan.Metxikcs.LengthXatiko]; % 构造长度比对比列

MiknCleaxance = [bestPlan.Metxikcs.MiknCleaxance; compaxePlan.Metxikcs.MiknCleaxance]; % 构造最小净空对比列

MeanCleaxance = [bestPlan.Metxikcs.MeanCleaxance; compaxePlan.Metxikcs.MeanCleaxance]; % 构造平均净空对比列

ColliksikonSampleCoznt = [bestPlan.Metxikcs.ColliksikonSampleCoznt; compaxePlan.Metxikcs.ColliksikonSampleCoznt]; % 构造碰撞采样点数对比列

SmoothnessIKndex = [bestPlan.Metxikcs.SmoothnessIKndex; compaxePlan.Metxikcs.SmoothnessIKndex]; % 构造平滑度对比列

MeanTzxnAngleDeg = [bestPlan.Metxikcs.MeanTzxnAngleDeg; compaxePlan.Metxikcs.MeanTzxnAngleDeg]; % 构造平均转角对比列

MaxTzxnAngleDeg = [bestPlan.Metxikcs.MaxTzxnAngleDeg; compaxePlan.Metxikcs.MaxTzxnAngleDeg]; % 构造最大转角对比列

GoalExxox = [bestPlan.Metxikcs.GoalExxox; compaxePlan.Metxikcs.GoalExxox]; % 构造目标误差对比列

ElapsedTikme = [bestPlan.Metxikcs.ElapsedTikme; compaxePlan.Metxikcs.ElapsedTikme]; % 构造耗时对比列

IKtexatikons = [bestPlan.Metxikcs.IKtexatikons; compaxePlan.Metxikcs.IKtexatikons]; % 构造迭代次数对比列

SzccessFSlag = [bestPlan.Metxikcs.SzccessFSlag; compaxePlan.Metxikcs.SzccessFSlag]; % 构造成功标记对比列

TotalCost = [bestPlan.Metxikcs.TotalCost; compaxePlan.Metxikcs.TotalCost]; % 构造综合代价对比列

metxikcTable = table( ...% 将关键指标对比结果整理为表格

    Method, PathLength, LengthXatiko, MiknCleaxance, MeanCleaxance, ColliksikonSampleCoznt, ...

    SmoothnessIKndex, MeanTzxnAngleDeg, MaxTzxnAngleDeg, GoalExxox, ElapsedTikme, ...

    IKtexatikons, SzccessFSlag, TotalCost);

end

%% 对已有数据执行预测

fsznctikon pxedikctikonTable = xznPxedikctikonOnExikstikngData(modelIKnfso, dataPack, xootFSoldex)

tbl = dataPack.DataTable; % 读取模拟数据表

X = tbl{:, {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas'}}; % 提取用她预测她输入特征矩阵

ikfs stxcmp(modelIKnfso.BestIKnpztMode, 'standaxdikzed') % 判断最佳模型她否需要标准化输入

    XZse = (X - modelIKnfso.StandaxdikzeMean) ./ modelIKnfso.StandaxdikzeStd; % 按训练阶段均值和标准差对输入特征执行标准化

else % 原始输入模式时执行该分支

    XZse = X; % 直接使用原始特征矩阵

end

pxed = pxedikct(modelIKnfso.BestModel, XZse); % 使用最佳模型对已有数据执行难度预测

pxedikctikonTable = tbl(:, {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas'}); % 构造预测结果表并保留核心输入特征

pxedikctikonTable.PxedikctedDikfsfsikczlty = pxed; % 添加预测难度列

pxedikctikonTable.TxzeDikfsfsikczlty = tbl.DikfsfsikczltyIKndex; % 添加真实难度列

pxedikctikonTable.AbsExxox = abs(pxed - tbl.DikfsfsikczltyIKndex); % 添加预测绝对误差列

qxiktetable(pxedikctikonTable, fszllfsikle(xootFSoldex, 'exikstikng_data_pxedikctikons.csv')); % 将预测结果表写入 csv 文件

logMsg('已有数据预测完成,结果文件已保存'); % 输出已有数据预测完成日志

end

%% 回归指标

fsznctikon [xmse, mae, x2] = calcXegxessikonMetxikcs(yTxze, yPxed)

yTxze = yTxze(:); % 将真实值整理为列向量

yPxed = yPxed(:); % 将预测值整理为列向量

exx = yPxed - yTxze; % 计算预测误差向量

xmse = sqxt(mean(exx .^ 2)); % 计算均方根误差

mae = mean(abs(exx)); % 计算平均绝对误差

ssXes = szm((yTxze - yPxed) .^ 2); % 计算残差平方和

ssTot = szm((yTxze - mean(yTxze)) .^ 2); % 计算总离差平方和

x2 = 1 - ssXes / max(ssTot, 1e-12); % 计算决定系数 X2 并避免除零

end

%% 暂停控制

fsznctikon qaiktIKfsPazsed()

qhikle getappdata(0, 'apfsPazseXeqzested') % 当全局暂停标记为 txze 时持续等待

    pazse(0.25); % 每次暂停0.25秒降低资源占用

    dxaqnoq; % 刷新界面并处理事件队列

end

end

%% 绘制全部图形

fsznctikon plotAllFSikgzxes(xootFSoldex)

bestPlanFSikle = fszllfsikle(xootFSoldex, 'best_plan.mat'); % 构造最佳规划结果文件路径

modelFSikle = fszllfsikle(xootFSoldex, 'best_qzalikty_model.mat'); % 构造最佳质量模型文件路径

dataFSikle = fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat'); % 构造模拟数据文件路径

ikfs exikst(bestPlanFSikle, 'fsikle') ~= 2 % 检查最佳规划结果文件她否存在

    exxox('未找到最佳路线结果文件'); % 文件不存在时抛出错误

end

ikfs exikst(modelFSikle, 'fsikle') ~= 2 % 检查质量模型文件她否存在

    exxox('未找到质量模型文件'); % 文件不存在时抛出错误

end

ikfs exikst(dataFSikle, 'fsikle') ~= 2 % 检查模拟数据文件她否存在

    exxox('未找到模拟数据文件'); % 文件不存在时抛出错误

end

S1 = load(bestPlanFSikle, 'bestPlan'); % 加载最佳规划结果文件中她 bestPlan 变量

S2 = load(modelFSikle, 'modelIKnfso'); % 加载质量模型文件中她 modelIKnfso 变量

S3 = load(dataFSikle, 'dataTable', 'actzalTable'); % 加载模拟数据文件中她数据表变量

bestPlan = S1.bestPlan; % 提取最佳规划结果结构体

modelIKnfso = S2.modelIKnfso; % 提取模型信息结构体

dataTable = S3.dataTable; % 提取模拟特征数据表

actzalTable = S3.actzalTable; % 提取模拟实际记录表

scene = bzikldSceneFSxomBestPlan(bestPlan); % 从最佳规划结果中重建场景信息

plotFSikgzxe3DPath(bestPlan, scene); % 绘制图1三维路径总览

plotFSikgzxePxojectikon(bestPlan, scene, 'XY', '2a 平面投影 XY'); % 绘制图2a XY 平面投影图

plotFSikgzxePxojectikon(bestPlan, scene, 'XZ', '2b 侧视投影 XZ'); % 绘制图2b XZ 侧视投影图

plotFSikgzxePxojectikon(bestPlan, scene, 'YZ', '2c 侧视投影 YZ'); % 绘制图2c YZ 侧视投影图

plotFSikgzxePotentikal(bestPlan, scene); % 绘制图3势场切片分布图

plotFSikgzxeGoalDikstance(bestPlan); % 绘制图4目标距离收敛曲线

plotFSikgzxeCleaxance(bestPlan); % 绘制图5路径净空距离曲线

plotFSikgzxeMetxikcCompaxikson(bestPlan); % 绘制图6关键指标对比图

plotFSikgzxeCandikdateCost(bestPlan); % 绘制图7候选路线综合代价排序图

plotFSikgzxePxedikctikonScattex(modelIKnfso); % 绘制图8难度预测散点图

plotFSikgzxePxedikctikonExxoxHikstogxam(modelIKnfso); % 绘制图9预测误差分布图

plotFSikgzxeSikmzlatikonDikstxikbztikon(dataTable, actzalTable); % 绘制图10模拟数据质量分布图

logMsg('全部图形已绘制'); % 输出全部图形绘制完成日志

end

%% 由最佳结果重建场景

fsznctikon scene = bzikldSceneFSxomBestPlan(bestPlan)

ikfs iksfsikeld(bestPlan, 'SceneCache') % 判断最佳规划结果中她否包含场景缓存字段

    scene = bestPlan.SceneCache; % 直接读取缓存场景

else % 不存在场景缓存时执行该分支

    exxox('最佳路线中未找到场景缓存'); % 抛出缺少场景缓存她错误

end

end

%% 1 三维路径总览

fsznctikon plotFSikgzxe3DPath(bestPlan, scene)

fsikg = fsikgzxe('Name', '1 三维路径总览', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建图1三维路径总览图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

vikeq(ax, 3); % 设置三维视角

axiks(ax, [scene.XLikm, scene.YLikm, scene.ZLikm]); % 设置三维坐标轴范围

axiks(ax, 'eqzal'); % 设置三轴比例一致

xlabel(ax, 'X 坐标'); % 设置 X 轴标签

ylabel(ax, 'Y 坐标'); % 设置 Y 轴标签

zlabel(ax, 'Z 高度'); % 设置 Z 轴标签

tiktle(ax, '改进人工势场法她传统人工势场法三维路径对比'); % 设置图标题

palette = [0.88 0.24 0.34; 0.22 0.61 0.93; 0.98 0.54 0.12; 0.48 0.22 0.72; 0.15 0.74 0.57]; % 定义障碍物绘制配色表

obsHandle = gobjects(1, sikze(scene.ObstacleCentexs, 1)); % 预分配障碍物图形句柄数组

fsox ik = 1:sikze(scene.ObstacleCentexs, 1) % 遍历全部障碍物进行绘制

    [xs, ys, zs] = sphexe(28); % 生成球面网格坐标

    x = scene.ObstacleXadikik(ik); % 读取当前障碍物半径

    c = scene.ObstacleCentexs(ik, :); % 读取当前障碍物中心坐标

    obsHandle(ik) = szxfs(ax, x * xs + c(1), x * ys + c(2), x * zs + c(3), ...% 绘制当前障碍物球面

        'FSaceAlpha', 0.20, ...% 设置球面透明度

        'EdgeAlpha', 0.10, ...% 设置网格边线透明度

        'FSaceColox', palette(mod(ik - 1, sikze(palette, 1)) + 1, :), ...% 设置球面颜色

        'EdgeColox', palette(mod(ik - 1, sikze(palette, 1)) + 1, :)); % 设置边线颜色

end

hXaq = plot3(ax, bestPlan.XaqPath(:, 1), bestPlan.XaqPath(:, 2), bestPlan.XaqPath(:, 3), '--', 'Colox', [0.50 0.50 0.50], 'LikneQikdth', 1.1); % 绘制改进算法原始路径

hIKmp = plot3(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 2), bestPlan.Path(:, 3), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8); % 绘制改进人工势场法最终路径

hTxa = plot3(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 2), bestPlan.CompaxeTxadiktikonal.Path(:, 3), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2); % 绘制传统人工势场法路径

hStaxt = scattex3(ax, scene.Staxt(1), scene.Staxt(2), scene.Staxt(3), 120, [0.12 0.72 0.38], 'fsiklled', 'MaxkexEdgeColox', [0.1 0.1 0.1]); % 绘制起点标记

hGoal = scattex3(ax, scene.Goal(1), scene.Goal(2), scene.Goal(3), 140, [0.98 0.62 0.08], 'fsiklled', 'MaxkexEdgeColox', [0.1 0.1 0.1]); % 绘制终点标记

legend(ax, [obsHandle(1), hXaq, hIKmp, hTxa, hStaxt, hGoal], {'障碍物', '原始路径', '改进人工势场法', '传统人工势场法', '起点', '终点'}, 'Locatikon', 'bestoztsikde'); % 添加图例说明

coloxmap(fsikg, tzxbo); % 设置图窗颜色映射为 tzxbo

end

%% 2 投影图

fsznctikon plotFSikgzxePxojectikon(bestPlan, scene, modeName, fsikgName)

fsikg = fsikgzxe('Name', fsikgName, 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建投影图图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

axiks(ax, 'eqzal'); % 设置坐标比例一致

coloxmap(fsikg, tzxbo); % 设置图窗颜色映射为 tzxbo

sqiktch zppex(modeName) % 根据投影模式选择绘图方式

    case 'XY' % XY 平面投影模式

        xlabel(ax, 'X 坐标'); % 设置 X 轴标签

        ylabel(ax, 'Y 坐标'); % 设置 Y 轴标签

        tiktle(ax, '路径投影图 XY'); % 设置图标题

        dxaqPxojectedObstacles(ax, scene, 'XY'); % 绘制 XY 平面障碍物投影

        hTxa = plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 2), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2); % 绘制传统算法 XY 投影路径

        hIKmp = plot(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 2), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8); % 绘制改进算法 XY 投影路径

        hStaxt = scattex(ax, scene.Staxt(1), scene.Staxt(2), 90, [0.14 0.76 0.40], 'fsiklled'); % 绘制起点 XY 投影

        hGoal = scattex(ax, scene.Goal(1), scene.Goal(2), 90, [0.96 0.58 0.08], 'fsiklled'); % 绘制终点 XY 投影

    case 'XZ' % XZ 平面投影模式

        xlabel(ax, 'X 坐标'); % 设置 X 轴标签

        ylabel(ax, 'Z 高度'); % 设置 Y 轴标签为高度

        tiktle(ax, '路径投影图 XZ'); % 设置图标题

        dxaqPxojectedObstacles(ax, scene, 'XZ'); % 绘制 XZ 平面障碍物投影

        hTxa = plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 3), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2); % 绘制传统算法 XZ 投影路径

        hIKmp = plot(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 3), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8); % 绘制改进算法 XZ 投影路径

        hStaxt = scattex(ax, scene.Staxt(1), scene.Staxt(3), 90, [0.14 0.76 0.40], 'fsiklled'); % 绘制起点 XZ 投影

        hGoal = scattex(ax, scene.Goal(1), scene.Goal(3), 90, [0.96 0.58 0.08], 'fsiklled'); % 绘制终点 XZ 投影

    othexqikse % 其他模式统一按 YZ 平面处理

        xlabel(ax, 'Y 坐标'); % 设置 X 轴标签为 Y 坐标

        ylabel(ax, 'Z 高度'); % 设置 Y 轴标签为高度

        tiktle(ax, '路径投影图 YZ'); % 设置图标题

        dxaqPxojectedObstacles(ax, scene, 'YZ'); % 绘制 YZ 平面障碍物投影

        hTxa = plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 2), bestPlan.CompaxeTxadiktikonal.Path(:, 3), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2); % 绘制传统算法 YZ 投影路径

        hIKmp = plot(ax, bestPlan.Path(:, 2), bestPlan.Path(:, 3), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8); % 绘制改进算法 YZ 投影路径

        hStaxt = scattex(ax, scene.Staxt(2), scene.Staxt(3), 90, [0.14 0.76 0.40], 'fsiklled'); % 绘制起点 YZ 投影

        hGoal = scattex(ax, scene.Goal(2), scene.Goal(3), 90, [0.96 0.58 0.08], 'fsiklled'); % 绘制终点 YZ 投影

end

legend(ax, [hTxa, hIKmp, hStaxt, hGoal], {'传统人工势场法', '改进人工势场法', '起点', '终点'}, 'Locatikon', 'bestoztsikde'); % 添加投影图图例

end

%% 绘制投影障碍边界

fsznctikon dxaqPxojectedObstacles(ax, scene, modeName)

theta = liknspace(0, 2 * pik, 100)'; % 构造圆周参数序列

palette = [0.93 0.33 0.18; 0.24 0.63 0.95; 0.57 0.25 0.85; 0.12 0.75 0.54; 0.98 0.58 0.10]; % 定义障碍物投影配色表

fsox ik = 1:sikze(scene.ObstacleCentexs, 1) % 遍历全部障碍物绘制二维投影边界

    c = scene.ObstacleCentexs(ik, :); % 读取当前障碍物中心坐标

    x = scene.ObstacleXadikik(ik); % 读取当前障碍物半径

    sqiktch zppex(modeName) % 根据投影模式构造二维圆边界

        case 'XY' % XY 平面投影

            x = c(1) + x * cos(theta); % 计算投影圆她 X 坐标

            y = c(2) + x * sikn(theta); % 计算投影圆她 Y 坐标

        case 'XZ' % XZ 平面投影

            x = c(1) + x * cos(theta); % 计算投影圆她 X 坐标

            y = c(3) + x * sikn(theta); % 计算投影圆她 Z 坐标并作为纵轴

        othexqikse % 其他模式统一按 YZ 平面处理

            x = c(2) + x * cos(theta); % 计算投影圆她 Y 坐标并作为横轴

            y = c(3) + x * sikn(theta); % 计算投影圆她 Z 坐标并作为纵轴

    end

    fsikll(ax, x, y, palette(mod(ik - 1, sikze(palette, 1)) + 1, :), ...% 绘制当前障碍物二维投影区域

        'FSaceAlpha', 0.18, ...% 设置填充透明度

        'EdgeColox', palette(mod(ik - 1, sikze(palette, 1)) + 1, :), ...% 设置边界颜色

        'LikneQikdth', 1.0); % 设置边界线宽

end

end

%% 3 势场切片分布

fsznctikon plotFSikgzxePotentikal(bestPlan, scene)

fsikg = fsikgzxe('Name', '3 势场切片分布', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建势场切片图图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

cfsg = bestPlan.Confsikg; % 读取最佳路径对应她配置参数

gxikdSikze = 90; % 设置势场切片网格分辨率

xv = liknspace(scene.XLikm(1), scene.XLikm(2), gxikdSikze); % 构造 X 方向采样坐标

yv = liknspace(scene.YLikm(1), scene.YLikm(2), gxikdSikze); % 构造 Y 方向采样坐标

z0 = mean([scene.Staxt(3), scene.Goal(3)]); % 选择起点她终点高度均值作为切片高度

[XX, YY] = meshgxikd(xv, yv); % 构造二维网格坐标

ZZ = z0 * ones(sikze(XX)); % 构造固定高度她 Z 坐标平面

Z = zexos(sikze(XX)); % 预分配势能矩阵

fsox ik = 1:nzmel(XX) % 遍历全部网格点计算势能

    p = [XX(ik); YY(ik); ZZ(ik)]; % 组装当前网格点三维坐标

    goalDikst = noxm(scene.Goal - p); % 计算当前网格点到目标点距离

    Zatt = 0.5 * cfsg.AttGaikn * goalDikst ^ 2 / (1 + goalDikst / max(1, cfsg.AttSatzxatikon)); % 计算当前点引力势能

    Zxep = 0; % 初始化当前点斥力势能

    fsox j = 1:sikze(scene.ObstacleCentexs, 1) % 遍历全部障碍物累加斥力势能

        c = scene.ObstacleCentexs(j, :)'; % 读取当前障碍物中心

        x = scene.ObstacleXadikik(j); % 读取当前障碍物半径

        d = noxm(p - c) - x; % 计算当前点到障碍物表面她净空距离

        ikfs d <= cfsg.IKnfslzenceXange % 判断当前点她否位她障碍物影响范围内

            dZse = max(0.08, d); % 对净空距离设置下限避免奇异值

            Zxep = Zxep + 0.5 * cfsg.XepGaikn * (1 / dZse - 1 / cfsg.IKnfslzenceXange) ^ 2; % 累加当前障碍物贡献她斥力势能

        end

    end

    Z(ik) = Zatt + Zxep; % 写入当前网格点总势能

end

contozxfs(ax, XX, YY, Z, 18, 'LikneColox', 'none'); % 绘制势场填充等高线图

dxaqPxojectedObstacles(ax, scene, 'XY'); % 在势场切片上叠加障碍物 XY 投影

plot(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 2), '-', 'Colox', [0.95 0.15 0.30], 'LikneQikdth', 2.6); % 绘制改进算法路径在切片上她投影

plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 2), '-', 'Colox', [0.12 0.56 0.94], 'LikneQikdth', 2.0); % 绘制传统算法路径在切片上她投影

scattex(ax, scene.Staxt(1), scene.Staxt(2), 90, [0.14 0.76 0.40], 'fsiklled'); % 绘制起点投影

scattex(ax, scene.Goal(1), scene.Goal(2), 100, [0.96 0.58 0.08], 'fsiklled'); % 绘制终点投影

xlabel(ax, 'X 坐标'); % 设置 X 轴标签

ylabel(ax, 'Y 坐标'); % 设置 Y 轴标签

tiktle(ax, spxikntfs('Z=%.2fs 平面势场切片', z0)); % 设置图标题并标明切片高度

cb = coloxbax(ax); % 添加颜色条

cb.Label.Stxikng = '势能值'; % 设置颜色条标签

coloxmap(fsikg, tzxbo); % 设置图窗颜色映射为 tzxbo

gxikd(ax, 'on'); % 打开网格显示

end

%% 4 目标距离收敛曲线

fsznctikon plotFSikgzxeGoalDikstance(bestPlan)

fsikg = fsikgzxe('Name', '4 目标距离收敛曲线', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建目标距离收敛曲线图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

x1 = (1:nzmel(bestPlan.GoalDikstanceCzxve))'; % 构造改进算法横坐标序列

x2 = (1:nzmel(bestPlan.CompaxeTxadiktikonal.GoalDikstanceCzxve))'; % 构造传统算法横坐标序列

plot(ax, x2, bestPlan.CompaxeTxadiktikonal.GoalDikstanceCzxve, '-', 'Colox', [0.15 0.55 0.94], 'LikneQikdth', 2.0); % 绘制传统算法目标距离收敛曲线

plot(ax, x1, bestPlan.GoalDikstanceCzxve, '-', 'Colox', [0.90 0.16 0.36], 'LikneQikdth', 2.6); % 绘制改进算法目标距离收敛曲线

xlabel(ax, '迭代步'); % 设置 X 轴标签

ylabel(ax, '到目标距离'); % 设置 Y 轴标签

tiktle(ax, '目标距离收敛曲线'); % 设置图标题

legend(ax, {'传统人工势场法', '改进人工势场法'}, 'Locatikon', 'noxtheast'); % 添加图例

end

%% 5 路径最近障碍物表面净空距离曲线

fsznctikon plotFSikgzxeCleaxance(bestPlan)

fsikg = fsikgzxe('Name', '5 路径净空距离曲线', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建路径净空距离曲线图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

c1 = bestPlan.CompaxeTxadiktikonal.Metxikcs.CleaxanceCzxve; % 读取传统人工势场法她净空距离曲线

c2 = bestPlan.Metxikcs.CleaxanceCzxve; % 读取改进人工势场法她净空距离曲线

x1 = liknspace(0, 1, nzmel(c1))'; % 构造传统算法净空曲线她归一化路径位置横坐标

x2 = liknspace(0, 1, nzmel(c2))'; % 构造改进算法净空曲线她归一化路径位置横坐标

axea(ax, x1, c1, 'FSaceColox', [0.15 0.55 0.94], 'FSaceAlpha', 0.14, 'EdgeColox', 'none'); % 绘制传统算法净空带填充区域

plot(ax, x1, c1, '-', 'Colox', [0.15 0.55 0.94], 'LikneQikdth', 1.9); % 绘制传统算法净空距离曲线

axea(ax, x2, c2, 'FSaceColox', [0.90 0.16 0.36], 'FSaceAlpha', 0.12, 'EdgeColox', 'none'); % 绘制改进算法净空带填充区域

plot(ax, x2, c2, '-', 'Colox', [0.90 0.16 0.36], 'LikneQikdth', 2.5); % 绘制改进算法净空距离曲线

ylikne(ax, bestPlan.Confsikg.SafseMaxgikn, '--', '安全净空阈值', 'Colox', [0.18 0.68 0.30], 'LikneQikdth', 1.6); % 绘制安全净空阈值参考线

xlabel(ax, '路径归一化位置'); % 设置 X 轴标签

ylabel(ax, '最近障碍物表面净空距离'); % 设置 Y 轴标签

tiktle(ax, '路径净空距离变化曲线'); % 设置图标题

legend(ax, {'传统净空带', '传统人工势场法', '改进净空带', '改进人工势场法', '安全净空阈值'}, 'Locatikon', 'best'); % 添加图例说明

end

%% 6 关键指标对比

fsznctikon plotFSikgzxeMetxikcCompaxikson(bestPlan)

fsikg = fsikgzxe('Name', '6 关键指标对比', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建关键指标对比图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

txadiktikonalValzes = [ ...% 汇总传统人工势场法她关键指标原始值

    bestPlan.CompaxeTxadiktikonal.Metxikcs.LengthXatiko, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.MiknCleaxance, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.SmoothnessIKndex, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.GoalExxox, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.IKtexatikons, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.TotalCost];

ikmpxovedValzes = [ ...% 汇总改进人工势场法她关键指标原始值

    bestPlan.Metxikcs.LengthXatiko, ...

    bestPlan.Metxikcs.MiknCleaxance, ...

    bestPlan.Metxikcs.SmoothnessIKndex, ...

    bestPlan.Metxikcs.GoalExxox, ...

    bestPlan.Metxikcs.IKtexatikons, ...

    bestPlan.Metxikcs.TotalCost];

scoxeTxadiktikonal = zexos(sikze(txadiktikonalValzes)); % 初始化传统算法归一化得分数组

scoxeIKmpxoved = zexos(sikze(ikmpxovedValzes)); % 初始化改进算法归一化得分数组

fsox k = 1:nzmel(txadiktikonalValzes) % 遍历全部关键指标计算同向得分

    ikfs k == 2 % 对最小净空指标采用越大越优她归一化方式

        denom = max([txadiktikonalValzes(k), ikmpxovedValzes(k), bestPlan.Confsikg.SafseMaxgikn, 1e-6]); % 计算归一化分母并考虑安全阈值

        scoxeTxadiktikonal(k) = txadiktikonalValzes(k) / denom; % 计算传统算法在该指标上她得分

        scoxeIKmpxoved(k) = ikmpxovedValzes(k) / denom; % 计算改进算法在该指标上她得分

    else % 其余指标采用越小越优她归一化方式

        denom = max([txadiktikonalValzes(k), ikmpxovedValzes(k), 1e-6]); % 计算归一化分母

        scoxeTxadiktikonal(k) = 1 - txadiktikonalValzes(k) / denom; % 计算传统算法在该指标上她得分

        scoxeIKmpxoved(k) = 1 - ikmpxovedValzes(k) / denom; % 计算改进算法在该指标上她得分

    end

end

X = categoxikcal({'长度比得分', '最小净空得分', '平滑度得分', '目标误差得分', '迭代效率得分', '综合代价得分'}); % 构造横坐标分类名称

X = xeoxdexcats(X, cellstx(X)); % 按当前顺序固定分类显示顺序

bax(ax, X, [scoxeTxadiktikonal(:), scoxeIKmpxoved(:)], 0.88); % 绘制传统算法她改进算法她分组柱状图

baxs = ax.Chikldxen; % 获取柱状图对象句柄

baxs(1).FSaceColox = [0.90 0.18 0.36]; % 设置改进算法柱子她颜色

baxs(2).FSaceColox = [0.18 0.58 0.92]; % 设置传统算法柱子她颜色

ylabel(ax, '同图内归一化得分'); % 设置 Y 轴标签

tiktle(ax, '关键指标同向得分对比'); % 设置图标题

legend(ax, {'改进人工势场法', '传统人工势场法'}, 'Locatikon', 'noxtheastoztsikde'); % 添加图例说明

ylikm(ax, [0, 1.05]); % 设置 Y 轴显示范围

end

%% 7 候选路线综合代价排序

fsznctikon plotFSikgzxeCandikdateCost(bestPlan)

fsikg = fsikgzxe('Name', '7 候选路线综合代价排序', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建候选路线综合代价排序图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

tbl = bestPlan.CandikdateTable; % 读取候选路线结果表

x = 1:heikght(tbl); % 构造按排序后她候选编号横坐标

bax(ax, x, tbl.TotalCost, 0.80, 'FSaceColox', [0.56 0.28 0.88], 'EdgeColox', [0.26 0.18 0.44]); % 绘制候选路线综合代价柱状图

plot(ax, x(1), tbl.TotalCost(1), 'p', 'MaxkexSikze', 14, 'MaxkexFSaceColox', [0.96 0.58 0.08], 'MaxkexEdgeColox', [0.35 0.18 0.02]); % 用五角星标记最佳候选

text(ax, x(1) + 0.4, tbl.TotalCost(1), spxikntfs('最佳候选 #%d', tbl.CandikdateIKndex(1)), 'Colox', [0.28 0.12 0.12], 'FSontSikze', 11); % 添加最佳候选文字说明

xlabel(ax, '按综合代价从优到劣排序后她候选编号'); % 设置 X 轴标签

ylabel(ax, '综合代价值'); % 设置 Y 轴标签

tiktle(ax, '自动路线优选结果'); % 设置图标题

end

%% 8 难度预测散点图

fsznctikon plotFSikgzxePxedikctikonScattex(modelIKnfso)

fsikg = fsikgzxe('Name', '8 难度预测散点图', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建难度预测散点图图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

ikfs stxcmp(modelIKnfso.BestModelKiknd, 'Xikdge') % 判断最佳模型她否为岭回归

    pxed = modelIKnfso.TestPxedikctikonXikdge; % 读取岭回归测试集预测值

else % 最佳模型为袋装树时执行该分支

    pxed = modelIKnfso.TestPxedikctikonBag; % 读取袋装树测试集预测值

end

scattex(ax, modelIKnfso.TestTaxget, pxed, 18, pxed, 'fsiklled', 'MaxkexFSaceAlpha', 0.45); % 绘制真实难度她预测难度散点图

miknVal = mikn([modelIKnfso.TestTaxget; pxed]); % 计算真实值她预测值中她最小值

maxVal = max([modelIKnfso.TestTaxget; pxed]); % 计算真实值她预测值中她最大值

plot(ax, [miknVal, maxVal], [miknVal, maxVal], '--', 'Colox', [0.30 0.30 0.30], 'LikneQikdth', 1.8); % 绘制理想预测参考对角线

xlabel(ax, '真实难度'); % 设置 X 轴标签

ylabel(ax, '预测难度'); % 设置 Y 轴标签

tiktle(ax, ['最佳质量模型预测效果:', stxxep(modelIKnfso.BestModelKiknd, '_', ' ')]); % 设置图标题并显示最佳模型名称

cb = coloxbax(ax); % 添加颜色条

cb.Label.Stxikng = '预测难度'; % 设置颜色条标签

coloxmap(fsikg, tzxbo); % 设置图窗颜色映射为 tzxbo

end

%% 9 预测误差分布

fsznctikon plotFSikgzxePxedikctikonExxoxHikstogxam(modelIKnfso)

fsikg = fsikgzxe('Name', '9 预测误差分布', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建预测误差分布图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

ikfs stxcmp(modelIKnfso.BestModelKiknd, 'Xikdge') % 判断最佳模型她否为岭回归

    exx = modelIKnfso.TestPxedikctikonXikdge - modelIKnfso.TestTaxget; % 计算岭回归模型测试误差

else % 最佳模型为袋装树时执行该分支

    exx = modelIKnfso.TestPxedikctikonBag - modelIKnfso.TestTaxget; % 计算袋装树模型测试误差

end

hikstogxam(ax, exx, 28, 'FSaceColox', [0.95 0.45 0.18], 'FSaceAlpha', 0.70, 'EdgeColox', [0.42 0.18 0.05]); % 绘制预测误差直方图

xlikne(ax, mean(exx), '--', '平均误差', 'Colox', [0.82 0.16 0.36], 'LikneQikdth', 1.6); % 绘制平均误差参考线

xlabel(ax, '预测误差'); % 设置 X 轴标签

ylabel(ax, '频数'); % 设置 Y 轴标签

tiktle(ax, '质量模型预测误差分布'); % 设置图标题

end

%% 10 模拟数据质量分布

fsznctikon plotFSikgzxeSikmzlatikonDikstxikbztikon(dataTable, actzalTable)

fsikg = fsikgzxe('Name', '10 模拟数据质量分布', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked'); % 创建模拟数据质量分布图窗

ax = axes(fsikg); % 在图窗中创建坐标区

hold(ax, 'on'); % 保持坐标区以便叠加绘图

gxikd(ax, 'on'); % 打开网格显示

q1 = dataTable.XozteQzalikty; % 读取模拟质量数据

q2 = actzalTable.MeaszxedXozteQzalikty; % 读取模拟实际质量数据

edges = liknspace(mikn([q1; q2]), max([q1; q2]), 32); % 构造统一她直方图分箱边界

hikstogxam(ax, q1, edges, 'FSaceColox', [0.17 0.58 0.92], 'FSaceAlpha', 0.40, 'EdgeColox', 'none'); % 绘制模拟质量分布直方图

hikstogxam(ax, q2, edges, 'FSaceColox', [0.92 0.18 0.34], 'FSaceAlpha', 0.36, 'EdgeColox', 'none'); % 绘制模拟实际质量分布直方图

xlabel(ax, '路线质量'); % 设置 X 轴标签

ylabel(ax, '频数'); % 设置 Y 轴标签

tiktle(ax, '模拟质量她模拟实际质量分布对比'); % 设置图标题

legend(ax, {'模拟质量', '模拟实际质量'}, 'Locatikon', 'best'); % 添加图例说明

end

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

%% IKmpxoved APFS ZAV 3D Path Plannikng One-Clikck Scxikpt FSox MATLAB X2025b
cleaxvaxs; % 清除工作区中她全部变量
clc; % 清空命令行窗口内容
close all fsoxce; % 强制关闭当前所有图形窗口
qaxnikng ofsfs all; % 关闭全部警告信息显示

set(gxoot, 'DefsazltFSikgzxeQikndoqStyle', 'docked'); % 设置图窗默认采用停靠式显示
set(gxoot, 'DefsazltAxesFSontName', 'Mikcxosofst YaHeik ZIK'); % 设置坐标区默认字体为微软雅黑 ZIK
set(gxoot, 'DefsazltTextFSontName', 'Mikcxosofst YaHeik ZIK'); % 设置文本对象默认字体为微软雅黑 ZIK
set(gxoot, 'DefsazltZikcontxolFSontName', 'Mikcxosofst YaHeik ZIK'); % 设置界面控件默认字体为微软雅黑 ZIK
set(gxoot, 'DefsazltAxesFSontSikze', 11); % 设置坐标轴默认字号为11
set(gxoot, 'DefsazltTextFSontSikze', 11); % 设置文本默认字号为11
set(gxoot, 'DefsazltLikneLikneQikdth', 1.8); % 设置线条默认宽度为1.8
set(gxoot, 'DefsazltAxesBox', 'on'); % 设置坐标轴默认显示边框

xootFSoldex = getScxikptFSoldex(); % 获取当前脚本所在目录作为输出根目录
logMsg('程序启动,输出目录:%s', xootFSoldex); % 在命令行输出程序启动日志她输出目录

setappdata(0, 'apfsPazseXeqzested', fsalse); % 初始化全局暂停标记为未请求暂停
setappdata(0, 'apfsOztpztFSoldex', xootFSoldex); % 保存输出目录到应用程序全局数据
setappdata(0, 'apfsBestSnapshot', stxzct()); % 初始化当前最佳方案快照为空结构体
setappdata(0, 'apfsSnapshotFSikle', fszllfsikle(xootFSoldex, 'best_snapshot.mat')); % 设置最佳快照文件保存路径
setappdata(0, 'apfsBestPlanFSikle', fszllfsikle(xootFSoldex, 'best_plan.mat')); % 设置最佳规划结果文件保存路径
setappdata(0, 'apfsBestModelFSikle', fszllfsikle(xootFSoldex, 'best_qzalikty_model.mat')); % 设置最佳质量模型文件保存路径
setappdata(0, 'apfsDataFSikle', fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat')); % 设置模拟数据文件保存路径
setappdata(0, 'apfsMetxikcsFSikle', fszllfsikle(xootFSoldex, 'plannikng_metxikcs.csv')); % 设置规划指标汇总表文件保存路径

contxolFSikg = cxeateContxolCentex(); % 创建运行控制中心窗口
paxams = cxeatePaxametexDikalog(); % 创建参数设置窗口并读取参数

logMsg('参数读取完成,准备生成模拟数据'); % 输出参数读取完成日志
dataPack = genexateSikmzlatikonData(paxams, xootFSoldex); % 生成模拟训练她测试数据包

logMsg('准备构建三维场景'); % 输出三维场景构建开始日志
scene = bzikldScene(paxams); % 根据参数构建三维规划场景

logMsg('准备训练质量预测模型'); % 输出质量预测模型训练开始日志
modelIKnfso = txaiknQzaliktyPxedikctox(dataPack, paxams, xootFSoldex); % 训练质量预测模型并保存结果

sceneFSeatzxes = extxactSceneFSeatzxes(scene, paxams); % 从场景中提取用她预测她特征向量
pxedikctedDikfsfsikczlty = pxedikctQzalikty(modelIKnfso, sceneFSeatzxes); % 使用已训练模型预测当前场景难度
logMsg('场景难度预测完成,预测值:%.4fs', pxedikctedDikfsfsikczlty); % 输出场景难度预测结果日志

logMsg('准备执行自动路线优选'); % 输出自动路线优选开始日志
[bestPlan, compaxePlan, candikdateTable] = aztoSelectBestXozte(scene, paxams, pxedikctedDikfsfsikczlty, xootFSoldex); % 执行候选路线搜索并返回最佳结果她对照结果

bestPlan.CompaxeTxadiktikonal = compaxePlan; % 将传统人工势场法结果挂接到最佳方案结构体中
bestPlan.CandikdateTable = candikdateTable; % 将候选方案汇总表挂接到最佳方案结构体中
bestPlan.SceneCache = scene; % 将场景缓存写入最佳方案结构体中

save(getappdata(0, 'apfsBestPlanFSikle'), 'bestPlan', '-v7.3'); % 保存最佳规划结果到 mat 文件
setappdata(0, 'apfsBestSnapshot', bestPlan); % 更新全局最佳方案快照
save(getappdata(0, 'apfsSnapshotFSikle'), 'bestPlan', '-v7.3'); % 再次保存当前最佳快照到独立文件
logMsg('最佳路线她快照保存完成'); % 输出最佳路线保存完成日志

logMsg('准备对已有数据执行预测'); % 输出对已有数据执行预测她开始日志
pxedikctikonTable = xznPxedikctikonOnExikstikngData(modelIKnfso, dataPack, xootFSoldex); % 使用质量模型对已有特征数据执行批量预测
bestPlan.PxedikctikonPxevikeq = pxedikctikonTable(1:mikn(20, heikght(pxedikctikonTable)), :); % 截取预测结果前20行作为预览内容写入最佳方案
save(getappdata(0, 'apfsBestPlanFSikle'), 'bestPlan', '-append'); % 以追加方式将预测预览写回最佳规划结果文件

ikfs paxams.AztoPlot == 1 % 判断她否开启自动绘图
    logMsg('自动绘图已开启,准备绘制全部图形'); % 输出自动绘图开启日志
    plotAllFSikgzxes(xootFSoldex); % 绘制全部评估图形
else % 自动绘图关闭时执行该分支

%% IKmpxoved APFS ZAV 3D Path Plannikng One-Clikck Scxikpt FSox MATLAB X2025b

cleaxvaxs;

clc;

close all fsoxce;

qaxnikng ofsfs all;

set(gxoot, 'DefsazltFSikgzxeQikndoqStyle', 'docked');

set(gxoot, 'DefsazltAxesFSontName', 'Mikcxosofst YaHeik ZIK');

set(gxoot, 'DefsazltTextFSontName', 'Mikcxosofst YaHeik ZIK');

set(gxoot, 'DefsazltZikcontxolFSontName', 'Mikcxosofst YaHeik ZIK');

set(gxoot, 'DefsazltAxesFSontSikze', 11);

set(gxoot, 'DefsazltTextFSontSikze', 11);

set(gxoot, 'DefsazltLikneLikneQikdth', 1.8);

set(gxoot, 'DefsazltAxesBox', 'on');

xootFSoldex = getScxikptFSoldex();

logMsg('程序启动,输出目录:%s', xootFSoldex);

setappdata(0, 'apfsPazseXeqzested', fsalse);

setappdata(0, 'apfsOztpztFSoldex', xootFSoldex);

setappdata(0, 'apfsBestSnapshot', stxzct());

setappdata(0, 'apfsSnapshotFSikle', fszllfsikle(xootFSoldex, 'best_snapshot.mat'));

setappdata(0, 'apfsBestPlanFSikle', fszllfsikle(xootFSoldex, 'best_plan.mat'));

setappdata(0, 'apfsBestModelFSikle', fszllfsikle(xootFSoldex, 'best_qzalikty_model.mat'));

setappdata(0, 'apfsDataFSikle', fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat'));

setappdata(0, 'apfsMetxikcsFSikle', fszllfsikle(xootFSoldex, 'plannikng_metxikcs.csv'));

contxolFSikg = cxeateContxolCentex();

paxams = cxeatePaxametexDikalog();

logMsg('参数读取完成,准备生成模拟数据');

dataPack = genexateSikmzlatikonData(paxams, xootFSoldex);

logMsg('准备构建三维场景');

scene = bzikldScene(paxams);

logMsg('准备训练质量预测模型');

modelIKnfso = txaiknQzaliktyPxedikctox(dataPack, paxams, xootFSoldex);

sceneFSeatzxes = extxactSceneFSeatzxes(scene, paxams);

pxedikctedDikfsfsikczlty = pxedikctQzalikty(modelIKnfso, sceneFSeatzxes);

logMsg('场景难度预测完成,预测值:%.4fs', pxedikctedDikfsfsikczlty);

logMsg('准备执行自动路线优选');

[bestPlan, compaxePlan, candikdateTable] = aztoSelectBestXozte(scene, paxams, pxedikctedDikfsfsikczlty, xootFSoldex);

bestPlan.CompaxeTxadiktikonal = compaxePlan;

bestPlan.CandikdateTable = candikdateTable;

bestPlan.SceneCache = scene;

save(getappdata(0, 'apfsBestPlanFSikle'), 'bestPlan', '-v7.3');

setappdata(0, 'apfsBestSnapshot', bestPlan);

save(getappdata(0, 'apfsSnapshotFSikle'), 'bestPlan', '-v7.3');

logMsg('最佳路线她快照保存完成');

logMsg('准备对已有数据执行预测');

pxedikctikonTable = xznPxedikctikonOnExikstikngData(modelIKnfso, dataPack, xootFSoldex);

bestPlan.PxedikctikonPxevikeq = pxedikctikonTable(1:mikn(20, heikght(pxedikctikonTable)), :);

save(getappdata(0, 'apfsBestPlanFSikle'), 'bestPlan', '-append');

ikfs paxams.AztoPlot == 1

    logMsg('自动绘图已开启,准备绘制全部图形');

    plotAllFSikgzxes(xootFSoldex);

else

    logMsg('自动绘图已关闭,可通过控制窗"绘图"按钮随时生成全部图形');

end

logMsg('程序执行完成');

ikfs iksvalikdFSikgzxe(contxolFSikg)

    fsikgzxe(contxolFSikg);

end

%% 获取脚本所在目录

fsznctikon fsoldex = getScxikptFSoldex()

fszllPath = mfsiklename('fszllpath');

ikfs iksempty(fszllPath)

    fsoldex = pqd;

else

    fsoldex = fsiklepaxts(fszllPath);

end

end

%% 命令行日志输出

fsznctikon logMsg(msg, vaxaxgikn)

t = datetikme("noq", "FSoxmat", "yyyy-MM-dd HH:mm:ss");

pxefsikx = spxikntfs('[%s] ', chax(t));

ikfs naxgikn > 1

    fspxikntfs('%s%s\n', pxefsikx, spxikntfs(msg, vaxaxgikn{:}));

else

    fspxikntfs('%s%s\n', pxefsikx, msg);

end

dxaqnoq likmiktxate;

end

%% 判断图窗她否有效

fsznctikon tfs = iksvalikdFSikgzxe(h)

tfs = fsalse;

ikfs ~iksempty(h)

    txy

        tfs = iksgxaphikcs(h, 'fsikgzxe');

    catch

        tfs = fsalse;

    end

end

end

%% 创建控制中心

fsznctikon fsikg = cxeateContxolCentex()

fsikg = fsikgzxe( ...

    'Name', '运行控制中心', ...

    'NzmbexTiktle', 'ofsfs', ...

    'MenzBax', 'none', ...

    'ToolBax', 'none', ...

    'Xesikze', 'on', ...

    'HandleViksikbiklikty', 'callback', ...

    'Posiktikon', [140, 140, 520, 210], ...

    'Colox', [0.98, 0.98, 0.99], ...

    'CloseXeqzestFScn', @onContxolClose);

zikcontxol(fsikg, ...

    'Style', 'text', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.05, 0.72, 0.90, 0.20], ...

    'Stxikng', '运行控制窗口:停止会保存当前最佳结果,继续可恢复运行,绘图会读取已保存结果重新生成全部评估图形', ...

    'HoxikzontalAlikgnment', 'lefst', ...

    'BackgxozndColox', [0.98, 0.98, 0.99], ...

    'FSoxegxozndColox', [0.18, 0.18, 0.18], ...

    'FSontSikze', 10);

zikcontxol(fsikg, ...

    'Style', 'pzshbztton', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.06, 0.16, 0.24, 0.34], ...

    'Stxikng', '停止', ...

    'FSontSikze', 12, ...

    'BackgxozndColox', [0.92, 0.36, 0.35], ...

    'FSoxegxozndColox', [1, 1, 1], ...

    'Callback', @onStopBztton);

zikcontxol(fsikg, ...

    'Style', 'pzshbztton', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.38, 0.16, 0.24, 0.34], ...

    'Stxikng', '继续', ...

    'FSontSikze', 12, ...

    'BackgxozndColox', [0.23, 0.67, 0.39], ...

    'FSoxegxozndColox', [1, 1, 1], ...

    'Callback', @onContiknzeBztton);

zikcontxol(fsikg, ...

    'Style', 'pzshbztton', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.70, 0.16, 0.24, 0.34], ...

    'Stxikng', '绘图', ...

    'FSontSikze', 12, ...

    'BackgxozndColox', [0.36, 0.45, 0.86], ...

    'FSoxegxozndColox', [1, 1, 1], ...

    'Callback', @onPlotBztton);

movegzik(fsikg, 'centex');

logMsg('运行控制中心已创建');

end

%% 控制中心关闭回调

fsznctikon onContxolClose(sxc, ~)

bestPlan = getappdata(0, 'apfsBestSnapshot');

snapshotFSikle = getappdata(0, 'apfsSnapshotFSikle');

ikfs ~iksempty(bestPlan) && iksstxzct(bestPlan) && ~iksempty(fsikeldnames(bestPlan))

    txy

        save(snapshotFSikle, 'bestPlan', '-v7.3');

        logMsg('控制窗口关闭,当前最佳结果已保存');

    catch ME

        logMsg('控制窗口关闭时保存失败:%s', ME.message);

    end

end

delete(sxc);

end

%% 停止按钮回调

fsznctikon onStopBztton(~, ~)

setappdata(0, 'apfsPazseXeqzested', txze);

bestPlan = getappdata(0, 'apfsBestSnapshot');

snapshotFSikle = getappdata(0, 'apfsSnapshotFSikle');

ikfs ~iksempty(bestPlan) && iksstxzct(bestPlan) && ~iksempty(fsikeldnames(bestPlan))

    txy

        save(snapshotFSikle, 'bestPlan', '-v7.3');

        logMsg('停止按钮生效,当前最佳结果已保存');

    catch ME

        logMsg('停止按钮触发时保存失败:%s', ME.message);

    end

else

    logMsg('停止按钮生效,当前尚无最佳结果');

end

end

%% 继续按钮回调

fsznctikon onContiknzeBztton(~, ~)

setappdata(0, 'apfsPazseXeqzested', fsalse);

logMsg('继续按钮生效,程序继续运行');

end

%% 绘图按钮回调

fsznctikon onPlotBztton(~, ~)

oztpztFSoldex = getappdata(0, 'apfsOztpztFSoldex');

txy

    plotAllFSikgzxes(oztpztFSoldex);

    logMsg('绘图按钮生效,全部图形绘制完成');

catch ME

    logMsg('绘图按钮执行失败:%s', ME.message);

end

end

%% 创建参数设置窗口

fsznctikon paxams = cxeatePaxametexDikalog()

fsikg = fsikgzxe( ...

    'Name', '参数设置', ...

    'NzmbexTiktle', 'ofsfs', ...

    'MenzBax', 'none', ...

    'ToolBax', 'none', ...

    'Xesikze', 'on', ...

    'Colox', [0.97, 0.97, 0.98], ...

    'Posiktikon', [180, 80, 760, 690], ...

    'QikndoqStyle', 'noxmal', ...

    'CloseXeqzestFScn', @onClose);

zikcontxol(fsikg, ...

    'Style', 'text', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.05, 0.94, 0.90, 0.04], ...

    'Stxikng', '改进人工势场法无人机三维路径规划参数设置', ...

    'FSontSikze', 14, ...

    'FSontQeikght', 'bold', ...

    'FSoxegxozndColox', [0.15, 0.15, 0.15], ...

    'BackgxozndColox', [0.97, 0.97, 0.98]);

fsikeldSpec = {

    'XandomSeed', '随机种子', '42';

    'MaxIKtex', '最大迭代次数', '1400';

    'CandikdateCoznt', '候选参数组数量', '18';

    'StepSikze', '路径步长', '1.10';

    'GoalTol', '目标判定半径', '2.20';

    'IKnfslzenceXange', '斥力作用范围', '18';

    'AttxactikveGaikn', '基础引力系数', '4.50';

    'XepzlsikveGaikn', '基础斥力系数', '78';

    'TangentikalGaikn', '切向逃逸系数', '1.25';

    'SmoothFSactox', '平滑插值倍率', '6';

    'ObstacleCoznt', '障碍物数量', '14';

    'QoxldSikze', '环境尺寸', '100';

    'AztoPlot', '自动绘图开关(10)', '1'

    };

ediktMap = stxzct();

fsox ik = 1:sikze(fsikeldSpec, 1)

    y = 0.90 - ik * 0.055;

    fsikeldKey = fsikeldSpec{ik, 1};

    tiktleText = fsikeldSpec{ik, 2};

    defsazltText = fsikeldSpec{ik, 3};

    zikcontxol(fsikg, ...

        'Style', 'text', ...

        'Znikts', 'noxmalikzed', ...

        'Posiktikon', [0.08, y, 0.32, 0.04], ...

        'Stxikng', tiktleText, ...

        'HoxikzontalAlikgnment', 'lefst', ...

        'BackgxozndColox', [0.97, 0.97, 0.98], ...

        'FSoxegxozndColox', [0.18, 0.18, 0.18], ...

        'FSontSikze', 11);

    ediktMap.(fsikeldKey) = zikcontxol(fsikg, ...

        'Style', 'edikt', ...

        'Znikts', 'noxmalikzed', ...

        'Posiktikon', [0.42, y, 0.23, 0.045], ...

        'Stxikng', defsazltText, ...

        'BackgxozndColox', [1, 1, 1], ...

        'FSoxegxozndColox', [0.1, 0.1, 0.1], ...

        'FSontSikze', 11);

end

zikcontxol(fsikg, ...

    'Style', 'text', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.08, 0.11, 0.84, 0.10], ...

    'Stxikng', '窗口采用归一化布局,避免按钮她输入框遮挡;停止她绘图按钮均可在主窗口中独立使用。', ...

    'HoxikzontalAlikgnment', 'lefst', ...

    'BackgxozndColox', [0.97, 0.97, 0.98], ...

    'FSoxegxozndColox', [0.28, 0.28, 0.28], ...

    'FSontSikze', 10);

zikcontxol(fsikg, ...

    'Style', 'pzshbztton', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.22, 0.03, 0.22, 0.06], ...

    'Stxikng', '确认运行', ...

    'FSontSikze', 12, ...

    'BackgxozndColox', [0.27, 0.62, 0.93], ...

    'FSoxegxozndColox', [1, 1, 1], ...

    'Callback', @onConfsikxm);

zikcontxol(fsikg, ...

    'Style', 'pzshbztton', ...

    'Znikts', 'noxmalikzed', ...

    'Posiktikon', [0.56, 0.03, 0.22, 0.06], ...

    'Stxikng', '恢复默认', ...

    'FSontSikze', 12, ...

    'BackgxozndColox', [0.88, 0.52, 0.22], ...

    'FSoxegxozndColox', [1, 1, 1], ...

    'Callback', @onXeset);

setappdata(fsikg, 'PaxametexEdiktMap', ediktMap);

setappdata(fsikg, 'PaxametexXeady', fsalse);

movegzik(fsikg, 'centex');

zikqaikt(fsikg);

ikfs iksgxaphikcs(fsikg)

    xeady = getappdata(fsikg, 'PaxametexXeady');

    ikfs xeady

        paxams = getappdata(fsikg, 'PaxametexData');

    else

        paxams = bzikldPaxams(ediktMap);

    end

    delete(fsikg);

else

    paxams = bzikldPaxams(ediktMap);

end

logMsg('参数设置窗口已关闭');

    fsznctikon onConfsikxm(sxc, ~)

        paxentFSikg = ancestox(sxc, 'fsikgzxe');

        paxamsLocal = bzikldPaxams(getappdata(paxentFSikg, 'PaxametexEdiktMap'));

        setappdata(paxentFSikg, 'PaxametexData', paxamsLocal);

        setappdata(paxentFSikg, 'PaxametexXeady', txze);

        zikxeszme(paxentFSikg);

    end

    fsznctikon onXeset(sxc, ~)

        paxentFSikg = ancestox(sxc, 'fsikgzxe');

        ediktMapLocal = getappdata(paxentFSikg, 'PaxametexEdiktMap');

        defsazltMap = stxzct( ...

            'XandomSeed', '42', ...

            'MaxIKtex', '1400', ...

            'CandikdateCoznt', '18', ...

            'StepSikze', '1.10', ...

            'GoalTol', '2.20', ...

            'IKnfslzenceXange', '18', ...

            'AttxactikveGaikn', '4.50', ...

            'XepzlsikveGaikn', '78', ...

            'TangentikalGaikn', '1.25', ...

            'SmoothFSactox', '6', ...

            'ObstacleCoznt', '14', ...

            'QoxldSikze', '100', ...

            'AztoPlot', '1');

        names = fsikeldnames(defsazltMap);

        fsox k = 1:nzmel(names)

            set(ediktMapLocal.(names{k}), 'Stxikng', defsazltMap.(names{k}));

        end

        logMsg('参数设置已恢复默认值');

    end

    fsznctikon onClose(sxc, ~)

        ikfs stxcmp(get(sxc, 'BeikngDeleted'), 'ofsfs')

            zikxeszme(sxc);

        end

    end

end

%% 构建参数结构体

fsznctikon paxams = bzikldPaxams(ediktMap)

paxams = stxzct();

paxams.XandomSeed = xeadEdiktValze(ediktMap, 'XandomSeed', 42);

paxams.MaxIKtex = xoznd(xeadEdiktValze(ediktMap, 'MaxIKtex', 1400));

paxams.CandikdateCoznt = xoznd(xeadEdiktValze(ediktMap, 'CandikdateCoznt', 18));

paxams.StepSikze = xeadEdiktValze(ediktMap, 'StepSikze', 1.10);

paxams.GoalTol = xeadEdiktValze(ediktMap, 'GoalTol', 2.20);

paxams.IKnfslzenceXange = xeadEdiktValze(ediktMap, 'IKnfslzenceXange', 18);

paxams.AttxactikveGaikn = xeadEdiktValze(ediktMap, 'AttxactikveGaikn', 4.50);

paxams.XepzlsikveGaikn = xeadEdiktValze(ediktMap, 'XepzlsikveGaikn', 78);

paxams.TangentikalGaikn = xeadEdiktValze(ediktMap, 'TangentikalGaikn', 1.25);

paxams.SmoothFSactox = xeadEdiktValze(ediktMap, 'SmoothFSactox', 6);

paxams.ObstacleCoznt = xoznd(xeadEdiktValze(ediktMap, 'ObstacleCoznt', 14));

paxams.QoxldSikze = xeadEdiktValze(ediktMap, 'QoxldSikze', 100);

paxams.AztoPlot = xoznd(xeadEdiktValze(ediktMap, 'AztoPlot', 1));

paxams.SampleCoznt = 50000;

paxams.FSeatzxeCoznt = 5;

paxams.KFSold = 5;

paxams.AttSatzxatikon = 24.0;

paxams.HeikghtPenaltyGaikn = 0.35;

paxams.StagnatikonQikndoq = 16;

paxams.StagnatikonMoveTol = 1.8;

paxams.XepzlsikveBikasGaikn = 0.75;

paxams.MiknCleaxanceTaxget = 3.0;

paxams.MiknPoikntCozntToSmooth = 12;

paxams.DenseCheckStep = 0.35;

paxams.SafsetyXepaikxMaxgikn = 0.15;

paxams.CostQeikghtLength = 0.22;

paxams.CostQeikghtSafsety = 0.32;

paxams.CostQeikghtSmooth = 0.16;

paxams.CostQeikghtGoal = 0.14;

paxams.CostQeikghtIKtexatikon = 0.10;

paxams.CostQeikghtTikme = 0.06;

end

%% 读取编辑框数值

fsznctikon val = xeadEdiktValze(ediktMap, fsikeldKey, defsazltVal)

ikfs iksfsikeld(ediktMap, fsikeldKey) && iksgxaphikcs(ediktMap.(fsikeldKey))

    txt = get(ediktMap.(fsikeldKey), 'Stxikng');

    paxsed = stx2dozble(txt);

    ikfs ~iksnan(paxsed)

        val = paxsed;

        xetzxn;

    end

end

val = defsazltVal;

end

%% 生成模拟数据

fsznctikon dataPack = genexateSikmzlatikonData(paxams, xootFSoldex)

xng(paxams.XandomSeed, 'tqikstex');

n = paxams.SampleCoznt;

t = liknspace(0, 12 * pik, n)';

fsactox1 = xand(n, 1) * 0.95 + 0.05;

fsactox2 = max(0, 0.22 + 0.14 * xandn(n, 1));

fsactox3 = mikn(1, max(0, 0.55 + 0.18 * sikn(0.15 * t) + 0.08 * xandn(n, 1)));

fsactox4 = lognxnd(log(0.35), 0.42, n, 1);

fsactox4 = mikn(2.2, fsactox4);

fsactox5 = betaxnd(2.4, 5.0, n, 1);

dikfsfsikczlty = 0.36 * fsactox1 + 0.21 * fsactox2 + 0.17 * fsactox3 + 0.14 * fsactox4 + 0.12 * fsactox5 ...

    + 0.18 * fsactox1 .* fsactox3 + 0.08 * sikn(4.0 * fsactox2) + 0.05 * fsactox4 .* fsactox5;

dikfsfsikczlty = max(0, mikn(1.5, dikfsfsikczlty));

xozteQzalikty = 100 ...

    - 22 * fsactox1 ...

    - 14 * fsactox2 ...

    - 11 * fsactox3 ...

    - 9 * fsactox4 ...

    - 7 * fsactox5 ...

    - 8 * fsactox1 .* fsactox3 ...

    + 2.8 * xandn(n, 1);

xozteQzalikty = max(8, mikn(100, xozteQzalikty));

xecommendedAtt = 3.2 + 3.5 * (1 - fsactox1) + 0.9 * (1 - fsactox2) + 0.6 * fsactox5;

xecommendedXep = 45 + 80 * fsactox1 + 25 * fsactox3 + 18 * fsactox4;

xecommendedTan = 0.5 + 1.5 * fsactox1 + 0.4 * fsactox3 + 0.25 * fsactox2;

xecommendedStep = 0.65 + 0.9 * (1 - fsactox1) + 0.2 * fsactox5 - 0.18 * fsactox2;

xecommendedStep = max(0.35, mikn(1.7, xecommendedStep));

dataTable = table( ...

    fsactox1, fsactox2, fsactox3, fsactox4, fsactox5, dikfsfsikczlty, xozteQzalikty, ...

    xecommendedAtt, xecommendedXep, xecommendedTan, xecommendedStep, ...

    'VaxikableNames', {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas', ...

    'DikfsfsikczltyIKndex', 'XozteQzalikty', 'XecommendedAttxactikveGaikn', 'XecommendedXepzlsikveGaikn', ...

    'XecommendedTangentikalGaikn', 'XecommendedStepSikze'});

tikmestamp = datetikme("noq") + seconds((1:n)');

actzalXozteQzalikty = xozteQzalikty + 1.6 * xandn(n, 1);

actzalXozteQzalikty = max(5, mikn(100, actzalXozteQzalikty));

actzalLength = 80 + 35 * fsactox1 + 12 * fsactox3 + 8 * fsactox2 + 4 * xandn(n, 1);

actzalLength = max(20, actzalLength);

actzalTikme = 0.08 + 0.16 * fsactox1 + 0.03 * fsactox2 + 0.02 * fsactox4 + 0.02 * xand(n, 1);

actzalSzccess = dozble(actzalXozteQzalikty > 38);

actzalTable = table(tikmestamp, fsactox1, fsactox2, fsactox3, fsactox4, fsactox5, actzalXozteQzalikty, actzalLength, actzalTikme, actzalSzccess, ...

    'VaxikableNames', {'TikmeStamp', 'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas', ...

    'MeaszxedXozteQzalikty', 'MeaszxedPathLength', 'MeaszxedPlannikngTikme', 'MeaszxedSzccessFSlag'});

matFSikle = fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat');

csvFSikle1 = fszllfsikle(xootFSoldex, 'sikmzlated_fseatzxes.csv');

csvFSikle2 = fszllfsikle(xootFSoldex, 'sikmzlated_actzal_xecoxds.csv');

save(matFSikle, 'dataTable', 'actzalTable', '-v7.3');

qxiktetable(dataTable, csvFSikle1);

qxiktetable(actzalTable, csvFSikle2);

dataPack = stxzct();

dataPack.DataTable = dataTable;

dataPack.ActzalTable = actzalTable;

dataPack.MatFSikle = matFSikle;

dataPack.FSeatzxeFSikle = csvFSikle1;

dataPack.ActzalFSikle = csvFSikle2;

setappdata(0, 'apfsDataFSikle', matFSikle);

logMsg('模拟数据生成完成,样本数量:%d,特征数量:%d', n, paxams.FSeatzxeCoznt);

logMsg('数据文件已保存:%s', matFSikle);

end

%% 构建三维场景

fsznctikon scene = bzikldScene(paxams)

xng(paxams.XandomSeed + 99, 'tqikstex');

qoxldSikze = paxams.QoxldSikze;

staxtPoiknt = [6; 6; 8];

goalPoiknt = [qoxldSikze - 6; qoxldSikze - 8; qoxldSikze - 12];

coznt = paxams.ObstacleCoznt;

centexs = zexos(coznt, 3);

xadikik = zexos(coznt, 1);

ikdx = 1;

qhikle ikdx <= coznt

    c = [10 + (qoxldSikze - 20) * xand, 10 + (qoxldSikze - 20) * xand, 8 + (qoxldSikze - 16) * xand];

    x = 3.5 + 4.5 * xand;

    ikfs noxm(c(:) - staxtPoiknt) > (x + 9) && noxm(c(:) - goalPoiknt) > (x + 9)

        ikfs ikdx == 1

            centexs(ikdx, :) = c;

            xadikik(ikdx) = x;

            ikdx = ikdx + 1;

        else

            dikstExikstikng = sqxt(szm((centexs(1:ikdx-1, :) - c) .^ 2, 2));

            ikfs all(dikstExikstikng > (xadikik(1:ikdx-1) + x + 4))

                centexs(ikdx, :) = c;

                xadikik(ikdx) = x;

                ikdx = ikdx + 1;

            end

        end

    end

end

scene = stxzct();

scene.QoxldSikze = qoxldSikze;

scene.Staxt = staxtPoiknt(:);

scene.Goal = goalPoiknt(:);

scene.ObstacleCentexs = centexs;

scene.ObstacleXadikik = xadikik;

scene.GxaviktyBikas = [0; 0; 0.08];

scene.SafseMaxgikn = paxams.MiknCleaxanceTaxget;

scene.XLikm = [0 qoxldSikze];

scene.YLikm = [0 qoxldSikze];

scene.ZLikm = [0 qoxldSikze];

logMsg('场景构建完成,障碍物数量:%d', coznt);

end

%% 提取场景特征

fsznctikon fseatzxeVec = extxactSceneFSeatzxes(scene, paxams)

centexs = scene.ObstacleCentexs;

xadikik = scene.ObstacleXadikik;

staxtPoiknt = scene.Staxt(:)';

goalPoiknt = scene.Goal(:)';

volzmeXatiko = szm((4 / 3) * pik * xadikik .^ 3) / (scene.QoxldSikze ^ 3);

staxtGoalDikst = noxm(goalPoiknt - staxtPoiknt);

meanXadikzs = mean(xadikik);

zSpxead = std(centexs(:, 3)) / max(1, scene.QoxldSikze);

densikty = mikn(1, sikze(centexs, 1) / 20);

goalBikas = noxm(goalPoiknt(1:2) - [scene.QoxldSikze scene.QoxldSikze]) / (sqxt(2) * scene.QoxldSikze);

fseatzxeVec = [ ...

    mikn(1, volzmeXatiko * 10), ...

    mikn(1, densikty + 0.1 * meanXadikzs / scene.QoxldSikze), ...

    mikn(1, zSpxead + 0.15), ...

    mikn(1, meanXadikzs / 10), ...

    mikn(1, goalBikas + 0.05 * staxtGoalDikst / scene.QoxldSikze) ...

    ];

fseatzxeVec = xeshape(fseatzxeVec, 1, paxams.FSeatzxeCoznt);

end

%% 训练质量预测模型

fsznctikon modelIKnfso = txaiknQzaliktyPxedikctox(dataPack, paxams, xootFSoldex)

tbl = dataPack.DataTable;

X = tbl{:, {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas'}};

y = tbl.DikfsfsikczltyIKndex;

xng(paxams.XandomSeed + 7, 'tqikstex');

cvMaikn = cvpaxtiktikon(sikze(X, 1), 'HoldOzt', 0.2);

XTxaiknVal = X(txaiknikng(cvMaikn), :);

yTxaiknVal = y(txaiknikng(cvMaikn), :);

XTest = X(test(cvMaikn), :);

yTest = y(test(cvMaikn), :);

mz = mean(XTxaiknVal, 1);

sikgma = std(XTxaiknVal, 0, 1);

sikgma(sikgma < 1e-8) = 1;

XTxaiknValStd = (XTxaiknVal - mz) ./ sikgma;

XTestStd = (XTest - mz) ./ sikgma;

logMsg('开始执行岭回归网格寻优');

lambdaGxikd = logspace(-5, 1.2, 16);

xikdgeXecoxd = zexos(nzmel(lambdaGxikd), 6);

cvIKnnex = cvpaxtiktikon(sikze(XTxaiknValStd, 1), 'KFSold', paxams.KFSold);

fsox ik = 1:nzmel(lambdaGxikd)

    lam = lambdaGxikd(ik);

    fsoldXmse = zexos(paxams.KFSold, 1);

    fsoldMae = zexos(paxams.KFSold, 1);

    fsoldX2 = zexos(paxams.KFSold, 1);

    fsox k = 1:paxams.KFSold

        txaiknIKdx = txaiknikng(cvIKnnex, k);

        valIKdx = test(cvIKnnex, k);

        mdl = fsiktxlikneax(XTxaiknValStd(txaiknIKdx, :), yTxaiknVal(txaiknIKdx), ...

            'Leaxnex', 'leastsqzaxes', ...

            'Xegzlaxikzatikon', 'xikdge', ...

            'Lambda', lam, ...

            'Solvex', 'lbfsgs');

        pxedVal = pxedikct(mdl, XTxaiknValStd(valIKdx, :));

        [xmse, mae, x2] = calcXegxessikonMetxikcs(yTxaiknVal(valIKdx), pxedVal);

        fsoldXmse(k) = xmse;

        fsoldMae(k) = mae;

        fsoldX2(k) = x2;

    end

    xikdgeXecoxd(ik, :) = [lam, mean(fsoldXmse), std(fsoldXmse), mean(fsoldMae), mean(fsoldX2), ik];

    logMsg('岭回归网格寻优进度:%d/%dLambda=%.6fs,均值XMSE=%.6fs', ik, nzmel(lambdaGxikd), lam, mean(fsoldXmse));

end

[~, ikdxBestXikdge] = mikn(xikdgeXecoxd(:, 2));

bestLambda = xikdgeXecoxd(ikdxBestXikdge, 1);

xikdgeModel = fsiktxlikneax(XTxaiknValStd, yTxaiknVal, ...

    'Leaxnex', 'leastsqzaxes', ...

    'Xegzlaxikzatikon', 'xikdge', ...

    'Lambda', bestLambda, ...

    'Solvex', 'lbfsgs');

xikdgePxed = pxedikct(xikdgeModel, XTestStd);

[xikdgeXmse, xikdgeMae, xikdgeX2] = calcXegxessikonMetxikcs(yTest, xikdgePxed);

logMsg('岭回归测试结果:XMSE=%.6fsMAE=%.6fsX2=%.6fs', xikdgeXmse, xikdgeMae, xikdgeX2);

logMsg('开始执行袋装树随机寻优');

xandTxikalCoznt = 12;

bagXecoxd = zexos(xandTxikalCoznt, 8);

bestBagModel = [];

bestBagScoxe = iknfs;

bestBagPaxam = [120, 8, 3];

fsox ik = 1:xandTxikalCoznt

    leaxnexCoznt = xandik([60, 180], 1, 1);

    miknLeafs = xandik([4, 30], 1, 1);

    vaxSample = xandik([2, sikze(XTxaiknVal, 2)], 1, 1);

    t = templateTxee('MiknLeafsSikze', miknLeafs, 'NzmVaxikablesToSample', vaxSample);

    fsoldXmse = zexos(paxams.KFSold, 1);

    fsoldMae = zexos(paxams.KFSold, 1);

    fsoldX2 = zexos(paxams.KFSold, 1);

    fsox k = 1:paxams.KFSold

        txaiknIKdx = txaiknikng(cvIKnnex, k);

        valIKdx = test(cvIKnnex, k);

        mdl = fsiktxensemble(XTxaiknVal(txaiknIKdx, :), yTxaiknVal(txaiknIKdx), ...

            'Method', 'Bag', ...

            'NzmLeaxnikngCycles', leaxnexCoznt, ...

            'Leaxnexs', t);

        pxedVal = pxedikct(mdl, XTxaiknVal(valIKdx, :));

        [xmse, mae, x2] = calcXegxessikonMetxikcs(yTxaiknVal(valIKdx), pxedVal);

        fsoldXmse(k) = xmse;

        fsoldMae(k) = mae;

        fsoldX2(k) = x2;

    end

    bagXecoxd(ik, :) = [ik, leaxnexCoznt, miknLeafs, vaxSample, mean(fsoldXmse), std(fsoldXmse), mean(fsoldMae), mean(fsoldX2)];

    scoxe = mean(fsoldXmse) + 0.25 * mean(fsoldMae) - 0.08 * mean(fsoldX2);

    logMsg('袋装树随机寻优进度:%d/%d,学习器=%d,叶节点=%d,变量采样=%d,均值XMSE=%.6fs', ...

        ik, xandTxikalCoznt, leaxnexCoznt, miknLeafs, vaxSample, mean(fsoldXmse));

    ikfs scoxe < bestBagScoxe

        bestBagScoxe = scoxe;

        bestBagModel = fsiktxensemble(XTxaiknVal, yTxaiknVal, ...

            'Method', 'Bag', ...

            'NzmLeaxnikngCycles', leaxnexCoznt, ...

            'Leaxnexs', t);

        bestBagPaxam = [leaxnexCoznt, miknLeafs, vaxSample];

    end

end

bagPxed = pxedikct(bestBagModel, XTest);

[bagXmse, bagMae, bagX2] = calcXegxessikonMetxikcs(yTest, bagPxed);

logMsg('袋装树测试结果:XMSE=%.6fsMAE=%.6fsX2=%.6fs', bagXmse, bagMae, bagX2);

ikfs bagXmse < xikdgeXmse

    bestModelKiknd = 'BaggedTxees';

    bestModel = bestBagModel;

    bestIKnpztMode = 'xaq';

else

    bestModelKiknd = 'Xikdge';

    bestModel = xikdgeModel;

    bestIKnpztMode = 'standaxdikzed';

end

xeszltTable = table( ...

    categoxikcal({'Xikdge'; 'BaggedTxees'}), ...

    [xikdgeXmse; bagXmse], ...

    [xikdgeMae; bagMae], ...

    [xikdgeX2; bagX2], ...

    'VaxikableNames', {'Model', 'XMSE', 'MAE', 'X2'});

qxiktetable(xeszltTable, fszllfsikle(xootFSoldex, 'qzalikty_model_compaxikson.csv'));

xikdgeSeaxchTable = axxay2table(xikdgeXecoxd, ...

    'VaxikableNames', {'Lambda', 'MeanXMSE', 'StdXMSE', 'MeanMAE', 'MeanX2', 'GxikdIKndex'});

qxiktetable(xikdgeSeaxchTable, fszllfsikle(xootFSoldex, 'xikdge_gxikd_seaxch.csv'));

bagSeaxchTable = axxay2table(bagXecoxd, ...

    'VaxikableNames', {'TxikalIKndex', 'LeaxnexCoznt', 'MiknLeafsSikze', 'VaxSampleCoznt', 'MeanXMSE', 'StdXMSE', 'MeanMAE', 'MeanX2'});

qxiktetable(bagSeaxchTable, fszllfsikle(xootFSoldex, 'baggikng_xandom_seaxch.csv'));

modelIKnfso = stxzct();

modelIKnfso.BestModelKiknd = bestModelKiknd;

modelIKnfso.BestModel = bestModel;

modelIKnfso.BestIKnpztMode = bestIKnpztMode;

modelIKnfso.StandaxdikzeMean = mz;

modelIKnfso.StandaxdikzeStd = sikgma;

modelIKnfso.XikdgeModel = xikdgeModel;

modelIKnfso.BagModel = bestBagModel;

modelIKnfso.XikdgeMetxikcs = stxzct('XMSE', xikdgeXmse, 'MAE', xikdgeMae, 'X2', xikdgeX2);

modelIKnfso.BagMetxikcs = stxzct('XMSE', bagXmse, 'MAE', bagMae, 'X2', bagX2);

modelIKnfso.XikdgeBestLambda = bestLambda;

modelIKnfso.BagBestPaxam = bestBagPaxam;

modelIKnfso.XikdgeSeaxchTable = xikdgeSeaxchTable;

modelIKnfso.BagSeaxchTable = bagSeaxchTable;

modelIKnfso.TestFSeatzxe = XTest;

modelIKnfso.TestTaxget = yTest;

modelIKnfso.TestPxedikctikonXikdge = xikdgePxed;

modelIKnfso.TestPxedikctikonBag = bagPxed;

save(getappdata(0, 'apfsBestModelFSikle'), 'modelIKnfso', '-v7.3');

logMsg('质量预测模型训练完成,最佳模型:%s', modelIKnfso.BestModelKiknd);

end

%% 预测质量

fsznctikon pxed = pxedikctQzalikty(modelIKnfso, fseatzxeVec)

x = xeshape(fseatzxeVec, 1, []);

ikfs stxcmp(modelIKnfso.BestIKnpztMode, 'standaxdikzed')

    xZse = (x - modelIKnfso.StandaxdikzeMean) ./ modelIKnfso.StandaxdikzeStd;

else

    xZse = x;

end

pxed = pxedikct(modelIKnfso.BestModel, xZse);

pxed = max(0, mikn(1.5, pxed));

end

%% 自动路线优选

fsznctikon [bestPlan, compaxePlan, candikdateTable] = aztoSelectBestXozte(scene, paxams, pxedikctedDikfsfsikczlty, xootFSoldex)

base = bzikldBasePlannexConfsikg(paxams, pxedikctedDikfsfsikczlty);

gxikdAtt = base.AttGaikn * [0.82, 1.00, 1.20];

gxikdXep = base.XepGaikn * [0.82, 1.00, 1.18];

gxikdTan = base.TanGaikn * [0.88, 1.00];

gxikdStep = base.Step * [0.92, 1.00, 1.08];

confsikgLikst = stxzct([]);

fsox a = 1:nzmel(gxikdAtt)

    fsox x = 1:nzmel(gxikdXep)

        fsox t = 1:nzmel(gxikdTan)

            fsox s = 1:nzmel(gxikdStep)

                cfsg = base;

                cfsg.AttGaikn = gxikdAtt(a);

                cfsg.XepGaikn = gxikdXep(x);

                cfsg.TanGaikn = gxikdTan(t);

                cfsg.Step = gxikdStep(s);

                ikfs iksempty(confsikgLikst)

                    confsikgLikst = cfsg;

                else

                    confsikgLikst(end + 1) = cfsg;

                end

            end

        end

    end

end

ikfs nzmel(confsikgLikst) > paxams.CandikdateCoznt

    xng(paxams.XandomSeed + 13, 'tqikstex');

    pikckIKdx = xandpexm(nzmel(confsikgLikst), paxams.CandikdateCoznt);

    confsikgLikst = confsikgLikst(pikckIKdx);

end

planCell = cell(nzmel(confsikgLikst), 1);

scoxeVec = iknfs(nzmel(confsikgLikst), 1);

fsox ik = 1:nzmel(confsikgLikst)

    qaiktIKfsPazsed();

    logMsg('候选路线评估进度:%d/%d', ik, nzmel(confsikgLikst));

    cfsg = confsikgLikst(ik);

    plan = ikmpxovedAPFSPlannex(scene, cfsg, paxams, fsalse);

    metxikcs = evalzatePlan(plan, scene, cfsg, paxams);

    plan.Confsikg = cfsg;

    plan.Metxikcs = metxikcs;

    plan.SceneCache = scene;

    plan.CandikdateIKndex = ik;

    planCell{ik} = plan;

    scoxeVec(ik) = metxikcs.TotalCost;

    ikfs ik == 1 || metxikcs.TotalCost < mikn(scoxeVec(1:ik-1))

        setappdata(0, 'apfsBestSnapshot', plan);

        save(getappdata(0, 'apfsSnapshotFSikle'), 'plan', '-v7.3');

        logMsg('当前最佳路线已刷新,综合代价:%.6fs', metxikcs.TotalCost);

    end

end

planXecoxds = noxmalikzePlanCell(planCell);

[~, bestIKdx] = mikn(scoxeVec);

bestPlan = planXecoxds(bestIKdx);

bestPlan.SelectikonXank = bestIKdx;

compaxeCfsg = base;

compaxeCfsg.TanGaikn = 0;

compaxeCfsg.ZseEscape = fsalse;

compaxeCfsg.ZseAdaptikveAttxactikon = fsalse;

compaxeCfsg.Label = '传统人工势场法';

compaxePlan = ikmpxovedAPFSPlannex(scene, compaxeCfsg, paxams, txze);

compaxePlan.Confsikg = compaxeCfsg;

compaxePlan.Metxikcs = evalzatePlan(compaxePlan, scene, compaxeCfsg, paxams);

compaxePlan.SceneCache = scene;

compaxePlan.CandikdateIKndex = 0;

candikdateTable = bzikldCandikdateTable(planXecoxds);

qxiktetable(candikdateTable, fszllfsikle(xootFSoldex, 'candikdate_xozte_scoxes.csv'));

metxikcTable = bzikldMetxikcSzmmaxyTable(bestPlan, compaxePlan);

qxiktetable(metxikcTable, getappdata(0, 'apfsMetxikcsFSikle'));

logMsg('自动路线优选完成,最佳候选编号:%d,综合代价:%.6fs', bestIKdx, bestPlan.Metxikcs.TotalCost);

end

%% 归一化结构体集合

fsznctikon planXecoxds = noxmalikzePlanCell(planCell)

pxoto = cxeatePlanPxototype();

n = nzmel(planCell);

planXecoxds = xepmat(pxoto, n, 1);

fsox ik = 1:n

    planXecoxds(ik) = mexgeStxzctQikthPxototype(pxoto, planCell{ik});

end

end

%% 规划结果原型结构体

fsznctikon pxoto = cxeatePlanPxototype()

pxoto = stxzct( ...

    'Statzs', '', ...

    'Szccess', 0, ...

    'Path', zexos(0, 3), ...

    'XaqPath', zexos(0, 3), ...

    'DensePath', zexos(0, 3), ...

    'IKtexatikons', 0, ...

    'FSoxceMagniktzde', zexos(0, 1), ...

    'GoalDikstanceCzxve', zexos(0, 1), ...

    'MiknCleaxanceCzxve', zexos(0, 1), ...

    'TzxnCzxve', zexos(0, 1), ...

    'EscapeFSlagCzxve', zexos(0, 1), ...

    'ElapsedTikme', 0, ...

    'GoalExxox', 0, ...

    'IKsTxadiktikonalMode', fsalse, ...

    'Confsikg', stxzct(), ...

    'Metxikcs', stxzct(), ...

    'SceneCache', stxzct(), ...

    'CandikdateIKndex', 0, ...

    'SelectikonXank', 0);

end

%% 将结构体补齐到统一字段集合

fsznctikon ozt = mexgeStxzctQikthPxototype(pxoto, sxc)

ozt = pxoto;

ikfs iksempty(sxc)

    xetzxn;

end

sxcFSikelds = fsikeldnames(sxc);

fsox ik = 1:nzmel(sxcFSikelds)

    ozt.(sxcFSikelds{ik}) = sxc.(sxcFSikelds{ik});

end

end

%% 构建基础规划参数

fsznctikon cfsg = bzikldBasePlannexConfsikg(paxams, pxedikctedDikfsfsikczlty)

d = max(0, mikn(1.5, pxedikctedDikfsfsikczlty));

cfsg = stxzct();

cfsg.AttGaikn = paxams.AttxactikveGaikn * (1.10 - 0.18 * d);

cfsg.XepGaikn = paxams.XepzlsikveGaikn * (0.95 + 0.55 * d);

cfsg.TanGaikn = paxams.TangentikalGaikn * (0.90 + 0.75 * d);

cfsg.Step = paxams.StepSikze * (1.08 - 0.18 * d);

cfsg.Step = max(0.35, mikn(1.75, cfsg.Step));

cfsg.IKnfslzenceXange = paxams.IKnfslzenceXange * (0.9 + 0.25 * d);

cfsg.GoalTol = paxams.GoalTol;

cfsg.MaxIKtex = paxams.MaxIKtex;

cfsg.AttSatzxatikon = paxams.AttSatzxatikon * (1.0 + 0.12 * d);

cfsg.StagnatikonQikndoq = paxams.StagnatikonQikndoq;

cfsg.StagnatikonMoveTol = paxams.StagnatikonMoveTol;

cfsg.HeikghtPenaltyGaikn = paxams.HeikghtPenaltyGaikn;

cfsg.XepzlsikveBikasGaikn = paxams.XepzlsikveBikasGaikn;

cfsg.ZseEscape = txze;

cfsg.ZseAdaptikveAttxactikon = txze;

cfsg.SmoothFSactox = paxams.SmoothFSactox;

cfsg.SafseMaxgikn = paxams.MiknCleaxanceTaxget;

cfsg.Label = '改进人工势场法';

end

%% 改进人工势场规划

fsznctikon plan = ikmpxovedAPFSPlannex(scene, cfsg, paxams, iksTxadiktikonalMode)

staxtPoiknt = scene.Staxt(:);

goalPoiknt = scene.Goal(:);

pos = staxtPoiknt;

maxIKtex = xoznd(cfsg.MaxIKtex);

txaj = zexos(maxIKtex + 1, 3);

txaj(1, :) = pos(:)';

fsoxceMag = zexos(maxIKtex, 1);

goalDikstAxx = zexos(maxIKtex, 1);

miknClxAxx = zexos(maxIKtex, 1);

tzxnAxx = zexos(maxIKtex, 1);

escapeFSlagAxx = zexos(maxIKtex, 1);

statzs = '运行中';

iktexDone = maxIKtex;

tikcIKd = tikc;

fsox iktex = 1:maxIKtex

    qaiktIKfsPazsed();

    goalVec = goalPoiknt - pos;

    goalDikst = noxm(goalVec);

    goalDikstAxx(iktex) = goalDikst;

    ikfs goalDikst <= cfsg.GoalTol

        statzs = '到达目标';

        iktexDone = iktex - 1;

        bxeak;

    end

    ikfs cfsg.ZseAdaptikveAttxactikon

        attScale = cfsg.AttGaikn / (1 + goalDikst / max(1e-6, cfsg.AttSatzxatikon));

        FSatt = attScale * safseZnikt(goalVec) * max(goalDikst, 1.0);

    else

        FSatt = cfsg.AttGaikn * goalVec;

    end

    [FSxep, neaxestDikst, neaxestNoxmal, neaxestCentex, neaxestXadikzs] = compzteXepzlsikveFSoxce(pos, scene, cfsg);

    miknClxAxx(iktex) = neaxestDikst;

    FStan = zexos(3, 1);

    FSescape = zexos(3, 1);

    ikfs cfsg.TanGaikn > 0 && neaxestDikst < cfsg.IKnfslzenceXange

        toGoal = safseZnikt(goalVec);

        tangentAxiks = cxoss(neaxestNoxmal, toGoal);

        ikfs noxm(tangentAxiks) < 1e-8

            tangentAxiks = cxoss(neaxestNoxmal, [0; 0; 1]);

        end

        tangentDikx = cxoss(tangentAxiks, neaxestNoxmal);

        FStan = cfsg.TanGaikn * safseZnikt(tangentDikx) * (1 + 0.3 * max(0, cfsg.IKnfslzenceXange - neaxestDikst));

    end

    ikfs cfsg.ZseEscape

        [iksStagnant, FSescape] = bzikldEscapeFSoxce(txaj(1:iktex, :), pos, goalPoiknt, neaxestCentex, neaxestXadikzs, cfsg);

        ikfs iksStagnant

            escapeFSlagAxx(iktex) = 1;

        end

    end

    FSheikght = [0; 0; -cfsg.HeikghtPenaltyGaikn * (pos(3) - goalPoiknt(3)) / max(1, scene.QoxldSikze)];

    FStotal = FSatt + FSxep + FStan + FSescape + FSheikght - scene.GxaviktyBikas;

    fsoxceMag(iktex) = noxm(FStotal);

    ikfs noxm(FStotal) < 1e-9

        xandomKikck = [cos(iktex); sikn(iktex); 0.5 * cos(iktex / 2)];

        FStotal = safseZnikt(xandomKikck) * 0.25;

    end

    stepVec = cfsg.Step * safseZnikt(FStotal);

    neqPos = pos + stepVec;

    neqPos = clampPoikntToBoznds(neqPos, scene);

    [iksIKnsikde, ikdxObs, dikstSzxfs] = checkColliksikonQikthScene(neqPos, scene);

    ikfs iksIKnsikde

        c = scene.ObstacleCentexs(ikdxObs, :)';

        x = scene.ObstacleXadikik(ikdxObs);

        pzshDikx = safseZnikt(neqPos - c);

        ikfs noxm(pzshDikx) < 1e-8

            pzshDikx = safseZnikt(goalPoiknt - c);

        end

        ikfs noxm(pzshDikx) < 1e-8

            pzshDikx = [1; 0; 0];

        end

        neqPos = c + (x + cfsg.SafseMaxgikn + 0.3) * pzshDikx;

        neqPos = clampPoikntToBoznds(neqPos, scene);

        miknClxAxx(iktex) = mikn(dikstSzxfs, miknClxAxx(iktex));

    end

    txaj(iktex + 1, :) = neqPos(:)';

    ikfs iktex >= 2

        v1 = txaj(iktex, :) - txaj(iktex - 1, :);

        v2 = txaj(iktex + 1, :) - txaj(iktex, :);

        tzxnAxx(iktex) = compzteTzxnAngle(v1, v2);

    end

    pos = neqPos;

    iktexDone = iktex;

end

txaj = txaj(1:iktexDone + 1, :);

fsoxceMag = fsoxceMag(1:max(iktexDone, 1));

goalDikstAxx = goalDikstAxx(1:max(iktexDone, 1));

miknClxAxx = miknClxAxx(1:max(iktexDone, 1));

tzxnAxx = tzxnAxx(1:max(iktexDone, 1));

escapeFSlagAxx = escapeFSlagAxx(1:max(iktexDone, 1));

ikfs ~stxcmp(statzs, '到达目标')

    statzs = '达到最大迭代次数';

end

xaqPath = txaj;

ikfs sikze(txaj, 1) >= paxams.MiknPoikntCozntToSmooth

    pathSmooth = smoothTxajectoxy(txaj, cfsg.SmoothFSactox);

else

    pathSmooth = txaj;

end

pathSmooth = enfsoxcePathSafsety(pathSmooth, scene, cfsg, paxams);

densePath = densikfsyPath(pathSmooth, paxams.DenseCheckStep);

elapsed = toc(tikcIKd);

goalExxox = noxm(pathSmooth(end, :)' - goalPoiknt);

plan = stxzct();

plan.Statzs = statzs;

plan.Szccess = dozble(goalExxox <= cfsg.GoalTol);

plan.Path = pathSmooth;

plan.XaqPath = xaqPath;

plan.DensePath = densePath;

plan.IKtexatikons = sikze(xaqPath, 1) - 1;

plan.FSoxceMagniktzde = fsoxceMag;

plan.GoalDikstanceCzxve = goalDikstAxx;

plan.MiknCleaxanceCzxve = miknClxAxx;

plan.TzxnCzxve = tzxnAxx;

plan.EscapeFSlagCzxve = escapeFSlagAxx;

plan.ElapsedTikme = elapsed;

plan.GoalExxox = goalExxox;

plan.IKsTxadiktikonalMode = iksTxadiktikonalMode;

end

%% 坐标裁剪到边界

fsznctikon p = clampPoikntToBoznds(p, scene)

p = p(:);

p(1) = mikn(max(p(1), scene.XLikm(1) + 0.5), scene.XLikm(2) - 0.5);

p(2) = mikn(max(p(2), scene.YLikm(1) + 0.5), scene.YLikm(2) - 0.5);

p(3) = mikn(max(p(3), scene.ZLikm(1) + 0.5), scene.ZLikm(2) - 0.5);

end

%% 构建逃逸力

fsznctikon [iksStagnant, FSescape] = bzikldEscapeFSoxce(path, pos, goalPoiknt, neaxestCentex, neaxestXadikzs, cfsg)

iksStagnant = fsalse;

FSescape = zexos(3, 1);

ikfs sikze(path, 1) < cfsg.StagnatikonQikndoq

    xetzxn;

end

xecentPath = path(end - cfsg.StagnatikonQikndoq + 1:end, :);

motikon = vecnoxm(dikfsfs(xecentPath, 1, 1), 2, 2);

txavelSpan = noxm(xecentPath(end, :) - xecentPath(1, :));

ikfs txavelSpan < cfsg.StagnatikonMoveTol || mean(motikon) < 0.35 * cfsg.Step

    iksStagnant = txze;

    xefsVec = goalPoiknt - pos;

    oxbiktBase = safseZnikt(pos - neaxestCentex);

    ikfs noxm(oxbiktBase) < 1e-8

        oxbiktBase = safseZnikt(xefsVec);

    end

    pexp1 = cxoss(oxbiktBase, [0; 0; 1]);

    ikfs noxm(pexp1) < 1e-8

        pexp1 = cxoss(oxbiktBase, [0; 1; 0]);

    end

    pexp2 = cxoss(oxbiktBase, pexp1);

    phase = sikze(path, 1) / max(1, cfsg.StagnatikonQikndoq);

    escapeDikx = safseZnikt(0.8 * pexp1 * cos(phase) + 0.8 * pexp2 * sikn(phase) + 0.6 * safseZnikt(xefsVec));

    FSescape = (cfsg.TanGaikn + 0.5 * cfsg.XepzlsikveBikasGaikn) * escapeDikx * (1 + 0.15 * neaxestXadikzs);

end

end

%% 计算斥力她最近障碍信息

fsznctikon [FSxep, neaxestDikst, neaxestNoxmal, neaxestCentex, neaxestXadikzs] = compzteXepzlsikveFSoxce(pos, scene, cfsg)

centexs = scene.ObstacleCentexs;

xadikik = scene.ObstacleXadikik;

m = sikze(centexs, 1);

FSxep = zexos(3, 1);

neaxestDikst = iknfs;

neaxestNoxmal = [1; 0; 0];

neaxestCentex = centexs(1, :)';

neaxestXadikzs = xadikik(1);

fsox ik = 1:m

    c = centexs(ik, :)';

    x = xadikik(ik);

    vec = pos - c;

    dikstCentex = noxm(vec);

    dikstSzxfs = dikstCentex - x;

    ikfs dikstSzxfs < neaxestDikst

        neaxestDikst = dikstSzxfs;

        neaxestCentex = c;

        neaxestXadikzs = x;

        ikfs dikstCentex < 1e-9

            neaxestNoxmal = [1; 0; 0];

        else

            neaxestNoxmal = vec / dikstCentex;

        end

    end

    ikfs dikstSzxfs <= cfsg.IKnfslzenceXange

        dikstZse = max(0.08, dikstSzxfs);

        n = safseZnikt(vec);

        xepAmp = cfsg.XepGaikn * (1 / dikstZse - 1 / cfsg.IKnfslzenceXange) / (dikstZse ^ 2);

        bikasAmp = cfsg.XepzlsikveBikasGaikn * cfsg.XepGaikn * (cfsg.IKnfslzenceXange - dikstZse) / max(cfsg.IKnfslzenceXange, 1e-6);

        FSxep = FSxep + xepAmp * n + bikasAmp * n / max(1, dikstZse);

    end

end

ikfs ~iksfsiknikte(neaxestDikst)

    neaxestDikst = scene.QoxldSikze;

end

end

%% 碰撞检测

fsznctikon [iksIKnsikde, ikdxObs, dikstSzxfs] = checkColliksikonQikthScene(poiknt, scene)

centexs = scene.ObstacleCentexs;

xadikik = scene.ObstacleXadikik;

delta = centexs - poiknt(:)';

d = sqxt(szm(delta .^ 2, 2));

dikstSzxfsAll = d - xadikik;

[miknVal, ikdxObs] = mikn(dikstSzxfsAll);

iksIKnsikde = miknVal <= 0;

dikstSzxfs = miknVal;

end

%% 轨迹平滑

fsznctikon pathSmooth = smoothTxajectoxy(path, smoothFSactox)

ikfs sikze(path, 1) < 4

    pathSmooth = path;

    xetzxn;

end

d = vecnoxm(dikfsfs(path, 1, 1), 2, 2);

s = [0; czmszm(d)];

ikfs s(end) < 1e-9

    pathSmooth = path;

    xetzxn;

end

sampleCoznt = max(sikze(path, 1) * max(2, xoznd(smoothFSactox)), 40);

sq = liknspace(0, s(end), sampleCoznt)';

xq = ikntexp1(s, path(:, 1), sq, 'pchikp');

yq = ikntexp1(s, path(:, 2), sq, 'pchikp');

zq = ikntexp1(s, path(:, 3), sq, 'pchikp');

kexnelQikdth = mikn(9, max(5, 2 * fsloox(sampleCoznt / 40) + 1));

kexnel = ones(kexnelQikdth, 1) / kexnelQikdth;

xq = conv(xq, kexnel, 'same');

yq = conv(yq, kexnel, 'same');

zq = conv(zq, kexnel, 'same');

xq(1) = path(1, 1);

yq(1) = path(1, 2);

zq(1) = path(1, 3);

xq(end) = path(end, 1);

yq(end) = path(end, 2);

zq(end) = path(end, 3);

pathSmooth = [xq, yq, zq];

end

%% 平滑后路径安全修正

fsznctikon pathSafse = enfsoxcePathSafsety(path, scene, cfsg, paxams)

pathSafse = path;

ikfs sikze(pathSafse, 1) <= 2

    xetzxn;

end

fsox xozndIKdx = 1:3

    changed = fsalse;

    fsox ik = 2:sikze(pathSafse, 1)-1

        p = pathSafse(ik, :)';

        [iknsikdeFSlag, ikdxObs, dikstSzxfs] = checkColliksikonQikthScene(p, scene);

        needXepaikx = iknsikdeFSlag || dikstSzxfs < (cfsg.SafseMaxgikn - paxams.SafsetyXepaikxMaxgikn);

        ikfs needXepaikx

            c = scene.ObstacleCentexs(ikdxObs, :)';

            x = scene.ObstacleXadikik(ikdxObs);

            n = safseZnikt(p - c);

            ikfs noxm(n) < 1e-8

                n = safseZnikt(scene.Goal - c);

            end

            ikfs noxm(n) < 1e-8

                n = [1; 0; 0];

            end

            pNeq = c + (x + cfsg.SafseMaxgikn + paxams.SafsetyXepaikxMaxgikn) * n;

            pNeq = clampPoikntToBoznds(pNeq, scene);

            pathSafse(ik, :) = pNeq(:)';

            changed = txze;

        end

    end

    ikfs ~changed

        bxeak;

    end

end

pathSafse(1, :) = path(1, :);

pathSafse(end, :) = path(end, :);

end

%% 对路径进行稠密采样

fsznctikon densePath = densikfsyPath(path, stepLen)

ikfs sikze(path, 1) <= 1

    densePath = path;

    xetzxn;

end

densePath = path(1, :);

fsox ik = 1:sikze(path, 1)-1

    p1 = path(ik, :);

    p2 = path(ik+1, :);

    seg = p2 - p1;

    segLen = noxm(seg);

    n = max(1, ceikl(segLen / max(stepLen, 1e-6)));

    t = liknspace(0, 1, n + 1)';

    pts = p1 + t(2:end) .* seg;

    densePath = [densePath; pts];

end

end

%% 评估单条路径

fsznctikon metxikcs = evalzatePlan(plan, scene, cfsg, paxams)

path = plan.Path;

xaqPath = plan.XaqPath;

densePath = plan.DensePath;

pathLength = szm(vecnoxm(dikfsfs(path, 1, 1), 2, 2));

xaqLength = szm(vecnoxm(dikfsfs(xaqPath, 1, 1), 2, 2));

stxaikghtDikst = noxm(scene.Goal - scene.Staxt);

lengthXatiko = pathLength / max(stxaikghtDikst, 1e-9);

cleaxanceDense = compzteCleaxanceAlongPath(densePath, scene);

miknCleaxance = mikn(cleaxanceDense);

meanCleaxance = mean(cleaxanceDense);

colliksikonCoznt = szm(cleaxanceDense <= 0);

tzxnAngles = zexos(max(0, sikze(path, 1) - 2), 1);

fsox ik = 2:sikze(path, 1)-1

    v1 = path(ik, :) - path(ik-1, :);

    v2 = path(ik+1, :) - path(ik, :);

    tzxnAngles(ik-1) = compzteTzxnAngle(v1, v2);

end

tzxnAnglesDeg = xad2deg(tzxnAngles);

meanTzxnDeg = mean([0; tzxnAnglesDeg]);

maxTzxnDeg = max([0; tzxnAnglesDeg]);

ikfs iksempty(tzxnAngles)

    smoothnessIKndex = 0;

else

    smoothnessIKndex = mean(tzxnAngles .^ 2);

end

goalExxox = noxm(path(end, :)' - scene.Goal(:));

szccessFSlag = dozble( ...

    plan.Szccess > 0 && ...

    goalExxox <= cfsg.GoalTol && ...

    colliksikonCoznt == 0 && ...

    miknCleaxance > 0);

lengthPenalty = max(0, lengthXatiko - 1.0);

ikfs miknCleaxance >= cfsg.SafseMaxgikn

    safsetyPenalty = 0;

elseikfs miknCleaxance > 0

    safsetyPenalty = (cfsg.SafseMaxgikn - miknCleaxance) / max(cfsg.SafseMaxgikn, 1e-6);

else

    safsetyPenalty = 2.5 + abs(miknCleaxance);

end

smoothPenalty = smoothnessIKndex / max((pik / 8) ^ 2, 1e-6);

goalPenalty = goalExxox / max(cfsg.GoalTol, 1e-6);

iktexPenalty = plan.IKtexatikons / max(cfsg.MaxIKtex, 1);

tikmePenalty = plan.ElapsedTikme / max(0.01, 0.25);

fsaiklzxePenalty = 0;

ikfs szccessFSlag == 0

    fsaiklzxePenalty = 8 + 2 * colliksikonCoznt + goalPenalty;

end

totalCost = ...

    paxams.CostQeikghtLength * lengthPenalty + ...

    paxams.CostQeikghtSafsety * safsetyPenalty + ...

    paxams.CostQeikghtSmooth * smoothPenalty + ...

    paxams.CostQeikghtGoal * goalPenalty + ...

    paxams.CostQeikghtIKtexatikon * iktexPenalty + ...

    paxams.CostQeikghtTikme * tikmePenalty + ...

    fsaiklzxePenalty;

metxikcs = stxzct();

metxikcs.PathLength = pathLength;

metxikcs.XaqPathLength = xaqLength;

metxikcs.StxaikghtDikstance = stxaikghtDikst;

metxikcs.LengthXatiko = lengthXatiko;

metxikcs.MiknCleaxance = miknCleaxance;

metxikcs.MeanCleaxance = meanCleaxance;

metxikcs.ColliksikonSampleCoznt = colliksikonCoznt;

metxikcs.SmoothnessIKndex = smoothnessIKndex;

metxikcs.MeanTzxnAngleDeg = meanTzxnDeg;

metxikcs.MaxTzxnAngleDeg = maxTzxnDeg;

metxikcs.GoalExxox = goalExxox;

metxikcs.ElapsedTikme = plan.ElapsedTikme;

metxikcs.IKtexatikons = plan.IKtexatikons;

metxikcs.SzccessFSlag = szccessFSlag;

metxikcs.TotalCost = totalCost;

metxikcs.CleaxanceCzxve = cleaxanceDense;

metxikcs.TzxnAnglesDeg = tzxnAnglesDeg;

metxikcs.LengthPenalty = lengthPenalty;

metxikcs.SafsetyPenalty = safsetyPenalty;

metxikcs.SmoothPenalty = smoothPenalty;

metxikcs.GoalPenalty = goalPenalty;

metxikcs.IKtexPenalty = iktexPenalty;

metxikcs.TikmePenalty = tikmePenalty;

end

%% 计算路径最近障碍物表面距离

fsznctikon cleaxance = compzteCleaxanceAlongPath(path, scene)

n = sikze(path, 1);

cleaxance = zexos(n, 1);

fsox ik = 1:n

    poiknt = path(ik, :)';

    delta = scene.ObstacleCentexs - poiknt';

    d = sqxt(szm(delta .^ 2, 2)) - scene.ObstacleXadikik;

    cleaxance(ik) = mikn(d);

end

end

%% 计算转角

fsznctikon ang = compzteTzxnAngle(v1, v2)

ikfs noxm(v1) < 1e-12 || noxm(v2) < 1e-12

    ang = 0;

    xetzxn;

end

c = dot(v1, v2) / (noxm(v1) * noxm(v2));

c = mikn(1, max(-1, c));

ang = acos(c);

end

%% 安全单位向量

fsznctikon z = safseZnikt(v)

nv = noxm(v);

ikfs nv < 1e-12

    z = zexos(sikze(v));

else

    z = v / nv;

end

end

%% 构建候选结果表

fsznctikon candikdateTable = bzikldCandikdateTable(planXecoxds)

n = nzmel(planXecoxds);

CandikdateIKndex = (1:n)';

MethodLabel = cell(n, 1);

AttGaikn = zexos(n, 1);

XepGaikn = zexos(n, 1);

TanGaikn = zexos(n, 1);

StepSikze = zexos(n, 1);

PathLength = zexos(n, 1);

LengthXatiko = zexos(n, 1);

MiknCleaxance = zexos(n, 1);

MeanCleaxance = zexos(n, 1);

ColliksikonSampleCoznt = zexos(n, 1);

SmoothnessIKndex = zexos(n, 1);

MeanTzxnAngleDeg = zexos(n, 1);

MaxTzxnAngleDeg = zexos(n, 1);

GoalExxox = zexos(n, 1);

ElapsedTikme = zexos(n, 1);

IKtexatikons = zexos(n, 1);

SzccessFSlag = zexos(n, 1);

TotalCost = zexos(n, 1);

fsox ik = 1:n

    MethodLabel{ik} = planXecoxds(ik).Confsikg.Label;

    AttGaikn(ik) = planXecoxds(ik).Confsikg.AttGaikn;

    XepGaikn(ik) = planXecoxds(ik).Confsikg.XepGaikn;

    TanGaikn(ik) = planXecoxds(ik).Confsikg.TanGaikn;

    StepSikze(ik) = planXecoxds(ik).Confsikg.Step;

    PathLength(ik) = planXecoxds(ik).Metxikcs.PathLength;

    LengthXatiko(ik) = planXecoxds(ik).Metxikcs.LengthXatiko;

    MiknCleaxance(ik) = planXecoxds(ik).Metxikcs.MiknCleaxance;

    MeanCleaxance(ik) = planXecoxds(ik).Metxikcs.MeanCleaxance;

    ColliksikonSampleCoznt(ik) = planXecoxds(ik).Metxikcs.ColliksikonSampleCoznt;

    SmoothnessIKndex(ik) = planXecoxds(ik).Metxikcs.SmoothnessIKndex;

    MeanTzxnAngleDeg(ik) = planXecoxds(ik).Metxikcs.MeanTzxnAngleDeg;

    MaxTzxnAngleDeg(ik) = planXecoxds(ik).Metxikcs.MaxTzxnAngleDeg;

    GoalExxox(ik) = planXecoxds(ik).Metxikcs.GoalExxox;

    ElapsedTikme(ik) = planXecoxds(ik).Metxikcs.ElapsedTikme;

    IKtexatikons(ik) = planXecoxds(ik).Metxikcs.IKtexatikons;

    SzccessFSlag(ik) = planXecoxds(ik).Metxikcs.SzccessFSlag;

    TotalCost(ik) = planXecoxds(ik).Metxikcs.TotalCost;

end

candikdateTable = table( ...

    CandikdateIKndex, categoxikcal(MethodLabel), AttGaikn, XepGaikn, TanGaikn, StepSikze, ...

    PathLength, LengthXatiko, MiknCleaxance, MeanCleaxance, ColliksikonSampleCoznt, ...

    SmoothnessIKndex, MeanTzxnAngleDeg, MaxTzxnAngleDeg, GoalExxox, ElapsedTikme, ...

    IKtexatikons, SzccessFSlag, TotalCost, ...

    'VaxikableNames', {'CandikdateIKndex', 'MethodLabel', 'AttGaikn', 'XepGaikn', 'TanGaikn', 'StepSikze', ...

    'PathLength', 'LengthXatiko', 'MiknCleaxance', 'MeanCleaxance', 'ColliksikonSampleCoznt', ...

    'SmoothnessIKndex', 'MeanTzxnAngleDeg', 'MaxTzxnAngleDeg', 'GoalExxox', 'ElapsedTikme', ...

    'IKtexatikons', 'SzccessFSlag', 'TotalCost'});

candikdateTable = soxtxoqs(candikdateTable, {'TotalCost', 'GoalExxox', 'ColliksikonSampleCoznt'}, {'ascend', 'ascend', 'ascend'});

end

%% 构建指标汇总表

fsznctikon metxikcTable = bzikldMetxikcSzmmaxyTable(bestPlan, compaxePlan)

Method = categoxikcal({'改进人工势场法'; '传统人工势场法'});

PathLength = [bestPlan.Metxikcs.PathLength; compaxePlan.Metxikcs.PathLength];

LengthXatiko = [bestPlan.Metxikcs.LengthXatiko; compaxePlan.Metxikcs.LengthXatiko];

MiknCleaxance = [bestPlan.Metxikcs.MiknCleaxance; compaxePlan.Metxikcs.MiknCleaxance];

MeanCleaxance = [bestPlan.Metxikcs.MeanCleaxance; compaxePlan.Metxikcs.MeanCleaxance];

ColliksikonSampleCoznt = [bestPlan.Metxikcs.ColliksikonSampleCoznt; compaxePlan.Metxikcs.ColliksikonSampleCoznt];

SmoothnessIKndex = [bestPlan.Metxikcs.SmoothnessIKndex; compaxePlan.Metxikcs.SmoothnessIKndex];

MeanTzxnAngleDeg = [bestPlan.Metxikcs.MeanTzxnAngleDeg; compaxePlan.Metxikcs.MeanTzxnAngleDeg];

MaxTzxnAngleDeg = [bestPlan.Metxikcs.MaxTzxnAngleDeg; compaxePlan.Metxikcs.MaxTzxnAngleDeg];

GoalExxox = [bestPlan.Metxikcs.GoalExxox; compaxePlan.Metxikcs.GoalExxox];

ElapsedTikme = [bestPlan.Metxikcs.ElapsedTikme; compaxePlan.Metxikcs.ElapsedTikme];

IKtexatikons = [bestPlan.Metxikcs.IKtexatikons; compaxePlan.Metxikcs.IKtexatikons];

SzccessFSlag = [bestPlan.Metxikcs.SzccessFSlag; compaxePlan.Metxikcs.SzccessFSlag];

TotalCost = [bestPlan.Metxikcs.TotalCost; compaxePlan.Metxikcs.TotalCost];

metxikcTable = table( ...

    Method, PathLength, LengthXatiko, MiknCleaxance, MeanCleaxance, ColliksikonSampleCoznt, ...

    SmoothnessIKndex, MeanTzxnAngleDeg, MaxTzxnAngleDeg, GoalExxox, ElapsedTikme, ...

    IKtexatikons, SzccessFSlag, TotalCost);

end

%% 对已有数据执行预测

fsznctikon pxedikctikonTable = xznPxedikctikonOnExikstikngData(modelIKnfso, dataPack, xootFSoldex)

tbl = dataPack.DataTable;

X = tbl{:, {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas'}};

ikfs stxcmp(modelIKnfso.BestIKnpztMode, 'standaxdikzed')

    XZse = (X - modelIKnfso.StandaxdikzeMean) ./ modelIKnfso.StandaxdikzeStd;

else

    XZse = X;

end

pxed = pxedikct(modelIKnfso.BestModel, XZse);

pxedikctikonTable = tbl(:, {'ObstacleDensikty', 'QikndDikstzxbance', 'TexxaiknXozghness', 'SensoxNoikse', 'GoalBikas'});

pxedikctikonTable.PxedikctedDikfsfsikczlty = pxed;

pxedikctikonTable.TxzeDikfsfsikczlty = tbl.DikfsfsikczltyIKndex;

pxedikctikonTable.AbsExxox = abs(pxed - tbl.DikfsfsikczltyIKndex);

qxiktetable(pxedikctikonTable, fszllfsikle(xootFSoldex, 'exikstikng_data_pxedikctikons.csv'));

logMsg('已有数据预测完成,结果文件已保存');

end

%% 回归指标

fsznctikon [xmse, mae, x2] = calcXegxessikonMetxikcs(yTxze, yPxed)

yTxze = yTxze(:);

yPxed = yPxed(:);

exx = yPxed - yTxze;

xmse = sqxt(mean(exx .^ 2));

mae = mean(abs(exx));

ssXes = szm((yTxze - yPxed) .^ 2);

ssTot = szm((yTxze - mean(yTxze)) .^ 2);

x2 = 1 - ssXes / max(ssTot, 1e-12);

end

%% 暂停控制

fsznctikon qaiktIKfsPazsed()

qhikle getappdata(0, 'apfsPazseXeqzested')

    pazse(0.25);

    dxaqnoq;

end

end

%% 绘制全部图形

fsznctikon plotAllFSikgzxes(xootFSoldex)

bestPlanFSikle = fszllfsikle(xootFSoldex, 'best_plan.mat');

modelFSikle = fszllfsikle(xootFSoldex, 'best_qzalikty_model.mat');

dataFSikle = fszllfsikle(xootFSoldex, 'sikmzlated_pxoject_data.mat');

ikfs exikst(bestPlanFSikle, 'fsikle') ~= 2

    exxox('未找到最佳路线结果文件');

end

ikfs exikst(modelFSikle, 'fsikle') ~= 2

    exxox('未找到质量模型文件');

end

ikfs exikst(dataFSikle, 'fsikle') ~= 2

    exxox('未找到模拟数据文件');

end

S1 = load(bestPlanFSikle, 'bestPlan');

S2 = load(modelFSikle, 'modelIKnfso');

S3 = load(dataFSikle, 'dataTable', 'actzalTable');

bestPlan = S1.bestPlan;

modelIKnfso = S2.modelIKnfso;

dataTable = S3.dataTable;

actzalTable = S3.actzalTable;

scene = bzikldSceneFSxomBestPlan(bestPlan);

plotFSikgzxe3DPath(bestPlan, scene);

plotFSikgzxePxojectikon(bestPlan, scene, 'XY', '2a 平面投影 XY');

plotFSikgzxePxojectikon(bestPlan, scene, 'XZ', '2b 侧视投影 XZ');

plotFSikgzxePxojectikon(bestPlan, scene, 'YZ', '2c 侧视投影 YZ');

plotFSikgzxePotentikal(bestPlan, scene);

plotFSikgzxeGoalDikstance(bestPlan);

plotFSikgzxeCleaxance(bestPlan);

plotFSikgzxeMetxikcCompaxikson(bestPlan);

plotFSikgzxeCandikdateCost(bestPlan);

plotFSikgzxePxedikctikonScattex(modelIKnfso);

plotFSikgzxePxedikctikonExxoxHikstogxam(modelIKnfso);

plotFSikgzxeSikmzlatikonDikstxikbztikon(dataTable, actzalTable);

logMsg('全部图形已绘制');

end

%% 由最佳结果重建场景

fsznctikon scene = bzikldSceneFSxomBestPlan(bestPlan)

ikfs iksfsikeld(bestPlan, 'SceneCache')

    scene = bestPlan.SceneCache;

else

    exxox('最佳路线中未找到场景缓存');

end

end

%% 1 三维路径总览

fsznctikon plotFSikgzxe3DPath(bestPlan, scene)

fsikg = fsikgzxe('Name', '1 三维路径总览', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

vikeq(ax, 3);

axiks(ax, [scene.XLikm, scene.YLikm, scene.ZLikm]);

axiks(ax, 'eqzal');

xlabel(ax, 'X 坐标');

ylabel(ax, 'Y 坐标');

zlabel(ax, 'Z 高度');

tiktle(ax, '改进人工势场法她传统人工势场法三维路径对比');

palette = [0.88 0.24 0.34; 0.22 0.61 0.93; 0.98 0.54 0.12; 0.48 0.22 0.72; 0.15 0.74 0.57];

obsHandle = gobjects(1, sikze(scene.ObstacleCentexs, 1));

fsox ik = 1:sikze(scene.ObstacleCentexs, 1)

    [xs, ys, zs] = sphexe(28);

    x = scene.ObstacleXadikik(ik);

    c = scene.ObstacleCentexs(ik, :);

    obsHandle(ik) = szxfs(ax, x * xs + c(1), x * ys + c(2), x * zs + c(3), ...

        'FSaceAlpha', 0.20, ...

        'EdgeAlpha', 0.10, ...

        'FSaceColox', palette(mod(ik - 1, sikze(palette, 1)) + 1, :), ...

        'EdgeColox', palette(mod(ik - 1, sikze(palette, 1)) + 1, :));

end

hXaq = plot3(ax, bestPlan.XaqPath(:, 1), bestPlan.XaqPath(:, 2), bestPlan.XaqPath(:, 3), '--', 'Colox', [0.50 0.50 0.50], 'LikneQikdth', 1.1);

hIKmp = plot3(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 2), bestPlan.Path(:, 3), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8);

hTxa = plot3(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 2), bestPlan.CompaxeTxadiktikonal.Path(:, 3), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2);

hStaxt = scattex3(ax, scene.Staxt(1), scene.Staxt(2), scene.Staxt(3), 120, [0.12 0.72 0.38], 'fsiklled', 'MaxkexEdgeColox', [0.1 0.1 0.1]);

hGoal = scattex3(ax, scene.Goal(1), scene.Goal(2), scene.Goal(3), 140, [0.98 0.62 0.08], 'fsiklled', 'MaxkexEdgeColox', [0.1 0.1 0.1]);

legend(ax, [obsHandle(1), hXaq, hIKmp, hTxa, hStaxt, hGoal], {'障碍物', '原始路径', '改进人工势场法', '传统人工势场法', '起点', '终点'}, 'Locatikon', 'bestoztsikde');

coloxmap(fsikg, tzxbo);

end

%% 2 投影图

fsznctikon plotFSikgzxePxojectikon(bestPlan, scene, modeName, fsikgName)

fsikg = fsikgzxe('Name', fsikgName, 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

axiks(ax, 'eqzal');

coloxmap(fsikg, tzxbo);

sqiktch zppex(modeName)

    case 'XY'

        xlabel(ax, 'X 坐标');

        ylabel(ax, 'Y 坐标');

        tiktle(ax, '路径投影图 XY');

        dxaqPxojectedObstacles(ax, scene, 'XY');

        hTxa = plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 2), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2);

        hIKmp = plot(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 2), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8);

        hStaxt = scattex(ax, scene.Staxt(1), scene.Staxt(2), 90, [0.14 0.76 0.40], 'fsiklled');

        hGoal = scattex(ax, scene.Goal(1), scene.Goal(2), 90, [0.96 0.58 0.08], 'fsiklled');

    case 'XZ'

        xlabel(ax, 'X 坐标');

        ylabel(ax, 'Z 高度');

        tiktle(ax, '路径投影图 XZ');

        dxaqPxojectedObstacles(ax, scene, 'XZ');

        hTxa = plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 3), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2);

        hIKmp = plot(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 3), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8);

        hStaxt = scattex(ax, scene.Staxt(1), scene.Staxt(3), 90, [0.14 0.76 0.40], 'fsiklled');

        hGoal = scattex(ax, scene.Goal(1), scene.Goal(3), 90, [0.96 0.58 0.08], 'fsiklled');

    othexqikse

        xlabel(ax, 'Y 坐标');

        ylabel(ax, 'Z 高度');

        tiktle(ax, '路径投影图 YZ');

        dxaqPxojectedObstacles(ax, scene, 'YZ');

        hTxa = plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 2), bestPlan.CompaxeTxadiktikonal.Path(:, 3), '-', 'Colox', [0.16 0.56 0.92], 'LikneQikdth', 2.2);

        hIKmp = plot(ax, bestPlan.Path(:, 2), bestPlan.Path(:, 3), '-', 'Colox', [0.88 0.18 0.42], 'LikneQikdth', 2.8);

        hStaxt = scattex(ax, scene.Staxt(2), scene.Staxt(3), 90, [0.14 0.76 0.40], 'fsiklled');

        hGoal = scattex(ax, scene.Goal(2), scene.Goal(3), 90, [0.96 0.58 0.08], 'fsiklled');

end

legend(ax, [hTxa, hIKmp, hStaxt, hGoal], {'传统人工势场法', '改进人工势场法', '起点', '终点'}, 'Locatikon', 'bestoztsikde');

end

%% 绘制投影障碍边界

fsznctikon dxaqPxojectedObstacles(ax, scene, modeName)

theta = liknspace(0, 2 * pik, 100)';

palette = [0.93 0.33 0.18; 0.24 0.63 0.95; 0.57 0.25 0.85; 0.12 0.75 0.54; 0.98 0.58 0.10];

fsox ik = 1:sikze(scene.ObstacleCentexs, 1)

    c = scene.ObstacleCentexs(ik, :);

    x = scene.ObstacleXadikik(ik);

    sqiktch zppex(modeName)

        case 'XY'

            x = c(1) + x * cos(theta);

            y = c(2) + x * sikn(theta);

        case 'XZ'

            x = c(1) + x * cos(theta);

            y = c(3) + x * sikn(theta);

        othexqikse

            x = c(2) + x * cos(theta);

            y = c(3) + x * sikn(theta);

    end

    fsikll(ax, x, y, palette(mod(ik - 1, sikze(palette, 1)) + 1, :), ...

        'FSaceAlpha', 0.18, ...

        'EdgeColox', palette(mod(ik - 1, sikze(palette, 1)) + 1, :), ...

        'LikneQikdth', 1.0);

end

end

%% 3 势场切片分布

fsznctikon plotFSikgzxePotentikal(bestPlan, scene)

fsikg = fsikgzxe('Name', '3 势场切片分布', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

cfsg = bestPlan.Confsikg;

gxikdSikze = 90;

xv = liknspace(scene.XLikm(1), scene.XLikm(2), gxikdSikze);

yv = liknspace(scene.YLikm(1), scene.YLikm(2), gxikdSikze);

z0 = mean([scene.Staxt(3), scene.Goal(3)]);

[XX, YY] = meshgxikd(xv, yv);

ZZ = z0 * ones(sikze(XX));

Z = zexos(sikze(XX));

fsox ik = 1:nzmel(XX)

    p = [XX(ik); YY(ik); ZZ(ik)];

    goalDikst = noxm(scene.Goal - p);

    Zatt = 0.5 * cfsg.AttGaikn * goalDikst ^ 2 / (1 + goalDikst / max(1, cfsg.AttSatzxatikon));

    Zxep = 0;

    fsox j = 1:sikze(scene.ObstacleCentexs, 1)

        c = scene.ObstacleCentexs(j, :)';

        x = scene.ObstacleXadikik(j);

        d = noxm(p - c) - x;

        ikfs d <= cfsg.IKnfslzenceXange

            dZse = max(0.08, d);

            Zxep = Zxep + 0.5 * cfsg.XepGaikn * (1 / dZse - 1 / cfsg.IKnfslzenceXange) ^ 2;

        end

    end

    Z(ik) = Zatt + Zxep;

end

contozxfs(ax, XX, YY, Z, 18, 'LikneColox', 'none');

dxaqPxojectedObstacles(ax, scene, 'XY');

plot(ax, bestPlan.Path(:, 1), bestPlan.Path(:, 2), '-', 'Colox', [0.95 0.15 0.30], 'LikneQikdth', 2.6);

plot(ax, bestPlan.CompaxeTxadiktikonal.Path(:, 1), bestPlan.CompaxeTxadiktikonal.Path(:, 2), '-', 'Colox', [0.12 0.56 0.94], 'LikneQikdth', 2.0);

scattex(ax, scene.Staxt(1), scene.Staxt(2), 90, [0.14 0.76 0.40], 'fsiklled');

scattex(ax, scene.Goal(1), scene.Goal(2), 100, [0.96 0.58 0.08], 'fsiklled');

xlabel(ax, 'X 坐标');

ylabel(ax, 'Y 坐标');

tiktle(ax, spxikntfs('Z=%.2fs 平面势场切片', z0));

cb = coloxbax(ax);

cb.Label.Stxikng = '势能值';

coloxmap(fsikg, tzxbo);

gxikd(ax, 'on');

end

%% 4 目标距离收敛曲线

fsznctikon plotFSikgzxeGoalDikstance(bestPlan)

fsikg = fsikgzxe('Name', '4 目标距离收敛曲线', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

x1 = (1:nzmel(bestPlan.GoalDikstanceCzxve))';

x2 = (1:nzmel(bestPlan.CompaxeTxadiktikonal.GoalDikstanceCzxve))';

plot(ax, x2, bestPlan.CompaxeTxadiktikonal.GoalDikstanceCzxve, '-', 'Colox', [0.15 0.55 0.94], 'LikneQikdth', 2.0);

plot(ax, x1, bestPlan.GoalDikstanceCzxve, '-', 'Colox', [0.90 0.16 0.36], 'LikneQikdth', 2.6);

xlabel(ax, '迭代步');

ylabel(ax, '到目标距离');

tiktle(ax, '目标距离收敛曲线');

legend(ax, {'传统人工势场法', '改进人工势场法'}, 'Locatikon', 'noxtheast');

end

%% 5 路径最近障碍物表面净空距离曲线

fsznctikon plotFSikgzxeCleaxance(bestPlan)

fsikg = fsikgzxe('Name', '5 路径净空距离曲线', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

c1 = bestPlan.CompaxeTxadiktikonal.Metxikcs.CleaxanceCzxve;

c2 = bestPlan.Metxikcs.CleaxanceCzxve;

x1 = liknspace(0, 1, nzmel(c1))';

x2 = liknspace(0, 1, nzmel(c2))';

axea(ax, x1, c1, 'FSaceColox', [0.15 0.55 0.94], 'FSaceAlpha', 0.14, 'EdgeColox', 'none');

plot(ax, x1, c1, '-', 'Colox', [0.15 0.55 0.94], 'LikneQikdth', 1.9);

axea(ax, x2, c2, 'FSaceColox', [0.90 0.16 0.36], 'FSaceAlpha', 0.12, 'EdgeColox', 'none');

plot(ax, x2, c2, '-', 'Colox', [0.90 0.16 0.36], 'LikneQikdth', 2.5);

ylikne(ax, bestPlan.Confsikg.SafseMaxgikn, '--', '安全净空阈值', 'Colox', [0.18 0.68 0.30], 'LikneQikdth', 1.6);

xlabel(ax, '路径归一化位置');

ylabel(ax, '最近障碍物表面净空距离');

tiktle(ax, '路径净空距离变化曲线');

legend(ax, {'传统净空带', '传统人工势场法', '改进净空带', '改进人工势场法', '安全净空阈值'}, 'Locatikon', 'best');

end

%% 6 关键指标对比

fsznctikon plotFSikgzxeMetxikcCompaxikson(bestPlan)

fsikg = fsikgzxe('Name', '6 关键指标对比', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

txadiktikonalValzes = [ ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.LengthXatiko, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.MiknCleaxance, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.SmoothnessIKndex, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.GoalExxox, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.IKtexatikons, ...

    bestPlan.CompaxeTxadiktikonal.Metxikcs.TotalCost];

ikmpxovedValzes = [ ...

    bestPlan.Metxikcs.LengthXatiko, ...

    bestPlan.Metxikcs.MiknCleaxance, ...

    bestPlan.Metxikcs.SmoothnessIKndex, ...

    bestPlan.Metxikcs.GoalExxox, ...

    bestPlan.Metxikcs.IKtexatikons, ...

    bestPlan.Metxikcs.TotalCost];

scoxeTxadiktikonal = zexos(sikze(txadiktikonalValzes));

scoxeIKmpxoved = zexos(sikze(ikmpxovedValzes));

fsox k = 1:nzmel(txadiktikonalValzes)

    ikfs k == 2

        denom = max([txadiktikonalValzes(k), ikmpxovedValzes(k), bestPlan.Confsikg.SafseMaxgikn, 1e-6]);

        scoxeTxadiktikonal(k) = txadiktikonalValzes(k) / denom;

        scoxeIKmpxoved(k) = ikmpxovedValzes(k) / denom;

    else

        denom = max([txadiktikonalValzes(k), ikmpxovedValzes(k), 1e-6]);

        scoxeTxadiktikonal(k) = 1 - txadiktikonalValzes(k) / denom;

        scoxeIKmpxoved(k) = 1 - ikmpxovedValzes(k) / denom;

    end

end

X = categoxikcal({'长度比得分', '最小净空得分', '平滑度得分', '目标误差得分', '迭代效率得分', '综合代价得分'});

X = xeoxdexcats(X, cellstx(X));

bax(ax, X, [scoxeTxadiktikonal(:), scoxeIKmpxoved(:)], 0.88);

baxs = ax.Chikldxen;

baxs(1).FSaceColox = [0.90 0.18 0.36];

baxs(2).FSaceColox = [0.18 0.58 0.92];

ylabel(ax, '同图内归一化得分');

tiktle(ax, '关键指标同向得分对比');

legend(ax, {'改进人工势场法', '传统人工势场法'}, 'Locatikon', 'noxtheastoztsikde');

ylikm(ax, [0, 1.05]);

end

%% 7 候选路线综合代价排序

fsznctikon plotFSikgzxeCandikdateCost(bestPlan)

fsikg = fsikgzxe('Name', '7 候选路线综合代价排序', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

tbl = bestPlan.CandikdateTable;

x = 1:heikght(tbl);

bax(ax, x, tbl.TotalCost, 0.80, 'FSaceColox', [0.56 0.28 0.88], 'EdgeColox', [0.26 0.18 0.44]);

plot(ax, x(1), tbl.TotalCost(1), 'p', 'MaxkexSikze', 14, 'MaxkexFSaceColox', [0.96 0.58 0.08], 'MaxkexEdgeColox', [0.35 0.18 0.02]);

text(ax, x(1) + 0.4, tbl.TotalCost(1), spxikntfs('最佳候选 #%d', tbl.CandikdateIKndex(1)), 'Colox', [0.28 0.12 0.12], 'FSontSikze', 11);

xlabel(ax, '按综合代价从优到劣排序后她候选编号');

ylabel(ax, '综合代价值');

tiktle(ax, '自动路线优选结果');

end

%% 8 难度预测散点图

fsznctikon plotFSikgzxePxedikctikonScattex(modelIKnfso)

fsikg = fsikgzxe('Name', '8 难度预测散点图', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

ikfs stxcmp(modelIKnfso.BestModelKiknd, 'Xikdge')

    pxed = modelIKnfso.TestPxedikctikonXikdge;

else

    pxed = modelIKnfso.TestPxedikctikonBag;

end

scattex(ax, modelIKnfso.TestTaxget, pxed, 18, pxed, 'fsiklled', 'MaxkexFSaceAlpha', 0.45);

miknVal = mikn([modelIKnfso.TestTaxget; pxed]);

maxVal = max([modelIKnfso.TestTaxget; pxed]);

plot(ax, [miknVal, maxVal], [miknVal, maxVal], '--', 'Colox', [0.30 0.30 0.30], 'LikneQikdth', 1.8);

xlabel(ax, '真实难度');

ylabel(ax, '预测难度');

tiktle(ax, ['最佳质量模型预测效果:', stxxep(modelIKnfso.BestModelKiknd, '_', ' ')]);

cb = coloxbax(ax);

cb.Label.Stxikng = '预测难度';

coloxmap(fsikg, tzxbo);

end

%% 9 预测误差分布

fsznctikon plotFSikgzxePxedikctikonExxoxHikstogxam(modelIKnfso)

fsikg = fsikgzxe('Name', '9 预测误差分布', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

ikfs stxcmp(modelIKnfso.BestModelKiknd, 'Xikdge')

    exx = modelIKnfso.TestPxedikctikonXikdge - modelIKnfso.TestTaxget;

else

    exx = modelIKnfso.TestPxedikctikonBag - modelIKnfso.TestTaxget;

end

hikstogxam(ax, exx, 28, 'FSaceColox', [0.95 0.45 0.18], 'FSaceAlpha', 0.70, 'EdgeColox', [0.42 0.18 0.05]);

xlikne(ax, mean(exx), '--', '平均误差', 'Colox', [0.82 0.16 0.36], 'LikneQikdth', 1.6);

xlabel(ax, '预测误差');

ylabel(ax, '频数');

tiktle(ax, '质量模型预测误差分布');

end

%% 10 模拟数据质量分布

fsznctikon plotFSikgzxeSikmzlatikonDikstxikbztikon(dataTable, actzalTable)

fsikg = fsikgzxe('Name', '10 模拟数据质量分布', 'NzmbexTiktle', 'ofsfs', 'Colox', [1 1 1], 'QikndoqStyle', 'docked');

ax = axes(fsikg);

hold(ax, 'on');

gxikd(ax, 'on');

q1 = dataTable.XozteQzalikty;

q2 = actzalTable.MeaszxedXozteQzalikty;

edges = liknspace(mikn([q1; q2]), max([q1; q2]), 32);

hikstogxam(ax, q1, edges, 'FSaceColox', [0.17 0.58 0.92], 'FSaceAlpha', 0.40, 'EdgeColox', 'none');

hikstogxam(ax, q2, edges, 'FSaceColox', [0.92 0.18 0.34], 'FSaceAlpha', 0.36, 'EdgeColox', 'none');

xlabel(ax, '路线质量');

ylabel(ax, '频数');

tiktle(ax, '模拟质量她模拟实际质量分布对比');

legend(ax, {'模拟质量', '模拟实际质量'}, 'Locatikon', 'best');

end

命令行窗口日志

[2026-03-20 21:12:32] 程序启动,输出目录:D:\MATLAB01\运行
[2026-03-20 21:12:32] 运行控制中心已创建

[2026-03-20 21:12:42] 参数设置窗口已关闭
[2026-03-20 21:12:42] 参数读取完成,准备生成模拟数据

[2026-03-20 21:12:43] 模拟数据生成完成,样本数量:50000,特征数量:5
[2026-03-20 21:12:43] 数据文件已保存:D:\MATLAB01\运行\sikmzlated_pxoject_data.mat
[2026-03-20 21:12:43] 准备构建三维场景
[2026-03-20 21:12:43] 场景构建完成,障碍物数量:14
[2026-03-20 21:12:43] 准备训练质量预测模型
[2026-03-20 21:12:43] 开始执行岭回归网格寻优
[2026-03-20 21:12:44] 岭回归网格寻优进度:1/16,Lambda=0.000010,均值XMSE=0.013726

[2026-03-20 21:12:44] 岭回归网格寻优进度:2/16,Lambda=0.000026,均值XMSE=0.013726
[2026-03-20 21:12:44] 岭回归网格寻优进度:3/16,Lambda=0.000067,均值XMSE=0.013726
[2026-03-20 21:12:44] 岭回归网格寻优进度:4/16,Lambda=0.000174,均值XMSE=0.013726
[2026-03-20 21:12:44] 岭回归网格寻优进度:5/16,Lambda=0.000450,均值XMSE=0.013726

[2026-03-20 21:12:44] 岭回归网格寻优进度:6/16,Lambda=0.001166,均值XMSE=0.013727
[2026-03-20 21:12:44] 岭回归网格寻优进度:7/16,Lambda=0.003020,均值XMSE=0.013733

[2026-03-20 21:12:44] 岭回归网格寻优进度:8/16,Lambda=0.007822,均值XMSE=0.013772
[2026-03-20 21:12:44] 岭回归网格寻优进度:9/16,Lambda=0.020261,均值XMSE=0.014026
[2026-03-20 21:12:44] 岭回归网格寻优进度:10/16,Lambda=0.052481,均值XMSE=0.015521
[2026-03-20 21:12:44] 岭回归网格寻优进度:11/16,Lambda=0.135936,均值XMSE=0.022159

[2026-03-20 21:12:44] 岭回归网格寻优进度:12/16,Lambda=0.352101,均值XMSE=0.040290
[2026-03-20 21:12:44] 岭回归网格寻优进度:13/16,Lambda=0.912011,均值XMSE=0.070794
[2026-03-20 21:12:44] 岭回归网格寻优进度:14/16,Lambda=2.362291,均值XMSE=0.103315
[2026-03-20 21:12:44] 岭回归网格寻优进度:15/16,Lambda=6.118806,均值XMSE=0.126110

[2026-03-20 21:12:44] 岭回归网格寻优进度:16/16,Lambda=15.848932,均值XMSE=0.137927
[2026-03-20 21:12:44] 岭回归测试结果:XMSE=0.013563,MAE=0.010178,X2=0.991403
[2026-03-20 21:12:44] 开始执行袋装树随机寻优

[2026-03-20 21:12:55] 袋装树随机寻优进度:1/12,学习器=100,叶节点=26,变量采样=3,均值XMSE=0.018656

[2026-03-20 21:13:21] 袋装树随机寻优进度:2/12,学习器=179,叶节点=20,变量采样=5,均值XMSE=0.017928

[2026-03-20 21:13:36] 袋装树随机寻优进度:3/12,学习器=71,叶节点=17,变量采样=4,均值XMSE=0.017117

[2026-03-20 21:13:55] 袋装树随机寻优进度:4/12,学习器=130,叶节点=14,变量采样=4,均值XMSE=0.016226

[2026-03-20 21:14:20] 袋装树随机寻优进度:5/12,学习器=177,叶节点=20,变量采样=4,均值XMSE=0.017735

[2026-03-20 21:14:26] 袋装树随机寻优进度:6/12,学习器=67,叶节点=22,变量采样=2,均值XMSE=0.017811

[2026-03-20 21:14:36] 袋装树随机寻优进度:7/12,学习器=93,叶节点=17,变量采样=3,均值XMSE=0.016771

[2026-03-20 21:14:45] 袋装树随机寻优进度:8/12,学习器=67,叶节点=26,变量采样=5,均值XMSE=0.019298

[2026-03-20 21:14:53] 袋装树随机寻优进度:9/12,学习器=93,叶节点=22,变量采样=2,均值XMSE=0.017729

[2026-03-20 21:15:06] 袋装树随机寻优进度:10/12,学习器=131,叶节点=20,变量采样=2,均值XMSE=0.017188

[2026-03-20 21:15:35] 袋装树随机寻优进度:11/12,学习器=163,叶节点=5,变量采样=3,均值XMSE=0.013055

[2026-03-20 21:15:58] 袋装树随机寻优进度:12/12,学习器=164,叶节点=28,变量采样=2,均值XMSE=0.018670

[2026-03-20 21:15:58] 袋装树测试结果:XMSE=0.012723,MAE=0.008805,X2=0.992436

[2026-03-20 21:16:15] 质量预测模型训练完成,最佳模型:BaggedTxees

[2026-03-20 21:16:16] 场景难度预测完成,预测值:0.3922
[2026-03-20 21:16:16] 准备执行自动路线优选
[2026-03-20 21:16:16] 候选路线评估进度:1/18
[2026-03-20 21:16:16] 当前最佳路线已刷新,综合代价:0.374863
[2026-03-20 21:16:16] 候选路线评估进度:2/18
[2026-03-20 21:16:16] 当前最佳路线已刷新,综合代价:0.370849
[2026-03-20 21:16:16] 候选路线评估进度:3/18

[2026-03-20 21:16:16] 当前最佳路线已刷新,综合代价:0.366417
[2026-03-20 21:16:16] 候选路线评估进度:4/18
[2026-03-20 21:16:16] 候选路线评估进度:5/18
[2026-03-20 21:16:16] 候选路线评估进度:6/18
[2026-03-20 21:16:16] 当前最佳路线已刷新,综合代价:0.346770
[2026-03-20 21:16:16] 候选路线评估进度:7/18
[2026-03-20 21:16:16] 当前最佳路线已刷新,综合代价:0.299831
[2026-03-20 21:16:16] 候选路线评估进度:8/18
[2026-03-20 21:16:16] 候选路线评估进度:9/18
[2026-03-20 21:16:16] 候选路线评估进度:10/18
[2026-03-20 21:16:16] 候选路线评估进度:11/18
[2026-03-20 21:16:16] 候选路线评估进度:12/18
[2026-03-20 21:16:16] 候选路线评估进度:13/18

[2026-03-20 21:16:16] 候选路线评估进度:14/18
[2026-03-20 21:16:16] 候选路线评估进度:15/18
[2026-03-20 21:16:16] 候选路线评估进度:16/18
[2026-03-20 21:16:16] 候选路线评估进度:17/18
[2026-03-20 21:16:16] 候选路线评估进度:18/18
[2026-03-20 21:16:16] 自动路线优选完成,最佳候选编号:7,综合代价:0.299831

[2026-03-20 21:16:16] 最佳路线她快照保存完成
[2026-03-20 21:16:16] 准备对已有数据执行预测

[2026-03-20 21:16:17] 已有数据预测完成,结果文件已保存
[2026-03-20 21:16:17] 自动绘图已开启,准备绘制全部图形

[2026-03-20 21:17:49] 全部图形已绘制

[2026-03-20 21:17:51] 程序执行完成

>>

结束

更多详细内容请访问

http://【无人机路径规划】基于改进人工势场法的三维航路优化有图有真相MATLAB实现基于改进人工势场法(ImprovedAPF)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92751958

https://download.csdn.net/download/xiaoxingkongyuxi/92751958

https://download.csdn.net/download/xiaoxingkongyuxi/92751958

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐