#!/usr/bin/env python3 import numpy as np from openpilot.common.conversions import Conversions as CV from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import COMFORT_BRAKE, desired_follow_distance, get_jerk_factor, get_T_FOLLOW from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT TRAFFIC_MODE_BP = [0., CITY_SPEED_LIMIT] PERSONALITY_BP = [20. * CV.KPH_TO_MS, 90. * CV.KPH_TO_MS] class FrogPilotFollowing: def __init__(self, FrogPilotPlanner): self.frogpilot_planner = FrogPilotPlanner self.disable_throttle = False self.following_lead = False self.slower_lead = False self.acceleration_jerk = 0 self.danger_jerk = 0 self.desired_follow_distance = 0 self.speed_jerk = 0 self.t_follow = 0 def update(self, v_ego, sm, frogpilot_toggles): if sm["controlsState"].enabled and sm["frogpilotCarState"].trafficModeEnabled: if sm["carState"].aEgo >= 0: self.base_acceleration_jerk = float(np.interp(v_ego, TRAFFIC_MODE_BP, frogpilot_toggles.traffic_mode_jerk_acceleration)) self.base_speed_jerk = float(np.interp(v_ego, TRAFFIC_MODE_BP, frogpilot_toggles.traffic_mode_jerk_speed)) else: self.base_acceleration_jerk = float(np.interp(v_ego, TRAFFIC_MODE_BP, frogpilot_toggles.traffic_mode_jerk_deceleration)) self.base_speed_jerk = float(np.interp(v_ego, TRAFFIC_MODE_BP, frogpilot_toggles.traffic_mode_jerk_speed_decrease)) self.base_danger_jerk = float(np.interp(v_ego, TRAFFIC_MODE_BP, frogpilot_toggles.traffic_mode_jerk_danger)) self.t_follow = float(np.interp(v_ego, TRAFFIC_MODE_BP, frogpilot_toggles.traffic_mode_follow)) elif sm["controlsState"].enabled: if sm["carState"].aEgo >= 0: self.base_acceleration_jerk, self.base_danger_jerk, self.base_speed_jerk = get_jerk_factor( frogpilot_toggles.aggressive_jerk_acceleration, frogpilot_toggles.aggressive_jerk_danger, frogpilot_toggles.aggressive_jerk_speed, frogpilot_toggles.standard_jerk_acceleration, frogpilot_toggles.standard_jerk_danger, frogpilot_toggles.standard_jerk_speed, frogpilot_toggles.relaxed_jerk_acceleration, frogpilot_toggles.relaxed_jerk_danger, frogpilot_toggles.relaxed_jerk_speed, frogpilot_toggles.custom_personalities, sm["controlsState"].personality ) else: self.base_acceleration_jerk, self.base_danger_jerk, self.base_speed_jerk = get_jerk_factor( frogpilot_toggles.aggressive_jerk_deceleration, frogpilot_toggles.aggressive_jerk_danger, frogpilot_toggles.aggressive_jerk_speed_decrease, frogpilot_toggles.standard_jerk_deceleration, frogpilot_toggles.standard_jerk_danger, frogpilot_toggles.standard_jerk_speed_decrease, frogpilot_toggles.relaxed_jerk_deceleration, frogpilot_toggles.relaxed_jerk_danger, frogpilot_toggles.relaxed_jerk_speed_decrease, frogpilot_toggles.custom_personalities, sm["controlsState"].personality ) t_follow_param = get_T_FOLLOW( frogpilot_toggles.aggressive_follow, frogpilot_toggles.standard_follow, frogpilot_toggles.relaxed_follow, frogpilot_toggles.custom_personalities, sm["controlsState"].personality ) if isinstance(t_follow_param, list): self.t_follow = float(np.interp(v_ego, PERSONALITY_BP, t_follow_param)) else: self.t_follow = float(t_follow_param) else: self.base_acceleration_jerk = 0 self.base_danger_jerk = 0 self.base_speed_jerk = 0 self.t_follow = 0 self.acceleration_jerk = self.base_acceleration_jerk self.danger_jerk = self.base_danger_jerk self.speed_jerk = self.base_speed_jerk self.following_lead = self.frogpilot_planner.tracking_lead and self.frogpilot_planner.lead_one.dRel < (self.t_follow * 2) * v_ego self.disable_throttle = self.frogpilot_planner.tracking_lead and not self.following_lead self.disable_throttle &= self.frogpilot_planner.lead_one.dRel + 6.0 < (self.t_follow * 2 * 2) * v_ego self.disable_throttle &= self.frogpilot_planner.lead_one.vLead < v_ego * 0.75 if sm["controlsState"].enabled and self.frogpilot_planner.tracking_lead: self.update_follow_values(self.frogpilot_planner.lead_one.dRel, v_ego, self.frogpilot_planner.lead_one.vLead, frogpilot_toggles) self.desired_follow_distance = int(desired_follow_distance(v_ego, self.frogpilot_planner.lead_one.vLead, self.t_follow)) else: self.desired_follow_distance = 0 def update_follow_values(self, lead_distance, v_ego, v_lead, frogpilot_toggles): # Offset by FrogAi for FrogPilot for a more natural approach to a faster lead if frogpilot_toggles.human_following and v_lead > v_ego: distance_factor = max(lead_distance - (v_ego * self.t_follow), 1) from frogpilot.common.frogpilot_variables import get_frogpilot_toggles fp_toggles = get_frogpilot_toggles() acceleration_offset = float(np.clip(fp_toggles.stop_distance - v_ego, 1, distance_factor)) self.acceleration_jerk /= acceleration_offset self.speed_jerk /= acceleration_offset self.t_follow /= acceleration_offset # Offset by FrogAi for FrogPilot for a more natural approach to a slower lead if (frogpilot_toggles.conditional_slower_lead or frogpilot_toggles.human_following) and v_lead < v_ego: distance_factor = max(lead_distance - (v_lead * self.t_follow), 1) braking_offset = float(np.clip(min(v_ego - v_lead, v_lead) - COMFORT_BRAKE, 1, distance_factor)) if frogpilot_toggles.human_following: from frogpilot.common.frogpilot_variables import get_frogpilot_toggles fp_toggles = get_frogpilot_toggles() far_lead_offset = max(lead_distance - (v_ego * self.t_follow) - fp_toggles.stop_distance, 0) self.t_follow /= braking_offset + far_lead_offset self.slower_lead = braking_offset > 1