无人车系统(五):轨迹跟踪Pure Pursuit方法

今天介绍一种基于几何追踪的无人车轨迹跟踪方法——Pure Pursuit(纯跟踪)方法。

1. 阿克曼转向几何模型

无人车系统(一):运动学模型及其线性化一文中,里面介绍无人车的运动学模型为阿克曼转向几何模型,并最终可简化为如下图所示的单车模型。

在这里插入图片描述

精确描述单车模型中几何关系的核心公式如下:
δ = a r c t a n ( L R ) (1) \delta=arctan(\frac{L}{R}) \tag{1} δ=arctan(RL)(1)
其中, δ \delta δ为前轮转角, L L L为轴距(wheel base), R R R为给定转向角运动时,无人车形成的轨迹圆的半径。

2. Pure pursuit控制器

我们利用下图【引自无人驾驶汽车系统入门(十八)——使用pure pursuit实现无人车轨迹追踪】来介绍Pure pursuit控制器的设计。
在这里插入图片描述

Pure pursuit方法的依据是使如上图所示的单车模型以合适的前轮转向( δ \delta δ)运动,并恰好使无人车后轴中心经过当前的路点。 这样一来,我们就可以根据当前的路点以及单车几何模型计算当前的期望前轮转向角( δ \delta δ)。

根据上图,我们有以下几何关系:

sin ⁡ α = l d 2 R ⇒ R = l d 2 sin ⁡ α (2) \sin \alpha=\frac{l_d}{2R} \Rightarrow R=\frac{l_d}{2\sin \alpha} \tag{2} sinα=2RldR=2sinαld(2)

将式(2)代入式(1)可得:

δ = a r c t a n ( 2 L sin ⁡ α l d ) (3) \delta=arctan(\frac{2L \sin \alpha}{l_d}) \tag{3} δ=arctan(ld2Lsinα)(3)

其中, α \alpha α为路点与车后轴连成的向量的角度与车航向角的差值,当路点在车的左边时, α > 0 \alpha>0 α>0,反之则 α < 0 \alpha<0 α<0 l d l_d ld为车后轴离路点的距离,又被称为前视距离

为了让式(3)在形式上更加统一,我们可以利用无人车相对当前路点的横向偏差 e y e_y ey与前视距离 l d l_d ld表示(如果不能立马了悟,还请看无人车系统(四):轨迹跟踪PID控制第一张图):

sin ⁡ α = e y l d (4) \sin \alpha = \frac{e_y}{l_d} \tag{4} sinα=ldey(4)

将式(4)代入式(3)得:

δ ( k ) = a r c t a n ( 2 L e y ( k ) l d 2 ( k ) ) (5) \delta(k) = arctan(\frac{2Le_y(k)}{l_d^2(k)}) \tag{5} δ(k)=arctan(ld2(k)2Ley(k))(5)

在pure pursuit方法中,前视距离表示成无人车纵向线速度的形式,即 l d = λ v x + c l_d=\lambda v_x+c ld=λvx+c c c c为一常值,最终的控制器如下:

δ ( k ) = a r c t a n ( 2 L e y ( k ) ( k v x ( k ) + c ) 2 ) (6) \delta(k) = arctan(\frac{2Le_y(k)}{(kv_x(k)+c)^2}) \tag{6} δ(k)=arctan((kvx(k)+c)22Ley(k))(6)

分析式(6),利用小角度近似,我们有:
δ ( k ) ≈ 2 L l d 2 e y (7) \delta(k)\approx \frac{2L}{l_d^2} e_y \tag{7} δ(k)ld22Ley(7)

我们把 2 L l d 2 \frac{2L}{l_d^2} ld22L看作比例控制器的参数, e y e_y ey作为系统误差,那么这就相当于一个以横向跟踪误差CTE作为系统误差的比例控制器。

无人车系统(四):轨迹跟踪PID控制不同的是,在pure pursuit 方法中, l d l_d ld是关于速度的线性函数 l d = λ v X l_d=\lambda v_X ld=λvX,其中参数 λ \lambda λ c c c是需要调整。

无人车模型的两个控制输入:无人车前轮转向角( δ \delta δ),有时候也用方向盘转角来表示;无人车线速度 v v v。前者是影响无人车横向运动的主要控制输入,因此,设计的轨迹跟踪控制器,都是为了得到合适的 δ \delta δ

3. python 示例

"""
Pure Pursuit
"""

import numpy as np
import math
import copy
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline

# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
    from IPython import display

plt.ion()
plt.figure(figsize=(18, 3))

class UGV_model:
    def __init__(self, x0, y0, theta0, L, v0, T): # L:wheel base
        self.x = x0 # X
        self.y = y0 # Y
        self.theta = theta0 # headding
        self.l = L  # wheel base
        self.v = v0  # speed
        self.dt = T  # decision time periodic
    def update(self, vt, deltat):  # update ugv's state
        dx = self.v*np.cos(self.theta)
        dy = self.v*np.sin(self.theta)
        dtheta = self.v*np.tan(deltat)/self.l
        self.x += dx*self.dt
        self.y += dy*self.dt
        self.theta += dtheta*self.dt
        
    def plot_duration(self):
        plt.scatter(self.x, self.y, color='r')   
        plt.axis([self.x-9, self.x+9, -3, 3])
#         plt.axis([self.x-9, self.x+9, -10, 10])
        if is_ipython:
            display.clear_output(wait=True)
            display.display(plt.gcf())  
            
            
from scipy.spatial import KDTree

# set reference trajectory
refer_path = np.zeros((1000, 2))
refer_path[:,0] = np.linspace(0, 1000, 1000)
# refer_path[:,1] = 5*np.sin(refer_path[:,0]/5.0)

refer_tree = KDTree(refer_path)

plt.plot(refer_path[:,0], refer_path[:,1], '-.b', linewidth=5.0)
L = 2.0
v = 2.0
k = 1.0  #  前视距离ld = k*v+2.0
ugv = UGV_model(0, 1.0, 0, L, v, 0.1)
ind = 0 
ld = k*v+2.0
for i in range(1000):
    robot_state = np.zeros(2)
    robot_state[0] = ugv.x
    robot_state[1] = ugv.y
    for i in range(ind, len(refer_path)):
        dist = np.linalg.norm(robot_state-refer_path[i])
        if dist >= ld:
            ind = i
            break
           
    dist = np.linalg.norm(robot_state-refer_path[ind])
    dx, dy = refer_path[ind] - robot_state
    alpha = math.atan2(dy, dx)
    delta = math.atan2(2.0*L*np.sin(alpha-ugv.theta)/ld, 1)  # pure pursuit controller
    ugv.update(2.0, delta)
    ugv.plot_duration()

我随便选了一个参数: λ = 1.0 , c = 2.0 \lambda=1.0, c=2.0 λ=1.0,c=2.0

  • 跟踪直线效果
    在这里插入图片描述

  • 跟踪直线效果
    在这里插入图片描述

4. 当前视距离 l d = 1.0 ∗ v x + 2.0 l_d=1.0*v_x+2.0 ld=1.0vx+2.0时,PID的效果

为了进一步说有pure pursuit方法其实等价于无人车系统(四):轨迹跟踪PID控制中介绍的纯比例控制器。我们采用与pure pursuit同样的前视距离,做一组实验。实验结果如下:

  • 纯比例P, k p = 1.0 k_p=1.0 kp=1.0
    在这里插入图片描述

  • PD控制, k p = 1.0 , k d = 20.0 k_p=1.0,k_d=20.0 kp=1.0,kd=20.0

在这里插入图片描述

  • PID控制, k p = 1.0 , k i = 0.001 , k d = 20.0 k_p=1.0,k_i=0.001, k_d=20.0 kp=1.0,ki=0.001,kd=20.0

在这里插入图片描述

对比纯P控制的效果与pure pursuit非常接近,加入微分与积分后,控制效果反而变差。(也可能是我PID参数没有调好,这套参数与无人车系统(四):轨迹跟踪PID控制)中的一样。

总结

本篇主要对用于无车轨迹跟踪控制的pure pursuit方法进行介绍。我们从原理出发,并给出pure pursuit的控制器计算公式,最后给出python示例。结果显示pure pursuit的跟踪效果还不错。文中也说明了,pure pursuit与P控制形式一样,只不过在无人车系统(四):轨迹跟踪PID控制中,我们只是选择离无人车最近的路点作为当前的目标点,并没有根据前视距离选择适当的路点。

在这里插入图片描述

  • 17
    点赞
  • 184
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
【资源说明】 基于Matlab实现跟踪(Pure Pursuit)算法源码+项目说明.zip 基于Matlab实现跟踪(Pure Pursuit)算法 在参考资料1的基础上修正部分错误,优化代码,演示跟踪算法。 ![图片](./imgs/1.png) ## 跟踪算法本质 参考人类驾驶员的行为,以车的后轴为基点,通过控制前轮的偏角delta,使车辆沿一条经过预瞄点的**圆弧**行驶,跟踪效果将由ld决定,如何设计ld也是算法的改进方向之一。 预瞄点的引入使得控制更加平顺,普通PID控制跟踪的是离车辆最近的轨迹点,而跟踪跟踪的是预瞄点。 跟踪本质是一个**P控制器**,对车辆进行**横向控制**,代码示例中的横向误差如图所示: ![横向误差](./imgs/2.png) 可见横向误差不收敛于0,即横向控制存在静态误差,加入积分控制后,横向误差如图所示: ![横向误差](./imgs/3.png) (加入积分控制,静态误差减小,超调量增大,为减小超调量,可引入微分控制) 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

windSeS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值