master
mcarfagno 2023-10-20 19:20:11 +01:00
parent 147670b5de
commit 35a0698c73
4 changed files with 53 additions and 38 deletions

View File

@ -23,10 +23,10 @@ params = mpcpy.Params()
# Params # Params
VEL = 1.0 # m/s VEL = 1.0 # m/s
# Classes # Classes
class MPCSim: class MPCSim:
def __init__(self): def __init__(self):
# State for the robot mathematical model [x,y,heading] # State for the robot mathematical model [x,y,heading]
self.state = np.array([SIM_START_X, SIM_START_Y, SIM_START_V, SIM_START_H]) self.state = np.array([SIM_START_X, SIM_START_Y, SIM_START_V, SIM_START_H])
@ -114,7 +114,7 @@ class MPCSim:
# State Matrices # State Matrices
A, B, C = mpcpy.get_linear_model_matrices(curr_state, self.action) A, B, C = mpcpy.get_linear_model_matrices(curr_state, self.action)
# Get Reference_traj -> inputs are in worldframe # Get Reference_traj -> inputs are in worldframe
target, _ = mpcpy.get_ref_trajectory(self.state, self.path, VEL) target = mpcpy.get_ref_trajectory(self.state, self.path, VEL)
x_mpc, u_mpc = self.mpc.optimize_linearized_model( x_mpc, u_mpc = self.mpc.optimize_linearized_model(
A, A,

View File

@ -247,7 +247,7 @@ def run_sim():
# Get Reference_traj # Get Reference_traj
# NOTE: inputs are in world frame # NOTE: inputs are in world frame
target, _ = mpcpy.get_ref_trajectory(state, path, params.TARGET_SPEED) target = mpcpy.get_ref_trajectory(state, path, params.TARGET_SPEED)
# for MPC base link frame is used: # for MPC base link frame is used:
# so x, y, yaw are 0.0, but speed is the same # so x, y, yaw are 0.0, but speed is the same

View File

@ -16,6 +16,9 @@ P = Params()
def get_linear_model_matrices(x_bar, u_bar): def get_linear_model_matrices(x_bar, u_bar):
""" """
Computes the LTI approximated state space model x' = Ax + Bu + C Computes the LTI approximated state space model x' = Ax + Bu + C
:param x_bar:
:param u_bar:
:return:
""" """
x = x_bar[0] x = x_bar[0]
@ -58,7 +61,12 @@ def get_linear_model_matrices(x_bar, u_bar):
class MPC: class MPC:
def __init__(self, state_cost, final_state_cost, input_cost, input_rate_cost): def __init__(self, state_cost, final_state_cost, input_cost, input_rate_cost):
""" """ """
:param state_cost:
:param final_state_cost:
:param input_cost:
:param input_rate_cost:
"""
self.nx = P.N # number of state vars self.nx = P.N # number of state vars
self.nu = P.M # umber of input/control vars self.nu = P.M # umber of input/control vars

View File

@ -8,6 +8,10 @@ P = Params()
def compute_path_from_wp(start_xp, start_yp, step=0.1): def compute_path_from_wp(start_xp, start_yp, step=0.1):
""" """
Computes a reference path given a set of waypoints Computes a reference path given a set of waypoints
:param start_xp:
:param start_yp:
:param step:
:return:
""" """
final_xp = [] final_xp = []
final_yp = [] final_yp = []
@ -34,6 +38,9 @@ def compute_path_from_wp(start_xp, start_yp, step=0.1):
def get_nn_idx(state, path): def get_nn_idx(state, path):
""" """
Computes the index of the waypoint closest to vehicle Computes the index of the waypoint closest to vehicle
:param state:
:param path:
:return:
""" """
dx = state[0] - path[0, :] dx = state[0] - path[0, :]
dy = state[1] - path[1, :] dy = state[1] - path[1, :]
@ -58,6 +65,8 @@ def get_nn_idx(state, path):
def normalize_angle(angle): def normalize_angle(angle):
""" """
Normalize an angle to [-pi, pi] Normalize an angle to [-pi, pi]
:param angle:
:return:
""" """
while angle > np.pi: while angle > np.pi:
angle -= 2.0 * np.pi angle -= 2.0 * np.pi
@ -68,40 +77,38 @@ def normalize_angle(angle):
def get_ref_trajectory(state, path, target_v): def get_ref_trajectory(state, path, target_v):
""" """
For each step in the time horizon Reinterpolate the trajectory to get a set N desired target states
modified reference in robot frame :param state:
:param path:
:param target_v:
:return:
""" """
K = int(P.T / P.DT) K = int(P.T / P.DT)
xref = np.zeros((P.N, K + 1))
dref = np.zeros((1, K + 1)) xref = np.zeros((P.N, K))
ncourse = path.shape[1]
ind = get_nn_idx(state, path) ind = get_nn_idx(state, path)
dx = path[0, ind] - state[0]
dy = path[1, ind] - state[1] cdist = np.append(
xref[0, 0] = dx * np.cos(-state[3]) - dy * np.sin(-state[3]) # X [0.0], np.cumsum(np.hypot(np.diff(path[0, :].T), np.diff(path[1, :]).T))
xref[1, 0] = dy * np.cos(-state[3]) + dx * np.sin(-state[3]) # Y )
xref[2, 0] = target_v # V cdist = np.clip(cdist, cdist[0], cdist[-1])
xref[3, 0] = normalize_angle(path[2, ind] - state[3]) # Theta
dref[0, 0] = 0.0 # Steer operational point should be 0 start_dist = cdist[ind]
travel = 0.0 interp_points = [d * P.DT * target_v + start_dist for d in range(1, K + 1)]
dl = np.hypot(path[0, 1] - path[0, 0], path[1, 1] - path[1, 0]) xref[0, :] = np.interp(interp_points, cdist, path[0, :])
for i in range(1, K + 1): xref[1, :] = np.interp(interp_points, cdist, path[1, :])
travel += abs(target_v) * P.DT xref[2, :] = target_v
dind = int(round(travel / dl)) xref[3, :] = np.interp(interp_points, cdist, path[2, :])
if (ind + dind) < ncourse:
dx = path[0, ind + dind] - state[0] # points where the vehicle is at the end of trajectory
dy = path[1, ind + dind] - state[1] xref_cdist = np.interp(interp_points, cdist, cdist)
xref[0, i] = dx * np.cos(-state[3]) - dy * np.sin(-state[3]) stop_idx = np.where(xref_cdist == cdist[-1])
xref[1, i] = dy * np.cos(-state[3]) + dx * np.sin(-state[3]) xref[2, stop_idx] = 0.0
xref[2, i] = target_v # sp[ind + dind]
xref[3, i] = normalize_angle(path[2, ind + dind] - state[3]) # transform in car ego frame
dref[0, i] = 0.0 dx = xref[0, :] - state[0]
else: dy = xref[1, :] - state[1]
dx = path[0, ncourse - 1] - state[0] xref[0, :] = dx * np.cos(-state[3]) - dy * np.sin(-state[3]) # X
dy = path[1, ncourse - 1] - state[1] xref[1, :] = dy * np.cos(-state[3]) + dx * np.sin(-state[3]) # Y
xref[0, i] = dx * np.cos(-state[3]) - dy * np.sin(-state[3]) xref[3, :] = normalize_angle(path[2, ind] - state[3]) # Theta
xref[1, i] = dy * np.cos(-state[3]) + dx * np.sin(-state[3]) return xref
xref[2, i] = 0.0 # stop? #sp[ncourse - 1]
xref[3, i] = normalize_angle(path[2, ncourse - 1] - state[3])
dref[0, i] = 0.0
return xref, dref