defsolve_DARE(A, B, Q, R): """ solve a discrete time_Algebraic Riccati equation (DARE) """ X = Q maxiter = 150 eps = 0.01
for i inrange(maxiter): Xn = A.T @ X @ A - A.T @ X @ B @ \ la.inv(R + B.T @ X @ B) @ B.T @ X @ A + Q if (abs(Xn - X)).max() < eps: break X = Xn return Xn
defdlqr(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.inv(B.T @ X @ B + R) @ (B.T @ X @ A)
eigVals, eigVecs = la.eig(A - B @ K)
return K, X, eigVals
注意这里的A,B使用的是frenet坐标系
主要是[e,e_dot,the_e,the_e_dot]
关于加入纵向控制lqr算法
注意: x = [e, dot_e, th_e, dot_th_e, delta_v],当然相关的A,B,Q,R同样修改
# B = [0.0, 0.0 # 0.0, 0.0 # 0.0, 0.0 # v/L, 0.0 # 0.0, dt] B = np.zeros((5, 2)) B[3, 0] = v / L B[4, 1] = dt
K, _, _ = dlqr(A, B, Q, R)
# state vector # x = [e, dot_e, th_e, dot_th_e, delta_v] # e: lateral distance to the path # dot_e: derivative of e # th_e: angle difference to the path # dot_th_e: derivative of th_e # delta_v: difference between current speed and target speed x = np.zeros((5, 1)) x[0, 0] = e x[1, 0] = (e - pe) / dt x[2, 0] = th_e x[3, 0] = (th_e - pth_e) / dt x[4, 0] = v - tv
# input vector # u = [delta, accel] # delta: steering angle # accel: acceleration ustar = -K @ x