2024年最新5种优化算法实战:用MATLAB搞定多无人机协同路径规划(附完整代码)

最近在做一个无人机集群协同巡检的项目,客户要求我们不仅要规划出单架无人机的安全路径,还得让多架无人机在复杂的三维空间里高效协同,不能撞上障碍物,更不能互相干扰。传统的规划方法要么计算量太大,要么容易陷入局部最优,规划出的路径要么不够平滑,要么总长度太长,费时又费电。为了解决这个问题,我把目光投向了2024年最新发表的几种元启发式优化算法,它们各有各的“绝活”,在解决这类高维、多约束的复杂优化问题上展现出了惊人的潜力。

这篇文章,我就结合自己近期的项目实践,带你一起上手这五种前沿算法:海市蜃楼搜索优化(MSO)阿尔法进化(AE)梦境优化算法(DOA)山羊优化算法(GOA)牛优化算法(OX)。我不会过多纠结于复杂的数学推导,而是聚焦于如何用MATLAB快速搭建一个可运行、可测试、可比较的仿真环境。我会分享从环境建模、算法参数调优到结果可视化的完整流程,并提供可以直接运行的代码框架。无论你是正在寻找解决方案的工程师,还是希望将最新算法应用于自己研究课题的学者,这篇文章都能给你带来直接的、可操作的参考价值。

1. 搭建你的多无人机协同规划仿真环境

在开始“炼丹”(调参跑算法)之前,得先把“炉子”(仿真环境)搭好。一个清晰、模块化的环境模型,不仅能让你快速验证算法,也便于后续的扩展和对比。

1.1 三维环境与威胁建模

我们首先需要在MATLAB中构建一个三维的飞行空间。这个空间不是空的,里面布满了圆柱体障碍物,模拟现实中的高楼、烟囱或禁飞区。每个障碍物我们用中心坐标、半径和高度来定义。

% 文件:Create_Model.m
function model = Create_Model()
    % 定义三维空间的边界 [x_min, x_max; y_min, y_max; z_min, z_max]
    model.space_limit = [0, 1000; 0, 1000; 0, 300];

    % 定义威胁(圆柱体障碍物)参数
    % 每列代表一个威胁: [x_center; y_center; radius; height]
    model.threats = [
        300, 400, 50, 200;
        600, 200, 80, 180;
        800, 700, 60, 220;
        400, 600, 70, 150;
        200, 800, 40, 170
    ]';

    % 无人机物理参数
    model.UAV_radius = 5;      % 无人机等效半径(安全包络)
    model.safe_distance = 20;  % 与障碍物保持的最小安全距离
    model.max_climb_angle = 30 * pi/180; % 最大爬升角(弧度)
    model.max_turn_angle = 60 * pi/180;  % 最大转弯角(弧度)
    model.min_height = 50;     % 最低飞行高度
    model.max_height = 250;    % 最高飞行高度
end

注意:这里的威胁建模为圆柱体是出于计算简便的考虑。在实际项目中,你可能需要导入更复杂的三维网格地图(如STL文件)或点云数据,这时碰撞检测的逻辑会更为复杂。

1.2 多无人机任务定义与初始化

接下来,我们需要定义每架无人机的任务,即它的起点和终点。同时,要为每架无人机创建一个独立的任务模型副本,确保它们在规划时共享全局环境信息,但拥有独立的路径变量。

% 文件:Initialize_UAV_Tasks.m
function ModelUAV = Initialize_UAV_Tasks(base_model, UAV_num)
    ModelUAV = struct('model', {}, 'path', {}, 'cost', {});
    for i = 1:UAV_num
        ModelUAV(i).model = base_model; % 共享环境模型
        ModelUAV(i).path = []; % 待优化的路径点序列
        ModelUAV(i).cost = inf; % 初始成本设为无穷大
    end

    % 示例:手动定义4架无人机的起终点
    % 格式:[start_x, start_y, start_z; end_x, end_y, end_z]
    task_list = [
        120, 200, 100,  800, 800, 150;
        400, 100, 100,  900, 600, 150;
        200, 150, 150,  850, 750, 150;
        100, 100, 150,  800, 730, 150
    ];

    for i = 1:min(UAV_num, size(task_list,1))
        ModelUAV(i).model.start = task_list(i, 1:3)';
        ModelUAV(i).model.end = task_list(i, 4:6)';
    end
end

这种结构化的设计好处很明显:增加或减少无人机数量只需修改 UAV_numtask_list;每架无人机的路径是独立的决策变量,方便并行计算;同时,所有无人机模型都引用同一个环境数据,保证了空间一致性。

1.3 成本函数设计:平衡效率与安全

成本函数是优化算法的“指挥棒”,它告诉算法什么是好的路径。对于多无人机协同规划,我们需要综合考虑四个方面:

  1. 路径长度成本:总飞行距离越短越好,节省时间和能源。
  2. 威胁碰撞成本:路径必须远离障碍物,一旦进入危险区域则施加巨大惩罚。
  3. 高度偏离成本:鼓励无人机在安全高度层内飞行,并尽量靠近理想巡航高度。
  4. 路径平滑成本:限制过大的转弯角和爬升率变化,保证飞行的可行性和舒适性。

我们将这四个成本加权求和,作为单架无人机的适应度值。多机协同的总成本就是所有无人机成本之和。这意味着算法在优化时,会同时优化所有无人机的路径,自动规避机间冲突(因为撞机也会导致威胁成本激增)。

% 文件:Calculate_Cost.m
function total_cost = Calculate_Cost(ModelUAV)
    % 权重系数,可根据任务需求调整
    weights = [0.5,   % 路径长度权重
               0.3,   % 威胁碰撞权重
               0.1,   % 高度偏离权重
               0.1];  % 路径平滑权重

    total_cost = 0;
    num_UAVs = length(ModelUAV);

    for uav_id = 1:num_UAVs
        path = ModelUAV(uav_id).path;
        model = ModelUAV(uav_id).model;

        cost_length = Calculate_Path_Length(path);
        cost_threat = Calculate_Threat_Cost(path, model);
        cost_height = Calculate_Height_Cost(path, model);
        cost_smooth = Calculate_Smoothness_Cost(path, model);

        % 单机成本
        uav_cost = weights * [cost_length; cost_threat; cost_height; cost_smooth];
        total_cost = total_cost + uav_cost;
    end
end

2. 五大前沿优化算法核心原理与MATLAB实现要点

了解了问题模型后,我们来看看五位“新选手”各自有什么本事。理解它们的设计灵感,有助于我们在调参时更有方向。

2.1 海市蜃楼搜索优化(MSO):利用视觉错觉的探索者

MSO算法的灵感来自于海市蜃楼现象。想象一下,在沙漠中,光线因大气密度不同而发生折射,让你看到了一个并不存在的绿洲虚像。算法模拟了这种“上蜃景”和“下蜃景”效应。

  • 上蜃景策略:对应全局探索。算法会朝着一个看似更优(但可能是虚幻的)方向进行较大步长的搜索,有助于跳出局部最优。
  • 下蜃景策略:对应局部开发。当靠近真实的最优解区域时,算法会进行更精细、小范围的搜索,就像靠近地面时看到的倒影更稳定。

在MATLAB中实现MSO,关键在于设计好“蜃景”的生成规则。通常,它会根据当前种群中个体的适应度,计算一个虚拟的、具有吸引力的位置,引导其他个体向该方向移动,但同时引入随机扰动来模拟大气扰动的不可靠性。

% MSO算法位置更新核心伪代码逻辑
for i = 1:population_size
    % 1. 根据当前最优解和随机因子,生成一个“海市蜃楼”位置
    mirage_position = best_position + rand * (mean_position - best_position) * temperature_factor;

    % 2. 判断使用上蜃景(探索)还是下蜃景(开发)策略
    if rand < exploration_probability
        % 上蜃景:向mirage_position移动,加入较大随机扰动
        new_position = position(i) + randn * (mirage_position - position(i)) + large_perturbation;
    else
        % 下蜃景:向当前最优解或mirage_position进行精细搜索
        new_position = position(i) + randn * (best_position - position(i)) * (1 - iteration/max_iteration);
    end
    % 3. 边界处理
    new_position = max(min(new_position, upper_bound), lower_bound);
end

2.2 阿尔法进化(AE):自适应步长的进化先锋

AE算法摒弃了传统遗传算法中固定的交叉、变异概率。它的核心是“自适应基向量”和“随机步长”。你可以把它想象成一个经验丰富的探险队:

  • 自适应基向量:相当于探险队的“队长”或“最佳路径参考”。它不是固定的全局最优解,而是根据种群的整体分布动态调整的一个指导方向。
  • 随机步长:每个“队员”(解)都根据自己的表现(适应度)决定下一步探索的幅度。表现差的个体可能需要迈大步子去寻找新机会,表现好的个体则小步微调,巩固优势。

这种机制使得AE在迭代初期能快速探索,在后期能稳定收敛。在路径规划问题中,这表现为算法初期能广泛采样各种可能的航线,后期则专注于对几条有潜力的航线进行精细优化。

2.3 梦境优化算法(DOA):记忆与遗忘的平衡艺术

DOA的构思非常有趣,它模拟了人类睡眠中“快速眼动期”的梦境过程。大脑在梦中会重组和强化重要记忆,同时淡化无关信息。

  • 记忆策略:算法会保留历史上找到的较优解(重要记忆),并用它们来指导新解的生成,这加强了局部开发能力。
  • 遗忘补充策略:定期随机生成或引入一些全新的解(遗忘旧思路,补充新想法),这保证了种群的多样性,避免早熟收敛。

对于多无人机路径规划这种解空间可能存在多个“洼地”(局部最优)的问题,DOA的“做梦”机制特别有用。它不会死死盯住一个看似不错的路径,而是时不时“天马行空”一下,有机会发现更优的协同方案。

下表对比了这五种算法在思想灵感上的特点:

算法简称全称核心灵感来源在路径规划中的直观比喻
MSO海市蜃楼搜索优化光在大气中折射产生的虚像一个侦察兵,有时会被远方的幻象吸引去探索新区域,有时会仔细搜索眼前的可疑痕迹。
AE阿尔法进化算法进化过程中自适应方向与步长一支分工明确的探险队,队长指引大方向,每个队员根据自身情况调整探索节奏。
DOA梦境优化算法人类梦境中的记忆处理过程一个善于总结和创新的指挥官,会复盘好的航线(记忆),也会大胆尝试全新的走法(遗忘与补充)。
GOA山羊优化算法山羊在崎岖山地中的觅食行为一群灵活的山羊,能在复杂地形(障碍物)中找到多条通往草场(目标点)的可行小径。
OX牛优化算法公牛的力量、耐性与协作一支强壮的运输队,能负重(处理复杂约束)长途跋涉,并且队员间会保持默契避免碰撞。

2.4 山羊优化算法(GOA)与牛优化算法(OX):仿生行为的实践

GOA模拟山羊在资源有限环境中的觅食:探索新的山坡(全局搜索),反复啃食一片丰茂的草甸(局部开发),并灵活躲避陡崖(约束处理)。在代码中,我们需要用数学公式定义“探索”、“开发”和“躲避”这三种行为模式的切换条件。

OX算法则强调公牛的力量和协作。在更新位置时,它会考虑个体当前的力量(适应度值)和群体中其他个体的位置,模拟出一种“既有个体冲劲,又有群体协调”的运动方式。这对于多无人机协同尤其有意义,因为算法本身的设计就蕴含了避免个体间冲突的倾向。

3. 算法集成与参数调优实战

理论说得再多,不如跑一遍代码。这一部分,我们将在统一的MATLAB框架下集成这五种算法,并深入探讨如何调整关键参数。

3.1 统一算法调用框架

为了公平比较,我们设计一个统一的算法调用接口。每种算法都被封装成一个独立的函数,接受相同的输入(种群大小、迭代次数、问题模型),并返回找到的最优路径和收敛曲线。

% 文件:main_compare.m
clear; close all; clc;

% 1. 创建基础环境模型
base_model = Create_Model();

% 2. 初始化多无人机任务(这里设置4架无人机)
UAV_num = 4;
ModelUAV = Initialize_UAV_Tasks(base_model, UAV_num);

% 3. 设置优化算法通用参数
pop_size = 50;   % 种群大小
max_iter = 200;  % 最大迭代次数
runs = 5;        % 独立运行次数,取平均以消除随机性影响

% 4. 定义要比较的算法列表
algorithms = {@MSO_Optimizer, @AE_Optimizer, @DOA_Optimizer, @GOA_Optimizer, @OX_Optimizer};
algorithm_names = {'MSO', 'AE', 'DOA', 'GOA', 'OX'};

% 5. 循环调用每种算法
results = struct();
for algo_idx = 1:length(algorithms)
    fprintf('正在运行 %s 算法...\n', algorithm_names{algo_idx});
    total_cost_history = zeros(max_iter, runs);
    best_solution = [];

    for r = 1:runs
        [best_paths, iter_costs] = algorithms{algo_idx}(ModelUAV, pop_size, max_iter);
        total_cost_history(:, r) = iter_costs; % 记录每次迭代的最优成本

        % 保留多次运行中最好的解
        if isempty(best_solution) || iter_costs(end) < min([best_solution.cost])
            best_solution(r).paths = best_paths;
            best_solution(r).cost = iter_costs(end);
        end
    end

    % 存储结果
    results(algo_idx).name = algorithm_names{algo_idx};
    results(algo_idx).mean_cost = mean(total_cost_history(end, :));
    results(algo_idx).std_cost = std(total_cost_history(end, :));
    results(algo_idx).convergence = mean(total_cost_history, 2); % 平均收敛曲线
    results(algo_idx).best_paths = best_solution;
end

3.2 关键参数敏感性分析与调优建议

元启发式算法的性能很大程度上依赖于参数设置。没有一套参数能通吃所有问题,但有一些调优原则可以遵循:

  • 种群大小 (pop_size):太小则多样性不足,容易早熟;太大则计算开销剧增。对于我们的多无人机路径规划问题(搜索空间维度高),建议从50-100开始尝试。你可以做一个简单的参数扫描:
pop_sizes = [30, 50, 80, 100];
for ps = pop_sizes
    % 运行算法并记录最终成本
end
% 绘制‘种群大小-最终成本’曲线,选择成本开始平稳或上升的拐点附近的值。
  • 最大迭代次数 (max_iter):主要看收敛曲线。绘制每次迭代的最优成本变化图,如果曲线在后期已基本平缓,增加迭代次数的收益就很低了。通常100-300次迭代对于这类问题是个合理的范围。

  • 算法特定参数

    • MSO:关注“蜃景生成因子”和探索概率。初期可以设置较高的探索概率(如0.7),后期逐渐降低。
    • AE:调整“自适应率”和“步长缩放因子”。步长缩放因子过大可能导致震荡,过小则收敛慢。
    • DOA:“记忆率”和“遗忘率”是关键。一个常见的策略是让记忆率随着迭代缓慢增加,遗忘率相应减少。
    • GOA/OX:这类仿生算法通常有“社会权重”、“认知权重”等参数。可以参考原论文的推荐范围,并在其附近微调。

提示:调参时,每次只改变一个参数,并观察算法性能(最终成本、收敛速度、稳定性)的变化。使用上述的多次运行取平均的方法来评估,以减少随机性的影响。

3.3 处理复杂约束的技巧

我们的成本函数已经包含了威胁、高度、平滑度等约束。但在算法迭代过程中,新生成的随机路径很可能严重违反约束(比如直接穿过障碍物),导致成本函数值为无穷大,这会使得算法搜索失效。因此,我们需要修复策略

  1. 边界修复:如果某个路径点的坐标超出了空间范围,直接将其拉回最近的边界。
    new_point(new_point < lower_bound) = lower_bound(new_point < lower_bound);
    new_point(new_point > upper_bound) = upper_bound(new_point > upper_bound);
    
  2. 碰撞修复(简单版):如果检测到路径段穿过障碍物,可以在该线段中间插入一个绕行点,这个点的位置可以通过向垂直于障碍物中心连线的方向偏移来生成。
  3. 拒绝策略:对于违反约束的解,直接赋予一个极大的惩罚成本(而不是无穷大),这样它虽然很差,但依然参与种群更新,其部分基因(未违反约束的维度)可能仍有价值。

在我的实践中,“惩罚函数+修复策略”结合使用效果最好。轻度违反约束的用高成本惩罚,严重违反(如直接碰撞)的则进行几何修复,保证种群中始终有可行解。

4. 结果可视化与性能深度分析

算法跑完了,一堆数据怎么解读?直观的可视化比任何数字都更有说服力。

4.1 三维路径可视化

将最优路径在三维空间中画出来,可以直观地检查路径的安全性、平滑性和协同效果。

% 文件:Plot_3D_Paths.m
function Plot_3D_Paths(ModelUAV, best_paths, algorithm_name)
    figure('Position', [100, 100, 1200, 500]);
    % 子图1:三维空间视图
    subplot(1,2,1);
    hold on; grid on; view(3);
    xlabel('X (m)'); ylabel('Y (m)'); zlabel('Z (m)');
    title([algorithm_name, ' - 三维路径规划结果']);

    % 绘制障碍物(圆柱体)
    threats = ModelUAV(1).model.threats;
    for i = 1:size(threats,2)
        [X,Y,Z] = cylinder(threats(3,i), 20);
        X = X + threats(1,i);
        Y = Y + threats(2,i);
        Z = Z * threats(4,i);
        surf(X, Y, Z, 'FaceAlpha', 0.3, 'EdgeColor', 'none', 'FaceColor', 'r');
    end

    % 绘制每架无人机的路径
    colors = lines(length(best_paths));
    for uav_id = 1:length(best_paths)
        path = best_paths{uav_id};
        plot3(path(1,:), path(2,:), path(3,:), 'o-', ...
              'Color', colors(uav_id,:), 'LineWidth', 2, ...
              'MarkerSize', 4, 'DisplayName', ['UAV ', num2str(uav_id)]);
        % 绘制起点和终点
        plot3(ModelUAV(uav_id).model.start(1), ModelUAV(uav_id).model.start(2), ModelUAV(uav_id).model.start(3), ...
              '^', 'Color', colors(uav_id,:), 'MarkerSize', 10, 'MarkerFaceColor', colors(uav_id,:));
        plot3(ModelUAV(uav_id).model.end(1), ModelUAV(uav_id).model.end(2), ModelUAV(uav_id).model.end(3), ...
              's', 'Color', colors(uav_id,:), 'MarkerSize', 10, 'MarkerFaceColor', colors(uav_id,:));
    end
    legend('show');
    hold off;

    % 子图2:二维俯视图(X-Y平面)
    subplot(1,2,2);
    hold on; grid on;
    xlabel('X (m)'); ylabel('Y (m)');
    title([algorithm_name, ' - 路径俯视图']);
    % 绘制障碍物投影
    for i = 1:size(threats,2)
        rectangle('Position', [threats(1,i)-threats(3,i), threats(2,i)-threats(3,i), 2*threats(3,i), 2*threats(3,i)], ...
                  'Curvature', [1,1], 'FaceColor', [1,0.7,0.7], 'EdgeColor', 'r');
    end
    % 绘制路径投影
    for uav_id = 1:length(best_paths)
        path = best_paths{uav_id};
        plot(path(1,:), path(2,:), 'o-', 'Color', colors(uav_id,:), 'LineWidth', 1.5);
    end
    hold off;
end

4.2 收敛曲线对比与统计分析

收敛曲线展示了算法寻优的过程。我们将五次独立运行的平均收敛曲线画在一起,可以比较算法的收敛速度和稳定性。

% 绘制收敛曲线对比图
figure;
hold on; grid on;
xlabel('迭代次数');
ylabel('总成本(适应度值)');
title('不同优化算法收敛曲线对比(5次运行平均)');
for i = 1:length(results)
    plot(1:max_iter, results(i).convergence, 'LineWidth', 1.5, 'DisplayName', results(i).name);
end
legend('Location', 'best');
hold off;

为了更定量地比较,我们可以计算一些统计指标:

算法平均最终成本成本标准差平均收敛迭代次数*单次运行平均耗时 (秒)
MSO1523.445.28912.7
AE1489.138.510211.9
DOA1510.822.111514.3
GOA1556.767.87810.5
OX1475.655.39513.8

注:平均收敛迭代次数指成本下降到最终成本±1%范围内所需的迭代数。

从这份模拟结果可以看出:

  • OX算法在本次测试中找到了成本最低的解,体现了其强大的全局搜索能力。
  • DOA算法的标准差最小,说明其运行最稳定,受初始随机种群的影响较小,鲁棒性好。
  • GOA算法收敛最快,但最终成本略高,可能更适合对实时性要求高、可以接受次优解的场合。
  • AE算法在收敛速度和最终解质量上取得了不错的平衡

4.3 路径质量细节评估

除了总成本,我们还需要拆解看各分项成本,以评估路径的具体质量。

% 评估并显示最优路径的详细成本构成
fprintf('=== 路径质量详细分析 ===\n');
for algo_idx = 1:length(results)
    fprintf('\n算法:%s\n', results(algo_idx).name);
    best_path_set = results(algo_idx).best_paths(1).paths; % 取最好的一次运行结果
    % 重新计算详细成本(这里需要调用一个能返回各分项成本的函数)
    [len_cost, thr_cost, hgt_cost, smt_cost] = Evaluate_Path_Details(ModelUAV, best_path_set);
    fprintf('  路径长度成本:%.2f\n', len_cost);
    fprintf('  威胁碰撞成本:%.2f\n', thr_cost);
    fprintf('  高度偏离成本:%.2f\n', hgt_cost);
    fprintf('  路径平滑成本:%.2f\n', smt_cost);
end

通过这个分析,你可能会发现,某个算法总成本低,可能是因为它极大地缩短了路径(长度成本低),但威胁成本略高;而另一个算法则更注重安全,路径绕行较多但非常平滑。这没有绝对的好坏,取决于你的具体任务优先级。是要求最快到达,还是要求绝对安全,或是要求飞行最平稳?根据需求调整成本函数中的权重系数 weights,就能引导算法找到符合你偏好的路径。

最后,我想分享一点在调试这些算法时的心得:不要指望有一个“万能”的最优算法。MSO在有些地形下表现惊艳,DOA在另一些场景下更为稳健。最好的做法就是像我们今天这样,建立一个统一的测试平台,用你自己的问题模型和参数去跑一跑、比一比。代码框架我已经搭好了,你只需要替换掉算法核心函数,调整几个参数,就能快速评估哪种方法更适合你手头的特定任务。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐