1. 简介

贝塞尔曲线于 1962 年,由法国工程师皮埃尔·贝济埃(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计,贝塞尔曲线最初由保尔·德·卡斯特里奥于1959年运用德卡斯特里奥算法开发,以稳定数值的方法求出贝塞尔曲线.

贝塞尔曲线有着很多特殊的性质, 在图形设计和路径规划中应用都非常广泛, 贝塞尔曲线完全由其控制点决定其形状, n个控制点对应着n-1阶的贝塞尔曲线,并且可以通过递归的方式来绘制.

先感受一下贝塞尔曲线:
贝塞尔曲线

2. 公式及原理

一阶贝塞尔曲线

中间点运动的轨迹为:

一阶曲线就是很好理解, 就是根据t来的线性插值. P0表示的是一个向量 [x ,y], 其中x和y是分别按照这个公式来计算的.

二阶贝塞尔曲线

既然重点是递归, 那么二阶贝塞尔必然和一阶有关系.

在平面内任选 3 个不共线的点,依次用线段连接。在第一条线段上任选一个点 D。计算该点到线段起点的距离 AD,与该线段总长 AB 的比例。
根据上一步得到的比例,从第二条线段上找出对应的点 E,使得 AD:AB = BE:BC。

这时候DE又是一条直线了, 就可以按照一阶的贝塞尔方程来进行线性插值了, t= AD:AB

这时候就可以推出公式了.

三阶贝塞尔曲线


二阶的贝塞尔通过在控制点之间再采点的方式实现降阶, 每一次选点都是一次的降阶.

四个点对应是三次的贝塞尔曲线. 分别在 AB BC CD 之间采EFG点, EFG三个点对应着二阶贝塞尔, 在EF FG之间采集HI点来降阶为一阶贝塞尔曲线.

贝塞尔曲线公式

可以通过递归的方式来理解贝塞尔曲线, 但是还是给出公式才方便计算的.
仔细看可以发现, 贝塞尔的参数B是二项式(t+(1-t))^n = (1)^n的展开公式. 划重点了: 系数是二项式的展开. 后面的很多的贝塞尔曲线的性质都可以用这个来解释

3. 贝塞尔曲线的性质

贝塞尔曲线具有众多特性,例如:递归性、凸包性、对称性、几何不变性、仿射不变性、拟局部性,保证了生成曲线的平滑性、连续性和可控性。

3.1 各项系数之和为1.
这个很好理解,因为是系数是二项式的展开(t+(1-t))^n = (1)^n非负性. 好理解, 二项式的展开啊

3.2 递归性
递归性指其系数满足下式:
3.3一阶导数性质
假设上图中贝塞尔的t是由左到右从0到1增加的,那么贝塞尔曲线在t=0时的导数是和P0P1的斜率(导数)是相同,t=1时的导数是和P2 P3的斜率(导数)是相同

这一点的性质可以用在贝塞尔曲线的拼接,只要保证三点一线中的中间点是两段贝塞尔曲线的连接点,就可以保证两端贝塞尔曲线的导数连续连续.

4. 如何确定贝塞尔曲线的控制点

假设道路上已经有(n+1)个采样点Pi(i=0,1,…,n),需要在相邻的每两个点P(i)和P(i+1)之间,用一条3次Bezier曲线连接。即由4个点确定, P0为起点、P3为终点,另外中间2个控制点P1和P2。

由四个控制点定义的平面三阶贝塞尔曲线可以形式化地表示为:

如图所示,在轨迹生成过程中,将目标车辆的中心点坐标作为起点P0,以目标车辆的驶意图为引导推理得到的目标点作为P3,其他两个控制点由车辆的约束条件计算得到。

由于车辆在运动过程中无法进行原地滑动移动,所以生成的曲线需要满足起点方向约束。另外,在执行换道和转弯动作时,在终点处行驶轨迹要遵从道路结构化特征的约束,行驶轨迹的切线方向和道路的走势要相同,所以生成轨迹的终点需要满足终点方向约束。为了满足上述方向约束,P1和P2分别通过以起点坐标为起点沿起点航向向前移动距离d,以终点P3为起点沿终点航向的反方向向后移动距离d得到。

简单来说,考虑到车辆起止点速度方向的连续性,即要求曲线函数的一阶导数连续。

5. 代码实现

import matplotlib.pyplot as plt
import numpy as np
import scipy.specialshow_animation = Truedef calc_4points_bezier_path(sx, sy, syaw, ex, ey, eyaw, offset):"""Compute control points and path given start and end position.:param sx: (float) x-coordinate of the starting point:param sy: (float) y-coordinate of the starting point:param syaw: (float) yaw angle at start:param ex: (float) x-coordinate of the ending point:param ey: (float) y-coordinate of the ending point:param eyaw: (float) yaw angle at the end:param offset: (float):return: (numpy array, numpy array)"""dist = np.hypot(sx - ex, sy - ey) / offsetcontrol_points = np.array([[sx, sy],[sx + dist * np.cos(syaw), sy + dist * np.sin(syaw)],[ex - dist * np.cos(eyaw), ey - dist * np.sin(eyaw)],[ex, ey]])path = calc_bezier_path(control_points, n_points=100)return path, control_pointsdef calc_bezier_path(control_points, n_points=100):"""Compute bezier path (trajectory) given control points.:param control_points: (numpy array):param n_points: (int) number of points in the trajectory:return: (numpy array)"""traj = []for t in np.linspace(0, 1, n_points):traj.append(bezier(t, control_points))return np.array(traj)def bernstein_poly(n, i, t):"""Bernstein polynom.:param n: (int) polynom degree:param i: (int):param t: (float):return: (float)"""return scipy.special.comb(n, i) * t ** i * (1 - t) ** (n - i)def bezier(t, control_points):"""Return one point on the bezier curve.:param t: (float) number in [0, 1]:param control_points: (numpy array):return: (numpy array) Coordinates of the point"""n = len(control_points) - 1return np.sum([bernstein_poly(n, i, t) * control_points[i] for i in range(n + 1)], axis=0)def bezier_derivatives_control_points(control_points, n_derivatives):"""Compute control points of the successive derivatives of a given bezier curve.A derivative of a bezier curve is a bezier curve.See https://pomax.github.io/bezierinfo/#derivativesfor detailed explanations:param control_points: (numpy array):param n_derivatives: (int)e.g., n_derivatives=2 -> compute control points for first and second derivatives:return: ([numpy array])"""w = {0: control_points}for i in range(n_derivatives):n = len(w[i])w[i + 1] = np.array([(n - 1) * (w[i][j + 1] - w[i][j])for j in range(n - 1)])return wdef curvature(dx, dy, ddx, ddy):"""Compute curvature at one point given first and second derivatives.:param dx: (float) First derivative along x axis:param dy: (float):param ddx: (float) Second derivative along x axis:param ddy: (float):return: (float)"""return (dx * ddy - dy * ddx) / (dx ** 2 + dy ** 2) ** (3 / 2)def plot_arrow(x, y, yaw, length=1.0, width=0.5, fc="r", ec="k"):  # pragma: no cover"""Plot arrow."""if not isinstance(x, float):for (ix, iy, iyaw) in zip(x, y, yaw):plot_arrow(ix, iy, iyaw)else:plt.arrow(x, y, length * np.cos(yaw), length * np.sin(yaw),fc=fc, ec=ec, head_width=width, head_length=width)plt.plot(x, y)def main():"""Plot an example bezier curve."""start_x = 10.0  # [m]start_y = 1.0  # [m]start_yaw = np.radians(180.0)  # [rad]end_x = -0.0  # [m]end_y = -3.0  # [m]end_yaw = np.radians(-45.0)  # [rad]offset = 3.0path, control_points = calc_4points_bezier_path(start_x, start_y, start_yaw, end_x, end_y, end_yaw, offset)# Note: alternatively, instead of specifying start and end position# you can directly define n control points and compute the path:# control_points = np.array([[5., 1.], [-2.78, 1.], [-11.5, -4.5], [-6., -8.]])# path = calc_bezier_path(control_points, n_points=100)# Display the tangent, normal and radius of cruvature at a given pointt = 0.86  # Number in [0, 1]x_target, y_target = bezier(t, control_points)derivatives_cp = bezier_derivatives_control_points(control_points, 2)point = bezier(t, control_points)dt = bezier(t, derivatives_cp[1])ddt = bezier(t, derivatives_cp[2])# Radius of curvatureradius = 1 / curvature(dt[0], dt[1], ddt[0], ddt[1])# Normalize derivativedt /= np.linalg.norm(dt, 2)tangent = np.array([point, point + dt])normal = np.array([point, point + [- dt[1], dt[0]]])curvature_center = point + np.array([- dt[1], dt[0]]) * radiuscircle = plt.Circle(tuple(curvature_center), radius,color=(0, 0.8, 0.8), fill=False, linewidth=1)assert path.T[0][0] == start_x, "path is invalid"assert path.T[1][0] == start_y, "path is invalid"assert path.T[0][-1] == end_x, "path is invalid"assert path.T[1][-1] == end_y, "path is invalid"if show_animation:  # pragma: no coverfig, ax = plt.subplots()ax.plot(path.T[0], path.T[1], label="Bezier Path")ax.plot(control_points.T[0], control_points.T[1],'--o', label="Control Points")ax.plot(x_target, y_target)ax.plot(tangent[:, 0], tangent[:, 1], label="Tangent")ax.plot(normal[:, 0], normal[:, 1], label="Normal")ax.add_artist(circle)plot_arrow(start_x, start_y, start_yaw)plot_arrow(end_x, end_y, end_yaw)ax.legend()ax.axis("equal")ax.grid(True)plt.show()def main2():"""Show the effect of the offset."""start_x = 10.0  # [m]start_y = 1.0  # [m]start_yaw = np.radians(180.0)  # [rad]end_x = -0.0  # [m]end_y = -3.0  # [m]end_yaw = np.radians(-45.0)  # [rad]for offset in np.arange(1.0, 5.0, 1.0):path, control_points = calc_4points_bezier_path(start_x, start_y, start_yaw, end_x, end_y, end_yaw, offset)assert path.T[0][0] == start_x, "path is invalid"assert path.T[1][0] == start_y, "path is invalid"assert path.T[0][-1] == end_x, "path is invalid"assert path.T[1][-1] == end_y, "path is invalid"if show_animation:  # pragma: no coverplt.plot(path.T[0], path.T[1], label="Offset=" + str(offset))if show_animation:  # pragma: no coverplot_arrow(start_x, start_y, start_yaw)plot_arrow(end_x, end_y, end_yaw)plt.legend()plt.axis("equal")plt.grid(True)plt.show()if __name__ == '__main__':main()

参考文章:
1.曲线篇-贝塞尔曲线
2.运动规划-贝塞尔Bezier曲线
3.自动驾驶-初探轨迹规划

轨迹规划-贝塞尔曲线相关推荐

  1. 轨迹规划——Bezier曲线与B样条曲线

    一.Bezier曲线 1.Bezier曲线的背景 给定n+1个数据点,p0~pn,生成一条曲线,使得该曲线与这些点描述的形状相符. (如果要求曲线通过所有数据点,则属于插值问题:如果只要求曲线逼近这些 ...

  2. 自动驾驶路径轨迹规划(三阶曲线spline)

    对于给定的一连串waypoints我们需要对其进行平滑线处理,这里介绍一种三阶spline的平滑方法: call function: clc clear all% x = [-4 -2 0 2 4 6 ...

  3. 前端动画之贝塞尔曲线推导及应用

    hello,大家好,今天豆皮范儿给大家带来了贝塞尔曲线推导和应用,优美的贝塞尔曲线想起了大学时候老师在给我们讲如何实现,如何推导,如何实现和应用.本来也来详细介绍一下,纯纯的干货- 作者:lff 生活 ...

  4. 《考虑车辆运动约束的最优避障轨迹规划算法》论文解读二

    目录 1 贝塞尔曲线 1.1 公式推导 1.2 Bernstein基函数的性质 1.3 贝塞尔曲线的性质 1.4 曲线的连续性 2 贝塞尔曲线规划器 2.1 局部轨迹 2.2 约束 1 贝塞尔曲线 这 ...

  5. 六轴机械臂-正解+逆解+轨迹规划实现

    之前,写了一篇博客,从坐标系的说明 -> D-H参数表的建立 -> 正解和逆解的整个算法推导过程整理了一篇博客https://blog.csdn.net/ymj7150697/articl ...

  6. Bezier(贝塞尔)曲线的轨迹规划在自动驾驶中的应用(一)

    本文主要根据Path Generation and Tracking Based on a Bézier Curve for a Steering Rate Controller of Autonom ...

  7. 轨迹规划之 贝塞尔曲线

    轨迹规划之 贝塞尔曲线 前言 贝塞尔曲线 低次贝塞尔曲线的表达式 贝塞尔曲线的切线 高次贝塞尔曲线 高次贝塞尔曲线表达式 贝塞尔曲线的递归性 贝塞尔曲线的连接 贝塞尔曲线的速度 代码示例1:普通贝塞尔 ...

  8. Bezier(贝塞尔)曲线的轨迹规划在自动驾驶中的应用(二)

    根据(一)中的理论前提,我们通过matlab进行一次仿真验证: clcclear allp0 = [ 0, 0];p1 = [10,0.5];p2= [20,3.5];p3 = [30,4];%设置控 ...

  9. Bezier(贝塞尔)曲线(五阶)的轨迹规划在自动驾驶中的应用(六)

    本文介绍贝塞尔五阶曲线最为curve smoother的使用,分析关于时间的一阶和二阶导数的连续性,以及曲率的连续性,并给出一个smoother的实例进行效果展示. clcclear allp0 = ...

最新文章

  1. js学习总结----crm客户管理系统之项目开发流程和api接口文档
  2. Spring Framework 5.2.5 发布,增加对 Java 14 的支持
  3. 大专python工资有多高-最新 | 2019年Python工程师的平均薪资是多少?
  4. c类网络使用子网掩码有无实际意义_弄懂IP系列(2)(刘晶作品)|子网掩码到底是啥?...
  5. 逆水寒服务器更新响应超时,逆水寒patcher.zip文件更新失败怎么办 更新文件异常问题解决方法...
  6. C#全能数据库操作类及调用示例
  7. es6-super关键字
  8. UIWebView / NSURL / NSBoundle 相关应用 (实例,加载完成前的背景, 默认safari打开链接地址等)...
  9. 手机MODEM 开发(33)---SimCard 学习总结
  10. ASP.NET的视图(Razor)循环产生html代码
  11. RabbitMq学习笔记001---RabbitMq在Windows下安装配置
  12. 计算机基础是五笔吗,计算机基础 五笔一.ppt
  13. solr java 客户端
  14. python-map()/reduce()/filter()/sorted()/排列组合
  15. 《steam community 启动发现端口被占用》
  16. nginx容器通过docker内置DNS实现动态负载
  17. 修改远程计算机 时间,Pubwin服务器时间修改的四种办法
  18. Android开发工具类
  19. grep命令的-P选项
  20. 好吧,cnblogs给我的下马威

热门文章

  1. linux下的ld命令(1)
  2. 教你简单4步制作“截图工具”,再也不用微信或QQ截图了
  3. Scala样例类(case class)
  4. HTML5期末大作业:校园网站设计——云南艺术学院文化学院(3页) HTML+CSS+JavaScript web前端开发技术 web课程设计 网页规划与设计
  5. SpringBoot+Vue实现前后端分离的宠物医院管理系统
  6. java计算机毕业设计飞机航班信息查询系统源码+mysql数据库+系统+lw文档+部署
  7. 气质数据提取物质信息并批量查阅、翻译
  8. Android中的适配
  9. MSDTC无法启动的解决办法
  10. Tripleo之nova-compute 和Ironic的代码深入分析(三)