精准导航:用A*算法优化栅格地图的路径规划【附Matlab代码】

目录

    • 1.算法原理
    • 2.代码讲解
    • 3.结果展示
    • 4.代码获取


1.算法原理

A* 算法是一种基于传统图搜索的智能启发式算法,它具有稳定性高、节点搜索效率高等优点。主要原理为:以起点作为初始节点,搜索初始节点旁 8 个邻域,并通过启发函数评估后选择代价最小的节点,然后搜索这个节点的 8 个邻域,选择下一个代价最小的节点,重复上述步骤,直到选择的节点与目标点重合,将这些代价最小的节点连接起来就得到一条最优路径。

A*算法代价函数:
f ( n ) = g ( n ) + h ( n ) (1) f\begin{pmatrix}n\end{pmatrix}=g\begin{pmatrix}n\end{pmatrix}+h\begin{pmatrix}n\end{pmatrix}\tag{1} f(n)=g(n)+h(n)(1)
其中, f(n)为n节点的总代价值, g(n)代表从n节点到初始节点的最短路径代价值, h(n)代表从n节点到目标节点代价的估计值。
在这里插入图片描述

2.代码讲解

地图参数初始化

start_node = [1, 1]; %起点
target_node = [20, 20];%坐标
% 栅格地图的行数、列数定义
m = 20;
n = 20; 

% 加载地图
MAP = [0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0; 
   0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0; 
   0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0; 
   0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 0 0; 
   0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0 0; 
   0 1 1 0 1 0 0 0  0 0 0 0 0 0 1 1 1 0 0 0; 
   0 1 1 0 1 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0;
   0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0; 
   0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0; 
   0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0; 
   0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0; 
   0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0; 
   0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0; 
   0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 0; 
   1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0; 
   1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0; 
   0 0 0 1 0 0 1 1 0 1 1 1 0 0 0 0 0 1 1 0; 
   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0; 
   0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0; 
   0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0;];

地图中1代表障碍物,0代表可行区域,绿色代表起点,红色代表终点:
在这里插入图片描述

获得父结点的可行子结点列表

function child_nodes = child_nodes_cal(parent_node, m, n, obs, closeList)

child_nodes = [];
field = [1,1; n,1; n,m; 1,m]; %边界

% 左上结点
child_node = [parent_node(1)-1, parent_node(2)+1];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2)) %判断是否在地图内
    if ~ismember(child_node, obs, 'rows') %如果子结点不是障碍物
        child_nodes = [child_nodes; child_node];
    end
end

% 上结点
child_node = [parent_node(1), parent_node(2)+1];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

% 右上结点
child_node = [parent_node(1)+1, parent_node(2)+1];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

% 左结点
child_node = [parent_node(1)-1, parent_node(2)];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

% 右结点
child_node = [parent_node(1)+1, parent_node(2)];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

% 左下结点
child_node = [parent_node(1)-1, parent_node(2)-1];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

% 下结点
child_node = [parent_node(1), parent_node(2)-1];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

% 右下结点
child_node = [parent_node(1)+1, parent_node(2)-1];
if inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))
    if ~ismember(child_node, obs, 'rows')
        child_nodes = [child_nodes; child_node];
    end
end

%% 排除已经存在于closeList的节点
delete_idx = [];
for i = 1:size(child_nodes, 1)
    if ismember(child_nodes(i,:), closeList , 'rows')
        delete_idx(end+1,:) = i;
    end
end
child_nodes(delete_idx, :) = [];

采用8领域搜索方式,红色箭头为可行走8个方向:

在这里插入图片描述

函数child_nodes_cal.m得到父结点的可行子结点列表,可行子结点需要判断是否在地图内,通过代码进行判断:

inpolygon(child_node(1), child_node(2), field(:,1), field(:,2))

另一方面,可行子结点不能为障碍物:

~ismember(child_node, obs, 'rows')

起点预处理

% 初始化closeList
closeList = start_node;
closeList_path = {start_node,start_node};
closeList_cost = 0;
child_nodes = child_nodes_cal(start_node, m,n,obs,closeList);  

% 初始化openList
openList = child_nodes;
for i = 1:size(openList,1)
    openList_path{i,1} = openList(i,:);
    openList_path{i,2} = [start_node;openList(i,:)];
end

for i = 1:size(openList, 1)
    g = norm(start_node - openList(i,1:2)); %欧氏距离
    h = abs(target_node(1) - openList(i,1)) + abs(target_node(2) - openList(i,2)); %曼哈顿距离
    f=g+h;
    openList_cost(i,:) = [g, h, f];
end

这里g(n)采用欧式距离(表示结点n到起点实际距离),h(n)采用曼哈顿距离(表示结点n到终点估计值)

计算迭代

% 从openList开始搜索移动代价最小的节点
[~, min_idx] = min(openList_cost(:,3));
parent_node = openList(min_idx,:);


%% 进入循环
flag = 1;
while flag   
    
    % 找出父节点的忽略closeList的子节点
    child_nodes = child_nodes_cal(parent_node,  m, n, obs, closeList); 
    
    % 判断这些子节点是否在openList中,若在,则比较更新;没在则追加到openList中
    for i = 1:size(child_nodes,1)
        child_node = child_nodes(i,:);
        [in_flag,openList_idx] = ismember(child_node, openList, 'rows');   %in_flag=1则该child_node节点在openList中,openList_idx保存openList中第几位与child_node节点相同
        g = openList_cost(min_idx, 1) + norm(parent_node - child_node);
        h = abs(child_node(1) - target_node(1)) + abs(child_node(2) - target_node(2));
        f=g+h;
        
        if in_flag   % 若在,更新路径和成本     
            if g < openList_cost(openList_idx,1)
                openList_cost(openList_idx, 1) = g;
                openList_cost(openList_idx, 3) = f;
                openList_path{openList_idx,2} = [openList_path{min_idx,2}; child_node];
            end
        else         % 若不在,加入openList
            openList(end+1,:) = child_node;
            openList_cost(end+1, :) = [g, h, f];
            openList_path{end+1, 1} = child_node;
            openList_path{end, 2} = [openList_path{min_idx,2}; child_node];
        end
    end
   
    
    % 从openList移除移动代价最小的节点到 closeList
    closeList(end+1,: ) =  openList(min_idx,:);
    closeList_cost(end+1,1) =   openList_cost(min_idx,3);
    closeList_path(end+1,:) = openList_path(min_idx,:);
    openList(min_idx,:) = [];
    openList_cost(min_idx,:) = [];
    openList_path(min_idx,:) = [];
 
    % 重新搜索:从openList搜索移动代价最小的节点
    [~, min_idx] = min(openList_cost(:,3));
    parent_node = openList(min_idx,:);
    
    % 判断是否搜索到终点
    if parent_node == target_node
        closeList(end+1,: ) =  openList(min_idx,:);
        closeList_cost(end+1,1) =   openList_cost(min_idx,1);
        closeList_path(end+1,:) = openList_path(min_idx,:);
        flag = 0;
    end
end

3.结果展示

在这里插入图片描述

4.代码获取

完整代码公众号回复:A*,免费获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/684733.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IGraph使用实例——线性代数计算(blas)

1 概述 在图论中&#xff0c;BLAS&#xff08;Basic Linear Algebra Subprograms&#xff09;并不直接应用于图论的计算&#xff0c;而是作为一套线性代数计算中通用的基本运算操作函数集合&#xff0c;用于进行向量和矩阵的基本运算。然而&#xff0c;这些基本运算在图论的相…

深度神经网络——什么是扩散模型?

1. 概述 在人工智能的浩瀚领域中&#xff0c;扩散模型正成为技术创新的先锋&#xff0c;它们彻底改变了我们处理复杂问题的方式&#xff0c;特别是在生成式人工智能方面。这些模型基于高斯过程、方差分析、微分方程和序列生成等坚实的数学理论构建。 业界巨头如Nvidia、Google…

STM32(七):ADC电位检测 (标准库函数)

前言 上一篇文章已经介绍了如何用STM32单片机中的定时器的PWM波来实现LED的“呼吸”。这篇文章我们来介绍一下如何用STM32单片机中ADC进行电位检测&#xff0c;并发送到XCOM串口中显示。 一、实验原理 1.ADC模数转换的介绍 首先&#xff0c;我们先介绍一下AD模数模块&#…

驱动开发:内核扫描SSDT挂钩状态

100编程书屋_孔夫子旧书网 在笔者上一篇文章《驱动开发:内核实现SSDT挂钩与摘钩》中介绍了如何对SSDT函数进行Hook挂钩与摘钩的,本章将继续实现一个新功能,如何检测SSDT函数是否挂钩,要实现检测挂钩状态有两种方式,第一种方式则是类似于《驱动开发:摘除InlineHook内核钩…

免费,C++蓝桥杯等级考试真题--第11级(含答案解析和代码)

C蓝桥杯等级考试真题--第11级 答案&#xff1a;D 解析&#xff1a; A. a b; b a; 这种方式会导致a和b最终都等于b原来的值&#xff0c;因为a的原始值在被b覆盖前没有保存。 B. swap(a&#xff0c;b); 如果没有自定义swap函数或者没有包含相应的库&#xff0c;这个选项会编…

Mysql执行一条语句都有哪些操作

Mysql的执行流程 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层&#xff0c; Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包括连接器&#xff0c;查询缓存、解析器、预处理器、优化器、执行器等。另外&#xf…

Linux——PXE_FTP_EL8

PXE Kickstart &#xff08; el8 &#xff09; 使用两个网口一个用net接口用于下载服务和软件包&#xff0c;另一个为仅主机用于与其他的空主机相连 PXE(preboot execute environment) 预启动执行环境。支持工作站通过网络从远端服务器下载映像&#xff0c;并由此支持通过网络启…

JavaWeb2-Vue

Vue 前端框架&#xff0c;免除原生JS中的DOM操作简化书写 &#xff08;以前学过又忘了&#xff0c;现在才知道原来vue是前端的&#xff09; 基于MVVM思想&#xff08;model-view -viewModel&#xff09;实现数据双向绑定 model是数据模型 view负责数据展示 即DOM 中间这个负责…

可视化表单生成器好用吗?

当前的社会竞争是非常大的&#xff0c;随着业务的上涨&#xff0c;很多客户都需要找到更高效、更理想的软件平台产品实现流程化办公。这就需要了解低代码技术平台了。作为新的办公助力软件平台&#xff0c;低代码技术平台更好操作、更灵活、功能更多&#xff0c;其中可视化表单…

生产管理看板系统为优化工厂车间生产工艺

一、行业现状&#xff0c;管理中普遍存在的问题 1. 先进的管理流程与相应管理制度匮乏。大量管理工作依旧主要采取“人治”模式&#xff0c;众多高层自身理论知识欠缺&#xff0c;并且还难以听取相关人员的意见。 2. 生产过程的控制较为薄弱。企业全面质量控制&#xff08;TQ…

LSP5526 直接替用 LSP5502 SOP-8降压直流转换器

LSP5526 作为一款高性能的降压型直流-直流转换器&#xff0c;在医疗设备中的应用非常广泛。由于其具有高效率、宽输入电压范围以及良好的稳定性等特点&#xff0c;它可以为医疗设备中的关键电子系统提供稳定的电源支持。以下是一些具体的医疗设备应用案例&#xff1a; 1. 医用监…

人大金仓数据库报sys_user表字段不存在的问题

目录 一.问题&#xff1a; 二.原因 三.解决方法&#xff1a; 一.问题&#xff1a; 公司的一个项目从oracle切换到人大金仓之后&#xff0c;突然报了一个sys_user里面的字段不存在。 二.原因 检查了很多次确信sys_user表没问题&#xff0c;查了相应的文档之后发现原来人大金…

笔记96:前馈控制 + 航向误差

1. 回顾 对于一个 系统而言&#xff0c;结构可以画作&#xff1a; 如果采用 这样的控制策略&#xff0c;结构可以画作&#xff1a;&#xff08;这就是LQR控制&#xff09; 使用LQR控制器&#xff0c;可以通过公式 和 构建一个完美的负反馈系统&#xff1b; a a 但是有上…

【C语言】指针(4)

一、回顾 在这之前&#xff0c;我们学习了很多关于指针的内容&#xff0c;我们先在这里简单的回顾一下。 1、一级指针 int* p; -- 整形指针-指向整形的指针 char* p; ... void* p;... ... 2、二级指针 int** p; char** p; ... 3、数组指针 -- 指向数组的指针 int (*p)[ ]…

采用_findfirst和_findnext获取当前文件夹下以及子文件夹下特定文件

1.相关知识点&#xff1a; 在实现此功能&#xff0c;主要使用到的函数包含&#xff0c;_findfirst()、_findnext()、_findclose()。通过使用上述函数以及配合结构体 _finddata_t 来达到一个遍历的效果。 _finddata_t的结构体信息 struct _finddata64i32_t {unsigned attrib…

Linux.小技巧快捷键

1. ctrl c 强制停止 终止某些程序的运行 也可以取消某行命令 2. ctrl d 退出或登出 进入python环境中&#xff0c;使用ctrl d 退出 3.history 查看历史使用了哪些命令 4. ! 历史最近使用的命令的开头 5.使用ctrl r 搜索历史使用的命令 按下 ctrl r 会进入 reverse -…

course-nlp——5-nn-imdb

本文参考自https://github.com/fastai/course-nlp。这部分是fastai1.0版本的教程&#xff0c;由于现在fastai2.0重构的改变非常大&#xff0c;所以文中的很多api都变了&#xff0c;由于学习目的并不是熟练掌握fastai&#xff0c;因此这里就简单的存一下&#xff0c;本文是用IMD…

2024-04-27 - AI for everyone - 第三周 - 吴恩达

摘要 2024-05-01 周三 杭州 阴 小记: (☆-v-) 2024-05-03 周四 杭州 🌤 小记: 这几天地铁好拥挤呀!不过体重已经减了 2 公斤 ,咔咔咔,继续坚持 2024-05-04 周四 杭州 🐟 小记: 因为在意,所以昨天有些事情超级不开心,但是我决定要彻底舍弃了,羁绊这种东西本就可…

探索数据结构:堆,计数,桶,基数排序的分析与模拟实现

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 堆排序 1.1. 算法思想 堆排序(Heap Sort)是一种基于堆数据结构的排…

R语言绘图 | 双Y轴截断图

教程原文&#xff1a;双Y轴截断图绘制教程 本期教程 本期教程&#xff0c;我们提供的原文的译文&#xff0c;若有需求请回复关键词&#xff1a;20240529 小杜的生信笔记&#xff0c;自2021年11月开始做的知识分享&#xff0c;主要内容是R语言绘图教程、转录组上游分析、转录组…