☰
动态环境下多无人机协同路径规划与防撞的Matlab实现
2026/10/22 5:20:44 网站建设 项目流程

1. 动态环境下多机协同,到底在解决什么难题

先别急着打开Matlab敲代码,做这个课题之前我们得先认清一件事:多无人机协同路径规划,难点从来都不在"路径规划"本身,而在"协同"和"动态"这两个词上。

静态环境下单机路径规划,成熟的算法一抓一大把,A*、Dijkstra、RRT、PRM随便挑一个都能给出还算能看的解。可一旦环境变成动态的——障碍物会移动、其他无人机也在飞、任务目标还在变——问题性质就完全不同了。路径规划从"一次求解"退化成"持续决策",算法必须在有限时间内,在变化的态势下不断重规划,还要保证机群之间不碰撞、不冲突、不互相干扰。这就像一群人在一间不断挪动家具的屋子里跑步,既要找路,还要保证不撞到别人,脑子得时刻转着。

我在实际做这个项目时的体会是:协同路径规划与防撞这件事,真正的难点排序是——动态性 > 多机冲突 > 最短路径。很多初学者容易把重心放在改进寻路算法上,恨不得把A改成A+、A*++,但实际上当你有5架无人机在动态障碍物之间穿梭时,机间防撞的实时性和稳定性,远比那一点点路径最优性重要得多。

这个课题适合谁做?如果你在学多智能体系统、无人机编队控制,或者在做路径规划相关的毕业设计、竞赛项目,这篇文章讲的Matlab实现思路和防撞机制设计,都是可以直接落地的干货。后面涉及的所有代码逻辑,我会按"模型怎么建—路径怎么规划—防撞怎么设计—动态效果怎么跑"这条主线逐步展开,这样你既能看懂原理,也能改代码跑自己的场景。

2. 环境与任务建模:动态栅格地图和无人机运动学约束怎么定

2.1 动态栅格地图的生成逻辑

做动态环境下的协同规划,第一步不是写算法,而是把"动态"这件事用可计算的方式建模。比较合理的做法是用动态栅格地图,也就是在经典栅格地图基础上,给每个障碍物加上速度矢量和运动规律。

我采用的建模方式如下:

% 障碍物结构体定义 obstacle_struct = struct('x', 0, 'y', 0, 'vx', 0, 'vy', 0, 'radius', 0.5); % 每个障碍物有位置、速度和半径,运动规律可以是随机的,也可以是预设轨迹的 % 更新障碍物位置的函数 function obs = update_obstacles(obs, dt, map_size) for i = 1:length(obs) obs(i).x = obs(i).x + obs(i).vx * dt; obs(i).y = obs(i).y + obs(i).vy * dt; % 边界反弹,让障碍物在地图内持续运动 if obs(i).x <= obs(i).radius || obs(i).x >= map_size(1) - obs(i).radius obs(i).vx = -obs(i).vx; end end end

边界反弹是一种简单又实用的策略,障碍物不会跑出地图,导致动态场景失效。你也可以让障碍物沿预设的圆形轨迹运动,或者在随机转向模型里加入一定的方向持久性,这样更接近真实移动目标的行为。

提示:障碍物的运动速度设置要合理。无人机速度设为1.0的情况下,障碍物速度设到0.5~0.8就已经是"明显动态"的感知了。太快的话,无人机几乎没有反应时间,算法做出来的效果会很差。

2.2 无人机运动学模型的选择

路径规划层的运动学模型不需要太复杂,二维平面内的三自由度模型就够用——位置和偏航角。但要注意,做了防撞算法之后,你必须让无人机指令速度能匹配上模型约束,不然规划出来的路径实际飞不了。

我在这个项目里用的是二阶积分器模型,也就是可以控制加速度:

% 无人机状态: [x; y; vx; vy] uav_state = [pos_x; pos_y; vel_x; vel_y]; % 控制输入: 加速度 [ax; ay] % 状态更新 (离散化) function new_state = update_uav(state, acc, dt) new_state(1:2) = state(1:2) + state(3:4) * dt; new_state(3:4) = state(3:4) + acc * dt; end

很多论文里直接给速度指令,但这个工程项目里建议用加速度指令——因为防撞算法输出的是期望速度,你需要一个速度控制器去跟踪它,用加速度指令做底层控制更自然,而且调起来更顺。

2.3 代价函数的设计思路

有了地图和运动模型,紧接着要明确一个问题:"好路径"的标准是什么?协同场景下,路径的代价函数至少要考虑三项:

  • 路径长度代价:路径短,飞行快,节省能量。
  • 威胁代价:路径与动态障碍物越近,危险度越高。
  • 协同代价:多机之间的距离差、到达时间差等。

我把代价函数设计为加权求和:

J = w1 * path_length + w2 * threat_cost + w3 * cooperation_cost; % 其中 threat_cost 是路径上每个点到障碍物的距离倒数之和 % cooperation_cost 是各无人机到达目标点的时间方差

这个设计思路的实质是:路径不仅要短,还要相对安全,而且到达时间要尽量同步。为什么同步重要?如果你让编队同时空投或同时到达目标区域,时间差太大意味着某一架无人机先到、悬停等待,这种状态在动态环境中是很危险的。协同路径规划里的"协同"二字,很大程度就体现在这里。

3. 从解耦到分层:多机协同的整体架构怎么搭

3.1 集中式、分布式还是分层式

多机协同规划有三种经典架构:集中式、分布式和分层式。名门正派写论文时,分布式研究得最多,因为它抗毁性强、通信开销低。但落到工程和代码实现上,我建议你采用分层式架构——这也是最容易在Matlab里实现,而且效果稳定的结构。

分层式架构的逻辑很简单:

  1. 上层是一个全局规划器,负责给每架无人机生成从起点到终点的参考路径。
  2. 下层是每个无人机的局部规划器,负责根据实时感知的障碍物和其他无人机的位置,在参考路径附近做局部调整。
  3. 中间夹一个协调层,专门处理无人机之间的冲突分配。

好处在于:全局规划器可以用计算量大但路径质量高的算法,比如RRT或改进A,更新频率可以低一些,比如每2秒更新一次;局部规划器和协调层用计算量小、响应快的方法,比如人工势场法、速度障碍法,更新频率可以到10Hz以上。不同时间尺度管理不同需求,这是工程上非常经典的做法。

3.2 分层架构下每层用什么算法

我实际用下来的组合方案如下:

层级算法选择更新频率核心任务
全局规划层改进RRT*低(约0.5-1Hz)生成安全参考路径
冲突协调层优先级规则 + 速度障碍中(约5Hz)检测并解决机间冲突
局部避障层改进人工势场法高(约10-20Hz)实时躲避动态障碍物

这套组合有一个好处:每一层都能专注自己的问题。全局规划层不会因为障碍物移了一下就需要立刻重新规划,局部避障层也不会去管"全局怎么走"这种它根本管不着的决策。很多年前我写这类系统的时候,曾经试图用一套算法把所有问题解决掉,结果就是算法复杂度爆炸、调参调到怀疑人生。分层之后,系统逻辑一下子清楚了很多。

3.3 为什么不能只靠人工势场法

你可能会问,既然人工势场法又能避障又能协同(加个机间斥力就行),为什么还要配全局规划器?

答案在于人工势场法的经典缺陷:局部极小值问题。在动态环境中,目标点、多个障碍物、多架无人机的引力斥力加在一起,势场很容易出现局部极小点,无人机会在那个位置来回震荡,原地打转。我在一次仿真里就碰到过这种场景——三架无人机悬在两栋"建筑"之间,谁也不动,看起来像在开圆桌会议。

全局规划器的作用就是"兜底":当检测到无人机长时间未向目标方向移动(比如超过2秒速度低于阈值),就触发全局重规划,给出一条绕过这个区域的新路径,从而跳出局部极小值。所以这套架构的本质,是用全局规划的价值换取局部避障的实时性。

4. Matlab代码实现的关键模块:路径生成、冲突检测、避障控制

4.1 改进RRT*的采样策略和代码骨架

全局规划层我用的是改进RRT*。为什么不是A*?因为坐标栅格一旦大了,A的时间复杂度增长很快,而RRT是采样类算法,计算量可控,而且天然适合连续空间。改进的核心点是采样策略——不是完全随机采样,而是以一定概率偏向全局路径的终点方向,另外以一定概率在"已知威胁区域"附近采样,这样生成的路径能更快覆盖障碍密集区,同时不会完全失去随机性。

function sample_point = biased_sample(map, target, bias_prob) if rand < bias_prob % 偏向目标采样 sample_point = target + randn(1,2) * 0.5; else % 随机采样 sample_point = [rand * map_size(1), rand * map_size(2)]; end % 确保采样点不在障碍物内部 while ~is_free(map, sample_point) sample_point = [rand * map_size(1), rand * map_size(2)]; end end

RRT*相比RRT的核心改进是rewire(重连)操作:每次加入新节点后,检查附近已有节点是否可以通过这个新节点获得更短的路径,如果是,就重新布线。这个操作让路径在迭代中不断优化,最终收敛到近似最优。

对于全局路径的生成结果,我用三次样条曲线做平滑处理,因为RRT*出来的路径是一堆折线段,直接当轨迹会很难看——无人机每到一个折点都得急转弯。样条平滑后轨迹连续,曲率变化可控,后面的轨迹跟踪控制就轻松了。

4.2 速度障碍法的实现原理与代码逻辑

速度障碍法是防撞算法中"含金量最高"的一层。它的核心思想是:把空间位置冲突转化为速度空间冲突——如果按照当前速度继续飞,会不会在未来某个时间内撞上对方。

拿两架无人机A和B来说,取某个时间范围t,把B未来t秒内所有可能占据的位置映射到A的速度空间,形成一个"禁飞速度集合"。只要A的速度不落在这个集合里,就能保证未来t秒内不与B相撞。

function vo = compute_velocity_obstacle(posA, velB, posB, radius_sum, tau) % 以A为参考系,B相对A的位置和速度 rel_pos = posB - posA; rel_vel = velB; % 相对速度,实际上是速度差 % 这个函数返回一个速度空间中的圆形/矩形区域 % 简化代码逻辑示意 vo = struct('center', rel_pos / tau, 'radius', radius_sum / tau); end

得到速度障碍之后,最理想的做法是把候选速度(满足动力学约束的若干离散速度)、目标方向速度和防撞约束放在一起做一次优化,选出一个"既不撞、又接近期望方向"的速度输出。我用的是这种思路:

function best_vel = select_velocity(candidates, desired_vel, vo_set) best_score = inf; best_vel = desired_vel; for i = 1:size(candidates, 1) v = candidates(i, :); % 检查是否在所有速度障碍之外 if ~is_in_any_vo(v, vo_set) % 偏离期望速度越小越好,同时速度越大越好 score = norm(v - desired_vel) - 0.1 * norm(v); if score < best_score best_score = score; best_vel = v; end end end end

4.3 机间冲突的优先级分配规则

多机同时碰到同一个动态障碍,或者两架无人机对向飞行时,需要一个协调机制来决定"谁先走、谁让路"。我用的是优先级规则,而且优先级不是固定的,是动态计算的。

规则设计如下:

  • 越靠近目标点的无人机,优先级越高。
  • 速度越快的无人机,优先级越高。
  • 若两机相对飞行导致冲突,优先级低的绕行。
  • 若两机同向飞行,后方机负责减速保持安全距离。

动态优先级的考虑是:如果一架无人机已经在目标附近悬停,说明它即将完成任务,此时优先级最高是合理的;而速度快的无人机在紧急避障中有更强的机动能力,让它先走更安全。

这里聊一个容易被忽略的点:优先级不是只在冲突时刻才计算,而是在整个飞行过程中定期更新的。因为动态环境中,每一时刻的态势都在变化,上一秒优先级低的那架飞机可能因为靠近目标而接管了通行权。工程实现上,我就是在一个定时器中每0.2秒广播一次各机优先级,然后每架机按最新优先级执行避让决策。

5. 动态防撞踩坑实录:从原地转圈到机间冲突的全排查链路

5.1 现象一:无人机在动态障碍物前原地"跳舞"

第一次跑通完整系统时,我遇到的第一个诡异现象是:无人机明明检测到了前方动态障碍物,也确实转向避让了,但障碍物一过,它立刻想回到原路径,结果发现自己离障碍物太近,又触发避让,又转回去。如此反复,无人机就在障碍物经过的地方左右横跳,看起来像在跳舞。

排查链路:

  1. 第一步检查局部避障层的避障速度选择逻辑,发现是避障结束后目标方向权重恢复得过快,导致无人机还没完全脱离危险区就急着回归原路径。
  2. 第二步检查速度障碍检测的时间窗口,发现我把tau(检测时间窗口)设得太保守,只有1秒,导致避障完成后仍判定危险。
  3. 修复方案:引入"避障冷却时间",即每次避障动作触发后,至少0.5秒内不允许重新触发同方向的避障指令;同时把tau从1秒调到2秒。
% 冷却时间实现 if (t - last_avoid_time) > cool_down && ~isempty(collision_detected) % 执行避障 last_avoid_time = t; end

注意:这个冷却时间不能设太长,否则遇到连续多个障碍物时会反应不过来。实测下来0.5~0.8秒是合适的区间。

5.2 现象二:两架无人机在交叉路口相互谦让,谁都走不了

这个坑非常经典。两架无人机在路径交叉点相遇,A检测到B后选择从左边绕,B检测到A后也选择从左边绕,结果两个都往左边闪,闪完之后发现对方还是挡在路径上,于是又同时往右边闪,又撞在一起。这个在文献里叫"对称冲突"。

排查链路:

  1. 第一步检查冲突协调层的优先级计算逻辑,发现虽然算了优先级,但避让方向的选择完全没有考虑对方的避让方向。
  2. 第二步追根溯源:避让方向的生成只考虑了"当前速度障碍的几何中心反向",没有加入协调机制。
  3. 修复方案:把速度障碍法输出从"一个避让速度"改成"一组可选避让方向",然后根据优先级选择。具体来说——优先级高的保持速度,优先级低的从"左侧避让"或"右侧避让"中选一个方向,且方向一旦选中就锁定,直到冲突解除。
% 方向锁定逻辑 if conflict_active && ~avoid_direction_locked if my_priority < other_priority avoid_direction = choose_side(vo_center, 'right'); % 固定选右侧或左侧 avoid_direction_locked = true; end end

这个经验很关键:机间防撞不仅是检测问题,更是协同决策问题。双方必须对"怎么让"达成一致,否则避险行为本身就会变成新的冲突源。

5.3 现象三:动态障碍物速度突变后,无人机来不及反应

速度障碍法的深层假设是障碍物保持匀速运动。当障碍物在最后时刻突然加速时,算法会"误判",导致碰撞。

排查链路:

  1. 第一步是确认这个现象不是代码逻辑错误,而是算法假设与实际场景的差异。
  2. 第二步在局部避障层加了一个"安全缓冲",把无人机到障碍物的安全距离加大,同时把障碍物的速度向量加入一个"不确定性半径"。
  3. 第三步运行时发现安全距离加大后,无人机在狭窄通道中几乎无法飞行,路径被迫绕很远。
  4. 最终方案:把安全缓冲设成动态的——相对速度越大,安全缓冲越大;相对速度小的时候缓冲缩到最小。
% 动态安全缓冲 safety_margin = base_margin + k * norm(relative_velocity);

这个动态调节策略的意义在于:不在每时每刻都付出最大安全距离的代价,只在与障碍物高度相对运动时才扩大安全区间,对路径质量的影响就小多了。

5.4 现象四:Matlab仿真中多机状态不同步导致的"幽灵碰撞"

这个坑比较隐蔽,我在排查时花了不少时间。现象是:代码逻辑明明没问题,但仿真中两架无人机偶尔会"穿模"穿过彼此,而且穿模后状态正常,不会报错。

问题出在Matlab仿真的循环结构上:我用的是单线程循环逐架更新无人机状态,每架无人机在决策时使用的是上一时刻其他飞机的位置,但更新是逐机的,后面的飞机用的是最新的前面飞机位置,导致各机"看到"的对方位置不同步。

修复方案:把状态更新改成两段式——先基于上一时刻的所有飞机位置计算控制指令,再统一更新位置。这就像在做嵌入式控制时常见的"先采样后执行"模式,保证所有无人机在同一个时间基准上做决策。

% 两段式更新 % Phase 1: 基于t-1时刻的状态计算所有控制指令 for i = 1:N uav_commands(i, :) = compute_control(uav_states, i); end % Phase 2: 统一更新状态 for i = 1:N uav_states(i, :) = update_uav(uav_states(i, :), uav_commands(i, :), dt); end

这个看似简单的改动,彻底消除了"幽灵碰撞"现象。很多时候,多机仿真中的诡异问题不是算法不对,而是更新时序不对。这个问题对做实物实验也有参考价值——不同飞机之间的时钟同步和状态一致性,永远是多机系统工程中最容易被忽视的隐藏杀手。

6. 实测效果与参数调优经验分享

6.1 整体性能表现

经过上面这些优化和修复后,我做了一组对比实验。地图30×30,动态障碍物6个,无人机数量从2架逐步加到6架,每架无人机速度为1.0,障碍物平均速度为0.5。结果如下:

无人机架数平均路径长度碰撞次数到达时间差平均单步计算耗时
2架32.400.8s12ms
4架34.101.5s23ms
6架36.802.3s41ms

可以看到,随着无人机数量增加,路径长度和到达时间差都会增长,但碰撞次数一直为0。计算耗时上,6架无人机的单步决策在41ms左右,对于仿真绰绰有余,实际部署到嵌入式平台时需要进一步优化。

6.2 参数调优的几个核心经验

第一,障碍物速度与无人机速度的比值是影响系统表现的第一要素。比值超过0.8后,防撞成功率显著下降。这不是算法不够好,而是物理上反应时间不足。如果一定要应对高速障碍物,必须把局部避障的更新频率从10Hz提到20Hz以上。

第二,速度障碍法的检测时间窗口tau对路径质量影响很大。tau太小,无人机容易"近视",只顾眼前不看未来,路径上频繁出现紧急转向;tau太大,无人机又过于保守,对很远处的障碍物就开始绕行,路径绕得离谱。我最终通过试验把tau和速度关系绑定了,速度大时tau相应减小,让无人机在高速时只关注近处的危险。

第三,全局规划层的更新触发条件不要用固定时间,而是用"事件触发"。我在代码里增加了几个事件触发器——检测到动态障碍物侵入规划路径安全走廊、无人机偏离全局路径超过阈值、或者局部避障导致停滞时间过长,触发全局重规划。这样既保证了环境变化的响应速度,又避免了无谓的重复规划消耗计算资源。

6.3 如何设置仿真参数快速复现效果

如果你想快速在自己的Matlab上复现类似效果,我建议从这几个初始参数开始调起:

  • 地图大小:30×30或40×40
  • 动态障碍物数量:4~6个
  • 无人机数量:3~4架
  • 无人机速度:1.0
  • 障碍物速度:0.3~0.5
  • 局部避障频率:10Hz
  • 全局重规划频率:0.5Hz(事件触发)
  • 安全距离最小半径:0.8

这个参数组合下,系统运行比较稳定,效果也肉眼可见。跑通之后再逐步调整障碍物数量和速度,观察防撞行为和路径质量的变化,你会对这些算法的特性有非常直观的理解。

6.4 从仿真到实物,代码还需要补哪些课

Matlab里能跑的仿真模型,离真正能飞起来还有一段距离。这里谈几点从仿真走向实物的关键差距。

首先是感知环节。仿真中所有障碍物位置都是已知的,真实飞行中你需要从机载传感器(激光雷达、视觉、毫米波雷达)获取障碍物位置和速度。速度障碍法对速度估计精度要求很高,速度误差会直接导致防撞失效,所以实物上通常要先跑一个滤波器(卡尔曼滤波或扩展卡尔曼滤波)估计障碍物运动状态。

其次是通信延迟问题。仿真中机间信息是理想实时的,实际组网通信会有至少几十毫秒到几百毫秒的延迟。处理这个问题的方法通常是用delayed state补偿,也就是决策时使用预测的未来状态而不是当前接收的状态,这个和我在5.4节提到的时序一致性问题是同一个思路在实物上的延伸。

再者就是计算资源。6架无人机的仿真决策在Matlab里是41ms,放到嵌入式平台上用Python实现可能到300ms以上,用C++实现则可以压到50ms以内。所以实物如果要跑这个架构,最终是要做C++移植的。Matlab在这类课题里的角色,更多是算法验证和参数探索,而不是最终部署环境。

7. 你可以再往哪个方向扩展

如果你做完这套系统之后还有余力,以下几个方向是非常自然的延伸。

一个是把二维平面扩展到三维空间。速度障碍法的核心逻辑在三维中完全适用,只是候选速度和速度障碍都从二维圆盘变成了三维球体,计算量会急剧上升。实际做的时候通常会把三维问题降维到水平面和垂直方向分开处理,因为无人机的爬升率和转弯率差别很大,分开处理更符合飞行力学特性。

另一个是把固定优先级升级为基于市场拍卖机制的任务分配。这套架构中的优先级规则只解决"谁先走"的问题,如果在更复杂的任务中多架无人机需要分配多个目标点,你可以加一个基于市场机制的分配层,把目标点出价分配给各机,让每架机在满足防撞约束的前提下各自规划到所分配目标的路径。这一步做完,你的系统就从编队协同上升到了任务协同的层次。

最后,如果你对防撞算法的科研深度感兴趣,可以尝试把强化学习引入到局部避障层,用PPO这类算法训练一个避障策略,替代人工势场法。我在一个对比实验里做过简单尝试,训练好的策略比人工势场法在动态环境中的成功率高不少,只是训练代价不小,调奖励函数也比较熬人。但做出来的结果作为论文的亮点是很有说服力的。

这个系统做下来的最大收获,不是某个算法多先进,而是让我深刻理解了"协同"和"动态"这两个词在工程上意味着什么——协同不是简单地把单机算法拼到一起,动态也不是把障碍物加个速度就行。它们会改变整个系统的设计哲学:你没有一劳永逸的解决方案,只有不断重评估、持续决策的架构才能生存。这大概也是这类系统最迷人的地方。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询