路径规划 | 图搜索算法:DFS、BFS、GBFS、Dijkstra、A*

2023-05-16

地图数据常常可以用(Graph)这类数据结构表示,那么在图结构中常用的搜索算法也可以应用到路径规划中。

本文将从图搜索算法的基本流程入手,层层递进地介绍几种图搜索算法。首先是两种针对无权图的基本图搜索算法:深度优先搜索(Depth First Search, DFS)广度优先搜索(Breadth First Search, BFS)。它们的区别在于openlist(后面介绍)所选用的数据结构类型不同,前者使用栈,后者使用队列;之后引入一种启发式搜索算法:贪婪最佳优先算法(Greedy Best First Search, GBFS),用来提高搜索效率,但是不能确保找到最优路径;最后介绍两种在路径规划中非常经典的算法:Dijkstra算法A*算法,前者是广度优先算法(BFS)在带权图中的扩展,后者则是在前者中加入启发函数得到的算法,兼顾效率和完备性。

配置空间

在学习路径规划算法之前,首先了解一下配置空间(Configuration Space)这个概念。在实际环境,也就是机器人的工作空间(Workspace)中,机器人是有形状和大小的,这不利于进行运动规划。要将工作空间转换到配置空间中,即将机器人转化为一个质点,同时将障碍物按照机器人的体积进行膨胀,如下图:

img

这样,在进行路径规划时,就可以将机器人当做一个点来处理了。

基本流程

下面切入正题,图搜索算法的基本流程如下:

  • 创建一个容器,一般称为openlist,用来存储将要访问的节点
  • 将起点加入容器
  • 开始循环:
    • 弹出:从容器中取出一个节点
    • 扩展:获取该节点周围的节点,将这些节点放入容器

深度优先搜索(DFS)

深度优先,顾名思义即深度越大的节点会被优先扩展。在DFS中,使用栈(Stack) 数据结构来实现上述特性。

栈是一种后进先出(LIFO) 的容器,如下图

img

以在下面的无权图中找到从节点a到节点i的路径为例,说明一下DFS算法的工作流程

img

按照上节的图搜索算法的基本流程进行搜索,过程如下:

img

从i回溯得到路径:a->b->c->g->i,如下:

img

DFS能够快速地找到一条路径,是一种以时间换空间的方法。将其应用到二维地图的路径规划中,如下图,很显然找到的路径并不是移动机器人运动规划所需要的最优路径

img

广度优先搜索(BFS)

与DFS的“不撞南墙不回头”的个性不同,BFS在搜索时呈波状推进形式,一路稳扎稳打,它是一种以时间换空间的方法,能够保证搜索到的路径是最优的。

img

为了实现波状推进搜索特性,BFS采用队列(Queue) 作为openlist的数据结构。队列是一种先进先出(FIFO) 的容器,如下图

img

其流程与上节中DFS类似,继续以上节的图举例,过程如下,首先创建一个队列作为容器,将节点a加入队列

img

接着将节点a弹出队列,将节点a周围没有访问过的节点加入队列

img

按照上面的流程不断地弹出、扩展节点,直到找到节点i为止,完整流程如下图:

img

从终点回溯,i的父节点为f,f的父节点为e,e的父节点为a,这样就可以得到a到i的最短路径为:a->e->f->i,如下

img

显而易见,相较于DFS,BFS中使用了大量的入队、出队操作,耗时增加,但是能保证找到最优路径。

启发式搜索算法

BFS和DFS的区别主要在于节点的弹出策略,根据弹出策略的区别,分别使用了队列和栈两种数据结构,而栈和队列作为两种相当基本的容器,只将节点进入容器的顺序作为弹出节点的依据,并未考虑目标位置等因素,这就使搜索过程变得漫无目的,导致效率低下。启发式搜索算法(Heuristic Algorithm)就是用来解决搜索效率问题的,下面将以贪婪最佳优先算法(Greedy Best First Search, GBFS)为例来介绍启发式搜索算法。

GBFS也是图搜索算法的一种,它的算法流程和BFS、DFS并没有本质的不同,区别仍然在于openlist采用的数据结构,GBFS使用的是优先队列(Priority Queue),普通队列是一种先进先出的数据结构,而在优先队列中元素被赋予了优先级,最高优先级元素优先删除,也就是first in, largest out。(记住这种数据结构,后面的Dijkstra和A*算法都会用到这个结构)。

在图搜索算法中,使用代价函数 f ( n ) f(n) f(n)来作为优先级判断的标准, f ( n ) f(n) f(n)越小,优先级越高,反之优先级越低。

GBFS作为一种启发式搜索算法,使用启发评估函数 h ( n ) h(n) h(n)来作为代价函数,也就是
f ( n ) = h ( n ) f(n)=h(n) f(n)=h(n)
其中 h ( n ) h(n) h(n)是当前节点到终点的代价,它可以指引搜索算法往终点靠近,主要用欧氏距离(Euclidean Distance) 或者曼哈顿距离(Manhattan Distance) 来表示,它们的区别如下图:

img

假设有两个点 ( x 1 , y 1 ) (x_1, y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2),则它们的欧氏距离和曼哈顿距离分别为:
D E u c l i d e a n = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 D M a n h a t t a n = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ D_{Euclidean}=\sqrt{(x_1-x_2)^2 + (y_1 - y_2)^2}\\ D_{Manhattan}=|x_1-x_2| + |y_1-y_2| DEuclidean=(x1x2)2+(y1y2)2 DManhattan=x1x2+y1y2

将GBFS应用在二维地图路径规划中,如下图,可以看到它的指向性或者说目的非常明显,从起点直扑终点。

img

但是在实际的地图中,常常会有很多障碍物,它就很容易陷入局部最优的陷阱。下图的地图中有一个专门设置的局部最优陷阱,很显然GBFS虽然搜索速度够快,但是找不到最优路径。

img

将其应用到复杂二维地图路径规划中,效果如下:

img

Dijkstra算法

上面的算法中,只有广度优先搜索(BFS)具有完备性,能够保证搜索到最优路径。但是可以看到BFS算法搜索到的路径只有向上/下/左/右移动这四个动作,它们是没有权值或者说权值都相同的,只能用于无权图的路径规划,无法实现能够对角移动的路径规划。因此下面介绍一种能用于带权图的图搜索算法——Dijkstra算法(狄克斯特拉算法)。

img

Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,其流程仍然与上述算法基本一致,它也是用优先队列作为openlist的数据结构,它和GBFS的区别在于代价函数 f ( n ) f(n) f(n)的定义,Dijkstra算的 f ( n ) f(n) f(n)定义为:
f ( n ) = g ( n ) f(n)=g(n) f(n)=g(n)
其中 g ( n ) g(n) g(n)表示从起点到当前点的移动代价

以下图为例,计算左上角起点到右下角终点的最短路径,箭头上的数值表示两个节点间的距离

img

首先扩展第一个节点,计算其余节点与第一个节点的距离,用橙色标出已经扩展的节点,未扩展的节点仍用绿色标出,其中圆中的数值表示该节点的代价函数,字母则表示该节点没有直接到达此时已扩展节点的路径。从未扩展的节点(绿色节点)中选择代价函数最小的节点进行拓展,并更新其余节点的代价函数,如下图

img

重复进行上面的步骤,直到所有节点都已扩展。

img

最后标出起点到终点的最短路径

img

将Dijkstra算法应用到二维地图路径规划中,如下图,可以看到Dijkstra算法能够得到最优路径,但是它的速度和BFS是一样的,采取的都是稳扎稳打、波状前进的方式,导致速度较慢。

img

A*算法

对比GBFS和Dijkstra算法,两者都采用优先队列作为openlist,而代价函数的不同导致两者具有不同的优点:GBFS用节点到目标点的距离作为代价函数,将搜索方向引向目标点,搜索效率高;而Dijkstra算法采用起点到当前扩展节点的移动代价作为代价函数,能够确保路径最优。

那么可不可以将两者的代价函数进行融合,从而在保证路径最优的同时提高搜索效率?答案是肯定的,融合后的算法就是A*算法

img

A*算法也是一种启发式算法,它的代价函数表示为:
f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)
其中 g ( n ) g(n) g(n)为起点到当前扩展节点的移动代价函数, h ( n ) h(n) h(n)是启发函数,用节点到目标点的距离函数来表示。

根据这个式子,可以得到A*算法的几个特点:

  • 如果令 h ( n ) = 0 h(n)=0 h(n)=0,A* 算法就退化为Dijkstra算法;如果令 g ( n ) = 0 g(n)=0 g(n)=0,A* 算法就退化为GBFS算法。
  • 能否找到最优路径的关键是启发函数 h ( n ) h(n) h(n)的选取,如果 h ( n ) h(n) h(n)在大部分情况下比从当前节点到目标点的移动代价小,则能找到最优路径。
  • 由于A* 算法的启发函数是位置上的距离,因此在不带位置信息的图数据中不适用。

将A*算法应用到二维地图路径规划中,如下图:

img

附录:图基础

本节附录将介绍什么是图数据结构,以及图数据结构在计算机中的表示方法

图结构

图结构是一种由数据元素集合元素间的关系集合组成的非线性数据结构。数据元素用节点(node)表示,元素间的关系用边(edge)表示,如果两个元素相关,就用一条边将相应的节点连接起来,这两个节点称为相邻节点。根据边的方向性,可以分为无向图和有向图,一个无向图G记做 G = ( V , E ) G=(V,E) G=(V,E),其中 V V V是节点的有限集合, E E E是边的有限集合,则有:
V = { x ∣ x ∈ 某个具有相同特性的数据元素集合 } E = { e ( x , y ) ∣ x , y ∈ V } V=\{x|x\in某个具有相同特性的数据元素集合 \}\\ E=\{e(x,y)|x,y\in V\} V={xx某个具有相同特性的数据元素集合}E={e(x,y)x,yV}
上式中, e ( x , y ) e(x,y) e(x,y)表示节点x和节点y之间的相邻关系,是一种无序节点对,无方向性,称为连接节点x和节点y的一条边。如果节点间关系是有序节点对,则用 e < x , y > e<x,y> e<x,y>表示,表示从节点x到节点y的一条单向边,是
有方向的
,则有向边的集合可表示为:
E = { e < x , y > ∣ x , y ∈ V } E=\{e<x,y>|x,y\in V\} E={e<x,y>x,yV}
下图分别为无向图和有向图的图形化示例:

img

上图中的无向图可以表示为:
V ( G ) = { v 1 , v 2 , v 3 , v 4 } E ( G ) = { ( v 1 , v 2 ) , ( v 1 , v 3 ) , ( v 1 , v 4 ) , ( v 2 , v 3 ) , ( v 3 , v 4 ) } V(G)=\{v_1,v_2,v_3,v_4\}\\ E(G)=\{(v_1,v_2),(v_1,v_3),(v_1,v_4),(v_2,v_3),(v_3,v_4)\} V(G)={v1,v2,v3,v4}E(G)={(v1,v2),(v1,v3),(v1,v4),(v2,v3),(v3,v4)}
有向图可表示为:
V ( G ) = { v 1 , v 2 , v 3 , v 4 } E ( G ) = { < v 1 , v 2 > , < v 1 , v 3 > , < v 2 , v 3 > , < v 3 , v 4 > , < v 4 , v 4 > , < v 4 , v 1 > } V(G)=\{v_1,v_2,v_3,v_4\}\\ E(G)=\{<v_1,v_2>,<v_1,v_3>,<v_2,v_3>,<v_3,v_4>,<v_4,v_4>,<v_4,v_1>\} V(G)={v1,v2,v3,v4}E(G)={<v1,v2>,<v1,v3>,<v2,v3>,<v3,v4>,<v4,v4>,<v4,v1>}
在图中除了用边表示两个节点之间的相邻关系外,有时还需要表示它们相关的强度信息,例如从一个节点到另一个节点的距离、花费的代价、所需的时间等,诸如此类的信息可以通过在图的每条边上加上一个称作(weight)的数值表示,这类图称为带权图

img

上述就是图结构的基本概念,我们还需要知道图结构在计算机中的表示方法

图结构的邻接矩阵表示法

邻接矩阵用来表示图的边集,即节点间的相邻关系集合。设 G = ( V , E ) G=(V,E) G=(V,E)是一个具有n个节点的图,它的邻接矩阵是一个n阶矩阵,则其中的元素 a i j a_{ij} aij满足:
a i j = { 1 若 e ( v i , v j ) ∈ E 或者 e < v i , v j > ∈ E 0 若 e ( v i , v j ) ∉ E 或者 e < v i , v j > ∉ E a_{ij}=\begin{cases}1&若e(v_i,v_j)\in E或者e<v_i,v_j>\in E\\ 0&若e(v_i,v_j)\notin E或者e<v_i,v_j>\notin E\end{cases} aij={10e(vi,vj)E或者e<vi,vj>∈Ee(vi,vj)/E或者e<vi,vj>/E
对于无向图,其邻接矩阵是对称矩阵,即 a i j = a j i a_{ij}=a_{ji} aij=aji,而有向图的邻接矩阵不一定对称,其空间复杂度均为 O ( n 2 ) O(n^2) O(n2)。以下为两个不带权图的邻接矩阵示例:

img

对于带权图,设 e ( v i , v j ) e(v_i,v_j) e(vi,vj)或者 e < v i , v j > e<v_i,v_j> e<vi,vj>上的权值为 w i j w_{ij} wij,则带权图的邻接矩阵定义为:
a i j = { w i j 若 e ( v i , v j ) ∈ E 或者 e < v i , v j > ∈ E ∞ 若 e ( v i , v j ) ∉ E 或者 e < v i , v j > ∉ E 0 若 v i = v j a_{ij}=\begin{cases}w_{ij}&若e(v_i,v_j)\in E或者e<v_i,v_j>\in E\\ \infty&若e(v_i,v_j)\notin E或者e<v_i,v_j>\notin E\\ 0&若v_i=v_j \end{cases} aij= wij0e(vi,vj)E或者e<vi,vj>∈Ee(vi,vj)/E或者e<vi,vj>/Evi=vj
以下为两个带权图的邻接矩阵示例:

img

图结构的邻接表表示法

邻接矩阵表示法的空间复杂度为 O ( n 2 ) O(n^2) O(n2),其占用的空间大小与图中节点数量相关,而与边的数目无关。对于稀疏图,其边的数量可能远小于 n 2 n^2 n2,这样邻接矩阵中就会有很多零或 ∞ \infty 元素。对于这种情况,可以用节点表和邻接表来表示和存储图结构,其占用的存储空间既与图的节点数有关,也与边数有关。

图的节点表用来保存图中的所有节点,通常是一个顺序存储的线性表,该线性表中的每个元素对应图中的一个节点,该节点类型包括两个基本成员:节点数据元素信息data和指向该节点的邻接表neighbors。对于无向图有:

img

参考

图的实现(c++)

机器人路径规划之Dijkstra算法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

路径规划 | 图搜索算法:DFS、BFS、GBFS、Dijkstra、A* 的相关文章

  • C++基础:第五章 表达式基础与详述

    第五章 表达式基础与详述 第1节 基础 xff1a 引入 表达式由一到多个操作数组成 xff0c 可以求值并 xff08 通常会 xff09 返回求值结果 xff08 函数的调用是一种表达式 xff0c 有时函数不会返回求值结果 xff09
  • C++基础:第六章 语句

    第六章 语句 第1节 语句基础 常见类别 xff1a 表达式语句 xff0c 求值后丢弃 2 43 3 空语句复合语句 xff0c 用大括号 xff0c 形成独立的域 顺序语句 按先后顺序执行实际执行顺序可能产生变换 xff08 编译器优化
  • C++基础:第七章 函数

    第七章 函数 第1节 函数基础 栈帧结构 函数的外部链接 第2节 函数详解 传值 传址 传引用 传参数时的类型退化 xff0c 传数组时函数形参退化成指针 xff0c 所以形参不要写数组个数 多维数组作为函数参数时 void fun int
  • C++基础:第八章 深入IO

    第八章 深入IO 第1节 序 第2节 IOStream概述 流式IO而非记录IO 处理的主要问题 表示形式的变化 xff1a 使用格式化 解析在数据的内部表示与字符序列之间切换与外部设备的通信 xff1a 针对不同的外部设备引入不同的处理逻
  • 在vscode终端安装vue构建工具vite

    首先确保已安装npm 第一步 xff1a 全局安装yarn 0 打开cmd xff08 windows 43 R xff09 1 输入安装命令 npm install g yarn 2 如果能看到版本号 xff0c 则安装成功 yarn v
  • cmake相关:sudo make install后的卸载

    sudo make install后的卸载 我们知道linux中一般的编译一个package的顺序是 span class token function git span clone package git span class token
  • 提取rosbag中的图像话题存为本地图像

    新建存放图片文件夹 首先运行ros master roscore 在目标文件夹目录下运行 rosrun image view extract images sec per frame 61 0 05 image 61 lt ROSIMAGE
  • matlab循环读取文件

    一般情况下 xff0c 假如我要读取一个名为a txt的文件 xff0c 只需要利用下面的语句 xff1a a span class token operator 61 span span class token function load
  • 使用OpenMVG获取相机位姿的方法

    在生成sfm data bin文件后 xff0c 在文件目录下执行 openMVG main ConvertSfM DataFormat binary span class token operator span i yoursfm dat
  • Ubuntu修改文件夹下面所有文件权限的方法

    ubuntu修改文件夹下所有文件的权限 命令为 xff1a sudo chmod span class token operator span R 777 filename filename为要修改的文件夹名字 R应该是表示递归修改file
  • 写出对js事件,事件流,事件对象的理解

    事件 JavaScript 使我们有能力创建动态页面 事件是可以被 JavaScript 侦测到的行为 网页中的每个元素都可以产生某些可以触发 JavaScript 函数的事件 比方说 xff0c 我们可以在用户点击某按钮时产生一个 onC
  • UDP实时图像传输

    写在前面 首先问个问题 xff0c 为什么要用UDP传输图像 xff0c 而不是TCP xff1f TCP是我们经常使用的通信协议 xff0c 从认识它的第一天起 xff0c 就应该知道 xff0c 它非常稳 xff0c 丢包率超低 但是一
  • 机器学习 | 使用k-近邻算法实现手写识别系统

    KNN概述 k 近邻算法就是通过计算不同特征值之间的距离来进行分类的算法 假设我们现在有一个样本集 xff0c 每个样本都有几个特征用来描述这个样本 xff0c 以及一个它所属分类的标签 当我们拿到一个没有标签的样本时 xff0c 该如何判
  • Windows下如何查看一个process内有哪些thread

    从https docs microsoft com en us sysinternals downloads pslist下载PsTools xff0c 解压后找到pslist exe并移动到C盘任一目录下 xff0c 使用说明都在Psto
  • 机器人路径规划之动态窗口法

    动态窗口法 Dynamic Window Approach 概述 DWA是一种基于速度的局部规划器 xff0c 可计算达到目标所需的机器人的最佳无碰撞速度 程序实现 DWA算法主要分三步 xff1a 计算动态窗口计算最优 v
  • cso(布谷鸟)算法优化神经网络参数

    之前写了一篇pso工程上使用方法 xff0c 这一篇使用布谷鸟算法 xff0c 相关的原理也比较多的介绍了 目前实验结果还是pso快一点 一 布谷鸟算法介绍 布谷鸟搜索算法 xff0c 是 由剑 桥 大 学YANG等在文献 中提出的一种群智
  • 多线程之线程安全(Thread Safety)

    什么是线程安全 Thread Safety xff1f 怎样才能做到线程安全 xff1f 线程安全 线程安全指某个函数 函数库在多线程环境中被调用时 xff0c 能够正确地处理多个线程之间的共享变量 xff0c 使程序功能正确完成 数据类型
  • 多线程之简易注册验证程序

    问题描述 使用VC2010或以上版本编写一个多线程注册验证程序 xff0c 要求 xff1a 通过对话框输入若干人的学号和姓名 xff0c 并存入列表中作为注册记录 用户输入一个学号 xff0c 程序能通过多线程的方式与注册记录比对来验证其
  • 多线程之基于积分法与欧拉恒等式法的圆周率计算及OMP优化

    文章目录 一 问题描述二 积分法算法推导编程实现OMP优化 三 欧拉恒等式算法推导编程实现前期准备加法减法乘法除法 算法实现 OMP优化 四 总结积分法与欧拉恒等式法的对比OMP实现方式的对比 一 问题描述 分别采用积分法和欧拉恒等式计算
  • 语音信号处理 | 基于Hilbert-Huang变换的基音检测方法

    HHT原理 Hiibert Huang变换是由Huang等人于1998年提出来的一种信号分析方法 xff0c 它主要由两个部分组成 经验模型分解 Empirical Mode Decomposition EMD 和希尔伯特变换 xff08

随机推荐

  • 机器学习 | 使用TensorFlow搭建神经网络实现鸢尾花分类

    鸢尾花分类问题是机器学习领域一个非常经典的问题 xff0c 本文将利用神经网络来实现鸢尾花分类 实验环境 xff1a Windows10 TensorFlow2 0 Spyder 参考资料 xff1a 人工智能实践 xff1a Tensor
  • 语音信号处理 | 基于卡尔曼滤波的语音增强算法

    文章目录 1 概述2 卡尔曼滤波原理被估计的信号离散卡尔曼滤波算法参数选择 3 基于卡尔曼滤波的语音增强算法语音模型分析参数确定 4 程序实现语音数据的导入 加噪与分帧卡尔曼滤波器参数初始化卡尔曼滤波过程结果可视化 5 运行结果与结果分析运
  • UDP实时图像传输进阶篇——1080P视频传输

    在UDP实时图像传输一文中 xff0c 介绍了如何使用UDP来实现图像的实时传输 xff0c 并使用C 进行了发送端和接收端的搭建 但是文中的方法是对整张图片进行JPEG压缩 xff0c 并通过UDP一次性地发送到接收端 xff0c 由于一
  • 机器人路径规划之Dijkstra算法

    在机器人路径规划之动态窗口法文中 xff0c 介绍了一种局部路径规划方法 动态窗口法 xff0c 本文将介绍一种全局路径规划方法 Dijkstra算法 狄克斯特拉算法 Dijkstra算法是从一个顶点到其余各顶点的最短路径算法 xff0c
  • 语音信号处理 | 使用短时能量和谱质心特征进行端点检测

    文章目录 概述原理及MATLAB实现基本流程特征提取短时能量谱质心 阈值估计和阈值化处理提取语音片段 MATLAB2020a中的VAD函数参考 概述 在复杂的应用环境下 xff0c 从音频中分割出语音信号和和非语音信号 xff0c 是一个很
  • 语音信号处理 | 傅里叶变换、短时傅里叶变换、小波变换、希尔伯特变换、希尔伯特黄变换

    在信号处理领域 xff0c 存在诸多变换 xff0c 比如标题中的五个变换 本文将对这五个变换进行介绍和比较 在开始之前 xff0c 我们需要先理清什么是平稳信号 xff0c 什么是非平稳信号 我们知道 xff0c 自然界中几乎所有信号都是
  • clang-format格式文件。可以直接复制引用

    Language Cpp BasedOnStyle LLVM AccessModifierOffset 2 AlignAfterOpenBracket Align AlignConsecutiveMacros false AlignCons
  • 多线程之多核线上考试试题瞎解

    匆忙的大三早已结束 xff0c 时隔两月 xff0c 再以此文祭奠我炸掉的多核考试 这次考试真正能写出来的也就两道题 xff0c 以下简单地记录一下 第二题 随机产生2个10 10的浮点数矩阵A和B xff0c 先将矩阵A和B作转置 xff
  • 视觉SLAM | RealsenseD435i相机标定

    在运行VINS MONO VINS Fusion等SLAM方案的时候 xff0c 需要很准确的相机参数 xff0c 否则很容易漂移 本文是RealsenseD435i相机标定过程的记录 xff0c 标定主要有三个步骤 IMU标定相机标定IM
  • 视觉SLAM | 使用RealsenseD435i运行VINS-Fusion

    使用RealsenseD435i运行VINS Fusion VINS Fusion是基于双目的视觉惯导方案 xff0c 不太符合我目前的需求 xff0c 但这是我使用的第一个视觉SLAM方案 xff0c 接下来还是简单记录下 运行环境 硬件
  • 视觉SLAM | 在ROS上运行ORB-SLAM2

    本文直接使用的github上的orb slam 2 ros实现在ROS上运行ORB SLAM2 xff0c 这个ros包能够得到相机的位姿以及稀疏点云 xff0c 而且删掉了对Pangolin的依赖 xff0c 进行可视化时要用RViz 运
  • ROS报错记录及解决方法(不定期更新)

    ROS下载缓慢 如果是在国内安装 xff0c 建议在安装之前先配置国内的镜像源 xff0c 在软件和更新进行更改即可 参考 xff1a Ubuntu18 04下安装ROS 由于没有公钥 xff0c 无法验证下列签名 安装ROS时报错 xff
  • ROS与STM32通信

    ROS与STM32是用串口进行通信的 xff0c 主要有两种方式 xff0c 一是将STM32作为一个节点 xff0c 二是制作一个上位机节点 负责与STM32进行串口通信 xff0e 第一种方式需要专门的硬件 xff0c 所以我选择第二种
  • 使用VScode搭建ROS开发环境

    俗话说 xff02 工欲善其事必先利其器 xff02 xff0c 之前在Ubuntu上运行的ROS项目都是用vim或者gedit编写和修改代码 xff0c 然后在终端编译运行 xff0c 很不方便 xff0c 函数跳转查看都没办法实现 所以
  • TCP实时图像传输

    之前尝试过使用UDP进行图像传输 xff0c 而UDP协议要求包小于64K xff0c 对于较大的图像 xff0c 需要使用分片压缩的方式进行传输 xff0c 操作较复杂 xff0c 同时不能保证图片的每一部分都能够正确传输 详见 xff1
  • STM32部分BUG及解决方法记录(不定期更新)

    1 编译使用CubeMX生成的代码时报错 Error L6218E Undefined symbol HAL PWREx DisableUCPDDeadBattery referred from stm32g4xx hal msp o 解决
  • 语音信号处理 | Python实现端点检测

    由于项目需要 xff0c 我要使用Python对语音进行端点检测 xff0c 在之前的博客使用短时能量和谱质心特征进行端点检测中 xff0c 我使用MATLAB实现了一个语音端点检测算法 xff0c 下面我将使用Python重新实现这个这个
  • 进程,线程,应用程序。概念理解

    简单的说 xff0c 进程 可以承载一组相关的 NET 程序集 xff0c 而 应用程序域 xff08 简称AppDomain xff09 是对该进程的逻辑细分 一个应用程序域进一步被细分成多个 上下文边界 xff0c 这些边界用来分组目的
  • 搭建STM32开发环境

    安装keil 点击这里下载安装最新版的keil 破解 以管理员身份运行keil xff0c 打开File gt License Management 复制CID xff0c 如下 xff1a 运行keygen2032 exe xff0c 修
  • 路径规划 | 图搜索算法:DFS、BFS、GBFS、Dijkstra、A*

    地图数据常常可以用图 Graph 这类数据结构表示 xff0c 那么在图结构中常用的搜索算法也可以应用到路径规划中 本文将从图搜索算法的基本流程入手 xff0c 层层递进地介绍几种图搜索算法 首先是两种针对无权图的基本图搜索算法 xff1a