From 5e0447df1e91022c7067fb00a799331027043fe1 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Tue, 5 May 2026 11:11:10 -0500 Subject: [PATCH] ipedal --- .../opendbc/car/hyundai/carcontroller.py | 20 +++++++++- opendbc_repo/opendbc/car/hyundai/carstate.py | 13 ++++++- .../opendbc/car/hyundai/tests/test_hyundai.py | 37 ++++++++++++++++++- .../opendbc/dbc/hyundai_canfd_generated.dbc | 2 + 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py index ba6f194c8..eb746434f 100644 --- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -54,6 +54,10 @@ IONIQ_6_STOP_RELEASE_JERK_V = [3.6 * IONIQ_6_RESPONSE_MULTIPLIER, 4.2 * IONIQ_6_RESPONSE_MULTIPLIER, 4.8 * IONIQ_6_RESPONSE_MULTIPLIER] IONIQ_6_IPEDAL_PRESS_SEND_COUNT = 6 +IONIQ_6_IPEDAL_LATCH_PRESS_SEND_COUNT = 10 +IONIQ_6_IPEDAL_REGEN_STATE = 0x50 +IONIQ_6_IPEDAL_REGEN_STATE_2_PENDING = 0x01 +IONIQ_6_IPEDAL_PROGRESS_RETRY_WAIT_FRAMES = 10 IONIQ_6_IPEDAL_RETRY_WAIT_FRAMES = 30 @@ -242,6 +246,8 @@ class CarController(CarControllerBase): self._ioniq_6_always_ipedal_retry_frame = 0 self._ioniq_6_always_ipedal_counter = 0 self._ioniq_6_always_ipedal_startup_park_done = False + self._ioniq_6_last_ipedal_regen_state = 0 + self._ioniq_6_last_ipedal_regen_state_2 = 0 self._ioniq_6_last_gear = structs.CarState.GearShifter.unknown self._genesis_g90_long_tuning = GenesisG90LongitudinalTuningState() @@ -261,10 +267,16 @@ class CarController(CarControllerBase): if self.CP.carFingerprint != CAR.HYUNDAI_IONIQ_6 or not getattr(starpilot_toggles, "always_ipedal", False): self._reset_ioniq_6_always_ipedal() self._ioniq_6_always_ipedal_startup_park_done = False + self._ioniq_6_last_ipedal_regen_state = int(getattr(CS, "ipedal_regen_state", 0)) + self._ioniq_6_last_ipedal_regen_state_2 = int(getattr(CS, "ipedal_regen_state_2", 0)) self._ioniq_6_last_gear = CS.out.gearShifter return can_sends gear = CS.out.gearShifter + regen_state = int(getattr(CS, "ipedal_regen_state", 0)) + regen_state_2 = int(getattr(CS, "ipedal_regen_state_2", 0)) + regen_state_changed = regen_state != self._ioniq_6_last_ipedal_regen_state or regen_state_2 != self._ioniq_6_last_ipedal_regen_state_2 + ipedal_latch_pending = regen_state == IONIQ_6_IPEDAL_REGEN_STATE and regen_state_2 == IONIQ_6_IPEDAL_REGEN_STATE_2_PENDING drive = gear == structs.CarState.GearShifter.drive park = gear == structs.CarState.GearShifter.park drive_edge = drive and self._ioniq_6_last_gear != structs.CarState.GearShifter.drive @@ -287,7 +299,8 @@ class CarController(CarControllerBase): if target_gear and self._ioniq_6_always_ipedal_pending and not CS.ipedal_active and not CC.enabled: if self._ioniq_6_always_ipedal_press_remaining == 0 and self.frame >= self._ioniq_6_always_ipedal_retry_frame: - self._ioniq_6_always_ipedal_press_remaining = IONIQ_6_IPEDAL_PRESS_SEND_COUNT + self._ioniq_6_always_ipedal_press_remaining = IONIQ_6_IPEDAL_LATCH_PRESS_SEND_COUNT if ipedal_latch_pending \ + else IONIQ_6_IPEDAL_PRESS_SEND_COUNT self._ioniq_6_always_ipedal_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(CS.buttons_counter) if self._ioniq_6_always_ipedal_press_remaining > 0 and self.frame % 2 == 0: @@ -297,8 +310,11 @@ class CarController(CarControllerBase): self._ioniq_6_always_ipedal_counter) self._ioniq_6_always_ipedal_press_remaining -= 1 if self._ioniq_6_always_ipedal_press_remaining == 0: - self._ioniq_6_always_ipedal_retry_frame = self.frame + IONIQ_6_IPEDAL_RETRY_WAIT_FRAMES + retry_wait_frames = IONIQ_6_IPEDAL_PROGRESS_RETRY_WAIT_FRAMES if regen_state_changed else IONIQ_6_IPEDAL_RETRY_WAIT_FRAMES + self._ioniq_6_always_ipedal_retry_frame = self.frame + retry_wait_frames + self._ioniq_6_last_ipedal_regen_state = regen_state + self._ioniq_6_last_ipedal_regen_state_2 = regen_state_2 self._ioniq_6_last_gear = gear return can_sends diff --git a/opendbc_repo/opendbc/car/hyundai/carstate.py b/opendbc_repo/opendbc/car/hyundai/carstate.py index 713d65fa3..60cab0c87 100644 --- a/opendbc_repo/opendbc/car/hyundai/carstate.py +++ b/opendbc_repo/opendbc/car/hyundai/carstate.py @@ -24,6 +24,8 @@ BUTTONS_DICT = {Buttons.RES_ACCEL: ButtonType.accelCruise, Buttons.SET_DECEL: Bu IONIQ_6_BLINDSPOT_RIGHT_MASK = 0x08 IONIQ_6_BLINDSPOT_LEFT_MASK = 0x10 +IONIQ_6_IPEDAL_INTERMEDIATE_REGEN_STATE = 0x50 +IONIQ_6_IPEDAL_INTERMEDIATE_REGEN_STATE_2 = 0x01 IONIQ_6_IPEDAL_REGEN_STATE = 0x50 IONIQ_6_IPEDAL_REGEN_STATE_2 = 0x03 @@ -49,6 +51,10 @@ def decode_ioniq_6_ipedal_state(regen_state: int, regen_state_2: int) -> bool: return int(regen_state) == IONIQ_6_IPEDAL_REGEN_STATE and int(regen_state_2) == IONIQ_6_IPEDAL_REGEN_STATE_2 +def decode_ioniq_6_ipedal_intermediate_state(regen_state: int, regen_state_2: int) -> bool: + return int(regen_state) == IONIQ_6_IPEDAL_INTERMEDIATE_REGEN_STATE and int(regen_state_2) == IONIQ_6_IPEDAL_INTERMEDIATE_REGEN_STATE_2 + + class CarState(CarStateBase): @staticmethod def get_canfd_blinker_sig_names(car_fingerprint, use_alt_lamp: bool) -> tuple[str, str]: @@ -69,6 +75,8 @@ class CarState(CarStateBase): self.cancel_button_enable_in_progress = False self.cruise_buttons_msg = {} self.ipedal_active = False + self.ipedal_regen_state = 0 + self.ipedal_regen_state_2 = 0 self.gear_msg_canfd = "ACCELERATOR" if CP.flags & HyundaiFlags.EV else \ "GEAR_ALT" if CP.flags & HyundaiFlags.CANFD_ALT_GEARS else \ @@ -397,8 +405,9 @@ class CarState(CarStateBase): ret.cruiseState.nonAdaptive = cp.vl["MANUAL_SPEED_LIMIT_ASSIST"]["MSLA_ENABLED"] == 1 if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6: msla = cp.vl["MANUAL_SPEED_LIMIT_ASSIST"] - # Tolerate older/stale DBCs that do not yet expose the inferred regen state signals. - self.ipedal_active = decode_ioniq_6_ipedal_state(msla.get("EV_REGEN_STATE", 0), msla.get("EV_REGEN_STATE_2", 0)) + self.ipedal_regen_state = int(msla.get("EV_REGEN_STATE", 0)) + self.ipedal_regen_state_2 = int(msla.get("EV_REGEN_STATE_2", 0)) + self.ipedal_active = decode_ioniq_6_ipedal_state(self.ipedal_regen_state, self.ipedal_regen_state_2) prev_cruise_buttons = self.cruise_buttons[-1] prev_main_buttons = self.main_buttons[-1] diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index 6442d1605..94f0d945e 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -9,7 +9,8 @@ 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 -from opendbc.car.hyundai.carstate import CarState, decode_ioniq_6_blindspot_radar_state, decode_ioniq_6_ipedal_state +from opendbc.car.hyundai.carstate import CarState, decode_ioniq_6_blindspot_radar_state, decode_ioniq_6_ipedal_intermediate_state, \ + decode_ioniq_6_ipedal_state from opendbc.car.hyundai.interface import CarInterface from opendbc.car.hyundai import hyundaican, hyundaicanfd from opendbc.car.hyundai.hyundaicanfd import CanBus @@ -296,6 +297,8 @@ class TestHyundaiFingerprint: def test_ioniq_6_ipedal_state_decode(self): assert not decode_ioniq_6_ipedal_state(0x3C, 0x01) + assert not decode_ioniq_6_ipedal_state(0x50, 0x01) + assert decode_ioniq_6_ipedal_intermediate_state(0x50, 0x01) assert decode_ioniq_6_ipedal_state(0x50, 0x03) def test_ioniq_6_msla_regen_signals_decode(self): @@ -394,6 +397,38 @@ class TestHyundaiFingerprint: assert not controller._ioniq_6_always_ipedal_pending assert controller._ioniq_6_always_ipedal_press_remaining == 0 + def test_ioniq_6_always_ipedal_uses_stronger_followup_pull_for_intermediate_latch_state(self): + toggles = get_test_toggles() + toggles.always_ipedal = True + CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, gen_empty_fingerprint(), [], True, False, False, toggles) + + controller = CarController(DBC[CP.carFingerprint], CP) + cs = SimpleNamespace( + out=SimpleNamespace(gearShifter=structs.CarState.GearShifter.drive), + ipedal_active=False, + ipedal_regen_state=0x50, + ipedal_regen_state_2=0x01, + buttons_counter=5, + cruise_buttons_msg={ + "_CHECKSUM": 0, + "COUNTER": 5, + "CRUISE_BUTTONS": 0, + "ADAPTIVE_CRUISE_MAIN_BTN": 0, + "NORMAL_CRUISE_MAIN_BTN": 0, + "LDA_BTN": 0, + "RIGHT_PADDLE": 0, + "LEFT_PADDLE": 0, + "SET_ME_1": 1, + }, + ) + cc = SimpleNamespace(enabled=False) + + controller._ioniq_6_last_gear = structs.CarState.GearShifter.reverse + sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles) + + assert sends + assert controller._ioniq_6_always_ipedal_press_remaining == 9 + def test_ioniq_6_longitudinal_params_match_canfd_tune(self): toggles = get_test_toggles() CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, gen_empty_fingerprint(), [], True, False, False, toggles) diff --git a/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc b/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc index fb9b336c1..c49508bfd 100644 --- a/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc +++ b/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc @@ -823,7 +823,9 @@ BO_ 736 MANUAL_SPEED_LIMIT_ASSIST: 32 XXX SG_ MSLA_STATUS : 26|2@1+ (1,0) [0|3] "" XXX SG_ MSLA_ENABLED : 38|1@1+ (1,0) [0|1] "" XXX SG_ MAX_SPEED : 55|8@0+ (1,0) [0|255] "" XXX + SG_ EV_REGEN_STATE : 104|8@1+ (1,0) [0|255] "" XXX SG_ MAX_SPEED_COPY : 144|8@1+ (1,0) [0|255] "" XXX + SG_ EV_REGEN_STATE_2 : 184|8@1+ (1,0) [0|255] "" XXX BO_ 837 ADRV_0x345: 8 ADRV SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX