当前位置: 首页 > article >正文

ROS导航使用贝塞尔曲线对全局路径进行平滑处理

文章目录

  • 前言
  • 一、贝塞尔曲线的使用
  • 二、全局路经修改
  • 三、结果对比


前言

ROS原生的全局路径规划GlobalPlanner包含A*和Dijkstra,两者原理基本相同,能够规划出从起点到终点的路径,但是由于栅格地图存在锯齿形,得到的全局路径也会出现“折弯”,不够平滑的现象,虽然不影响导航的使用,但对于路径跟踪来讲,会存在运动不够平滑的情况,因此本文将会使用贝塞尔曲线对globalplanner规划的路径进行处理后给到局部路径,供导航使用。


一、贝塞尔曲线的使用

网上关于对贝塞尔曲线的介绍有很多,这里仅仅做一个简单的介绍。
贝塞尔曲线原理
贝塞尔曲线常用于绘制曲线,具有以下特征:

  1. 使用n个控制点{p1,p2,…,pn}来控制曲线的形状;
  2. 曲线通过起点平p1和终点pn,接近但不通过中间点

一阶贝塞尔曲线:给定点P0,P1,此时贝塞尔曲线只是两点之间的一条直线,描述为:
B ( t ) = P 0 + ( P 1 − P 0 ) t = ( 1 − t ) P 0 + t P 1 , t ∈ [ 0 , 1 ] B(t) = P0 + (P1-P0)t = (1-t)P0 + tP1, t ∈ [0,1] B(t)=P0+(P1P0)t=(1t)P0+tP1,t[0,1]
二阶贝塞尔曲线:给定点P0,P1,P2,贝塞尔曲线描述为:
B ( t ) = ( 1 − t ) 2 P 0 + 2 t ( 1 − t ) P 1 + t 2 P 2 , t ∈ [ 0 , 1 ] B(t) = (1-t)^2P0 + 2t(1-t)P1 + t^2P2, t ∈ [0,1] B(t)=(1t)2P0+2t(1t)P1+t2P2,t[0,1]

二、全局路经修改

ROS运动规划学习五介绍过全局路径的生成过程,是由planer_core文件中makePlan函数实现,因此在可以在makePlan函数中进行路径平滑。
步骤如下:

  1. 声明定义二阶和三阶贝塞尔曲线函数。
//二阶贝塞尔曲线
float GlobalPlanner::bezier2func(float uu,float* controlPoint){  
   float part0 = controlPoint[0] * (1-uu) * (1-uu);  
   float part1 = 2 * controlPoint[1] * uu * (1-uu);  
   float part2 = controlPoint[2] * uu * uu ;     
   return part0 + part1 + part2 ;   
}
//三阶贝塞尔曲线
float GlobalPlanner::bezier3func(float uu,float* controlPoint){  
   float part0 = controlPoint[0] * (1-uu) * (1-uu) * (1-uu);  
   float part1 = 3 * controlPoint[1] * uu * (1-uu) * (1 - uu);  
   float part2 = 3 * controlPoint[2] * uu * uu * (1 - uu);  
   float part3 = controlPoint[3] * uu * uu * uu;     
   return part0 + part1 + part2 + part3;   
}  

  1. 全局路径处理,获取要平滑的路径点。由于全局路径上的点太过密集,为减少计算量,这里每隔distance个点取一个点作为放入要平滑的路径,同时将路径终点也放入。
void GlobalPlanner::deal_path(const nav_msgs::Path& input,nav_msgs::Path& output,int distance){
    output.header.stamp = ros::Time::now();
    output.header.frame_id = "map";
    output.poses.clear();
    geometry_msgs::PoseStamped pathVehicle;
    int length = input.poses.size();
    for (int i = 0; i < (length / distance); i++) {
        pathVehicle.header.frame_id = "map";
        pathVehicle.header.stamp = ros::Time::now();
        pathVehicle.pose.position.x = input.poses[i*distance].pose.position.x;
        pathVehicle.pose.position.y = input.poses[i*distance].pose.position.y;
        pathVehicle.pose.position.z = 0;
        pathVehicle.pose.orientation.x = input.poses[i*distance].pose.orientation.x;
        pathVehicle.pose.orientation.y = input.poses[i*distance].pose.orientation.y;
        pathVehicle.pose.orientation.z = input.poses[i*distance].pose.orientation.z;
        pathVehicle.pose.orientation.w = input.poses[i*distance].pose.orientation.w;
        output.poses.push_back(pathVehicle);
    }
    pathVehicle.header.frame_id = "map";
    pathVehicle.header.stamp = ros::Time::now();
    pathVehicle.pose.position.x = input.poses[length-1].pose.position.x;
    pathVehicle.pose.position.y = input.poses[length-1].pose.position.y;
    pathVehicle.pose.position.z = 0;
    pathVehicle.pose.orientation.x = input.poses[length-1].pose.orientation.x;
    pathVehicle.pose.orientation.y = input.poses[length-1].pose.orientation.y;
    pathVehicle.pose.orientation.z = input.poses[length-1].pose.orientation.z;
    pathVehicle.pose.orientation.w = input.poses[length-1].pose.orientation.w;
    output.poses.push_back(pathVehicle);
}
  1. 使用贝塞尔曲线函数对2中得到的路径进行平滑,并创建新的全局路径。
void GlobalPlanner::createCurve(const nav_msgs::Path& originPoint,nav_msgs::Path& output){

}

三、结果对比

图中蓝色曲线为原始路径,红色曲线为平滑后的路径,能够看出,相比于原始路径存在折弯的部分,贝塞尔曲线处理后的路径更加平滑。
在这里插入图片描述



http://www.kler.cn/a/466617.html

相关文章:

  • 前端(API)学习笔记(CLASS 4):进阶
  • 智能客户服务:科技如何重塑客户服务体验
  • NVIDIA DLI课程《NVIDIA NIM入门》——学习笔记
  • Android12 App窗口创建流程
  • 为什么HTTP请求后面有时带一个sign参数(HTTP请求签名校验)
  • 【Vim Masterclass 笔记08】第 6 章:Vim 中的文本变换及替换操作 + S06L20:文本的插入、变更、替换,以及合并操作
  • 一份完整的软件测试报告如何编写?
  • 拆解 Web3:探寻去中心化网络的核心密码
  • RK3588+麒麟国产系统+FPGA+AI在电力和轨道交通视觉与采集系统的应用
  • mysql连接时报错1130-Host ‘hostname‘ is not allowed to connect to this MySQL server
  • 积木(01)
  • @Transactional注解 细节!
  • 检索增强生成(RAG):大语言模型的创新应用
  • LeetCode 141:环形链表
  • C++面向对象编程:纯虚函数、抽象类、虚析构、纯虚析构
  • 【项目】多模态图文理解-GLM-Edge实战
  • Scala_【5】函数式编程
  • 以太网连接,本地连接,宽带连接,无线WLAN连接;交换机和路由器
  • 【MyBatis-Plus 条件构造器】全面解析 Wrapper
  • 【赵渝强老师】MongoDB文档级别的并发控制
  • vue 虚拟滚动 vue-virtual-scroller RecycleScroller
  • logback日志文件多环境配置路径
  • Linux下读取Windows下保存的文件,报错信息中出现“^M“时如何解决?【由于Windows和Linux的换行方式不同造成的-提供两种转换方式】
  • React18路由和Vue3路由进行对比
  • [2024] 如何以 5 种可行的方式在Android中打开 HEIC 文件?
  • aardio —— 虚表 —— 模拟属性框