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

目录

  • 0 专栏介绍
  • 1 贝塞尔曲线的应用
  • 2 图解贝塞尔曲线
  • 3 贝塞尔曲线的性质
  • 4 算法仿真
    • 4.1 ROS C++仿真
    • 4.2 Python仿真
    • 4.3 Matlab仿真

0 专栏介绍

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

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


1 贝塞尔曲线的应用

贝塞尔曲线是一种数学曲线,由法国数学家皮埃尔·贝塞尔于1962年引入。它使用一组控制点来定义曲线的形状,这些控制点的位置和数量决定了曲线的特征。贝塞尔曲线的应用非常广泛:

  • 计算机图形学:贝塞尔曲线可以用于绘制平滑的曲线和曲面。在计算机图形学中,它们被广泛用于绘制二维和三维图形对象,如曲线、路径、字体等。贝塞尔曲线具有良好的平滑性和灵活性,在图形渲染和模型构建方面发挥着重要作用;
  • CAD 设计:贝塞尔曲线在计算机辅助设计中起到关键作用。设计师可以使用贝塞尔曲线创建和编辑复杂的曲线形状,如汽车外形、船体曲线、建筑物外观等。贝塞尔曲线的控制点可以通过拖动和调整来改变曲线的形状,使设计过程更加灵活和直观;
  • 动画和游戏开发:贝塞尔曲线提供了一种方便的方法来定义和控制动画路径和运动轨迹。动画师可以使用贝塞尔曲线来创建平滑的动画路径,让角色和物体按照指定的路径移动。在游戏开发中,贝塞尔曲线也常用于实现精确的物体运动轨迹和碰撞检测;
  • 字体设计:贝塞尔曲线被广泛应用于字体设计中。每个字母、数字或符号都可以由一组贝塞尔曲线组成,通过调整和连接这些曲线,可以创建出各种字体形状和风格。贝塞尔曲线的灵活性使得字体设计者能够轻松地创建出各种自然流畅的字符形状。

2 图解贝塞尔曲线

设平面上存在 n n n个离散的控制节点,则贝塞尔曲线的阶数 n − 1 n-1 n1。这 n n n个节点按某个顺序依次联结形成特征多边形,一个特征多边形将递归地确定一条以比例系数 t ∈ [ 0 , 1 ] t \in [0,1 ] t[0,1]为参数的贝塞尔曲线

在这里插入图片描述

如图所示为1阶贝塞尔曲线的生成过程,具体地,对于一阶贝塞尔曲线有

P 1 ( t ) = ( 1 − t ) p 0 + t p 1 \boldsymbol{P}_1\left( t \right) =\left( 1-t \right) \boldsymbol{p}_0+t\boldsymbol{p}_1 P1(t)=(1t)p0+tp1

其中控制节点 p i = [ x i , y i ] T \boldsymbol{p}_i=\left[ x_i,y_i \right] ^T pi=[xi,yi]T

对于二阶贝塞尔曲线,首先给定比例系数 t ∈ [ 0 , 1 ] t \in [0,1 ] t[0,1],使

∣ p 0 a ∣ ∣ p 0 p 1 ∣ = ∣ p 1 b ∣ ∣ p 1 p 2 ∣ = ∣ a q ∣ ∣ a b ∣ \frac{|\boldsymbol{p}_0\boldsymbol{a}|}{|\boldsymbol{p}_0\boldsymbol{p}_1|}=\frac{|\boldsymbol{p}_1\boldsymbol{b}|}{|\boldsymbol{p}_1\boldsymbol{p}_2|}=\frac{|\boldsymbol{aq}|}{|\boldsymbol{ab}|} p0p1p0a=p1p2p1b=abaq

其中 q \boldsymbol{q} q落在由 a \boldsymbol{a} a b \boldsymbol{b} b确定的一阶贝塞尔曲线上, a \boldsymbol{a} a b \boldsymbol{b} b分别落在由 p 0 \boldsymbol{p}_0 p0 p 1 \boldsymbol{p}_1 p1 p 1 \boldsymbol{p}_1 p1 p 2 \boldsymbol{p}_2 p2确定的一阶贝塞尔曲线上,因此 q \boldsymbol{q} q最终为二阶贝塞尔曲线上的一点,有

P 2 ( t ) = ( 1 − t ) a + t b \boldsymbol{P}_2\left( t \right) =\left( 1-t \right) \boldsymbol{a}+t\boldsymbol{b} P2(t)=(1t)a+tb

P 2 ( t ) = ( 1 − t ) 2 p 0 + 2 t ( 1 − t ) p 1 + t 2 p 2 \boldsymbol{P}_2\left( t \right) =\left( 1-t \right) ^2\boldsymbol{p}_0+2t\left( 1-t \right) \boldsymbol{p}_1+t^2\boldsymbol{p}_2 P2(t)=(1t)2p0+2t(1t)p1+t2p2

如图所示

在这里插入图片描述

递推地,有

P ( t ) = ∑ i = 0 n − 1 p i B i , n − 1 ( t ) , t ∈ [ 0 , 1 ] \boldsymbol{P}\left( t \right) =\sum_{i=0}^{n-1}{\boldsymbol{p}_iB_{i,n-1}\left( t \right)}, t\in \left[ 0,1 \right] P(t)=i=0n1piBi,n1(t),t[0,1]

其中 p i ( i = 0 , ⋯ , n − 1 ) \boldsymbol{p}_i\left( i=0,\cdots ,n-1 \right) pi(i=0,,n1)为控制节点的有序序列, B i , n ( t ) = C n i t i ( 1 − t ) n − i , t ∈ [ 0 , 1 ] B_{i,n}\left( t \right) =C_{n}^{i}t^i\left( 1-t \right) ^{n-i},t\in \left[ 0,1 \right] Bi,n(t)=Cniti(1t)ni,t[0,1]称为伯恩斯坦多项式(Bernstein Polynomial),可视为权重因子,即曲线上某点 P ( t ) \boldsymbol{P}\left( t \right) P(t)是控制节点序列的加权平均

3 贝塞尔曲线的性质

贝塞尔曲线具有非常多优良的性质,主要列举如下

  • 归一性:各项系数和为1
  • 凸包性:贝塞尔曲线始终被所有控制点形成的最小凸多边形所包含
  • 端点性:由于 B 0 , n ( 0 ) = B n , n ( 1 ) = 1 B_{0,n}\left( 0 \right) =B_{n,n}\left( 1 \right) =1 B0,n(0)=Bn,n(1)=1,所以贝塞尔曲线始于 p 0 \boldsymbol{p}_0 p0终于 p n \boldsymbol{p}_n pn,但不经过中间控制节点,即为逼近而非插值
  • 几何不变性:贝塞尔曲线的形状仅与特征多边形各顶点相对位置有关,与坐标系的选择无关
  • 变差伸缩性:若贝塞尔曲线特征多边形是一个平面图形,则平面内任意直线与贝塞尔曲线交点的个数不多于该直线与特征多边形的交点个数
  • 微分 P ′ ( t ) = n ∑ i = 1 n ( p i − p i − 1 ) B i − 1 , n − 1 ( t ) \boldsymbol{P}'\left( t \right) =n\sum\nolimits_{i=1}^n{\left( \boldsymbol{p}_i-\boldsymbol{p}_{i-1} \right) B_{i-1,n-1}\left( t \right)} P(t)=ni=1n(pipi1)Bi1,n1(t),即 n n n阶贝塞尔曲线的导数是 n − 1 n-1 n1阶贝塞尔曲线,控制节点为 q i = n ( p i + 1 − p i ) , i = 0 , ⋯ , n − 1 \boldsymbol{q}_i=n\left( \boldsymbol{p}_{i+1}-\boldsymbol{p}_i \right) , i=0,\cdots ,n-1 qi=n(pi+1pi),i=0,,n1。特别地, P ′ ( 0 ) = n ( p 1 − p 0 ) \boldsymbol{P}'\left( 0 \right) =n\left( \boldsymbol{p}_1-\boldsymbol{p}_0 \right) P(0)=n(p1p0) P ′ ( 1 ) = n ( p n − p n − 1 ) \boldsymbol{P}'\left( 1 \right) =n\left( \boldsymbol{p}_n-\boldsymbol{p}_{n-1} \right) P(1)=n(pnpn1),即贝塞尔曲线首末位置切线方向与特征多边形首末边方向一致

4 算法仿真

4.1 ROS C++仿真

核心代码如下

Points2d Bezier::generation(Pose2d start, Pose2d goal)
{double sx, sy, syaw;double gx, gy, gyaw;std::tie(sx, sy, syaw) = start;std::tie(gx, gy, gyaw) = goal;int n_points = (int)(helper::dist(Point2d(sx, sy), Point2d(gx, gy)) / step_);Points2d control_pts = getControlPoints(start, goal);Points2d points;for (size_t i = 0; i < n_points; i++){double t = (double)(i) / (double)(n_points - 1);points.push_back(bezier(t, control_pts));}return points;
}

其中bezier函数实现了伯恩斯坦多项式求和

Point2d Bezier::bezier(double t, Points2d control_pts)
{size_t n = control_pts.size() - 1;Point2d pt(0, 0);for (size_t i = 0; i < n + 1; i++){pt.first += _comb(n, i) * std::pow(t, i) * std::pow(1 - t, n - i) * control_pts[i].first;pt.second += _comb(n, i) * std::pow(t, i) * std::pow(1 - t, n - i) * control_pts[i].second;}return pt;
}

4.2 Python仿真

核心代码如下所示

def generation(self, start_pose: tuple, goal_pose: tuple):sx, sy, _ = start_posegx, gy, _ = goal_posen_points = int(np.hypot(sx - gx, sy - gy) / self.step)control_points = self.getControlPoints(start_pose, goal_pose)return [self.bezier(t, control_points) for t in np.linspace(0, 1, n_points)], \control_points
def bezier(self, t: float, control_points: list) ->np.ndarray:n = len(control_points) - 1control_points = np.array(control_points)return np.sum([comb(n, i) * t ** i * (1 - t) ** (n - i) * control_points[i] for i in range(n + 1)], axis=0)

在这里插入图片描述

4.3 Matlab仿真

核心代码如下所示

function curve = generation(start, goal, param)sx = start(1); sy = start(2);gx = goal(1); gy = goal(2);n_points =  hypot(sx - gx, sy - gy) / param.step;control_pts = getControlPoints(start, goal, param);curve = [];for t=0:1 / n_points:1curve = [curve; bezier(t, control_pts)];end
end
function curve_pt = bezier(t, control_pts)[m, ~] = size(control_pts);n = m - 1;pt_x = 0; pt_y = 0;for i=0:npt_x = pt_x + nchoosek(n, i) * power(t, i) * power(1 - t, n - i) * control_pts(i + 1, 1);pt_y = pt_y + nchoosek(n, i) * power(t, i) * power(1 - t, n - i) * control_pts(i + 1, 2);endcurve_pt = [pt_x, pt_y];
end

在这里插入图片描述

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


🔥 更多精彩专栏

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

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

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

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

相关文章

全包了 功能超级强大的linux管理平台1panel部署教程

目录 先看下效果 1.1panel是什么 2.安装教程 2.1下载安装包 2.2解压 2.3安装 3.查看 3.1初始化并登录 3.2容器管理页面&#xff0c;可以启动 重启 创建容器 ​编辑 3.3应用商店 意见安装常用应用 ​编辑 3.4可视化任务管理 3.5网站管理 3.6数据库管理 ​编辑 3…

iOS UIViewContentMode 不同效果图文对比

一. iOS提供了的ContentMode有如下几种 其中默认mode是UIViewContentModeScaleToFill typedef NS_ENUM(NSInteger, UIViewContentMode) {UIViewContentModeScaleToFill,UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is tr…

Python教程44:海龟画图turtle画卡塔尔世界杯吉祥物

---------------turtle源码集合--------------- Python教程42&#xff1a;海龟画图turtle画海绵宝宝 Python教程41&#xff1a;海龟画图turtle画蜡笔小新 Python教程40&#xff1a;使用turtle画一只杰瑞 Python教程39&#xff1a;使用turtle画美国队长盾牌 Python教程38&a…

领域驱动设计解决汉诺塔问题-文风批评(1)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 以下文章内容纯属虚构&#xff0c;用来批评某些领域驱动设计文风。后续将挑一些近期的文章作为例子来批评。 ********** 领域驱动设计是革命性的创新&#xff0c;是划时代的洞见。领…

OpenCV-Python(40):光流算法

目标 光流的概念以及Lucas-Kanade 光流法使用函数cv2.calcOpticalFlowPyrLK() 对图像中的特征点进行跟踪 光流 介绍 由于目标对象或者摄像机的移动造成的图像对象在连续两帧图像中的移动被称为光流。它是一个2D 向量场&#xff0c;可以用来显示一个点从第一帧图像到第二帧图像…

CLion、IDEA设置编码为utf-8,防乱码

其实只要是JetBrains的软件都是通用的&#xff0c;下面以IDEA为例 1.设置项目文件编码 2.设置控制台的字符编码

bash shell基础命令

1.shell启动 shell提供了对Linux系统的交互式访问&#xff0c;通常在用户登录终端时启动。系统启动的shell程序取决于用户账户的配置。 /etc/passwd/文件包含了所有用户的基本信息配置&#xff0c; $ cat /etc/passwd root:x:0:0:root:/root:/bin/bash ...例如上述root账户信…

【外汇天眼】误入假冒Ctrl Investments无法出金,投资者:太相信网友了!

在当下这个互联网迅速发展的时代&#xff0c;各类交友类APP成为人们拓展社交圈的新渠道。一方面这样的交友软件在满足了用户基础的社交要求&#xff0c;另一方面网络世界所交往的朋友能给用户带来的神秘感和新鲜感&#xff0c;所以导致一部分年轻人离不开这些交友软件。然而&am…

Python 两种多值参数

有时可能需要一个函数中处理的参数的个数是不确定的&#xff0c;就需要使用多值参数 参数名前加上*&#xff0c;代表可以接收元组参数名前加上**&#xff0c;代表可以接收字典 代码&#xff1a; def demo(*args, **kwargs):print(args)print(kwargs)demo(1, 2, 3, 4, 5, nam…

两个数组的交集 II

题目链接 两个数组的交集 II 题目描述 注意点 返回结果中每个元素出现的次数&#xff0c;应与元素在两个数组中都出现的次数一致&#xff08;如果出现次数不一致&#xff0c;则考虑取较小值&#xff09;可以不考虑输出结果的顺序 解答思路 使用哈希表存储nums1中的元素及出…

“语言服务40人论坛2023年年会”在北京举行

为充分发挥区域合作优势&#xff0c;深度推进翻译专业学位研究生培养模式和路径建设&#xff0c;提升翻译人才培养质量&#xff0c;推动京津冀地区教育协同发展&#xff0c;为中国高质量发展提供语言服务智慧和方案&#xff0c;1月13日至14日&#xff0c;“语言服务40人论坛202…

2.IHRM人力资源 - 登录

一、登录页结构与表单开发 我们要实现的登录界面 目前的登录界面 1.1 登录页结构 复制下面的代码到views/login/index.vue页面下 <template><div class"login-container"><div class"logo"/><div class"form"><h1&…

CANFD数据记录仪在新能源汽车复杂路测下的应用

CANFD数据记录仪在新能源汽车复杂路测下的应用 汽车制造商在生产预批量阶段的耐久性测试中,为了检测潜在故障,必须让车辆在严酷的路况和环境下接受测试。为确保能回溯故障发生的现场情况,我们需要对测试数据精准记录与储存。这些数据是新车型优化迭代的关键,也是确保产品质量的…

【2023我的编程之旅】系统学习C语言easyx图形库心得体会

目录 引言 C语言基础知识回顾 easyx图形库介绍 如何快速学习easyx图形库 学习笔记积累 学习成果展示 学习拓展 总结 引言 首先说一下我为什么要学习C语言easyx图形库。我接触C语言easyx图形库是在我今年一月份的时候&#xff0c;也是机缘巧合之下偶然在B站上看到了鸣人…

C++力扣题目669--修剪二叉搜索树

给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c;原有的父代子代关系都应当保留)。…

Win10不用U盘重装系统教程

在Win10电脑中&#xff0c;用户想重装电脑系统&#xff0c;但是自己没有U盘&#xff0c;想知道不用U盘要怎么完成Win10系统的重装&#xff1f;接下来小编给大家介绍Win10系统不用U盘重装的步骤&#xff0c;帮助大家轻轻松松完成系统Win10的重新安装&#xff0c;体验Win10系统的…

CF1446C Xor Tree 题解 DP Trie树

Xor Tree 传送门 题面翻译 给定你一个非负整数序列 a a a&#xff0c;保证其中每个数两两不同。 对于每个 a i a _ i ai​&#xff0c;它会向 j ≠ i j \ne i ji 且 a i ⊕ a j a_i\oplus a_j ai​⊕aj​&#xff08; ⊕ \oplus ⊕ 代表异或&#xff09;最小的 a j a…

React18-树形菜单-递归

文章目录 案例分析技巧通信展示效果实现代码技巧点技巧点 Refer to 案例分析 https://github.com/dL-hx/manager-fe/commit/85faf3b1ae9a925513583feb02b9a1c87fb462f7 从接口获取城市数据,渲染出一个树形菜单 要求: 可以展开和收起 技巧 学会递归渲染出一个树形菜单, 并点击后…

gramine运行nodejs例程

首先&#xff0c; 修改js例程代码&#xff1a; const { Web3 } require(web3); const rpcURL "https://sepolia.infura.io/v3/40b89bc0f5584056b19626b521ee5874"; const web3 new Web3(rpcURL); const address "0xde51E698b4585Af1C8322cc084ABbdbDcfe533…

C++力扣题目450--删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#xff1a; 首先…