46.在ROS中实现global planner(2)- A*规划算法预研

article/2025/9/21 13:14:09

前文45.在ROS中实现global planner(1)- 实现一个可以用的模板实现了一个global planner的模板,并且可以工作,本文将实现astar算法,为后续完成一个astar global planner做准备

1. AStar简介

1.1 AStar

Astar算法是一种图形搜索算法,常用于寻路。Astar算法原理网上可以找到很多,简单的说就是,从起点开始,向外发散,再去其中每个点到终端的估计距离最短的,继续循环上次步骤,直到到达目标点。

1.2 启发函数

估算距离(f)=距离起点距离(G)+距离终点的距离(H)

显然G是已知的,

  • 第一次从起点开始,G当然是0,
  • 向外发散也就是上下左右,距离起点当然是1,也就是其父节点的G+1

H 是距离目标点的距离,我们就是要规划路径,怎么找到距离目标有多远,其实这个距离是估计理想距离,当没有障碍物的时的距离,也就是直线距离

这里的直线距离又有两种方式表示

  • 曼哈顿距离
    x + y x+y x+y
  • 欧式距离
    x 2 + y 2 \sqrt{x^2 + y^2} x2+y2

显然网格计算适合使用曼哈顿距离的,其计算消耗要小很多

2. 实现过程

2.1 数据结构

上面简单提到实现过程,下面我们先定义数据结构, 我们需要保存当前已经搜索的节点,同时需要找到最小的f值,然后在该节点进行继续搜索和添加

  • 节点定义

class Grid {public:Point parent_point_;Point point_;float g_;float h_;  // f = g + h
};

节点定义比较简单,也就是当前点坐标,父节点坐标,g,h值

  • open list
    需要保存当前已经搜索点的列表,由于下次搜索有需要搜有f最小值,我们定义一个有限队列,这样我们取top就可以得到最小f的节点
struct greater {
bool operator()(const Grid& g1, const Grid& g2) const {float f1 = g1.h_ + g1.g_;float f2 = g2.h_ + g2.g_;return f1 > f2 || (f1 == f2 && g1.g_ < g2.g_);
}
};
std::priority_queue<Grid, std::vector<Grid>, greater> open_list_;

2.2 邻域

邻域定义较简单,定义为相对该点的偏移即可

  std::vector<Point> neighbors_;// 四邻域neighbors_.emplace_back(-1, 0);neighbors_.emplace_back(1, 0);neighbors_.emplace_back(0, -1);neighbors_.emplace_back(0, 1);// 八领域再加上下面neighbors_.emplace_back(-1, -1);neighbors_.emplace_back(1, 1);neighbors_.emplace_back(1, -1);neighbors_.emplace_back(-1, 1);

2.3 搜索实现

2.3.1 搜索过程

简单概括就是搜索过程就是不断最小的f值的节点的邻域,直到到达终点

伪代码如下

open_list.push(start);while(!open_list_.empty()) {// 取最前面的也就是最小的f节点Grid grid = open_list.top();open_list.pop();// 直到当前搜索点 为终点,终止循环if (grid.point == end.point) {return true;}// 循环这个节点的邻居V节点, 分别计算g h, 同时把这些节点添加到open_listfor (neighbor:neighbors) {Grid current;current.g_ = grid.g_ + 1current.h_ = calc_h(grid, neighbor, end); // 计算邻域的hcurrent.parent_point_ = grid.point;  // 更新父节点if (!(current in open_list)) {// 如果该点已经不在open list中则添加open_list.push(current);else {// 如果该点已经存在open list中 则根据V计算结果确认是否需要更新float f = current.g_ + current.h_;open_list[current.point].g_ = current.g_ ;open_list[current.point].h_ = current.h_ ;open_list[current.point].parent_point_ = grid.point;  // 更新父节点}}
}

2.3.2 得到路径

grid结构可以看出来,其实相当于一个链表结构,找到路径后,只需要从end循环即可得到路径

bool GetPathFromGrid(const Point& start_point, const Point& end_point, std::vector<Point>& path) {path.clear();path.push_back(end_point);int start_index;bool ret = Point2Index(start_point, start_index);if (!ret) {return false;}int index;Point point = end_point;ret = Point2Index(point, index);if (!ret) {return false;}while (index != start_index) {point = all_grid_[index].parent_point_;path.push_back(point);Point2Index(point, index);}return true;
}

3. 测试验证

3.1 输入

为了方便我们直接读取png图,这样我们直接编辑图就可以直接用于测试,

   // 使用opencv直接读取png图片cv::Mat mat = cv::imread("../map/map_demo.png", cv::IMREAD_GRAYSCALE);// 为了保持习惯 我们反转下, 值255认为障碍物(读取的图片255是白色)cv::threshold(mat, mat, 128, 255, CV_THRESH_BINARY_INV);

3.2 显示

为了方便我们观察过程,我们设计一个函数用于显示规划和过程,为了简便我们使用opencv窗口

void Display(const cv::Mat& map_data,    // 传入grid mapcv::Point begin,           // 起点cv::Point end,                // 终点const std::vector<cv::Point>& path,  // 输出的路径const std::vector<cv::Point>& close_list  // 已经完成搜索的点);

4. 测试

  • 输入地图

地图

  • 测试结果

plan


http://chatgpt.dhexx.cn/article/fYXQ9DWm.shtml

相关文章

【GlobalMapper精品教程】002:GlobalMapper中文版安装后的基本设置

本文讲述安装globalmapper后的一些简单基本设置&#xff08;持续更新&#xff09;&#xff0c;为后续深入学习软件打下基础。订阅专栏后私信作者&#xff0c;获取中文安装包及配套实验数据包。 文章目录 1. 工具条的显示与关闭2. 面积单位设置3. 选择所选面要素的边框4. 二三维…

nvm + nodejs + vue项目 环境搭建备忘

内容介绍&#xff1a; 传统 JavaScript 传统 JavaScript 运行在浏览器上&#xff0c;浏览器内核分为两个部分&#xff1a; 渲染引擎渲染HTML和CSSJavaScript 引擎 负责运行 JavaScrip…

python3_函数_形参调用方式 / 不定长参数 / 函数返回值 / 变量作用域 / 匿名函数 / 递归调用 / 函数式编程 / 高阶函数 / gobal和nonlocal关键字 / 内置函数

1.形参的调用方式 1. 位置参数调用 2. 关键词参数调用 原则&#xff1a; 关键词参数调用不能写在位置参数调用的前边 def test1(name, age):print("name:", name)print("age:", age)if "__main__" __name__:test1("admin_maxin", age…

关于Vivado综合选项——Out of context per IP和Gobal

Vivado生成IP输出文件注意的地方&#xff0c;是选择Global还是Out of context per IP: vivado默认是第二种&#xff0c;Out of context per IP是指让vivado在综合的时候对IP进行单独综合&#xff0c;生成.dcp文件&#xff0c;然后再工程要用到IP的时候&#xff0c;只需从.dcp文…

Oracle 临时表 (Gobal Temporary Table)

提问&#xff0c;插入数据之后&#xff0c;COMMIT&#xff0c;数据是否一定会在表里呢&#xff1f; 回答 一定会在。我认为没有错 回答 可能会在。也没有错 → 没在就一定是被删了&#xff0c;那么有一种表&#xff0c;会在Commit时&#xff0c;清空所有数据。 刚才说的那种…

转载:关于Vivado综合选项——Out of context per IP和Gobal

转载&#xff1a;关于Vivado综合选项——Out of context per IP和Gobal 原文地址&#xff1a;https://www.cnblogs.com/yhsy1002/p/7441309.html 关于Vivado综合选项——Out of context per IP和Gobal Vivado生成IP输出文件注意的地方&#xff0c;是选择Global还是Out of cont…

An Implemention of Realtime Gobal Illumination

前言&#xff1a;CG画面的“效果”最重要&#xff0c;至于达到这一效果所使用的技术倒是其次&#xff0c;一切的一切对于观众来说都是透明的。即使是Pixar都认为仅仅One Bounce Indirect Illumination对构建一个足够真实可信的光照效果足矣。看过这里的SII&#xff0c;我想你对…

Oracle ORA-06502 ORA-06512

问题描述&#xff1a; 发现存储过程里有对oracle <Collection>类型的操作 sql_text : select a.* from t_Drivewaystatus a inner join t_intersection b on a.intersectioncode b.intersectioncode where b.used 1 order by a.intersectioncode,a.drivewaycode; open…

ora-20011 ora-01555

问题 解决方案 ora undoinfo alter tablespace undotbs1 add datafile size 30g; alter tablespace undotbs2 add datafile size 30g; ora undoinfoora tempfree alter tablespace temp add tempfile size 30g; ora tempfree

ora-01461

插入数据长度大于4000&#xff0c;报该错ora-01461 解决方式&#xff1a;修改字段类型为 clob&#xff0c; 第一步&#xff1a;添加一个clob类型字段 ALTER TABLE tb_a ADD (RYZP CLOB);第二步&#xff1a;删除原来的字段 ALTER TABLE tb_a DROP COLUMN RYZP1;上面只是我工…

ORA-01156

需要关闭mrp进行操作。 alter database recover managed standby database cancel; alter database recover managed standby database parallel 10 using current logfile disconnect from session;

拼接字符串报错:Oracle: ORA-06512:字符串缓冲区太小

报错目前可以肯定的是&#xff0c;拼接的字符串超过oracle定义的上限。 plsql中varchar2长度上限是4000字节 报错语句定位到下面的这句&#xff1a; 我这里的p_zbdcdyh是存储过程的输出参数&#xff0c;故是默认数据库的字符串varchar2的大小。 p_zbdcdyh:p_zbdcdyh||,||PSELEN…

图像传感器设计资料-764-GSPRINT4502 2MP-4.5微米 全局快门 高速 CMOS 图像传感器

GSPRINT4502 2MP-4.5微米 全局快门 高速 CMOS 图像传感器 GSPRINT4502是一款一千万分辨率 (2048 x 1216) &#xff0c;2/3”光学尺寸的高速图像传感器&#xff0c;采用最新的4.5微米电荷域全局快门像素设计&#xff0c;实现30ke-的满阱容量和小于4e-的读出噪声。利用先进的65n…

转:详细图解,一眼就能看懂!卷帘快门(Rolling Shutter)与全局快门(Global Shutter)的区别

什么是快门 快门是照相机用来控制感光片有效曝光时间的机构。是照相机的一个重要组成部分&#xff0c;它的结构、形式及功能是衡量照相机档次的一个重要因素。 什么是Global Shutter&#xff08;Total Shutter&#xff09;&#xff1f; 通过整幅场景在同一时间曝光实现的。Sen…

详细图解,一眼就能看懂!卷帘快门(Rolling Shutter)与全局快门(Global Shutter)的区别

什么是快门 快门是照相机用来控制感光片有效曝光时间的机构。是照相机的一个重要组成部分&#xff0c;它的结构、形式及功能是衡量照相机档次的一个重要因素。 什么是Global Shutter&#xff08;Total Shutter&#xff09;&#xff1f; 通过整幅场景在同一时间曝光实现的。S…

VIO与全局快门及轮速计的一些应用小技巧

封面就用一个可爱的小车车~ 之前各种针对VIO&#xff0c;VSLAM和VINS的工程注意事项都讲过了 今天的内容主要是针对VSLAM&#xff0c;VIO的实用性。 比如Td&#xff0c;同步对时&#xff0c;内参&#xff0c;外参这一串 最近比较忙&#xff0c;简单写点全局快门和轮速计的东…

图解:卷帘快门(Rolling shutter)与全局快门(global shutter)的区别

什么是快门 快门是照相机用来控制感光片有效曝光时间的机构。是照相机的一个重要组成部分&#xff0c;它的结构、形式及功能是衡量照相机档次的一个重要因素。 什么是Global Shutter&#xff08;Total Shutter&#xff09;&#xff1f; 通过整幅场景在同一时间曝光实现的。Sens…

卷帘快门(Rolling Shutter)与全局快门(Global Shutter)的区别

转载的原始连接&#xff1a; https://blog.csdn.net/abcwoabcwo/article/details/93099982 快门是照相机用来控制感光片有效曝光时间的机构。是照相机的一个重要组成部分&#xff0c;它的结构、形式及功能是衡量照相机档次的一个重要因素。 什么是Global Shutter&#xff08;…

安森美的全局快门图像传感器解决机器视觉的成像需求

在“工业4.0”和“中国制造2025”的大势下&#xff0c;工业自动化趋势持续增强&#xff0c;机器视觉成为电子行业重要的新兴领域。在持续的自动化需求、社会安全保障需求和市场经济实力的推动下&#xff0c;全球机器视觉和智能交通系统市场迎来发展热潮。在中国&#xff0c;越来…

763-GMAX3809 1.1” 900万分辨率全局快门CMOS图像传感器

GMAX3809 1.1” 900万分辨率全局快门CMOS图像传感器 GMAX3809采用3.8μm像素设计&#xff0c;光学尺寸为1.1”&#xff0c;分辨率为900万&#xff0c;12bit数据输出最快帧频65fps。 GMAX3809采用了3.8μm的大像素设计&#xff0c;有效分辨率为4096(H) x 2160(V) (…