Stanley横向控制算法:针对低速场景

无人驾驶算法——使用Stanley method实现无人车轨迹追踪

文章已搬至 知乎,如果对你有所帮助和启发,欢迎关注,点赞,评论交流,感谢
Date: 2019/08/03
Editor:萧潇子(Jesse)
Contact: 1223167600@qq.com

基于几何追踪的方法

关于无人车追踪轨迹,目前的主流方法分为两类:基于几何追踪的方法和基于模型预测的方法,其中几何追踪方法主要包含纯跟踪和Stanley两种方法,纯跟踪方法已经广泛应用于移动机器人的路径跟踪中,网上也有很多详细的介绍,本文主要介绍斯坦福大学无人车使用的Stanley方法。

Stanley method


Stanley方法是一种基于横向跟踪误差(cross-track error :e 为前轴中心到最近路径点( p x , p y )​的距离)的非线性反馈函数,并且能实现横向跟踪误差指数收敛于0。根据车辆位姿与给定路径的相对几何关系可以直观的获得控制车辆方向盘转角的控制变量,其中包含横向偏差e 和航向偏差θ e 。

在不考虑横向跟踪误差的情况下,前轮偏角和给定路径切线方向一致,如图所示。其中θ e 表示车辆航向与最近路径点切线方向之间的夹角,在没有任何横向误差的情况下,前轮方向与所在路径点的方向相同:


在不考虑航向跟踪偏差的情况下,横向跟踪误差越大,前轮转向角越大,假设车辆预期轨迹在距离前轮d ( t ) 处与给定路径上最近点切线相交,根据几何关系得出如下非线性比例函数:

其中d ( t ) 与车速相关,最后用车速v ( t ),增益参数k 表示。随着横向误差的增加,arctan函数产生一个直接指向期望路径的前轮偏角,并且收敛受车速v ( t ) 限制。
综合两方面控制因素,基本转向角控制率如下:

使用线性自行车运动模型,可以得到横向误差的变化率:

其中sin ⁡ δ e ( t )根据几何关系可知:

基于Python的Stanley算法跟踪直线仿真

Stanley控制转向角度,使用一个简单的P控制器控制速度,首先我们定义参数数值如下:

import numpy as np
import math
import matplotlib.pyplot as plt

k  = 0.5   # 增益参数
Kp = 1.0   # 速度P控制器系数
dt = 0.1   # 时间间隔,单位:s
L  = 3.0   # 车辆轴距,单位:m


这里将增益参数k设置为0.3,速度P控制器的比例系数Kp设置为1.0,时间间隔为0.1 秒,车的轴距我们定为3.0米。

定义车辆状态类,在简单的自行车模型中,我们只考虑车辆的当前位置 ( x , y )  ,车辆的偏航角度y a w 以及车辆的速度v ,为了仿真模拟,我们定义车辆的状态更新函数来模拟真实车辆的状态更新:

class VehicleState:

    def __init__(self, x=0.0, y=0.0, yaw=0.0, v=0.0):
        self.x = x
        self.y = y
        self.yaw = yaw
        self.v = v


def update(state, a, delta):
    state.x = state.x + state.v * math.cos(state.yaw) * dt
    state.y = state.y + state.v * math.sin(state.yaw) * dt
    state.yaw = state.yaw + state.v / L * math.tan(delta) * dt
    state.v = state.v + a * dt
    return state
仿真中,纵向控制使用一个简单的P控制器,横向控制(即转角控制)使用Stanley控制器,并且限制车轮转角范围[-30, 30],这两个控制器定义如下:

def PControl(target, current):
    a = Kp * (target - current)
    return a


def stanley_control(state, cx, cy, ch, pind):
    ind = calc_target_index(state, cx, cy)

    if pind >= ind:
        ind = pind

    if ind < len(cx):
        tx = cx[ind]
        ty = cy[ind]
        th = ch[ind]
    else:
        tx = cx[-1]
        ty = cy[-1]
        th = ch[-1]
        ind = len(cx) - 1

    # 计算横向误差
    if ((state.x - tx) * th - (state.y - ty)) > 0:
        error = abs(math.sqrt((state.x - tx) ** 2 + (state.y - ty) ** 2))
    else:
        error = -abs(math.sqrt((state.x - tx) ** 2 + (state.y - ty) ** 2))
    delta = ch[ind] - state.yaw + math.atan2(k * error, state.v)

    #  限制车轮转角 [-30, 30]
    if delta > np.pi / 6.0:
        delta = np.pi / 6.0
    elif delta < - np.pi / 6.0:
        delta = - np.pi / 6.0
    return delta, ind


定义函数用于搜索最临近的路点:

def calc_target_index(state, cx, cy):
    # 搜索最临近的路点
    dx = [state.x - icx for icx in cx]
    dy = [state.y - icy for icy in cy]
    d = [abs(math.sqrt(idx ** 2 + idy ** 2)) for (idx, idy) in zip(dx, dy)]
    ind = d.index(min(d))

    return ind
主函数:


def main():
    #  设置目标路点
    cx = np.arange(0, 50, 1)
    cy = [0 * ix for ix in cx]
    ch = [0 * ix for ix in cx]
    target_speed = 5.0 / 3.6  # [m/s]
    T = 200.0  # 最大模拟时间
    # 设置车辆的初始状态
    state = VehicleState(x=-0.0, y=-3.0, yaw=-0.0, v=0.0)
    lastIndex = len(cx) - 1
    time = 0.0
    x = [state.x]
    y = [state.y]
    yaw = [state.yaw]
    v = [state.v]
    t = [0.0]
    target_ind = calc_target_index(state, cx, cy)

    while T >= time and lastIndex > target_ind:
        ai = PControl(target_speed, state.v)
        di, target_ind = stanley_control(state, cx, cy, ch, target_ind)
        state = update(state, ai, di)
        time = time + dt

        x.append(state.x)
        y.append(state.y)
        yaw.append(state.yaw)
        v.append(state.v)
        t.append(time)

        plt.cla()
        plt.plot(cx, cy, ".r", label="course")
        plt.plot(x, y, "-b", label="trajectory")
        plt.plot(cx[target_ind], cy[target_ind], "go", label="target")
        plt.axis("equal")
        plt.grid(True)
        plt.title("Speed[km/h]:" + str(state.v * 3.6)[:4])
        plt.pause(0.001)


if __name__ == '__main__':
    main()


仿真结果:

在这里插入图片描述

通过仿真结果图,我们看到红点表示实现规划好的直线路径,蓝线则表示我们的车辆实际运行的轨迹,绿点表示距离当前位置最近路径点,在这段代码中,我们设置了增益参数k kk为0.3,通过进一步去改变k kk的大小对比结果,可以减小k kk值得到更平滑的跟踪轨迹,但是更加平滑的结果会引起某些急剧的转角处会存在转向不足的情况。

参考

Automatic Steering Methods for Autonomous Automobile Path Tracking
Stanley_ The robot that won the DARPA grand challenge
无人驾驶汽车系统入门(十八)——使用pure pursuit实现无人车轨迹追踪(https://blog.csdn.net/adamshan/article/details/80555174)
————————————————
版权声明:本文为CSDN博主「萧潇子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/renyushuai900/article/details/98460758

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Stanley控制器是一种用于横向控制(即转角控制)的算法,常用于自动驾驶系统中。它的原理是通过计算车辆当前位置与目标位置之间的横向误差,然后根据误差和车辆速度来计算转角控制指令。 在Stanley控制器中,横向误差的计算公式如下: ``` if ((state.x - tx) * th - (state.y - ty)) > 0: error = abs(math.sqrt((state.x - tx) ** 2 + (state.y - ty) ** 2)) else: error = -abs(math.sqrt((state.x - tx) ** 2 + (state.y - ty) ** 2)) ``` 其中,state.x和state.y表示车辆当前位置的x和y坐标,tx和ty表示目标位置的x和y坐标,th表示目标位置的航向角。 然后,根据横向误差和车辆速度来计算转角控制指令: ``` delta = ch\[ind\] - state.yaw + math.atan2(k * error, state.v) ``` 其中,ch\[ind\]表示车辆当前位置的航向角,state.yaw表示车辆当前的偏航角,k是一个控制参数,state.v表示车辆当前的速度。 通过这样的计算,Stanley控制器可以实现车辆的横向控制,使车辆能够跟随预定的路径行驶。具体的算法细节可以参考引用\[3\]中的代码和引用\[2\]中提供的参考链接。 #### 引用[.reference_title] - *1* *3* [Stanley横向控制算法:针对低速场景](https://blog.csdn.net/ChenGuiGan/article/details/116143446)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [横向控制 | Stanley算法](https://blog.csdn.net/baoli8425/article/details/116865006)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值