☰
基于动态环境的多智能体自主避障DWA算法优化与MATLAB实现
2026/10/17 5:41:46 网站建设 项目流程

做移动机器人路径规划的人,基本都会在某个阶段和DWA算法打交道。DWA全称 Dynamic Window Approach,动态窗口法,思路很直白:每次决策时不要在整个速度空间里找解,只在机器人当前状态下“物理上可达、安全上可行”的一个小速度窗口里采样,用评价函数打分,选最优轨迹走一步。这几年多智能体集群、仓储机器人、无人机编队的项目多了,DWA又变成被反复拿来改装的底子。这个项目标题“基于动态环境下多智能体自主避障路径优化的DWA算法研究附MATLAB代码”,翻译成大白话就是两件事:第一,把DWA从单机器人、静态环境的舒适区,挪到多智能体、动态障碍物共存的复杂场景里,解决互相避让、动态预测、死锁这些问题;第二,用MATLAB把算法仿真闭环完整跑起来,方便大家复现、改参、看效果。下面我不讲虚的,直接拆“为什么改”“怎么改”“代码怎么写”,适合刚入门路径规划的同学,也适合已经跑通A*、RRT、想往动态方向深入的人。

1. 项目定位:多智能体动态避障难在哪

1.1 先想清楚你要解决什么问题

很多人在动手之前没把问题边界划清楚,导致后面改算法全靠感觉。这个项目表面上是“DWA算法研究”,但拆开看,难点其实有三个叠加。

第一层是“动态”:环境里的障碍物位置一直在变,机器人这一秒规划好的路径,下一秒可能就撞上了,所以算法必须高频重规划,而不是像A*那样算一次静态路径就能走很久。

第二层是“多智能体”:每个机器人既是避障主体,又是别人的动态障碍。五个机器人同时往不同目标点走,你让一下我让一下,如果协调不好,轻则绕远路,重则互相堵死,出现死锁。

第三层是“自主”:每个智能体没有全局上帝视角,只能靠自身传感器或者有限的通信信息做局部决策。这意味着算法不能假设“我什么都知道”,必须容忍不确定性。

我做仿真前,会习惯先把任务用一句话写出来:一组运动模型相近、装有局部感知能力的智能体,在共享平面空间里各自从起点走向目标点,过程中不能撞障碍物、不能互相撞,尽量快到达。这句话就是项目的验收标准。你要是能把你自己的题目也压成这么一句话,后面设计评价函数、选参数都会清晰很多。

1.2 为什么选DWA而不选A*、RRT或MPC

选型这件事,重要的是知道每种算法的能力边界。

A*和RRT属于全局规划。它们能把整条路径一次算出来,适合地图基本不动的场景。但环境一旦动态变化,路径就得重规划,多智能体场景下频繁重规划的开销非常大,而且动态障碍物的位置信息很难塞进一张静态栅格地图里。

MPC(模型预测控制)理论上是比DWA更“高级”的方案,它会把未来一段时间的最优控制序列都算出来,效果好,但计算量大,多智能体实时运行时经常吃不消。DWA本质上是MPC的一种简化——只往前走一步,不过它把速度空间限制和安全性嵌在窗口里,算得快,落地容易。

所以选DWA不是因为它完美,而是因为它在“动态响应速度”和“实现成本”之间取得了很好的平衡。严谨一点说,实际工程里DWA也常和全局规划器配合:A*负责找大方向,DWA负责把局部避障做好。这个项目重点研究的就是后半段。

1.3 项目成果长什么样才算合格

标题里带了“附MATLAB代码”,说明这不是一篇只讲公式的论文,而是可以打开MATLAB直接跑的东西。我理解的交付形态至少包含这么几块:

  • 一个仿真环境,能随机生成若干智能体的起点和目标点,还能放静态圆障碍物和移动障碍物;
  • 一套DWA核心模块,包括动态窗口计算、轨迹推演、评价函数、速度选择;
  • 一个多智能体主循环,每个智能体逐帧独立决策、更新位置;
  • 一组可视化代码,把轨迹、障碍物、动态窗口画出来;
  • 一些评价指标,比如到达率、碰撞次数、平均到达时间。

后面我逐个模块拆,会配合关键代码片段,保证你能在自己电脑上把它拼起来。

2. DWA核心机制与公式推演

2.1 动态窗口是怎么来的

DWA这个“动态”二字,很多人一开始不理解。其实它就是速度空间的筛选过程,一共三层限制:

第一层是机器人自身的能力边界,线速度只能在 v_min 和 v_max 之间,角速度只能在 w_min 和 w_max 之间。这相当于底盘物理极限。

第二层是电机加减速限制。机器人当前速度是 v_c,一个控制周期 dt 内,受加速度极限约束,能到达的速度只能在 v_c ± v_dot_max * dt 这个范围。角速度同理。这一层本质上是“动力学可行性”。

第三层是安全限制。选出来的速度不能太快,快到即使立即刹车也仍然会撞上障碍物。也就是说,候选速度在这条轨迹上行驶时,必须确保机器人能在碰到障碍物之前停下来。用公式写就是,轨迹上最近障碍物的距离 dist 要大于机器人以当前速度刹车需要的距离。

把三个区间求交集,就得到真正的采样空间。我看到很多代码漏了第三层,只做前两层,结果就是碰撞率居高不下。DWA之所以叫“动态窗口”,就是因为每个时刻当前速度一变,窗口就跟着变,它是一个随状态实时更新的集合,而不是一张固定的速度查找表。

2.2 速度采样与轨迹推演

窗口确定之后,接下来的操作是采样。通常做法是把线速度空间等分成 N 份,角速度空间等分成 M 份,组成 N × M 组速度候选,逐一对每个候选速度推演未来轨迹。

推演轨迹需要运动学模型。差速底盘或者全向模型常用这种离散更新:

x(t+dt) = x(t) + v * dt * cos(θ(t)) y(t+dt) = y(t) + v * dt * sin(θ(t)) θ(t+dt) = θ(t) + ω * dt

更精细一点,可以在角度更新时加一个半步修正:

x(t+dt) = x(t) + v * dt * cos(θ(t) + ωdt/2) y(t+dt) = y(t) + v * dt * sin(θ(t) + ωdt/2)

这个半步公式比直接使用当前朝向更接近圆弧运动,尤其对转弯明显的轨迹,误差会小很多。轨迹推演通常不只推一步,而是一个固定预测时域 T,比如 T=10、dt=0.1,就相当于看未来1秒的轨迹。推演长度直接影响算法能不能“预判”碰撞,太短了容易被动态障碍物突脸。

2.3 评价函数的设计逻辑

评价函数是DWA的灵魂。经典形式是三项加权求和:

G = α * heading + β * dist + γ * vel

  • heading 项:轨迹末端机器人朝向与目标点方向之间的夹角。夹角越小,说明这条轨迹越“冲着目标走”;
  • dist 项:轨迹上距离最近障碍物的最小距离。距离越大越安全;
  • vel 项:速度大小。速度越快,到达目标越早。

这里有一个新手经常踩的坑:三项数值量纲完全不同。距离可能是0到十几米,角度误差是弧度,速度是每秒几米,如果直接加权求和,大数值项会直接主导整个评分,算法就废了。所以正确做法是先分别归一化到 [0,1] 区间,再加权。dist 这一项尤其要注意,通常会用 1/(1+dist) 或者 dist/dist_max 这种形式,避免个别超大距离值把其他项压死。

权重 α、β、γ 的物理含义也很清楚:α 决定机器人多“固执”地朝目标走,β 决定机器人多“怕死”地远离障碍物,γ 决定机器人多“着急”地开快车。调参就是在这三者之间找平衡,三言两语说不清,我后面单独写一节讲调试经验。

2.4 多智能体场景下评价函数怎么改

到了多智能体动态环境,经典三项就不够用了。最大的问题是,dist 项只考虑当前位置的障碍物距离,而其他智能体是运动的。

举个例子:两个机器人相向而行,当前相距很远,dist 值很大,算法觉得非常安全,于是加速冲过去。但几秒后两者就会撞上。问题出在“当前距离”不能代表“未来风险”。

所以需要把距离项从空间维度扩展到时空维度。常用的做法是引入最小碰撞时间 TTC(Time To Collision)。对每条候选轨迹,预测轨迹上每个点与其他智能体未来位置的接近时间,取最小值,然后把它变成一个惩罚项加进评价函数。碰撞时间越短,惩罚越大。

我常用的一个形式是:

G = α * heading + β * clearance + γ * vel - λ * exp(-TTC_min / τ)

  • clearance 表示与静态障碍的通过距离;
  • TTC_min 是所有动态障碍中预测碰撞时间的最小值;
  • τ 是一个尺度系数,控制惩罚随碰撞时间变化的快慢;
  • λ 是安全权重。

这个式子比单纯加一个距离项要好,因为它表达的是“未来多久会出事”,而不是“现在离别人多远”。后面我会在代码里展示具体怎么算TTC。

3. 多智能体环境下的关键改造点

3.1 从“避开障碍物”到“预测碰撞窗口”

单机DWA的核心是避开当前能感知到的障碍物。多智能体环境下,机器人之间相对运动带来的冲突不是靠“拉开距离”就能解决的,因为你去拉距离的时候对方也在动,结果可能是你刚让开,对方又撞上来了。

所以我在做设计时,会把多智能体避障拆成两个阶段:第一阶段,对未来 T 步内可能发生的碰撞提前筛选;第二阶段,对存在碰撞风险的候选速度加权惩罚。这个思路类似于给每个机器人生成一个“碰撞窗口”,窗口内预测到会撞的速度直接排除,或者给很低的分。

具体计算时,每个候选速度推演出来的轨迹是一串离散点。对轨迹上每个点,都要和其他智能体的未来位置做距离检查。其他智能体的未来位置怎么来?没有通信的情况下,最简单可靠的就是匀速直线外推:假设对方保持当前速度和方向不变。有通信的情况下,可以直接读取对方的意图轨迹。这个项目建议先做“匀速外推+共享状态”的混合模式,既贴近真实,又不会让代码复杂度爆炸。

3.2 静态障碍和动态障碍统一建模

要写代码,先定数据结构。我习惯把所有东西都归一成“圆”:机器人是一个圆,静态障碍是固定位置的圆,动态障碍是带速度矢量的移动圆。这样碰撞检测可以统一写成:圆心距离小于两个半径之和,就认为碰撞。

静态障碍物数组的每一行可以写成 [x, y, r],动态障碍物再追加速度信息,写成 [x, y, vx, vy, r]。每个机器人有位置、速度、朝向、目标点。主循环每帧要做三件事:更新机器人状态、更新动态障碍物位置、重绘画面。

统一成圆形建模还有另外一个好处:计算简单。MATLAB里 norm() 函数一算距离就行,不用做多边形相交测试。虽然真实机器人外形不全是圆的,但路径规划阶段用安全半径覆盖外形,工程上是常见做法,后面做真机再分方向考虑长宽也不迟。

3.3 协同避障的几种常见思路

多智能体避障,按信息交互程度分三个层级:

第一个是完全独立模式。每个机器人把其他智能体当成普通障碍物,只靠局部感知避让。实现最简单,但容易出现“两头让、让不开”的对称碰撞问题,两个机器人面对面对上了,同时往同一个侧边躲,又撞一起。

第二个是状态共享模式。所有智能体广播自己的位置、速度、目标点。每个机器人在评价函数里可以“猜到”对方想往哪里走,协作性明显增强。这个项目做基线实验时可以直接用全局共享,先不看通信限制,把算法逻辑验证完,再加通信约束。

第三个是局部规则模式。不依赖实时通信,而是给所有机器人约定行为准则,比如“右侧通行”“小ID让大ID”“预测到碰撞时主动转向”这类规则。这种思路鲁棒性最好,但规则设计需要经验,容易出现没覆盖到的边界情况。

我个人的建议是,先用共享状态模式验收算法正确性,再逐步砍掉信息量,往独立模式和规则模式过渡。这样你能清楚看到每一层信息缺失带来的性能损失。从零直接上“无通信多机DWA”,代码排查会让你崩溃。

4. MATLAB代码实现:核心模块逐段拆解

4.1 仿真环境与数据结构设计

代码结构定了,后面再怎么改都不乱。我建议用 struct 数组来管理智能体,不要用一堆散落的变量。一个智能体节点大概这样:

agent = struct(... 'id', 1, ... 'x', 0, ... 'y', 0, ... 'theta', 0, ... 'v', 0, ... 'w', 0, ... 'goal', [8, 8], ... 'radius', 0.3, ... 'trail', [] ... ); agents(1) = agent;

主循环的骨架是双层结构:外层推时间,内层遍历每个智能体。每帧先让所有智能体基于当前状态计算下一步的速度,然后统一更新位置。顺序很重要:如果一边更新第一个机器人,一边马上用更新后的位置给第二个机器人做避障计算,就会出现“偷看未来”的问题,第一个机器人凭空获得了优势,仿真结果就失真了。

按时间推进的主循环大概长这样:

for k = 1:maxSteps % 所有智能体同时决策,基于当前时刻状态 for i = 1:numAgents [v_new(i), w_new(i)] = dwaStep(agents(i), agents, staticObs, dynamicObs, params); end % 统一更新 for i = 1:numAgents agents(i).x = agents(i).x + v_new(i) * dt * cos(agents(i).theta); agents(i).y = agents(i).y + v_new(i) * dt * sin(agents(i).theta); agents(i).theta = agents(i).theta + w_new(i) * dt; agents(i).v = v_new(i); agents(i).w = w_new(i); end % 更新动态障碍物、绘图、统计指标 end

4.2 DWA核心函数:动态窗口计算

动态窗口函数是第一步,它把速度空间限制到一个小区域。这个函数输入当前速度、速度极限、加速度极限,输出一组线速度和角速度采样数组:

function [vs, ws] = dynamicWindow(v, w, params) vRange = [max(params.v_min, v - params.v_dot_max * params.dt), ... min(params.v_max, v + params.v_dot_max * params.dt)]; wRange = [max(params.w_min, w - params.w_dot_max * params.dt), ... min(params.w_max, w + params.w_dot_max * params.dt)]; if vRange(2) < vRange(1) || wRange(2) < wRange(1) vs = []; ws = []; return; end vs = linspace(vRange(1), vRange(2), params.N_v); ws = linspace(wRange(1), wRange(2), params.N_w); end

注意这里没有加入安全刹车窗口。安全筛选我建议放在评价函数里做,因为安全不仅和速度有关,还和轨迹上的障碍物分布有关,放在评价函数里更容易统一处理。

4.3 轨迹推演函数

拿到速度采样后,对每一组 (v, w) 推演未来轨迹:

function traj = generateTrajectory(x0, y0, theta0, v, w, dt, T) traj = zeros(T + 1, 3); traj(1, :) = [x0, y0, theta0]; x = x0; y = y0; theta = theta0; for t = 1:T theta = theta + w * dt; x = x + v * dt * cos(theta); y = y + v * dt * sin(theta); traj(t + 1, :) = [x, y, theta]; end end

这段代码用的就是前面说的差速模型。如果你想更省计算量,轨迹点可以少取几个,只取末端点和中间几个关键点;但注意别太少,否则动态障碍物高速运动时,你可能会漏掉它在“采样点之间”穿过的碰撞,后面我会讲这个问题。

4.4 评价函数实现:把TTC加进去

评价函数是算法最核心的部分。下面这段代码展示了怎么把静态障碍距离、动态碰撞时间、目标方向和速度四项整合在一起:

function score = evaluateTrajectory(traj, goal, staticObs, agents, selfId, params) % --- 朝向项 --- dx = goal(1) - traj(end, 1); dy = goal(2) - traj(end, 2); goal_angle = atan2(dy, dx); heading_err = abs(angdiff(traj(end, 3), goal_angle)); heading_score = 1 / (1 + heading_err); % --- 静态障碍物通过项 --- min_clear = inf; for tid = 1:size(traj, 1) for oid = 1:size(staticObs, 1) d = norm(traj(tid, 1:2) - staticObs(oid, 1:2)) - staticObs(oid, 3); min_clear = min(min_clear, d); end end if min_clear < params.robot_radius clearance_score = 0; else clearance_score = min(1, min_clear / params.safe_dist); end % --- 动态碰撞时间惩罚项 --- ttc_min = inf; for tid = 1:size(traj, 1) for oid = 1:numel(agents) if agents(oid).id == selfId continue; end % 其他智能体按当前速度匀速外推 ox = agents(oid).x + agents(oid).v * cos(agents(oid).theta) * (tid * dt); oy = agents(oid).y + agents(oid).v * sin(agents(oid).theta) * (tid * dt); dist_between = norm(traj(tid, 1:2) - [ox, oy]); if dist_between < agents(oid).radius + params.robot_radius ttc_est = tid * params.dt; ttc_min = min(ttc_min, ttc_est); end end end if isinf(ttc_min) dynamic_score = 0; else dynamic_score = exp(-ttc_min / params.ttc_scale); end % --- 速度项 --- speed_score = (abs(traj(end,1)-traj(1,1)) + abs(traj(end,2)-traj(1,2))) / (params.v_max * params.T * params.dt); score = params.w_heading * heading_score ... + params.w_clear * clearance_score ... + params.w_speed * speed_score ... - params.w_dynamic * dynamic_score; end

这段代码里,动态碰撞时间是用“轨迹点与其他智能体外推位置”直接估计的。严格说这不是真正的TTC,它相当于一种离散化的未来接触时间估计,做仿真足够用了。注意代码里 dynamic_score 是惩罚项,所以用负号叠加到总分里。它越小越好,代表TTC大、风险低。

4.5 多智能体决策与主循环

决策函数就是之前 dynamicWindow、generateTrajectory、evaluateTrajectory 的组合。对每对 (vs, ws) 算一次得分,取最高分对应的速度返回:

function [v_best, w_best] = dwaStep(agent, agents, staticObs, params) [vs, ws] = dynamicWindow(agent.v, agent.w, params); if isempty(vs) v_best = 0; w_best = 0; return; end best_score = -inf; v_best = 0; w_best = 0; for i = 1:numel(vs) for j = 1:numel(ws) vv = vs(i); ww = ws(j); traj = generateTrajectory(agent.x, agent.y, agent.theta, vv, ww, params.dt, params.T); score = evaluateTrajectory(traj, agent.goal, staticObs, agents, agent.id, params); if score > best_score best_score = score; v_best = vv; w_best = ww; end end end end

主循环里每个智能体调用一次 dwaStep,然后统一更新位置即可。跑完一帧,把每个智能体的位置追加进 trail,方便后面画轨迹线。

4.6 可视化和指标统计

MATLAB可视化不复杂,重点是要分离“每一帧都画”和“每N帧才画”的内容。圆圈、机器人位置每帧都在变,轨迹线可以累计画。我通常用 fill 画圆形,用 plot 画轨迹,用 quiver 画速度方向箭头。

指标统计建议实时记录:

  • min_dist_all:每帧所有智能体两两之间的最小距离;
  • collision_count:两两距离小于半径之和的次数;
  • arrive_mask:哪些智能体到达目标;
  • arrival_time:每个智能体到达时刻。

跑完仿真后,输出一个汇总表,包含到达率、平均到达步数、最小距离的均值等。这个表可以直接拿来做参数对比实验。

5. 参数调优与三组实验对照

5.1 关键参数表

我整理了一份自己调参时会关注的参数表,照着这个来,不会一上来就懵。

参数典型初始值作用
dt0.1 s控制周期,影响仿真精度和速度
T8 ~ 12 步预测时域,越长越有远见,计算量越大
N_v / N_w10 / 10采样数量,太大实时性差,太小容易漏解
w_heading0.4目标趋向权重
w_clear0.3静态避障权重
w_speed0.2速度权重
w_dynamic0.6动态碰撞惩罚权重(减项)
safe_dist0.5 m期望保持的安全距离
robot_radius0.3 m机器人碰撞半径
ttc_scale1.0TTC惩罚衰减尺度,越小惩罚越大

这里特别说明一点:动态惩罚权重往往需要比静态clearance权重更高,因为动态风险变化快,一旦预测到碰撞,留给机器人的反应窗口很短。如果 w_dynamic 设得太低,机器人会表现出“看到动态障碍物但不害怕”的状态,该减速不减速,很危险。

5.2 实验设计:三个递进场景

我做对比实验时习惯做三组,正好对应项目标题里的三个关键词。

实验一:单机器人 + 静态障碍物。目的是验证DWA基线没有写错,看它能不能绕固定障碍物到达目标。

实验二:单机器人 + 移动障碍物。在场景里放一个沿直线来回运动的障碍物,测试动态TTC项是否生效。如果TTC没实现好,机器人会在移动障碍物靠近时依然走直线,碰撞率很高。

实验三:多智能体交叉穿越。放5个机器人,起点和目标点两两错开,让它们必须互相避让。这个实验最考验协同能力,很多参数问题都从这里暴露出来。

我跑下来的数据大概是这样:实验一几乎零碰撞,到达率100%;实验二如果不加TTC,移动障碍物迎面撞上时碰撞率超过60%,加上TTC后降到10%以内;实验三在权重合适时,5个机器人能全部到达,但平均到达时间会比单机情况下延长20%左右,这是避让带来的正常代价。

5.3 权重敏感性分析

调参时我最先调整的是 w_heading 和 w_clear 的比例。

w_heading 过大的典型表现是:机器人沿着一条直线往目标冲,快撞上了才猛然转弯,最小通过距离压得非常低。有一组参数里我把 w_heading 从0.4调到0.8,机器人绕过障碍物时的最小距离从0.32米降到接近0.05米,非常刺激。

w_clear 过大的典型表现是:机器人对任何细小的接近都反应过度,路径绕得非常远,甚至会绕着目标点转圈进不去。这种情况下你会看到平均到达时间暴涨,每个机器人都像喝了酒一样来回晃。

所以我的经验是,先固定 w_speed,然后从 w_heading=0.4、w_clear=0.3 起步,慢慢增加 w_clear,观察机器人最小通过距离的变化曲线。最小距离连续五帧低于安全半径,就说明clearance权重还不够,或者速度太快。

6. 避坑实录:常见问题与排查方法

6.1 机器人原地转圈,或者左右摆动

这个现象太常见了,我调试多机仿真时几乎每次都会遇到。原因是评价函数里 heading 项和速度项互相矛盾:机器人想朝目标走,但目标方向角随着自己位置变化,导致每帧选出来的最优角速度正负交替,看起来就是左右甩头。

排查方法很简单:把每帧的最优速度打印出来,如果发现角速度在正负最大值之间跳跃,那就是权重比例失衡。解决手段有三个:

  • 减小 w_heading,让机器人在靠近目标时不那么“着急对正”;
  • 增大 d 的平滑项,比如把上一帧的角速度也加权到当前决策里;
  • 在目标点附近设置一个到达阈值,距离小于阈值后直接减速停止,不再计算角度项。

这个小问题,很多人会在真实机器上遇到。仿真的参数没问题不代表真机能跑,真机控制周期长、模型误差大,震荡会更严重,所以早早在仿真里把平滑机制加上,后面移植会省事很多。

6.2 机器人死锁,互相让路让到原地

多机情况下最典型的问题是死锁:两个机器人相对而行,快到相遇时都选择往同一个方向避让,结果两个人同步侧移,还是面对面,谁也不走。

我在代码里处理这个问题用的方法很简单:给每个智能体加一个固定偏好方向的偏移量,偶数ID优先向右避让,奇数ID优先向左避让。这个规则在真实交通里也成立,类似“右侧通行”约定。加了之后,对称碰撞基本消失。

如果还死锁,就要检查是不是速度采样空间太小,导致机器人没有“绕大弯”的候选速度。出现这种情况,把 N_v 增大一些,让线速度采样点更多,避免只有低速选项,那样机器人想绕也绕不开。

6.3 轨迹明明看着没碰,却判定碰撞

这类问题多出在半径参数和轨迹采样点上。

第一种情况:机器人、障碍物的半径设置和可视化圆形半径不一致。我见过有人画圆时画的半径是0.2,但判碰用的半径是0.5,肉眼看起来根本碰不上,程序却疯狂报碰撞。排查方法就是统一在一个地方定义半径,可视化时直接读取同一个变量。

第二种情况:轨迹采样点太稀,动态障碍物速度太快,两个轨迹点之间其实已经穿模了,但采样点恰好都没落在碰撞范围内,导致漏检。解决办法是把轨迹细化,或者用线段与圆的相交检测,而不是只检查离散点。

6.4 运行速度慢,仿真卡成PPT

多智能体DWA的计算复杂度从理论上就是 O(numAgents × N_v × N_w × T),五个机器人、10×10采样、10步预测,意味着每帧要算5000条轨迹,MATLAB如果写得粗糙,跑起来会非常难受。

优化的办法有三个方向:

第一,只考虑近邻。每个智能体不会同时和所有障碍物、所有其他机器人相关,判断时先按距离筛选一遍,只对半径范围内的对象计算轨迹距离。多机数量上去后,这一步能从根上减少计算量。

第二,降采样。N_v 和 N_w 不用都取10,很多时候8×8就够用。我先用10×10跑通逻辑,再逐步降采样,观察性能指标不下降就行。

第三,绘图优化。不要在每一帧都用 plot 重新画所有轨迹线,那样很慢。可以每5帧刷新一次,或者用 set 函数更新现有图形对象的 XData、YData,比反复 plot 快很多。

6.5 动态障碍物总是“看到太晚”

这也是常见问题,本质上来自预测时域太短。我见过有人把 T 设为3,未来只能看0.3秒,高速动态障碍物从侧面冲过来时,算法根本来不及反应。

我的经验是把预测时域拉长到至少能覆盖最大相对速度跨越安全距离所需的时间。比如机器人最大速度1m/s,安全半径0.8m,相对相向而来的障碍物速度也是1m/s,那么最短反应时间大约是0.4秒,T至少取4步,加上分辨率余量,取8步以上比较安心。

7. 一点个人体会和后续扩展

这套代码完整跑下来之后,我最大的体会是:DWA不是一个“调参到位就万事大吉”的算法,它的上限取决于你对环境建模的精细程度。经典三项评价函数在静态单人场景里很灵,但一到动态多机环境,如果不把“未来风险”显式建模进评价函数,再好的参数也救不回来。

另外,多智能体避障真正的难点不是数学,而是“信息”的处理。你有对方的完整状态,还是只有局部感知,这直接决定了算法设计的天花板。这个项目里我先用了共享状态+匀速外推,算是打通了主链路。后续如果你还想深入,我认为有三个方向可以走:

一是把匀速外推换成更真实的运动模型,比如考虑对方的最大加速度,或者用卡尔曼滤波估计别人未来的轨迹;

二是把评价函数里的权重做成在线自适应,比如动态障碍物逼近时提高安全权重,空旷地带提高速度权重,这类方法在工程上很实用;

三是把全局规划加进来,用A*的全局路径做引导,DWA只负责局部执行,这样能解决DWA在复杂U形障碍物里陷入局部最小值的问题。

我可以明确说,把本文这个基线版本完整跑通一次,改一个变量记录一次指标,收获会比你直接去看十篇论文还要大。DWA这类方法,只有在亲手碰到它的“性格”之后,你才真正掌握它。如果你也在这个方向摸索,希望这些代码和调试记录能帮你少走一点弯路。

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

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

立即咨询