diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py index 825e70006f..75a681fb31 100644 --- a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py +++ b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py @@ -123,7 +123,12 @@ def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, else: lkas_values = copy.copy(control_values) lkas_values["LKA_AVAILABLE"] = 0 - if CP.carFingerprint in (CAR.KIA_CARNIVAL_4TH_GEN, CAR.KIA_CARNIVAL_2025, CAR.KIA_CARNIVAL_HEV_4TH_GEN): + if CP.carFingerprint in ( + CAR.KIA_CARNIVAL_4TH_GEN, + CAR.KIA_CARNIVAL_2025, + CAR.KIA_CARNIVAL_HEV_4TH_GEN, + CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN, + ): lkas_values["DAMP_FACTOR"] = 100 if lfa_base_values: diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index 85fcd065a7..ac82b0a3b1 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -2535,7 +2535,7 @@ class TestHyundaiFingerprint: assert parser.vl["LKAS_ALT"]["ADAS_ACIAnglTqRedcGainVal"] == pytest.approx(0.0) assert parser.vl["LKAS_ALT"]["ADAS_StrAnglReqVal"] == pytest.approx(8.5) - def test_gv70_electrified_uses_generic_lkas_status_payload(self): + def test_gv70_electrified_uses_clean_damped_lkas_status_payload(self): CP = CarParams.new_message() CP.carFingerprint = CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_LKA_STEERING) @@ -2580,11 +2580,11 @@ class TestHyundaiFingerprint: parser.update([(1, lkas_msgs)]) assert parser.can_valid assert parser.vl["LKAS"]["HAS_LANE_SAFETY"] == 0 - assert parser.vl["LKAS"]["DAMP_FACTOR"] == 0 + assert parser.vl["LKAS"]["DAMP_FACTOR"] == 100 assert parser.vl["LKAS"]["TORQUE_REQUEST"] == 0 assert parser.vl["LKAS"]["STEER_REQ"] == 1 - assert parser.vl["LKAS"]["STEER_MODE"] == 0 - assert parser.vl["LKAS"]["NEW_SIGNAL_2"] == 0 + assert parser.vl["LKAS"]["STEER_MODE"] == 2 + assert parser.vl["LKAS"]["NEW_SIGNAL_2"] == 3 lfa_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LFA", 0)], can_bus.ECAN) lfa_msgs = hyundaicanfd.create_steering_messages(controller.packer, CP, can_bus, True, True, 0, 0.0) @@ -2608,6 +2608,27 @@ class TestHyundaiFingerprint: if controller.packer.dbc.addr_to_msg[addr].name in ("LFA", "LKAS")] assert steering_names == [("LFA", can_bus.ECAN), ("LKAS", can_bus.ACAN)] + def test_gv70_electrified_stock_long_uses_damped_lkas_request(self): + CP = CarParams.new_message() + CP.carFingerprint = CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN + CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_LKA_STEERING) + CP.openpilotLongitudinalControl = False + + controller = CarController(DBC[CP.carFingerprint], CP) + can_bus = CanBus(CP) + parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS", 0)], can_bus.ACAN) + msgs = hyundaicanfd.create_steering_messages(controller.packer, CP, can_bus, True, True, 123, 0.0) + + assert [(controller.packer.dbc.addr_to_msg[addr].name, bus) for addr, _, bus in msgs] == [("LKAS", can_bus.ACAN)] + parser.update([(1, msgs)]) + assert parser.can_valid + assert parser.vl["LKAS"]["TORQUE_REQUEST"] == 123 + assert parser.vl["LKAS"]["STEER_REQ"] == 1 + assert parser.vl["LKAS"]["HAS_LANE_SAFETY"] == 0 + assert parser.vl["LKAS"]["DAMP_FACTOR"] == 100 + assert parser.vl["LKAS"]["STEER_MODE"] == 2 + assert parser.vl["LKAS"]["NEW_SIGNAL_2"] == 3 + @pytest.mark.parametrize(("car", "powertrain_flag"), [ (CAR.HYUNDAI_IONIQ_5, HyundaiFlags.EV), (CAR.HYUNDAI_IONIQ_6, HyundaiFlags.EV), diff --git a/opendbc_repo/opendbc/car/toyota/carcontroller.py b/opendbc_repo/opendbc/car/toyota/carcontroller.py index 531b2bf7be..10ad8cdced 100644 --- a/opendbc_repo/opendbc/car/toyota/carcontroller.py +++ b/opendbc_repo/opendbc/car/toyota/carcontroller.py @@ -47,6 +47,7 @@ TOYOTA_AUTO_HOLD_ACTIVATION_FRAMES = 100 # EPS faults if you apply torque while the steering rate is above 100 deg/s for too long MAX_STEER_RATE = 100 # deg/s MAX_STEER_RATE_FRAMES = 18 # tx control frames needed before torque can be cut +TOYOTA_COROLLA_TSS2_MAX_STEER_RATE_FRAMES = 8 # EPS allows user torque above threshold for 50 frames before permanently faulting MAX_USER_TORQUE = 500 @@ -77,6 +78,11 @@ def should_bypass_toyota_long_pid(CP, starpilot_toggles=None) -> bool: ) or highlander_sdsu) +def get_steer_rate_limit_frames(car_fingerprint) -> int: + return (TOYOTA_COROLLA_TSS2_MAX_STEER_RATE_FRAMES + if car_fingerprint == CAR.TOYOTA_COROLLA_TSS2 else MAX_STEER_RATE_FRAMES) + + def supports_toyota_auto_hold(CP, auto_hold_enabled: bool) -> bool: return ( auto_hold_enabled and @@ -244,6 +250,7 @@ class CarController(CarControllerBase): self.standstill_req = False self.permit_braking = True self.steer_rate_counter = 0 + self.steer_rate_limit_frames = get_steer_rate_limit_frames(self.CP.carFingerprint) self.distance_button = 0 # *** start long control state *** @@ -363,7 +370,7 @@ class CarController(CarControllerBase): # >100 degree/sec steering fault prevention self.steer_rate_counter, apply_steer_req = common_fault_avoidance( abs(CS.out.steeringRateDeg) >= MAX_STEER_RATE, lat_active, - self.steer_rate_counter, MAX_STEER_RATE_FRAMES, + self.steer_rate_counter, self.steer_rate_limit_frames, ) if not lat_active: diff --git a/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py b/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py index 72e026d69c..c88b31d494 100644 --- a/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py +++ b/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py @@ -11,6 +11,7 @@ from opendbc.car.toyota import toyotacan from opendbc.car.toyota.carcontroller import CarController, get_camry_hybrid_feedforward, get_long_tune, get_prius_feedforward, \ get_prius_positive_feedforward_scale, \ get_rav4_interceptor_pedal_scale, \ + get_steer_rate_limit_frames, \ limit_interceptor_pcm_accel, \ limit_interceptor_stopping_accel, limit_no_lead_cruise_sign_flip, \ limit_prius_stopping_accel, should_bypass_toyota_long_pid, supports_toyota_auto_hold, \ @@ -734,6 +735,10 @@ class TestToyotaFingerprint: class TestToyotaCarController: + def test_corolla_tss2_uses_early_steer_rate_fault_guard(self): + assert get_steer_rate_limit_frames(CAR.TOYOTA_COROLLA_TSS2) == 8 + assert get_steer_rate_limit_frames(CAR.TOYOTA_RAV4_TSS2) == 18 + @staticmethod def _make_controller(*, standstill_req=False, last_standstill=False): controller = CarController.__new__(CarController) diff --git a/selfdrive/ui/tests/test_device_screen_settings.py b/selfdrive/ui/tests/test_device_screen_settings.py index 95907d62ed..5094b09382 100644 --- a/selfdrive/ui/tests/test_device_screen_settings.py +++ b/selfdrive/ui/tests/test_device_screen_settings.py @@ -113,6 +113,32 @@ def test_standby_blanks_after_timeout_and_touch_wakes(monkeypatch): assert device._calculate_brightness() == 45 +def test_standby_powers_down_onroad_and_touch_wakes(monkeypatch): + now = 100.0 + monkeypatch.setattr(ui_state_module.time, "monotonic", lambda: now) + monkeypatch.setattr(ui_state_module, "PC", False) + display_power = [] + monkeypatch.setattr(ui_state_module.HARDWARE, "set_display_power", display_power.append) + device, state = make_device(monkeypatch, StandbyMode=True) + state.started = True + state.ignition = True + device._ignition = True + device._interaction_time = now - 1 + + device._update_wakefulness() + + assert display_power == [False] + assert not device.awake + assert device._calculate_brightness() == 0 + + monkeypatch.setattr(ui_state_module.gui_app, "_mouse_events", [SimpleNamespace(left_down=True)]) + device._update_wakefulness() + + assert display_power == [False, True] + assert device.awake + assert device._calculate_brightness() == 45 + + def test_hide_ui_blanks_after_timeout_and_touch_wakes(monkeypatch): now = 100.0 monkeypatch.setattr(ui_state_module.time, "monotonic", lambda: now) diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index e7f9fbfb74..6fc17569d5 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -465,7 +465,10 @@ class Device: callback() self._prev_timed_out = interaction_timeout - self._set_awake(ui_state.ignition or not interaction_timeout or PC) + standby_active = ui_state.started and self._standby_mode + keep_display_awake = not interaction_timeout or PC + keep_display_awake |= ui_state.ignition and not standby_active + self._set_awake(keep_display_awake) @staticmethod def _visible_onroad_alert() -> bool: diff --git a/starpilot/system/the_galaxy/assets/mobile/js/components/NavigationDestinationPanel.js b/starpilot/system/the_galaxy/assets/mobile/js/components/NavigationDestinationPanel.js index 229b1d5e90..29e3da518f 100644 --- a/starpilot/system/the_galaxy/assets/mobile/js/components/NavigationDestinationPanel.js +++ b/starpilot/system/the_galaxy/assets/mobile/js/components/NavigationDestinationPanel.js @@ -108,6 +108,9 @@ export const NavigationDestinationPanel = { }).slice(0, 10) }, }, + methods: { + secondaryLabel, + }, async mounted() { await this.load() }, diff --git a/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py b/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py index 5bf53c99dc..8290b0bea1 100644 --- a/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py +++ b/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py @@ -480,6 +480,7 @@ def test_ui_all_remaining_classic_tools_native_no_embed(): assert "mapboxSuggest" in destination and "mapboxRetrieve" in destination assert "mapboxGeocode" in destination and "mapboxDirections" in destination assert "ref=\"map\"" in destination and "setNavigation(this.destination)" in destination + assert "methods: {" in destination and "secondaryLabel," in destination assert _read("js/components/LateralTuningPanel.js") # Shared API surface added for the second batch of ported pages.