LQR轨迹跟踪 | python实现
基本概念
离散LQR求解公式推导看这篇博客,这里直接给出结果。
P
k
=
Q
+
A
T
P
k
−
1
A
−
A
T
P
B
(
B
T
P
k
−
1
B
+
R
)
−
1
B
T
P
k
−
1
A
K
=
(
B
T
P
B
+
R
)
−
1
B
T
P
A
u
∗
(
k
)
=
−
K
x
(
k
)
\begin{aligned} &P_{k} = Q + A^T P_{k-1} A - A^T P B(B^T P_{k-1} B + R)^{-1} B^T P_{k-1} A \\ &K = (B^T P B + R)^{-1} B^T P A \\ &u^*(k) = -Kx(k) \end{aligned}
Pk=Q+ATPk−1A−ATPB(BTPk−1B+R)−1BTPk−1AK=(BTPB+R)−1BTPAu∗(k)=−Kx(k)
式中
P
k
P_k
Pk表示LQR求解过程中的黎卡提矩阵迭代值,
P
P
P表示收敛后的黎卡提矩阵;
K
K
K表示反馈增益;
A
,
B
A, B
A,B表示离散的系统矩阵;
Q
,
R
Q, R
Q,R表示系统状态和输入的权重矩阵;
x
,
u
x, u
x,u分别表示系统状态和系统输入,
u
∗
u^*
u∗表示最优系统输入。
求解步骤
-
设置迭代最大值 N N N和收敛差值 ε \varepsilon ε
-
设置迭代初值 P 0 = Q P_{0} = Q P0=Q
-
迭代求解, k = 1 , . . . , N k=1,...,N k=1,...,N
P k = Q + A T P k − 1 A − A T P B ( B T P k − 1 B + R ) − 1 B T P k − 1 A P_{k} = Q + A^T P_{k-1} A - A^T P B(B^T P_{k-1} B + R)^{-1} B^T P_{k-1} A Pk=Q+ATPk−1A−ATPB(BTPk−1B+R)−1BTPk−1A
若 ∣ P k − P k − 1 ∣ ≤ ε \vert P_{k} - P_{k-1} \vert \leq \varepsilon ∣Pk−Pk−1∣≤ε,表示黎卡提矩阵收敛,可以结束迭代,否则迭代至最大步数 N N N。 -
计算反馈增益
K = ( B T P B + R ) − 1 B T P A K = (B^T P B + R)^{-1} B^T P A K=(BTPB+R)−1BTPA -
用反馈增益 K K K进行控制
u ∗ ( t ) = − K x ( t ) u^*(t) = -Kx(t) u∗(t)=−Kx(t)
python实现轨迹跟踪
实现效果
这里用LQR控制以后轴中心为车辆中心的模型进行轨迹跟踪,用这个模型是因为方便线性化进行控制,该模型线性化推导过程可以看这篇博客。
LQR求解
轨迹跟踪的完整代码在github仓库,这里给出LQR求解部分
import math
import numpy as np
class DiscreteLQR:
def __init__(self, Ad, Bd, Q, R, epsilon = 1e-4):
self.Ad = Ad # 离散系统矩阵
self.Bd = Bd # 离散系统矩阵
self.Q = Q
self.R = R
self.P = Q # 给个初始值Q
self.K = np.mat(np.zeros([Bd.shape[1], Bd.shape[0]]))
self.epsilon = epsilon
# 离散LQR迭代求解,给定一个P的初值,迭代更新P和K,直到收敛
def solve(self, MAX_ITER = 100):
self.P = self.Q
for it in range(MAX_ITER):
P_ = self.Q + self.Ad.T * self.P * self.Ad - self.Ad.T * self.P * self.Bd * (self.R + self.Bd.T * self.P * self.Bd).I * self.Bd.T * self.P * self.Ad
if (abs(P_ - self.P).max() < self.epsilon):
break
self.P = P_
if (it == MAX_ITER - 1):
print("Maximum iteration reached.")
return False
self.K = (self.R + self.Bd.T * self.P * self.Bd).I * self.Bd.T * self.P * self.Ad
return True
def update_mat(self, Ad, Bd, Q, R):
self.Ad = Ad
self.Bd = Bd
self.Q = Q
self.R = R