Fast Planner规划算法(一)—— Fast Planner前端

   本系列文章用于回顾学习记录Fast-Planner规划算法的相关内容,【本系列博客写于2023年9月,共包含四篇文章,现在进行补发第一篇,其余几篇文章将在近期补发】

   一、Fast Planner前端

   Fast Planner的轨迹规划部分一共分为三个模块,前端采用Hybrid A* 算法生成比较粗糙的路径\轨迹,然后采用后端对前端生成的路径进行更加细致的处理和优化。

在这里插入图片描述

   本部分内容对前端进行介绍,Hybrid A* 算法的原理在前面的文章中已经介绍过了,这里主要介绍在Fast Planner中具体使用的一些流程和细节。

在这里插入图片描述
在这里插入图片描述

   Fast Planner中 Hybrid A* 算法的主要流程如下:

   在每轮循环中,首先会从优先队列中拿出新的节点 n c n_c nc,并判断该节点是否为终点以及从该节点能不能直接生成到终点的路径(比如采用Reeds sheep算法),若是,则规划结束返回路径,若不是则继续进行本轮循环

   在该新节点 n c n_c nc处向外拓展生成一些小的轨迹,这些小轨迹称为primitive,它们的末端就是拓展出来的节点,然后进行剪枝操作,如果有多个节点落在同一个栅格中,仅保留一个,讲这些新拓展出来的节点存放在nodes中。

   然后对nodes中的每个节点的质量进行评估(伪代码8-16行),对于每个节点,首先检查其是否已经在已经拓展过的闭集合中以及是否是可行节点(在边界范围内、不与障碍物碰撞等),

   若在闭集合或不是可行节点,则结束对这个节点的评估,继续进行下一个节点的评估。若不在闭集合中且为可行节点,则继续进行该节点的评估,计算该节点的g值,即其父节点 n c n_c nc的g值加上该节点对应的小轨迹的代价值。然后判断该节点是否在待拓展的开集合中,若不在,则将其加入到开集合中,记录该节点的g值以及父节点,并计算该节点的f值,该节点的评估结束,若已经在开集合中了,则判断该节点上面算出的新g值是否大于原有的g值,若是则不需要进行处理(该节点原有的方案更优),继续评估下一个节点,若不是,则说明该节点的现有方案更优,将该节点的父节点更新为 n c n_c nc,g值更新为新的g值,并更新计算该节点的总代价f值。本节点评估结束,继续评估下一个节点。

在这里插入图片描述


   下面来详细看一下上面流程中的一些具体细节:

   【注:Hybrid A * 算法每个具体执行过程的实现都有很多种方法,在前面的文章中,我们给出了 zhm_real/MotionPlanning运动规划库中的实现方法及细节,这里给出Fast Planner中的具体实现细节】

   (1)、如何由节点 n c n_c nc拓展生成小轨迹primitive——对应Expend函数

   将x,y、z轴的轨迹用三个独立的多项式来表示,比如用二次多项式 p x ( t ) = a 0 + a 1 t + a 2 t 2 p_x(t)=a_0+a_1t+a_2t^2 px(t)=a0+a1t+a2t2,自变量是时间t,则状态量和控制输入量可表示成以下的形式

   x ( t ) : = [ p ( t ) T , p ˙ ( t ) T , . . . , p ( n − 1 ) ( t ) T ] T ⊂ R 3 n u ( t ) : = p ( n ) ( t ) ∈ U : = [ − u m a x , u m a x ] 3 ⊂ R 3 \begin{aligned}&\mathbf{x}(t):=\boxed{\left[\mathbf{p}(t)^{\mathrm{T}}, \mathbf{\dot p}(t)^{\mathrm{T}},...,\mathbf{p}^{(n-1)}(t)^{\mathrm{T}}\right]^{\mathrm{T}}}\subset\mathbb{R}^{3n}\\&\mathbf{u}(t):=\mathbf{p}^{(n)}(t)\in\mathcal{U}:=[-u_{max},u_{max}]^3\subset\mathbb{R}^3\end{aligned} x(t):=[p(t)T,p˙(t)T,...,p(n1)(t)T]TR3nu(t):=p(n)(t)U:=[umax,umax]3R3

   然后,我们就可以写出状态空间方程,

   x ˙ = A x + B u A = [ 0 I 3 0 ⋯ 0 0 0 I 3 ⋯ 0 ⋮ ⋮ ⋮ ⋱ ⋮ 0 ⋯ ⋯ 0 I 3 0 ⋯ ⋯ 0 0 ] , B = [ 0 0 ⋮ 0 I 3 ] \begin{gathered}\dot{\mathbf{x}}=\mathbf{A}\mathbf{x}+\mathbf{B}\mathbf{u}\\\mathbf{A}=\begin{bmatrix}0&\mathbf{I}_3&\mathbf{0}&\cdots&\mathbf{0}\\\mathbf{0}&\mathbf{0}&\mathbf{I}_3&\cdots&\mathbf{0}\\\varvdots&\varvdots&\varvdots&\ddots&\varvdots\\\mathbf{0}&\cdots&\cdots&\mathbf{0}&\mathbf{I}_3\\\mathbf{0}&\cdots&\cdots&\mathbf{0}&\mathbf{0}\end{bmatrix},\mathbf{B}=\begin{bmatrix}\mathbf{0}\\\mathbf{0}\\\varvdots\\\mathbf{0}\\\mathbf{I}_3\end{bmatrix}\end{gathered} x˙=Ax+BuA= 0000I300I30000I30 ,B= 000I3

   这样,我们给定一个初始状态和一段时间内的控制输入里以后,就可以利用下式计算整条小轨迹上任意时刻的状态

   x ( t ) = e A t x ( 0 ) + ∫ 0 t e A ( t − τ ) B u ( τ ) d τ initial state control input \begin{aligned}\mathbf{x}(t)=e^{\mathbf{A}t}&\color{red}{\boxed{\mathbf{x}(0)}}+\color{black}\int_0^te^{\mathbf{A}(t-\tau)}\mathbf{B}&\color{red}{\boxed{\mathbf{u}(\tau)}}\color{black} d\tau\\&\color{red}{\text{initial state}}&\color{red}{\text{control input}}\end{aligned} x(t)=eAtx(0)+0teA(tτ)Binitial stateu(τ)dτcontrol input

在这里插入图片描述

   实际使用时,会对控制量在上下界范围内进行平均的离散采样,得到多组控制输入量,从而得到多条小轨迹

在这里插入图片描述

   在Fast-Planner中,n取值为2,即状态选取为位置和速度,输入为加速度

在这里插入图片描述


   (2)、如何计算每段小轨迹的代价值——对应EdgeCost函数

   对于一条小轨迹,在Fast-Planner中我们比较在意的是这条轨迹的执行时间和控制量,所以定义如下的代价函数(不同的需求和实际应用场景,可以选择不同的代价函数)

   T ( T ) = ∫ 0 T ∥ u ( t ) ∥ 2 d t + ρ T T(T)=\int_{0}^{T}\|\mathbf{u}(t)\|^{2}dt+\rho T T(T)=0Tu(t)2dt+ρT

   其中 T T T表示这一段小轨迹的时间, u u u是控制量, ρ \rho ρ表示对时间惩罚项的权重参数,对于一条小轨迹而言,在0~T时间内它的控制输入是固定的常量,每条小轨迹的总时间T也是固定的, 所以,我们并不需要计算上面的积分,它等效于使用下式来计算小轨迹的代价值, τ \tau τ即为小轨迹的持续时间

   e c = ( ∥ u d ∥ 2 + ρ ) τ e_{c}=(\|\mathbf{u}_{d}\|^{2}+\rho)\tau ec=(ud2+ρ)τ

   然后,我们把从起点开始的到当前节点的所有小轨迹的代价加起来,就得到了,从起点到当前节点的代价值,也就是该节点的g值,如下所示:

   g c = ∑ j = 1 J ( ∥ ( u d ) j ∥ 2 + ρ ) τ g_c=\sum_{j=1}^J\left(\left\|(\mathbf{u}_d)_j\right\|^2+\rho\right)\tau gc=j=1J((ud)j2+ρ)τ

在这里插入图片描述

   (3)、如何评估一个节点的启发代价值——对应Heuristic函数

   基于庞特里亚金最小原理设计了一条三阶的多项式轨迹,从当前状态出发,终止于目标点,轨迹的总时长已知,给定当前点和目标点的位置和速度,如下所示:

   p ( t ) = a 3 t 3 + a 2 t 2 + a 1 t + a 0 p ( 0 ) = p μ c , p ( 0 ˙ ) = v μ c p ( T ) = p μ g , p ( T ˙ ) = v μ g \begin{aligned}p(t)&=a_3t^3+a_2t^2+a_1t+a_0\\p(0)&=p_{\mu c},\quad p(\dot{0})=v_{\mu c}\\p(T)&=p_{\mu g},\quad p(\dot{T})=v_{\mu g}\end{aligned} p(t)p(0)p(T)=a3t3+a2t2+a1t+a0=pμc,p(0˙)=vμc=pμg,p(T˙)=vμg

   因此,可以得到该多项式系数满足下式:

   [ 0 0 0 1 0 0 1 0 T 3 T 2 T 1 3 T 2 2 T 1 0 ] [ a 3 a 2 a 1 a 0 ] = [ p μ c v μ c p μ g v μ g ] \begin{bmatrix}0&0&0&1\\0&0&1&0\\T^3&T^2&T&1\\3T^2&2T&1&0\end{bmatrix}\begin{bmatrix}a_3\\a_2\\a_1\\a_0\end{bmatrix}=\begin{bmatrix}p_{\mu c}\\v_{\mu c}\\p_{\mu g}\\v_{\mu g}\end{bmatrix} 00T33T200T22T01T11010 a3a2a1a0 = pμcvμcpμgvμg

   然后,基于庞特里亚金最小原理,得到最优的轨迹表达式如下:

   p μ ∗ ( t ) = 1 6 α μ t 3 + 1 2 β μ t 2 + v μ c t + p μ c [ α μ β μ ] = 1 T 3 [ − 12 6 T 6 T − 2 T 2 ] [ p μ g − p μ c − v μ c T v μ g − v μ c ] \begin{aligned}p_\mu^*(t)&=\frac{1}{6}\alpha_\mu t^3+\frac{1}{2}\beta_\mu t^2+v_{\mu c}t+p_{\mu c}\\\\\begin{bmatrix}\alpha_\mu\\\beta_\mu\end{bmatrix}&=\frac{1}{T^3}\begin{bmatrix}-12&6T\\6T&-2T^2\end{bmatrix}\begin{bmatrix}p_{\mu g}-p_{\mu c}-v_{\mu c}T\\v_{\mu g}-v_{\mu c}\end{bmatrix}\end{aligned} pμ(t)[αμβμ]=61αμt3+21βμt2+vμct+pμc=T31[126T6T2T2][pμgpμcvμcTvμgvμc]

   得到上面的位置轨迹后,求两阶导数可以得到加速度轨迹,在取位置和速度为状态量时,加速度也即控制输入:

   a μ ∗ ( t ) = α μ t + β μ u ( t ) : = [ a x ( t ) , a y ( t ) , a z ( t ) ] T \begin{aligned}&a_\mu^*(t)=\alpha_\mu t+\beta_\mu\\\\&\mathbf{u}(t):=[a_x(t),a_y(t),a_z(t)]^\mathrm{T}\end{aligned} aμ(t)=αμt+βμu(t):=[ax(t),ay(t),az(t)]T

   得到了这样一条轨迹后,就可以利用上面介绍的求小轨迹的代价的方式,求出这条轨迹的代价,作为考虑运动学但不考虑障碍物的启发式代价函数。

   T ∗ ( T ) = ∫ 0 l ∥ u ( t ) ∥ 2 d t + ρ T = ∑ μ ∈ { x , y , z } ( 1 3 α μ 2 T 3 + 1 2 α μ β μ T 2 + β μ 2 T ) + ρ T \begin{aligned} \mathcal{T}^{*}(T)& =\int_{0}^{l}\|\mathbf{u}(t)\|^{2}dt+\rho T \\ &=\sum_{\mu\in\{x,y,z\}}\left(\frac{1}{3}{\alpha_{\mu}}^{2}T^{3}+\frac{1}{2}\alpha_{\mu}\beta_{\mu}T^{2}+{\beta_{\mu}}^{2}T\right)+\rho T \end{aligned} T(T)=0lu(t)2dt+ρT=μ{x,y,z}(31αμ2T3+21αμβμT2+βμ2T)+ρT

   上面,我们假设时间T是人为给定的、已知的,但是很明显,我们并不清楚,从当前点到目标点合适的T应该如何选择。所以,我们可以将上式对T进行求导等于0,即 ∂ T ∗ ( T ) ∂ T = 0 \frac{\partial\mathcal{T}^*(T)}{\partial T}=0 TT(T)=0,来求取最合适的 T h T_h Th,进而得到代价值

在这里插入图片描述



   参考资料:

   1、[深蓝学院—移动机器人运动规划]

   链接放不了了,感兴趣的小伙伴自行查找吧

在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4.基础知识-数据库技术基础

基础知识 一、数据库基本概念1、数据库系统基础知识2、三级模式-两级映像3、数据库设计4、数据模型:4.1 E-R模型★4.2 关系模型★ 5、关系代数 二、规范化和并发控制1、函数依赖2、键与约束3、范式★3.1 第一范式1NF实例3.2 第二范式2NF3.3 第三范式3NF3.4 BC范式BC…

rockchip的yolov5 rknn python推理分析

rockchip的yolov5 rknn推理分析 对于rockchip给出的这个yolov5后处理代码的分析,本人能力十分有限,可能有的地方描述的很不好,欢迎大家和我一起讨论,指出我的错误!!! RKNN模型输出 将官方的Y…

直方图的最大长方形面积

前提知识:单调栈基础题-CSDN博客 子数组的最大值-CSDN博客 题目描述: 给定一个非负数(0和正数),代表直方图,返回直方图的最大长方形面积,比如,arr {3, 2, 4, 2, 5}&#xff0c…

景区导航导览系统:基于AR技术+VR技术的功能效益全面解析

在数字化时代背景下,游客对旅游体验的期望不断提升。游客们更倾向于使用手机作为旅行的贴身助手,不仅因为它能提供实时、精准的导航服务,更在于其融合AR(增强现实)、VR(虚拟现实)等前沿技术&…

十三、网络编程正则表达式设计模式(模块23)

网络编程&正则表达式&设计模式 模块23_网络编程&正则表达式&设计模式第一章.网络编程1.软件结构2.服务器概念3.通信三要素4.UDP协议编程4.1.客户端(发送端)4.2.服务端(接收端) 5.TCP协议编程4.1.编写客户端4.2.编写服务端 6.文件上传6.1.文件上传客户端以及服务…

【开发踩坑】 MySQL不支持特殊字符(表情)插入问题

背景 线上功能报错: Cause:java.sql.SQLException:Incorrect string value:xFO\x9F\x9FxBO for column commentat row 1 uncategorized SQLException; SQL state [HY000]:error code [1366]排查 初步觉得是编码问题(utf8 — utf8mb4) 参考上…

Leetcode 2520. 统计能整除数字的位数

问题描述: 给你一个整数 num ,返回 num 中能整除 num 的数位的数目。 如果满足 nums % val 0 ,则认为整数 val 可以整除 nums 。 示例 1: 输入:num 7 输出:1 解释:7 被自己整除&#xff0…

浅谈芯片验证中的仿真运行之 timescale (五)提防陷阱

一 仿真单位 timeunit 我们知道,当我们的代码中写清楚延时语句时,若不指定时间单位,则使用此单位; 例如: `timescale 1ns/1ps 则 #15 语句表示delay15ns; 例:如下代码,module a 的timescale是1ns/1ps, module b 是1ps/1ps; module b中的clk,频率是由输入参…

HTML开发笔记:1.环境、标签和属性、CSS语法

一、环境与新建 在VSCODE里&#xff0c;加载插件&#xff1a;“open in browser” 然后新建一个文件夹&#xff0c;再在VSCODE中打开该文件夹&#xff0c;在右上角图标新建文档&#xff0c;一定要是加.html&#xff0c;不要忘了文件后缀 复制任意一个代码比如&#xff1a; <…

primeflex教学笔记20240720, FastAPI+Vue3+PrimeVue前后端分离开发

练习 先实现基本的页面结构&#xff1a; 代码如下&#xff1a; <template><div class"flex p-3 bg-gray-100 gap-3"><div class"w-20rem h-12rem bg-indigo-200 flex justify-content-center align-items-center text-white text-5xl">…

C++关系运算符重载 函数运算符重载

#include <iostream> #include <string> using namespace std; //实现关系运算符重载 仿函数 class Person { public:Person(int Age,string Name){age Age;name Name;}int age;string name;int operator()(){return age ;}bool operator(const Person& p)…

用html做python教程01

用html做python教程01 前言开肝构思实操额外修饰更换字体自适应 最后 前言 今天打开csdn的时候&#xff0c;看见csdn给我推荐了一个python技能书。 说实话&#xff0c;做得真不错。再看看我自己&#xff0c;有亿点差距&#x1f61f;。 开肝 先创建一个文件&#xff0c;后缀…

获取本地时间(Linux下,C语言)

一、函数 #include <time.h> time_t time(time_t *tloc);函数功能&#xff1a;获取本机时间&#xff08;以秒数存储&#xff0c;从1970年1月1日0:0:0开始到现在&#xff09;。返回值&#xff1a;获得的秒数&#xff0c;如果形参非空&#xff0c;返回值也可以通过传址调用…

昇思25天学习打卡营第9天 | 使用静态图加速

用静态图加速在MindSpore中的实践体验 在深入学习MindSpore框架的过程中&#xff0c;我特别关注了动态图和静态图两种模式的运行机制及其各自的优缺点。通过实际编程实验和应用&#xff0c;我对静态图加速的效果和应用场景有了更深入的了解。 动态图与静态图的对比 在开始使…

Xcode学习笔记

Xcode学习笔记 前言一、在Mac上安装Xcode并做点简单设置1.查看一下Xcode的版本 二、使用Xcode新建一个Playground三、swift基础-变量1.swift是什么2.变量是什么3.建立变量4.改变变量5.小帖士 四、swift基础-变量命名规范1.使用小驼峰命名法2.使用有意义且描述性的名称3.避免使用…

【web】-flask-简单的计算题(不简单)

打开页面是这样的 初步思路&#xff0c;打开F12&#xff0c;查看头&#xff0c;都发现了这个表达式的base64加密字符串。编写脚本提交答案&#xff0c;发现不对&#xff1b; 无奈点开source发现源代码&#xff0c;是flask,初始化表达式&#xff0c;获取提交的表达式&#xff0…

【iOS】——探究isKindOfClass和isMemberOfClass底层实现

isKindOfClass 判断该对象是否为传入的类或其子类的实例 // 类方法实现&#xff0c;用于检查一个类是否属于另一个类或其父类链上的任何类。(BOOL)isKindOfClass:(Class)cls {// 从当前类开始&#xff0c;tcls将沿着元类的继承链向上遍历。for (Class tcls self->ISA(); …

【C#】计算两条直线的交点坐标

问题描述 计算两条直线的交点坐标&#xff0c;可以理解为给定坐标P1、P2、P3、P4&#xff0c;形成两条线&#xff0c;返回这两条直线的交点坐标&#xff1f; 注意区分&#xff1a;这两条线是否垂直、是否平行。 代码实现 斜率解释 斜率是数学中的一个概念&#xff0c;特别是…

视频分帧【截取图片】(YOLO目标检测【生成数据集】)

高效率制作数据集【按这个流程走&#xff0c;速度很顶】 本次制作&#xff0c;1059张图片【马路上流动车辆】 几乎就是全自动了&#xff0c;只要视频拍得好&#xff0c;YOLO辅助制作数据集就效率极高 视频中的图片抽取&#xff1a; 【由于视频内存过大&#xff0c;遇到报错执行…

Android 小白菜鸟从入门到精通教程

前言 Android一词最早出现于法国作家利尔亚当&#xff08;Auguste Villiers de l’Isle-Adam&#xff09;在1886年发表的科幻小说《未来的夏娃》&#xff08;L’ve future&#xff09;中。他将外表像人的机器起名为Android。从初学者的角度出发&#xff0c;通过通俗易懂的语言…