-
Notifications
You must be signed in to change notification settings - Fork 2
/
mpc.py
93 lines (75 loc) · 2.36 KB
/
mpc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import torch
from torchdiffeq import odeint
from mpc_step import step_physics
CENTERLINE_REWARD = 1.0
SPEED_REWARD = 0.1
DRIFT_REWARD = 0.3
L_STATECOST = torch.diag(
torch.tensor([CENTERLINE_REWARD, -SPEED_REWARD, 0, -DRIFT_REWARD, 0, 0, 0])
)
def riccatti_diff(K, A, B, L):
return K @ B @ B.T @ K - A.T @ K - K @ A - L
def get_jacobians(state_cur, action_last, track_curv, gear):
J_f_x = torch.autograd.functional.jacobian(
lambda state: step_physics(state, action_last, track_curv, gear),
state_cur,
create_graph=True,
)
J_f_u = torch.autograd.functional.jacobian(
lambda action: step_physics(state_cur, action, 0.2, 2),
action_last,
create_graph=True,
)
return J_f_x, J_f_u
def optimize_next_frame(
state_cur, action_last, track_curv, gear, mpc_horizon=1.0, mpc_sol_steps=10_000
):
J_f_x, J_f_u = get_jacobians(state_cur, action_last, track_curv, gear)
# Check controllability
C = torch.concat([J_f_u,
J_f_x @ J_f_u,
J_f_x @ J_f_x @ J_f_u,
J_f_x @ J_f_x @ J_f_x @ J_f_u,
J_f_x @ J_f_x @ J_f_x @ J_f_x @ J_f_u,
J_f_x @ J_f_x @ J_f_x @ J_f_x @ J_f_x @ J_f_u,
J_f_x @ J_f_x @ J_f_x @ J_f_x @ J_f_x @ J_f_x @ J_f_u]
)
print("C.shape")
print(C.shape)
print("\n\nrank of ctrlb")
print(torch.matrix_rank(C))
print("\n\n")
print("J_f_x")
print(J_f_x)
print("J_f_u")
print(J_f_u)
t_sol = torch.linspace(mpc_horizon, 0.0, mpc_sol_steps)
K_traj = odeint(
lambda t, K: riccatti_diff(K, J_f_x, J_f_u, L_STATECOST),
torch.zeros(7, 7),
t_sol,
)
action_cur = -J_f_u.T @ K_traj[0, :, :] @ state_cur
return action_cur
if __name__ == "__main__":
state_cur = torch.tensor([-9.6022e+00, 1.4705e+01,
-2.7156e-02,
-1.2177e-02,
-1.2591e-02, -1.6055e-03,
0.0000e+00])
'''
state_cur = torch.tensor(
[0.0, # d
0.1, # v
0.0, # delta
0.1, # beta
0.1, # psi
0.1, # w_z
0.0, # sigma
0.0 # t
], requires_grad=True
)
'''
action_last = torch.tensor([0.0, 0.0, 0.8], requires_grad=True)
K_traj = optimize_next_frame(state_cur, action_last, 0.1, 2)
print(K_traj)