From 79e31ff24131ad9d948935d4c298856d33fc34d8 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Wed, 10 Jun 2026 22:30:48 -0500 Subject: [PATCH] TRY AGAIN, SPIDERMAN --- .../opendbc/car/hyundai/tests/test_hyundai.py | 34 +++++----------- opendbc_repo/opendbc/car/hyundai/values.py | 1 - selfdrive/car/redneck_cruise.py | 8 +++- selfdrive/car/tests/test_redneck_cruise.py | 34 ++++++++++++++++ selfdrive/controls/lib/latcontrol_torque.py | 16 ++++---- starpilot/controls/starpilot_card.py | 12 +++--- .../controls/tests/test_starpilot_card.py | 40 ++++++++++--------- 7 files changed, 87 insertions(+), 58 deletions(-) diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index da8bbe01e..4d162997f 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -683,7 +683,7 @@ class TestHyundaiFingerprint: ret = update(0, 3) assert any(be.type == ButtonType.lkas and not be.pressed for be in ret.buttonEvents) - def test_sonata_hybrid_uses_alt_bus_lkas_parser(self): + def test_sonata_hybrid_uses_main_bus_lkas_parser(self): toggles = get_test_toggles() fingerprint = gen_empty_fingerprint() fingerprint[0][0x391] = 8 @@ -694,9 +694,9 @@ class TestHyundaiFingerprint: car_state = CarState(CP, FPCP) can_parsers = car_state.get_can_parsers(CP) - assert Bus.alt in can_parsers + assert Bus.alt not in can_parsers - def test_sonata_hybrid_alt_bus_clu13_lkas_button_event(self): + def test_sonata_hybrid_bcm_lkas_button_event(self): toggles = get_test_toggles() fingerprint = gen_empty_fingerprint() fingerprint[0][0x391] = 8 @@ -709,18 +709,20 @@ class TestHyundaiFingerprint: packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) def update(lkas_button: int, frame: int): - msg = packer.make_can_msg("CLU13", 1, { - "CF_Clu_LdwsLkasSW": lkas_button, + msg = packer.make_can_msg("BCM_PO_11", 0, { + "LDA_BTN": lkas_button, }) - can_parsers[Bus.alt].update([(frame, [msg])]) + can_parsers[Bus.pt].update([(frame, [msg])]) return car_state.update(can_parsers, toggles)[0] update(0, 1) ret = update(1, 2) assert any(be.type == ButtonType.lkas and be.pressed for be in ret.buttonEvents) + + ret = update(0, 3) assert any(be.type == ButtonType.lkas and not be.pressed for be in ret.buttonEvents) - def test_sonata_hybrid_alt_bus_initial_high_does_not_emit_lkas_button_event(self): + def test_sonata_hybrid_ignores_noisy_alt_bus_clu13_lkas_button(self): toggles = get_test_toggles() fingerprint = gen_empty_fingerprint() fingerprint[0][0x391] = 8 @@ -730,24 +732,8 @@ class TestHyundaiFingerprint: car_state = CarState(CP, FPCP) can_parsers = car_state.get_can_parsers(CP) - packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) - def update(lkas_button: int, frame: int): - msg = packer.make_can_msg("CLU13", 1, { - "CF_Clu_LdwsLkasSW": lkas_button, - }) - can_parsers[Bus.alt].update([(frame, [msg])]) - return car_state.update(can_parsers, toggles)[0] - - ret = update(1, 1) - assert not any(be.type == ButtonType.lkas for be in ret.buttonEvents) - - ret = update(0, 2) - assert not any(be.type == ButtonType.lkas for be in ret.buttonEvents) - - ret = update(1, 3) - assert any(be.type == ButtonType.lkas and be.pressed for be in ret.buttonEvents) - assert any(be.type == ButtonType.lkas and not be.pressed for be in ret.buttonEvents) + assert Bus.alt not in can_parsers def test_sonata_alt_bus_clu13_swl_stat_lkas_button_event(self): toggles = get_test_toggles() diff --git a/opendbc_repo/opendbc/car/hyundai/values.py b/opendbc_repo/opendbc/car/hyundai/values.py index f1dd2ddb2..37a5b7636 100644 --- a/opendbc_repo/opendbc/car/hyundai/values.py +++ b/opendbc_repo/opendbc/car/hyundai/values.py @@ -917,7 +917,6 @@ CANCEL_BUTTON_ENABLE_CARS = frozenset({ # engage/disengage regression. ALT_BUS_LDA_BUTTON_CARS = frozenset({ CAR.HYUNDAI_SONATA, - CAR.HYUNDAI_SONATA_HYBRID, }) # On these Sonata layouts the alt-bus LKAS button pulses through the CLU13 diff --git a/selfdrive/car/redneck_cruise.py b/selfdrive/car/redneck_cruise.py index 3431be15f..3588ecec1 100644 --- a/selfdrive/car/redneck_cruise.py +++ b/selfdrive/car/redneck_cruise.py @@ -13,7 +13,9 @@ HYST_GAP = 0.0 INCREASE_INACTIVE_TIMER = 0.12 DECREASE_INACTIVE_TIMER = 0.05 LEAD_INCREASE_INACTIVE_TIMER = 0.05 +MANUAL_BUTTON_INACTIVE_TIMER = 0.5 LEAD_RECOVERY_LOOKAHEAD_POINTS = 4 +LEAD_RECOVERY_HOLD_BUFFER_MS = 0.5 * CV.MPH_TO_MS LEAD_COAST_BUFFER_MS = 1.0 * CV.MPH_TO_MS CRUISE_BUTTON_TIMERS = { @@ -43,6 +45,10 @@ def select_redneck_target_speed(v_cruise_kph: float, speed_cluster_ms: float, return min(target_speed_ms, recovery_target_speed_ms) decrease_target_speed_ms = min(plan_speeds_ms[:lookahead_points]) + if lead_present and target_speed_ms > speed_cluster_ms and \ + decrease_target_speed_ms >= speed_cluster_ms - LEAD_RECOVERY_HOLD_BUFFER_MS: + return speed_cluster_ms + if lead_present and decrease_target_speed_ms < speed_cluster_ms: decrease_target_speed_ms = max(0.0, decrease_target_speed_ms - LEAD_COAST_BUFFER_MS) @@ -107,7 +113,7 @@ class RedneckCruise: def _update_readiness(self, CS: car.CarState, CC: car.CarControl) -> None: update_manual_button_timers(CS, self.cruise_button_timers) - button_pressed = any(timer > 0 for timer in self.cruise_button_timers.values()) + button_pressed = any(0 < timer <= int(MANUAL_BUTTON_INACTIVE_TIMER / DT_CTRL) for timer in self.cruise_button_timers.values()) self.is_ready = CC.enabled and not CC.cruiseControl.override and not CC.cruiseControl.cancel and not CC.cruiseControl.resume and not button_pressed def _desired_state(self) -> str: diff --git a/selfdrive/car/tests/test_redneck_cruise.py b/selfdrive/car/tests/test_redneck_cruise.py index efef2024f..6d3ffdc18 100644 --- a/selfdrive/car/tests/test_redneck_cruise.py +++ b/selfdrive/car/tests/test_redneck_cruise.py @@ -8,6 +8,7 @@ from openpilot.selfdrive.car.redneck_cruise import ( DECREASE_INACTIVE_TIMER, INCREASE_INACTIVE_TIMER, LEAD_INCREASE_INACTIVE_TIMER, + MANUAL_BUTTON_INACTIVE_TIMER, RedneckCruise, SEND_BUTTON_DECREASE, SEND_BUTTON_INCREASE, @@ -106,6 +107,27 @@ class TestRedneckCruise(unittest.TestCase): send_button, _ = self._run_until_active(target_mph=25.0, speed_cluster_mph=20.0, button_events=[button_event]) self.assertEqual(SEND_BUTTON_NONE, send_button) + def test_missing_button_release_only_suppresses_temporarily(self): + button_event = self._button_event(ButtonType.accelCruise, True) + send_button, _ = self.redneck.run( + self._new_state(speed_cluster_mph=20.0, button_events=[button_event]), + self._new_control(), + 25.0 * CV.MPH_TO_MS, + is_metric=False, + ) + self.assertEqual(SEND_BUTTON_NONE, send_button) + + frames = int((MANUAL_BUTTON_INACTIVE_TIMER + INCREASE_INACTIVE_TIMER) / DT_CTRL) + 4 + for _ in range(frames): + send_button, _ = self.redneck.run( + self._new_state(speed_cluster_mph=20.0), + self._new_control(), + 25.0 * CV.MPH_TO_MS, + is_metric=False, + ) + + self.assertEqual(SEND_BUTTON_INCREASE, send_button) + def test_suppresses_output_for_capnp_style_button_events(self): button_event = SimpleNamespace(type=SimpleNamespace(raw=int(ButtonType.accelCruise)), pressed=True) send_button, _ = self._run_until_active(target_mph=25.0, speed_cluster_mph=20.0, button_events=[button_event]) @@ -182,6 +204,18 @@ class TestRedneckCruise(unittest.TestCase): ) self.assertAlmostEqual(55.8 * CV.MPH_TO_MS, target_speed) + def test_target_speed_holds_current_step_during_lead_recovery(self): + target_speed = select_redneck_target_speed( + 128.0, + 79.0 * CV.MPH_TO_MS, + 0.0, + [78.56 * CV.MPH_TO_MS, 78.56 * CV.MPH_TO_MS, 78.56 * CV.MPH_TO_MS, 78.56 * CV.MPH_TO_MS], + 10, + allow_plan_decrease=True, + lead_present=True, + ) + self.assertAlmostEqual(79.0 * CV.MPH_TO_MS, target_speed) + def test_target_speed_does_not_use_recovery_branch_when_cluster_is_above_internal_max(self): target_speed = select_redneck_target_speed( 45.0, diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 33e250d87..148866bb6 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -317,9 +317,9 @@ ELANTRA_NON_SCC_TURN_IN_BOOST_RIGHT = 0.12 ELANTRA_NON_SCC_UNWIND_TAPER_LEFT = 0.22 ELANTRA_NON_SCC_UNWIND_TAPER_RIGHT = 0.12 -KIA_FORTE_BASE_LAT_ACCEL_FACTOR_MULT = 1.10 -KIA_FORTE_FF_REDUCTION_LEFT = 0.10 -KIA_FORTE_FF_REDUCTION_RIGHT = 0.24 +KIA_FORTE_BASE_LAT_ACCEL_FACTOR_MULT = 1.05 +KIA_FORTE_FF_REDUCTION_LEFT = 0.05 +KIA_FORTE_FF_REDUCTION_RIGHT = 0.10 KIA_FORTE_FF_ONSET = 0.16 KIA_FORTE_FF_ONSET_WIDTH = 0.06 KIA_FORTE_FF_CUTOFF = 1.20 @@ -327,16 +327,16 @@ KIA_FORTE_FF_CUTOFF_WIDTH = 0.36 KIA_FORTE_TRANSITION_SPEED = 9.0 KIA_FORTE_PHASE_SCALE = 0.10 KIA_FORTE_TURN_IN_BOOST_LEFT = 0.10 -KIA_FORTE_TURN_IN_BOOST_RIGHT = 0.00 -KIA_FORTE_UNWIND_TAPER_LEFT = 0.26 -KIA_FORTE_UNWIND_TAPER_RIGHT = 0.04 +KIA_FORTE_TURN_IN_BOOST_RIGHT = 0.05 +KIA_FORTE_UNWIND_TAPER_LEFT = 0.18 +KIA_FORTE_UNWIND_TAPER_RIGHT = 0.02 KIA_FORTE_CRAWL_TURN_IN_FF_BOOST_LEFT = 0.10 KIA_FORTE_CRAWL_TURN_IN_FF_BOOST_RIGHT = 0.14 KIA_FORTE_CRAWL_TURN_IN_FF_SPEED = 4.5 KIA_FORTE_CRAWL_TURN_IN_FF_SPEED_WIDTH = 0.8 KIA_FORTE_CRAWL_TURN_IN_FF_LAT = 0.10 KIA_FORTE_CRAWL_TURN_IN_FF_LAT_WIDTH = 0.05 -KIA_FORTE_CENTER_TAPER_MAX = 0.18 +KIA_FORTE_CENTER_TAPER_MAX = 0.12 KIA_FORTE_CENTER_TAPER_LAT = 0.18 KIA_FORTE_CENTER_TAPER_LAT_WIDTH = 0.04 KIA_FORTE_CENTER_TAPER_SPEED = 22.5 @@ -347,7 +347,7 @@ KIA_FORTE_FRICTION_SPEED = 24.0 KIA_FORTE_FRICTION_SPEED_WIDTH = 3.0 KIA_FORTE_FRICTION_CALM_JERK = 0.24 KIA_FORTE_FRICTION_CALM_JERK_WIDTH = 0.08 -KIA_FORTE_FRICTION_THRESHOLD_GAIN = 0.18 +KIA_FORTE_FRICTION_THRESHOLD_GAIN = 0.10 PALISADE_BASE_LAT_ACCEL_FACTOR_MULT = 0.98 PALISADE_FF_GAIN_LEFT = 0.14 diff --git a/starpilot/controls/starpilot_card.py b/starpilot/controls/starpilot_card.py index e6b7f2f4f..2a3a17fc9 100644 --- a/starpilot/controls/starpilot_card.py +++ b/starpilot/controls/starpilot_card.py @@ -103,22 +103,24 @@ class StarPilotCard: self.switchback_mode_enabled = self.params_memory.get_bool("SwitchbackModeEnabled") if self.hyundai_aol_needs_engagement: - if carState.gearShifter in NON_DRIVING_GEARS or not carState.cruiseState.available: + if carState.gearShifter in NON_DRIVING_GEARS: self.hyundai_aol_ready = False self.always_on_lateral_allowed = False elif sm["selfdriveState"].active or carState.cruiseState.enabled: self.hyundai_aol_ready = True - can_toggle_aol = not self.hyundai_aol_needs_engagement or self.hyundai_aol_ready - if self.CP.brand == "hyundai" or starpilot_toggles.lkas_allowed_for_aol: for be in carState.buttonEvents: - if be.type == ButtonType.lkas and be.pressed and starpilot_toggles.always_on_lateral_lkas and can_toggle_aol: + if be.type == ButtonType.lkas and be.pressed and starpilot_toggles.always_on_lateral_lkas: + if self.hyundai_aol_needs_engagement: + self.hyundai_aol_ready = True self.always_on_lateral_allowed = not self.always_on_lateral_allowed if carState.cruiseState.enabled or self.pause_lateral: self.pause_lateral = not self.always_on_lateral_allowed elif be.type == ButtonType.mainCruise and be.pressed: - if starpilot_toggles.main_cruise_aol_toggle and can_toggle_aol: + if starpilot_toggles.main_cruise_aol_toggle: + if self.hyundai_aol_needs_engagement: + self.hyundai_aol_ready = True self.always_on_lateral_allowed = not self.always_on_lateral_allowed elif starpilot_toggles.main_cruise_slc_adopt and starpilot_toggles.speed_limit_controller: self.params_memory.put_bool("SLCAdoptSpeedLimit", True) diff --git a/starpilot/controls/tests/test_starpilot_card.py b/starpilot/controls/tests/test_starpilot_card.py index 2a2e67447..63bedaf16 100644 --- a/starpilot/controls/tests/test_starpilot_card.py +++ b/starpilot/controls/tests/test_starpilot_card.py @@ -97,7 +97,7 @@ def test_honda_lkas_button_can_toggle_always_on_lateral(monkeypatch, tmp_path): assert ret.pauseLateral is False -def test_hyundai_lkas_button_waits_for_normal_engagement_before_aol(monkeypatch, tmp_path): +def test_hyundai_lkas_button_can_start_aol_before_normal_engagement(monkeypatch, tmp_path): monkeypatch.setattr(spc, "Params", FakeParams) monkeypatch.setattr(spc, "is_FrogsGoMoo", lambda: False) monkeypatch.setattr(spc, "ERROR_LOGS_PATH", tmp_path) @@ -117,17 +117,9 @@ def test_hyundai_lkas_button_waits_for_normal_engagement_before_aol(monkeypatch, ret = card.update(car_state, starpilot_car_state, sm, toggles) - assert ret.alwaysOnLateralAllowed is False - assert ret.alwaysOnLateralEnabled is False - - sm["selfdriveState"].active = True - car_state.buttonEvents = [] - ret = card.update(car_state, starpilot_car_state, sm, toggles) - assert ret.alwaysOnLateralAllowed is True assert ret.alwaysOnLateralEnabled is True - sm["selfdriveState"].active = False car_state.buttonEvents = [SimpleNamespace(type=spc.ButtonType.lkas, pressed=True)] ret = card.update(car_state, starpilot_car_state, sm, toggles) @@ -135,6 +127,23 @@ def test_hyundai_lkas_button_waits_for_normal_engagement_before_aol(monkeypatch, assert ret.pauseLateral is False +def test_hyundai_aol_does_not_auto_start_from_cruise_availability(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="hyundai"), + SimpleNamespace(alternativeExperience=spc.ALTERNATIVE_EXPERIENCE.ALWAYS_ON_LATERAL), + ) + + ret = card.update(make_car_state(available=True), SimpleNamespace(distancePressed=False), make_sm(), + make_toggles(always_on_lateral=True, always_on_lateral_lkas=True)) + + assert ret.alwaysOnLateralAllowed is False + assert ret.alwaysOnLateralEnabled is False + + def test_hyundai_canfd_lkas_button_can_toggle_aol_before_engagement(monkeypatch, tmp_path): monkeypatch.setattr(spc, "Params", FakeParams) monkeypatch.setattr(spc, "is_FrogsGoMoo", lambda: False) @@ -181,7 +190,7 @@ def test_kia_forte_non_scc_main_cruise_button_can_toggle_aol_before_engagement(m assert ret.alwaysOnLateralEnabled is True -def test_hyundai_main_cruise_button_toggles_aol_when_assigned_to_aol(monkeypatch, tmp_path): +def test_hyundai_main_cruise_button_can_start_aol_before_normal_engagement(monkeypatch, tmp_path): monkeypatch.setattr(spc, "Params", FakeParams) monkeypatch.setattr(spc, "is_FrogsGoMoo", lambda: False) monkeypatch.setattr(spc, "ERROR_LOGS_PATH", tmp_path) @@ -197,17 +206,10 @@ def test_hyundai_main_cruise_button_toggles_aol_when_assigned_to_aol(monkeypatch toggles = make_toggles(always_on_lateral=True, main_cruise_aol_toggle=True) ret = card.update(car_state, starpilot_car_state, sm, toggles) - assert ret.alwaysOnLateralAllowed is False - - sm["selfdriveState"].active = True - car_state.buttonEvents = [] - ret = card.update(car_state, starpilot_car_state, sm, toggles) - assert ret.alwaysOnLateralAllowed is False + assert ret.alwaysOnLateralAllowed is True + assert ret.alwaysOnLateralEnabled is True car_state.buttonEvents = [SimpleNamespace(type=spc.ButtonType.mainCruise, pressed=True)] - ret = card.update(car_state, starpilot_car_state, sm, toggles) - assert ret.alwaysOnLateralAllowed is True - ret = card.update(car_state, starpilot_car_state, sm, toggles) assert ret.alwaysOnLateralAllowed is False