在航海自动化领域,船舶避碰系统是保障航行安全的核心技术。传统的人工操舵方式在面对复杂海况和多变障碍物时存在反应延迟和人为失误的风险。人工势场法(Artificial Potential Field)作为路径规划领域的经典算法,通过模拟物理场中的引力和斥力作用,为船舶提供实时、自适应的避障决策支持。
这个项目使用MATLAB实现了基于人工势场法的船舶自动避碰系统原型,主要包含三个核心功能:
实际应用中,这类系统通常需要与雷达、AIS等传感器数据联动,本文实现的简化版本可作为算法验证和教学演示的基础框架。
人工势场法的核心思想是将航行环境抽象为势能场,包含两种基本势场:
引力场:由目标点产生,计算公式为:
code复制U_att = 0.5 * k_att * (d_target)^2
其中k_att为引力系数,d_target为船舶与目标点的欧氏距离
斥力场:由障碍物产生,采用分段函数:
code复制U_rep = 0.5 * k_rep * (1/d_obs - 1/d0)^2 (当d_obs < d0)
U_rep = 0 (当d_obs ≥ d0)
d0为安全距离阈值,d_obs为船舶与障碍物的距离
船舶受到的合力是各势场梯度的矢量和:
code复制F_total = -∇U_att + Σ(-∇U_rep)
具体到二维平面:
通过多次实测验证,推荐以下参数范围:
matlab复制%% 环境参数设置
target = [100, 100]; % 目标点坐标
obstacles = [50, 50; 70, 80]; % 障碍物坐标矩阵
ship_pos = [0, 0]; % 船舶初始位置
params.k_att = 0.1; % 引力系数
params.k_rep = 100; % 斥力系数
params.d0 = 10; % 安全距离
params.step = 1; % 移动步长
params.max_iter = 500; % 最大迭代次数
%% 轨迹记录变量初始化
trajectory = ship_pos; % 位置轨迹
turn_angles = []; % 转向角度记录
matlab复制for iter = 1:params.max_iter
% 计算到目标点距离
d_target = norm(target - ship_pos);
% 引力计算(标准化方向向量)
if d_target > 0
F_att = params.k_att * (target - ship_pos)/d_target;
else
break; % 到达目标点
end
% 斥力计算
F_rep = [0, 0];
for obs = obstacles'
d_obs = norm(obs' - ship_pos);
if d_obs < params.d0
dir_vector = (ship_pos - obs')/d_obs;
F_rep = F_rep + params.k_rep*(1/d_obs-1/params.d0)*...
(1/d_obs^2)*dir_vector;
end
end
% 合力计算与位置更新
F_total = F_att + F_rep;
unit_force = F_total/norm(F_total);
ship_pos = ship_pos + params.step * unit_force;
% 记录转向角度
if iter > 1
prev_dir = trajectory(end,:) - trajectory(end-1,:);
curr_dir = unit_force;
turn_angle = atan2d(prev_dir(1)*curr_dir(2)-prev_dir(2)*curr_dir(1),...
prev_dir*curr_dir');
turn_angles(end+1) = turn_angle;
end
% 存储新位置
trajectory(end+1,:) = ship_pos;
% 终止条件检查
if d_target < params.step
disp(['到达目标点,迭代次数:', num2str(iter)]);
break;
end
end
matlab复制%% 动态轨迹绘制
figure('Position', [100,100,600,600]);
h_ax = gca;
axis equal;
xlim([0 120]); ylim([0 120]);
grid on; hold on;
% 绘制静态元素
plot(target(1), target(2), 'gp', 'MarkerSize', 15, 'LineWidth', 2);
for obs = obstacles'
plot(obs(1), obs(2), 'ro', 'MarkerSize', 10, 'LineWidth', 2);
end
% 创建动态元素
h_ship = plot(nan, nan, 'b-o', 'MarkerSize', 6);
h_path = plot(nan, nan, 'b-', 'LineWidth', 1.5);
% GIF生成设置
gif_file = 'ship_navigation.gif';
delay_time = 0.1; % 帧间隔(秒)
for k = 1:size(trajectory,1)
% 更新船舶和路径
set(h_ship, 'XData', trajectory(k,1), 'YData', trajectory(k,2));
if k > 1
set(h_path, 'XData', trajectory(1:k,1), 'YData', trajectory(1:k,2));
end
% 捕获帧并写入GIF
frame = getframe(h_ax);
im = frame2im(frame);
[A, map] = rgb2ind(im, 256);
if k == 1
imwrite(A, map, gif_file, 'gif', 'LoopCount', Inf, 'DelayTime', delay_time);
else
imwrite(A, map, gif_file, 'gif', 'WriteMode', 'append', 'DelayTime', delay_time);
end
pause(0.05); % 控制绘制速度
end
现象:当引力与斥力平衡时,船舶会陷入停滞(如图示情况)
code复制[图示位置]
障碍物
↑
船舶
↓
目标点
解决方案:
matlab复制if norm(F_total) < 0.1 % 检测力平衡
ship_pos = ship_pos + randn(1,2)*0.5;
end
扩展代码支持移动障碍物预测:
matlab复制% 在障碍物定义中添加速度向量
obstacles = [50,50, 0.2,-0.1; % [x,y,vx,vy]
70,80, -0.3,0.2];
% 在主循环中更新障碍物位置
obstacles(:,1:2) = obstacles(:,1:2) + obstacles(:,3:4)*params.step;
通过添加船舶间的互斥势场实现:
matlab复制% 在斥力计算部分添加:
for other_ship in ship_list
if other_ship != current_ship
d_ship = norm(other_ship.pos - ship_pos);
if d_ship < params.d0_ship
F_rep = F_rep + k_rep_ship*(1/d_ship-1/params.d0_ship)*...
(1/d_ship^2)*(ship_pos-other_ship.pos)/d_ship;
end
end
end
实时性优化:
传感器集成:
matlab复制% 模拟雷达数据输入
function obstacles = get_radar_data()
[az, r] = radar_scan(); % 获取极坐标数据
[x,y] = pol2cart(deg2rad(az), r);
obstacles = [x(:), y(:)];
end
航海特性适配:
测试验证建议:
这个实现版本虽然简化,但完整呈现了人工势场法的核心思想。在实际船舶系统中,还需要考虑更多现实约束条件,建议在掌握基本原理后,逐步扩展以下功能模块:传感器噪声处理、多目标决策、人机交互接口等。