最近在搞路径规划项目,发现A*这玩意儿真是又好用又有趣。今天咱们用Matlab从头撸个带自定义地图的A*路径规划,保证代码比教程还清楚,直接开整

A*算法路径规划 A星Matlab路径规划 自定义栅格 可自行更改绘制栅格地图,自定义起始点目标点位置、未知障碍物位置 matlab实现 详细注释!

先来个灵魂草图:地图用栅格表示,0能走,1是墙,起点终点自己定。Matlab矩阵直接当地图简直不要太方便,先搞个10x10的示例地图:

% 初始化地图(可随便改尺寸)
map = zeros(10,10); 
% 手动加墙(中间一堵墙)
map(4:7,3) = 1;
map(4,4:7) = 1;

接下来定义起点终点。这里我故意把起点终点放在墙的两侧,看算法能不能绕过去:

start_node = [2, 3];  % [行, 列]
goal_node = [8, 7];

A*的核心是节点数据结构,咱们用Matlab的结构体搞定:

node.g = 0;          % 从起点到当前节点的实际代价
node.h = 0;          % 启发式估计值
node.f = 0;          % g + h
node.parent = [];    % 路径回溯用
node.position = [];  % 当前坐标

重点来了——启发函数。这里用曼哈顿距离(适合四方向移动),想用欧式距离的自己改:

function h = heuristic(pos, goal)
    % 曼哈顿距离
    h = abs(pos(1)-goal(1)) + abs(pos(2)-goal(2));
    % 欧式距离:norm(pos - goal) * 10
end

主循环才是重头戏。开放列表用优先队列(按f值排序),每次取最优节点展开:

open_list = struct2table(node);
closed_list = [];

while ~isempty(open_list)
    % 找f值最小的节点
    [~, idx] = min(open_list.f);
    current_node = open_list(idx, :);
    
    % 到达终点就收工
    if isequal(current_node.position, goal_node)
        path = reconstruct_path(current_node);
        break
    end
    
    % 把当前节点挪到关闭列表
    open_list(idx, :) = [];
    closed_list = [closed_list; current_node];
    
    % 遍历四个邻居方向
    neighbors = [...
        -1, 0;  % 上
        1, 0;   % 下
        0, -1;  % 左
        0, 1];  % 右
    
    for k = 1:size(neighbors,1)
        neighbor_pos = current_node.position + neighbors(k,:);
        
        % 跳过越界和障碍
        if neighbor_pos(1)<1 || neighbor_pos(1)>size(map,1) || ...
           neighbor_pos(2)<1 || neighbor_pos(2)>size(map,2) || ...
           map(neighbor_pos(1), neighbor_pos(2)) == 1
            continue
        end
        
        % 计算新g值(移动成本算10)
        tentative_g = current_node.g + 10;
        
        % 检查是否在关闭列表
        in_closed = any(cellfun(@(x) isequal(x, neighbor_pos), closed_list.position));
        
        % 新路径更优时才更新
        if ~in_closed || tentative_g < existing_g
            new_node = struct();
            new_node.position = neighbor_pos;
            new_node.parent = current_node.position;
            new_node.g = tentative_g;
            new_node.h = heuristic(neighbor_pos, goal_node);
            new_node.f = new_node.g + new_node.h;
            
            % 加入开放列表前查重
            in_open = find(cellfun(@(x) isequal(x, neighbor_pos), open_list.position));
            if isempty(in_open)
                open_list = [open_list; struct2table(new_node)];
            elseif open_list.g(in_open(1)) > tentative_g
                open_list(in_open(1), :) = struct2table(new_node);
            end
        end
    end
end

路径回溯函数像倒带一样往回找:

function path = reconstruct_node(node)
    path = [];
    while ~isempty(node.parent)
        path = [node.position; path];
        % 在关闭列表里找父节点
        parent_idx = find(cellfun(@(x) isequal(x, node.parent), closed_list.position));
        node = closed_list(parent_idx, :);
    end
    path = [start_node; path]; % 补上起点
end

跑起来的效果:算法会先贴着墙边试探,发现走不通马上绕远路。障碍物设置成L型的话,路径会拐两个直角弯。要是把启发函数换成对角线距离,路径会更丝滑,不过要注意移动成本的计算方式得跟着改。

A*算法路径规划 A星Matlab路径规划 自定义栅格 可自行更改绘制栅格地图,自定义起始点目标点位置、未知障碍物位置 matlab实现 详细注释!

几个可以魔改的地方:

  1. 把地图改成20x20,加点随机障碍物(用randi生成)
  2. 在计算g值时加入地形权重(比如沼泽地g+20)
  3. 允许斜角移动(八方向搜索)

遇到坑爹情况怎么办?比如完全封闭的环境,代码会陷入死循环。解决方法是在while循环里加个计数器,超过最大步数直接break报错。不过咱们示例地图是通的,所以不用慌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值