diff --git a/opendbc_repo/opendbc/car/toyota/carstate.py b/opendbc_repo/opendbc/car/toyota/carstate.py index d73b8663d8..e8c41a5df7 100644 --- a/opendbc_repo/opendbc/car/toyota/carstate.py +++ b/opendbc_repo/opendbc/car/toyota/carstate.py @@ -23,6 +23,7 @@ TEMP_STEER_FAULTS = (0, 9, 11, 21, 25) # - lka/lta msg drop out: 3 (recoverable) # - prolonged high driver torque: 17 (permanent) PERM_STEER_FAULTS = (3, 17) +LKAS_BUTTON_CAR = TSS2_CAR | {CAR.TOYOTA_PRIUS} # Traffic signals for Speed Limit Controller - Credit goes to the DragonPilot team! @@ -43,6 +44,13 @@ def calculate_interceptor_gas_pressed(cp) -> bool: return interceptor_gas > 805 +def create_lkas_button_events(lkas_button: int, prev_lkas_button: int) -> list[structs.CarState.ButtonEvent]: + if lkas_button != 0 and lkas_button != prev_lkas_button: + return (create_button_events(1, 0, {1: ButtonType.lkas}) + + create_button_events(0, 1, {1: ButtonType.lkas})) + return [] + + class CarState(CarStateBase): def __init__(self, CP, FPCP): super().__init__(CP, FPCP) @@ -220,16 +228,12 @@ class CarState(CarStateBase): self.pcm_follow_distance = cp.vl["PCM_CRUISE_2"]["PCM_FOLLOW_DISTANCE"] buttonEvents = [] - if self.CP.carFingerprint in TSS2_CAR: - # lkas button is wired to the camera + if self.CP.carFingerprint in LKAS_BUTTON_CAR: prev_lkas_button = self.lkas_button self.lkas_button = cp_cam.vl["LKAS_HUD"]["LDA_ON_MESSAGE"] + buttonEvents += create_lkas_button_events(self.lkas_button, prev_lkas_button) - # Cycles between 1 and 2 when pressing the button, then rests back at 0 after ~3s - if self.lkas_button != 0 and self.lkas_button != prev_lkas_button: - buttonEvents.extend(create_button_events(1, 0, {1: ButtonType.lkas}) + - create_button_events(0, 1, {1: ButtonType.lkas})) - + if self.CP.carFingerprint in TSS2_CAR: if self.CP.carFingerprint not in (RADAR_ACC_CAR | SECOC_CAR): # distance button is wired to the ACC module (camera or radar) prev_distance_button = self.distance_button diff --git a/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py b/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py index dc10379ec1..020037c6d3 100644 --- a/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py +++ b/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py @@ -11,7 +11,7 @@ from opendbc.car.toyota import toyotacan from opendbc.car.toyota.carcontroller import CarController, get_long_tune, get_prius_positive_feedforward_scale, limit_interceptor_pcm_accel, \ limit_interceptor_stopping_accel, limit_no_lead_cruise_sign_flip, \ limit_prius_stopping_accel, update_permit_braking -from opendbc.car.toyota.carstate import calculate_interceptor_gas_pressed +from opendbc.car.toyota.carstate import LKAS_BUTTON_CAR, calculate_interceptor_gas_pressed, create_lkas_button_events from opendbc.car.toyota.fingerprints import FW_VERSIONS from opendbc.car.toyota.interface import CarInterface from opendbc.car.toyota.radar_interface import RadarInterface, TSSP_RADAR_EGO_SPEED_SCALE @@ -610,6 +610,29 @@ class TestToyotaCarController: class TestToyotaCarState: + def test_lkas_button_platforms(self): + assert CAR.TOYOTA_PRIUS in LKAS_BUTTON_CAR + assert TSS2_CAR <= LKAS_BUTTON_CAR + assert CAR.TOYOTA_CAMRY not in LKAS_BUTTON_CAR + assert CAR.LEXUS_RX not in LKAS_BUTTON_CAR + + @pytest.mark.parametrize("lkas_button,prev_lkas_button,event_count", [ + (0, 0, 0), + (1, 0, 2), + (1, 1, 0), + (0, 1, 0), + (2, 1, 2), + ]) + def test_lkas_button_events(self, lkas_button, prev_lkas_button, event_count): + events = create_lkas_button_events(lkas_button, prev_lkas_button) + + assert len(events) == event_count + if events: + assert [(event.type, event.pressed) for event in events] == [ + (structs.CarState.ButtonEvent.Type.lkas, True), + (structs.CarState.ButtonEvent.Type.lkas, False), + ] + def test_interceptor_gas_pressed_threshold(self): cp = SimpleNamespace(vl={ "GAS_SENSOR": { diff --git a/starpilot/controls/tests/test_starpilot_card.py b/starpilot/controls/tests/test_starpilot_card.py index 0f1b99d0da..e4a5ec598a 100644 --- a/starpilot/controls/tests/test_starpilot_card.py +++ b/starpilot/controls/tests/test_starpilot_card.py @@ -556,6 +556,19 @@ def test_cancel_button_short_press_can_run_independent_mapping(monkeypatch, tmp_ assert card.params_memory.get_int("WheelButtonBookmarkCounter") == 1 +def test_lkas_button_press_creates_bookmark(monkeypatch, tmp_path): + monkeypatch.setattr(spc, "Params", FakeParams) + monkeypatch.setattr(spc, "is_FrogsGoMoo", lambda: False) + monkeypatch.setattr(spc, "ERROR_LOGS_PATH", tmp_path) + + card = spc.StarPilotCard(SimpleNamespace(brand="toyota"), SimpleNamespace(alternativeExperience=0)) + car_state = make_car_state(button_events=[SimpleNamespace(type=spc.ButtonType.lkas, pressed=True)]) + + card.update(car_state, SimpleNamespace(distancePressed=False), make_sm(), make_toggles(bookmark_via_lkas=True)) + + assert card.params_memory.get_int("WheelButtonBookmarkCounter") == 1 + + def test_favorite_wheel_action_toggles_hidden_onroad_slot(monkeypatch, tmp_path): monkeypatch.setattr(spc, "Params", FakeParams) monkeypatch.setattr(spc, "is_FrogsGoMoo", lambda: False)