自动驾驶算法详解(4): 横向LQR、纵向PID控制进行轨迹跟踪以及python实现

本文探讨了在自动驾驶算法中,如何利用LQR进行横向控制,同时结合PID算法进行纵向控制。通过实例展示了不同PID参数下车辆的控制结果,并提供了代码实现。理解了这种分离控制在实际应用中的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在量产ADAS或者自动驾驶算法中,横纵向控制往往都是分开控制的,上一篇文章中介绍了如何使用LQR同时进行横纵向的控制,本文将介绍一种横纵向分开控制的思路,将使用LQR算法进行横向控制,同时使用PID算法进行纵向控制。这种方法在很多自动驾驶科技公司比较常见,百度apollo的控制节点conrol也是使用同样的思路。

如果对自动驾驶算法感兴趣,可以关注我的主页和专栏。

https://blog.youkuaiyun.com/nn243823163/category_11685852.htmlhttps://blog.youkuaiyun.com/nn243823163/category_11685852.html最新文章推荐:

Apollo Planning决策规划算法代码详细解析 (1):Scenario选择

Apollo Planning决策规划算法代码详细解析 (5):规划算法流程介绍

Apollo Planning决策规划算法代码详解 (22):决策规划算法最完整介绍

自动驾驶算法详解(2): prescan联合simulink进行FCW的仿真

自动驾驶算法详解(3): LQR算法进行轨迹跟踪,lqr_speed_steering_control( )的python实现

自动驾驶算法详解(5): 贝塞尔曲线进行路径规划的python实现

 Apollo算法仿真调试(1): 使用Vscode断点调试apollo的方法

Apollo规划决策算法仿真调试(4):  动态障碍物绕行

Apollo规划决策算法仿真调试(7):pnc_map模块详解GetRouteSegments规划局部地图生成下篇_

正文如下:

一、横向LQR问题模型建立:

理论部分比较成熟,这里只介绍demo所使用的建模方程:

使用离散代数黎卡提方程求解

系统状态矩阵与LQR同时控制横纵向相比有所简化,状态矩阵如下,X = [距离差,距离差导数,角度差,角度差导数]:

输入矩阵变为1个变量,只有前轮转角。

A矩阵和B矩阵如下:

二、纵向PID控制

纵向上由PID算法来计算加速度,本demo中只保留P项:

三、结果分析

从状态更新的方法可以看到,纵向控制的速度会影响横向控制的结果

1、纵向参数P = 1 时的控制结果:

速度控制结果:

轨迹跟踪结果:

2、纵向参数P = 5 时的控制结果:

速度控制结果:

轨迹跟踪结果:

3、纵向参数P = 20时的控制结果:

速度控制结果:

轨迹跟踪结果:

4、纵向参数P = 30时的控制结果:

速度控制结果:

四、代码实现

1、参数初始化

Kp = 1.0 # speed proportional gain


# LQR parameter
Q = np.eye(4)
R = np.eye(1)


# parameters
dt = 0.1 # time tick[s]
L = 0.5 # Wheel base of the vehicle [m]
max_steer = np.deg2rad(45.0) # maximum steering angle[rad]


show_animation = True
#  show_animation = False

2、相关函数定义

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



def lqr_steering_control(state, cx, cy, cyaw, ck, pe, pth_e):
    ind, e = calc_nearest_index(state, cx, cy, cyaw)


    k = ck[ind]
    v = state.v
    th_e = pi_2_pi(state.yaw - cyaw[ind])


    A = np.zeros((4, 4))
    A[0, 0] = 1.0
    A[0, 1] = dt
    A[1, 2] = v
    A[2, 2] = 1.0
    A[2, 3] = dt
 # print(A)


    B = np.zeros((4, 1))
    B[3, 0] = v / L


    K, _, _ = dlqr(A, B, Q, R)


    x = np.zeros((4, 1))


    x[0, 0] = e
    x[1, 0] = (e - pe) / dt
    x[2, 0] = th_e
    x[3, 0] = (th_e - pth_e) / dt


    ff = math.atan2(L * k, 1)
    fb = pi_2_pi((-K @ x)[0, 0])


    delta = ff + fb


 return delta, ind, e, th_e



def closed_loop_prediction(cx, cy, cyaw, ck, speed_profile, goal):
    T = 500.0 # max simulation time
    goal_dis = 0.3
    stop_speed = 0.05


    state = State(x=-0.0, y=-0.0, yaw=0.0, v=0.0)


    time = 0.0
    x = [state.x]
    y = [state.y]
    yaw = [state.yaw]
    v = [state.v]
    t = [0.0]


    e, e_th = 0.0, 0.0


 while T >= time:
        dl, target_ind, e, e_th = lqr_steering_control(
            state, cx, cy, cyaw, ck, e, e_th)


        ai = PIDControl(speed_profile[target_ind], state.v)
        state = update(state, ai, dl)


 if abs(state.v) <= stop_speed:
            target_ind += 1


        time = time + dt


 # check goal
        dx = state.x - goal[0]
        dy = state.y - goal[1]
 if math.hypot(dx, dy) <= goal_dis:
 print("Goal")
 break


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


 if target_ind % 100 == 0 and show_animation:
            plt.cla()
 # for stopping simulation with the esc key.
            plt.gcf().canvas.mpl_connect('key_release_event',
 lambda event: [exit(0) if event.key == 'escape' else None])
            plt.plot(cx, cy, "-r", label="course")
            plt.plot(x, y, "ob", label="trajectory")
            plt.plot(cx[target_ind], cy[target_ind], "xg", label="target")
            plt.axis("equal")
            plt.grid(True)
            plt.title("speed[km/h]:" + str(round(state.v * 3.6, 2))
 + ",target index:" + str(target_ind))
            plt.pause(0.0001)


 return t, x, y, yaw, v

3、主函数

def main():
 print("LQR steering control tracking start!!")
#     ax = [0.0, 6.0, 12.5, 10.0, 7.5, 3.0, -1.0]
#     ay = [0.0, -3.0, -5.0, 6.5, 3.0, 5.0, -2.0]


    ax = [0.0, 6.0, 12.5, 10.0, 17.5, 20.0, 25.0]
    ay = [0.0, -3.0, -5.0, 6.5, 3.0, 0.0, 0.0]
 
    goal = [ax[-1], ay[-1]]


    cx, cy, cyaw, ck, s = calc_spline_course(
        ax, ay, ds=0.1)
    target_speed = 10.0 / 3.6 # simulation parameter km/h -> m/s


    sp = calc_speed_profile(cx, cy, cyaw, target_speed)


    t, x, y, yaw, v = closed_loop_prediction(cx, cy, cyaw, ck, sp, goal)


 if show_animation: # pragma: no cover
        plt.close()
        plt.subplots(1)
        plt.plot(ax, ay, "xb", label="input")
        plt.plot(cx, cy, "-r", label="spline")
        plt.plot(x, y, "-g", label="tracking")
        plt.grid(True)
        plt.axis("equal")
        plt.xlabel("x[m]")
        plt.ylabel("y[m]")
        plt.legend()
 
        plt.show()
<think>好的,我现在需要处理用户关于LQR跟踪算法实现控制理论的查询。首先,我要回顾用户提供的引用内容,确保准确理解LQR的基本原理和应用场景。引用中提到了LQR算法轨迹跟踪中的应用,尤其是车辆和机器人的控制模型,涉及四自由度动力学模型,包括质心侧偏角、横摆角速度等参数。我需要将这些信息整合成一个结构清晰的回答,分步骤解释LQR的理论基础和实现步骤。 接下来,用户的问题可能集中在LQR实现细节、数学推导以及实际应用案例上。根据引用内容,LQR的核心是通过优化状态偏差和控制成本来设计控制策略,因此需要详细说明Q和R矩阵的作用,以及如何建立状态空间方程。此外,用户可能对代码实现感兴趣,但引用中提到的C++代码没有具体内容,可能需要引导用户参考相关资源或提供伪代码示例。 在回答过程中,必须确保所有数学公式正确使用$$...$$格式,例如状态方程和Riccati方程。同时,要检查LaTeX语法是否正确,避免出现格式错误。生成的相关问题需要与LQR的应用、优化方法、参数调整以及与其他算法的比较相关,帮助用户进一步探索该主题。 最后,引用标识需要自然地附加在相关段落末尾,确保每个引用对应正确的来源。需要确认引用内容中的信息是否足够支持回答,必要时补充解释,但不可添加未提及的信息。整个过程要保持回答的中文表达流畅,结构清晰,分点说明,便于用户逐步理解LQR跟踪算法实现控制理论。</think>### LQR跟踪算法实现控制理论详解 #### 一、LQR控制基本原理 线性二次型调节器(LQR)通过最小化状态偏差和控制成本实现最优控制。其核心目标函数为: $$ J = \int_{0}^{\infty} (x^T Q x + u^T R u) dt $$ 其中: - $x$为状态向量,$u$为控制输入 - $Q$(半正定矩阵)和$R$(正定矩阵)分别加权状态误差与控制能耗[^1] #### 二、LQR跟踪实现步骤 1. **建立系统模型** 以车辆轨迹跟踪为例,需构建四自由度动力学模型: $$ \dot{x} = A x + B u $$ 状态向量$x$包含质心侧偏角、横摆角速度、横向误差、航向误差[^1] 2. **设计目标函数** 根据跟踪需求调整$Q$和$R$矩阵。例如: - 增大$Q$中横向误差权重可增强轨迹跟踪精度 - 增大$R$权重可降低控制能耗[^2] 3. **求解Riccati方程** 通过代数Riccati方程计算最优反馈矩阵$K$: $$ A^T P + PA - PBR^{-1}B^T P + Q = 0 $$ 最优控制律为: $$ u = -Kx $$ 4. **实现闭环控制** 实时测量状态偏差,应用控制律生成控制量(如转向角、加速度)[^3] #### 三、典型应用场景 1. 自动驾驶车辆路径跟踪 2. 机器人末端轨迹跟踪 3. 无人机姿态控制 ```python # 伪代码示例(需根据具体模型实现) def lqr_controller(current_state, reference): error = current_state - reference K = compute_K(A, B, Q, R) # 离线计算反馈矩阵 control_input = -K @ error return control_input ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

自动驾驶Player

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

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

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

打赏作者

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

抵扣说明:

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

余额充值