from common.numpy_fast import interp import numpy as np from cereal import log CAMERA_OFFSET = 0.06 # m from center car to camera TRAJECTORY_SIZE = 33 class LanePlanner: def __init__(self): self.lane_t = np.zeros((TRAJECTORY_SIZE,)) self.lll_y = np.zeros((TRAJECTORY_SIZE,)) self.rll_y = np.zeros((TRAJECTORY_SIZE,)) self.lane_width_estimate = 3.7 self.lane_width_certainty = 1.0 self.lane_width = 3.7 self.lll_prob = 0. self.rll_prob = 0. self.lll_std = 0. self.rll_std = 0. self.l_lane_change_prob = 0. self.r_lane_change_prob = 0. def parse_model(self, md): if len(md.laneLines) == 4 and len(md.laneLines[0].t) == TRAJECTORY_SIZE: self.ll_t = (np.array(md.laneLines[1].t) + np.array(md.laneLines[2].t))/2 # left and right ll x is the same self.ll_x = md.laneLines[1].x # only offset left and right lane lines; offsetting path does not make sense self.lll_y = np.array(md.laneLines[1].y) - CAMERA_OFFSET self.rll_y = np.array(md.laneLines[2].y) - CAMERA_OFFSET self.lll_prob = md.laneLineProbs[1] self.rll_prob = md.laneLineProbs[2] self.lll_std = md.laneLineStds[1] self.rll_std = md.laneLineStds[2] if len(md.meta.desireState): self.l_lane_change_prob = md.meta.desireState[log.PathPlan.Desire.laneChangeLeft] self.r_lane_change_prob = md.meta.desireState[log.PathPlan.Desire.laneChangeRight] def get_d_path(self, v_ego, path_t, path_xyz): # Reduce reliance on lanelines that are too far apart or # will be in a few seconds l_prob, r_prob = self.lll_prob, self.rll_prob width_pts = self.rll_y - self.lll_y prob_mods = [] for t_check in [0.0, 1.5, 3.0]: width_at_t = interp(t_check * (v_ego + 7), self.ll_x, width_pts) prob_mods.append(interp(width_at_t, [4.0, 5.0], [1.0, 0.0])) mod = min(prob_mods) l_prob *= mod r_prob *= mod # Reduce reliance on uncertain lanelines l_std_mod = interp(self.lll_std, [.15, .3], [1.0, 0.0]) r_std_mod = interp(self.rll_std, [.15, .3], [1.0, 0.0]) l_prob *= l_std_mod r_prob *= r_std_mod # Find current lanewidth self.lane_width_certainty += 0.05 * (l_prob * r_prob - self.lane_width_certainty) current_lane_width = abs(self.rll_y[0] - self.lll_y[0]) self.lane_width_estimate += 0.005 * (current_lane_width - self.lane_width_estimate) speed_lane_width = interp(v_ego, [0., 31.], [2.8, 3.5]) self.lane_width = self.lane_width_certainty * self.lane_width_estimate + \ (1 - self.lane_width_certainty) * speed_lane_width clipped_lane_width = min(4.0, self.lane_width) path_from_left_lane = self.lll_y + clipped_lane_width / 2.0 path_from_right_lane = self.rll_y - clipped_lane_width / 2.0 lr_prob = l_prob + r_prob - l_prob * r_prob lane_path_y = (l_prob * path_from_left_lane + r_prob * path_from_right_lane) / (l_prob + r_prob + 0.0001) lane_path_y_interp = np.interp(path_t, self.ll_t, lane_path_y) path_xyz[:,1] = lr_prob * lane_path_y_interp + (1.0 - lr_prob) * path_xyz[:,1] return path_xyz