diff --git a/opendbc_repo/opendbc/car/docs.py b/opendbc_repo/opendbc/car/docs.py index 901b889d5..b10476303 100755 --- a/opendbc_repo/opendbc/car/docs.py +++ b/opendbc_repo/opendbc/car/docs.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse import os +from types import SimpleNamespace from typing import get_args from collections import defaultdict @@ -32,7 +33,8 @@ def get_params_for_docs(platform) -> CarParams: cp_platform = platform if platform in interfaces else MOCK.MOCK CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(), car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)], - alpha_long=True, is_release=False, docs=True) + alpha_long=True, is_release=False, docs=True, + starpilot_toggles=SimpleNamespace()) return CP diff --git a/opendbc_repo/opendbc/car/docs_definitions.py b/opendbc_repo/opendbc/car/docs_definitions.py index adb974d28..53d0c3191 100644 --- a/opendbc_repo/opendbc/car/docs_definitions.py +++ b/opendbc_repo/opendbc/car/docs_definitions.py @@ -131,6 +131,7 @@ class CarHarness(EnumBase): hyundai_p = BaseCarHarness("Hyundai P connector") hyundai_q = BaseCarHarness("Hyundai Q connector") hyundai_r = BaseCarHarness("Hyundai R connector") + hyundai_s = BaseCarHarness("Hyundai S connector") custom = BaseCarHarness("Developer connector") obd_ii = BaseCarHarness("OBD-II connector", parts=[Cable.long_obdc_cable, Cable.usbc_coupler], has_connector=False) gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box]) diff --git a/opendbc_repo/opendbc/car/fingerprints.py b/opendbc_repo/opendbc/car/fingerprints.py index 2eefbd0ca..25150d1c3 100644 --- a/opendbc_repo/opendbc/car/fingerprints.py +++ b/opendbc_repo/opendbc/car/fingerprints.py @@ -193,29 +193,43 @@ MIGRATION = { "HYUNDAI IONIQ PLUG-IN HYBRID 2019": HYUNDAI.HYUNDAI_IONIQ_PHEV_2019, "HYUNDAI IONIQ PHEV 2020": HYUNDAI.HYUNDAI_IONIQ_PHEV, "HYUNDAI KONA 2020": HYUNDAI.HYUNDAI_KONA, + "HYUNDAI KONA 2ND GEN": HYUNDAI.HYUNDAI_KONA_2ND_GEN, "HYUNDAI KONA ELECTRIC 2019": HYUNDAI.HYUNDAI_KONA_EV, "HYUNDAI KONA ELECTRIC 2022": HYUNDAI.HYUNDAI_KONA_EV_2022, "HYUNDAI KONA ELECTRIC 2ND GEN": HYUNDAI.HYUNDAI_KONA_EV_2ND_GEN, "HYUNDAI KONA HYBRID 2020": HYUNDAI.HYUNDAI_KONA_HEV, + "HYUNDAI KONA HYBRID 2ND GEN": HYUNDAI.HYUNDAI_KONA_HEV_2ND_GEN, "HYUNDAI SANTA FE 2019": HYUNDAI.HYUNDAI_SANTA_FE, "HYUNDAI SANTA FE 2022": HYUNDAI.HYUNDAI_SANTA_FE_2022, "HYUNDAI SANTA FE HYBRID 2022": HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022, + "HYUNDAI SANTA FE HYBRID 5TH GEN": HYUNDAI.HYUNDAI_SANTA_FE_HEV_5TH_GEN, "HYUNDAI SANTA FE PlUG-IN HYBRID 2022": HYUNDAI.HYUNDAI_SANTA_FE_PHEV_2022, "HYUNDAI SONATA 2020": HYUNDAI.HYUNDAI_SONATA, + "HYUNDAI SONATA 2024": HYUNDAI.HYUNDAI_SONATA_2024, "HYUNDAI SONATA 2019": HYUNDAI.HYUNDAI_SONATA_LF, "HYUNDAI STARIA 4TH GEN": HYUNDAI.HYUNDAI_STARIA_4TH_GEN, "HYUNDAI TUCSON 2019": HYUNDAI.HYUNDAI_TUCSON, + "HYUNDAI TUCSON 2025": HYUNDAI.HYUNDAI_TUCSON_2025, + "HYUNDAI TUCSON HYBRID 2025": HYUNDAI.HYUNDAI_TUCSON_HEV_2025, + "HYUNDAI TUCSON PLUG-IN HYBRID 2025": HYUNDAI.HYUNDAI_TUCSON_PHEV_2025, "HYUNDAI PALISADE 2020": HYUNDAI.HYUNDAI_PALISADE, "HYUNDAI PALISADE 2023": HYUNDAI.HYUNDAI_PALISADE_2023, "HYUNDAI VELOSTER 2019": HYUNDAI.HYUNDAI_VELOSTER, "HYUNDAI SONATA HYBRID 2021": HYUNDAI.HYUNDAI_SONATA_HYBRID, + "HYUNDAI SONATA HYBRID 2024": HYUNDAI.HYUNDAI_SONATA_HEV_2024, "HYUNDAI IONIQ 5 2022": HYUNDAI.HYUNDAI_IONIQ_5, + "HYUNDAI IONIQ 5 2025": HYUNDAI.HYUNDAI_IONIQ_5_PE, + "HYUNDAI IONIQ 5 N 2024": HYUNDAI.HYUNDAI_IONIQ_5_N, "HYUNDAI IONIQ 6 2023": HYUNDAI.HYUNDAI_IONIQ_6, + "HYUNDAI IONIQ 9 2025": HYUNDAI.HYUNDAI_IONIQ_9, "HYUNDAI TUCSON 4TH GEN": HYUNDAI.HYUNDAI_TUCSON_4TH_GEN, "HYUNDAI SANTA CRUZ 1ST GEN": HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN, + "HYUNDAI SANTA CRUZ 2025": HYUNDAI.HYUNDAI_SANTA_CRUZ_2025, "HYUNDAI CUSTIN 1ST GEN": HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN, "KIA FORTE E 2018 & GT 2021": HYUNDAI.KIA_FORTE, + "KIA K4 2025": HYUNDAI.KIA_K4_2025, "KIA K5 2021": HYUNDAI.KIA_K5_2021, + "KIA K5 2025": HYUNDAI.KIA_K5_2025, "KIA K5 HYBRID 2020": HYUNDAI.KIA_K5_HEV_2020, "KIA K8 HYBRID 1ST GEN": HYUNDAI.KIA_K8_HEV_1ST_GEN, "KIA NIRO EV 2020": HYUNDAI.KIA_NIRO_EV, @@ -230,22 +244,29 @@ MIGRATION = { "KIA OPTIMA HYBRID 4TH GEN FACELIFT": HYUNDAI.KIA_OPTIMA_H_G4_FL, "KIA SELTOS 2021": HYUNDAI.KIA_SELTOS, "KIA SPORTAGE 5TH GEN": HYUNDAI.KIA_SPORTAGE_5TH_GEN, + "KIA SPORTAGE 2026": HYUNDAI.KIA_SPORTAGE_2026, "KIA SPORTAGE HYBRID 2026": HYUNDAI.KIA_SPORTAGE_HEV_2026, "KIA SORENTO GT LINE 2018": HYUNDAI.KIA_SORENTO, "KIA SORENTO 4TH GEN": HYUNDAI.KIA_SORENTO_4TH_GEN, + "KIA SORENTO 2024": HYUNDAI.KIA_SORENTO_2024, "KIA SORENTO HYBRID 4TH GEN": HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, + "KIA SORENTO HYBRID 4TH GEN LFA2": HYUNDAI.KIA_SORENTO_HEV_4TH_GEN_LFA2, "KIA STINGER GT2 2018": HYUNDAI.KIA_STINGER, "KIA STINGER 2022": HYUNDAI.KIA_STINGER_2022, "KIA CEED INTRO ED 2019": HYUNDAI.KIA_CEED, "KIA EV6 2022": HYUNDAI.KIA_EV6, + "KIA EV6 2025": HYUNDAI.KIA_EV6_2025, + "KIA EV9 2025": HYUNDAI.KIA_EV9, "KIA CARNIVAL 4TH GEN": HYUNDAI.KIA_CARNIVAL_4TH_GEN, "GENESIS GV60 ELECTRIC 1ST GEN": HYUNDAI.GENESIS_GV60_EV_1ST_GEN, "GENESIS G70 2018": HYUNDAI.GENESIS_G70, "GENESIS G70 2020": HYUNDAI.GENESIS_G70_2020, "GENESIS GV70 1ST GEN": HYUNDAI.GENESIS_GV70_1ST_GEN, + "GENESIS GV70 ELECTRIFIED 2026": HYUNDAI.GENESIS_GV70_ELECTRIFIED_2ND_GEN, "GENESIS G80 2017": HYUNDAI.GENESIS_G80, "GENESIS G90 2017": HYUNDAI.GENESIS_G90, "GENESIS GV80 2023": HYUNDAI.GENESIS_GV80, + "GENESIS GV80 2025": HYUNDAI.GENESIS_GV80_2025, "MAZDA CX-5": MAZDA.MAZDA_CX5, "MAZDA CX-9": MAZDA.MAZDA_CX9, "MAZDA 3": MAZDA.MAZDA_3, diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py index d4b4b1397..0f0485fa1 100644 --- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -527,6 +527,7 @@ 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 @@ -546,8 +547,13 @@ class CarController(CarControllerBase): # LFA and HDA icons if self.frame % 5 == 0 and (not lka_steering or lka_steering_long): - can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CS.stock_lfahda_cluster_msg, - lfa_icon=lfa_icon)) + if ccnc_non_hda2: + can_sends.extend(hyundaicanfd.create_ccnc(self.packer, self.CAN, self.long_active_ecu, CC.enabled, CC.hudControl, + CC.leftBlinker, CC.rightBlinker, CS.msg_161, CS.msg_162, CS.msg_1b5, + CS.is_metric, CS.out, CS.out.cruiseState.available, lfa_icon)) + else: + can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CS.stock_lfahda_cluster_msg, + lfa_icon=lfa_icon)) # blinkers if lka_steering and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS: @@ -577,7 +583,7 @@ class CarController(CarControllerBase): if self.long_active_ecu: if lka_steering: can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame)) - else: + elif not ccnc_non_hda2: can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame)) if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.frame % 5 == 0: rear_stale = now_nanos - CS.blindspots_rear_corners_ts > CANFD_BLINDSPOT_STATUS_STALE_NS @@ -612,7 +618,8 @@ class CarController(CarControllerBase): 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, - set_speed_in_units, hud_control, **acc_kwargs)) + set_speed_in_units, hud_control, cruise_info=CS.cruise_info if ccnc_non_hda2 else None, + **acc_kwargs)) self.accel_last = accel else: # button presses diff --git a/opendbc_repo/opendbc/car/hyundai/carstate.py b/opendbc_repo/opendbc/car/hyundai/carstate.py index 0f12f8362..2a9ea8860 100644 --- a/opendbc_repo/opendbc/car/hyundai/carstate.py +++ b/opendbc_repo/opendbc/car/hyundai/carstate.py @@ -7,7 +7,7 @@ from opendbc.can import CANDefine, CANParser from opendbc.car import Bus, create_button_events, structs from opendbc.car.common.conversions import Conversions as CV from opendbc.car.hyundai.hyundaicanfd import CanBus -from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, CAR, DBC, Buttons, CarControllerParams, \ +from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, HyundaiStarPilotSafetyFlags, CAR, DBC, Buttons, CarControllerParams, \ hyundai_cancel_button_enables_cruise from opendbc.car.interfaces import CarStateBase @@ -108,6 +108,9 @@ class CarState(CarStateBase): self.buttons_counter = 0 self.cruise_info = {} + self.msg_161 = {} + self.msg_162 = {} + self.msg_1b5 = {} self.msg_364 = {} self.stock_lkas_msg = {} self.stock_lfa_msg = {} @@ -306,7 +309,7 @@ class CarState(CarStateBase): prev_lda_button = self.lda_button self.cruise_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwState"]) self.main_buttons.extend(cp.vl_all["CLU11"]["CF_Clu_CruiseSwMain"]) - if self.CP.flags & HyundaiFlags.HAS_LDA_BUTTON: + if self.FPCP.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON: self.lda_button = cp.vl["BCM_PO_11"]["LDA_BTN"] ret.buttonEvents = [*self.create_cruise_button_events(self.cruise_buttons[-1], prev_cruise_buttons), @@ -365,8 +368,16 @@ class CarState(CarStateBase): ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5) ret.steerFaultTemporary = cp.vl["MDPS"]["LKA_FAULT"] != 0 - left_blinker_sig, right_blinker_sig = self.get_canfd_blinker_sig_names(self.CP.carFingerprint, - cp.vl["BLINKERS"]["USE_ALT_LAMP"] == 1) + ccnc_non_hda2 = self.CP.flags & HyundaiFlags.CCNC and not self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING + if ccnc_non_hda2: + self.msg_161 = copy.copy(cp_cam.vl["CCNC_0x161"]) + self.msg_162 = copy.copy(cp_cam.vl["CCNC_0x162"]) + self.msg_1b5 = copy.copy(cp_cam.vl["FR_CMR_03_50ms"]) + cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp + self.cruise_info = copy.copy(cp_cruise_info.vl["SCC_CONTROL"]) + + use_alt_lamp = cp.vl["BLINKERS"]["USE_ALT_LAMP"] == 1 or bool(self.CP.flags & HyundaiFlags.CCNC) + left_blinker_sig, right_blinker_sig = self.get_canfd_blinker_sig_names(self.CP.carFingerprint, use_alt_lamp) ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig], cp.vl["BLINKERS"][right_blinker_sig]) self.left_blindspot_from_radar = False @@ -380,6 +391,9 @@ class CarState(CarStateBase): self.left_blindspot_from_radar) ret.rightBlindspot = (bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_RtIndSta"]) or self.right_blindspot_from_radar) + elif self.CP.flags & HyundaiFlags.CCNC: + ret.leftBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_LtIndSta"]) + ret.rightBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_RtIndSta"]) else: ret.leftBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_LtIndSta"]) ret.rightBlindspot = bool(cp.vl["BLINDSPOTS_REAR_CORNERS"]["BCW_RtIndSta"]) @@ -487,6 +501,11 @@ class CarState(CarStateBase): else: cam_msgs.append(("FR_CMR_02_100ms", 0)) # optional: not all non-LKA CANFD cars have this on CAM bus cam_msgs.append(("FR_CMR_03_50ms", 0)) # optional: camera lead/cipv data is not present on every CAN-FD trim + if CP.flags & HyundaiFlags.CCNC: + cam_msgs += [ + ("CCNC_0x161", 0), + ("CCNC_0x162", 0), + ] msgs += [ ("LFA", 0), # optional: may stop once OP takes over, but preserve stock UI fields when present ("LFAHDA_CLUSTER", 0), # optional: carries cluster icon state on some variants diff --git a/opendbc_repo/opendbc/car/hyundai/fingerprints.py b/opendbc_repo/opendbc/car/hyundai/fingerprints.py index 7a6462177..05d6305dd 100644 --- a/opendbc_repo/opendbc/car/hyundai/fingerprints.py +++ b/opendbc_repo/opendbc/car/hyundai/fingerprints.py @@ -741,6 +741,27 @@ FW_VERSIONS = { ], (Ecu.fwdCamera, 0x7c4, None): [ b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410', + b'\xf1\x00SX2EMFC AT USA LHD 1.00 1.02 99211-BF000 230823', + ], + }, + CAR.HYUNDAI_KONA_2ND_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.03 99211-BE000 230517', + b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.07 99211-BE000 240611', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ', + b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ', + ], + }, + CAR.HYUNDAI_KONA_HEV_2ND_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00SX2HMFC AT AUS RHD 1.00 1.00 99211-BE001 241015', + b'\xf1\x00SX2HMFC AT EUR RHD 1.00 1.04 99211-BE000 231010', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ', + b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ', ], }, CAR.KIA_NIRO_EV: { @@ -1159,6 +1180,186 @@ FW_VERSIONS = { b'\xf1\x00NQ5__ 1.00 1.04 99110CH100 ', ], }, + CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00MX5HMFC AT CAN LHD 1.00 1.07 99211-P6000 231218', + b'\xf1\x00MX5HMFC AT KOR LHD 1.00 1.07 99211-P6000 231218', + b'\xf1\x00MX5HMFC AT USA LHD 1.00 1.06 99211-R6000 231218', + b'\xf1\x00MX5HMFC AT USA LHD 1.00 1.09 99211-R6200 250519', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MX5_ RDR ----- 1.00 1.01 99110-P6000 ', + b'\xf1\x00MX5_ RDR ----- 1.00 1.01 99110-R6000 ', + ], + }, + CAR.HYUNDAI_SONATA_2024: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.01 99211-L1800 230512', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.01 99211-L1800 230512', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ', + ], + }, + CAR.HYUNDAI_SONATA_HEV_2024: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DN8HMFC AT KOR LHD 1.00 1.01 99211-L1800 230512', + b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.01 99211-L1800 230512', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ', + ], + }, + CAR.HYUNDAI_IONIQ_5_PE: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NE__ RDR ----- 1.00 1.00 99110-PI000 ', + b'\xf1\x00NE__ RDR ----- 1.00 1.01 99110-GI500 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NE MFC AT USA LHD 1.00 1.01 99211-PI000 240905', + b'\xf1\x00NE MFC AT EUR LHD 1.00 1.03 99211-GI500 240809', + b'\xf1\x00NE MFC AT USA LHD 1.00 1.00 99211-PI010 250407', + b'\xf1\x00NE MFC AT EUR LHD 1.00 1.00 99211-GI510 250513', + ], + }, + CAR.HYUNDAI_IONIQ_5_N: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NE1N RDR ----- 1.00 1.00 99110-NI000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.04 99211-NI000 231219', + b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.00 99211-NI010 240712', + b'\xf1\x00NE1NMFC AT USA LHD 1.00 1.04 99211-NI000 231219', + ], + }, + CAR.HYUNDAI_IONIQ_9: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MEev RDR ----- 1.00 1.00 99110-GO000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00ME MFC AT KOR LHD 1.00 1.00 99211-GO000 241007', + b'\xf1\x00ME MFC AT KOR LHD 1.00 1.01 99211-GO000 250103', + ], + }, + CAR.HYUNDAI_TUCSON_2025: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N7050 C5A', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ', + ], + }, + CAR.HYUNDAI_TUCSON_HEV_2025: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55', + b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N7030 C55', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NX4__ 1.00 1.02 99110N7000 ', + b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ', + b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ', + ], + }, + CAR.HYUNDAI_TUCSON_PHEV_2025: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N7030 C55', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ', + ], + }, + CAR.HYUNDAI_SANTA_CRUZ_2025: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NX4__ 1.00 1.00 99110K5500 ', + ], + }, + CAR.KIA_K4_2025: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CL4 MFC AT CAN LHD 1.00 1.02 99210-GG000 240708', + b'\xf1\x00CL4 MFC AT USA LHD 1.00 1.02 99210-GG000 240708', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG000 ', + b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG100 ', + ], + }, + CAR.KIA_K5_2025: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.04 99210-L2500 240117', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DL3_ RDR ----- 1.00 1.01 99110-L2500 ', + ], + }, + CAR.KIA_SPORTAGE_2026: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NQ51.011.021.012551000HKP_NQ524_50509099211P1110', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NQ5__ 1.00 1.04 99110P1100 ', + ], + }, + CAR.KIA_SORENTO_2024: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00MQ4 MFC AT AUS RHD 1.01 1.04 99210-P2550 231127', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-P2500 ', + ], + }, + CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.00 99210-P2600 250617', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-P2500 ', + ], + }, + CAR.KIA_EV6_2025: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CV__ RDR ----- 1.00 1.00 99110-XG500 ', + b'\xf1\x00CV__ RDR ----- 1.00 1.01 99110-CV500 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CV MFC AT KOR LHD 1.00 1.01 99210-CV500 240405', + b'\xf1\x00CV MFC AT USA LHD 1.00 1.02 99210-XG500 241223', + ], + }, + CAR.KIA_EV9: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MV__ RDR ----- 1.00 1.02 99110-DO000 ', + b'\xf1\x00MV__ RDR ----- 1.00 1.03 99110-DO000 ', + b'\xf1\x00MV__ RDR ----- 1.00 1.04 99110-DO000 ', + b'\xf1\x00MV__ RDR ----- 1.00 1.02 99110-DO700 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00MV MFC AT KOR LHD 1.00 1.01 99211-DO000 230419', + b'\xf1\x00MV MFC AT USA LHD 1.00 1.02 99211-DO000 230616', + b'\xf1\x00MV MFC AT EUR LHD 1.00 1.02 99211-DO000 230616', + b'\xf1\x00MV MFC AT CAN LHD 1.00 1.00 99211-DO100 240403', + b'\xf1\x00MV MFC AT USA LHD 1.00 1.01 99211-XA000 241023', + b'\xf1\x00MV MFC AT CAN LHD 1.00 1.01 99211-DO100 241023', + ], + }, + CAR.GENESIS_GV70_ELECTRIFIED_2ND_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JK MFC AT USA LHD 1.00 1.03 99211-DS600 241125', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JK__ RDR ----- 1.00 1.01 99110-DS500 ', + ], + }, + CAR.GENESIS_GV80_2025: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JX__ RDR ----- 1.00 1.03 99110-T6500 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JX MFC AT USA LHD 1.00 1.03 99211-T6510 240124', + ], + }, CAR.GENESIS_GV70_1ST_GEN: { (Ecu.fwdCamera, 0x7c4, None): [ b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.02 99211-IY000 230627', diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py index 7f15a3696..48c84c6ba 100644 --- a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py +++ b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py @@ -1,6 +1,7 @@ import copy import numpy as np from opendbc.car import CanBusBase, CanData +from opendbc.car.common.conversions import Conversions as CV from opendbc.car.crc import CRC16_XMODEM from opendbc.car.hyundai.values import HyundaiFlags @@ -219,6 +220,102 @@ def create_lfahda_cluster(packer, CAN, enabled, base_values=None, lfa_icon=None) return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values) +def create_ccnc(packer, CAN, openpilot_longitudinal, enabled, hud, left_blinker, right_blinker, msg_161, msg_162, msg_1b5, + is_metric, out, main_cruise_enabled, lfa_icon): + for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS"): + msg_162[fault] = 0 + + if msg_161["ALERTS_2"] == 5: + msg_161.update({"ALERTS_2": 0, "SOUNDS_2": 0}) + if msg_161["ALERTS_3"] == 17: + msg_161["ALERTS_3"] = 0 + if msg_161["ALERTS_5"] in (2, 5): + msg_161["ALERTS_5"] = 0 + if msg_161["SOUNDS_4"] == 2 and msg_161["LFA_ICON"] in (3, 0): + msg_161["SOUNDS_4"] = 0 + + lane_change_speed_min = 8.9408 + any_blinker = left_blinker or right_blinker + curvature = {i: (31 if i == -1 else 13 - abs(i + 15)) if i < 0 else 15 + i for i in range(-15, 16)} + + msg_161.update({ + "DAW_ICON": 0, + "LKA_ICON": 0, + "LFA_ICON": 2 if lfa_icon else 0, + "CENTERLINE": 1 if lfa_icon else 0, + "LANELINE_CURVATURE": curvature.get(max(-15, min(int(out.steeringAngleDeg / 4.5), 15)), 14) if lfa_icon and not any_blinker else 15, + "LANELINE_LEFT": 0 if not lfa_icon else 1 if not hud.leftLaneVisible else 4 if hud.leftLaneDepart else 6 if any_blinker else 2, + "LANELINE_RIGHT": 0 if not lfa_icon else 1 if not hud.rightLaneVisible else 4 if hud.rightLaneDepart else 6 if any_blinker else 2, + "LCA_LEFT_ICON": 0 if not lfa_icon or out.vEgo < lane_change_speed_min else 1 if out.leftBlindspot else 2 if any_blinker else 4, + "LCA_RIGHT_ICON": 0 if not lfa_icon or out.vEgo < lane_change_speed_min else 1 if out.rightBlindspot else 2 if any_blinker else 4, + "LCA_LEFT_ARROW": 2 if left_blinker else 0, + "LCA_RIGHT_ARROW": 2 if right_blinker else 0, + }) + + if lfa_icon and any_blinker: + left_lane_raw = msg_1b5["Info_LftLnPosVal"] + right_lane_raw = msg_1b5["Info_RtLnPosVal"] + scale_per_m = 15 / 1.7 + left_lane = abs(int(round(15 + (left_lane_raw - 1.7) * scale_per_m))) + right_lane = abs(int(round(15 + (right_lane_raw - 1.7) * scale_per_m))) + + if msg_1b5["Info_LftLnQualSta"] not in (2, 3): + left_lane = 0 + if msg_1b5["Info_RtLnQualSta"] not in (2, 3): + right_lane = 0 + + if left_lane_raw == -2.0248375: + left_lane = 30 - right_lane + if right_lane_raw == 2.0248375: + right_lane = 30 - left_lane + + if left_lane_raw == right_lane_raw == 0: + left_lane = right_lane = 15 + elif left_lane_raw == 0: + left_lane = 30 - right_lane + elif right_lane_raw == 0: + right_lane = 30 - left_lane + + total = left_lane + right_lane + if total == 0: + left_lane = right_lane = 15 + else: + left_lane = round((left_lane / total) * 30) + right_lane = 30 - left_lane + + msg_161["LANELINE_LEFT_POSITION"] = left_lane + msg_161["LANELINE_RIGHT_POSITION"] = right_lane + + if hud.leftLaneDepart or hud.rightLaneDepart: + msg_162["VIBRATE"] = 1 + + if openpilot_longitudinal: + if msg_161["ALERTS_3"] in (1, 2, 3, 4, 7, 8, 9, 10): + msg_161["ALERTS_3"] = 0 + if msg_161["ALERTS_5"] == 4: + msg_161["ALERTS_5"] = 0 + if msg_161["SOUNDS_3"] == 5: + msg_161["SOUNDS_3"] = 0 + + cruise_speed = round(out.vCruiseCluster * (1 if is_metric else CV.KPH_TO_MPH)) + msg_161.update({ + "SETSPEED": 3 if enabled else 1, + "SETSPEED_HUD": 0 if not main_cruise_enabled else 2 if enabled else 1, + "SETSPEED_SPEED": 255 if not main_cruise_enabled else (40 if is_metric else 25) if cruise_speed > (145 if is_metric else 90) else cruise_speed, + "DISTANCE": hud.leadDistanceBars, + "DISTANCE_SPACING": 0 if not main_cruise_enabled else 1 if enabled else 3, + "DISTANCE_LEAD": 0 if not main_cruise_enabled else 2 if enabled and hud.leadVisible else 1 if hud.leadVisible else 0, + "DISTANCE_CAR": 0 if not main_cruise_enabled else 2 if enabled else 1, + "SLA_ICON": 0, + "NAV_ICON": 0, + "TARGET": 0, + }) + msg_162["LEAD"] = 0 if not main_cruise_enabled else 2 if enabled else 1 + msg_162["LEAD_DISTANCE"] = msg_1b5["Longitudinal_Distance"] + + return [packer.make_can_msg(msg, CAN.ECAN, values) for msg, values in (("CCNC_0x161", msg_161), ("CCNC_0x162", msg_162))] + + def create_blindspot_status_messages(packer, CAN, rear_values, front_corner_values, left_blindspot=False, right_blindspot=False, left_blinker=False, right_blinker=False): @@ -463,7 +560,7 @@ def create_ioniq_6_cluster_lane_change_messages(CAN, frame, side=None): def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control, main_mode_acc=1, jerk_lower=None, jerk_upper=None, direct_accel=False, - lead_distance=None, lead_rel_speed=None, lead_visible=None): + lead_distance=None, lead_rel_speed=None, lead_visible=None, cruise_info=None): jerk = 5 jn = jerk / 50 if not enabled or gas_override: @@ -506,6 +603,8 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov "SET_ME_TMP_64": 0x64, "DISTANCE_SETTING": hud_control.leadDistanceBars, } + if cruise_info: + values.update({s: cruise_info[s] for s in ("ACC_ObjDist", "ACC_ObjRelSpd")}) return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values) diff --git a/opendbc_repo/opendbc/car/hyundai/interface.py b/opendbc_repo/opendbc/car/hyundai/interface.py index 97d14a64f..eb614c60d 100644 --- a/opendbc_repo/opendbc/car/hyundai/interface.py +++ b/opendbc_repo/opendbc/car/hyundai/interface.py @@ -70,6 +70,9 @@ class CarInterface(CarInterfaceBase): # this needs to be figured out for cars without an ADAS ECU # Cars in CANFD_SECURITYACCESS_CAR are known to have ADAS ECUs that work with SecurityAccess ret.alphaLongitudinalAvailable = False + if lka_steering and ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING: + # Angle-steering LKA platforms still need stock longitudinal validation. + ret.alphaLongitudinalAvailable = False ret.enableBsm = 0x1ba in fingerprint[CAN.ECAN] @@ -115,6 +118,8 @@ class CarInterface(CarInterfaceBase): if ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING: ret.steerControlType = structs.CarParams.SteerControlType.angle ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ANGLE_STEERING.value + if ret.flags & HyundaiFlags.CCNC and not ret.flags & HyundaiFlags.CANFD_LKA_STEERING: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CCNC.value else: # Shared configuration for non CAN-FD cars @@ -139,8 +144,6 @@ class CarInterface(CarInterfaceBase): ret.safetyConfigs[0].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value # These cars have the LFA button on the steering wheel - if 0x391 in fingerprint[0] or ret.flags & HyundaiFlags.CAN_CANFD_BLENDED: - ret.flags |= HyundaiFlags.HAS_LDA_BUTTON.value if ret.flags & HyundaiFlags.CAN_CANFD_BLENDED: ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAN_CANFD_BLENDED.value if hyundai_cancel_button_enables_cruise(candidate): diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index 5db2844cd..ed5ec6c21 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -32,7 +32,12 @@ NO_DATES_PLATFORMS = { CAR.KIA_SPORTAGE_5TH_GEN, CAR.KIA_SPORTAGE_HEV_2026, CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN, + CAR.HYUNDAI_SANTA_CRUZ_2025, CAR.HYUNDAI_TUCSON_4TH_GEN, + CAR.HYUNDAI_TUCSON_2025, + CAR.HYUNDAI_TUCSON_HEV_2025, + CAR.HYUNDAI_TUCSON_PHEV_2025, + CAR.KIA_SPORTAGE_2026, # CAN CAR.HYUNDAI_ELANTRA, CAR.HYUNDAI_ELANTRA_GT_I30, @@ -65,6 +70,37 @@ HYUNDAI_NON_SCC_CARS = ( ) HYUNDAI_NON_SCC_FW_CARS = tuple(car_model for car_model in HYUNDAI_NON_SCC_CARS if car_model in FW_VERSIONS) +CCNC_NON_HDA2_CARS = ( + CAR.HYUNDAI_KONA_2ND_GEN, + CAR.HYUNDAI_KONA_HEV_2ND_GEN, + CAR.HYUNDAI_KONA_EV_2ND_GEN, + CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN, + CAR.HYUNDAI_SONATA_2024, + CAR.HYUNDAI_SONATA_HEV_2024, + CAR.HYUNDAI_IONIQ_5_N, + CAR.HYUNDAI_TUCSON_2025, + CAR.HYUNDAI_TUCSON_HEV_2025, + CAR.HYUNDAI_TUCSON_PHEV_2025, + CAR.HYUNDAI_SANTA_CRUZ_2025, + CAR.KIA_K4_2025, + CAR.KIA_K5_2025, + CAR.KIA_SPORTAGE_2026, + CAR.KIA_SORENTO_2024, +) + +ANGLE_STEERING_CARS = ( + CAR.HYUNDAI_SANTA_FE_HEV_5TH_GEN, + CAR.HYUNDAI_IONIQ_5_PE, + CAR.HYUNDAI_IONIQ_9, + CAR.KIA_SPORTAGE_2026, + CAR.KIA_SPORTAGE_HEV_2026, + CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2, + CAR.KIA_EV6_2025, + CAR.KIA_EV9, + CAR.GENESIS_GV70_ELECTRIFIED_2ND_GEN, + CAR.GENESIS_GV80_2025, +) + def get_test_toggles() -> SimpleNamespace: return SimpleNamespace(always_on_lateral_lkas=False, force_torque_controller=False, nnff=False, nnff_lite=False) @@ -106,12 +142,42 @@ class TestHyundaiFingerprint: CP = CarInterface.get_params(CAR.KIA_SPORTAGE_HEV_2026, fingerprint, [], False, False, False, None) assert CP.flags & HyundaiFlags.SEND_LFA + @pytest.mark.parametrize("candidate", CCNC_NON_HDA2_CARS) + def test_ccnc_non_hda2_platforms_set_ccnc_safety(self, candidate): + CP = CarInterface.get_params(candidate, gen_empty_fingerprint(), [], False, False, False, None) + + assert CP.flags & HyundaiFlags.CCNC + assert CP.flags & HyundaiFlags.CANFD_CAMERA_SCC + assert not (CP.flags & HyundaiFlags.CANFD_LKA_STEERING) + assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CCNC + assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CAMERA_SCC + + @pytest.mark.parametrize("candidate", ANGLE_STEERING_CARS) + def test_angle_steering_platforms_use_angle_control(self, candidate): + CP = CarInterface.get_params(candidate, gen_empty_fingerprint(), [], False, False, False, None) + + assert CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING + assert CP.steerControlType == CarParams.SteerControlType.angle + assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CANFD_ANGLE_STEERING + + def test_ccnc_hda2_lka_layout_does_not_set_ccnc_safety_param(self): + fingerprint = gen_empty_fingerprint() + cam_can = CanBus(None, fingerprint).CAM + fingerprint[cam_can] = {0x50: 16} + + CP = CarInterface.get_params(CAR.KIA_K4_2025, fingerprint, [], False, False, False, None) + + assert CP.flags & HyundaiFlags.CCNC + assert CP.flags & HyundaiFlags.CANFD_LKA_STEERING + assert not (CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CCNC) + def test_ioniq_6_hda1_layout_stays_non_lka(self): fingerprint = gen_empty_fingerprint() fingerprint[1] = {0x100: 8, 0x110: 8} CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, fingerprint, [], False, False, False, None) + assert not (CP.flags & HyundaiFlags.CCNC) assert not (CP.flags & HyundaiFlags.CANFD_LKA_STEERING) assert bool(CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) @@ -604,6 +670,124 @@ class TestHyundaiFingerprint: assert parser.vl["SCC_CONTROL"]["ObjValid"] == 1 assert parser.vl["SCC_CONTROL"]["OBJ_STATUS"] == 0 + def test_canfd_acc_control_preserves_stock_ccnc_object_fields(self): + CP = CarParams.new_message() + CP.carFingerprint = CAR.HYUNDAI_SONATA_2024 + CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CCNC) + + packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) + can_bus = CanBus(CP) + parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("SCC_CONTROL", 0)], can_bus.ECAN) + + msg = hyundaicanfd.create_acc_control(packer, can_bus, enabled=True, accel_last=0.0, accel=0.1, stopping=False, + gas_override=False, set_speed=42, hud_control=SimpleNamespace(leadDistanceBars=3), + direct_accel=True, lead_distance=27.5, lead_rel_speed=-1.2, lead_visible=True, + cruise_info={"ACC_ObjDist": 13.5, "ACC_ObjRelSpd": -0.4}) + parser.update([(1, [msg])]) + + assert parser.can_valid + assert parser.vl["SCC_CONTROL"]["ACC_ObjDist"] == pytest.approx(13.5) + assert parser.vl["SCC_CONTROL"]["ACC_ObjRelSpd"] == pytest.approx(-0.4) + + def test_ccnc_hud_helper_clears_faults_and_generates_ui_fields(self): + CP = CarParams.new_message() + CP.carFingerprint = CAR.HYUNDAI_SONATA_2024 + CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CCNC) + CP.openpilotLongitudinalControl = True + + packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) + can_bus = CanBus(CP) + parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CCNC_0x161", 0), ("CCNC_0x162", 0)], can_bus.ECAN) + + msg_161 = { + "ALERTS_2": 5, + "ALERTS_3": 17, + "ALERTS_5": 5, + "SOUNDS_3": 5, + "SOUNDS_4": 2, + "LFA_ICON": 3, + } + msg_162 = {fault: 1 for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS")} + msg_162["VIBRATE"] = 0 + msg_1b5 = { + "Info_LftLnPosVal": 1.4, + "Info_RtLnPosVal": 1.9, + "Info_LftLnQualSta": 3, + "Info_RtLnQualSta": 3, + "Longitudinal_Distance": 42.0, + } + hud = SimpleNamespace(leftLaneVisible=True, rightLaneVisible=True, leftLaneDepart=True, rightLaneDepart=False, + leadDistanceBars=3, leadVisible=True) + out = SimpleNamespace(steeringAngleDeg=22.5, vEgo=15.0, leftBlindspot=True, rightBlindspot=False, + vCruiseCluster=88.0) + + msgs = hyundaicanfd.create_ccnc(packer, can_bus, openpilot_longitudinal=True, enabled=True, hud=hud, + left_blinker=False, right_blinker=False, msg_161=msg_161, msg_162=msg_162, + msg_1b5=msg_1b5, is_metric=False, out=out, main_cruise_enabled=True, lfa_icon=2) + parser.update([(1, msgs)]) + + assert parser.can_valid + assert parser.vl["CCNC_0x161"]["DAW_ICON"] == 0 + assert parser.vl["CCNC_0x161"]["LKA_ICON"] == 0 + assert parser.vl["CCNC_0x161"]["LFA_ICON"] == 2 + assert parser.vl["CCNC_0x161"]["CENTERLINE"] == 1 + assert parser.vl["CCNC_0x161"]["LANELINE_CURVATURE"] == 20 + assert parser.vl["CCNC_0x161"]["LANELINE_LEFT"] == 4 + assert parser.vl["CCNC_0x161"]["LANELINE_RIGHT"] == 2 + assert parser.vl["CCNC_0x161"]["LCA_LEFT_ICON"] == 1 + assert parser.vl["CCNC_0x161"]["LCA_RIGHT_ICON"] == 4 + assert parser.vl["CCNC_0x161"]["ALERTS_2"] == 0 + assert parser.vl["CCNC_0x161"]["ALERTS_3"] == 0 + assert parser.vl["CCNC_0x161"]["ALERTS_5"] == 0 + assert parser.vl["CCNC_0x161"]["SOUNDS_3"] == 0 + assert parser.vl["CCNC_0x161"]["SOUNDS_4"] == 0 + assert parser.vl["CCNC_0x161"]["SETSPEED"] == 3 + assert parser.vl["CCNC_0x161"]["SETSPEED_HUD"] == 2 + assert parser.vl["CCNC_0x161"]["SETSPEED_SPEED"] == 55 + assert parser.vl["CCNC_0x161"]["DISTANCE"] == 3 + assert parser.vl["CCNC_0x161"]["DISTANCE_LEAD"] == 2 + assert all(parser.vl["CCNC_0x162"][fault] == 0 for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS")) + assert parser.vl["CCNC_0x162"]["VIBRATE"] == 1 + assert parser.vl["CCNC_0x162"]["LEAD"] == 2 + assert parser.vl["CCNC_0x162"]["LEAD_DISTANCE"] == pytest.approx(42.0) + + def test_ccnc_hud_helper_generates_lane_position_animation_and_lca_arrows(self): + CP = CarParams.new_message() + CP.carFingerprint = CAR.HYUNDAI_SONATA_2024 + CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CCNC) + + packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) + can_bus = CanBus(CP) + parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CCNC_0x161", 0), ("CCNC_0x162", 0)], can_bus.ECAN) + hud = SimpleNamespace(leftLaneVisible=True, rightLaneVisible=True, leftLaneDepart=False, rightLaneDepart=False, + leadDistanceBars=1, leadVisible=False) + out = SimpleNamespace(steeringAngleDeg=0.0, vEgo=15.0, leftBlindspot=False, rightBlindspot=False, + vCruiseCluster=55.0) + msg_1b5 = { + "Info_LftLnPosVal": 1.4, + "Info_RtLnPosVal": 1.9, + "Info_LftLnQualSta": 3, + "Info_RtLnQualSta": 3, + "Longitudinal_Distance": 0.0, + } + + msgs = hyundaicanfd.create_ccnc(packer, can_bus, openpilot_longitudinal=False, enabled=True, hud=hud, + left_blinker=True, right_blinker=False, + msg_161={"ALERTS_2": 0, "ALERTS_3": 0, "ALERTS_5": 0, "SOUNDS_4": 0, "LFA_ICON": 2}, + msg_162={fault: 0 for fault in ("FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS")}, + msg_1b5=msg_1b5, is_metric=True, out=out, main_cruise_enabled=True, lfa_icon=2) + parser.update([(1, msgs)]) + + assert parser.can_valid + assert parser.vl["CCNC_0x161"]["LANELINE_CURVATURE"] == 15 + assert parser.vl["CCNC_0x161"]["LANELINE_LEFT"] == 6 + assert parser.vl["CCNC_0x161"]["LANELINE_RIGHT"] == 6 + assert parser.vl["CCNC_0x161"]["LCA_LEFT_ICON"] == 2 + assert parser.vl["CCNC_0x161"]["LCA_LEFT_ARROW"] == 2 + assert parser.vl["CCNC_0x161"]["LCA_RIGHT_ARROW"] == 0 + assert parser.vl["CCNC_0x161"]["LANELINE_LEFT_POSITION"] == 12 + assert parser.vl["CCNC_0x161"]["LANELINE_RIGHT_POSITION"] == 18 + def test_canfd_scc_lead_state_prefers_openpilot_lead_distance(self): CP = CarParams.new_message() CP.carFingerprint = CAR.KIA_EV6 @@ -1196,7 +1380,7 @@ class TestHyundaiFingerprint: # Hyundai places the ECU part number in their FW versions, assert all parsable # Some examples of valid formats: b"56310-L0010", b"56310L0010", b"56310/M6300" - if car_model != CAR.KIA_SPORTAGE_HEV_2026: + if car_model not in (CAR.KIA_SPORTAGE_2026, CAR.KIA_SPORTAGE_HEV_2026): assert all(b"-" in code for code, _ in codes), \ f"FW does not have part number: {fw}" diff --git a/opendbc_repo/opendbc/car/hyundai/values.py b/opendbc_repo/opendbc/car/hyundai/values.py index 7116bfda7..b5d992242 100644 --- a/opendbc_repo/opendbc/car/hyundai/values.py +++ b/opendbc_repo/opendbc/car/hyundai/values.py @@ -121,6 +121,7 @@ class HyundaiSafetyFlags(IntFlag): NON_SCC = 4096 CAN_CANFD_BLENDED = 8192 CANCEL_BTN_ENABLE = 16384 + CCNC = 32768 class HyundaiStarPilotSafetyFlags(IntFlag): @@ -184,8 +185,6 @@ class HyundaiFlags(IntFlag): MIN_STEER_32_MPH = 2 ** 23 - HAS_LDA_BUTTON = 2 ** 24 - FCEV = 2 ** 25 ALT_LIMITS_2 = 2 ** 26 @@ -203,6 +202,9 @@ class HyundaiFlags(IntFlag): NON_SCC_NO_FCA = 2 ** 30 NON_SCC_RADAR_FCA = 2 ** 31 + # Connected Car Navigation Cockpit CAN-FD platforms. + CCNC = 2 ** 24 + @dataclass class HyundaiCarDocs(CarDocs): @@ -342,6 +344,16 @@ class CAR(Platforms): CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2, ) + HYUNDAI_KONA_2ND_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Kona (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_l]))], + CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CCNC, + ) + HYUNDAI_KONA_HEV_2ND_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Kona Hybrid (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_l]))], + CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CCNC, + ) HYUNDAI_KONA_EV = HyundaiPlatformConfig( [HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))], CarSpecs(mass=1685, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), @@ -353,10 +365,13 @@ class CAR(Platforms): flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS, ) HYUNDAI_KONA_EV_2ND_GEN = HyundaiCanFDPlatformConfig( - [HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw", - car_parts=CarParts.common([CarHarness.hyundai_r]))], + [ + HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw", + car_parts=CarParts.common([CarHarness.hyundai_r])), + HyundaiCarDocs("Hyundai Kona Electric (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_a])), + ], CarSpecs(mass=1740, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385), - flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE, + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE | HyundaiFlags.CCNC, ) HYUNDAI_KONA_HEV = HyundaiPlatformConfig( [HyundaiCarDocs("Hyundai Kona Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_i]))], # TODO: check packages, @@ -390,12 +405,27 @@ class CAR(Platforms): HYUNDAI_SANTA_FE.specs, flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, ) + HYUNDAI_SANTA_FE_HEV_5TH_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Hyundai Santa Fe Hybrid (with HDA II & LFA2) 2024-25", "Highway Driving Assist II & Lane Follow Assist 2", + car_parts=CarParts.common([CarHarness.hyundai_p])), + HyundaiCarDocs("Hyundai Santa Fe Hybrid (without HDA II, LFA2) 2025-26", "Lane Follow Assist 2", + car_parts=CarParts.common([CarHarness.hyundai_l])), + ], + CarSpecs(mass=2035, wheelbase=2.81, steerRatio=13.72), + flags=HyundaiFlags.CANFD_ANGLE_STEERING | HyundaiFlags.CCNC, + ) HYUNDAI_SONATA = HyundaiPlatformConfig( [HyundaiCarDocs("Hyundai Sonata 2020-23", "All", video="https://www.youtube.com/watch?v=ix63r9kE3Fw", car_parts=CarParts.common([CarHarness.hyundai_a]))], CarSpecs(mass=1513, wheelbase=2.84, steerRatio=13.27 * 1.15, tireStiffnessFactor=0.65), # 15% higher at the center seems reasonable flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8, ) + HYUNDAI_SONATA_2024 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Sonata (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))], + CarSpecs(mass=1556, wheelbase=2.84, steerRatio=12.81), + flags=HyundaiFlags.CCNC, + ) HYUNDAI_SONATA_LF = HyundaiPlatformConfig( [HyundaiCarDocs("Hyundai Sonata 2018-19", car_parts=CarParts.common([CarHarness.hyundai_e]))], CarSpecs(mass=1536, wheelbase=2.804, steerRatio=13.27 * 1.15), # 15% higher at the center seems reasonable @@ -441,6 +471,11 @@ class CAR(Platforms): HYUNDAI_SONATA.specs, flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, ) + HYUNDAI_SONATA_HEV_2024 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Sonata Hybrid (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))], + CarSpecs(mass=1616, wheelbase=2.84, steerRatio=13.27), + flags=HyundaiFlags.CCNC, + ) HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig( [ HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), @@ -450,11 +485,32 @@ class CAR(Platforms): CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65), flags=HyundaiFlags.EV, ) + HYUNDAI_IONIQ_5_PE = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Hyundai Ioniq 5 PE (with HDA II & LFA2) 2025-26", "Highway Driving Assist II & Lane Follow Assist 2", + car_parts=CarParts.common([CarHarness.hyundai_q])) + ], + HYUNDAI_IONIQ_5.specs, + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING, + ) + HYUNDAI_IONIQ_5_N = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq 5 N (with HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_s]))], + CarSpecs(mass=2205, wheelbase=3.00, steerRatio=14.26, tireStiffnessFactor=1.3), + flags=HyundaiFlags.EV | HyundaiFlags.CCNC, + ) HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig( [HyundaiCarDocs("Hyundai Ioniq 6 (with HDA II) 2023-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))], HYUNDAI_IONIQ_5.specs, flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE, ) + HYUNDAI_IONIQ_9 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Hyundai Ioniq 9 (with HDA II & LFA2) 2025-26", "Highway Driving Assist II & Lane Follow Assist 2", + car_parts=CarParts.common([CarHarness.hyundai_m])) + ], + CarSpecs(mass=2700, wheelbase=3.13, steerRatio=16.02), + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING, + ) HYUNDAI_TUCSON_4TH_GEN = HyundaiCanFDPlatformConfig( [ HyundaiCarDocs("Hyundai Tucson 2022", car_parts=CarParts.common([CarHarness.hyundai_n])), @@ -464,11 +520,31 @@ class CAR(Platforms): ], CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385), ) + HYUNDAI_TUCSON_2025 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Tucson (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))], + CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CCNC, + ) + HYUNDAI_TUCSON_HEV_2025 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Tucson Hybrid (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))], + CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CCNC, + ) + HYUNDAI_TUCSON_PHEV_2025 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Tucson Plug-in Hybrid (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))], + CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CCNC, + ) HYUNDAI_SANTA_CRUZ_1ST_GEN = HyundaiCanFDPlatformConfig( [HyundaiCarDocs("Hyundai Santa Cruz 2022-24", car_parts=CarParts.common([CarHarness.hyundai_n]))], # weight from Limited trim - the only supported trim, steering ratio according to Hyundai News https://www.hyundainews.com/assets/documents/original/48035-2022SantaCruzProductGuideSpecsv2081521.pdf CarSpecs(mass=1870, wheelbase=3, steerRatio=14.2), ) + HYUNDAI_SANTA_CRUZ_2025 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Santa Cruz (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))], + CarSpecs(mass=1920, wheelbase=3, steerRatio=14.2), + flags=HyundaiFlags.CCNC, + ) HYUNDAI_CUSTIN_1ST_GEN = HyundaiPlatformConfig( [HyundaiCarDocs("Hyundai Custin 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))], CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner @@ -483,11 +559,24 @@ class CAR(Platforms): ], CarSpecs(mass=2878 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5) ) + KIA_K4_2025 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia K4 (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_a])), + HyundaiCarDocs("Kia K4 (with HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_r])), + ], + CarSpecs(mass=2987 * CV.LB_TO_KG, wheelbase=2.72, steerRatio=13.4), + flags=HyundaiFlags.CCNC, + ) KIA_K5_2021 = HyundaiPlatformConfig( [HyundaiCarDocs("Kia K5 2021-24", car_parts=CarParts.common([CarHarness.hyundai_a]))], CarSpecs(mass=3381 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5), # 2021 Kia K5 Steering Ratio (all trims) flags=HyundaiFlags.CHECKSUM_CRC8, ) + KIA_K5_2025 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Kia K5 (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_m]))], + CarSpecs(mass=3230 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27), + flags=HyundaiFlags.CCNC, + ) KIA_K5_HEV_2020 = HyundaiPlatformConfig( [HyundaiCarDocs("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a]))], KIA_K5_2021.specs, @@ -580,6 +669,13 @@ class CAR(Platforms): # weight from SX and above trims, average of FWD and AWD version, steering ratio according to Kia News https://www.kiamedia.com/us/en/models/sportage/2023/specifications CarSpecs(mass=1725, wheelbase=2.756, steerRatio=13.6), ) + KIA_SPORTAGE_2026 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia Sportage (without HDA II) 2026", car_parts=CarParts.common([CarHarness.hyundai_n])), + ], + CarSpecs(mass=1735, wheelbase=2.756, steerRatio=13.7), + flags=HyundaiFlags.CANFD_ANGLE_STEERING | HyundaiFlags.CCNC, + ) KIA_SPORTAGE_HEV_2026 = HyundaiCanFDPlatformConfig( [HyundaiCarDocs("Kia Sportage Hybrid 2026", car_parts=CarParts.common([CarHarness.hyundai_n]))], CarSpecs(mass=1812, wheelbase=2.756, steerRatio=13.7), @@ -599,6 +695,11 @@ class CAR(Platforms): CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms flags=HyundaiFlags.RADAR_SCC, ) + KIA_SORENTO_2024 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Kia Sorento (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))], + CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), + flags=HyundaiFlags.CCNC, + ) KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig( [ HyundaiCarDocs("Kia Sorento Hybrid 2021-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])), @@ -607,6 +708,13 @@ class CAR(Platforms): CarSpecs(mass=4395 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms flags=HyundaiFlags.RADAR_SCC, ) + KIA_SORENTO_HEV_4TH_GEN_LFA2 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia Sorento Hybrid 2026", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), + ], + CarSpecs(mass=1970, wheelbase=2.814, steerRatio=13.27, tireStiffnessFactor=0.65), + flags=HyundaiFlags.CANFD_ANGLE_STEERING, + ) KIA_STINGER = HyundaiPlatformConfig( [HyundaiCarDocs("Kia Stinger 2018-20", video="https://www.youtube.com/watch?v=MJ94qoofYw0", car_parts=CarParts.common([CarHarness.hyundai_c]))], @@ -630,6 +738,20 @@ class CAR(Platforms): CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65), flags=HyundaiFlags.EV, ) + KIA_EV6_2025 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia EV6 (with HDA I) 2025", "Highway Driving Assist I", car_parts=CarParts.common([CarHarness.hyundai_p])) + ], + CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65), + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING, + ) + KIA_EV9 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia EV9 2025-26", car_parts=CarParts.common([CarHarness.hyundai_r])) + ], + CarSpecs(mass=2664, wheelbase=3.1, steerRatio=16), + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING, + ) KIA_CARNIVAL_4TH_GEN = HyundaiCanFDPlatformConfig( [ HyundaiCarDocs("Kia Carnival 2022-24", car_parts=CarParts.common([CarHarness.hyundai_a])), @@ -680,6 +802,13 @@ class CAR(Platforms): CarSpecs(mass=2260, wheelbase=2.87, steerRatio=17.1), flags=HyundaiFlags.EV, ) + GENESIS_GV70_ELECTRIFIED_2ND_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Genesis GV70 Electrified 2026", "All", car_parts=CarParts.common([CarHarness.hyundai_m])), + ], + GENESIS_GV70_ELECTRIFIED_1ST_GEN.specs, + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING, + ) GENESIS_G80 = HyundaiPlatformConfig( [HyundaiCarDocs("Genesis G80 2018-19", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))], CarSpecs(mass=2060, wheelbase=3.01, steerRatio=16.5), @@ -698,6 +827,16 @@ class CAR(Platforms): CarSpecs(mass=2258, wheelbase=2.95, steerRatio=14.14), flags=HyundaiFlags.RADAR_SCC, ) + GENESIS_GV80_2025 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Genesis GV80 (3.5T Prestige Trim, with HDA II & LFA2) 2025", "Highway Driving Assist II & Lane Follow Assist 2", + car_parts=CarParts.common([CarHarness.hyundai_q])), + HyundaiCarDocs("Genesis GV80 Coupe (with HDA II & LFA2) 2025", "Highway Driving Assist II & Lane Follow Assist 2", + car_parts=CarParts.common([CarHarness.hyundai_q])), + ], + GENESIS_GV80.specs, + flags=HyundaiFlags.CANFD_ANGLE_STEERING, + ) # Hyundai non-SCC extensions HYUNDAI_BAYON_1ST_GEN_NON_SCC = HyundaiNonSccPlatformConfig( @@ -857,7 +996,7 @@ PART_NUMBER_FW_PATTERN = re.compile(b'(?<=[0-9][.,][0-9]{2} )([0-9]{5}[-/]?[A-Z] # We've seen both ICE and hybrid for these platforms, and they have hybrid descriptors (e.g. MQ4 vs MQ4H) CANFD_FUZZY_WHITELIST = {CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN, CAR.KIA_K8_HEV_1ST_GEN, # TODO: the hybrid variant is not out yet - CAR.KIA_CARNIVAL_4TH_GEN} + CAR.KIA_CARNIVAL_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN_LFA2} # List of ECUs expected to have platform codes, camera and radar should exist on all cars # TODO: use abs, it has the platform code and part number on many platforms diff --git a/opendbc_repo/opendbc/car/interfaces.py b/opendbc_repo/opendbc/car/interfaces.py index da4fa0ab7..27b263f2c 100644 --- a/opendbc_repo/opendbc/car/interfaces.py +++ b/opendbc_repo/opendbc/car/interfaces.py @@ -233,7 +233,7 @@ class CarInterfaceBase(ABC): not CP.openpilotLongitudinalControl: fp_ret.pcmCruiseSpeed = False - if CP.flags & HyundaiFlags.HAS_LDA_BUTTON: + if 0x391 in fingerprint[0] or CP.flags & HyundaiFlags.CAN_CANFD_BLENDED: fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON.value if starpilot_toggles.always_on_lateral_lkas: fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value diff --git a/opendbc_repo/opendbc/car/tests/routes.py b/opendbc_repo/opendbc/car/tests/routes.py index 15e6bb681..7883e69ea 100644 --- a/opendbc_repo/opendbc/car/tests/routes.py +++ b/opendbc_repo/opendbc/car/tests/routes.py @@ -25,6 +25,17 @@ non_tested_cars = [ GM.HOLDEN_ASTRA, GM.CHEVROLET_MALIBU, HYUNDAI.GENESIS_G90, + HYUNDAI.GENESIS_GV70_ELECTRIFIED_2ND_GEN, + HYUNDAI.GENESIS_GV80_2025, + HYUNDAI.HYUNDAI_IONIQ_5_PE, + HYUNDAI.HYUNDAI_IONIQ_5_N, + HYUNDAI.HYUNDAI_SANTA_FE_HEV_5TH_GEN, + HYUNDAI.HYUNDAI_TUCSON_PHEV_2025, + HYUNDAI.KIA_EV6_2025, + HYUNDAI.KIA_EV9, + HYUNDAI.KIA_SPORTAGE_2026, + HYUNDAI.KIA_SORENTO_2024, + HYUNDAI.KIA_SORENTO_HEV_4TH_GEN_LFA2, VOLKSWAGEN.VOLKSWAGEN_CRAFTER_MK2, # need a route from an ACC-equipped Crafter SUBARU.SUBARU_FORESTER_HYBRID, VOLKSWAGEN.PORSCHE_MACAN_MK1, @@ -143,6 +154,7 @@ routes = [ CarTestRoute("66eaa6c3b6b2afc6/00000009--3a5199aabe", HYUNDAI.GENESIS_G80_2ND_GEN_FL), # LKA steering CarTestRoute("0bbe367c98fa1538/2023-09-16--00-16-49", HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN), CarTestRoute("f0709d2bc6ca451f/2022-10-15--08-13-54", HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN), + CarTestRoute("6e7904b03a4aafc2/00000010--31034184b6", HYUNDAI.HYUNDAI_SANTA_CRUZ_2025), CarTestRoute("4dbd55df87507948/2022-03-01--09-45-38", HYUNDAI.HYUNDAI_SANTA_FE), CarTestRoute("bf43d9df2b660eb0/2021-09-23--14-16-37", HYUNDAI.HYUNDAI_SANTA_FE_2022), CarTestRoute("37398f32561a23ad/2021-11-18--00-11-35", HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022), @@ -156,11 +168,14 @@ routes = [ CarTestRoute("6a42c1197b2a8179/2023-09-21--10-23-44", HYUNDAI.KIA_OPTIMA_H_G4_FL), CarTestRoute("c75a59efa0ecd502/2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS), CarTestRoute("5b7c365c50084530/2020-04-15--16-13-24", HYUNDAI.HYUNDAI_SONATA), + CarTestRoute("4267ea8a353cdb36/00000262--8a427003c7", HYUNDAI.HYUNDAI_SONATA_2024, segment=34), CarTestRoute("b2a38c712dcf90bd/2020-05-18--18-12-48", HYUNDAI.HYUNDAI_SONATA_LF), CarTestRoute("c344fd2492c7a9d2/2023-12-11--09-03-23", HYUNDAI.HYUNDAI_STARIA_4TH_GEN), CarTestRoute("fb3fd42f0baaa2f8/2022-03-30--15-25-05", HYUNDAI.HYUNDAI_TUCSON), CarTestRoute("db68bbe12250812c/2022-12-05--00-54-12", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # 2023 CarTestRoute("36e10531feea61a4/2022-07-25--13-37-42", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # hybrid + CarTestRoute("a01ca5d4f394c812/00000000--e98b7e4414", HYUNDAI.HYUNDAI_TUCSON_2025), + CarTestRoute("22f9090014364a87/00000002--4cc739c0b2", HYUNDAI.HYUNDAI_TUCSON_HEV_2025), CarTestRoute("5875672fc1d4bf57/2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO), CarTestRoute("1d0d000db3370fd0/2023-01-04--22-28-42", HYUNDAI.KIA_SORENTO_4TH_GEN, segment=5), CarTestRoute("fc19648042eb6896/2023-08-16--11-43-27", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, segment=14), @@ -168,6 +183,7 @@ routes = [ CarTestRoute("9c917ba0d42ffe78/2020-04-17--12-43-19", HYUNDAI.HYUNDAI_PALISADE), CarTestRoute("05a8f0197fdac372/2022-10-19--14-14-09", HYUNDAI.HYUNDAI_IONIQ_5), # LKA steering CarTestRoute("eb4eae1476647463/2023-08-26--18-07-04", HYUNDAI.HYUNDAI_IONIQ_6, segment=6), # LKA steering + CarTestRoute("71e4e67d29034771/0000001b--b7b4774ec4", HYUNDAI.HYUNDAI_IONIQ_9), CarTestRoute("3f29334d6134fcd4/2022-03-30--22-00-50", HYUNDAI.HYUNDAI_IONIQ_PHEV_2019), CarTestRoute("fa8db5869167f821/2021-06-10--22-50-10", HYUNDAI.HYUNDAI_IONIQ_PHEV), CarTestRoute("e1107f9d04dfb1e2/2023-09-05--22-32-12", HYUNDAI.HYUNDAI_IONIQ_PHEV), # openpilot longitudinal enabled @@ -178,11 +194,13 @@ routes = [ CarTestRoute("ab59fe909f626921/2021-10-18--18-34-28", HYUNDAI.HYUNDAI_IONIQ_HEV_2022), CarTestRoute("22d955b2cd499c22/2020-08-10--19-58-21", HYUNDAI.HYUNDAI_KONA), CarTestRoute("0099bdb24d82951b/00000005--c38d940b04", HYUNDAI.HYUNDAI_KONA_2022), + CarTestRoute("32025f26789d8fab/00000022--a499e8ffa3", HYUNDAI.HYUNDAI_KONA_2ND_GEN), CarTestRoute("efc48acf44b1e64d/2021-05-28--21-05-04", HYUNDAI.HYUNDAI_KONA_EV), CarTestRoute("f90d3cd06caeb6fa/2023-09-06--17-15-47", HYUNDAI.HYUNDAI_KONA_EV), # openpilot longitudinal enabled CarTestRoute("ff973b941a69366f/2022-07-28--22-01-19", HYUNDAI.HYUNDAI_KONA_EV_2022, segment=11), CarTestRoute("1618132d68afc876/2023-08-27--09-32-14", HYUNDAI.HYUNDAI_KONA_EV_2ND_GEN, segment=13), CarTestRoute("49f3c13141b6bc87/2021-07-28--08-05-13", HYUNDAI.HYUNDAI_KONA_HEV), + CarTestRoute("97ca61196eb73e0d/00000052--4555329470", HYUNDAI.HYUNDAI_KONA_HEV_2ND_GEN), CarTestRoute("a74afe0cf708748f/0000000e--a2885a9a71", HYUNDAI.HYUNDAI_NEXO_1ST_GEN), CarTestRoute("a74afe0cf708748f/0000000c--b476a8fd00", HYUNDAI.HYUNDAI_NEXO_1ST_GEN), # openpilot longitudinal enabled CarTestRoute("5dddcbca6eb66c62/2020-07-26--13-24-19", HYUNDAI.KIA_STINGER), @@ -191,7 +209,9 @@ routes = [ CarTestRoute("d545129f3ca90f28/2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # LKA steering CarTestRoute("68d6a96e703c00c9/2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # LFA steering CarTestRoute("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6), + CarTestRoute("baf39eeaba1217ca/00000002--b36e3fa031", HYUNDAI.KIA_K4_2025), CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021), + CarTestRoute("c4a804b067623789/0000007c--163f831540", HYUNDAI.KIA_K5_2025), CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020), CarTestRoute("78ad5150de133637/2023-09-13--16-15-57", HYUNDAI.KIA_K8_HEV_1ST_GEN), CarTestRoute("50c6c9b85fd1ff03/2020-10-26--17-56-06", HYUNDAI.KIA_NIRO_EV), @@ -210,6 +230,7 @@ routes = [ CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021), CarTestRoute("715ac05b594e9c59/2021-06-20--16-21-07", HYUNDAI.HYUNDAI_ELANTRA_HEV_2021), CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID), + CarTestRoute("bc40c72b728178f2/00000006--ee76ae8c42", HYUNDAI.HYUNDAI_SONATA_HEV_2024), CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020), CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80), diff --git a/opendbc_repo/opendbc/car/torque_data/override.toml b/opendbc_repo/opendbc/car/torque_data/override.toml index eeaf7b322..22e892749 100644 --- a/opendbc_repo/opendbc/car/torque_data/override.toml +++ b/opendbc_repo/opendbc/car/torque_data/override.toml @@ -64,13 +64,25 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "VOLKSWAGEN_PASSAT_NMS" = [2.5, 2.5, 0.1] "VOLKSWAGEN_SHARAN_MK2" = [2.5, 2.5, 0.1] "HYUNDAI_SANTA_CRUZ_1ST_GEN" = [2.7, 2.7, 0.1] +"HYUNDAI_SANTA_CRUZ_2025" = [2.5, 2.5, 0.1] +"HYUNDAI_SANTA_FE_HEV_5TH_GEN" = [nan, 2.5, nan] +"HYUNDAI_SONATA_2024" = [2.5, 2.5, 0.1] +"HYUNDAI_SONATA_HEV_2024" = [2.5, 2.5, 0.1] +"HYUNDAI_KONA_2ND_GEN" = [2.5, 2.5, 0.1] +"HYUNDAI_KONA_HEV_2ND_GEN" = [2.5, 2.5, 0.1] +"HYUNDAI_TUCSON_2025" = [2.5, 2.5, 0.1] +"HYUNDAI_TUCSON_HEV_2025" = [2.5, 2.5, 0.1] +"HYUNDAI_TUCSON_PHEV_2025" = [2.5, 2.5, 0.1] "KIA_SPORTAGE_5TH_GEN" = [2.6, 2.6, 0.1] +"KIA_SPORTAGE_2026" = [nan, 2.5, nan] "KIA_SPORTAGE_HEV_2026" = [nan, 2.5, nan] "GENESIS_GV70_1ST_GEN" = [2.42, 2.42, 0.1] "GENESIS_GV60_EV_1ST_GEN" = [2.5, 2.5, 0.1] "GMC_YUKON" = [1.2, 2.5, 0.26] "KIA_SORENTO_4TH_GEN" = [2.5, 2.5, 0.1] +"KIA_SORENTO_2024" = [2.5, 2.5, 0.1] "KIA_SORENTO_HEV_4TH_GEN" = [2.5, 2.5, 0.1] +"KIA_SORENTO_HEV_4TH_GEN_LFA2" = [nan, 2.5, nan] "KIA_NIRO_HEV_2ND_GEN" = [2.42, 2.5, 0.12] "KIA_NIRO_EV_2ND_GEN" = [2.05, 2.5, 0.14] "GENESIS_GV80" = [2.5, 2.5, 0.1] @@ -78,15 +90,24 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "GMC_ACADIA" = [1.6, 1.6, 0.2] "LEXUS_IS_TSS2" = [2.0, 2.0, 0.1] "HYUNDAI_KONA_EV_2ND_GEN" = [2.5, 2.5, 0.1] +"HYUNDAI_IONIQ_5_PE" = [nan, 2.5, nan] +"HYUNDAI_IONIQ_5_N" = [2.5, 2.5, 0.1] "HYUNDAI_IONIQ_6" = [3.0, 3.0, 0.09] +"HYUNDAI_IONIQ_9" = [nan, 2.5, nan] "HYUNDAI_AZERA_6TH_GEN" = [1.8, 1.8, 0.1] "HYUNDAI_AZERA_HEV_6TH_GEN" = [1.8, 1.8, 0.1] "KIA_K8_HEV_1ST_GEN" = [2.5, 2.5, 0.1] +"KIA_K4_2025" = [2.5, 2.5, 0.1] +"KIA_K5_2025" = [2.5, 2.5, 0.1] +"KIA_EV6_2025" = [nan, 2.5, nan] +"KIA_EV9" = [nan, 2.5, nan] "HYUNDAI_CUSTIN_1ST_GEN" = [2.5, 2.5, 0.1] "LEXUS_GS_F" = [2.5, 2.5, 0.08] "HYUNDAI_STARIA_4TH_GEN" = [1.8, 2.0, 0.15] "GENESIS_GV70_ELECTRIFIED_1ST_GEN" = [1.9, 1.9, 0.09] +"GENESIS_GV70_ELECTRIFIED_2ND_GEN" = [nan, 2.5, nan] "GENESIS_G80_2ND_GEN_FL" = [2.5819356441497803, 2.5, 0.11244568973779678] +"GENESIS_GV80_2025" = [nan, 2.5, nan] # Note that some Rivians achieve significantly less lateral acceleration than this "RIVIAN_R1_GEN1" = [2.8, 2.5, 0.07] "HYUNDAI_NEXO_1ST_GEN" = [2.5, 2.5, 0.1] diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h index 611423c2b..063f9de8f 100644 --- a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h +++ b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h @@ -56,6 +56,7 @@ static bool hyundai_canfd_alt_buttons = false; static bool hyundai_canfd_lka_steering_alt = false; static bool hyundai_canfd_angle_steering = false; +static bool hyundai_ccnc = false; static unsigned int hyundai_canfd_get_lka_addr(void) { return hyundai_canfd_lka_steering_alt ? 0x110U : 0x50U; @@ -289,6 +290,7 @@ static safety_config hyundai_canfd_init(uint16_t param) { const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT = 128; const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32; const uint16_t HYUNDAI_PARAM_CANFD_ANGLE_STEERING = 1024; + const uint16_t HYUNDAI_PARAM_CCNC = 32768U; static const CanMsg HYUNDAI_CANFD_LKA_STEERING_TX_MSGS[] = { HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1) @@ -335,12 +337,22 @@ static safety_config hyundai_canfd_init(uint16_t param) { HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \ {0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \ +#define HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(longitudinal) \ + HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) \ + HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) \ + HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \ + {0x161, 0, 32, .check_relay = true}, /* CCNC_0x161 */ \ + {0x162, 0, 32, .check_relay = true}, /* CCNC_0x162 */ \ + {0x7C4, 2, 8, .check_relay = true}, /* camera support frame */ \ + {0xEA, 2, 24, .check_relay = true}, /* MDPS support frame */ \ + hyundai_common_init(param); gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut); hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS); hyundai_canfd_lka_steering_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT); hyundai_canfd_angle_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ANGLE_STEERING); + hyundai_ccnc = GET_FLAG(param, HYUNDAI_PARAM_CCNC); safety_config ret; if (hyundai_longitudinal) { @@ -367,6 +379,10 @@ static safety_config hyundai_canfd_init(uint16_t param) { HYUNDAI_CANFD_BLINDSPOT_DASH_TX_MSGS(0) }; + static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = { + HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(true) + }; + if (hyundai_canfd_alt_buttons) { SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret); } else { @@ -374,7 +390,11 @@ static safety_config hyundai_canfd_init(uint16_t param) { } if (hyundai_camera_scc) { - SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret); + if (hyundai_ccnc) { + SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret); + } else { + SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret); + } } else { SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret); } @@ -435,7 +455,15 @@ static safety_config hyundai_canfd_init(uint16_t param) { HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false) }; - SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret); + static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = { + HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(false) + }; + + if (hyundai_ccnc) { + SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret); + } else { + SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret); + } if (hyundai_canfd_alt_buttons) { SET_RX_CHECKS(hyundai_canfd_alt_buttons_rx_checks, ret); diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py index ee8054b82..75b7d7d8a 100755 --- a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py @@ -422,6 +422,37 @@ class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButton pass +class TestHyundaiCanfdCCNCSupportFrames(common.SafetyTestBase): + TX_MSGS = [[0x161, 0], [0x162, 0], [0x7C4, 2], [0xEA, 2]] + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + + def _set_hooks(self, param): + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, param) + self.safety.init_tests() + + def test_ccnc_support_frames_require_ccnc_flag(self): + support_msgs = ( + self.packer.make_can_msg_safety("CCNC_0x161", 0, {}), + self.packer.make_can_msg_safety("CCNC_0x162", 0, {}), + common.make_msg(2, 0x7C4, 8), + common.make_msg(2, 0xEA, 24), + ) + + for longitudinal in (False, True): + base_param = HyundaiSafetyFlags.CAMERA_SCC | (HyundaiSafetyFlags.LONG if longitudinal else 0) + + self._set_hooks(base_param) + for msg in support_msgs: + self.assertFalse(self._tx(msg)) + + self._set_hooks(base_param | HyundaiSafetyFlags.CCNC) + for msg in support_msgs: + self.assertTrue(self._tx(msg)) + + class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase): TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]