基于MATLAB的双移线路径规划与高速避障仿真

📅 发布时间:2026/9/15 11:19:20
基于MATLAB的双移线路径规划与高速避障仿真
简介这是面向自动驾驶与高级驾驶辅助系统ADAS的高速紧急避障仿真资源聚焦双移线路径规划与控制策略设计适合智能车辆方向的研究者、工程师及MATLAB/Simulink学习者用来理解动态避障算法。压缩包仅含1个m文件、大小约2KB即evasive.m完整源码文件虽小但覆盖了输入参数定义、双移线路径几何计算、车辆动力学建模、控制策略设计、仿真循环与结果可视化等关键环节。已有622人学习下载可直接在MATLAB中运行复现S/Z形双移线避让过程并进行参数调优或二次开发。通过该程序可直观观察不同车速、障碍物位置下的避障轨迹为验证控制算法、评估车辆动态极限以及教学演示提供轻量级参考实现。1. 高速避让为什么要走“双移线”而不是急转弯在高速公路上遇到前车突然掉落物或静止事故车时驾驶员本能会急打方向。但车速超过 80 km/h 时转向输入每增加 0.1 rad车辆的横摆角速度就会迅速建立若超过轮胎附着极限车身会出现侧滑甚至甩尾。双移线Double Lane Change避让策略的核心是让车辆在保持可控侧向加速度的前提下先向一侧偏移避开障碍再平稳回到原车道形成一条 S 形路径。evasive.m 实现的就是这条 S 形路径的规划与跟踪仿真。它不是让车“绕过”障碍物而是让车“滑过”障碍物旁边在时间、空间上同时完成换道和回正这对 ADAS 算法工程师验证高速避障逻辑非常实用。2. 双移线路径的几何构造从等速偏移到正弦过渡2.1 双移线的数学本质横向位移与纵向位移的解耦双移线路径可以看作一个关于纵向坐标 x 的函数 y_ref(x)。在高速场景下我们通常假设车辆纵向速度基本恒定因此时间维度可以折算到空间维度。路径设计的核心约束有三个起点和终点横向位置相同回到原车道、横向位移连续、横向速度即 y 对 x 的一阶导数连续同时尽量降低横向加速度峰值。一种经典构造方式是采用正弦函数叠加线性项。设道路宽度为 W换道总长度为 L那么路径可以写成y_ref(x) W/2 * (1 - cos(2*pi*x/L)) for x in [0, L]这个式子的优点是一阶导数连续且曲率峰值可控。但它的三阶导数不连续导致转向角在某些点出现跳变。改进方法是把路径分为两段第一段从本车道向临车道偏移 W第二段从临车道返回本车道。每段都可以使用五次多项式或正弦过渡函数这样不仅位移连续曲率也连续。2.2 用分段多项式构造可导的参考路径2.2.1 各段表达式与边界条件工程上我更倾向于用五次多项式构造每一段换道曲线因为它能同时约束位置、角度和曲率。设某一段换道的纵向起点为 x0、终点为 x1对应的横向位移从 y0 变为 y1那么路径可以表达为y(x) a0 a1*x a2*x^2 a3*x^3 a4*x^4 a5*x^5系数由六个边界条件唯一确定边界条件坐标形式数学表达起点位置x x0y(x0) y0起点航向角x x0y(x0) tan(theta0)起点曲率x x0y(x0) kappa0终点位置x x1y(x1) y1终点航向角x x1y(x1) tan(theta1)终点曲率x x1y(x1) kappa1对于双移线第一段从当前车道中心y0出发航向角为 0曲率为 0到达临车道中心yW时同样航向角为 0、曲率为 0。第二段则从 yW 回到 y0。这样每段都是对称的 S 形合在一起就是双移线。2.2.2 生成路径的 MATLAB 函数以下代码实现一个简单的双移线路径生成函数输入纵向长度 L、偏移宽度 W输出离散参考路径点function [x_ref, y_ref] generate_double_lane_change(L, W, N) % L: 单次换道的纵向长度 (m) % W: 横向偏移量 (m) % N: 离散点数 x_ref linspace(0, 2*L, N); y_ref zeros(N, 1); for i 1:N x x_ref(i); if x L % 第一段从本车道到临车道 xi x / L; y_ref(i) W * (6*xi^5 - 15*xi^4 10*xi^3); else % 第二段从临车道回到本车道 xi (x - L) / L; y_ref(i) W - W * (6*xi^5 - 15*xi^4 10*xi^3); end end end代码说明这里使用了 quintic五次多项式的标准形式6*xi^5 - 15*xi^4 10*xi^3是满足边界条件的过渡函数它的一阶和二阶导数在 xi0 和 xi1 处均为 0因此拼接处不会出现折角和曲率突变。注意第二段是W - W*f(xi)这样在 xL 处第一段终点 yW第二段起点也等于 W位移连续。2.3 路径连续性检验与曲率限制路径生成了必须验证曲率是否在车辆能接受的范围内。曲率 kappa 的计算公式是kappa |y| / (1 y^2)^(3/2)在 MATLAB 中可以对 y_ref 做数值微分dy gradient(y_ref, x_ref(2)-x_ref(1)); ddy gradient(dy, x_ref(2)-x_ref(1)); kappa abs(ddy) ./ (1 dy.^2).^1.5; [max_kappa, idx] max(kappa); fprintf(最大曲率: %.4f 1/m出现在 x%.2f m\n, max_kappa, x_ref(idx));如果最大曲率超过了轮胎附着极限对应的曲率一般根据侧向加速度极限 a_y_max 和车速 v 估算kappa_max a_y_max / v^2则需要增大 L 或降低车速。这里的一个常见误区是只看横向位移是否平滑忽略了曲率峰值。高速避障时曲率峰值决定转向角速度需求是车辆稳定性的直接指标。3. 车辆动力学模型与控制策略让轨迹可跟随3.1 自行车模型高速下不能忽略侧偏刚度路径只是参考车辆要跟踪它需要一个动力学模型。低速下可以用运动学自行车模型但高速避障时轮胎侧偏特性起主要作用必须使用动力学自行车模型。简化的状态量取为横向位置 y、横向速度 vy、横摆角 psi、横摆角速度 r、纵向速度 vx。状态方程如下vy_dot (Fy_f Fy_r)/m - vx*r r_dot (a*Fy_f - b*Fy_r)/Iz psi_dot r y_dot vy vx*psi其中 Fy_f 和 Fy_r 是前后轮侧向力在线性区可以表达为Fy_f -Cf * (atan((vy a*r)/vx - delta)) Fy_r -Cr * (atan((vy - b*r)/vx))Cf、Cr 是前后轴等效侧偏刚度a、b 是质心到前后轴的距离。这个模型忽略了车辆的俯仰和侧倾但足以评估双移线避让的稳定性。3.2 前馈反馈控制横向误差与航向误差的收敛跟踪双移线路径我通常采用“前馈转向角 反馈修正”的方式。前馈部分由路径曲率决定delta_ff atan(L_wb * kappa_ref)其中 L_wb 是轴距。反馈部分使用横向位置误差 e_y 和航向误差 e_psi 的 PD 控制function delta lateral_controller(e_y, e_psi, kappa_ref, vx) L_wb 2.8; % 轴距 (m) Kp_y 0.8; % 横向位置比例增益 Kd_y 0.2; % 横向位置微分增益 Kp_psi 1.5; % 航向角比例增益 % 前馈稳态转向角 delta_ff atan(L_wb * kappa_ref); % 弧度 % 反馈消除横向偏差和航向偏差 delta_fb Kp_y * e_y Kd_y * derivative(e_y) Kp_psi * e_psi; delta delta_ff delta_fb; % 限幅防止转向角超限 delta max(-0.5, min(0.5, delta)); end参数说明Kp_y 控制横向偏差的响应速度Kd_y 抑制偏差变化率引起的振荡Kp_psi 修正航向角误差。高速时如果 Kp_y 过大转向角会频繁饱和反而破坏稳定性一般推荐先调节 Kp_psi让航向先跟上再慢慢加大 Kp_y。3.2.1 PID 参数整定思路这里没有使用纯 PID而是“前馈 PD”因为前馈部分已经抵消了曲率带来的稳态误差。整定顺序是设反馈增益为 0固定车速观察车辆是否偏离参考路径。如果前馈准确稳态横向误差应该很小。逐渐增加 Kp_psi直到航向误差在 0.02 rad 以内。增加 Kp_y观察横向误差收敛时间一般要求 1 秒内误差小于 0.1 m。最后加 Kd_y 抑制超调但注意它对传感器噪声敏感。3.3 纵向速度规划避障时该减速还是匀速双移线避障有两种策略匀速避让和减速避让。evasive.m 如果默认匀速是为了测试纯转向能力但如果障碍物静止且距离较近必须同时减速。常见的做法是根据剩余纵向距离 s 和最大横向加速度 a_y_max 计算允许的最大车速% 给定路径曲率序列 kappa_path 和当前速度 vx a_y_limit 0.7 * 9.81; % 侧向加速度上限约 0.7g vx_max sqrt(a_y_limit ./ max(abs(kappa_path), 1e-6)); vx_target min(vx, vx_max);这样在曲率大的地方自动把目标车速降下来。需要注意的是减速本身也会改变路径跟踪的时序因此控制周期内要动态更新前馈项。若在仿真中发现车辆推头转向不足优先降低车速而不是盲目增加转向角。4. evasive.m 实战从路径生成到闭环仿真的完整流程4.1 输入参数定义初始状态、障碍物位置、避障阈值打开 evasive.m最前面通常是参数区。我一般会按下面的结构来组织方便批量跑不同场景%% 输入参数 param.vx 90/3.6; % 初始车速m/s90 km/h param.L 45; % 单次换道纵向长度m param.W 3.5; % 横向偏移量m一个半车道 param.dt 0.02; % 仿真步长s param.t_end 6; % 仿真总时长s param.x0 0; param.y0 0; % 初始位置 param.psi0 0; % 初始航向角rad % 障碍物位置前车静止位于本车道中心 obstacle.x 50; obstacle.y 0; obstacle.width 2.0; % 障碍物宽度m膨胀后半径 % 避障触发阈值预计碰撞时间小于 TTC_limit 时激活 param.TTC_limit 2.0; % 秒这些参数决定避障起点。实际中如果障碍物距离较远TTC 大于阈值车辆可以先减速而不触发变道一旦 TTC 低于阈值再生成双移线路径。这也是 evasive 算法的核心决策点。4.2 仿真循环时间步进、状态更新、安全检测主体仿真循环把路径生成、控制器、车辆模型串联起来。下面是一个精简但完整的闭环节点% 初始化状态向量 state [param.x0; param.y0; param.y0*0; 0; 0]; % x, y, vy, psi, r t 0; i 1; while t param.t_end % 1. 计算参考路径点以当前 x 为基准 [x_ref, y_ref] generate_double_lane_change(param.L, param.W, 200); dx state(1) - obstacle.x; if abs(dx) 5 ~evasive_triggered evasive_triggered true; % 记住触发位置之后的参考路径从这里开始 x_start_ref state(1); end % 2. 找到参考路径上离车辆最近的点的索引 [~, idx] min(abs(x_ref - (state(1)-x_start_ref))); % 3. 计算横向误差和航向误差 y_des interp1(x_ref, y_ref, state(1)-x_start_ref, spline); psi_des atan2(interp1(x_ref, gradient(y_ref), state(1)-x_start_ref, spline), 1); e_y y_des - state(2); e_psi psi_des - state(4); % 4. 曲率估计 kappa_ref interp1(x_ref, kappa, state(1)-x_start_ref, spline); % 5. 控制输出 delta lateral_controller(e_y, e_psi, kappa_ref, state(1)); % 6. 车辆动力学更新使用 ode4 或简单欧拉 state vehicle_dynamics_update(state, delta, param.dt); % 7. 安全检测车辆轨迹是否与障碍物边界相交 if check_collision(state, obstacle) warning(碰撞发生!); break; end t t param.dt; i i 1; % 记录轨迹 log(i,:) [state, t]; end代码逻辑说明先判断是否触发避障之后把车辆当前纵向位置映射到相对路径坐标通过插值获取期望横向位置和航向角。这里有两个容易出错的地方。一是参考路径的原点必须从触发时刻的车辆位置算起否则车辆会试图回到起点之前的路径二是在interp1时要用spline保持导数平滑直接用默认线性插值会导致航向角跳动。4.3 结果可视化与性能指标仿真结束后绘制车辆轨迹和障碍物位置的代码figure; hold on; grid on; plot(log(:,1), log(:,2), b-, LineWidth, 1.5); % 车辆轨迹 % 画出参考路径 [x_ref_p, y_ref_p] generate_double_lane_change(param.L, param.W, 200); plot(x_ref_p, y_ref_p, r--, LineWidth, 1); % 障碍物以圆形表示 viscircles([obstacle.x, obstacle.y], obstacle.width/2, Color, k); legend(实际轨迹, 参考路径, 障碍物); xlabel(纵向位置 x (m)); ylabel(横向位置 y (m)); axis equal;同时输出关键指标指标计算方式目标范围最大横向偏差max(abs(log(:,2) - y_ref_interp)) 0.3 m最大横向加速度max(abs(diff(log(:,2))) / dt) 0.7g碰撞安全距离min(车辆边缘到障碍物中心距离) 0.5 m这些指标可以直接用于评估算法在不同车速、不同 L 值下的表现。5. 验证双移线程序的三件套曲率检查、最大横向加速度、留出安全裕度5.1 曲率检查与重采样插值拿到双移线程序后第一件事不是跑仿真而是检查生成的参考路径是否可执行。直接对原始离散点求曲率结果可能受到采样密度影响。我建议先按参考速度对路径重采样采用等弧长采样再用csaps平滑最后计算曲率pp csaps(x_ref, y_ref, 0.999); % 平滑样条 y_smooth fnval(pp, x_smooth); dy fnder(pp); ddy fnder(dy, 2); kappa fnval(ddy, x_smooth) ./ (1 fnval(dy, x_smooth).^2).^1.5;csaps的平滑系数 0.999 表示保留 99.9% 原始波动只去掉微小的数值噪声。检查曲率序列中是否有尖峰如果有说明生成路径的边界条件在拼接点没有完全对齐需要回到第五章的多项式系数重新核对。5.2 用最大横向加速度评估避障是否平稳横向加速度可以近似为a_y vx^2 * kappa。在双移线路径中曲率峰值出现在两段换道的过渡区附近。如果计算出的 a_y 超过 0.7g实际车辆会发生明显侧倾甚至触发 ESC 介入。比较直观的验证方法是绘制 a_y 随时间的变化曲线观察是否存在两个对称的峰值。如果峰值一个大一个小说明第一段和第二段的 L 设置不平衡需要调整。另外一个实用技巧是把最大横向加速度换算成等效转向角需求delta_req atan(L_wb * kappa) a_y/m * (I_gain...)如果超过转向机构上限一般 0.5 rad则必须增大 L 或降低车速。5.3 把障碍物膨胀成圆形做碰撞检测双移线程序的核心目的不是“漂亮地绕过去”而是“安全地不碰”。在 MATLAB 中把车辆简化为一个半径为 r_car 的圆障碍物膨胀为半径为 r_obs 的圆。碰撞检测就是判断两个圆心距离是否小于半径之和function is_collision check_collision(state, obstacle, r_car, r_obs) dx state(1) - obstacle.x; dy state(2) - obstacle.y; dist sqrt(dx^2 dy^2); is_collision dist (r_car r_obs); end注意这里的车体半径必须覆盖车辆轴距的投影一般取 1.8~2.2 m障碍物膨胀半径取 1.5 m。将这个检测放在每个仿真步长里一旦返回 true就可以确认该组参数下避障失败。我习惯用fminsearch搜索最小可行的 L 值给定车速和偏移宽度不断缩小 L直到碰撞检测刚好不触发这个临界 L 就是该速度下的极限换道距离也是评估车辆动态性能上限的数值依据。本文还有配套的精品资源点击获取