diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 4f42a933c..6f525598d 100644 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -179,27 +179,69 @@ class CarInterface(CarInterfaceBase): is_bolt_2022_2023_pedal = candidate == CAR.CHEVROLET_BOLT_CC_2022_2023 and ret.enableGasInterceptor - if candidate in (CAMERA_ACC_CAR | SDGM_CAR | ASCM_INT) or candidate == CAR.CHEVROLET_VOLT_CAMERA: - ret.experimentalLongitudinalAvailable = candidate not in (CC_ONLY_CAR | ASCM_INT | SDGM_CAR) or has_sascm(fingerprint) + is_camera_acc = candidate in CAMERA_ACC_CAR and candidate not in CC_ONLY_CAR and candidate not in kaofui_cars + if is_camera_acc: + # TorqueTune camera-ACC behavior + ret.experimentalLongitudinalAvailable = (candidate not in CC_ONLY_CAR) and not ret.enableGasInterceptor + ret.networkLocation = NetworkLocation.fwdCamera + ret.pcmCruise = not ret.enableGasInterceptor + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM + ret.minEnableSpeed = 5 * CV.KPH_TO_MS + ret.minSteerSpeed = 10 * CV.KPH_TO_MS + + # Tuning for experimental long + ret.longitudinalTuning.kiV = [0.5, 0.5, 0.5] + ret.vEgoStopping = 0.1 + ret.vEgoStarting = 0.1 + + ret.stoppingDecelRate = 1.0 # reach brake quickly after enabling + ret.vEgoStopping = 0.25 + ret.vEgoStarting = 0.25 + ret.stopAccel = -0.25 + + if ret.experimentalLongitudinalAvailable and experimental_long: + ret.pcmCruise = False + ret.openpilotLongitudinalControl = True + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM_LONG + elif candidate in SDGM_CAR: + ret.experimentalLongitudinalAvailable = candidate not in CC_ONLY_CAR or has_sascm(fingerprint) + ret.networkLocation = NetworkLocation.fwdCamera + ret.radarUnavailable = 0x460 not in fingerprint.get(CanBus.OBSTACLE, {}) + ret.pcmCruise = True + ret.minEnableSpeed = -1. # engage speed is decided by pcm + ret.minSteerSpeed = 7 * CV.MPH_TO_MS + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_SDGM + # Use C9 brake bit only on SDGM variants that lack 0xBE (ECMAcceleratorPos) + if ACCELERATOR_POS_MSG not in fingerprint.get(CanBus.POWERTRAIN, {}): + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_FORCE_BRAKE_C9 + ret.flags |= GMFlags.FORCE_BRAKE_C9.value + + # Tuning for experimental long + ret.longitudinalTuning.kiV = [0.5, 0.5] if candidate in kaofui_cars else [0.5, 0.5, 0.5] + ret.vEgoStopping = 0.1 + ret.vEgoStarting = 0.1 + + ret.stoppingDecelRate = 1.0 # reach brake quickly after enabling + ret.vEgoStopping = 0.25 + ret.vEgoStarting = 0.25 + ret.stopAccel = -0.25 + + if ret.experimentalLongitudinalAvailable and experimental_long: + ret.pcmCruise = False + ret.openpilotLongitudinalControl = True + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM_LONG + if is_bolt_2022_2023_pedal: + ret.experimentalLongitudinalAvailable = False + ret.pcmCruise = False + elif candidate in ASCM_INT: + ret.experimentalLongitudinalAvailable = candidate not in CC_ONLY_CAR or has_sascm(fingerprint) ret.networkLocation = NetworkLocation.fwdCamera ret.radarUnavailable = 0x460 not in fingerprint.get(CanBus.OBSTACLE, {}) ret.pcmCruise = True ret.minEnableSpeed = 5 * CV.KPH_TO_MS - ret.minSteerSpeed = 10 * CV.KPH_TO_MS - if candidate in SDGM_CAR: - gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_SDGM - # Use C9 brake bit only on SDGM variants that lack 0xBE (ECMAcceleratorPos) - if ACCELERATOR_POS_MSG not in fingerprint.get(CanBus.POWERTRAIN, {}): - gm_safety_cfg.safetyParam |= Panda.FLAG_GM_FORCE_BRAKE_C9 - ret.flags |= GMFlags.FORCE_BRAKE_C9.value - ret.minEnableSpeed = -1. # engage speed is decided by pcm - ret.minSteerSpeed = 7 * CV.MPH_TO_MS - elif candidate in ASCM_INT: - gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM - ret.minSteerSpeed = 7 * CV.MPH_TO_MS - gm_safety_cfg.safetyParam |= Panda.FLAG_GM_ASCM_INT - else: - gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM + ret.minSteerSpeed = 7 * CV.MPH_TO_MS + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_HW_CAM + gm_safety_cfg.safetyParam |= Panda.FLAG_GM_ASCM_INT # Tuning for experimental long ret.longitudinalTuning.kiV = [0.5, 0.5] if candidate in kaofui_cars else [0.5, 0.5, 0.5] @@ -254,14 +296,17 @@ class CarInterface(CarInterfaceBase): ret.radarTimeStep = 0.0667 # GM radar runs at 15Hz instead of standard 20Hz ret.longitudinalActuatorDelay = 0.5 # large delay to initially start braking - if candidate in (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_CC, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA): + if candidate in (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_CC, CAR.CHEVROLET_VOLT_CAMERA): ret.minEnableSpeed = -1 - ret.lateralTuning.pid.kpBP = [0., 40.] - ret.lateralTuning.pid.kpV = [0., 0.17] - ret.lateralTuning.pid.kiBP = [0.] - ret.lateralTuning.pid.kiV = [0.] - ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt() + + if candidate == CAR.CHEVROLET_VOLT_2019 and not ret.openpilotLongitudinalControl: + ret.minEnableSpeed = -1 + + if candidate in VOLT_LIKE_CARS: + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) ret.steerActuatorDelay = 0.2 + if candidate == CAR.CHEVROLET_MALIBU_HYBRID_CC and ret.enableGasInterceptor: + ret.flags |= GMFlags.PEDAL_LONG.value elif candidate == CAR.GMC_ACADIA: ret.minEnableSpeed = -1. # engage speed is decided by pcm diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 3b635944f..d78f9abc4 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -58,33 +58,79 @@ class CarControllerParams: self.ZERO_GAS = 6150 # 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 = 8848 - 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. - self.BRAKE_SWITCH_MAX = self.MAX_ACC_REGEN if CP.carFingerprint in EV_CAR else self.ZERO_GAS + kaofui_cars = SDGM_CAR | ASCM_INT | { + CAR.CHEVROLET_VOLT, + CAR.CHEVROLET_VOLT_2019, + CAR.CHEVROLET_VOLT_ASCM, + CAR.CHEVROLET_VOLT_CAMERA, + CAR.CHEVROLET_VOLT_CC, + CAR.CHEVROLET_MALIBU_CC, + CAR.CHEVROLET_MALIBU_HYBRID_CC, + } + volt_like = { + CAR.CHEVROLET_VOLT, + CAR.CHEVROLET_VOLT_2019, + CAR.CHEVROLET_VOLT_ASCM, + CAR.CHEVROLET_VOLT_CAMERA, + CAR.CHEVROLET_VOLT_CC, + } - elif CP.carFingerprint in SDGM_CAR: - self.MAX_GAS = 8191 - self.MAX_GAS_PLUS = 8191 - self.MAX_ACC_REGEN = 5500 - self.INACTIVE_REGEN = 5500 - max_regen_acceleration = 0. - self.BRAKE_SWITCH_MAX = self.ZERO_GAS + if CP.carFingerprint in kaofui_cars: + if (CP.carFingerprint in (CAMERA_ACC_CAR | SDGM_CAR) and + CP.carFingerprint not in CC_ONLY_CAR and + CP.carFingerprint != CAR.CHEVROLET_BOLT_ACC_2022_2023): + self.MAX_GAS = 8848 + 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. + else: + self.MAX_GAS = 8191 # Safety limit, not ACC max. Stock ACC >8192 from standstill. + self.MAX_GAS_PLUS = 8191 + 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.BRAKE_SWITCH_MAX = self.MAX_ACC_REGEN if CP.carFingerprint in EV_CAR else self.ZERO_GAS + if CP.carFingerprint in volt_like: + self.BRAKE_LOOKUP_BP = [self.ACCEL_MIN, 0.] + else: + self.BRAKE_LOOKUP_BP = [self.ACCEL_MIN, max_regen_acceleration] else: - self.MAX_GAS = 7168 # Safety limit, not ACC max. Stock ACC >8192 from standstill. - self.MAX_GAS_PLUS = 7168 # 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 = -3. if CP.carFingerprint in EV_CAR else -0.1 - self.BRAKE_SWITCH_MAX = self.MAX_ACC_REGEN if CP.carFingerprint in EV_CAR else self.ZERO_GAS + if CP.carFingerprint in CAMERA_ACC_CAR and CP.carFingerprint not in CC_ONLY_CAR: + self.MAX_GAS = 8848 + 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. + self.BRAKE_SWITCH_MAX = self.MAX_ACC_REGEN if CP.carFingerprint in EV_CAR else self.ZERO_GAS + + elif CP.carFingerprint in SDGM_CAR: + self.MAX_GAS = 8191 + self.MAX_GAS_PLUS = 8191 + self.MAX_ACC_REGEN = 5500 + self.INACTIVE_REGEN = 5500 + max_regen_acceleration = 0. + self.BRAKE_SWITCH_MAX = self.ZERO_GAS + + else: + self.MAX_GAS = 7168 # Safety limit, not ACC max. Stock ACC >8192 from standstill. + self.MAX_GAS_PLUS = 7168 # 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 = -3. if CP.carFingerprint in EV_CAR else -0.1 + self.BRAKE_SWITCH_MAX = self.MAX_ACC_REGEN if CP.carFingerprint in EV_CAR else self.ZERO_GAS + + self.BRAKE_LOOKUP_BP = [self.ACCEL_MIN, 0.] self.max_regen_acceleration = max_regen_acceleration self.GAS_LOOKUP_BP = [self.max_regen_acceleration, 0., self.ACCEL_MAX] @@ -92,7 +138,6 @@ class CarControllerParams: 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, 0.] self.BRAKE_LOOKUP_V = [self.MAX_BRAKE, 0.] self.BRAKE_SWITCH_LOOKUP_BP = [0.5, 10]