From 1363a5b0447caf7a8aca31ea452794d2679980df Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:30:44 -0500 Subject: [PATCH] fixes --- opendbc_repo/opendbc/car/gm/gmcan.py | 3 ++ opendbc_repo/opendbc/car/gm/tests/test_gm.py | 7 ++++- .../opendbc/car/hyundai/carcontroller.py | 19 ++++++++++-- .../opendbc/car/hyundai/tests/test_hyundai.py | 21 ++++++++++++- starpilot/controls/starpilot_card.py | 7 +++-- .../controls/tests/test_starpilot_card.py | 31 +++++++++++++++++++ 6 files changed, 81 insertions(+), 7 deletions(-) diff --git a/opendbc_repo/opendbc/car/gm/gmcan.py b/opendbc_repo/opendbc/car/gm/gmcan.py index fedd4765de..d4293d1dda 100644 --- a/opendbc_repo/opendbc/car/gm/gmcan.py +++ b/opendbc_repo/opendbc/car/gm/gmcan.py @@ -17,6 +17,8 @@ MALIBU_BUTTON_MAP = { CruiseButtons.CANCEL: 5, } +ACC_CRUISE_STATE_ADAPTIVE = 2 + def malibu_phase_map_for_button(button): key = MALIBU_BUTTON_MAP.get(button) @@ -220,6 +222,7 @@ def create_acc_dashboard_command(packer, bus, enabled, target_speed_kph, hud_con values = { "ACCAlwaysOne": 1, + "ACCCruiseState": ACC_CRUISE_STATE_ADAPTIVE, "ACCResumeButton": 0, "ACCSpeedSetpoint": target_speed, "ACCGapLevel": hud_control.leadDistanceBars * enabled, # 3 "far", 0 "inactive" diff --git a/opendbc_repo/opendbc/car/gm/tests/test_gm.py b/opendbc_repo/opendbc/car/gm/tests/test_gm.py index 4bbaea4c7f..aab995af72 100644 --- a/opendbc_repo/opendbc/car/gm/tests/test_gm.py +++ b/opendbc_repo/opendbc/car/gm/tests/test_gm.py @@ -554,7 +554,11 @@ class TestGMCarController: parser.update([0, [msg]]) - assert parser.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"] == 2 + values = parser.vl["ASCMActiveCruiseControlStatus"] + + assert values["ACCCruiseState"] == 2 + assert values["ACCCmdActive"] == 1 + assert values["FCWAlert"] == 2 def test_acc_dashboard_command_uses_openpilot_hud_when_disengaged(self): packer = CANPacker(DBC[CAR.CHEVROLET_VOLT_ASCM][Bus.pt]) @@ -572,6 +576,7 @@ class TestGMCarController: values = parser.vl["ASCMActiveCruiseControlStatus"] assert values["ACCSpeedSetpoint"] == 50 + assert values["ACCCruiseState"] == 2 assert values["ACCGapLevel"] == 0 assert values["ACCCmdActive"] == 0 assert values["ACCLeadCar"] == 1 diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py index 8d87a7bae4..ff9d8171fc 100644 --- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -53,6 +53,7 @@ IONIQ_6_LAUNCH_HOLD_SPEED_V = [0.75, 0.6, 0.4, 0.0] IONIQ_6_STOP_BRAKE_CAP_MAX_SPEED = 2.0 IONIQ_6_STOP_BRAKE_CAP_SPEED_BP = [0.0, 0.08, 0.25, 0.6, 1.2, 2.0, 3.0] IONIQ_6_STOP_BRAKE_CAP_ACCEL_V = [-0.15, -0.16, -0.22, -0.42, -0.78, -1.15, -1.40] +EV6_GT_LINE_STOP_BRAKE_CAP_MAX_SPEED = 1.2 IONIQ_6_STOP_HOLD_JERK_BP = [0.0, 0.15, 0.6, 1.2, 2.0, 3.0] IONIQ_6_STOP_HOLD_JERK_V = [0.35, 0.40, 0.48, 0.65, 0.85, 1.10] IONIQ_6_STOP_RELEASE_JERK_BP = [0.0, 0.15, 0.5] @@ -122,8 +123,14 @@ def _calculate_ioniq_6_dynamic_lower_jerk(accel_error: float) -> float: return IONIQ_6_LONG_MIN_JERK +def should_use_ev6_gt_line_stop_direct_tracking(ev6_gt_line: bool, stopping: bool, v_ego: float, + accel_cmd: float, actual_accel: float) -> bool: + return bool(ev6_gt_line and stopping and v_ego > EV6_GT_LINE_STOP_BRAKE_CAP_MAX_SPEED and accel_cmd < actual_accel) + + def update_ioniq_6_longitudinal_tuning(state: Ioniq6LongitudinalTuningState, accel_cmd: float, v_ego: float, a_ego: float, - long_control_state: LongCtrlState, long_active: bool) -> Ioniq6LongitudinalTuningState: + long_control_state: LongCtrlState, long_active: bool, + ev6_gt_line: bool = False) -> Ioniq6LongitudinalTuningState: starting = long_control_state == LongCtrlState.starting stopping = long_control_state == LongCtrlState.stopping restart_from_stop = state.long_control_state_last in (LongCtrlState.stopping, LongCtrlState.starting) and \ @@ -165,7 +172,8 @@ def update_ioniq_6_longitudinal_tuning(state: Ioniq6LongitudinalTuningState, acc state.jerk_lower = min(dynamic_lower_jerk, lower_speed_limit) if state.stopping: - if v_ego <= IONIQ_6_STOP_BRAKE_CAP_MAX_SPEED: + stop_brake_cap_max_speed = EV6_GT_LINE_STOP_BRAKE_CAP_MAX_SPEED if ev6_gt_line else IONIQ_6_STOP_BRAKE_CAP_MAX_SPEED + if v_ego <= stop_brake_cap_max_speed: stop_brake_cap = float(np.interp(v_ego, IONIQ_6_STOP_BRAKE_CAP_SPEED_BP, IONIQ_6_STOP_BRAKE_CAP_ACCEL_V)) state.desired_accel = min(0.0, max(accel_cmd, stop_brake_cap)) state.jerk_upper = min(state.jerk_upper, float(np.interp(v_ego, IONIQ_6_STOP_HOLD_JERK_BP, IONIQ_6_STOP_HOLD_JERK_V)) * IONIQ_6_RESPONSE_MULTIPLIER) @@ -487,18 +495,23 @@ class CarController(CarControllerBase): use_egmp_dynamic_long_tuning = egmp_dynamic_longitudinal_tuning(self.CP) and self.long_active_ecu and \ actuators.longControlState in (LongCtrlState.starting, LongCtrlState.pid, LongCtrlState.stopping) + is_ev6_gt_line = kia_ev6_gt_line_longitudinal_tuning(self.CP.carFingerprint, getattr(self.CP, "carVin", "")) if should_reset_ev6_gt_line_longitudinal_tuning(self.CP, actuators.longControlState): self._ioniq_6_long_tuning = reset_ev6_gt_line_longitudinal_tuning(self._ioniq_6_long_tuning, self.CP, actuators.longControlState) elif use_egmp_dynamic_long_tuning and self.frame % 5 == 0: self._ioniq_6_long_tuning = update_ioniq_6_longitudinal_tuning(self._ioniq_6_long_tuning, accel_cmd, CS.out.vEgo, CS.out.aEgo, - actuators.longControlState, self.long_active_ecu) + actuators.longControlState, self.long_active_ecu, + ev6_gt_line=is_ev6_gt_line) use_egmp_smoothed_accel = use_egmp_dynamic_long_tuning and ( accel_cmd >= self._ioniq_6_long_tuning.actual_accel or self._ioniq_6_long_tuning.launch_active or self._ioniq_6_long_tuning.stopping ) + if should_use_ev6_gt_line_stop_direct_tracking(is_ev6_gt_line, self._ioniq_6_long_tuning.stopping, + CS.out.vEgo, accel_cmd, self._ioniq_6_long_tuning.actual_accel): + use_egmp_smoothed_accel = False if use_egmp_dynamic_long_tuning: if use_egmp_smoothed_accel: accel = self._ioniq_6_long_tuning.actual_accel diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index be19fceb65..53266aaed4 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -11,7 +11,8 @@ from opendbc.car.hyundai.carcontroller import CarController, Ioniq6LongitudinalT update_ioniq_6_longitudinal_tuning, \ update_genesis_g90_longitudinal_tuning, egmp_dynamic_longitudinal_tuning, \ should_reset_ev6_gt_line_longitudinal_tuning, reset_ev6_gt_line_longitudinal_tuning, \ - get_angle_smoothing_alpha, apply_ev9_high_angle_gain_cap, ev9_driver_override_active + get_angle_smoothing_alpha, apply_ev9_high_angle_gain_cap, ev9_driver_override_active, \ + should_use_ev6_gt_line_stop_direct_tracking from opendbc.car.hyundai.carstate import CarState, decode_canfd_camera_lead, decode_ioniq_6_blindspot_radar_state from opendbc.car.hyundai.interface import CarInterface from opendbc.car.hyundai import hyundaican, hyundaicanfd @@ -1113,6 +1114,24 @@ class TestHyundaiFingerprint: assert state.desired_accel == pytest.approx(-2.82) assert state.actual_accel < -1.8 + def test_kia_ev6_gt_line_longitudinal_tuning_helper_delays_final_stop_cap(self): + state = Ioniq6LongitudinalTuningState(actual_accel=-2.82, accel_last=-2.82, + long_control_state_last=LongCtrlState.pid) + + state = update_ioniq_6_longitudinal_tuning(state, accel_cmd=-2.82, v_ego=1.8, a_ego=-2.4, + long_control_state=LongCtrlState.stopping, long_active=True, + ev6_gt_line=True) + assert state.stopping + assert state.desired_accel == pytest.approx(-2.82) + assert state.actual_accel == pytest.approx(-2.82) + + def test_kia_ev6_gt_line_prefers_direct_stop_tracking_above_final_band(self): + assert should_use_ev6_gt_line_stop_direct_tracking(True, True, 1.8, -2.05, -1.29) + assert not should_use_ev6_gt_line_stop_direct_tracking(True, True, 1.0, -2.05, -1.29) + assert not should_use_ev6_gt_line_stop_direct_tracking(True, False, 1.8, -2.05, -1.29) + assert not should_use_ev6_gt_line_stop_direct_tracking(False, True, 1.8, -2.05, -1.29) + assert not should_use_ev6_gt_line_stop_direct_tracking(True, True, 1.8, -1.0, -1.29) + def test_genesis_g90_longitudinal_tuning_softens_final_stop_hold(self): state = GenesisG90LongitudinalTuningState() diff --git a/starpilot/controls/starpilot_card.py b/starpilot/controls/starpilot_card.py index a5a1a51208..0562ea4502 100644 --- a/starpilot/controls/starpilot_card.py +++ b/starpilot/controls/starpilot_card.py @@ -37,6 +37,7 @@ class StarPilotCard: getattr(self.CP, "carFingerprint", None) in (HYUNDAI_CAR.KIA_FORTE_2019_NON_SCC, HYUNDAI_CAR.KIA_FORTE_2021_NON_SCC) and bool(hyundai_flags & HyundaiFlags.NON_SCC) ) + self.hyundai_preserve_aol_across_reverse = getattr(self.CP, "carFingerprint", None) == HYUNDAI_CAR.HYUNDAI_SONATA_HYBRID self.hyundai_aol_needs_engagement = self.CP.brand == "hyundai" and not (hyundai_flags & HyundaiFlags.CANFD) and not kia_forte_non_scc self.hyundai_aol_ready = False self.prev_active = False @@ -116,8 +117,10 @@ class StarPilotCard: if self.hyundai_aol_needs_engagement: if carState.gearShifter in NON_DRIVING_GEARS: - self.hyundai_aol_ready = False - self.always_on_lateral_allowed = False + preserve_reverse_latch = self.hyundai_preserve_aol_across_reverse and carState.gearShifter == GearShifter.reverse + if not preserve_reverse_latch: + self.hyundai_aol_ready = False + self.always_on_lateral_allowed = False elif sm["selfdriveState"].active or carState.cruiseState.enabled: self.hyundai_aol_ready = True diff --git a/starpilot/controls/tests/test_starpilot_card.py b/starpilot/controls/tests/test_starpilot_card.py index 7550bdaab4..725e3ef447 100644 --- a/starpilot/controls/tests/test_starpilot_card.py +++ b/starpilot/controls/tests/test_starpilot_card.py @@ -167,6 +167,37 @@ def test_sonata_hybrid_lkas_button_can_start_aol_before_normal_engagement(monkey assert ret.alwaysOnLateralEnabled is True +def test_sonata_hybrid_preserves_aol_latch_across_reverse(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", carFingerprint=spc.HYUNDAI_CAR.HYUNDAI_SONATA_HYBRID), + SimpleNamespace(alternativeExperience=spc.ALTERNATIVE_EXPERIENCE.ALWAYS_ON_LATERAL), + ) + + starpilot_car_state = SimpleNamespace(distancePressed=False) + sm = make_sm() + toggles = make_toggles(always_on_lateral=True, always_on_lateral_lkas=True) + + enabled_state = make_car_state(available=False, enabled=False, button_events=[SimpleNamespace(type=spc.ButtonType.lkas, pressed=True)]) + ret = card.update(enabled_state, starpilot_car_state, sm, toggles) + assert ret.alwaysOnLateralAllowed is True + assert ret.alwaysOnLateralEnabled is True + + reverse_state = make_car_state(available=False, enabled=False) + reverse_state.gearShifter = spc.GearShifter.reverse + ret = card.update(reverse_state, starpilot_car_state, sm, toggles) + assert ret.alwaysOnLateralAllowed is True + assert ret.alwaysOnLateralEnabled is False + + drive_state = make_car_state(available=False, enabled=False) + ret = card.update(drive_state, starpilot_car_state, sm, toggles) + assert ret.alwaysOnLateralAllowed is True + assert ret.alwaysOnLateralEnabled is True + + 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)