轨迹规划 | 图解纯追踪算法Pure Pursuit(附ROS C++/Python/Matlab仿真)

目录

  • 0 专栏介绍
  • 1 纯追踪算法原理推导
  • 2 自适应纯追踪算法(APP)
  • 3 规范化纯追踪算法(RPP)
  • 4 仿真实现
    • 4.1 ROS C++仿真
    • 4.2 Python仿真
    • 4.3 Matlab仿真

0 专栏介绍

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

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


1 纯追踪算法原理推导

纯追踪算法(Pure Pursuit, PP)参考了人类驾驶行为,其基本思想是:在待跟踪路径上设置预瞄点(goal-ahead),通过简单的几何方法驱动机器人跟踪预瞄点,随着机器人运动,预瞄点动态移动直至抵达目标位置。

给定路径点 P = { p 0 , p 1 , ⋯ , p g } \mathcal{P} =\left\{ \boldsymbol{p}_0,\boldsymbol{p}_1,\cdots ,\boldsymbol{p}_g \right\} P={p0,p1,,pg}。根据纯追踪算法设置的固定预瞄距离 L L L选择预瞄点

p l = p i ∈ P s . t . ∥ p i − 1 − p r ∥ 2 2 < L a n d ∥ p i − p r ∥ 2 2 ⩾ L \boldsymbol{p}_l=\boldsymbol{p}_i\in \mathcal{P} \,\,\mathrm{s}.\mathrm{t}. \left\| \boldsymbol{p}_{i-1}-\boldsymbol{p}_r \right\| _{2}^{2}<L\,\,\mathrm{and} \left\| \boldsymbol{p}_i-\boldsymbol{p}_r \right\| _{2}^{2}\geqslant L pl=piPs.t.pi1pr22<Landpipr22L

其中 p r \boldsymbol{p}_r pr是最接近机器人当前位置的路径点。

当规划时间间隔 Δ t → 0 \varDelta t\rightarrow 0 Δt0时,可认为机器人线速度 v v v和角速度 ω \omega ω不变,因此其转向半径 R = v / ω R={{v}/{\omega}} R=v/ω是定值,即机器人进行圆周运动。

在这里插入图片描述

如图所示,根据几何关系可得

L sin ⁡ 2 α = R sin ⁡ ( π / 2 − α ) ⇒ R = L 2 sin ⁡ α \frac{L}{\sin 2\alpha}=\frac{R}{\sin \left( {{\pi}/{2}}-\alpha \right)}\Rightarrow R=\frac{L}{2\sin \alpha} sin2αL=sin(π/2α)RR=2sinαL

确定曲率半径后,对于差速轮式移动机器人而言,可根据下式计算当前的控制指令

{ v t = v d ω t = v t / R \begin{cases} v_t=v_d\\ \omega _t={{v_t}/{R}}\\\end{cases} {vt=vdωt=vt/R

在机器人局部坐标系中,设机器人与预瞄点的纵向误差为 e y e_y ey,则

R = L 2 2 e y ⇔ κ = 2 L 2 ⋅ e y R=\frac{L^2}{2e_y}\Leftrightarrow \kappa =\frac{2}{L^2}\cdot e_y R=2eyL2κ=L22ey

相当于一个以横向跟踪误差为系统误差的比例控制器,如图所示。增大 L L L有利于降低超调,但会产生稳态误差;减小 L L L能够加快动态响应速度,但容易引起振荡。

在这里插入图片描述

2 自适应纯追踪算法(APP)

为了在跟踪振荡和较慢收敛间取得可接受的权衡,自适应纯追踪算法(Adaptive Pure Pursuit, APP)根据运动速度自适应调整预瞄距离

L t = l t v t + L 0 L_t=l_tv_t+L_0 Lt=ltvt+L0

其中 l t l_t lt是前瞻增益,表示将 v t v_t vt向前投影的时间增量; L 0 L_0 L0是最小预瞄距离。

3 规范化纯追踪算法(RPP)

考虑到机器人始终以期望速度 运动并不合理,尤其是在狭窄区域、急转弯等不完全可见工作空间,动态调整机器人速度有利于提供更高质量的行为表现。规范化纯追踪算法(Regulated Pure Pursuit, RPP)引入了修正启发式等进行自适应调整。举例而言,曲率启发式,目的是放慢机器人在部分可观察环境的速度,以提高盲转弯时的安全性。其中最大曲率阈值 提供了急转弯位置的速度缩放。

v t ′ = { v t , κ ⩽ κ max ⁡ κ max ⁡ κ v t , κ > κ max ⁡ v_{t}^{'}=\begin{cases} v_t\,\, , \kappa \leqslant \kappa _{\max}\\ \frac{\kappa _{\max}}{\kappa}v_t\,\, , \kappa >\kappa _{\max}\\\end{cases} vt={vt,κκmaxκκmaxvt,κ>κmax

可以根据应用需求设计更多启发式

4 仿真实现

4.1 ROS C++仿真

核心代码如下所示

bool RPPPlanner::computeVelocityCommands(geometry_msgs::Twist& cmd_vel)
{...double vt = std::hypot(base_odom.twist.twist.linear.x, base_odom.twist.twist.linear.y);double L = getLookAheadDistance(vt);getLookAheadPoint(L, robot_pose_map, prune_plan, lookahead_pt, theta, kappa);double lookahead_k = 2 * sin(_dphi(lookahead_pt, robot_pose_map)) / L;// calculate commandsif (shouldRotateToGoal(robot_pose_map, global_plan_.back())){...}else{double e_theta = regularizeAngle(_dphi(lookahead_pt, robot_pose_map));// large angle, turn firstif (shouldRotateToPath(std::fabs(e_theta), M_PI_2)){cmd_vel.linear.x = 0.0;cmd_vel.angular.z = angularRegularization(base_odom, e_theta / d_t_);}// apply constraintselse{double curv_vel = _applyCurvatureConstraint(max_v_, lookahead_k);double cost_vel = _applyObstacleConstraint(max_v_);double v_d = std::min(curv_vel, cost_vel);v_d = _applyApproachConstraint(v_d, robot_pose_map, prune_plan);cmd_vel.linear.x = linearRegularization(base_odom, v_d);cmd_vel.angular.z = angularRegularization(base_odom, v_d * lookahead_k);}}return true;
}

在这里插入图片描述

4.2 Python仿真

核心代码如下所示

def plan(self):lookahead_pts = []dt = self.params["TIME_STEP"]for _ in range(self.params["MAX_ITERATION"]):# break until goal reachedif self.shouldRotateToGoal(self.robot.position, self.goal):return True, self.robot.history_pose, lookahead_pts# get the particular point on the path at the lookahead distancelookahead_pt, _, _ = self.getLookaheadPoint()# get the tracking curvature with goalahead pointlookahead_k = 2 * math.sin(self.angle(self.robot.position, lookahead_pt) - self.robot.theta) / self.lookahead_dist# calculate velocity commande_theta = self.regularizeAngle(self.robot.theta - self.goal[2]) / 10if self.shouldRotateToGoal(self.robot.position, self.goal):if not self.shouldRotateToPath(abs(e_theta)):u = np.array([[0], [0]])else:u = np.array([[0], [self.angularRegularization(e_theta / dt)]])else:e_theta = self.regularizeAngle(self.angle(self.robot.position, lookahead_pt) - self.robot.theta) / 10if self.shouldRotateToPath(abs(e_theta), np.pi / 4):u = np.array([[0], [self.angularRegularization(e_theta / dt)]])else:# apply constraintscurv_vel = self.applyCurvatureConstraint(self.params["MAX_V"], lookahead_k)cost_vel = self.applyObstacleConstraint(self.params["MAX_V"])v_d = min(curv_vel, cost_vel)u = np.array([[self.linearRegularization(v_d)], [self.angularRegularization(v_d * lookahead_k)]])# update lookahead pointslookahead_pts.append(lookahead_pt)# feed into robotic kinematicself.robot.kinematic(u, dt)return False, None, None

在这里插入图片描述

4.3 Matlab仿真

核心代码如下所示

while iter < param.max_iterationiter = iter + 1;% break until goal reachedif shouldRotateToGoal([robot.x, robot.y], goal, param)flag = true;break;end% get the particular point on the path at the lookahead distance[lookahead_pt, ~, ~] = getLookaheadPoint(robot, path, param);% get the tracking curvature with goalahead pointlookahead_k = 2 * sin( ...atan2(lookahead_pt(2) - robot.y, lookahead_pt(1) - robot.x) - robot.theta ...) / getLookaheadDistance(robot, param);% calculate velocity commande_theta = regularizeAngle(robot.theta - goal(3)) / 10;if shouldRotateToGoal([robot.x, robot.y], goal, param)if ~shouldRotateToPath(abs(e_theta), 0.0, param)u = [0, 0];elseu = [0, angularRegularization(robot, e_theta / param.dt, param)];endelsee_theta = regularizeAngle( ...atan2(lookahead_pt(2) - robot.y, lookahead_pt(1) - robot.x) - robot.theta ...) / 10;if shouldRotateToPath(abs(e_theta), pi / 4, param)u = [0, angularRegularization(robot, e_theta / param.dt, param)];else% apply constraintscurv_vel = applyCurvatureConstraint(param.max_v, lookahead_k, param);cost_vel = applyObstacleConstraint(param.max_v, map, robot, param);v_d = min(curv_vel, cost_vel);u = [linearRegularization(robot, v_d, param), ...angularRegularization(robot, v_d * lookahead_k, param) ...];endend% input into robotic kinematicrobot = f(robot, u, param.dt);pose = [pose; robot.x, robot.y, robot.theta];
end

在这里插入图片描述

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


🔥 更多精彩专栏

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

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

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

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

相关文章

快速配置 Nginx 来实现 GPT 流式传输

目录 1. Nginx 参考配置2. Nginx 核心参数3. 其他参数 场景&#xff1a;代理 ChatGPT、代理各种 GPT 工具套壳等。 1. Nginx 参考配置 支持 GPT 流式访问的配置如下&#xff0c;请根据实际需求适当取舍即可&#xff1a; server {listen 80;server_name chat.test.com; # 绑…

如何推动物联网的未来?——青创智通

工业物联网解决方案-工业IOT-青创智通 物联网作为连接物理世界和数字世界的桥梁&#xff0c;正逐渐改变着我们的生活和工作方式。在工业领域&#xff0c;物联网技术的应用不仅提高了生产效率&#xff0c;还实现了对设备的智能化管理和维护。而工业网关作为物联网的重要组成部分…

java数据保留几位小数的问题

String.format()&#xff1a; 这个方法在格式化输出时非常常用&#xff0c;可以方便地控制小数位数&#xff0c;并且语法简洁易懂。它不仅可以用于格式化浮点数和双精度数&#xff0c;还可以用于格式化其他数据类型&#xff0c;如整数、字符串等。 示例代码&#xff1a; BigD…

仪器校准中,CNAS对报告的认可评审要求有哪些?

CNAS扩项时&#xff0c;常常会有关于对报告认可的相关要求&#xff0c;而这些要求往往有明确规范&#xff0c;那么在仪器校准中&#xff0c;CNAS对报告的认可评审要求有哪些&#xff1f; 现场评审时&#xff0c;评审组应关注抽查报告&#xff0c;评审组将现场随机抽取报告&…

酷开科技让你能够放心地把遥控器交给孩子

我国电视从诞生至今已有65个年头&#xff0c;从黑白到彩色&#xff0c;从背投到液晶&#xff0c;电视的外观随着时代技术的发展而不断变化&#xff0c;直到现在随着技术的不断迭代&#xff0c;电视的功能越来越丰富&#xff0c;电视在客厅中的地位也越来越凸显。作为家庭娱乐的…

【Linux基础】Vim保姆级一键配置教程(手把手教你把Vim打造成高效率C++开发环境)

目录 一、前言 二、安装Vim 三、原始Vim编译器的缺陷分析 四、Vim配置 &#x1f95d;预备知识----.vimrc 隐藏文件 &#x1f34b;手动配置 Vim --- &#xff08;不推荐&#xff09; &#x1f347;自动化一键配置 Vim --- (强烈推荐) ✨功能演示 五、共勉 一、前言 Vim作为…

实现字符串比较函数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int i, result;char s1[100], s2[100];//填充数组&#xff1b;printf("请输入数组s1的…

2.分布式-算法

目录 一、限流算法有哪些&#xff1f; 1.计数器算法&#xff08;Counter-Based Algorithm&#xff09; 2.固定窗口算法&#xff08;Fixed Window&#xff09; 3.滑动窗口算法&#xff08;Sliding Window&#xff09; 4.令牌桶算法&#xff08;Token Bucket&#xff09; 5.…

生产设备数据管控要怎么做 可以实现精益生产和智能制造?

生产设备在制造过程中会产生多种类型的数据&#xff0c;这些数据对于优化生产流程、提高效率、降低成本和预防性维护等方面至关重要。需要对这些数据进行有效的采集和管理&#xff0c;以实现对生产设备数据管控。 一、生产设备数据类型包括&#xff1a; 设备运行状态数据&…

C++八股(面试题、手撕题)自用版

目录 面试题&#xff1a; 1. define inline 在编译的哪个阶段 2. const static 3. 子函数返回结构体有什么问题&#xff0c;返回对象调用了哪些函数 4. volatile关键字 5. 编译器基本原理 6. 预处理、编译、汇编、链接以及他们在操作系统上如何运作的 7. 数组和指针&a…

第十一届蓝桥杯大赛软件类决赛 Java 研究生组

文章目录 发现宝藏【考生须知】试题 A: 合数个数试题 B: 含 2 天数试题 C 阶乘约数试题 D: 本质上升序列试题 E: 迨尺天涯试题 F 循环小数试题 G: 蓝肽子序列试题 H 出租车试题 I: 答疑试题 J: 蓝跳跳 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&a…

【高阶数据结构(三)】图的遍历最小生成树问题

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:高阶数据结构专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Go语言知识   &#x1f51d;&#x1f51d; 高阶数据结构 1. 前言2. 图的遍…

成功案例(IF=7.4)| 脂代谢组学和蛋白质组学分析揭示多囊卵巢综合征的发病机制

研究背景 多囊卵巢综合征&#xff08;PCOS&#xff09;是女性最常见的内分泌和代谢紊乱&#xff0c;也是无排卵性不孕症和高雄激素血症的主要原因。患者的主要临床表现为月经少、不孕、高雄激素血症、肥胖、多毛、痤疮、胰岛素抵抗&#xff08;IR&#xff09;和B超下多囊卵巢改…

Electron学习笔记(六)

文章目录 相关笔记笔记说明 七、系统5、托盘图标(1)、设置托盘图标(2)、托盘图标闪烁(3)、托盘图标菜单 6、剪切板(1)、写入剪切板(2)、读取剪切板 7、系统通知8、其他(1)、使用系统默认应用打开文件(2)、接收拖拽到窗口中的文件(3)、使用系统字体 相关笔记 Electron学习笔记&…

具身智能论文(二)

目录 1. Code as Policies: Language Model Programs for Embodied Control2. Embodied Agents for Efficient Exploration and Smart Scene Description3. Embodied Agents for Efficient Exploration and Smart Scene Description4. Learning to explore informative traject…

Stateflow基础知识笔记

01--Simulink/Stateflow概述 Stateflow是集成于Simulink中的图形化设计与开发工具&#xff0c;主要 用于针对控制系统中的复杂控制逻辑进行建模与仿真&#xff0c;或者说&#xff0c; Stateflow适用于针对事件响应系统进行建模与仿真。 Stateflow必须与Simulink联合使用&#…

第七届世界通信工程研讨会(WSCE 2024)即将召开!

第七届世界通信工程研讨会&#xff08;WSCE 2024&#xff09;将于2024年9月27-29日在日本东京举行。WSCE 的成立旨在应对通信工程领域所面临的挑战和机遇&#xff0c;尽管该领域已趋于饱和&#xff0c;但其仍保持着强劲的发展势头。本次研讨会旨在加速通信创新并加强该领域专家…

编程技巧:什么是JavaScript递归

什么是递归 程序调用自身的编程技巧称为递归&#xff08;recursion&#xff09; 递归的基本思想是将一个复杂的问题分解成更小、更易于管理的子问题&#xff0c;这些子问题与原始问题相似&#xff0c;但规模更小。 递归的要素 基本情况&#xff08;Base Case&#xff09;&…

Python 编程语言中的 None 到底是什么?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 让我们一起深入了解 Python 中的 None。 什么是 None&#xff1f; 在 Python 编程语言中&#xff0c;None 是一个特殊的常量&#xff0c;它代表了 “无” 或 “没有值”。你可以把它想象成一个空盒子…

Debian常用命令:高效管理与运维的必备指南

在Linux世界中&#xff0c;Debian以其稳定性、安全性和开源精神赢得了广大用户的青睐。作为一个基于Linux的操作系统&#xff0c;Debian拥有丰富且强大的命令行工具&#xff0c;这些命令对于系统管理员和开发者来说至关重要。本文将为您介绍一系列Debian系统中的常用命令&#…