This commit is contained in:
firestar5683
2026-07-02 11:30:44 -05:00
parent 60406cb982
commit 1363a5b044
6 changed files with 81 additions and 7 deletions
+3
View File
@@ -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"
+6 -1
View File
@@ -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
@@ -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
@@ -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()
+5 -2
View File
@@ -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
@@ -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)