自动驾驶规划模块学习笔记-多项式曲线

这篇具有很好参考价值的文章主要介绍了自动驾驶规划模块学习笔记-多项式曲线。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

自动驾驶运动规划中会用到各种曲线,主要用于生成车辆变道的轨迹,高速场景中使用的是五次多项式曲线,城市场景中使用的是分段多项式曲线(piecewise),相比多项式,piecewise能够生成更为复杂的路径。另外对于自由空间,可以使用A*搜索出的轨迹再加以cilqr加以平滑,也能直接供控制使用。下面的内容不一定都对,欢迎大家一起交流学习~

目录

基础类

三次多项式曲线

四次多项式曲线

五次多项式曲线

下期预告:piecewise曲线 


基础类

// 基类Curve1d,定义一维曲线(变量是时间)
class Curve1d {
 public:
  // 构造函数
  Curve1d() = default;
  // 拷贝构造函数
  Curve1d(const Curve1d& other) = default;
  // 有继承的基类的析构函数需要定义为虚函数
  virtual ~Curve1d() = default;
  // 纯虚函数,子类实现,曲线不同阶数对应的param时刻的结果
  virtual double Evaluate(const std::uint32_t order, const double param) const = 0;
  // 纯虚函数,子类实现,时长
  virtual double ParamLength() const = 0;
};

三次多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

构造函数定义

x0初始位置,dx0初始速度,ddx0初始加速度,x1终点位置,param时间长度,这个很好理解

// 定义了两种构造函数的实现

// 第一种构造函数的实现是直接调用第二种构造函数
CubicPolynomialCurve1d::CubicPolynomialCurve1d(const std::array<double, 3>& start, const double end, const double param)
    : CubicPolynomialCurve1d(start[0], start[1], start[2], end, param) {}

// 第二种构造函数,x0初始位置,dx0初始速度,ddx0初始加速度,x1终点位置,param时间长度
CubicPolynomialCurve1d::CubicPolynomialCurve1d(const double x0, const double dx0, const double ddx0, const double x1,
                                               const double param) {
  ComputeCoefficients(x0, dx0, ddx0, x1, param);
  param_ = param;
  start_condition_[0] = x0;
  start_condition_[1] = dx0;
  start_condition_[2] = ddx0;
  end_condition_ = x1;
}

计算多项式系数

方法1:一般地,自动驾驶里初始状态对应的是当前时刻,规划时长为param的轨迹,可以理解初始状态即为0时刻的状态,这样的话,多项式系数就很好求出来了

 

void CubicPolynomialCurve1d::ComputeCoefficients(const double x0, const double dx0, const double ddx0, const double x1,
                                                 const double param) {
  assert(param > 0.0);
  const double p2 = param * param;
  const double p3 = param * p2;
  coef_[0] = x0;
  coef_[1] = dx0;
  coef_[2] = 0.5 * ddx0;
  coef_[3] = (x1 - x0 - dx0 * param - coef_[2] * p2) / p3;
}

方法2:已知初始和终点的位置和速度,没有加速度,也比较简单,C2和C3需要手动推算下

自动驾驶规划模块学习笔记-多项式曲线, p为终点时刻

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

// 注意这里的返回类型,用到了this指针,相当于返回一个实例化的类
CubicPolynomialCurve1d& CubicPolynomialCurve1d::FitWithEndPointFirstOrder(const double x0, const double dx0, const double x1, 
                                                                          const double dx1, const double param) {
  if (param <= 0.0) {
    return *this;
  }
  param_ = param;
  coef_[0] = x0;
  coef_[1] = dx0;

  double param2 = param * param;
  double param3 = param2 * param;
  
  double b0 = dx1 + 2 * coef_[1];
  double b1 = dx1 + coef_[1];

  coef_[2] = (3 * x1 - b0 * param -3 * coef_[0]) / param2;
  coef_[3] = (2 * coef_[0] + b1 * param - 2 * x1) / param3;

  return *this;
}

方法3:通过四次多项式曲线来推算,这里用到四次多项式求导为三次多项式的关系

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

以此类推

// 这里为什么要用静态类型转换static_cast
void CubicPolynomialCurve1d::DerivedFromQuarticCurve(const PolynomialCurve1d& other) {
  assert(other.Order() == 4);
  param_ = other.ParamLength();
  for (size_t i = 1; i < 5; ++i) {
    coef_[i - 1] = other.Coef(i) * static_cast<double>(i);
  }
}

多项式曲线阶数求值

这里代码有点没太看懂,p是param的几次方?

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

double CubicPolynomialCurve1d::Evaluate(const std::uint32_t order, const double p) const {
  switch (order) {
    case 0: {
      return ((coef_[3] * p + coef_[2]) * p + coef_[1]) * p + coef_[0];
    }
    case 1: {
      return (3.0 * coef_[3] * p + 2.0 * coef_[2]) * p + coef_[1];
    }
    case 2: {
      return 6.0 * coef_[3] * p + 2.0 * coef_[2];
    }
    case 3: {
      return 6.0 * coef_[3];
    }
    default:
      return 0.0;
  }
}

四次多项式曲线

构造函数

 四次多项式有五个系数,所以需要五个状态量

QuarticPolynomialCurve1d::QuarticPolynomialCurve1d(
    const std::array<double, 3>& start, const std::array<double, 2>& end,
    const double param)
    : QuarticPolynomialCurve1d(start[0], start[1], start[2], end[0], end[1],
                               param) {}

QuarticPolynomialCurve1d::QuarticPolynomialCurve1d(
    const double x0, const double dx0, const double ddx0, const double dx1,
    const double ddx1, const double param) {
  param_ = param;
  start_condition_[0] = x0;
  start_condition_[1] = dx0;
  start_condition_[2] = ddx0;
  end_condition_[0] = dx1;
  end_condition_[1] = ddx1;
  ComputeCoefficients(x0, dx0, ddx0, dx1, ddx1, param);
}

求解多项式系数

方法1:已知初始状态x0,dx0,ddx0和终点状态dx1,ddx1,相当于终点的位置是不确定的。代码中C3和C4计算没有使用C1和C2,是避免计算过程中带来的误差,是一种较好的处理方法。但阅读起来可能不直观,可以参考下面公式,实质是一样的。

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

void QuarticPolynomialCurve1d::ComputeCoefficients(
    const double x0, const double dx0, const double ddx0, const double dx1,
    const double ddx1, const double p) {
  CHECK_GT(p, 0.0);

  coef_[0] = x0;
  coef_[1] = dx0;
  coef_[2] = 0.5 * ddx0;

  double b0 = dx1 - ddx0 * p - dx0;
  double b1 = ddx1 - ddx0;

  double p2 = p * p;
  double p3 = p2 * p;

  coef_[3] = (3 * b0 - b1 * p) / (3 * p2);
  coef_[4] = (-2 * b0 + b1 * p) / (4 * p3);
}

方法2和3:终点或初始位置的加速度不确定,已知其他参数,推导过程与上面类似,注意这里返回的是实例化的类

QuarticPolynomialCurve1d& QuarticPolynomialCurve1d::FitWithEndPointFirstOrder(
    const double x0, const double dx0, const double ddx0, const double x1,
    const double dx1, const double p) {
  CHECK_GT(p, 0.0);

  param_ = p;

  coef_[0] = x0;

  coef_[1] = dx0;

  coef_[2] = 0.5 * ddx0;

  double p2 = p * p;
  double p3 = p2 * p;
  double p4 = p3 * p;

  double b0 = x1 - coef_[0] - coef_[1] * p - coef_[2] * p2;
  double b1 = dx1 - dx0 - ddx0 * p;

  coef_[4] = (b1 * p - 3 * b0) / p4;
  coef_[3] = (4 * b0 - b1 * p) / p3;
  return *this;
}
QuarticPolynomialCurve1d& QuarticPolynomialCurve1d::FitWithEndPointSecondOrder(
    const double x0, const double dx0, const double x1, const double dx1,
    const double ddx1, const double p) {
  CHECK_GT(p, 0.0);

  param_ = p;

  coef_[0] = x0;

  coef_[1] = dx0;

  double p2 = p * p;
  double p3 = p2 * p;
  double p4 = p3 * p;

  double b0 = x1 - coef_[0] - coef_[1] * p;
  double b1 = dx1 - coef_[1];
  double c1 = b1 * p;
  double c2 = ddx1 * p2;

  coef_[2] = (0.5 * c2 - 3 * c1 + 6 * b0) / p2;
  coef_[3] = (-c2 + 5 * c1 - 8 * b0) / p3;
  coef_[4] = (0.5 * c2 - 2 * c1 + 3 * b0) / p4;

  return *this;
}

方法4和5:根据三次多项式积分或五次多项式微分得到

QuarticPolynomialCurve1d& QuarticPolynomialCurve1d::IntegratedFromCubicCurve(
    const PolynomialCurve1d& other, const double init_value) {
  CHECK_EQ(other.Order(), 3U);
  param_ = other.ParamLength();
  coef_[0] = init_value;
  for (size_t i = 0; i < 4; ++i) {
    coef_[i + 1] = other.Coef(i) / (static_cast<double>(i) + 1);
  }
  return *this;
}

QuarticPolynomialCurve1d& QuarticPolynomialCurve1d::DerivedFromQuinticCurve(
    const PolynomialCurve1d& other) {
  CHECK_EQ(other.Order(), 5U);
  param_ = other.ParamLength();
  for (size_t i = 1; i < 6; ++i) {
    coef_[i - 1] = other.Coef(i) * static_cast<double>(i);
  }
  return *this;
}

多项式曲线阶数求值

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

自动驾驶规划模块学习笔记-多项式曲线

double QuarticPolynomialCurve1d::Evaluate(const std::uint32_t order,
                                          const double p) const {
  switch (order) {
    case 0: {
      return (((coef_[4] * p + coef_[3]) * p + coef_[2]) * p + coef_[1]) * p +
             coef_[0];
    }
    case 1: {
      return ((4.0 * coef_[4] * p + 3.0 * coef_[3]) * p + 2.0 * coef_[2]) * p +
             coef_[1];
    }
    case 2: {
      return (12.0 * coef_[4] * p + 6.0 * coef_[3]) * p + 2.0 * coef_[2];
    }
    case 3: {
      return 24.0 * coef_[4] * p + 6.0 * coef_[3];
    }
    case 4: {
      return 24.0 * coef_[4];
    }
    default:
      return 0.0;
  }
}

五次多项式曲线

整体思路和四次多项式类型,附上代码,可以参考上面思路理解

在具体代码实现时,数值求解比矩阵计算效率更高文章来源地址https://www.toymoban.com/news/detail-451500.html

QuinticPolynomialCurve1d::QuinticPolynomialCurve1d(
    const std::array<double, 3>& start, const std::array<double, 3>& end,
    const double param)
    : QuinticPolynomialCurve1d(start[0], start[1], start[2], end[0], end[1],
                               end[2], param) {}

QuinticPolynomialCurve1d::QuinticPolynomialCurve1d(
    const double x0, const double dx0, const double ddx0, const double x1,
    const double dx1, const double ddx1, const double param) {
  ComputeCoefficients(x0, dx0, ddx0, x1, dx1, ddx1, param);
  start_condition_[0] = x0;
  start_condition_[1] = dx0;
  start_condition_[2] = ddx0;
  end_condition_[0] = x1;
  end_condition_[1] = dx1;
  end_condition_[2] = ddx1;
  param_ = param;
}
void QuinticPolynomialCurve1d::ComputeCoefficients(
    const double x0, const double dx0, const double ddx0, const double x1,
    const double dx1, const double ddx1, const double p) {
  CHECK_GT(p, 0.0);

  coef_[0] = x0;
  coef_[1] = dx0;
  coef_[2] = ddx0 / 2.0;

  const double p2 = p * p;
  const double p3 = p * p2;

  // the direct analytical method is at least 6 times faster than using matrix
  // inversion.
  const double c0 = (x1 - 0.5 * p2 * ddx0 - dx0 * p - x0) / p3;
  const double c1 = (dx1 - ddx0 * p - dx0) / p2;
  const double c2 = (ddx1 - ddx0) / p;

  coef_[3] = 0.5 * (20.0 * c0 - 8.0 * c1 + c2);
  coef_[4] = (-15.0 * c0 + 7.0 * c1 - c2) / p;
  coef_[5] = (6.0 * c0 - 3.0 * c1 + 0.5 * c2) / p2;
}
void QuinticPolynomialCurve1d::IntegratedFromQuarticCurve(
    const PolynomialCurve1d& other, const double init_value) {
  CHECK_EQ(other.Order(), 4U);
  param_ = other.ParamLength();
  coef_[0] = init_value;
  for (size_t i = 0; i < 5; ++i) {
    coef_[i + 1] = other.Coef(i) / (static_cast<double>(i) + 1);
  }
}
double QuinticPolynomialCurve1d::Evaluate(const uint32_t order,
                                          const double p) const {
  switch (order) {
    case 0: {
      return ((((coef_[5] * p + coef_[4]) * p + coef_[3]) * p + coef_[2]) * p +
              coef_[1]) *
                 p +
             coef_[0];
    }
    case 1: {
      return (((5.0 * coef_[5] * p + 4.0 * coef_[4]) * p + 3.0 * coef_[3]) * p +
              2.0 * coef_[2]) *
                 p +
             coef_[1];
    }
    case 2: {
      return (((20.0 * coef_[5] * p + 12.0 * coef_[4]) * p) + 6.0 * coef_[3]) *
                 p +
             2.0 * coef_[2];
    }
    case 3: {
      return (60.0 * coef_[5] * p + 24.0 * coef_[4]) * p + 6.0 * coef_[3];
    }
    case 4: {
      return 120.0 * coef_[5] * p + 24.0 * coef_[4];
    }
    case 5: {
      return 120.0 * coef_[5];
    }
    default:
      return 0.0;
  }
}

下期预告:piecewise曲线 

到了这里,关于自动驾驶规划模块学习笔记-多项式曲线的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 曲线生成 | 基于多项式插值的轨迹规划(附ROS C++/Python/Matlab仿真)

    🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。 🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法 多项式插值(polynomial

    2024年02月03日
    浏览(39)
  • 机器学习_数据升维_多项式回归代码_保险案例数据说明_补充_均匀分布_标准正太分布---人工智能工作笔记0038

    然后我们再来看一下官网注意上面这个旧的,现在2023-05-26 17:26:31..我去看了新的官网, scikit-learn已经添加了很多新功能,     我们说polynomial多项式回归其实是对数据,进行 升维对吧,从更多角度去看待问题,这样 提高模型的准确度. 其实y=w0x0+w1x1.. 这里就是提高了这个x的个数对吧

    2024年02月06日
    浏览(45)
  • 机器人在笛卡尔空间和关节空间的多项式轨迹规划以及matlab代码(三次、五次、七次)

    三次多项式轨迹规划就是s(t)相对于时间t的变化满足三次多项式变化,其表达式如下:                      如前文所述:t的取值范围是[0,T],s(t)的取值范围是[0,1], 又因为初始速度和末速度都为0,所以: S(t)的一阶导数表达式为: 从而可以计算出对应的系数: 将

    2024年01月17日
    浏览(44)
  • Python 中的机器学习简介:多项式回归

            多项式回归可以识别自变量和因变量之间的非线性关系。本文是关于回归、梯度下降和 MSE 系列文章的第三篇。前面的文章介绍了简单线性回归、回归的正态方程和多元线性回归。         多项式回归用于最适合曲线拟合的复杂数据。它可以被视为多元线性回

    2024年02月13日
    浏览(45)
  • 机器学习-朴素贝叶斯(高斯、多项式、伯努利)

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 贝叶斯分类器主要思想是基于贝叶斯定理,是机器学习中重要的分类算法,适用于高维度的大数据集,速度快,准确率高,一个经典的应用场景是识别垃圾邮件。

    2023年04月09日
    浏览(70)
  • 机器学习-朴素贝叶斯之多项式模型

    贝叶斯概率公式,来自Wang’s Blog的原创 输出结果: 显示的没办法爬数据,我又换了一组数据 输出的效果还挺不错

    2024年02月08日
    浏览(44)
  • 每天五分钟机器学习:多项式非线性回归模型

    在前面的课程中,我们学习了线性回归模型和非线性回归模型的区别和联系。多项式非线性回归模型是一种用于拟合非线性数据的回归模型。与线性回归模型不同,多项式非线性回归模型可以通过增加多项式的次数来适应更复杂的数据模式。在本文中,我们将介绍多项式非线

    2024年02月16日
    浏览(48)
  • MATLAB仿真UR5机器人simulink simscape 自制建模 正向运动学,逆向运动学关节空间轨迹规划 五次多项式轨迹规划

    MATLAB仿真UR5机器人simulink simscape 自制建模  正向运动学,逆向运动学 关节空间轨迹规划 五次多项式轨迹规划 笛卡尔空间轨迹规划 直线插补    还包含机器人工具箱建立的模型对比 MATLAB仿真UR5机器人simulink simscape 自制建模及运动学规划 摘要:本文介绍了利用MATLAB仿真UR5机器

    2024年02月04日
    浏览(67)
  • AA@有理系数多项式@整系数多项式@本原多项式@有理多项式可约问题

    有理数域上一元多项式的因式分解. 作为 因式分解定理 的一个特殊情形,我们有结论: 每个次数大等于1的 有理系数多项式 都能 唯一地 分解成 不可约的有理系数多项式 的乘积. 有理数域版本中,从一般数域具体到了\\\" 有理系数 \\\" 我们讨论多项式的时候,都假设多项式是在某个数

    2024年02月16日
    浏览(51)
  • 机器学习:多项式拟合分析中国温度变化与温室气体排放量的时序数据

    ​ 当分析数据时,如果我们找的不是直线或者超平面,而是一条曲线,那么就可以用多项式回归来分析和预测。 ​ 多项式回归可以写成: Y i = β 0 + β 1 X i + β 2 X i 2 + . . . + β k X i k Y_{i} = beta_{0} +beta_{1}X_{i}+beta_{2}X_{i}^2+...+beta_{k}X_{i}^k Y i ​ = β 0 ​ + β 1 ​ X i ​ + β 2 ​

    2023年04月21日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包