基于Matlab的改进人工势场法路径规划与避障

基于Matlab的改进人工势场法路径规划与避障

一、算法原理与改进策略

1.1 传统人工势场法问题

问题 描述 解决方案
局部极小值 机器人陷入势能谷点无法逃脱 引入虚拟目标点/随机扰动/次梯度法
目标不可达 障碍物附近斥力使机器人无法到达 改进斥力函数,目标点附近斥力衰减
振荡问题 狭窄通道中来回振荡 引入速度势场/惯性项
障碍物附近震荡 斥力过大导致轨迹抖动 自适应调节引力斥力系数

1.2 改进势场函数

% 改进后的势场函数形式
U_att(q) = ½ * k_att * ρ_goal^n(q)  % 引力势
U_rep(q) = ½ * k_rep * (1/ρ_obs(q) - 1/ρ0)^2 * ρ_goal^m(q)  % 斥力势
F_total = -∇U_att(q) - ∇U_rep(q) + F_virtual  % 总力

二、MATLAB实现

2.1 主程序(main_improved_apf.m)

%% 改进人工势场法路径规划与避障
clc; clear; close all;
warning('off', 'all');

%% 1. 环境参数设置
env.map_size = [0, 100, 0, 100];  % 地图范围 [x_min, x_max, y_min, y_max]
env.start = [10, 10];             % 起点坐标
env.goal = [90, 90];              % 终点坐标
env.robot_radius = 2;             % 机器人半径
env.safety_margin = 1;            % 安全裕度

% 障碍物设置(圆形障碍物:[x, y, radius])
env.obstacles = [
    30, 30, 5;
    50, 40, 8;
    60, 60, 6;
    40, 70, 7;
    70, 20, 4;
    20, 60, 6;
    80, 50, 5
];

%% 2. 改进APF参数
apf.k_att = 5.0;         % 引力增益系数
apf.k_rep = 100.0;       % 斥力增益系数
apf.eta = 0.3;           % 斥力衰减系数
apf.rho0 = 20;           % 障碍物影响范围
apf.step_size = 1.0;     % 步长
apf.max_iter = 3000;     % 最大迭代次数
apf.goal_tol = 1.0;      % 目标容差
apf.alpha = 0.8;         % 动量系数
apf.beta = 0.1;          % 随机扰动系数
apf.n = 2;               % 引力势幂次
apf.m = 3;               % 斥力势幂次

%% 3. 初始化
fprintf('改进人工势场法路径规划开始...\n');
fprintf('起点: (%.1f, %.1f), 终点: (%.1f, %.1f)\n', ...
    env.start(1), env.start(2), env.goal(1), env.goal(2));

% 路径记录
path = zeros(apf.max_iter, 2);
path(1, :) = env.start;
vel = [0, 0];  % 速度初始化

% 性能记录
performance.iterations = 0;
performance.path_length = 0;
performance.min_clearance = inf;
performance.collision_free = true;
performance.local_minima = 0;

% 局部极小值检测
local_min_counter = 0;
local_min_threshold = 20;  % 连续20次位置变化小于阈值认为陷入局部极小
pos_history = zeros(local_min_threshold, 2);

% 虚拟目标点
virtual_goal_active = false;
virtual_goal = [0, 0];

%% 4. 主循环
figure('Position', [100, 100, 1200, 500]);
for iter = 1:apf.max_iter
    current_pos = path(iter, :);
    
    % 检查是否到达目标
    dist_to_goal = norm(current_pos - env.goal);
    if dist_to_goal < apf.goal_tol
        fprintf('成功到达目标点!迭代次数: %d\n', iter);
        performance.iterations = iter;
        path = path(1:iter, :);
        break;
    end
    
    % 记录位置历史
    pos_history(mod(iter-1, local_min_threshold)+1, :) = current_pos;
    
    % 计算合力
    [F_total, F_att, F_rep, min_dist] = compute_total_force(...
        current_pos, env.goal, env.obstacles, apf, virtual_goal_active, virtual_goal);
    
    % 更新最小通过距离
    performance.min_clearance = min(performance.min_clearance, min_dist);
    
    % 检查碰撞
    if check_collision(current_pos, env.obstacles, env.robot_radius, env.safety_margin)
        fprintf('发生碰撞!迭代次数: %d\n', iter);
        performance.collision_free = false;
        break;
    end
    
    % 局部极小值检测与处理
    [is_local_min, virtual_goal_active, virtual_goal] = ...
        handle_local_minima(iter, pos_history, current_pos, env.goal, ...
        env.obstacles, apf, virtual_goal_active, virtual_goal, local_min_threshold);
    
    if is_local_min
        performance.local_minima = performance.local_minima + 1;
        
        % 添加随机扰动
        random_force = apf.beta * (2*rand(1,2)-1);
        F_total = F_total + random_force;
        
        % 添加虚拟目标力
        if virtual_goal_active
            F_virtual = compute_virtual_force(current_pos, virtual_goal, apf);
            F_total = F_total + F_virtual;
        end
    end
    
    % 动量法更新速度
    vel = apf.alpha * vel + (1 - apf.alpha) * F_total;
    
    % 归一化并更新位置
    vel_norm = norm(vel);
    if vel_norm > 0
        vel = vel / vel_norm;
    end
    
    new_pos = current_pos + apf.step_size * vel;
    
    % 边界约束
    new_pos(1) = max(env.map_size(1) + env.robot_radius, ...
                     min(env.map_size(2) - env.robot_radius, new_pos(1)));
    new_pos(2) = max(env.map_size(3) + env.robot_radius, ...
                     min(env.map_size(4) - env.robot_radius, new_pos(2)));
    
    % 记录新位置
    if iter < apf.max_iter
        path(iter+1, :) = new_pos;
    end
    
    % 实时显示
    if mod(iter, 10) == 0
        visualize_path(env, path, iter, current_pos, F_att, F_rep, ...
                      virtual_goal_active, virtual_goal, apf);
    end
end

if iter == apf.max_iter
    fprintf('达到最大迭代次数!\n');
    performance.iterations = apf.max_iter;
    path = path(1:iter, :);
end

%% 5. 性能评估
performance.path_length = calculate_path_length(path);
performance = evaluate_performance(env, path, performance);

%% 6. 显示最终结果
plot_final_results(env, path, performance, apf);

2.2 合力计算函数(compute_total_force.m)

function [F_total, F_att, F_rep, min_dist] = compute_total_force(...
    pos, goal, obstacles, apf, virtual_goal_active, virtual_goal)
% 计算改进人工势场法的合力
% 输入:
%   pos: 当前位置
%   goal: 目标位置
%   obstacles: 障碍物列表
%   apf: 势场参数结构体
%   virtual_goal_active: 虚拟目标是否激活
%   virtual_goal: 虚拟目标位置
% 输出:
%   F_total: 总力
%   F_att: 引力
%   F_rep: 斥力
%   min_dist: 到最近障碍物的距离

% 1. 计算引力
if virtual_goal_active
    % 使用虚拟目标计算引力
    F_att = compute_attractive_force(pos, virtual_goal, apf);
else
    % 使用真实目标计算引力
    F_att = compute_attractive_force(pos, goal, apf);
end

% 2. 计算斥力
F_rep = [0, 0];
min_dist = inf;

n_obstacles = size(obstacles, 1);
for i = 1:n_obstacles
    obs_center = obstacles(i, 1:2);
    obs_radius = obstacles(i, 3);
    
    % 计算到障碍物边缘的距离
    dist_to_obs = norm(pos - obs_center) - obs_radius;
    
    if dist_to_obs < min_dist
        min_dist = dist_to_obs;
    end
    
    % 改进斥力:只在影响范围内计算
    if dist_to_obs <= apf.rho0
        % 计算斥力方向
        if dist_to_obs > 0
            dir_rep = (pos - obs_center) / norm(pos - obs_center);
        else
            % 如果在障碍物内部,取随机方向
            dir_rep = (2*rand(1,2)-1);
            dir_rep = dir_rep / norm(dir_rep);
        end
        
        % 改进的斥力函数
        d_goal = norm(pos - goal);
        if d_goal > 0
            % 斥力随接近目标而衰减
            rep_mag = apf.k_rep * (1/dist_to_obs - 1/apf.rho0) * ...
                     (d_goal^apf.m) / (dist_to_obs^2);
            
            % 增加切向力分量,帮助绕过障碍物
            F_rep_obs = rep_mag * dir_rep;
            
            % 添加切向分量
            if dist_to_obs < apf.rho0/2
                tangent_dir = [dir_rep(2), -dir_rep(1)];
                F_rep_obs = F_rep_obs + 0.3 * rep_mag * tangent_dir;
            end
            
            F_rep = F_rep + F_rep_obs;
        end
    end
end

% 3. 计算总力
F_total = F_att + F_rep;
end

function F_att = compute_attractive_force(pos, target, apf)
% 计算引力
% 改进的引力函数:使用指数衰减

dist = norm(pos - target);

if dist > 0
    % 改进的引力:在远处使用二次函数,近处使用线性函数
    if dist > 10
        F_att = apf.k_att * (target - pos);
    else
        F_att = apf.k_att * (target - pos) / dist;
    end
else
    F_att = [0, 0];
end
end

2.3 局部极小值处理(handle_local_minima.m)

function [is_local_min, virtual_goal_active, virtual_goal] = ...
    handle_local_minima(iter, pos_history, current_pos, goal, obstacles, ...
                       apf, virtual_goal_active, virtual_goal, threshold)
% 处理局部极小值问题
% 输入:
%   iter: 当前迭代次数
%   pos_history: 位置历史
%   current_pos: 当前位置
%   goal: 目标位置
%   obstacles: 障碍物
%   apf: 势场参数
%   virtual_goal_active: 虚拟目标是否激活
%   virtual_goal: 虚拟目标
%   threshold: 检测阈值
% 输出:
%   is_local_min: 是否陷入局部极小
%   virtual_goal_active: 更新后的虚拟目标状态
%   virtual_goal: 更新后的虚拟目标

is_local_min = false;

% 只在有足够历史数据时检测
if iter >= threshold
    % 计算最近threshold次迭代的位置变化
    pos_changes = zeros(threshold-1, 1);
    for i = 1:threshold-1
        pos1 = pos_history(i, :);
        pos2 = pos_history(i+1, :);
        pos_changes(i) = norm(pos1 - pos2);
    end
    
    % 如果最近的位置变化都很小,认为陷入局部极小
    if all(pos_changes < 0.1 * apf.step_size)
        is_local_min = true;
        fprintf('检测到局部极小值!迭代: %d\n', iter);
        
        % 如果虚拟目标未激活,创建虚拟目标
        if ~virtual_goal_active
            virtual_goal_active = true;
            
            % 方法1:在障碍物稀疏方向设置虚拟目标
            [free_direction, is_valid] = find_free_direction(current_pos, obstacles, apf.rho0);
            
            if is_valid
                virtual_goal = current_pos + 20 * free_direction;
            else
                % 方法2:随机方向
                random_angle = 2*pi*rand();
                virtual_goal = current_pos + 20 * [cos(random_angle), sin(random_angle)];
            end
            
            fprintf('设置虚拟目标: (%.1f, %.1f)\n', virtual_goal(1), virtual_goal(2));
        end
        
        % 检查是否应该切换到真实目标
        if virtual_goal_active
            dist_to_virtual = norm(current_pos - virtual_goal);
            if dist_to_virtual < 2.0
                % 到达虚拟目标,切换回真实目标
                virtual_goal_active = false;
                fprintf('到达虚拟目标,切换回真实目标\n');
            end
            
            % 检查是否有更直接的路径
            if can_reach_goal_directly(current_pos, goal, obstacles, apf.rho0)
                virtual_goal_active = false;
                fprintf('找到直接路径,切换回真实目标\n');
            end
        end
    end
end
end

function [free_dir, is_valid] = find_free_direction(pos, obstacles, rho0)
% 寻找自由方向
% 输入: pos - 当前位置
%       obstacles - 障碍物列表
%       rho0 - 影响范围
% 输出: free_dir - 自由方向
%       is_valid - 是否找到有效方向

n_directions = 36;  % 每10度一个方向
angles = linspace(0, 2*pi, n_directions+1);
angles = angles(1:end-1);

best_score = -inf;
best_angle = 0;
is_valid = false;

for i = 1:n_directions
    direction = [cos(angles(i)), sin(angles(i))];
    score = 0;
    
    % 计算这个方向的得分
    for j = 1:size(obstacles, 1)
        obs_center = obstacles(j, 1:2);
        obs_radius = obstacles(j, 3);
        
        dist_to_obs = norm(pos - obs_center) - obs_radius;
        
        if dist_to_obs < rho0
            % 计算障碍物方向
            obs_dir = (obs_center - pos) / norm(obs_center - pos);
            
            % 计算与障碍物的夹角
            angle_diff = acos(dot(direction, obs_dir));
            
            % 远离障碍物的方向得分高
            score = score + exp(-(angle_diff^2) * 10) * (rho0 - dist_to_obs);
        end
    end
    
    if score < best_score
        best_score = score;
        best_angle = angles(i);
        is_valid = true;
    end
end

free_dir = [cos(best_angle), sin(best_angle)];
end

function can_reach = can_reach_goal_directly(pos, goal, obstacles, rho0)
% 检查是否可以直接到达目标
% 输入: pos - 当前位置
%       goal - 目标位置
%       obstacles - 障碍物
%       rho0 - 影响范围
% 输出: can_reach - 是否可以直接到达

% 计算直线路径
path_vector = goal - pos;
path_length = norm(path_vector);
path_dir = path_vector / path_length;

can_reach = true;

% 检查路径上的障碍物
for i = 1:size(obstacles, 1)
    obs_center = obstacles(i, 1:2);
    obs_radius = obstacles(i, 3);
    
    % 计算点到线段的最小距离
    t = max(0, min(1, dot(obs_center - pos, path_vector) / (path_length^2)));
    projection = pos + t * path_vector;
    dist = norm(obs_center - projection);
    
    if dist < obs_radius + rho0/2
        can_reach = false;
        break;
    end
end
end

2.4 虚拟目标力计算(compute_virtual_force.m)

function F_virtual = compute_virtual_force(pos, virtual_goal, apf)
% 计算虚拟目标力
% 输入: pos - 当前位置
%       virtual_goal - 虚拟目标
%       apf - 势场参数
% 输出: F_virtual - 虚拟力

dist = norm(pos - virtual_goal);

if dist > 0
    % 使用与真实引力相同的计算方式
    F_virtual = 0.5 * apf.k_att * (virtual_goal - pos);
    
    % 归一化
    F_norm = norm(F_virtual);
    if F_norm > 0
        F_virtual = F_virtual / F_norm;
    end
else
    F_virtual = [0, 0];
end
end

2.5 碰撞检测函数(check_collision.m)

function collision = check_collision(pos, obstacles, robot_radius, safety_margin)
% 碰撞检测
% 输入: pos - 当前位置
%       obstacles - 障碍物列表
%       robot_radius - 机器人半径
%       safety_margin - 安全裕度
% 输出: collision - 是否发生碰撞

collision = false;
total_radius = robot_radius + safety_margin;

for i = 1:size(obstacles, 1)
    obs_center = obstacles(i, 1:2);
    obs_radius = obstacles(i, 3);
    
    dist = norm(pos - obs_center);
    
    if dist < (obs_radius + total_radius)
        collision = true;
        return;
    end
end
end

2.6 路径评估函数

function path_length = calculate_path_length(path)
% 计算路径长度
% 输入: path - 路径点
% 输出: path_length - 路径长度

path_length = 0;
for i = 1:size(path, 1)-1
    segment_length = norm(path(i+1, :) - path(i, :));
    path_length = path_length + segment_length;
end
end

function performance = evaluate_performance(env, path, performance)
% 评估路径性能
% 输入: env - 环境参数
%       path - 路径
%       performance - 性能结构体
% 输出: performance - 更新后的性能结构体

% 1. 计算平滑度
performance.smoothness = calculate_path_smoothness(path);

% 2. 计算安全性评分
performance.safety_score = calculate_safety_score(path, env.obstacles, env.robot_radius);

% 3. 计算效率
direct_distance = norm(env.goal - env.start);
performance.efficiency = direct_distance / performance.path_length * 100;

% 4. 计算转弯次数
performance.turn_count = calculate_turn_count(path);

fprintf('\n=== 路径性能评估 ===\n');
fprintf('路径长度: %.2f (直接距离: %.2f)\n', performance.path_length, direct_distance);
fprintf('效率: %.1f%%\n', performance.efficiency);
fprintf('最小通过距离: %.2f\n', performance.min_clearance);
fprintf('安全性评分: %.2f/10\n', performance.safety_score);
fprintf('路径平滑度: %.2f/10\n', performance.smoothness);
fprintf('转弯次数: %d\n', performance.turn_count);
fprintf('局部极小值次数: %d\n', performance.local_minima);
fprintf('是否无碰撞: %s\n', string(performance.collision_free));
end

function smoothness = calculate_path_smoothness(path)
% 计算路径平滑度
% 输入: path - 路径
% 输出: smoothness - 平滑度评分 (0-10)

if size(path, 1) < 3
    smoothness = 10;
    return;
end

total_angle_change = 0;
for i = 2:size(path, 1)-1
    v1 = path(i, :) - path(i-1, :);
    v2 = path(i+1, :) - path(i, :);
    
    if norm(v1) > 0 && norm(v2) > 0
        v1 = v1 / norm(v1);
        v2 = v2 / norm(v2);
        angle = acos(dot(v1, v2));
        total_angle_change = total_angle_change + abs(angle);
    end
end

% 转换为评分 (0-10,越高越平滑)
max_angle = pi * (size(path, 1)-2);
if max_angle > 0
    smoothness = 10 * (1 - total_angle_change / max_angle);
    smoothness = max(0, min(10, smoothness));
else
    smoothness = 10;
end
end

function safety_score = calculate_safety_score(path, obstacles, robot_radius)
% 计算安全性评分
% 输入: path - 路径
%       obstacles - 障碍物
%       robot_radius - 机器人半径
% 输出: safety_score - 安全性评分 (0-10)

if isempty(path)
    safety_score = 0;
    return;
end

min_distances = zeros(size(path, 1), 1);
for i = 1:size(path, 1)
    pos = path(i, :);
    min_dist = inf;
    
    for j = 1:size(obstacles, 1)
        obs_center = obstacles(j, 1:2);
        obs_radius = obstacles(j, 3);
        
        dist = norm(pos - obs_center) - obs_radius - robot_radius;
        if dist < min_dist
            min_dist = dist;
        end
    end
    
    min_distances(i) = min_dist;
end

% 使用平均距离计算安全性评分
avg_safe_dist = mean(min_distances);
safety_score = min(10, avg_safe_dist * 2);  % 每0.5单位距离得1分
end

function turn_count = calculate_turn_count(path)
% 计算转弯次数
% 输入: path - 路径
% 输出: turn_count - 转弯次数

if size(path, 1) < 3
    turn_count = 0;
    return;
end

turn_count = 0;
angle_threshold = pi/6;  % 30度阈值

for i = 2:size(path, 1)-1
    v1 = path(i, :) - path(i-1, :);
    v2 = path(i+1, :) - path(i, :);
    
    if norm(v1) > 0 && norm(v2) > 0
        v1 = v1 / norm(v1);
        v2 = v2 / norm(v2);
        angle = acos(dot(v1, v2));
        
        if abs(angle) > angle_threshold
            turn_count = turn_count + 1;
        end
    end
end
end

2.7 可视化函数

function visualize_path(env, path, iter, current_pos, F_att, F_rep, ...
                       virtual_goal_active, virtual_goal, apf)
% 实时可视化路径规划过程
% 输入: env - 环境参数
%       path - 当前路径
%       iter - 当前迭代
%       current_pos - 当前位置
%       F_att, F_rep - 引力斥力
%       virtual_goal_active - 虚拟目标状态
%       virtual_goal - 虚拟目标位置
%       apf - 势场参数

% 清除当前图形
clf;

% 子图1:路径规划
subplot(1,2,1);
hold on; grid on; axis equal;
axis(env.map_size);
title(sprintf('改进人工势场法 - 迭代: %d', iter));

% 绘制障碍物
for i = 1:size(env.obstacles, 1)
    rectangle('Position', [env.obstacles(i,1)-env.obstacles(i,3), ...
                          env.obstacles(i,2)-env.obstacles(i,3), ...
                          2*env.obstacles(i,3), 2*env.obstacles(i,3)], ...
             'Curvature', [1,1], 'FaceColor', [0.8, 0.2, 0.2], 'EdgeColor', 'k', 'LineWidth', 1.5);
    
    % 绘制障碍物影响范围
    viscircles(env.obstacles(i,1:2), env.obstacles(i,3)+apf.rho0, ...
              'Color', [0.9, 0.9, 0.2], 'LineWidth', 0.5, 'LineStyle', '--');
end

% 绘制起点和终点
plot(env.start(1), env.start(2), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
plot(env.goal(1), env.goal(2), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');

% 绘制当前路径
plot(path(1:iter, 1), path(1:iter, 2), 'b-', 'LineWidth', 2);

% 绘制当前位置
plot(current_pos(1), current_pos(2), 'bo', 'MarkerSize', 8, 'MarkerFaceColor', 'b');

% 绘制力向量
scale = 5;
if norm(F_att) > 0
    quiver(current_pos(1), current_pos(2), F_att(1)*scale, F_att(2)*scale, ...
           'Color', 'g', 'LineWidth', 2, 'MaxHeadSize', 0.5);
end
if norm(F_rep) > 0
    quiver(current_pos(1), current_pos(2), F_rep(1)*scale, F_rep(2)*scale, ...
           'Color', 'r', 'LineWidth', 2, 'MaxHeadSize', 0.5);
end

% 绘制虚拟目标
if virtual_goal_active
    plot(virtual_goal(1), virtual_goal(2), 'm*', 'MarkerSize', 12, 'LineWidth', 2);
    plot([current_pos(1), virtual_goal(1)], [current_pos(2), virtual_goal(2)], ...
         'm--', 'LineWidth', 1);
end

% 添加图例
legend_items = {'起点', '终点', '路径', '当前位置', '引力', '斥力'};
if virtual_goal_active
    legend_items{end+1} = '虚拟目标';
end
legend(legend_items, 'Location', 'northeastoutside');

xlabel('X坐标');
ylabel('Y坐标');

% 子图2:势场可视化
subplot(1,2,2);
[x_grid, y_grid] = meshgrid(linspace(env.map_size(1), env.map_size(2), 50), ...
                           linspace(env.map_size(3), env.map_size(4), 50));
U_total = zeros(size(x_grid));

% 计算总势场
for i = 1:numel(x_grid)
    pos = [x_grid(i), y_grid(i)];
    
    % 计算引力势
    dist_goal = norm(pos - env.goal);
    U_att = 0.5 * apf.k_att * dist_goal^apf.n;
    
    % 计算斥力势
    U_rep = 0;
    for j = 1:size(env.obstacles, 1)
        obs_center = env.obstacles(j, 1:2);
        obs_radius = env.obstacles(j, 3);
        
        dist_obs = norm(pos - obs_center) - obs_radius;
        if dist_obs < apf.rho0
            U_rep = U_rep + 0.5 * apf.k_rep * (1/dist_obs - 1/apf.rho0)^2 * dist_goal^apf.m;
        end
    end
    
    U_total(i) = U_att + U_rep;
end

% 绘制势场
contourf(x_grid, y_grid, U_total, 20, 'LineStyle', 'none');
hold on;
colorbar;
title('总势场分布');

% 绘制障碍物
for i = 1:size(env.obstacles, 1)
    rectangle('Position', [env.obstacles(i,1)-env.obstacles(i,3), ...
                          env.obstacles(i,2)-env.obstacles(i,3), ...
                          2*env.obstacles(i,3), 2*env.obstacles(i,3)], ...
             'Curvature', [1,1], 'FaceColor', [0.8, 0.2, 0.2], 'EdgeColor', 'k', 'LineWidth', 1.5);
end

% 绘制路径
plot(path(1:iter, 1), path(1:iter, 2), 'w-', 'LineWidth', 2);
plot(env.start(1), env.start(2), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
plot(env.goal(1), env.goal(2), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');

axis equal;
axis(env.map_size);
xlabel('X坐标');
ylabel('Y坐标');

drawnow;
end

function plot_final_results(env, path, performance, apf)
% 绘制最终结果
figure('Position', [100, 100, 1400, 600]);

% 子图1:完整路径
subplot(1,3,1);
hold on; grid on; axis equal;
axis(env.map_size);
title('改进人工势场法 - 最终路径');

% 绘制障碍物
for i = 1:size(env.obstacles, 1)
    rectangle('Position', [env.obstacles(i,1)-env.obstacles(i,3), ...
                          env.obstacles(i,2)-env.obstacles(i,3), ...
                          2*env.obstacles(i,3), 2*env.obstacles(i,3)], ...
             'Curvature', [1,1], 'FaceColor', [0.8, 0.2, 0.2], 'EdgeColor', 'k', 'LineWidth', 1.5);
end

% 绘制起点和终点
plot(env.start(1), env.start(2), 'go', 'MarkerSize', 12, 'MarkerFaceColor', 'g');
plot(env.goal(1), env.goal(2), 'ro', 'MarkerSize', 12, 'MarkerFaceColor', 'r');

% 绘制路径
plot(path(:,1), path(:,2), 'b-', 'LineWidth', 2);
plot(path(:,1), path(:,2), 'b.', 'MarkerSize', 8);

% 绘制机器人轨迹
for i = 1:5:size(path,1)
    rectangle('Position', [path(i,1)-env.robot_radius, path(i,2)-env.robot_radius, ...
                          2*env.robot_radius, 2*env.robot_radius], ...
             'Curvature', [1,1], 'EdgeColor', 'b', 'LineWidth', 0.5, 'LineStyle', '--');
end

xlabel('X坐标');
ylabel('Y坐标');
legend('起点', '终点', '路径', '机器人位置', 'Location', 'best');

% 子图2:距离障碍物曲线
subplot(1,3,2);
hold on; grid on;
distances = zeros(size(path,1), 1);
for i = 1:size(path,1)
    pos = path(i, :);
    min_dist = inf;
    for j = 1:size(env.obstacles, 1)
        obs_center = env.obstacles(j, 1:2);
        obs_radius = env.obstacles(j, 3);
        dist = norm(pos - obs_center) - obs_radius;
        if dist < min_dist
            min_dist = dist;
        end
    end
    distances(i) = min_dist;
end

plot(1:size(path,1), distances, 'b-', 'LineWidth', 2);
plot([1, size(path,1)], [env.robot_radius+env.safety_margin, env.robot_radius+env.safety_margin], ...
     'r--', 'LineWidth', 1.5);
xlabel('路径点序号');
ylabel('到最近障碍物距离');
title('安全性分析');
legend('实际距离', '安全阈值', 'Location', 'best');

% 子图3:性能指标雷达图
subplot(1,3,3);
metrics = {'路径长度', '安全性', '平滑度', '效率', '转弯次数'};
values = [performance.path_length/100, ...
          performance.safety_score/10, ...
          performance.smoothness/10, ...
          performance.efficiency/100, ...
          min(1, performance.turn_count/10)];

% 归一化(越小越好或越大越好调整)
values(1) = 1 - values(1);  % 路径长度越小越好
values(5) = 1 - values(5);  % 转弯次数越少越好

% 绘制雷达图
angles = linspace(0, 2*pi, length(metrics)+1);
angles = angles(1:end-1);
values = [values, values(1)];
angles = [angles, angles(1)];

polarplot(angles, values, 'b-', 'LineWidth', 2);
hold on;
fill(angles, values, 'b', 'FaceAlpha', 0.2);
thetalim([0, 360]);
rlim([0, 1]);
title('性能指标雷达图');
legend('改进APF', 'Location', 'southoutside');

% 添加参数表
annotation('textbox', [0.02, 0.02, 0.3, 0.15], ...
    'String', sprintf('APF参数:\nk_{att}=%.1f, k_{rep}=%.1f\nρ_0=%.1f, α=%.1f\n步长=%.1f', ...
    apf.k_att, apf.k_rep, apf.rho0, apf.alpha, apf.step_size), ...
    'FitBoxToText', 'on', 'BackgroundColor', 'w');

% 保存结果
saveas(gcf, 'improved_apf_result.png');
end

参考代码 基于Matlab的改进人工势场法实现路径规划与避障 www.youwenfan.com/contentcnu/54690.html

三、高级功能扩展

3.1 动态障碍物处理

function [updated_obstacles, predicted_positions] = handle_dynamic_obstacles(...
    obstacles, current_time, velocity, dt)
% 处理动态障碍物
% 输入: obstacles - 障碍物列表
%       current_time - 当前时间
%       velocity - 速度场
%       dt - 时间步长
% 输出: updated_obstacles - 更新后的障碍物
%       predicted_positions - 预测位置

updated_obstacles = obstacles;
predicted_positions = cell(size(obstacles, 1), 1);

% 假设前3个障碍物是动态的
for i = 1:min(3, size(obstacles, 1))
    % 简谐运动模型
    amplitude = 5;
    frequency = 0.5;
    
    % 更新位置
    dx = amplitude * sin(2*pi*frequency*current_time);
    dy = amplitude * cos(2*pi*frequency*current_time);
    
    updated_obstacles(i, 1:2) = obstacles(i, 1:2) + [dx, dy];
    
    % 预测未来位置
    prediction_steps = 5;
    predicted_positions{i} = zeros(prediction_steps, 2);
    for step = 1:prediction_steps
        t_pred = current_time + step * dt;
        dx_pred = amplitude * sin(2*pi*frequency*t_pred);
        dy_pred = amplitude * cos(2*pi*frequency*t_pred);
        predicted_positions{i}(step, :) = obstacles(i, 1:2) + [dx_pred, dy_pred];
    end
end
end

3.2 多机器人协同

function F_robot = compute_robot_repulsion(current_robot, other_robots, k_robot, rho_robot)
% 计算机器人间的斥力
% 输入: current_robot - 当前机器人位置
%       other_robots - 其他机器人位置
%       k_robot - 机器人间斥力系数
%       rho_robot - 机器人间影响距离
% 输出: F_robot - 机器人间斥力

F_robot = [0, 0];
n_robots = size(other_robots, 1);

for i = 1:n_robots
    other_pos = other_robots(i, :);
    dist = norm(current_robot - other_pos);
    
    if dist > 0 && dist < rho_robot
        dir = (current_robot - other_pos) / dist;
        magnitude = k_robot * (1/dist - 1/rho_robot) * (1/dist^2);
        F_robot = F_robot + magnitude * dir;
    end
end
end

四、参数调优指南

参数 推荐范围 影响 调优建议
k_att 1-20 引力强度 增大加快收敛,但可能振荡
k_rep 50-200 斥力强度 增大提高安全性,但可能无法到达目标
ρ0 10-30 障碍物影响范围 增大提前避障,但计算量增加
α 0.5-0.9 动量系数 增大提高平滑性,降低响应速度
β 0.05-0.2 随机扰动系数 增大增强跳出局部极小能力,降低稳定性
步长 0.5-2.0 移动步长 增大加快规划,但可能振荡或不安全

五、应用场景

5.1 移动机器人导航

% 室内环境导航示例
env.map_size = [0, 50, 0, 50];  % 室内环境
env.start = [5, 5];
env.goal = [45, 45];
env.robot_radius = 0.5;

% 墙壁和家具障碍物
env.obstacles = [
    % 墙壁
    25, 0, 2; 25, 50, 2; 0, 25, 2; 50, 25, 2;
    % 家具
    10, 20, 3; 30, 15, 2; 40, 30, 4; 15, 40, 3
];

5.2 无人机路径规划

% 三维扩展
function F_total_3D = compute_3d_force(pos_3d, goal_3d, obstacles_3d, params)
% 3D人工势场计算
% 输入: pos_3d - 三维位置
%       goal_3d - 三维目标
%       obstacles_3d - 三维障碍物
%       params - 参数
% 输出: F_total_3D - 三维合力

% 引力
dist_goal = norm(pos_3d - goal_3d);
F_att_3d = params.k_att * (goal_3d - pos_3d);

% 斥力
F_rep_3d = [0, 0, 0];
for i = 1:size(obstacles_3d, 1)
    obs_center = obstacles_3d(i, 1:3);
    obs_radius = obstacles_3d(i, 4);
    
    dist_obs = norm(pos_3d - obs_center) - obs_radius;
    
    if dist_obs < params.rho0
        dir_rep = (pos_3d - obs_center) / norm(pos_3d - obs_center);
        magnitude = params.k_rep * (1/dist_obs - 1/params.rho0) * ...
                   (dist_goal^params.m) / (dist_obs^2);
        F_rep_3d = F_rep_3d + magnitude * dir_rep;
    end
end

F_total_3D = F_att_3d + F_rep_3d;
end

六、总结

这个改进的人工势场法实现具有以下特点:

局部极小值处理:虚拟目标+随机扰动+切向力
目标可达保证:改进斥力函数,目标点附近斥力衰减
平滑路径生成:动量法+路径平滑度评估
安全性保证:碰撞检测+安全裕度+安全性评分
动态适应性:可扩展支持动态障碍物
全面评估:路径长度、平滑度、安全性、效率等多指标评估

核心改进

  1. 改进的斥力函数,避免目标不可达
  2. 虚拟目标策略跳出局部极小
  3. 切向力帮助绕过障碍物
  4. 动量法提高路径平滑性
  5. 多指标性能评估体系

应用场景

进一步优化方向

  1. 结合A*等全局规划器
  2. 引入机器学习自适应参数
  3. 支持非完整约束机器人
  4. 多智能体协同规划
  5. 实时性能优化

专注于matlab/simulink,电子电路,编程