From 031ad89851e82f02ee82f4ede4ec0b4994b82853 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:29:51 -0500 Subject: [PATCH] kia forte --- opendbc_repo/opendbc/car/hyundai/carstate.py | 15 +++-- .../opendbc/car/hyundai/fingerprints.py | 2 + .../opendbc/car/hyundai/tests/test_hyundai.py | 63 ++++++++++++++++++- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/opendbc_repo/opendbc/car/hyundai/carstate.py b/opendbc_repo/opendbc/car/hyundai/carstate.py index 7c6f9e528..3bb406245 100644 --- a/opendbc_repo/opendbc/car/hyundai/carstate.py +++ b/opendbc_repo/opendbc/car/hyundai/carstate.py @@ -147,15 +147,17 @@ class CarState(CarStateBase): ret.cruiseState.standstill = False ret.cruiseState.nonAdaptive = False elif no_scc: - cruise_enabled = cp.vl["TCS13"]["ACC_REQ"] == 1 cruise_set_speed = cp.vl["LVR12"]["CF_Lvr_CruiseSet"] + cruise_has_set_speed = 0 < cruise_set_speed < 255 + # Some regular-cruise Forte trims never assert ACC_REQ even when stock cruise is engaged. + cruise_enabled = cp.vl["TCS13"]["ACC_REQ"] == 1 or cruise_has_set_speed # Regular-cruise Forte trims don't publish SCC11/SCC12; use the stock cruise request and set speed. ret.cruiseState.available = cruise_enabled or cp.vl["TCS13"]["ACCEnable"] == 0 ret.cruiseState.enabled = cruise_enabled ret.cruiseState.standstill = False ret.cruiseState.nonAdaptive = False - if 0 < cruise_set_speed < 255: + if cruise_has_set_speed: ret.cruiseState.speed = cruise_set_speed * speed_conv else: ret.cruiseState.available = cp_cruise.vl["SCC11"]["MainMode_ACC"] == 1 @@ -202,7 +204,8 @@ class CarState(CarStateBase): aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12" aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct" aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0 - scc_warning = cp_cruise.vl["SCC12"]["TakeOverReq"] == 1 # sometimes only SCC system shows an FCW + # Regular-cruise Forte trims don't publish SCC12; avoid poisoning parser validity on no-SCC cars. + scc_warning = False if no_scc else cp_cruise.vl["SCC12"]["TakeOverReq"] == 1 aeb_braking = cp_cruise.vl[aeb_src]["CF_VSM_DecCmdAct"] != 0 or cp_cruise.vl[aeb_src][aeb_sig] != 0 ret.stockFcw = (aeb_warning or scc_warning) and not aeb_braking ret.stockAeb = aeb_warning and aeb_braking @@ -377,7 +380,11 @@ class CarState(CarStateBase): if CP.flags & HyundaiFlags.CANFD: return self.get_can_parsers_canfd(CP) + msgs = [] + if CP.flags & HyundaiFlags.NON_SCC and CP.flags & HyundaiFlags.USE_FCA.value: + msgs.append(("FCA11", 0)) # no-SCC Forte trims can stop publishing FCA11; don't let it poison canValid + return { - Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0), + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, 0), Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), } diff --git a/opendbc_repo/opendbc/car/hyundai/fingerprints.py b/opendbc_repo/opendbc/car/hyundai/fingerprints.py index a1f2c6b04..e1def32e2 100644 --- a/opendbc_repo/opendbc/car/hyundai/fingerprints.py +++ b/opendbc_repo/opendbc/car/hyundai/fingerprints.py @@ -583,12 +583,14 @@ FW_VERSIONS = { CAR.KIA_FORTE: { (Ecu.eps, 0x7d4, None): [ b'\xf1\x00BD MDPS C 1.00 1.02 56310-XX000 4BD2C102', + b'\xf1\x00BD MDPS C 1.00 1.07 56310/M6300 4BDDC107', b'\xf1\x00BD MDPS C 1.00 1.08 56310/M6300 4BDDC108', b'\xf1\x00BD MDPS C 1.00 1.08 56310M6300\x00 4BDDC108', b'\xf1\x00BDm MDPS C A.01 1.01 56310M7800\x00 4BPMC101', b'\xf1\x00BDm MDPS C A.01 1.03 56310M7800\x00 4BPMC103', ], (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00BD LKAS AT USA LHD 1.00 1.02 95740-M6000 J31', b'\xf1\x00BD LKAS AT USA LHD 1.00 1.04 95740-M6000 J33', b'\xf1\x00BDP LKAS AT USA LHD 1.00 1.05 99211-M6500 744', ], diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index 5df771d69..ff2e6e2f5 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -6,7 +6,7 @@ import pytest from opendbc.can import CANPacker from opendbc.car import Bus, ButtonType, gen_empty_fingerprint from opendbc.car.structs import CarParams -from opendbc.car.fw_versions import build_fw_dict +from opendbc.car.fw_versions import build_fw_dict, match_fw_to_car from opendbc.car.hyundai.carstate import CarState from opendbc.car.hyundai.interface import CarInterface from opendbc.car.hyundai import hyundaicanfd @@ -93,6 +93,67 @@ class TestHyundaiFingerprint: CP = CarInterface.get_params(CAR.KIA_SPORTAGE_HEV_2026, fingerprint, [], False, False, False, None) assert CP.flags & HyundaiFlags.SEND_LFA + def test_kia_forte_no_scc_fw_match(self): + car_fw = [ + CarParams.CarFw( + ecu=Ecu.eps, + fwVersion=b'\xf1\x00BD MDPS C 1.00 1.07 56310/M6300 4BDDC107', + address=0x7d4, + subAddress=0, + brand="hyundai", + ), + CarParams.CarFw( + ecu=Ecu.fwdCamera, + fwVersion=b'\xf1\x00BD LKAS AT USA LHD 1.00 1.02 95740-M6000 J31', + address=0x7c4, + subAddress=0, + brand="hyundai", + ), + ] + + exact, matches = match_fw_to_car(car_fw, "3KPF34AD2LE154148", allow_exact=True, allow_fuzzy=False, log=False) + assert exact + assert matches == {CAR.KIA_FORTE} + + def test_kia_forte_no_scc_fca_does_not_require_scc12(self): + toggles = get_test_toggles() + fingerprint = gen_empty_fingerprint() + fingerprint[0][0x38D] = 8 + + CP = CarInterface.get_params(CAR.KIA_FORTE, fingerprint, [], True, False, False, toggles) + FPCP = CarInterface.get_starpilot_params(CAR.KIA_FORTE, fingerprint, [], CP, toggles) + + car_state = CarState(CP, FPCP) + can_parsers = car_state.get_can_parsers(CP) + packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) + fca11_addr = packer.dbc.name_to_msg["FCA11"].address + + assert can_parsers[Bus.pt].message_states[fca11_addr].ignore_alive + + car_state.update(can_parsers, toggles) + pt_states = {state.name for state in can_parsers[Bus.pt].message_states.values()} + assert "FCA11" in pt_states + assert "SCC12" not in pt_states + + for frame in range(1, 6): + t = frame * 100_000_000 + for parser in can_parsers.values(): + required_msgs = [] + for state in parser.message_states.values(): + if state.ignore_alive: + continue + values = {} + if state.name == "LVR12": + values["CF_Lvr_CruiseSet"] = 30 + required_msgs.append(packer.make_can_msg(state.name, parser.bus, values)) + parser.update([(t, required_msgs)]) + + assert all(parser.can_valid for parser in can_parsers.values()) + + ret, _ = car_state.update(can_parsers, toggles) + assert ret.cruiseState.enabled + assert ret.cruiseState.speed > 0 + def test_alternate_limits(self): # Alternate lateral control limits, for high torque cars, verify Panda safety mode flag is set fingerprint = gen_empty_fingerprint()