diff --git a/common/params_keys.h b/common/params_keys.h index d9b0544..272e900 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -227,6 +227,32 @@ inline static std::unordered_map keys = { // iqpilot car specific params {"HyundaiLongitudinalTuning", {PERSISTENT, INT, "0"}}, + {"AutoCruiseControl", {PERSISTENT, INT, "0"}}, + {"AutoEngage", {PERSISTENT, INT, "0"}}, + {"CanfdDebug", {PERSISTENT, INT, "0"}}, + {"CanfdHDA2", {PERSISTENT, INT, "0"}}, + {"CarrotCruiseAtcDecel", {PERSISTENT, INT, "-1"}}, + {"CarrotCruiseDecel", {PERSISTENT, INT, "-1"}}, + {"CruiseButtonTest1", {PERSISTENT, INT, "8"}}, + {"CruiseButtonTest2", {PERSISTENT, INT, "30"}}, + {"CruiseButtonTest3", {PERSISTENT, INT, "1"}}, + {"CustomSteerDeltaDown", {PERSISTENT, INT, "0"}}, + {"CustomSteerDeltaDownLC", {PERSISTENT, INT, "0"}}, + {"CustomSteerDeltaUp", {PERSISTENT, INT, "0"}}, + {"CustomSteerDeltaUpLC", {PERSISTENT, INT, "0"}}, + {"CustomSteerMax", {PERSISTENT, INT, "0"}}, + {"EnableCornerRadar", {PERSISTENT, INT, "0"}}, + {"EnableRadarTracks", {PERSISTENT, INT, "0"}}, + {"EnableRadarTracksResult", {PERSISTENT | CLEAR_ON_MANAGER_START, INT}}, + {"FingerPrints", {PERSISTENT | CLEAR_ON_MANAGER_START, STRING}}, + {"HDPuse", {PERSISTENT, INT, "0"}}, + {"HapticFeedbackWhenSpeedCamera", {PERSISTENT, INT, "0"}}, + {"HyundaiCameraSCC", {PERSISTENT, INT, "0"}}, + {"IsLdwsCar", {PERSISTENT, INT, "0"}}, + {"LaneLineCheck", {PERSISTENT, INT, "0"}}, + {"LongitudinalPersonalityMax", {PERSISTENT, INT, "3"}}, + {"MaxAngleFrames", {PERSISTENT, INT, "89"}}, + {"SpeedFromPCM", {PERSISTENT, INT, "2"}}, {"SubaruStopAndGo", {PERSISTENT, BOOL, "0"}}, {"SubaruStopAndGoManualParkingBrake", {PERSISTENT, BOOL, "0"}}, {"TeslaCoopSteering", {PERSISTENT, BOOL, "0"}}, diff --git a/iqdbc_repo/iqdbc/car/hyundai/interface.py b/iqdbc_repo/iqdbc/car/hyundai/interface.py index fcab212..8dc5b9a 100644 --- a/iqdbc_repo/iqdbc/car/hyundai/interface.py +++ b/iqdbc_repo/iqdbc/car/hyundai/interface.py @@ -1,8 +1,8 @@ from iqdbc.car import Bus, get_safety_config, structs from iqdbc.car.hyundai.hyundaicanfd import CanBus -from iqdbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CANFD_RADAR_SCC_CAR, \ +from iqdbc.car.hyundai.values import HyundaiFlags, HyundaiFlagsIQ, CAR, DBC, CANFD_RADAR_SCC_CAR, \ CANFD_UNSUPPORTED_LONGITUDINAL_CAR, \ - UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags, HyundaiExtFlags, \ + UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags, HyundaiSafetyFlagsIQ, HyundaiExtFlags, \ CANFD_HYBRID_STATUS_ADDR, CANFD_HYBRID_STATUS_DLC, \ EV_MODE_STATUS_ADDR, EV_MODE_STATUS_DLC from iqdbc.car.hyundai.radar_interface import RADAR_START_ADDR @@ -254,6 +254,14 @@ class CarInterface(CarInterfaceBase): return ret + @staticmethod + def _get_params_iq(stock_cp, ret, candidate, fingerprint, car_fw, alpha_long, is_release_iq, docs): + del candidate, car_fw, alpha_long, is_release_iq, docs + if not stock_cp.flags & HyundaiFlags.CANFD and 0x391 in fingerprint[0]: + ret.flags |= HyundaiFlagsIQ.HAS_LFA_BUTTON + ret.iqSafetyFlags |= HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON + return ret + @staticmethod def init(CP, can_recv, can_send): diff --git a/iqdbc_repo/iqdbc/car/hyundai/tests/test_integration.py b/iqdbc_repo/iqdbc/car/hyundai/tests/test_integration.py index a0a92d4..5dfb818 100644 --- a/iqdbc_repo/iqdbc/car/hyundai/tests/test_integration.py +++ b/iqdbc_repo/iqdbc/car/hyundai/tests/test_integration.py @@ -2,7 +2,7 @@ import pytest from iqdbc.car import gen_empty_fingerprint, structs from iqdbc.car.hyundai.interface import CarInterface -from iqdbc.car.hyundai.values import CAR +from iqdbc.car.hyundai.values import CAR, HyundaiFlagsIQ, HyundaiSafetyFlagsIQ @pytest.mark.parametrize("candidate", list(CAR), ids=lambda candidate: candidate.value) @@ -39,3 +39,15 @@ def test_parameter_defaults_do_not_require_persisted_fingerprint(monkeypatch, tm state, _ = interface.update([]) assert state.vEgo == 0.0 + + +def test_classic_lfa_button_capability_survives_iq_module_removal(monkeypatch, tmp_path): + monkeypatch.setenv("PARAMS_ROOT", str(tmp_path)) + fingerprint = gen_empty_fingerprint() + fingerprint[0][0x391] = 8 + + cp = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False) + cp_iq = CarInterface.get_params_iq(cp, CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False) + + assert cp_iq.flags & HyundaiFlagsIQ.HAS_LFA_BUTTON + assert cp_iq.iqSafetyFlags & HyundaiSafetyFlagsIQ.HAS_LDA_BUTTON diff --git a/iqdbc_repo/iqdbc/car/hyundai/values.py b/iqdbc_repo/iqdbc/car/hyundai/values.py index 69ac2f4..3fd7310 100644 --- a/iqdbc_repo/iqdbc/car/hyundai/values.py +++ b/iqdbc_repo/iqdbc/car/hyundai/values.py @@ -26,7 +26,7 @@ class CarControllerParams: #([0, 9, 16, 25], [1.6, 1.0, 0.6, 0.15]), #([0, 9, 16, 25], [2.0, 1.2, 0.8, 0.28]), ) - # Stock LFA system is seen sending 250 max, but for LKAS events it's 175 max. + # Stock LFA system is seen sending 250 max, but for LKAS events it's 175 max. # 250 can at least achieve 4 m/s^2, 80 corresponds to ~2.5 m/s^2 ANGLE_MAX_TORQUE = 200 # The maximum amount of torque that will be allowed ANGLE_MIN_TORQUE = 25 # equivalent to ~0.8 m/s^2 of torque (based on ANGLE_MAX_TORQUE) when overriding @@ -83,6 +83,28 @@ class HyundaiSafetyFlags(IntFlag): ALT_LIMITS_2 = 512 +class HyundaiSafetyFlagsIQ: + DEFAULT = 0 + ESCC = 16 + MAIN_BTN_LONG_TOGGLE = 32 + HAS_LDA_BUTTON = 64 + NON_SCC = 128 + + +class HyundaiFlagsIQ(IntFlag): + ENHANCED_SCC = 1 + HAS_LFA_BUTTON = 2 + MAIN_BTN_LONG_TOGGLE = 2 ** 2 + ENABLE_RADAR_TRACKS_DEPRECATED = 2 ** 3 + LONG_TUNING_DYNAMIC = 2 ** 4 + LONG_TUNING_PREDICTIVE = 2 ** 5 + NON_SCC = 2 ** 6 + NON_SCC_RADAR_FCA = 2 ** 7 + NON_SCC_NO_FCA = 2 ** 8 + SPEED_LIMIT_AVAILABLE = 2 ** 9 + HAS_LKAS12 = 2 ** 10 + + class HyundaiFlags(IntFlag): # Dynamic Flags CANFD_HDA2 = 1 @@ -468,7 +490,6 @@ class CAR(Platforms): flags=HyundaiFlags.ANGLE_CONTROL, ) - # Kia KIA_FORTE = HyundaiPlatformConfig( [ diff --git a/iqpilot/sab/behavior.py b/iqpilot/sab/behavior.py index ea8cec3..0124837 100644 --- a/iqpilot/sab/behavior.py +++ b/iqpilot/sab/behavior.py @@ -12,8 +12,7 @@ from iqdbc.car import structs from openpilot.common.realtime import DT_CTRL from iqdbc.safety import ALTERNATIVE_EXPERIENCE from openpilot.selfdrive.selfdrived.events import ET -from iqdbc.car.hyundai.values import HyundaiFlags -from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ, HyundaiSafetyFlagsIQ +from iqdbc.car.hyundai.values import HyundaiFlags, HyundaiFlagsIQ, HyundaiSafetyFlagsIQ from openpilot.selfdrive.selfdrived.state import SOFT_DISABLE_TIME from cereal import log, custom @@ -255,7 +254,7 @@ _BTN = structs.CarState.ButtonEvent.Type _GEAR = structs.CarState.GearShifter _CRUISE_SET_TAPS = frozenset((_BTN.accelCruise, _BTN.resumeCruise, _BTN.decelCruise, _BTN.setCruise)) -_HYUNDAI_LDA_MASK = HyundaiFlags.HAS_LDA_BUTTON | HyundaiFlags.CANFD +_HYUNDAI_LDA_MASK = HyundaiFlags.CANFD # While a lateral-only session rides through a pause, these stock blockers are # swapped for their silent IQ twins. Order here is not load-bearing (each row @@ -295,7 +294,7 @@ class SteeringAssistanceBehavior: def _apply_brand_capabilities(self): brand = self.CP.brand self.no_main_cruise = brand in BRANDS_WITHOUT_MAIN_CRUISE_TOGGLE - lda_capable = bool(self.CP.flags & _HYUNDAI_LDA_MASK) + lda_capable = bool(self.CP.flags & _HYUNDAI_LDA_MASK) or bool(self.CP_IQ.flags & HyundaiFlagsIQ.HAS_LFA_BUTTON) self.hkg_allow = brand == "hyundai" and lda_capable def _reload_preferences(self, full: bool = False): diff --git a/iqpilot/sab/tests/test_sab.py b/iqpilot/sab/tests/test_sab.py index 48f30ca..bb81933 100644 --- a/iqpilot/sab/tests/test_sab.py +++ b/iqpilot/sab/tests/test_sab.py @@ -6,7 +6,7 @@ from types import SimpleNamespace from cereal import custom from iqdbc.car import structs -from iqdbc.car.hyundai.values import HyundaiFlags +from iqdbc.car.hyundai.values import HyundaiFlags, HyundaiFlagsIQ from openpilot.iqpilot.sab.behavior import SteeringAssistanceBehavior from openpilot.iqpilot.selfdrive.selfdrived.events import IQEvents from openpilot.selfdrive.selfdrived.events import Events @@ -39,7 +39,7 @@ class MockParams: def make_selfdrive(cp_flags: int, brand: str = "hyundai", main_cruise_allowed: bool = False, - aol_enabled: bool = True): + aol_enabled: bool = True, cp_iq_flags: int = 0): cp = SimpleNamespace( brand=brand, flags=cp_flags, @@ -47,7 +47,7 @@ def make_selfdrive(cp_flags: int, brand: str = "hyundai", main_cruise_allowed: b notCar=False, safetyModel=structs.CarParams.SafetyModel.noOutput, ) - cp_iq = SimpleNamespace(flags=0) + cp_iq = SimpleNamespace(flags=cp_iq_flags) return SimpleNamespace( CP=cp, CP_IQ=cp_iq, @@ -100,7 +100,7 @@ def make_vw_car_state(cruise_available: bool, cruise_fault_lateral: bool = False def test_hyundai_lkas_button_can_arm_guidance_before_lateral_available(): - selfdrive = make_selfdrive(HyundaiFlags.HAS_LDA_BUTTON) + selfdrive = make_selfdrive(0, cp_iq_flags=HyundaiFlagsIQ.HAS_LFA_BUTTON) guidance = SteeringAssistanceBehavior(selfdrive) guidance.update_events(make_car_state()) diff --git a/selfdrive/controls/radard.py b/selfdrive/controls/radard.py index 48d2b69..14b00ec 100755 --- a/selfdrive/controls/radard.py +++ b/selfdrive/controls/radard.py @@ -13,8 +13,7 @@ from openpilot.common.swaglog import cloudlog from openpilot.common.simple_kalman import KF1D from iqdbc.car import structs -from iqdbc.car.hyundai.values import HyundaiFlags -from iqdbc.iqpilot.car.hyundai.values import HyundaiFlagsIQ +from iqdbc.car.hyundai.values import HyundaiFlags, HyundaiFlagsIQ from openpilot.iqpilot.selfdrive.controls.lib.custom_stop_distance import CustomStopDistance