From 068a48408921dcf6afca31a9eac4829a9da688cd Mon Sep 17 00:00:00 2001 From: FrogAi <91348155+FrogAi@users.noreply.github.com> Date: Sat, 29 Jun 2024 15:08:25 -0700 Subject: [PATCH] Controls - Longitudinal Tuning - Acceleration Profile Change the acceleration rate to be either sporty or eco-friendly. --- opendbc/gm_global_a_powertrain_generated.dbc | 3 +- panda/board/safety/safety_gm.h | 42 +++++++++++++++---- panda/board/safety/safety_honda.h | 25 +++++++++-- panda/board/safety/safety_hyundai.h | 16 ++++++- panda/board/safety/safety_toyota.h | 13 +++++- panda/board/safety/safety_volkswagen_mqb.h | 16 ++++++- panda/board/safety/safety_volkswagen_pq.h | 18 +++++++- panda/board/safety_declarations.h | 1 + selfdrive/car/card.py | 2 + selfdrive/car/ford/carcontroller.py | 5 ++- selfdrive/car/ford/values.py | 1 + selfdrive/car/gm/carcontroller.py | 10 ++++- selfdrive/car/gm/interface.py | 7 +++- selfdrive/car/gm/values.py | 27 +++++++----- selfdrive/car/honda/carcontroller.py | 5 ++- selfdrive/car/honda/interface.py | 12 ++++-- selfdrive/car/honda/values.py | 2 + selfdrive/car/hyundai/carcontroller.py | 5 ++- selfdrive/car/hyundai/values.py | 1 + selfdrive/car/interfaces.py | 8 +++- selfdrive/car/toyota/carcontroller.py | 5 ++- selfdrive/car/toyota/interface.py | 7 +++- selfdrive/car/toyota/values.py | 1 + selfdrive/car/volkswagen/carcontroller.py | 5 ++- selfdrive/car/volkswagen/values.py | 1 + selfdrive/controls/controlsd.py | 2 +- .../frogpilot/controls/frogpilot_planner.py | 20 ++++++++- 27 files changed, 212 insertions(+), 48 deletions(-) diff --git a/opendbc/gm_global_a_powertrain_generated.dbc b/opendbc/gm_global_a_powertrain_generated.dbc index 1c78dd7b0..3528e98d1 100644 --- a/opendbc/gm_global_a_powertrain_generated.dbc +++ b/opendbc/gm_global_a_powertrain_generated.dbc @@ -221,8 +221,7 @@ BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO - SG_ GasRegenAlwaysOne3 : 23|1@0+ (1,0) [0|1] "" NEO - SG_ GasRegenCmd : 22|12@0+ (1,0) [0|0] "" NEO + SG_ GasRegenCmd : 8|14@0+ (1,0) [0|0] "" NEO BO_ 717 ASCM_2CD: 5 K124_ASCM diff --git a/panda/board/safety/safety_gm.h b/panda/board/safety/safety_gm.h index c0aa8701d..c7ae19b7d 100644 --- a/panda/board/safety/safety_gm.h +++ b/panda/board/safety/safety_gm.h @@ -10,16 +10,30 @@ const SteeringLimits GM_STEERING_LIMITS = { }; const LongitudinalLimits GM_ASCM_LONG_LIMITS = { - .max_gas = 3072, - .min_gas = 1404, - .inactive_gas = 1404, + .max_gas = 7168, + .min_gas = 5500, + .inactive_gas = 5500, + .max_brake = 400, +}; + +const LongitudinalLimits GM_ASCM_LONG_LIMITS_SPORT = { + .max_gas = 8191, + .min_gas = 5500, + .inactive_gas = 5500, .max_brake = 400, }; const LongitudinalLimits GM_CAM_LONG_LIMITS = { - .max_gas = 3400, - .min_gas = 1514, - .inactive_gas = 1554, + .max_gas = 7496, + .min_gas = 5610, + .inactive_gas = 5650, + .max_brake = 400, +}; + +const LongitudinalLimits GM_CAM_LONG_LIMITS_SPORT = { + .max_gas = 8848, + .min_gas = 5610, + .inactive_gas = 5650, .max_brake = 400, }; @@ -229,7 +243,7 @@ static bool gm_tx_hook(const CANPacket_t *to_send) { // GAS/REGEN: safety check if (addr == 0x2CB) { bool apply = GET_BIT(to_send, 0U); - int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3); + int gas_regen = ((GET_BYTE(to_send, 1) & 0x1U) << 13) + ((GET_BYTE(to_send, 2) & 0xFFU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3); bool violation = false; // Allow apply bit in pre-enabled and overriding states @@ -286,6 +300,8 @@ static int gm_fwd_hook(int bus_num, int addr) { } static safety_config gm_init(uint16_t param) { + sport_mode = alternative_experience & ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX; + if GET_FLAG(param, GM_PARAM_HW_CAM) { gm_hw = GM_CAM; } else if GET_FLAG(param, GM_PARAM_HW_SDGM) { @@ -297,9 +313,17 @@ static safety_config gm_init(uint16_t param) { gm_force_ascm = GET_FLAG(param, GM_PARAM_HW_ASCM_LONG); if (gm_hw == GM_ASCM || gm_force_ascm) { - gm_long_limits = &GM_ASCM_LONG_LIMITS; + if (sport_mode) { + gm_long_limits = &GM_ASCM_LONG_LIMITS_SPORT; + } else { + gm_long_limits = &GM_ASCM_LONG_LIMITS; + } } else if ((gm_hw == GM_CAM) || (gm_hw == GM_SDGM)) { - gm_long_limits = &GM_CAM_LONG_LIMITS; + if (sport_mode) { + gm_long_limits = &GM_CAM_LONG_LIMITS_SPORT; + } else { + gm_long_limits = &GM_CAM_LONG_LIMITS; + } } else { } diff --git a/panda/board/safety/safety_honda.h b/panda/board/safety/safety_honda.h index 0e081e742..29cfedd37 100644 --- a/panda/board/safety/safety_honda.h +++ b/panda/board/safety/safety_honda.h @@ -19,6 +19,14 @@ const LongitudinalLimits HONDA_BOSCH_LONG_LIMITS = { .inactive_gas = -30000, }; +const LongitudinalLimits HONDA_BOSCH_LONG_LIMITS_SPORT = { + .max_accel = 400, // accel is used for brakes + .min_accel = -350, + + .max_gas = 2000, + .inactive_gas = -30000, +}; + const LongitudinalLimits HONDA_NIDEC_LONG_LIMITS = { .max_gas = 198, // 0xc6 .max_brake = 255, @@ -276,6 +284,8 @@ static void honda_rx_hook(const CANPacket_t *to_push) { } static bool honda_tx_hook(const CANPacket_t *to_send) { + sport_mode = alternative_experience & ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX; + bool tx = true; int addr = GET_ADDR(to_send); int bus = GET_BUS(to_send); @@ -319,8 +329,13 @@ static bool honda_tx_hook(const CANPacket_t *to_send) { gas = to_signed(gas, 16); bool violation = false; - violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); - violation |= longitudinal_gas_checks(gas, HONDA_BOSCH_LONG_LIMITS); + if (sport_mode) { + violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS_SPORT); + violation |= longitudinal_gas_checks(gas, HONDA_BOSCH_LONG_LIMITS_SPORT); + } else { + violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); + violation |= longitudinal_gas_checks(gas, HONDA_BOSCH_LONG_LIMITS); + } if (violation) { tx = false; } @@ -332,7 +347,11 @@ static bool honda_tx_hook(const CANPacket_t *to_send) { accel = to_signed(accel, 12); bool violation = false; - violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); + if (sport_mode) { + violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS_SPORT); + } else { + violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); + } if (violation) { tx = false; } diff --git a/panda/board/safety/safety_hyundai.h b/panda/board/safety/safety_hyundai.h index 5a324bff2..a849a87e1 100644 --- a/panda/board/safety/safety_hyundai.h +++ b/panda/board/safety/safety_hyundai.h @@ -25,6 +25,11 @@ const LongitudinalLimits HYUNDAI_LONG_LIMITS = { .min_accel = -350, // 1/100 m/s2 }; +const LongitudinalLimits HYUNDAI_LONG_LIMITS_SPORT = { + .max_accel = 400, // 1/100 m/s2 + .min_accel = -350, // 1/100 m/s2 +}; + const CanMsg HYUNDAI_TX_MSGS[] = { {0x340, 0, 8}, // LKAS11 Bus 0 {0x4F1, 0, 4}, // CLU11 Bus 0 @@ -215,6 +220,8 @@ static void hyundai_rx_hook(const CANPacket_t *to_push) { } static bool hyundai_tx_hook(const CANPacket_t *to_send) { + sport_mode = alternative_experience & ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX; + bool tx = true; int addr = GET_ADDR(to_send); @@ -239,8 +246,13 @@ static bool hyundai_tx_hook(const CANPacket_t *to_send) { bool violation = false; - violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS); - violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS); + if (sport_mode) { + violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS_SPORT); + violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS_SPORT); + } else { + violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS); + violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS); + } violation |= (aeb_decel_cmd != 0); violation |= aeb_req; diff --git a/panda/board/safety/safety_toyota.h b/panda/board/safety/safety_toyota.h index 0e9742c6a..538fc79a6 100644 --- a/panda/board/safety/safety_toyota.h +++ b/panda/board/safety/safety_toyota.h @@ -37,6 +37,11 @@ const LongitudinalLimits TOYOTA_LONG_LIMITS = { .min_accel = -3500, // -3.5 m/s2 }; +const LongitudinalLimits TOYOTA_LONG_LIMITS_SPORT = { + .max_accel = 4000, // 4.0 m/s2 + .min_accel = -3500, // -3.5 m/s2 +}; + // panda interceptor threshold needs to be equivalent to openpilot threshold to avoid controls mismatches // If thresholds are mismatched then it is possible for panda to see the gas fall and rise while openpilot is in the pre-enabled state // Threshold calculated from DBC gains: round((((15 + 75.555) / 0.159375) + ((15 + 151.111) / 0.159375)) / 2) = 805 @@ -233,6 +238,8 @@ static void toyota_rx_hook(const CANPacket_t *to_push) { } static bool toyota_tx_hook(const CANPacket_t *to_send) { + sport_mode = alternative_experience & ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX; + bool tx = true; int addr = GET_ADDR(to_send); int bus = GET_BUS(to_send); @@ -253,7 +260,11 @@ static bool toyota_tx_hook(const CANPacket_t *to_send) { desired_accel = to_signed(desired_accel, 16); bool violation = false; - violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + if (sport_mode) { + violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS_SPORT); + } else { + violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + } // only ACC messages that cancel are allowed when openpilot is not controlling longitudinal if (toyota_stock_longitudinal) { diff --git a/panda/board/safety/safety_volkswagen_mqb.h b/panda/board/safety/safety_volkswagen_mqb.h index d880a69a6..0a84342f5 100644 --- a/panda/board/safety/safety_volkswagen_mqb.h +++ b/panda/board/safety/safety_volkswagen_mqb.h @@ -20,6 +20,12 @@ const LongitudinalLimits VOLKSWAGEN_MQB_LONG_LIMITS = { .inactive_accel = 3010, // VW sends one increment above the max range when inactive }; +const LongitudinalLimits VOLKSWAGEN_MQB_LONG_LIMITS_SPORT = { + .max_accel = 4000, + .min_accel = -3500, + .inactive_accel = 3010, // VW sends one increment above the max range when inactive +}; + #define MSG_ESP_19 0x0B2 // RX from ABS, for wheel speeds #define MSG_LH_EPS_03 0x09F // RX from EPS, for driver steering torque #define MSG_ESP_05 0x106 // RX from ABS, for brake switch state @@ -197,6 +203,8 @@ static void volkswagen_mqb_rx_hook(const CANPacket_t *to_push) { } static bool volkswagen_mqb_tx_hook(const CANPacket_t *to_send) { + sport_mode = alternative_experience & ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX; + int addr = GET_ADDR(to_send); bool tx = true; @@ -234,7 +242,13 @@ static bool volkswagen_mqb_tx_hook(const CANPacket_t *to_send) { desired_accel = (((GET_BYTE(to_send, 7) << 3) | ((GET_BYTE(to_send, 6) & 0xE0U) >> 5)) * 5U) - 7220U; } - violation |= longitudinal_accel_checks(desired_accel, VOLKSWAGEN_MQB_LONG_LIMITS); + if (sport_mode) { + if (desired_accel != 0) { + violation |= longitudinal_accel_checks(desired_accel, VOLKSWAGEN_MQB_LONG_LIMITS_SPORT); + } + } else { + violation |= longitudinal_accel_checks(desired_accel, VOLKSWAGEN_MQB_LONG_LIMITS); + } if (violation) { tx = false; diff --git a/panda/board/safety/safety_volkswagen_pq.h b/panda/board/safety/safety_volkswagen_pq.h index de147cb58..c8838cf48 100644 --- a/panda/board/safety/safety_volkswagen_pq.h +++ b/panda/board/safety/safety_volkswagen_pq.h @@ -20,6 +20,12 @@ const LongitudinalLimits VOLKSWAGEN_PQ_LONG_LIMITS = { .inactive_accel = 3010, // VW sends one increment above the max range when inactive }; +const LongitudinalLimits VOLKSWAGEN_PQ_LONG_LIMITS_SPORT = { + .max_accel = 4000, + .min_accel = -3500, + .inactive_accel = 3010, // VW sends one increment above the max range when inactive +}; + #define MSG_LENKHILFE_3 0x0D0 // RX from EPS, for steering angle and driver steering torque #define MSG_HCA_1 0x0D2 // TX by OP, Heading Control Assist steering torque #define MSG_BREMSE_1 0x1A0 // RX from ABS, for ego speed @@ -170,6 +176,8 @@ static void volkswagen_pq_rx_hook(const CANPacket_t *to_push) { } static bool volkswagen_pq_tx_hook(const CANPacket_t *to_send) { + sport_mode = alternative_experience & ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX; + int addr = GET_ADDR(to_send); bool tx = true; @@ -198,8 +206,14 @@ static bool volkswagen_pq_tx_hook(const CANPacket_t *to_send) { // Signal: ACC_System.ACS_Sollbeschl (acceleration in m/s2, scale 0.005, offset -7.22) int desired_accel = ((((GET_BYTE(to_send, 4) & 0x7U) << 8) | GET_BYTE(to_send, 3)) * 5U) - 7220U; - if (longitudinal_accel_checks(desired_accel, VOLKSWAGEN_PQ_LONG_LIMITS)) { - tx = false; + if (sport_mode) { + if (longitudinal_accel_checks(desired_accel, VOLKSWAGEN_PQ_LONG_LIMITS_SPORT)) { + tx = false; + } + } else { + if (longitudinal_accel_checks(desired_accel, VOLKSWAGEN_PQ_LONG_LIMITS)) { + tx = false; + } } } diff --git a/panda/board/safety_declarations.h b/panda/board/safety_declarations.h index e9b5cbf55..0427d90aa 100644 --- a/panda/board/safety_declarations.h +++ b/panda/board/safety_declarations.h @@ -220,6 +220,7 @@ bool brake_pressed_prev = false; bool regen_braking = false; bool regen_braking_prev = false; bool cruise_engaged_prev = false; +bool sport_mode = false; struct sample_t vehicle_speed; bool vehicle_moving = false; bool acc_main_on = false; // referred to as "ACC off" in ISO 15622:2018 diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index eac4c8ded..4fa74b060 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -63,6 +63,8 @@ class Car: self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.ALWAYS_ON_LATERAL self.params.put_bool("AlwaysOnLateralSet", True) + self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX + openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle") controller_available = self.CI.CC is not None and openpilot_enabled_toggle and not self.CP.dashcamOnly diff --git a/selfdrive/car/ford/carcontroller.py b/selfdrive/car/ford/carcontroller.py index eddd804a6..c89ab953d 100644 --- a/selfdrive/car/ford/carcontroller.py +++ b/selfdrive/car/ford/carcontroller.py @@ -94,7 +94,10 @@ class CarController(CarControllerBase): # send acc msg at 50Hz if self.CP.openpilotLongitudinalControl and (self.frame % CarControllerParams.ACC_CONTROL_STEP) == 0: # Both gas and accel are in m/s^2, accel is used solely for braking - accel = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX) + if frogpilot_toggles.sport_plus: + accel = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX_PLUS) + else: + accel = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX) gas = accel if not CC.longActive or gas < CarControllerParams.MIN_GAS: gas = CarControllerParams.INACTIVE_GAS diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index b1868bfa9..c1bfa579a 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -33,6 +33,7 @@ class CarControllerParams: CURVATURE_ERROR = 0.002 # ~6 degrees at 10 m/s, ~10 degrees at 35 m/s ACCEL_MAX = 2.0 # m/s^2 max acceleration + ACCEL_MAX_PLUS = 4.0 # m/s^2 max acceleration ACCEL_MIN = -3.5 # m/s^2 max deceleration MIN_GAS = -0.5 INACTIVE_GAS = -5.0 diff --git a/selfdrive/car/gm/carcontroller.py b/selfdrive/car/gm/carcontroller.py index 40e4050a7..83b21f666 100644 --- a/selfdrive/car/gm/carcontroller.py +++ b/selfdrive/car/gm/carcontroller.py @@ -122,10 +122,16 @@ class CarController(CarControllerBase): # Normal operation if self.CP.carFingerprint in EV_CAR: self.params.update_ev_gas_brake_threshold(CS.out.vEgo) - self.apply_gas = int(round(interp(actuators.accel, self.params.EV_GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V))) + if frogpilot_toggles.sport_plus: + self.apply_gas = int(round(interp(actuators.accel, self.params.EV_GAS_LOOKUP_BP_PLUS, self.params.GAS_LOOKUP_V_PLUS))) + else: + self.apply_gas = int(round(interp(actuators.accel, self.params.EV_GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V))) self.apply_brake = int(round(interp(actuators.accel, self.params.EV_BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V))) else: - self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V))) + if frogpilot_toggles.sport_plus: + self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP_PLUS, self.params.GAS_LOOKUP_V_PLUS))) + else: + self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V))) self.apply_brake = int(round(interp(actuators.accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V))) # Don't allow any gas above inactive regen while stopping # FIXME: brakes aren't applied immediately when enabling at a stop diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 7d2ae5106..51bb2d3e6 100644 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -38,8 +38,11 @@ NEURAL_PARAMS_PATH = os.path.join(BASEDIR, 'selfdrive/car/torque_data/neural_ff_ class CarInterface(CarInterfaceBase): @staticmethod - def get_pid_accel_limits(CP, current_speed, cruise_speed): - return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX + def get_pid_accel_limits(CP, current_speed, cruise_speed, frogpilot_toggles): + if frogpilot_toggles.sport_plus: + return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX_PLUS + else: + return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX # Determined by iteratively plotting and minimizing error for f(angle, speed) = steer. @staticmethod diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index ebb950d55..d547b43d2 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -33,37 +33,43 @@ class CarControllerParams: # Our controller should still keep the 2 second average above # -3.5 m/s^2 as per planner limits ACCEL_MAX = 2. # m/s^2 + ACCEL_MAX_PLUS = 4. # m/s^2 ACCEL_MIN = -4. # m/s^2 def __init__(self, CP): # Gas/brake lookups - self.ZERO_GAS = 2048 # Coasting + self.ZERO_GAS = 6144 # Coasting self.MAX_BRAKE = 400 # ~ -4.0 m/s^2 with regen if CP.carFingerprint in CAMERA_ACC_CAR and CP.carFingerprint not in CC_ONLY_CAR: - self.MAX_GAS = 3400 - self.MAX_ACC_REGEN = 1514 - self.INACTIVE_REGEN = 1554 + self.MAX_GAS = 7496 + self.MAX_GAS_PLUS = 8848 + self.MAX_ACC_REGEN = 5610 + self.INACTIVE_REGEN = 5650 # Camera ACC vehicles have no regen while enabled. # Camera transitions to MAX_ACC_REGEN from ZERO_GAS and uses friction brakes instantly max_regen_acceleration = 0. elif CP.carFingerprint in SDGM_CAR: - self.MAX_GAS = 3400 - self.MAX_ACC_REGEN = 1514 - self.INACTIVE_REGEN = 1554 + self.MAX_GAS = 7496 + self.MAX_GAS_PLUS = 7496 + self.MAX_ACC_REGEN = 5610 + self.INACTIVE_REGEN = 5650 max_regen_acceleration = 0. else: - self.MAX_GAS = 3072 # Safety limit, not ACC max. Stock ACC >4096 from standstill. - self.MAX_ACC_REGEN = 1404 # Max ACC regen is slightly less than max paddle regen - self.INACTIVE_REGEN = 1404 + self.MAX_GAS = 7168 # Safety limit, not ACC max. Stock ACC >8192 from standstill. + self.MAX_GAS_PLUS = 8191 # 8292 uses new bit, possible but not tested. Matches Twilsonco tw-main max + self.MAX_ACC_REGEN = 5500 # Max ACC regen is slightly less than max paddle regen + self.INACTIVE_REGEN = 5500 # ICE has much less engine braking force compared to regen in EVs, # lower threshold removes some braking deadzone max_regen_acceleration = -1. if CP.carFingerprint in EV_CAR else -0.1 self.GAS_LOOKUP_BP = [max_regen_acceleration, 0., self.ACCEL_MAX] + self.GAS_LOOKUP_BP_PLUS = [max_regen_acceleration, 0., self.ACCEL_MAX_PLUS] self.GAS_LOOKUP_V = [self.MAX_ACC_REGEN, self.ZERO_GAS, self.MAX_GAS] + self.GAS_LOOKUP_V_PLUS = [self.MAX_ACC_REGEN, self.ZERO_GAS, self.MAX_GAS_PLUS] self.BRAKE_LOOKUP_BP = [self.ACCEL_MIN, max_regen_acceleration] self.BRAKE_LOOKUP_V = [self.MAX_BRAKE, 0.] @@ -77,6 +83,7 @@ class CarControllerParams: def update_ev_gas_brake_threshold(self, v_ego): gas_brake_threshold = interp(v_ego, self.EV_GAS_BRAKE_THRESHOLD_BP, self.EV_GAS_BRAKE_THRESHOLD_V) self.EV_GAS_LOOKUP_BP = [gas_brake_threshold, max(0., gas_brake_threshold), self.ACCEL_MAX] + self.EV_GAS_LOOKUP_BP_PLUS = [gas_brake_threshold, max(0., gas_brake_threshold), self.ACCEL_MAX_PLUS] self.EV_BRAKE_LOOKUP_BP = [self.ACCEL_MIN, gas_brake_threshold] diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py index 67f29b4c1..62afcf100 100644 --- a/selfdrive/car/honda/carcontroller.py +++ b/selfdrive/car/honda/carcontroller.py @@ -216,7 +216,10 @@ class CarController(CarControllerBase): ts = self.frame * DT_CTRL if self.CP.carFingerprint in HONDA_BOSCH: - self.accel = clip(accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX) + if frogpilot_toggles.sport_plus: + self.accel = clip(accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX_PLUS) + else: + self.accel = clip(accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX) self.gas = interp(accel, self.params.BOSCH_GAS_LOOKUP_BP, self.params.BOSCH_GAS_LOOKUP_V) stopping = actuators.longControlState == LongCtrlState.stopping diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 922ea0922..26fc97c4d 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -22,11 +22,17 @@ SETTINGS_BUTTONS_DICT = {CruiseSettings.DISTANCE: ButtonType.gapAdjustCruise, Cr class CarInterface(CarInterfaceBase): @staticmethod - def get_pid_accel_limits(CP, current_speed, cruise_speed): + def get_pid_accel_limits(CP, current_speed, cruise_speed, frogpilot_toggles): if CP.carFingerprint in HONDA_BOSCH: - return CarControllerParams.BOSCH_ACCEL_MIN, CarControllerParams.BOSCH_ACCEL_MAX + if frogpilot_toggles.sport_plus: + return CarControllerParams.BOSCH_ACCEL_MIN, CarControllerParams.BOSCH_ACCEL_MAX_PLUS + else: + return CarControllerParams.BOSCH_ACCEL_MIN, CarControllerParams.BOSCH_ACCEL_MAX elif CP.enableGasInterceptor: - return CarControllerParams.NIDEC_ACCEL_MIN, CarControllerParams.NIDEC_ACCEL_MAX + if frogpilot_toggles.sport_plus: + return CarControllerParams.NIDEC_ACCEL_MIN, CarControllerParams.NIDEC_ACCEL_MAX_PLUS + else: + return CarControllerParams.NIDEC_ACCEL_MIN, CarControllerParams.NIDEC_ACCEL_MAX else: # NIDECs don't allow acceleration near cruise_speed, # so limit limits of pid to prevent windup diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index 7c2e3d8b3..3410e495a 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -20,6 +20,7 @@ class CarControllerParams: # -3.5 m/s^2 as per planner limits NIDEC_ACCEL_MIN = -4.0 # m/s^2 NIDEC_ACCEL_MAX = 1.6 # m/s^2, lower than 2.0 m/s^2 for tuning reasons + NIDEC_ACCEL_MAX_PLUS = 4.0 # m/s^2 NIDEC_ACCEL_LOOKUP_BP = [-1., 0., .6] NIDEC_ACCEL_LOOKUP_V = [-4.8, 0., 2.0] @@ -32,6 +33,7 @@ class CarControllerParams: BOSCH_ACCEL_MIN = -3.5 # m/s^2 BOSCH_ACCEL_MAX = 2.0 # m/s^2 + BOSCH_ACCEL_MAX_PLUS = 4.0 # m/s^2 BOSCH_GAS_LOOKUP_BP = [-0.2, 2.0] # 2m/s^2 BOSCH_GAS_LOOKUP_V = [0, 1600] diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py index 61417cc62..9ffbaa848 100644 --- a/selfdrive/car/hyundai/carcontroller.py +++ b/selfdrive/car/hyundai/carcontroller.py @@ -79,7 +79,10 @@ class CarController(CarControllerBase): self.apply_steer_last = apply_steer # accel + longitudinal - accel = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX) + if frogpilot_toggles.sport_plus: + accel = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX_PLUS) + else: + accel = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX) stopping = actuators.longControlState == LongCtrlState.stopping set_speed_in_units = hud_control.setSpeed * (CV.MS_TO_KPH if CS.is_metric else CV.MS_TO_MPH) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 3d9a8fc9d..8587141b1 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -15,6 +15,7 @@ Ecu = car.CarParams.Ecu class CarControllerParams: ACCEL_MIN = -3.5 # m/s ACCEL_MAX = 2.0 # m/s + ACCEL_MAX_PLUS = 4.0 # m/s def __init__(self, CP): self.STEER_DELTA_UP = 3 diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index f51064886..ed88ecffe 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -29,6 +29,7 @@ EventName = car.CarEvent.EventName MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS ACCEL_MAX = 2.0 +ACCEL_MAX_PLUS = 4.0 ACCEL_MIN = -3.5 FRICTION_THRESHOLD = 0.3 @@ -261,8 +262,11 @@ class CarInterfaceBase(ABC): return self.CC.update(c, self.CS, now_nanos, frogpilot_toggles) @staticmethod - def get_pid_accel_limits(CP, current_speed, cruise_speed): - return ACCEL_MIN, ACCEL_MAX + def get_pid_accel_limits(CP, current_speed, cruise_speed, frogpilot_toggles): + if frogpilot_toggles.sport_plus: + return ACCEL_MIN, ACCEL_MAX_PLUS + else: + return ACCEL_MIN, ACCEL_MAX @classmethod def get_non_essential_params(cls, candidate: str): diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py index 283af5f33..a6d216923 100644 --- a/selfdrive/car/toyota/carcontroller.py +++ b/selfdrive/car/toyota/carcontroller.py @@ -121,7 +121,10 @@ class CarController(CarControllerBase): interceptor_gas_cmd = 0.12 if CS.out.standstill else 0. else: interceptor_gas_cmd = 0. - pcm_accel_cmd = clip(actuators.accel, self.params.ACCEL_MIN, self.params.ACCEL_MAX) + if frogpilot_toggles.sport_plus: + pcm_accel_cmd = clip(actuators.accel, self.params.ACCEL_MIN, self.params.ACCEL_MAX_PLUS) + else: + pcm_accel_cmd = clip(actuators.accel, self.params.ACCEL_MIN, self.params.ACCEL_MAX) # on entering standstill, send standstill request if CS.out.standstill and not self.last_standstill and (self.CP.carFingerprint not in NO_STOP_TIMER_CAR or self.CP.enableGasInterceptor): diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index f03f8de5e..17120f308 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -15,8 +15,11 @@ SteerControlType = car.CarParams.SteerControlType class CarInterface(CarInterfaceBase): @staticmethod - def get_pid_accel_limits(CP, current_speed, cruise_speed): - return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX + def get_pid_accel_limits(CP, current_speed, cruise_speed, frogpilot_toggles): + if frogpilot_toggles.sport_plus: + return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX_PLUS + else: + return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX @staticmethod def _get_params(ret, params, candidate, fingerprint, car_fw, experimental_long, docs): diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index b441e6f72..06feac6c8 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -17,6 +17,7 @@ PEDAL_TRANSITION = 10. * CV.MPH_TO_MS class CarControllerParams: ACCEL_MAX = 1.5 # m/s2, lower than allowed 2.0 m/s2 for tuning reasons + ACCEL_MAX_PLUS = 4.0 # m/s2 ACCEL_MIN = -3.5 # m/s2 STEER_STEP = 1 diff --git a/selfdrive/car/volkswagen/carcontroller.py b/selfdrive/car/volkswagen/carcontroller.py index 045498fb6..fe659b1ba 100644 --- a/selfdrive/car/volkswagen/carcontroller.py +++ b/selfdrive/car/volkswagen/carcontroller.py @@ -80,7 +80,10 @@ class CarController(CarControllerBase): if self.frame % self.CCP.ACC_CONTROL_STEP == 0 and self.CP.openpilotLongitudinalControl: acc_control = self.CCS.acc_control_value(CS.out.cruiseState.available, CS.out.accFaulted, CC.longActive) - accel = clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX) if CC.longActive else 0 + if frogpilot_toggles.sport_plus: + accel = clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX_PLUS) if CC.longActive else 0 + else: + accel = clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX) if CC.longActive else 0 stopping = actuators.longControlState == LongCtrlState.stopping starting = actuators.longControlState == LongCtrlState.pid and (CS.esp_hold_confirmation or CS.out.vEgo < self.CP.vEgoStopping) can_sends.extend(self.CCS.create_acc_accel_control(self.packer_pt, CANBUS.pt, CS.acc_type, CC.longActive, accel, diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 8b58769b3..d0be20a49 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -37,6 +37,7 @@ class CarControllerParams: DEFAULT_MIN_STEER_SPEED = 0.4 # m/s, newer EPS racks fault below this speed, don't show a low speed alert ACCEL_MAX = 2.0 # 2.0 m/s max acceleration + ACCEL_MAX_PLUS = 4.0 # 4.0 m/s max acceleration ACCEL_MIN = -3.5 # 3.5 m/s max deceleration def __init__(self, CP): diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index c19c5d7ee..b06b23dff 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -603,7 +603,7 @@ class Controls: if not self.joystick_mode: # accel PID loop - pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, self.v_cruise_helper.v_cruise_kph * CV.KPH_TO_MS) + pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, self.v_cruise_helper.v_cruise_kph * CV.KPH_TO_MS, self.frogpilot_toggles) actuators.accel = self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits) if len(long_plan.speeds): diff --git a/selfdrive/frogpilot/controls/frogpilot_planner.py b/selfdrive/frogpilot/controls/frogpilot_planner.py index a38c14b27..ba1004b85 100644 --- a/selfdrive/frogpilot/controls/frogpilot_planner.py +++ b/selfdrive/frogpilot/controls/frogpilot_planner.py @@ -18,6 +18,17 @@ from openpilot.selfdrive.frogpilot.controls.lib.conditional_experimental_mode im from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_functions import calculate_lane_width, calculate_road_curvature from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_variables import CITY_SPEED_LIMIT, CRUISING_SPEED, TRAJECTORY_SIZE + # MPH = [ 0., 11, 22, 34, 45, 56, 89] +A_CRUISE_MAX_BP_CUSTOM = [ 0., 5., 10., 15., 20., 25., 40.] +A_CRUISE_MAX_VALS_ECO = [1.4, 1.2, 1.0, 0.8, 0.6, 0.4, 0.2] +A_CRUISE_MAX_VALS_SPORT = [4.0, 3.0, 2.0, 1.0, 0.9, 0.8, 0.6] + +def get_max_accel_eco(v_ego): + return interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_ECO) + +def get_max_accel_sport(v_ego): + return interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT) + class FrogPilotPlanner: def __init__(self): self.params_memory = Params("/dev/shm/params") @@ -69,11 +80,18 @@ class FrogPilotPlanner: self.update_v_cruise(carState, controlsState, frogpilotCarState, frogpilotNavigation, modelData, v_cruise, v_ego, frogpilot_toggles) def set_acceleration(self, controlsState, frogpilotCarState, v_cruise, v_ego, frogpilot_toggles): - if controlsState.experimentalMode: + if frogpilot_toggles.acceleration_profile == 1: + self.max_accel = get_max_accel_eco(v_ego) + elif frogpilot_toggles.acceleration_profile in (2, 3): + self.max_accel = get_max_accel_sport(v_ego) + elif controlsState.experimentalMode: self.max_accel = ACCEL_MAX else: self.max_accel = get_max_accel(v_ego) + if not self.tracking_lead: + self.max_accel = float(min(self.max_accel, self.max_accel * (self.v_cruise / CITY_SPEED_LIMIT))) + if controlsState.experimentalMode: self.min_accel = ACCEL_MIN else: