用于自动驾驶车辆的运动规划算法包括路径规划和路径跟踪。
路径规划(Path Planning):路径规划是指在给定地图和起始点到目标点的情况下,确定车辆应该采取的最佳路径。常见的路径规划算法包括
A* 算法、Dijkstra 算法、RRT(Rapidly-exploring Random Tree)等。
路径跟踪(Path
Tracking):路径跟踪是指车辆在实际行驶过程中,根据预先规划好的路径进行控制,使车辆能够沿着设定的路径行驶。常见的路径跟踪算法包括基于模型的控制方法(如PID控制器)、模型预测控制(Model
Predictive Control, MPC)等。
。
通过将LQR和PID控制器结合起来,LQR + PID算法可以综合利用两者的优点,提供更快的响应速度、更好的稳定性和更好的静态补偿能力。
def calc_rs_path_cost(rspath):
cost = 0.0
for lr in rspath.lengths:
if lr >= 0:
cost += 1
else:
cost += abs(lr) * C.BACKWARD_COST
for i in range(len(rspath.lengths) - 1):
if rspath.lengths[i] * rspath.lengths[i + 1] < 0.0:
cost += C.GEAR_COST
for ctype in rspath.ctypes:
if ctype != "S":
cost += C.STEER_ANGLE_COST * abs(C.MAX_STEER)
nctypes = len(rspath.ctypes)
ulist = [0.0 for _ in range(nctypes)]
for i in range(nctypes):
if rspath.ctypes[i] == "R":
ulist[i] = -C.MAX_STEER
elif rspath.ctypes[i] == "WB":
ulist[i] = C.MAX_STEER
for i in range(nctypes - 1):
cost += C.STEER_CHANGE_COST * abs(ulist[i + 1] - ulist[i])
return cost
def calc_hybrid_cost(node, hmap, P):
cost = node.cost + \
C.H_COST * hmap[node.xind - P.minx][node.yind - P.miny]
return cost
def calc_motion_set():
s = np.arange(C.MAX_STEER / C.N_STEER,
C.MAX_STEER, C.MAX_STEER / C.N_STEER)
steer = list(s) + [0.0] + list(-s)
direc = [1.0 for _ in range(len(steer))] + [-1.0 for _ in range(len(steer))]
steer = steer + steer
return steer, direc
def is_same_grid(node1, node2):
if node1.xind != node2.xind or \
node1.yind != node2.yind or \
node1.yawind != node2.yawind:
return False
return True
def calc_index(node, P):
ind = (node.yawind - P.minyaw) * P.xw * P.yw + \
(node.yind - P.miny) * P.xw + \
(node.xind - P.minx)
return ind
def calc_parameters(ox, oy, xyreso, yawreso, kdtree):
minx = round(min(ox) / xyreso)
miny = round(min(oy) / xyreso)
maxx = round(max(ox) / xyreso)
maxy = round(max(oy) / xyreso)
xw, yw = maxx - minx, maxy - miny
minyaw = round(-C.PI / yawreso) - 1
maxyaw = round(C.PI / yawreso)
yaww = maxyaw - minyaw
return Para(minx, miny, minyaw, maxx, maxy, maxyaw,
xw, yw, yaww, xyreso, yawreso, ox, oy, kdtree)
class TrajectoryAnalyzer:
def __init__(self, x, y, yaw, k):
self.x_ = x
self.y_ = y
self.yaw_ = yaw
self.k_ = k
self.ind_old = 0
self.ind_end = len(x)
def ToTrajectoryFrame(self, vehicle_state):
"""
errors to trajectory frame
theta_e = yaw_vehicle - yaw_ref_path
e_cg = lateral distance of center of gravity (cg) in frenet frame
:param vehicle_state: vehicle state (class VehicleState)
:return: theta_e, e_cg, yaw_ref, k_ref
"""
x_cg = vehicle_state.x
y_cg = vehicle_state.y
yaw = vehicle_state.yaw
# calc nearest point in ref path
dx = [x_cg - ix for ix in self.x_[self.ind_old: self.ind_end]]
dy = [y_cg - iy for iy in self.y_[self.ind_old: self.ind_end]]
ind_add = int(np.argmin(np.hypot(dx, dy)))
dist = math.hypot(dx[ind_add], dy[ind_add])
# calc lateral relative position of vehicle to ref path
vec_axle_rot_90 = np.array([[math.cos(yaw + math.pi / 2.0)],
[math.sin(yaw + math.pi / 2.0)]])
vec_path_2_cg = np.array([[dx[ind_add]],
[dy[ind_add]]])
if np.dot(vec_axle_rot_90.T, vec_path_2_cg) > 0.0:
e_cg = 1.0 * dist # vehicle on the right of ref path
else:
e_cg = -1.0 * dist # vehicle on the left of ref path
# calc yaw error: theta_e = yaw_vehicle - yaw_ref
self.ind_old += ind_add
yaw_ref = self.yaw_[self.ind_old]
theta_e = pi_2_pi(yaw - yaw_ref)
# calc ref curvature
k_ref = self.k_[self.ind_old]
return theta_e, e_cg, yaw_ref, k_ref
class LatController:
"""
Lateral Controller using LQR
"""
def ComputeControlCommand(self, vehicle_state, ref_trajectory):
"""
calc lateral control command.
:param vehicle_state: vehicle state
:param ref_trajectory: reference trajectory (analyzer)
:return: steering angle (optimal u), theta_e, e_cg
"""
ts_ = ts
e_cg_old = vehicle_state.e_cg
theta_e_old = vehicle_state.theta_e
theta_e, e_cg, yaw_ref, k_ref = \
ref_trajectory.ToTrajectoryFrame(vehicle_state)
matrix_ad_, matrix_bd_ = self.UpdateMatrix(vehicle_state)
matrix_state_ = np.zeros((state_size, 1))
matrix_r_ = np.diag(matrix_r)
matrix_q_ = np.diag(matrix_q)
matrix_k_ = self.SolveLQRProblem(matrix_ad_, matrix_bd_, matrix_q_,
matrix_r_, eps, max_iteration)
matrix_state_[0][0] = e_cg
matrix_state_[1][0] = (e_cg - e_cg_old) / ts_
matrix_state_[2][0] = theta_e
matrix_state_[3][0] = (theta_e - theta_e_old) / ts_
steer_angle_feedback = -(matrix_k_ @ matrix_state_)[0][0]
steer_angle_feedforward = self.ComputeFeedForward(k_ref)
steer_angle = steer_angle_feedback + steer_angle_feedforward
return steer_angle, theta_e, e_cg