曲线生成 | 图解Dubins曲线生成原理(附ROS C++/Python/Matlab仿真)

目录

  • 0 专栏介绍
  • 1 什么是Dubins曲线?
  • 2 Dubins曲线原理
    • 2.1 坐标变换
    • 2.2 单步运动公式
    • 2.3 曲线模式
  • 3 Dubins曲线生成算法
  • 4 仿真实现
    • 4.1 ROS C++实现
    • 4.2 Python实现
    • 4.3 Matlab实现

0 专栏介绍

🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。

🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法


1 什么是Dubins曲线?

Dubins曲线是指由美国数学家 Lester Dubins 在20世纪50年代提出的一种特殊类型的最短路径曲线。这种曲线通常用于描述在给定转弯半径下的无人机、汽车或船只等载具的最短路径,其特点是起始点和终点处的切线方向和曲率都是已知的。

在这里插入图片描述

Dubins曲线包括直线段和最大转弯半径下的圆弧组成,通过合适的组合可以实现从一个姿态到另一个姿态的最短路径规划。这种曲线在航空、航海、自动驾驶等领域具有广泛的应用,能够有效地规划航行路径,减少能量消耗并提高效率。

2 Dubins曲线原理

2.1 坐标变换

如图所示,在全局坐标系 x O y xOy xOy中,设机器人起始位姿、终止位姿、最小转弯半径分别为 ( x s , y s , α ) \left( x_s,y_s,\alpha \right) (xs,ys,α) ( x g , y g , β ) \left( x_g,y_g,\beta \right) (xg,yg,β) R R R,则以 p s = ( x s , y s ) \boldsymbol{p}_s=\left( x_s,y_s \right) ps=(xs,ys)为新坐标系原点, p s \boldsymbol{p}_s ps指向 p g = ( x g , y g ) \boldsymbol{p}_g=\left( x_g,y_g \right) pg=(xg,yg)方向为 x ′ x' x轴,垂直方向为 y ′ y' y轴建立新坐标系 x ′ O ′ y ′ x'O'y' xOy

在这里插入图片描述

根据比例关系 d / D = r / R {{d}/{D}}={{r}/{R}} d/D=r/R,其中 D = ∥ p s − p g ∥ 2 D=\left\| \boldsymbol{p}_s-\boldsymbol{p}_g \right\| _2 D= pspg 2。为了便于后续推导,不妨归一化最小转弯半径,即令 r = 1 r=1 r=1。所以在坐标系 x ′ O ′ y ′ x'O'y' xOy中,通常取起点、终点间距为 d = D / R d={{D}/{R}} d=D/R,从而起始位姿、终止位姿、最小转弯半径分别转换为

s t a r t = [ 0 0 α − θ ] T , g o a l = [ d 0 β − θ ] T , r = 1 \mathrm{start}=\left[ \begin{matrix} 0& 0& \alpha -\theta\\\end{matrix} \right] ^T, \mathrm{goal}=\left[ \begin{matrix} d& 0& \beta -\theta\\\end{matrix} \right] ^T, r=1 start=[00αθ]T,goal=[d0βθ]T,r=1

其中 θ = a r c tan ⁡ ( ( y g − y s ) / ( x g − x s ) ) \theta =\mathrm{arc}\tan \left( {{\left( y_g-y_s \right)}/{\left( x_g-x_s \right)}} \right) θ=arctan((ygys)/(xgxs)),接下来的推导均基于转换坐标系 x ′ O ′ y ′ x'O'y' xOy

2.2 单步运动公式

对于直行运动,设沿直线行进距离为 l l l,则

[ x ∗ y ∗ ϕ ∗ ] T = [ x + l cos ⁡ ϕ y + l sin ⁡ ϕ ϕ ] T \left[ \begin{matrix} x^*& y^*& \phi ^*\\\end{matrix} \right] ^T=\left[ \begin{matrix} x+l\cos \phi& y+l\sin \phi& \phi\\\end{matrix} \right] ^T [xyϕ]T=[x+lcosϕy+lsinϕϕ]T

对于转弯运动,假设转向角为 ψ \psi ψ,则由弧长公式可得

l = ψ r = r = 1 ψ l=\psi r\xlongequal{r=1}\psi l=ψrr=1 ψ

因此设沿圆弧行进距离为 l l l,以左转为例,由几何关系易得

[ x ∗ y ∗ ϕ ∗ ] T = [ x + r sin ⁡ ( ϕ + ψ ) − r sin ⁡ ( ϕ ) y + r cos ⁡ ( ϕ + ψ ) + r cos ⁡ ( ϕ ) ϕ + ψ ] T \left[ \begin{matrix} x^*& y^*& \phi ^*\\\end{matrix} \right] ^T=\left[ \begin{matrix} x+r\sin \left( \phi +\psi \right) -r\sin \left( \phi \right)& y+r\cos \left( \phi +\psi \right) +r\cos \left( \phi \right)& \phi +\psi\\\end{matrix} \right] ^T [xyϕ]T=[x+rsin(ϕ+ψ)rsin(ϕ)y+rcos(ϕ+ψ)+rcos(ϕ)ϕ+ψ]T

代入 r = 1 r=1 r=1 ψ = l \psi=l ψ=l可得

[ x ∗ y ∗ ϕ ∗ ] T = [ x + sin ⁡ ( ϕ + l ) − sin ⁡ ( ϕ ) y + cos ⁡ ( ϕ + l ) + cos ⁡ ( ϕ ) ϕ + l ] T \left[ \begin{matrix} x^*& y^*& \phi ^*\\\end{matrix} \right] ^T=\left[ \begin{matrix} x+\sin \left( \phi +l \right) -\sin \left( \phi \right)& y+\cos \left( \phi +l \right) +\cos \left( \phi \right)& \phi +l\\\end{matrix} \right] ^T [xyϕ]T=[x+sin(ϕ+l)sin(ϕ)y+cos(ϕ+l)+cos(ϕ)ϕ+l]T

同理,对于右转而言,有

[ x ∗ y ∗ ϕ ∗ ] T = [ x − sin ⁡ ( ϕ − l ) + sin ⁡ ( ϕ ) y + cos ⁡ ( ϕ + l ) − cos ⁡ ( ϕ ) ϕ − l ] T \left[ \begin{matrix} x^*& y^*& \phi ^*\\\end{matrix} \right] ^T=\left[ \begin{matrix} x-\sin \left( \phi -l \right) +\sin \left( \phi \right)& y+\cos \left( \phi +l \right) -\cos \left( \phi \right)& \phi -l\\\end{matrix} \right] ^T [xyϕ]T=[xsin(ϕl)+sin(ϕ)y+cos(ϕ+l)cos(ϕ)ϕl]T

综上所述,可得单步运动映射

{ L l + ( x , y , ϕ ) = [ x + sin ⁡ ( ϕ + l ) − sin ⁡ ( ϕ ) y − cos ⁡ ( ϕ + l ) + cos ⁡ ( ϕ ) ϕ + l ] T R l + ( x , y , ϕ ) = [ x − sin ⁡ ( ϕ − l ) + sin ⁡ ( ϕ ) y + cos ⁡ ( ϕ − l ) − cos ⁡ ( ϕ ) ϕ − l ] T S l + ( x , y , ϕ ) = [ x + l cos ⁡ ϕ y + l sin ⁡ ϕ ϕ ] T \begin{cases} L_{l}^{+}\left( x,y,\phi \right) =\left[ \begin{matrix} x+\sin \left( \phi +l \right) -\sin \left( \phi \right)& y-\cos \left( \phi +l \right) +\cos \left( \phi \right)& \phi +l\\\end{matrix} \right] ^T\\ R_{l}^{+}\left( x,y,\phi \right) =\left[ \begin{matrix} x-\sin \left( \phi -l \right) +\sin \left( \phi \right)& y+\cos \left( \phi -l \right) -\cos \left( \phi \right)& \phi -l\\\end{matrix} \right] ^T\\ S_{l}^{+}\left( x,y,\phi \right) =\left[ \begin{matrix} x+l\cos \phi& y+l\sin \phi& \phi\\\end{matrix} \right] ^T\\\end{cases} Ll+(x,y,ϕ)=[x+sin(ϕ+l)sin(ϕ)ycos(ϕ+l)+cos(ϕ)ϕ+l]TRl+(x,y,ϕ)=[xsin(ϕl)+sin(ϕ)y+cos(ϕl)cos(ϕ)ϕl]TSl+(x,y,ϕ)=[x+lcosϕy+lsinϕϕ]T

2.3 曲线模式

Dubins曲线假设物体只能向前,通过组合左转、右转、直行可得六种运动模式

{ L S L , R S R , R S L , L S R , R L R , L R L } \left\{ LSL, RSR, RSL, LSR, RLR, LRL \right\} {LSL,RSR,RSL,LSR,RLR,LRL}

可以总结这六种运动模式的解析解为

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

3 Dubins曲线生成算法

Dubins曲线路径生成算法流程如表所示

在这里插入图片描述

4 仿真实现

4.1 ROS C++实现

核心代码如下所示

Points2d Dubins::generation(Pose2d start, Pose2d goal)
{Points2d path;double sx, sy, syaw;double gx, gy, gyaw;std::tie(sx, sy, syaw) = start;std::tie(gx, gy, gyaw) = goal;// coordinate transformationgx -= sx;gy -= sy;double theta = helper::mod2pi(atan2(gy, gx));double dist = hypot(gx, gy) * max_curv_;double alpha = helper::mod2pi(syaw - theta);double beta = helper::mod2pi(gyaw - theta);// select the best motionDubinsMode best_mode;double best_cost = DUBINS_MAX;DubinsLength length;DubinsLength best_length = { DUBINS_NONE, DUBINS_NONE, DUBINS_NONE };DubinsMode mode;for (const auto solver : dubins_solvers){(this->*solver)(alpha, beta, dist, length, mode);_update(length, mode, best_length, best_mode, best_cost);}if (best_cost == DUBINS_MAX)return path;// interpolation...// coordinate transformationEigen::AngleAxisd r_vec(theta, Eigen::Vector3d(0, 0, 1));Eigen::Matrix3d R = r_vec.toRotationMatrix();Eigen::MatrixXd P = Eigen::MatrixXd::Ones(3, path_x.size());for (size_t i = 0; i < path_x.size(); i++){P(0, i) = path_x[i];P(1, i) = path_y[i];}P = R * P;for (size_t i = 0; i < path_x.size(); i++)path.push_back({ P(0, i) + sx, P(1, i) + sy });return path;
}

4.2 Python实现

核心代码如下所示

def generation(self, start_pose: tuple, goal_pose: tuple):sx, sy, syaw = start_posegx, gy, gyaw = goal_pose# coordinate transformationgx, gy = gx - sx, gy - sytheta = self.mod2pi(math.atan2(gy, gx))dist = math.hypot(gx, gy) * self.max_curvalpha = self.mod2pi(syaw - theta)beta = self.mod2pi(gyaw - theta)# select the best motionplanners = [self.LSL, self.RSR, self.LSR, self.RSL, self.RLR, self.LRL]best_t, best_p, best_q, best_mode, best_cost = None, None, None, None, float("inf")for planner in planners:t, p, q, mode = planner(alpha, beta, dist)if t is None:continuecost = (abs(t) + abs(p) + abs(q))if best_cost > cost:best_t, best_p, best_q, best_mode, best_cost = t, p, q, mode, cost# interpolation...# coordinate transformationrot = Rot.from_euler('z', theta).as_matrix()[0:2, 0:2]converted_xy = rot @ np.stack([x_list, y_list])x_list = converted_xy[0, :] + sxy_list = converted_xy[1, :] + syyaw_list = [self.pi2pi(i_yaw + theta) for i_yaw in yaw_list]return best_cost, best_mode, x_list, y_list, yaw_list

在这里插入图片描述

4.3 Matlab实现

核心代码如下所示

function [x_list, y_list, yaw_list] = generation(start_pose, goal_pose, param)sx = start_pose(1); sy = start_pose(2); syaw = start_pose(3);gx = goal_pose(1); gy = goal_pose(2); gyaw = goal_pose(3);% coordinate transformationgx = gx - sx; gy = gy - sy;theta = mod2pi(atan2(gy, gx));dist = hypot(gx, gy) * param.max_curv;alpha = mod2pi(syaw - theta);beta = mod2pi(gyaw - theta);% select the best motionplanners = ["LSL", "RSR", "LSR", "RSL", "RLR", "LRL"];best_cost = inf;best_segs = [];best_mode = [];for i=1:length(planners)planner = str2func(planners(i));[segs, mode] = planner(alpha, beta, dist);if isempty(segs)continueendcost = (abs(segs(1)) + abs(segs(2)) + abs(segs(3)));if best_cost > costbest_segs = segs;best_mode = mode;best_cost = cost;endend% interpolation...% coordinate transformationrot = [cos(theta), -sin(theta); sin(theta), cos(theta)];converted_xy = rot * [x_list; y_list];x_list = converted_xy(1, :) + sx;y_list = converted_xy(2, :) + sy;for j=1:length(yaw_list)yaw_list(j) = pi2pi(yaw_list(j) + theta);end
end

在这里插入图片描述

完整工程代码请联系下方博主名片获取


🔥 更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

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

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

相关文章

Foxmail快捷键设置问题

当快捷键设置错误时不会生效&#xff0c;原来的快捷键仍有效&#xff0c;即使禁用快捷键功能&#xff0c;原先快捷键仍有效。正确的快捷键&#xff1a; 1. 不能是空&#xff08;NULL&#xff09; 2. 应该设置按键值只有一个的键盘按钮。

【动态规划专栏】

动态规划基础知识 概念 动态规划&#xff08;Dynamic Programming&#xff0c;DP&#xff09;&#xff1a;用来解决最优化问题的算法思想。 动态规划是分治思想的延伸&#xff0c;通俗一点来说就是大事化小&#xff0c;小事化无的艺术。 一般来说&#xff0c;…

探索Hadoop的三种运行模式:单机模式、伪分布式模式和完全分布式模式

目录 前言一、 单机模式二、 伪分布式模式三、 完全分布式模式&#xff08;重点&#xff09;3.1 准备工作3.2 配置集群3.2.1 配置core-site.xml 文件3.2.2 配置hdfs-site.xml 文件3.2.3 配置yarn-site.xml 文件3.2.4 配置mapred-site.xml 文件 3.3 启动集群3.3.1 配置workers3.…

RK3568 android11 调试陀螺仪模块 MPU6500

一&#xff0c;MPU6500功能介绍 1.简介 MPU6500是一款由TDK生产的运动/惯性传感器&#xff0c;属于惯性测量设备&#xff08;IMU&#xff09;的一种。MPU6500集成了3轴加速度计、3轴陀螺仪和一个板载数字运动处理器&#xff08;DMP&#xff09;&#xff0c;能够提供6轴的运动…

Matlab|基于Logistic函数负荷需求响应

目录 1 基于Logistic函数的负荷转移率模型 2 程序示例 3 效果图 4 下载链接 负荷需求响应模型种类较多&#xff0c;有电价型和激励型等类型&#xff0c;本次和大家分享一个基于Logistic函数的负荷转移率模型&#xff0c;该模型属于电价型&#xff0c;由于该方法使用的较少&a…

亿道信息发布两款升级款全加固笔记本电脑

2022年5月19日&#xff0c;加固手持终端。加固平板电脑、加固笔记本电脑专业设计商和制造商&#xff0c;以及加固型移动计算机软硬件整体定制解决方案提供商亿道信息&#xff0c;宣布对其两款广受欢迎的加固笔记本电脑产品EM-X14U和EM-X15U进行重大升级。新发布的两款升级款全加…

《TCP/IP详解 卷一》第10章 UDP 和 IP 分片

目录 10.1 引言 10.2 UDP 头部 10.3 UDP校验和 10.4 例子 10.5 UDP 和 IPv6 10.6 UDP-Lite 10.7 IP分片 10.7.1 例子&#xff1a;IPV4 UDP分片 10.7.2 重组超时 10.8 采用UDP的路径MTU发现 10.9 IP分片和ARP/ND之间的交互 10.10 最大UDP数据报长度 10.11 UDP服务器…

Docker将本地的镜像上传到私有仓库

使用register镜像创建私有仓库 [rootopenEuler-node1 ~]# docker run --restartalways -d -p 5000:5000 -v /opt/data/regostry:/var/lib/registry registry:2[rootopenEuler-node1 ~]# docker images REPOSITORY TAG IMAGE…

基于React低代码平台开发:构建高效、灵活的应用新范式

文章目录 一、React与低代码平台的结合优势二、基于React的低代码平台开发挑战三、基于React的低代码平台开发实践四、未来展望《低代码平台开发实践&#xff1a;基于React》编辑推荐内容简介作者简介目录前言为什么要写这本书 读者对象如何阅读本书 随着数字化转型的深入&…

内核中的Kconfig文件

Kconfig解析 编译内核时用于配置的Kconfig文件 以内核中的ttyprintk.c为例&#xff0c;其位于/kernel-sources/dirver/char/ttyprintk.c 如何将其编译进内核&#xff1f; 在char目录下有Kconfig文件&#xff0c;其中有如下内容 tristate 表示该模块可以选择 Y N M(以.ko形…

华为od机试C卷-最长表达式求值

1 题目描述 提取字符串中的最长合法简单数学表达式子串&#xff0c;字符串长度最长的&#xff0c;并计算表达式的值&#xff0c;如果没有返回0。简单数学表达式只能包含以下内容0-9 数字&#xff0c;符号* 说明: 1.所有数字&#xff0c;计算结果都不超过 long 2.如果有多个长…

递归实现n的k次方(C语言)

编写一个函数实现n的k次方&#xff0c;使用递归实现。 下面来说一下思路 5的3次方&#xff1a;就是5*(5的3-1次方) 7的4次方&#xff1a;就是7*&#xff08;7的4-1次方&#xff09; 以此类推 n的k次方就是&#xff1a;n* n的&#xff08;k-1&#xff09;次方 int Func(int n,…

HOOPS Communicator对3D大模型轻量化加载与渲染的4种解决方案

今天给大家介绍一些关于3D Web轻量化引擎HOOPS Commuicator的关键概念&#xff0c;这些概念可以帮您在HOOPS Communicator流缓存服务器之上更好地构建您自己的模型流服务器。如果您是有大型数据集&#xff0c;那么&#xff0c;使用流缓存服务器可以极大地帮助您最大限度地减少内…

Unity-PDF分割器(iTextSharp)

PDF分割器 Unity-PDF分割器前言核心思路解决过程一、Unity安装iTextSharp二、运行时计算将要生成文件的大小三、分割核心代码四、使用StandaloneFileBrowser五、其他的一些脚本六、游戏界面主体的构建MainWindowWarningPanel & FinishPanel By-Round Moon Unity-PDF分割器 …

基于主从模式的Reactor的仿muduo网络库

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

【.NET Core】.NET中的流(Stream)

【.NET Core】.NET中的流&#xff08;Stream&#xff09; 文章目录 【.NET Core】.NET中的流&#xff08;Stream&#xff09;一、流&#xff08;Stream&#xff09;1.1 FileStream类1.2 IsolatedStorageFileStream类1.3 MemoryStream类1.4 BufferedStream类1.5 NetworkStream类…

谷歌浏览器打开,图片糊了

现象&#xff08;问题&#xff09;&#xff1a;早上开机&#xff0c;打开谷歌浏览器发现里面的所有图片相关的都糊了&#xff0c;离谱&#xff01; 查阅一番资料后发现&#xff1a; 谷歌浏览器的硬件加速模式被打开了 解决&#xff1a; 打开谷歌浏览器->设置->系统->…

【C++从练气到飞升】01---C++入门

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书。 目录 推荐 前言 什么是C C的发展史 &#x1f4cb;命名空间 命名空间定义 命名空间使用 命名空间的嵌套 std命名空间的使用 &#…

编译 qsqlmysql.dll QMYSQL driver not loaded

Qt 连接MySQL数据库&#xff0c;没有匹配的qsqlmysql.dll, 需要我们跟进自己Mysql 以及QT版本自行编译的。异常如下图&#xff1a; 安装环境为 VS2019 Qt5.12.12&#xff08;msvc2017_64、以及源码&#xff09; 我的安装地址&#xff1a;D:\Qt\Qt5.12.12 Mysql 8.1.0 默认安…

2023年下半年教师资格证考试《教育知识与能力》(中学)题

3.李老师在初二选择了人数、性别比例、学习成绩、教材各方面情况相同的两个班进行教学&#xff0c;对其中一班采用讲授法&#xff0c;对另一个班采用自学辅导法&#xff0c;经过一个阶段的教学后进行测验&#xff0c;以比较两种方法教学效果&#xff0c;李老师采用的方法属于&a…