【路径跟踪控制:Bang-Bang 控制与车辆运动学模型】

news2024/10/21 16:25:01

【路径跟踪控制:Bang-Bang 控制与车辆运动学模型】

    • 1. 引言
    • 2. 环境准备
    • 3. 车辆运动学模型
      • 3.1 理论基础
      • 3.2 Python 实现车辆运动学模型建模
    • 4. Bang-Bang 控制策略
      • 4.1 理论基础
        • 4.1.1 误差角度计算与转向角调整
        • 4.1.2 Bang-Bang控制实现
      • 4.2 完整代码
      • 4.3 控制策略解释
    • 5. 改进BangBang控制
      • 5.2 动态管理路径点
      • 5.3 优化速度控制策略
      • Python 实现
    • 6. 结论

1. 引言

自动驾驶系列博客梳理:

  1. 【【自动驾驶】车辆运动学模型】
  2. 【路径跟踪控制:Bang-Bang 控制与车辆运动学模型】

参考文献:
3. 【自动驾驶】总目录(持续更新)

随着自动驾驶技术的不断发展,无人车的轨迹跟踪控制成为了研究热点之一。本文将通过介绍无人车的运动学模型和Bang-Bang控制策略,探讨如何实现无人车的轨迹跟踪。我们将使用Python语言编写代码,通过模拟实验展示控制策略的效果。
先看优化后的Bang-Bang追踪sine函数路径跟踪效果啦!!超级OK💖💖💖
在这里插入图片描述

2. 环境准备

为了运行本文提供的代码,你需要安装以下Python库:

  • numpy: 用于数值计算。
  • matplotlib: 用于绘图和动画制作。
  • scipy: 提供科学计算工具,本文中用于KDTree查询。

可以通过以下命令安装这些库:

pip install numpy matplotlib scipy

3. 车辆运动学模型

3.1 理论基础

在自动驾驶中,车辆的运动学模型是用于预测车辆未来状态的重要工具。通常情况下,车辆模型被简化为 以后轴中心为车辆中心的单车运动学模型,该模型假设左右前轮合并为一个轮子,后轮同样合并为一个轮子。车辆的运动状态可以通过位置 x x x, y y y、航向角 ψ \psi ψ和速度 v v v 来描述。
在这里插入图片描述

对于前轮驱动的车辆,其运动学模型可以表示为:

{ x ˙ = v cos ⁡ ( ψ ) y ˙ = v sin ⁡ ( ψ ) ψ ˙ = v L tan ⁡ ( δ f ) \begin{cases} \dot{x} = v \cos(\psi) \\ \dot{y} = v \sin(\psi) \\ \dot{\psi} = \frac{v}{L} \tan(\delta_f) \end{cases} x˙=vcos(ψ)y˙=vsin(ψ)ψ˙=Lvtan(δf)
其中:

  • v v v 是车辆的速度;
  • l f l_f lf l r l_r lr 分别是前轴和后轴到车辆重心的距离。
  • L L L 是车辆的前后轴轴距。
  • δ f \delta_f δf 是前轮的转向角。

3.2 Python 实现车辆运动学模型建模

以下是车辆运动学模型的Python实现:

import numpy as np
import matplotlib.pyplot as plt
import math
from scipy.spatial import KDTree
from matplotlib.animation import FuncAnimation

# 车辆运动学模型类
class KinematicModel:
    def __init__(self, x, y, psi, v, L, dt):
        self.x = x
        self.y = y
        self.psi = psi
        self.v = v
        self.L = L
        self.dt = dt

    def update_state(self, v, delta_f):
        self.x += v * np.cos(self.psi) * self.dt
        self.y += v * np.sin(self.psi) * self.dt
        self.psi += (v / self.L) * np.tan(delta_f) * self.dt

    def get_state(self):
        return self.x, self.y, self.psi, self.v

4. Bang-Bang 控制策略

4.1 理论基础

Bang-Bang控制是一种简单的控制策略,它将控制变量限制在两个极端值之间切换。在无人车轨迹跟踪任务中,Bang-Bang控制器可以根据横向跟踪误差 e y e_y ey决定方向盘的角度 δ f \delta_f δf。具体来说,如果误差超过某个阈值 tolerance \text{tolerance} tolerance,则方向盘转向最大角度 max_delta  \text{max\_delta } max_delta ;否则,方向盘保持不动。

4.1.1 误差角度计算与转向角调整

在控制策略中,我们首先计算当前位置与目标位置之间的角度误差 theta_e  \text{theta\_e } theta_e 

theta_e = alpha - ugv.psi

接下来,我们根据角度误差的大小动态调整最大转向角 max_delta  \text{max\_delta } max_delta 

if abs(theta_e) > np.pi / 2.0:
    max_delta = np.pi / 12.0
else:
    max_delta = np.pi / 24.0

这里的逻辑是,当角度误差较大时(超过90度),我们允许更大的转向角以便更快地纠正误差;而当角度误差较小时,我们限制转向角以避免过度调整。

4.1.2 Bang-Bang控制实现

有了最大转向角 max_delta  \text{max\_delta } max_delta ,我们可以实现Bang-Bang控制:

delta_f = np.sign(error_y) * max_delta if abs(error_y) > tolerance else 0
ugv.update_state(2 + l_d/10, delta_f=delta_f)

这里的 error_y \text{error\_y} error_y 是当前位置与目标位置在y轴方向上的误差。我们根据误差的符号决定转向角的方向(左转或右转),并根据 max_delta  \text{max\_delta } max_delta  确定转向角的大小。如果误差在容差范围内,则不进行转向调整。

4.2 完整代码

结合上述分析,以下是完整的Python代码实现:

import numpy as np
import matplotlib.pyplot as plt
import math
from scipy.spatial import KDTree
from matplotlib.animation import FuncAnimation

# 车辆运动学模型类
class KinematicModel:
    def __init__(self, x, y, psi, v, L, dt):
        self.x = x
        self.y = y
        self.psi = psi
        self.v = v
        self.L = L
        self.dt = dt

    def update_state(self, v, delta_f):
        self.x += v * np.cos(self.psi) * self.dt
        self.y += v * np.sin(self.psi) * self.dt
        self.psi += (v / self.L) * np.tan(delta_f) * self.dt
        # self.v += a * self.dt

    def get_state(self):
        return self.x, self.y, self.psi, self.v


def main(interactive=True):
    # 设置参考路径
    refer_path = np.zeros((1000, 2))
    refer_path[:, 0] = np.linspace(0, 100, 1000)
    refer_path[:, 1] = np.zeros(1000)  # 直线轨迹
    # refer_path[:, 1] = np.sin(refer_path[:, 0] / 10) * 2   # sine 轨迹

    refer_tree = KDTree(refer_path)

    # 初始化车辆状态
    ugv = KinematicModel(0, 2, 0, 2, 2, 0.1)
    trajectory_x, trajectory_y = [], []

    # 创建绘图窗口
    fig, ax = plt.subplots()
    ax.plot(refer_path[:, 0], refer_path[:, 1], '-.b', linewidth=1.0, label="Reference Path")
    line, = ax.plot([], [], '-r', label="UGV Trajectory")
    target_dot, = ax.plot([], [], 'go', label="Target")
    ax.set_title("Bang-Bang Trajectory Control")
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.set_xlim(-1, 110)
    ax.set_ylim(-3, 3)
    ax.grid(True)
    ax.legend()

    # Bang-Bang 控制器参数
    tolerance = 0.01
    max_delta = np.pi / 12.0

    def init():
        line.set_data([], [])
        target_dot.set_data([], [])
        return line, target_dot

    def update(frame):
        robot_state = np.array([ugv.x, ugv.y])
        distance, ind = refer_tree.query(robot_state)

        # 控制器逻辑
        dx, dy = refer_path[ind] - robot_state
        alpha = math.atan2(dy, dx)
        l_d = np.linalg.norm(refer_path[ind] - robot_state)
        theta_e = alpha - ugv.psi
        error_y = l_d * math.sin(theta_e)
        if abs(theta_e) > np.pi / 2.0:
            max_delta = np.pi / 12.0
        else:
            max_delta = np.pi / 24.0

        # Bang-Bang 控制
        delta_f = np.sign(error_y) * max_delta if abs(error_y) > tolerance else 0
        ugv.update_state(2 + l_d/10 , delta_f=delta_f)

        # 更新轨迹
        trajectory_x.append(ugv.x)
        trajectory_y.append(ugv.y)
        line.set_data(trajectory_x, trajectory_y)

        # 更新目标点 (确保传入的是列表或数组)
        target_dot.set_data([refer_path[ind, 0]], [refer_path[ind, 1]])
        return line, target_dot

    # 创建动画
    anim = FuncAnimation(fig, update, frames=500, init_func=init, blit=True, interval=50, repeat=False)

    if interactive:
        plt.show()
    else:
        anim.save('Control/Controllers_python/Bang_Bang/ugv_animation.gif', writer='pillow', fps=20)
        print("GIF 已保存")

# 运行主程序
if __name__ == '__main__':
    interactive_mode = True  # 设置为 True 以在交互式模式下运行,False 以保存 GIF
    if not interactive_mode:
        import matplotlib
        matplotlib.use('Agg')

    main(interactive=interactive_mode)

4.3 控制策略解释

  1. 初始化

    • 设置参考路径为一条直线。
    • 初始化车辆状态,包括位置、航向角和速度。
    • 创建绘图窗口,绘制参考路径。
  2. 控制器逻辑

    • 使用KDTree查询当前车辆位置到最近路径点的距离和索引。
    • 计算当前车辆位置与最近路径点之间的角度差 θ e \theta_e θe和横向跟踪误差 error_y \text{error\_y} error_y
    • 根据 θ e \theta_e θe 的大小调整最大转向角 max_delta \text{max\_delta} max_delta
    • 如果横向跟踪误差 error_y \text{error\_y} error_y超过阈值 tolerance \text{tolerance} tolerance,则执行Bang-Bang控制,即转向最大角度 max_delta \text{max\_delta} max_delta;否则,方向盘保持不动。
  3. 更新状态

    • 使用计算出的转向角 δ f \delta_f δf更新车辆状态。
    • 将新的位置添加到轨迹列表中。
    • 更新绘图窗口中的轨迹和目标点。
    • interactive_mode = True # 设置为 True 以在交互式模式下运行,False 以保存 GIF
      效果如下
      在这里插入图片描述
      整体跟踪效果一般,有明显的震荡,尝试收敛中

如果换成sine跟踪,只需调整跟踪轨迹代码如下

refer_path[:, 1] = np.sin(refer_path[:, 0] / 10) * 2   # sine 轨迹

勉强可以跟踪啦!🤣🤣🤣
在这里插入图片描述

5. 改进BangBang控制

在上文中,原始的Bang-Bang控制算法主要依赖于车辆当前位置与参考路径之间的横向误差来决定转向角。当横向误差超过设定的阈值时,车辆会以最大转向角转向;当误差小于阈值时,车辆停止转向。这种控制方式简单有效,但在复杂路径跟踪时可能表现不佳,例如在曲率变化较大的路径上。改进后的Bang-Bang控制算法引入了对路径点的动态管理机制,以适应更长的路径跟踪需求。此外,还优化了速度控制策略,使得车辆能够更加平滑地跟随路径。

5.2 动态管理路径点

在改进的版本中,我们引入了一个全局变量 iadd 来追踪当前车辆应跟踪的路径点索引。当 iadd 超出路径点数组的长度时,动态增加路径点,确保路径点数组足够长以支持整个动画过程。

5.3 优化速度控制策略

改进后的速度控制策略不再固定为常数,而是根据当前车辆与目标路径点之间的距离 l_d 来动态调整。这有助于车辆在接近目标点时减速,从而减少过冲现象,提高路径跟踪精度。

Python 实现

以下是改进后的Bang-Bang控制算法的Python实现:

import numpy as np
import matplotlib.pyplot as plt
import math
from scipy.spatial import KDTree
from matplotlib.animation import FuncAnimation

# 初始化参考路径
refer_path = np.zeros((1000, 2))

# 车辆运动学模型类
class KinematicModel:
    def __init__(self, x, y, psi, v, L, dt):
        self.x = x
        self.y = y
        self.psi = psi
        self.v = v
        self.L = L
        self.dt = dt

    def update_state(self, v, delta_f):
        self.x += v * np.cos(self.psi) * self.dt
        self.y += v * np.sin(self.psi) * self.dt
        self.psi += (v / self.L) * np.tan(delta_f) * self.dt

    def get_state(self):
        return self.x, self.y, self.psi, self.v


def main(interactive=True):
    global refer_path, iadd  # 确保这些变量被声明为全局变量
    
    # 初始化车辆状态
    ugv = KinematicModel(0, 2, 0, 2, 2, 0.01)
    trajectory_x, trajectory_y = [], []

    # 创建绘图窗口
    fig, ax = plt.subplots()
    ax.plot(refer_path[:, 0], refer_path[:, 1], '-.b', linewidth=1.0, label="Reference Path")
    line, = ax.plot([], [], '-r', label="UGV Trajectory")
    target_dot, = ax.plot([], [], 'go', label="Target")
    ax.set_title("Improved Bang-Bang Trajectory Control")
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.set_xlim(-1, 110)
    ax.set_ylim(-3, 3)
    ax.grid(True)
    ax.legend()

    # Bang-Bang 控制器参数
    tolerance = 0.01
    max_delta = np.pi / 12.0
    
    def init():
        line.set_data([], [])
        target_dot.set_data([], [])
        return line, target_dot
        
    def update(frame):
        global iadd, refer_path  # 确保使用全局变量
        robot_state = np.array([ugv.x, ugv.y])

        # 判断 iadd 是否超出 refer_path 的长度,适当添加路径点
        if iadd + 1 > refer_path.shape[0]:
            refer_path = np.resize(refer_path, (refer_path.shape[0] + 1, 2))  # 增加一行
            refer_path[iadd, 0] = refer_path[iadd - 1, 0]  # 增加新路径点
            refer_path[iadd, 1] = refer_path[iadd - 1, 1]  # 增加新路径点的 y 坐标

        dx, dy = refer_path[iadd] - robot_state
        alpha = math.atan2(dy, dx)
        l_d = np.linalg.norm(refer_path[iadd] - robot_state)
        theta_e = alpha - ugv.psi
        error_y = l_d * math.sin(theta_e)

        # 根据误差调整最大转向角
        if abs(theta_e) > np.pi / 2.0:
            max_delta = np.pi / 12.0
        else:
            max_delta = np.pi / 24.0

        # Bang-Bang 控制
        delta_f = np.sign(error_y) * max_delta if abs(error_y) > tolerance else 0
        ugv.update_state(l_d * 4, delta_f=delta_f)

        # 更新轨迹
        trajectory_x.append(ugv.x)
        trajectory_y.append(ugv.y)
        line.set_data(trajectory_x, trajectory_y)

        # 更新目标点
        target_dot.set_data([refer_path[iadd, 0]], [refer_path[iadd, 1]])
        iadd += 1  # 增加 iadd
        return line, target_dot

    # 创建动画
    anim = FuncAnimation(fig, update, frames=1050, init_func=init, blit=True, interval=20, repeat=False)

    if interactive:
        plt.show()
    else:
        anim.save('Control/Controllers_python/Bang_Bang/ugv_animation.gif', writer='pillow', fps=20)
        print("GIF 已保存")

# 运行主程序
if __name__ == '__main__':
    iadd = 0
    refer_path[:, 0] = np.linspace(0, 100, 1000)
    refer_path[:, 1] = np.sin(refer_path[:, 0] / 10) * 2  # sine 轨迹
    interactive_mode = False  # 设置为 True 以在交互式模式下运行,False 以保存 GIF
    
    if not interactive_mode:
        import matplotlib
        matplotlib.use('Agg')

    main(interactive=interactive_mode)

在这里插入图片描述

  • 动态管理路径点
    原始算法:使用固定的路径点数组,可能导致路径点不足的问题。
    改进算法:动态增加路径点,确保路径点数组足够长,适用于更长的路径跟踪。
  • 速度控制策略
    原始算法:速度固定为常数,可能导致过冲现象。
    改进算法:根据距离动态调整速度,减少过冲现象,提高路径跟踪精度。
  • 控制效果
    原始算法:在直线路段表现良好,但在曲率变化较大的路径上可能表现不佳。
    改进算法:通过动态调整速度和路径点管理,提高了在复杂路径上的跟踪精度和平滑性。

6. 结论

通过上述改进,Bang-Bang控制算法在复杂路径跟踪中的性能得到了显著提升。动态管理路径点和优化速度控制策略使得车辆能够更加平滑地跟随路径,减少了过冲现象,提高了路径跟踪精度。通过Python代码实现和模拟实验,我们可以观察到控制策略的效果。后期会有更多的路径跟踪(PID,LQR,MPC等)算法分享,希望本文对你理解和实现无人车轨迹跟踪有所帮助。

如果你有任何问题或建议,欢迎加QQ群留言交流!😘😘😘

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

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

相关文章

springboot051医院管理系统(论文+源码)_kaic

医院管理系统 摘要 随着信息互联网信息的飞速发展,医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求,创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系统的系统分析部分&#…

万家数科:零售业务信息化融合的探索|OceanBase案例

本文作者:马琳,万家数科数据库专家。 万家数科商业数据有限公司,作为华润万家旗下的信息技术企业,专注于零售行业,在为华润万家提供服务的同时,也积极面向市场,为零售商及其生态系统提供全面的核…

基于DSP+ARM+FPGA的电能质量分析仪的软件设计

软件设计是电能质量设备的核心内容,上述章节详细介绍了电能质量参数的 算法,并且通过仿真实验进行了验证,本章将结合现代电能质量监测设备需求实 现算法在实际电网中应用。根据设计的电能质量分析仪的需求分析,进行总体的 软件…

【Android】Jetpack入门知识总结(LifeCycle,ViewModel,LiveData,DataBinding等)

文章目录 LifeCycle使用Lifecycle解耦页面与组件自定义控件实现LifecycleObserver接口注册生命周期监听器 使用LifecycleService解耦Service与组件使用ProcessLifecycleOwner监听应用程序生命周期 ViewModel用法在 Fragment 中使用 ViewModel LiveDataDataBinding导入依赖基本用…

Redis 性能优化选择:Pika 的配置与使用详解

引言 在我们日常开发中 redis是我们开发业务场景中不可缺少的部分。Redis 凭借其内存存储和快速响应的特点,广泛应用于缓存、消息队列等各种业务场景。然而,随着数据量的不断增长,单节点的 Redis 因为内存限制和并发能力的局限,逐…

FP7127:降压恒流LED芯片 支持双路调色调光 PWM调光

一、降压恒流LED芯片FP7127 FP7127 是平均电流模式控制的 LED 驱动 IC,具有稳定输出恒流的能力,优秀的负载调整率与高精度的电流控制。不用额外增加外部补偿元件,简化 PCB 板设计。输出的LED电流精度为 2%。 如果你想进行PWM数位调光&#…

R语言机器学习教程大纲

文章目录 介绍机器学习算法监督学习Supervised Learning分类Classification回归Regression 无监督学习 Unsupervised Learning聚类 Clustering降纬 Dimensionality Reduction相关Association 强化学习Reinforcement Learning模型自由 Model-Free Methods模型驱动 Model-Based M…

Rancher—多集群Kubernetes管理平台

目录 一、Rancher 简介1.1 Rancher 和 k8s 的区别 二、Rancher 安装及配置2.1 安装 rancher2.2 登录 Rancher 平台2.3 Rancher 管理已存在的 k8s 集群2.4 创建名称空间 namespace2.5 创建 Deployment 资源2.6 创建 service2.7 Rancher 部署监控系统 一、Rancher 简介 Rancher …

curl支持ssl错误:curl: (60) SSL certificate problem: certificate is not yet valid

在测试curl命令的时候发现curl: (60) SSL certificate problem: certificate is not yet valid出现这个错误,已经设置了ssl证书路径,最终发现是板子上时间不对,设置时间后可以正常使用。

论文研读 | End-to-End Object Detection with Transformers

DETR:端到端目标检测的创新 —— 作者 Nicolas Carion 等人 一、背景与挑战 目标检测是计算机视觉领域的一个核心任务,要求模型精确识别图像中的物体类别和位置。传统方法如 Faster R-CNN,因其区域建议网络等复杂结构,使得模型调…

网络安全基础知识点_网络安全知识基础知识篇

文章目录 一、网络安全概述1.1 定义1.2 信息安全特性1.3 网络安全的威胁1.4 网络安全的特征 二、入侵方式2.1 黑客2.1.1 入侵方法2.1.2 系统的威胁2.2 IP欺骗与防范2.2.1 TCP等IP欺骗基础知识2.2.2 IP欺骗可行的原因2.2.3 IP欺骗过程2.2.4 IP欺骗原理2.2.5 IP欺骗防范2.3 Sniff…

数据结构编程实践20讲(Python版)—16有向图

本文目录 16 有向图(Directed Graph)S1 说明特征应用领域S2 示例S3 问题:利用有向图构建贝叶斯网络Python代码代码说明结果S4 问题:有依赖的任务调度Python代码代码说明结果S5 问题:基于有向图的搜索引擎排序算法Python代码代码说明结果往期链接 01 数组02 链表03 栈04 队…

成都睿明智科技有限公司电商服务可靠不?

在这个短视频风起云涌的时代,抖音不仅成为了人们娱乐消遣的首选平台,更是众多商家竞相追逐的电商新蓝海。成都睿明智科技有限公司,作为抖音电商服务领域的佼佼者,正以其独到的洞察力和专业的服务,助力无数品牌在这片沃…

使用redis存储股股票数据及近一个月的行情数据

使用redis存储股票数据及近一个月的行情数据 性能瓶颈redis的使用odoo连接redis股票数据的读写结论 性能瓶颈 股票行情对数据的实时性是有要求的,在数据同步时如果都从数据库中查询数据,对于股票行情数据来说是有些慢了,因此我们使用redis来…

视频网站开发:Spring Boot框架的高效实现

5 系统实现 5.1用户信息管理 管理员管理用户信息,可以添加,修改,删除用户信息信息。下图就是用户信息管理页面。 图5.1 用户信息管理页面 5.2 视频分享管理 管理员管理视频分享,可以添加,修改,删除视频分…

HCIP-HarmonyOS Application Developer 习题(十五)

(判断)1、在HarmonyOs中发布带权限公共事件,发布者首先要在config.json中申请所需的权限。 答案:正确 分析:发布携带权限的公共事件:构造CommonEventPublishInfo对象,设置订阅者的权限。 &#…

基于springboot vue的音乐播放系统设计与实现

博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php phython node.js uniapp 微信小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不…

【Postman】如何导出导入数据文件?Postman链接分享?

方式一:postman分享链接 1.1 导出 1.2 导入 1.3 导入完成后删除分享的链接 方式二:postman导出导入json 2.1 导出 2.2 post导入json数据

智慧监管:EasyCVR视频汇聚智能分析平台助力有限空间作业实现全天候可视化监控

随着工业化和城市化进程的加快,有限空间作业(如地下管道、储罐、隧道等)在各类企事业单位中日益频繁。然而,这类作业环境复杂、危险系数高,对作业人员的安全管理和实时监控提出了严峻挑战。为了保障有限空间作业的安全…

基于Java的茶叶商城设计与实现(源码+定制+开发)茶叶电商系统开发、茶叶电商平台开发、茶叶在线销售平台设计与开发

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…