从路径优化学习FastPlanner之B样条曲线平滑(二):FastPlanner中B样条曲线代码理解与解读

news2024/9/17 7:15:19

参考别人的博客学习
根据之前一章只是大致了解了B样条数学原理,实际读代码还有疑惑。

控制点是什么?和规划出的路径点什么关系?
控制点可以说我们规划出的路径点,即n等于轨迹点个数。也可以不是轨迹点,通过线性方程反解出控制点
B样条曲线是少C0,即至少是连续的,但不能保证C1(即可导,无折现)甚至更高C2.。。
在这里插入图片描述
p3,p4为 规划出的点,若直接当作控制点生成B样条,则因为点的位置注定P3处不可导。若要可导则必定要移动P4到上面,那怎么求出P4的位置呢? 求出样条基函数后线性方程反解出控制点即可得到平滑的P4。
即C1连续以上控制点只能生成。

规划出的路径大多是开B样条曲线(Open Curves),即首尾没用有连接一起。所以U的范围由之前的[U0,Um],变为 [Up,Um-p].
在这里插入图片描述

代码初始化有些细节

这里直接粘贴大佬解释后的代码。

这里明确一下流程:调用evaluateDeBoorT函数,将参数t转换为u,后调用evaluateDeBoor计算出变量u,然后就是evaluateDeBoor里将基函数和控制点累加相乘,返回的是曲线上的点,即我们想要拟合完后的某i个路径点

注意:B样条最后出来的拟合函数参数是t,De Boor算法来计算B样条基函数的参数是u,所以要把u转换成t。转换方法很简单就是线性转换。
在这里插入图片描述

通俗讲: 3级样条基函数Nm-3,3,需要4个0级样条计算得来,对应范围如图[Um-3,Um+1)四个定义域的连接,通过转换定义域对应t的[0,4)
U=t_cur + i * dt+u_(p_)

 pos = traj[0].evaluateDeBoorT(t_cur + i * dt);  //这里调用evaluateDeBoorT 把t转成u
Eigen::VectorXd NonUniformBspline::evaluateDeBoorT(const double& t) {
  return evaluateDeBoor(t + u_(p_));  
}
/*De Boor递归算法,计算传入参数u处的B样条曲线值,返回B-样条曲线在参数 u 处的B样条曲线函数*/
Eigen::VectorXd NonUniformBspline::evaluateDeBoor(const double& u) {
//限制参数 u 的范围: 将参数 u 限制在 B-样条曲线有效范围内,即 [u_(p_), u_(m_ - p_)]。
  double ub = min(max(u_(p_), u), u_(m_ - p_));  //体现出是open B样条
 
  // determine which [ui,ui+1] lay in
  //找到输入的u是第几个节点处
  int k = p_;
  while (true) {
    if (u_(k + 1) >= ub) break; //因为下限是u_(p_)所以从k开始,又因为u是非递减的所以每次检查k+1即可
    ++k;
  }
 
//通过k找到与当前节点相关的控制点k-p_到k
  /* deBoor's alg */
  vector<Eigen::VectorXd> d;
  for (int i = 0; i <= p_; ++i) {
    d.push_back(control_points_.row(k - p_ + i));
    // cout << d[i].transpose() << endl;
  }
 
//De Boor递归计算控制点,计算过程中使用了混合参数 alpha,该参数用于混合现有控制点以生成新的控制点。
//数学推导https://en.wikipedia.org/wiki/De_Boor%27s_algorithm
  for (int r = 1; r <= p_; ++r) {//外循环次数
    for (int i = p_; i >= r; --i) {//内循环控制节点,次数高一次,控制节点少一个(自己写以下就能理解)
      double alpha = (ub - u_[i + k - p_]) / (u_[i + 1 + k - r] - u_[i + k - p_]);
      // cout << "alpha: " << alpha << endl;
      d[i] = (1 - alpha) * d[i - 1] + alpha * d[i];  //   累加在这里实现
    }
  }
  //返回计算得到的 B-样条曲线在参数 u 处的点
  return d[p_];
}

下面是写代码时候遇见的问题:

  1. 数组u的含义是什么? 不同取值的影响?
    u就是自变量,求完B样条后得到的是含u的分段函数,我们要画出这个拟合的曲线就要在定义域内带入函数,画出来
    U的范围即定义域范围,应在节点向量最大和最小内(否则就会有0,0点出现)
    U取的过于稀疏发现拟合的线多折线不平滑;U过于密集发现拟合曲线就经过了几个控制点,大部分控制点没拟合
    GPT给我答案:应该是太小时有些基函数十分接近于0,计算机直接近似0处理了。
    在这里插入图片描述
    if flag == 1:  # 均匀B样条很简单
        NodeVector = np.array([np.linspace(0, 1, n + k + 1)])  # 均匀B样条节点向量,首末值定义为 01
        #节点向量 前K个和后K个重复  否则会生成(00)的点
        NodeVector[0, :k] = 0  # 重复开头的节点
        NodeVector[0, n+1:n+k+1] = 1 # 重复结尾的节点
        print(NodeVector)
        u_min = NodeVector[0, k]  # 最小的有效 u 值
        u_max = NodeVector[0, n]  # 最大的有效 u 值
        print(u_min, u_max)
        # 设置合适的 u 取值范围和步长
        u_values = np.linspace(u_min, u_max, num=200)  # 200 可以调整,覆盖整个 u 的范围
        
        for u in u_values:
            print(u)
            for i in range(n+1):
                Bik_u[i, 0] = BaseFunction(i, k, u, NodeVector)
            p_u = P.T @ Bik_u
            path.append(p_u)

2.网上代码u范围for u in np.arange((k-1) / (n + k + 1), (n + 2) / (n + k + 1),0.005): 表示从k-1个开始,取到n+1,因为范围【0,1】所以除了 (n + k + 1),但实际使用发现 生成曲线首尾要短不是标准开曲线,于是改成上面u_min和max形式,发现尾处短了一截,还是不知道为啥。。。希望大佬解答吧

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

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

相关文章

Einsum(Einstein summation convention)

Einsum&#xff08;Einstein summation convention&#xff09; 笔记来源&#xff1a; Permute和Reshape嫌麻烦&#xff1f;einsum来帮忙&#xff01; The Einstein summation convention is a notational shorthand used in tensor calculus, particularly in the fields of …

免费也能高质量!2024年免费录屏软件深度对比评测

我公司因为客户覆盖面广的原因经常会开远程会议&#xff0c;有时候说的内容比较广需要引用多份的数据&#xff0c;我记录起来有一定难度&#xff0c;所以一般都用录屏工具来记录会议内容。这次我们来一起探索有什么免费录屏工具可以提高我们的工作效率吧。 1.福晰录屏大师 链…

9.7(QT.Day 1)

一、自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面 要求&#xff1a;每行代码都有注释 【需要用到的图片或者动图&#xff0c;自己去网上找】 1.mywidget.h代码 #ifndef MYWIDGET_H #define MYWIDGET_H#include <QWidget> #include <QIcon> //图…

C++之格式化日期时间为字符串(精确到毫秒)

C11中提供了获取时间的chrono库&#xff0c;但是格式化显示太方便&#xff1b;C11还提供了格式化时间iomanip库&#xff0c;通过其put_time方法可以格式化时间到秒&#xff0c;要显示毫秒&#xff0c;就需要自己处理了。 #include <chrono> #include <string> #in…

css flex与inline-flex的区别

1、flex与inline-flex布局&#xff0c;都是弹性布局&#xff0c;盒状容器布局。 Flex 布局是什么&#xff1f;_w3cschool 2、下面一个实例来说明一下&#xff1a; 有一个要求&#xff0c;要求item增多的时候&#xff0c;不会换行&#xff0c;并且container容器也会随时item的…

【机器学习】我小学二年级妹妹都能理解的线性回归算法

什么是线性回归&#xff1f; 我小学二年级的妹妹想用压岁钱买房子&#xff0c;售楼广告上写着100万可以买100的房子&#xff0c;200万可以买200的房子&#xff0c;但是我的妹妹觉得那些房子都太小了&#xff0c;想买300的房子&#xff0c;那她应该要花多少钱呢&#xff1f; 对…

DBMS-2.2 数据库设计(2)——数据库规范化设计理论

本文章的素材与知识来自李国良老师和冠宇老师。 依赖理论 对于关系数据库中的依赖&#xff0c;分为函数依赖、多值依赖和连接依赖。 一.函数依赖 1.函数依赖 &#xff08;1&#xff09;定义&#xff1a; &#xff08;2&#xff09;理解&#xff1a; 通俗地讲&#xff0c;…

【Linux】借命令行参数的引导,探索环境变量的奥秘

目录 1.命令行参数 1.1.概念&#xff1a; 1.2.利用命令行参数打造计算器&#xff1a; 2.环境变量 2.1.环境变量是什么&#xff1f; 2.2.有什么方法可以不用带路径&#xff0c;直接就可以运行自己的程序呢&#xff1f; 法一&#xff1a; 法二&#xff1a; 2.3.通过代码…

PostgreSQL技术内幕9:PostgreSQL事务原理解析

文章目录 0.简介1.PG事务整体介绍1.1 事务类型介绍 1.2 事务模块介绍2. 代码分析 0.简介 有了上一篇数据库事务并发控制协议的介绍&#xff0c;对于数据库事务和并发控制有了基本的认识&#xff0c;本文将介绍PG事务模块&#xff0c;主要介绍PG支持的事务类型&#xff08;普通…

git为不同的项目设置不同的提交作者

方法1&#xff1a;找到项目的.git文件夹打开 打开config在下面添加自己作者信息 [user]name 作者名email 邮箱方法2&#xff1a;直接在.git文件夹设置作者名&#xff08;不使用–global参数&#xff09; git config user.name "xxxxx"如果想要修改之前提交的…

银行结算业务

1.1 银行本票 银行本票是由银行签发的,承诺自己在见票时无条件支付票款给收款人或持票人的业务。银行本票按票面划分为定额本票和不定额本票,按币种划分为人民币银行本票和外币银行本票。人民币银行本票仅在同一交换区域内使用,资金清算利用当地人民银行组织的资金清算形式…

vllm源码解析(五):LLM模型推理

八 模型推理细节探索 8.1 回顾下step的流程 def step(self) -> List[Union[RequestOutput, EmbeddingRequestOutput]]:# 多GPU并行推理时走AsyncLLMEngine分支。如果进入当前LLMEngine,性能会下降&#xff0c;这里会抛出异常。if self.parallel_config.pipeline_parallel_s…

基于机器学习的电商优惠券核销预测

1. 项目简介 随着移动互联网的快速发展&#xff0c;O2O&#xff08;Online to Offline&#xff09;模式已成为电商领域的一大亮点。优惠券作为一种有效的营销工具&#xff0c;被广泛应用于吸引新客户和激活老用户。然而&#xff0c;传统的随机投放方式往往效率低下&#xff0c;…

JavaWeb【day11】--(SpringBootWeb案例)

SpringBootWeb案例 前面我们已经实现了员工信息的条件分页查询以及删除操作。 关于员工管理的功能&#xff0c;还有两个需要实现&#xff1a; 新增员工 修改员工 首先我们先完成"新增员工"的功能开发&#xff0c;再完成"修改员工"的功能开发。而在&quo…

万能视频下载器-下载所有网站上的任何视频

万能视频下载器-下载所有网站上的任何视频 在Edge浏览器中发现了一款令人惊叹的视频下载扩展插件&#xff0c;简直就是视觉盛宴的利器&#xff01;只需轻点几下&#xff0c;在拓展商店中轻松查找并安装&#xff0c;你便能随时随地随心所欲地把心仪的视频收入囊中。无论是教学资…

matlab仿真 OFDM系统仿真

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第九章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; clear all N8;%子载波数 f1:N;%各个子载波频率 xrandi([0 3],1,N);%子载波上的数据 x1qammod(x,4);%4-QAM调制 t0:0.001:1-0.…

学习周报-2024.9.3

目录 摘要 Abstract 文献阅读&#xff1a;一种改善河流水质预测的耦合模型以解决非平稳性和数据限制 一、现有问题 二、提出方法 三、相关知识 1、基于小波分析的LSTM&#xff08;WA-LSTM&#xff09; 2、迁移学习TL改进WA-LSTM 四、WA-LSTM-TL模型 五、研究实验 1、…

手写NACOS的服务的注册与发现|心跳机制|轮询调用服务功能

背景 手写NACOS的服务的部分核心功能&#xff0c;提高自身的编码能力 本篇文章设计的是单体NACOS后端服务&#xff0c;提供SDK给多个NACOS客户端使用 本文编写了注册与发现|心跳机制|轮询调用服务功能&#xff0c;可当做入门级阅读 nacos-service 项目结构 代码内容 pom配置…

Detect It Easy

Detect It Easy&#xff08;简称 DIE&#xff09;项目的网址为 https://github.com/horsicq/Detect-It-Easy 下载完安装包后&#xff0c;直接双击die.exe即可进入到操作界面 工具介绍&#xff1a; 它可以用来检测程序架构和文件类型。如图所示。其中&#xff0c;「模式」说明程…

UE5 贝塞尔曲线导弹

首先创建导弹Actor蓝图 代码逻辑&#xff0c;这其中创建的所有变量都不用添加值&#xff0c;这些逻辑要画图来解释&#xff0c;比较麻烦&#xff0c;大家自行理解一下 接下来进入人物蓝图编写代码逻辑&#xff0c;我这里是在两个不同的位置发射两枚导弹 宏中的代码&#xff0c;…