diff --git a/opendbc_repo/opendbc/car/car_helpers.py b/opendbc_repo/opendbc/car/car_helpers.py index dffc5e75b..e6526b0ba 100644 --- a/opendbc_repo/opendbc/car/car_helpers.py +++ b/opendbc_repo/opendbc/car/car_helpers.py @@ -334,6 +334,9 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip CP.carFw = car_fw CP.fingerprintSource = source CP.fuzzyFingerprint = not exact_match + post_fingerprint_params = getattr(CarInterface, "apply_post_fingerprint_params", None) + if post_fingerprint_params is not None: + post_fingerprint_params(CP, candidate, fingerprints, car_fw) FPCP: StarPilotCarParams = CarInterface.get_starpilot_params(candidate, fingerprints, car_fw, CP, starpilot_toggles) diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py index cc294f6f1..a4f2a521e 100644 --- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -8,7 +8,8 @@ from opendbc.car.lateral import apply_driver_steer_torque_limits, apply_steer_an from opendbc.car.common.conversions import Conversions as CV from opendbc.car.hyundai import hyundaicanfd, hyundaican from opendbc.car.hyundai.hyundaicanfd import CanBus -from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR, CANFD_RADAR_LIVE_LONGITUDINAL_CAR +from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR, CANFD_RADAR_LIVE_LONGITUDINAL_CAR, \ + kia_ev6_gt_line_longitudinal_tuning from opendbc.car.interfaces import CarControllerBase from opendbc.car.vehicle_model import VehicleModel from openpilot.common.params import Params @@ -65,6 +66,11 @@ REDNECK_BUTTON_COPIES_TIME_METRIC = [REDNECK_BUTTON_COPIES_TIME, 40] ANGLE_SAFETY_BASELINE_MODEL = str(CAR.KIA_SPORTAGE_HEV_2026) +def egmp_dynamic_longitudinal_tuning(CP) -> bool: + return CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 or \ + kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, getattr(CP, "carVin", "")) + + @dataclass class Ioniq6LongitudinalTuningState: desired_accel: float = 0.0 @@ -426,22 +432,22 @@ class CarController(CarControllerBase): # longitudinal messages - stock ECU is still active and these would conflict self.long_active_ecu = self.CP.openpilotLongitudinalControl and not self.ecu_disable_failed - use_ioniq_6_dynamic_long_tuning = self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.long_active_ecu and \ - actuators.longControlState in (LongCtrlState.starting, LongCtrlState.pid, LongCtrlState.stopping) - if use_ioniq_6_dynamic_long_tuning and self.frame % 5 == 0: + use_egmp_dynamic_long_tuning = egmp_dynamic_longitudinal_tuning(self.CP) and self.long_active_ecu and \ + actuators.longControlState in (LongCtrlState.starting, LongCtrlState.pid, LongCtrlState.stopping) + if use_egmp_dynamic_long_tuning and self.frame % 5 == 0: self._ioniq_6_long_tuning = update_ioniq_6_longitudinal_tuning(self._ioniq_6_long_tuning, accel_cmd, CS.out.vEgo, CS.out.aEgo, actuators.longControlState, self.long_active_ecu) - use_ioniq_6_smoothed_accel = use_ioniq_6_dynamic_long_tuning and ( + use_egmp_smoothed_accel = use_egmp_dynamic_long_tuning and ( accel_cmd >= self._ioniq_6_long_tuning.actual_accel or self._ioniq_6_long_tuning.launch_active or self._ioniq_6_long_tuning.stopping ) - if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.long_active_ecu: - if use_ioniq_6_smoothed_accel: + if use_egmp_dynamic_long_tuning: + if use_egmp_smoothed_accel: accel = self._ioniq_6_long_tuning.actual_accel stopping = self._ioniq_6_long_tuning.stopping - elif use_ioniq_6_dynamic_long_tuning: + else: accel = float(np.clip(accel_cmd, self.accel_last - IONIQ_6_CANFD_SCC_DECEL_STEP, self.accel_last + IONIQ_6_CANFD_SCC_ACCEL_STEP)) @@ -566,9 +572,13 @@ class CarController(CarControllerBase): lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING lka_steering_long = lka_steering and self.long_active_ecu ccnc_non_hda2 = self.CP.flags & HyundaiFlags.CCNC and not lka_steering - use_ioniq_6_dynamic_long_tuning = self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.long_active_ecu and \ - CC.actuators.longControlState == LongCtrlState.pid - use_ioniq_6_smoothed_accel = use_ioniq_6_dynamic_long_tuning and CC.actuators.accel >= self._ioniq_6_long_tuning.actual_accel + use_egmp_dynamic_long_tuning = egmp_dynamic_longitudinal_tuning(self.CP) and self.long_active_ecu and \ + CC.actuators.longControlState in (LongCtrlState.starting, LongCtrlState.pid, LongCtrlState.stopping) + use_egmp_smoothed_accel = use_egmp_dynamic_long_tuning and ( + CC.actuators.accel >= self._ioniq_6_long_tuning.actual_accel or + self._ioniq_6_long_tuning.launch_active or + self._ioniq_6_long_tuning.stopping + ) # steering control preserve_stock_lkas = bool(self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING) and not self.long_active_ecu @@ -656,8 +666,8 @@ class CarController(CarControllerBase): "lead_rel_speed": lead_rel_speed, "lead_visible": lead_visible, } - if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6: - if use_ioniq_6_smoothed_accel: + if use_egmp_dynamic_long_tuning: + if use_egmp_smoothed_accel: acc_kwargs["jerk_lower"] = self._ioniq_6_long_tuning.jerk_lower acc_kwargs["jerk_upper"] = self._ioniq_6_long_tuning.jerk_upper can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override, diff --git a/opendbc_repo/opendbc/car/hyundai/interface.py b/opendbc_repo/opendbc/car/hyundai/interface.py index bff4ae638..797c6ee0e 100644 --- a/opendbc_repo/opendbc/car/hyundai/interface.py +++ b/opendbc_repo/opendbc/car/hyundai/interface.py @@ -9,7 +9,8 @@ from opendbc.car.hyundai.values import HyundaiFlags, CAR, CarControllerParams, \ UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags, \ LEGACY_LONGITUDINAL_CAR, \ HyundaiStarPilotSafetyFlags, \ - hyundai_cancel_button_enables_cruise + hyundai_cancel_button_enables_cruise, \ + kia_ev6_gt_line_longitudinal_tuning from opendbc.car.hyundai.radar_interface import get_radar_track_config, radar_tracks_available from opendbc.car.interfaces import CarInterfaceBase, ACCEL_MIN from opendbc.car.disable_ecu import disable_ecu, ecu_log @@ -40,6 +41,12 @@ def apply_platform_longitudinal_params(ret: structs.CarParams) -> None: ret.stoppingDecelRate = 0.4 +def apply_kia_ev6_gt_line_longitudinal_params(ret: structs.CarParams) -> None: + ret.startAccel = 1.4 + ret.longitudinalActuatorDelay = 0.35 + ret.vEgoStarting = 0.5 + + def apply_ecu_disable_failure_fallback(CP: structs.CarParams, params) -> None: params.put_bool("EcuDisableFailed", True) CP.safetyConfigs[-1].safetyParam &= ~HyundaiSafetyFlags.LONG.value @@ -68,6 +75,11 @@ class CarInterface(CarInterfaceBase): def get_pid_accel_limits(CP, current_speed, cruise_speed): return ACCEL_MIN, CarControllerParams.ACCEL_MAX + @staticmethod + def apply_post_fingerprint_params(CP: structs.CarParams, candidate, fingerprint, car_fw) -> None: + if kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, CP.carVin): + apply_kia_ev6_gt_line_longitudinal_params(CP) + @staticmethod def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: ret.brand = "hyundai" diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index ecec704f4..bbdcbdf69 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -9,7 +9,7 @@ from opendbc.car.structs import CarControl, CarParams from opendbc.car.fw_versions import build_fw_dict, match_fw_to_car from opendbc.car.hyundai.carcontroller import CarController, Ioniq6LongitudinalTuningState, GenesisG90LongitudinalTuningState, \ update_ioniq_6_longitudinal_tuning, \ - update_genesis_g90_longitudinal_tuning + update_genesis_g90_longitudinal_tuning, egmp_dynamic_longitudinal_tuning from opendbc.car.hyundai.carstate import CarState, decode_canfd_camera_lead, decode_ioniq_6_blindspot_radar_state from opendbc.car.hyundai.interface import CarInterface from opendbc.car.hyundai import hyundaican, hyundaicanfd @@ -20,7 +20,7 @@ from opendbc.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR HYBRID_CAR, EV_CAR, FW_QUERY_CONFIG, LEGACY_SAFETY_MODE_CAR, CANFD_FUZZY_WHITELIST, \ UNSUPPORTED_LONGITUDINAL_CAR, PLATFORM_CODE_ECUS, HYUNDAI_VERSION_REQUEST_LONG, \ LEGACY_LONGITUDINAL_CAR, CarControllerParams, DBC, HyundaiFlags, get_platform_codes, HyundaiSafetyFlags, \ - HyundaiStarPilotSafetyFlags, Buttons + HyundaiStarPilotSafetyFlags, Buttons, kia_ev6_gt_line_longitudinal_tuning LongCtrlState = CarControl.Actuators.LongControlState from opendbc.car.hyundai.fingerprints import FW_VERSIONS @@ -527,6 +527,34 @@ class TestHyundaiFingerprint: assert CP.longitudinalActuatorDelay == pytest.approx(0.5) assert CP.startingState + def test_kia_ev6_gt_line_post_fingerprint_longitudinal_params(self): + toggles = get_test_toggles() + CP = CarInterface.get_params(CAR.KIA_EV6, gen_empty_fingerprint(), [], True, False, False, toggles) + CP.carVin = "KNDC4DLC0P0000000" + + CarInterface.apply_post_fingerprint_params(CP, CAR.KIA_EV6, gen_empty_fingerprint(), []) + + assert CP.startAccel == pytest.approx(1.4) + assert CP.vEgoStarting == pytest.approx(0.5) + assert CP.longitudinalActuatorDelay == pytest.approx(0.35) + assert CP.vEgoStopping == pytest.approx(0.3) + assert CP.stoppingDecelRate == pytest.approx(0.4) + assert kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, CP.carVin) + assert egmp_dynamic_longitudinal_tuning(CP) + + def test_kia_ev6_non_gt_line_keeps_family_longitudinal_params(self): + toggles = get_test_toggles() + CP = CarInterface.get_params(CAR.KIA_EV6, gen_empty_fingerprint(), [], True, False, False, toggles) + CP.carVin = "KNDC3DLC0P0000000" + + CarInterface.apply_post_fingerprint_params(CP, CAR.KIA_EV6, gen_empty_fingerprint(), []) + + assert CP.startAccel == pytest.approx(1.0) + assert CP.vEgoStarting == pytest.approx(0.1) + assert CP.longitudinalActuatorDelay == pytest.approx(0.5) + assert not kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, CP.carVin) + assert not egmp_dynamic_longitudinal_tuning(CP) + def test_genesis_g90_longitudinal_params_bias_toward_earlier_stop_handoff(self): toggles = get_test_toggles() CP = CarInterface.get_params(CAR.GENESIS_G90, gen_empty_fingerprint(), [], True, False, False, toggles) diff --git a/opendbc_repo/opendbc/car/hyundai/values.py b/opendbc_repo/opendbc/car/hyundai/values.py index aee2bad65..f68f77cf0 100644 --- a/opendbc_repo/opendbc/car/hyundai/values.py +++ b/opendbc_repo/opendbc/car/hyundai/values.py @@ -914,6 +914,10 @@ CANCEL_BUTTON_ENABLE_CARS = frozenset({ CAR.HYUNDAI_PALISADE_2023, }) +KIA_EV6_GT_LINE_LONG_TUNING_VDS_PREFIXES = frozenset({ + "C4DLC", +}) + # These classic HKG platforms publish the LKAS button on CLU13 over the alt bus. # Keep G90 excluded until its alt-bus path is route-proven without the recent @@ -933,6 +937,11 @@ def hyundai_cancel_button_enables_cruise(car_fingerprint) -> bool: return car_fingerprint in CANCEL_BUTTON_ENABLE_CARS +def kia_ev6_gt_line_longitudinal_tuning(car_fingerprint, vin: str) -> bool: + return car_fingerprint == CAR.KIA_EV6 and isinstance(vin, str) and \ + len(vin) == 17 and vin[3:8] in KIA_EV6_GT_LINE_LONG_TUNING_VDS_PREFIXES + + def get_platform_codes(fw_versions: list[bytes]) -> set[tuple[bytes, bytes | None]]: # Returns unique, platform-specific identification codes for a set of versions codes = set() # (code-Optional[part], date)