LQR轨迹跟踪算法Python算法实现3

根据LQR轨迹跟踪算法Python/Matlab算法实现2的代码,我们转化成Python,后续上车使用。代码仅开源到这,可以进行仿真,函数都可以直接使用。工程代码就不开源了。

from numpy import *
from math import *
import matplotlib.pyplot as plt
import scipy.linalg as la
import time
Kp = 1
dt = 0.1
L = 2.9
Q = eye(4)
Q[0,0] = 19.7
Q[1,1] =0.01
Q[2,2] = 18.3
Q[3,3] = 7.3
R = 1
max_steer =60 * pi/180#in rad
target_v =10.0 / 3.6


cx = linspace(0,200,2000)
cy = zeros(len(cx))
pd= zeros(len(cx))
pdd = zeros(len(cx))
ck = zeros(len(cx))
cyaw = zeros(len(cx))
for i in range(len(cx)):
    cy[i] = -sin(cx[i]/10) * cx[i]/8

for i in range (len(cx)-1):
    pd[i] = (cy[i+1]-cy[i])/(cx[i+1]-cx[i])

for i in range (len(cx)-1):
    pdd[i] = (cy[i+1]-2*cy[i] + cy[i-1])/(0.5* (cx[i+1]- cx[i-1]))**2

for i in range(len(cx)-1):
    ck[i] = pdd[i]/((1+pd[i]**2)**1.5)

for i in range(len(pd)):
    cyaw[i] = atan(pd[i])

pe = 0
pth_e = 0
i = 1
x = 0
y = -0.1
yaw = 0
v = 0
ind =0

class State:

    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):
    if delta >= max_steer:
        delta = max_steer
    if delta <= - max_steer:
        delta = - max_steer
    state.x = state.x + state.v * cos(state.yaw) * dt
    state.y = state.y + state.v * sin(state.yaw) * dt
    state.yaw = state.yaw + state.v / L * tan(delta) * dt
    state.v = state.v + a * dt

    return state

def PIDControl(target, current):
    a = Kp * (target - current)
    return a
#
# def pi_2_pi(angle):  # the unit of angle is in rad;
#     while (angle > pi):
#         angle = angle - 2.0 * pi
#
#     while (angle < -pi):
#         angle = angle + 2.0 * pi
#
#     return angle

def solve_DARE(A, B, Q, R):
    """
    solve a discrete time_Algebraic Riccati equation (DARE)
    """
    X = Q
    maxiter = 500
    eps = 0.01

    for i in range(maxiter):
        Xn = A.T * X * A - A.T * X * B * la.pinv(R + B.T * X * B) * B.T * X * A + Q
        if (abs(Xn - X)).max()  < eps:
            X = Xn
            break
        X = Xn

    return Xn

def dlqr(A, B, Q, R):
    """Solve the discrete time lqr controller.
    x[k+1] = A x[k] + B u[k]
    cost = sum x[k].T*Q*x[k] + u[k].T*R*u[k]
    # ref Bertsekas, p.151
    """

    # first, try to solve the ricatti equation
    X = solve_DARE(A, B, Q, R)

    # compute the LQR gain
    K = la.pinv(B.T * X * B + R) * (B.T * X * A)

    return K

def calc_nearest_index(state, cx, cy):
    dx = [state.x - icx for icx in cx]
    dy = [state.y - icy for icy in cy]

    d = [abs(sqrt(idx ** 2 + idy ** 2)) for (idx, idy) in zip(dx, dy)]

    error = min(d)

    ind = d.index(error)

    dy = cy[ind] - state.y
    if dy > 0:
        error = -error

    return ind, error

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

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

    A = mat(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 = mat(zeros((4, 1)))
    B[3, 0] = v / L

    K = dlqr(A, B, Q, R)
    print('K is', K)
    x =mat(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 = atan(L * k)
    fb = (-K * x)
    print(ff,fb)
    delta = 1*ff + 1 * fb
    print(delta)
    return delta, ind, e, th_e

state = State(x=0.0, y= -0.5, yaw=0.0, v=0.0)
x = state.x
y = state.y
yaw = state.yaw
v = state.v
i = 0
x_pos = zeros(len(cx))
y_pos = zeros(len(cx))

while ind < len(cx):
    delta,ind, e, th_e = lqr_steering_control(state, cx, cy, cyaw, ck, pe, pth_e)
    pth_e = th_e
    pe = e
    print('lateral error is ',e)
    v = state.v
    print("v is",v)
    #print('Index is ', ind)
    if abs(e) > 4:
       print('too far from reference!\n')
       break
    a = PIDControl(target_v, v)

    state = update(state, a, delta)
    x = state.x
    y = state.y
    x_pos[i] = x
    y_pos[i] = y
    i = i + 1


plt.plot(cx, cy,"-b")

for i in range(len(x_pos)):
    plt.plot(x_pos[i],y_pos[i],".r",markersize = 1)

plt.grid(True)
plt.axis("equal")
plt.xlabel("x[m]")
plt.ylabel("y[m]")
plt.show()
print(cyaw[0:20])

效果如图:
在这里插入图片描述

LQR(线性二次调节)控制是经典控制理论中一种常用的控制方法,在现代控制领域得到了广泛应用。Matlab是一种强大的数学计算软件,可以方便地实现各种控制算法。这里将介绍如何利用Matlab实现LQR跟踪控制算法LQR算法的核心是设计一个最优控制器,使得系统在满足一定性能指标下能够稳定地运行。这里以单自由度调节系统为例,其动力学方程为: $$m \ddot{x} + c \dot{x} + kx = u$$ 其中,$m$、$c$、$k$分别是质量、阻尼和弹性系数;$x$是位移;$u$是控制力。假设需要将系统调整到某一给定位置$x_d$,设计LQR控制器需要先将系统状态转化为标准状态空间形式: $$\dot{x} = Ax + Bu$$ $$y = Cx + Du$$ 其中,$A$、$B$、$C$、$D$分别是状态方程和输出方程的系数矩阵和向量。针对该系统,其状态方程和输出方程可分别表示为: $$\begin{bmatrix} \dot{x}_1 \\ \dot{x}_2 \end{bmatrix}=\begin{bmatrix} 0 & 1 \\ -\frac{k}{m} & -\frac{c}{m} \end{bmatrix}\begin{bmatrix} {x}_1 \\ {x}_2 \end{bmatrix}+\begin{bmatrix} 0 \\ \frac{1}{m} \end{bmatrix}u$$ $$y = \begin{bmatrix} 1 & 0 \end{bmatrix}\begin{bmatrix} {x}_1 \\ {x}_2 \end{bmatrix}$$ 在Matlab中,可以利用lqr函数求解问题。具体步骤如下: 1.定义状态方程和输出方程。 2.设置Q矩阵和R矩阵,其中Q矩阵衡量状态误差对控制变量的影响,R矩阵则衡量控制力的大小,需要根据实际情况进行取值。在本系统中,可以设置如下值: $$Q = \begin{bmatrix} 1 & 0 \\ 0 & 10 \end{bmatrix},R = 1$$ 3.调用lqr函数,得到最优控制器增益矩阵K。 4.针对系统初始状态$x(0)$和给定状态$x_d$,计算控制力u。 5.根据计算的控制力进行控制,更新系统状态。重复步骤4和5,直至系统稳定。 通过以上步骤,就可以在Matlab中实现LQR跟踪控制算法。需要注意的是,应当根据实际系统情况选择不同的参数,并对控制器进行调试和优化,以达到最优的控制效果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值