rework imports
parent
ac2f901047
commit
1914bfe92d
|
@ -1,2 +1,2 @@
|
|||
from .cvxpy_mpc import *
|
||||
from .cvxpy_mpc import MPC
|
||||
from .mpc_config import Params
|
|
@ -2,63 +2,13 @@ import numpy as np
|
|||
|
||||
np.seterr(divide="ignore", invalid="ignore")
|
||||
|
||||
from scipy.integrate import odeint
|
||||
from scipy.interpolate import interp1d
|
||||
import cvxpy as opt
|
||||
|
||||
from .utils import *
|
||||
|
||||
from .mpc_config import Params
|
||||
|
||||
P = Params()
|
||||
|
||||
|
||||
def get_linear_model_matrices(x_bar, u_bar):
|
||||
"""
|
||||
Computes the LTI approximated state space model x' = Ax + Bu + C
|
||||
:param x_bar:
|
||||
:param u_bar:
|
||||
:return:
|
||||
"""
|
||||
|
||||
x = x_bar[0]
|
||||
y = x_bar[1]
|
||||
v = x_bar[2]
|
||||
theta = x_bar[3]
|
||||
|
||||
a = u_bar[0]
|
||||
delta = u_bar[1]
|
||||
|
||||
ct = np.cos(theta)
|
||||
st = np.sin(theta)
|
||||
cd = np.cos(delta)
|
||||
td = np.tan(delta)
|
||||
|
||||
A = np.zeros((P.N, P.N))
|
||||
A[0, 2] = ct
|
||||
A[0, 3] = -v * st
|
||||
A[1, 2] = st
|
||||
A[1, 3] = v * ct
|
||||
A[3, 2] = v * td / P.L
|
||||
A_lin = np.eye(P.N) + P.DT * A
|
||||
|
||||
B = np.zeros((P.N, P.M))
|
||||
B[2, 0] = 1
|
||||
B[3, 1] = v / (P.L * cd**2)
|
||||
B_lin = P.DT * B
|
||||
|
||||
f_xu = np.array([v * ct, v * st, a, v * td / P.L]).reshape(P.N, 1)
|
||||
C_lin = (
|
||||
P.DT
|
||||
* (
|
||||
f_xu - np.dot(A, x_bar.reshape(P.N, 1)) - np.dot(B, u_bar.reshape(P.M, 1))
|
||||
).flatten()
|
||||
)
|
||||
|
||||
# return np.round(A_lin,6), np.round(B_lin,6), np.round(C_lin,6)
|
||||
return A_lin, B_lin, C_lin
|
||||
|
||||
|
||||
class MPC:
|
||||
def __init__(self, state_cost, final_state_cost, input_cost, input_rate_cost):
|
||||
"""
|
||||
|
@ -91,20 +41,60 @@ class MPC:
|
|||
self.u_bounds = np.array([P.MAX_ACC, P.MAX_STEER])
|
||||
self.du_bounds = np.array([P.MAX_D_ACC, P.MAX_D_STEER])
|
||||
|
||||
def optimize_linearized_model(
|
||||
def get_linear_model_matrices(self, x_bar, u_bar):
|
||||
"""
|
||||
Computes the LTI approximated state space model x' = Ax + Bu + C
|
||||
:param x_bar:
|
||||
:param u_bar:
|
||||
:return:
|
||||
"""
|
||||
|
||||
x = x_bar[0]
|
||||
y = x_bar[1]
|
||||
v = x_bar[2]
|
||||
theta = x_bar[3]
|
||||
|
||||
a = u_bar[0]
|
||||
delta = u_bar[1]
|
||||
|
||||
ct = np.cos(theta)
|
||||
st = np.sin(theta)
|
||||
cd = np.cos(delta)
|
||||
td = np.tan(delta)
|
||||
|
||||
A = np.zeros((self.nx, self.nx))
|
||||
A[0, 2] = ct
|
||||
A[0, 3] = -v * st
|
||||
A[1, 2] = st
|
||||
A[1, 3] = v * ct
|
||||
A[3, 2] = v * td / P.L
|
||||
A_lin = np.eye(self.nx) + self.dt * A
|
||||
|
||||
B = np.zeros((P.N, P.M))
|
||||
B[2, 0] = 1
|
||||
B[3, 1] = v / (P.L * cd**2)
|
||||
B_lin = self.dt * B
|
||||
|
||||
f_xu = np.array([v * ct, v * st, a, v * td / P.L]).reshape(P.N, 1)
|
||||
C_lin = (
|
||||
self.dt
|
||||
* (
|
||||
f_xu
|
||||
- np.dot(A, x_bar.reshape(self.nx, 1))
|
||||
- np.dot(B, u_bar.reshape(self.nu, 1))
|
||||
).flatten()
|
||||
)
|
||||
return A_lin, B_lin, C_lin
|
||||
|
||||
def step(
|
||||
self,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
initial_state,
|
||||
target,
|
||||
prev_cmd,
|
||||
verbose=False,
|
||||
):
|
||||
"""
|
||||
Optimisation problem defined for the linearised model,
|
||||
:param A:
|
||||
:param B:
|
||||
:param C:
|
||||
:param initial_state:
|
||||
:param target:
|
||||
:param verbose:
|
||||
|
@ -119,6 +109,8 @@ class MPC:
|
|||
cost = 0
|
||||
constr = []
|
||||
|
||||
A, B, C = self.get_linear_model_matrices(initial_state, prev_cmd)
|
||||
|
||||
for k in range(self.control_horizon):
|
||||
cost += opt.quad_form(target[:, k] - x[:, k + 1], self.Q)
|
||||
cost += opt.quad_form(u[:, k], self.R)
|
|
@ -62,19 +62,6 @@ def get_nn_idx(state, path):
|
|||
return target_idx
|
||||
|
||||
|
||||
def normalize_angle(angle):
|
||||
"""
|
||||
Normalize an angle to [-pi, pi]
|
||||
:param angle:
|
||||
:return:
|
||||
"""
|
||||
while angle > np.pi:
|
||||
angle -= 2.0 * np.pi
|
||||
while angle < -np.pi:
|
||||
angle += 2.0 * np.pi
|
||||
return angle
|
||||
|
||||
|
||||
def get_ref_trajectory(state, path, target_v):
|
||||
"""
|
||||
Reinterpolate the trajectory to get a set N desired target states
|
||||
|
@ -110,5 +97,17 @@ def get_ref_trajectory(state, path, target_v):
|
|||
dy = xref[1, :] - state[1]
|
||||
xref[0, :] = dx * np.cos(-state[3]) - dy * np.sin(-state[3]) # X
|
||||
xref[1, :] = dy * np.cos(-state[3]) + dx * np.sin(-state[3]) # Y
|
||||
xref[3, :] = normalize_angle(path[2, ind] - state[3]) # Theta
|
||||
xref[3, :] = path[2, ind] - state[3] # Theta
|
||||
|
||||
def fix_angle_reference(angle_ref, angle_init):
|
||||
"""
|
||||
This function returns a "smoothened" angle_ref wrt angle_init so there are no jumps.
|
||||
"""
|
||||
diff_angle = angle_ref - angle_init
|
||||
diff_angle = np.unwrap(diff_angle)
|
||||
return angle_init + diff_angle
|
||||
|
||||
xref[3, :] = (xref[3, :] + np.pi) % (2.0 * np.pi) - np.pi
|
||||
xref[3, :] = fix_angle_reference(xref[3, :], xref[3, 0])
|
||||
|
||||
return xref
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import animation
|
||||
from scipy.integrate import odeint
|
||||
|
||||
from mpcpy.utils import compute_path_from_wp
|
||||
import mpcpy
|
||||
from cvxpy_mpc.utils import compute_path_from_wp, get_ref_trajectory
|
||||
from cvxpy_mpc import MPC, Params
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
# Robot Starting position
|
||||
SIM_START_X = 0.0
|
||||
|
@ -18,7 +16,7 @@ SIM_START_V = 0.0
|
|||
SIM_START_H = 0.0
|
||||
L = 0.3
|
||||
|
||||
params = mpcpy.Params()
|
||||
params = Params()
|
||||
|
||||
# Params
|
||||
VEL = 1.0 # m/s
|
||||
|
@ -44,7 +42,7 @@ class MPCSim:
|
|||
R = [10, 10] # input cost
|
||||
P = [10, 10] # input rate of change cost
|
||||
|
||||
self.mpc = mpcpy.MPC(Q, Qf, R, P)
|
||||
self.mpc = MPC(Q, Qf, R, P)
|
||||
|
||||
# Interpolated Path to follow given waypoints
|
||||
self.path = compute_path_from_wp(
|
||||
|
@ -111,17 +109,13 @@ class MPCSim:
|
|||
# start=time.time()
|
||||
# dynamycs w.r.t robot frame
|
||||
curr_state = np.array([0, 0, self.state[2], 0])
|
||||
# State Matrices
|
||||
A, B, C = mpcpy.get_linear_model_matrices(curr_state, self.action)
|
||||
# Get Reference_traj -> inputs are in worldframe
|
||||
target = mpcpy.get_ref_trajectory(self.state, self.path, VEL)
|
||||
target = get_ref_trajectory(self.state, self.path, VEL)
|
||||
|
||||
x_mpc, u_mpc = self.mpc.optimize_linearized_model(
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
x_mpc, u_mpc = self.mpc.step(
|
||||
curr_state,
|
||||
target,
|
||||
self.action,
|
||||
verbose=False,
|
||||
)
|
||||
# NOTE: used only for preview purposes
|
||||
|
@ -142,8 +136,8 @@ class MPCSim:
|
|||
dxdt = x[2] * np.cos(x[3])
|
||||
dydt = x[2] * np.sin(x[3])
|
||||
dvdt = u[0]
|
||||
dtheta0dt = x[2] * np.tan(u[1]) / params.L
|
||||
dqdt = [dxdt, dydt, dvdt, dtheta0dt]
|
||||
dthetadt = x[2] * np.tan(u[1]) / params.L
|
||||
dqdt = [dxdt, dydt, dvdt, dthetadt]
|
||||
return dqdt
|
||||
|
||||
# solve ODE
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import animation
|
||||
|
||||
from mpcpy.utils import compute_path_from_wp
|
||||
import mpcpy
|
||||
from cvxpy_mpc.utils import compute_path_from_wp, get_ref_trajectory
|
||||
from cvxpy_mpc import MPC, Params
|
||||
|
||||
params = mpcpy.Params()
|
||||
params = Params()
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
@ -221,7 +220,7 @@ def run_sim():
|
|||
R = [10, 10] # input cost [acc ,steer]
|
||||
P = [10, 10] # input rate of change cost [acc ,steer]
|
||||
|
||||
mpc = mpcpy.MPC(Q, Qf, R, P)
|
||||
mpc = MPC(Q, Qf, R, P)
|
||||
x_history = []
|
||||
y_history = []
|
||||
|
||||
|
@ -247,7 +246,7 @@ def run_sim():
|
|||
|
||||
# Get Reference_traj
|
||||
# NOTE: inputs are in world frame
|
||||
target = mpcpy.get_ref_trajectory(state, path, params.TARGET_SPEED)
|
||||
target = get_ref_trajectory(state, path, params.TARGET_SPEED)
|
||||
|
||||
# for MPC base link frame is used:
|
||||
# so x, y, yaw are 0.0, but speed is the same
|
||||
|
@ -262,16 +261,11 @@ def run_sim():
|
|||
ego_state[3] + action[0] * np.tan(action[1]) / params.L * params.DT
|
||||
)
|
||||
|
||||
# State Matrices
|
||||
A, B, C = mpcpy.get_linear_model_matrices(ego_state, action)
|
||||
|
||||
# optimization loop
|
||||
start = time.time()
|
||||
|
||||
# MPC step
|
||||
_, u_mpc = mpc.optimize_linearized_model(
|
||||
A, B, C, ego_state, target, verbose=False
|
||||
)
|
||||
_, u_mpc = mpc.step(ego_state, target, action, verbose=False)
|
||||
action[0] = u_mpc.value[0, 0]
|
||||
action[1] = u_mpc.value[1, 0]
|
||||
|
||||
|
|
Loading…
Reference in New Issue