Ferd Long

This commit is contained in:
firestar5683
2026-09-28 14:57:33 -05:00
parent ac8028a21e
commit faf5b53321
4 changed files with 73 additions and 1 deletions
@@ -57,6 +57,7 @@ FORD_LIGHTNING_FAR_FOLLOW_RELEASE_SLEW_RATE = 1.75
FORD_LIGHTNING_STANDSTILL_GUARD_DISTANCE_MARGIN = 5.0
FORD_LIGHTNING_STANDSTILL_GUARD_MAX_LEAD_SPEED = 0.60
FORD_LIGHTNING_GAP_SETTLE_MAX_EXTRA_GAP = 3.0
FORD_MACH_E_GAP_SETTLE_MAX_EXTRA_GAP = 2.5
TOYOTA_SIENNA_POST_DEPARTURE_RESTOP_MAX_EGO_SPEED = 2.0
TOYOTA_SIENNA_POST_DEPARTURE_RESTOP_MAX_LEAD_SPEED = 0.45
TOYOTA_SIENNA_POST_DEPARTURE_RESTOP_MAX_LEAD_DELTA = 0.35
@@ -329,6 +330,8 @@ def get_standstill_gap_settle_max_extra_gap(CP):
return HONDA_CRV_5G_GAP_SETTLE_MAX_EXTRA_GAP
if is_ford_f150_lightning(CP):
return FORD_LIGHTNING_GAP_SETTLE_MAX_EXTRA_GAP
if getattr(CP, "brand", "") == "ford" and str(getattr(CP, "carFingerprint", "")) == "FORD_MUSTANG_MACH_E_MK1":
return FORD_MACH_E_GAP_SETTLE_MAX_EXTRA_GAP
return 1.5
@@ -858,6 +858,21 @@ def test_lightning_stopped_lead_guard_tune_is_vehicle_specific():
assert get_tracked_lead_catchup_bias_gain(civic) is None
def test_mach_e_standstill_gap_settle_covers_observed_gap_without_changing_other_cars():
mach_e = FordCarInterface.get_non_essential_params(FORD_CAR.FORD_MUSTANG_MACH_E_MK1)
civic = CarInterface.get_non_essential_params(CAR.HONDA_CIVIC)
lead = make_lead(status=True, d_rel=7.7, v_lead=0.0, radar=True, model_prob=1.0, y_rel=0.0)
assert get_standstill_gap_settle_max_extra_gap(mach_e) == pytest.approx(2.5)
assert get_standstill_gap_settle_max_extra_gap(civic) == pytest.approx(1.5)
assert LongitudinalPlanner.is_radar_standstill_gap_settle_candidate(
lead, 0.0, 5.5, max_extra_gap=get_standstill_gap_settle_max_extra_gap(mach_e))
assert not LongitudinalPlanner.is_radar_standstill_gap_settle_candidate(
lead, 0.0, 5.5, max_extra_gap=get_standstill_gap_settle_max_extra_gap(civic))
assert not LongitudinalPlanner.is_radar_standstill_gap_settle_candidate(
lead, 0.5, 5.5, max_extra_gap=get_standstill_gap_settle_max_extra_gap(mach_e))
def test_lightning_stopped_radar_lead_handoff_is_narrow_and_vehicle_specific():
lightning = FordCarInterface.get_non_essential_params(FORD_CAR.FORD_F_150_LIGHTNING_MK1)
civic = CarInterface.get_non_essential_params(CAR.HONDA_CIVIC)
@@ -1,5 +1,7 @@
import json
import sys
from contextlib import contextmanager
from types import SimpleNamespace
import numpy as np
import pytest
@@ -788,6 +790,38 @@ def test_reset_defaults_requires_confirmed_offroad_without_side_effects(monkeypa
assert reboots == []
def test_reset_defaults_preserves_detected_vehicle_for_vehicle_settings(monkeypatch):
client, params = _client(monkeypatch, {
"CarMake": "Ford", "CarModel": "FORD_MUSTANG_MACH_E_MK1", "CarModelName": "Mustang Mach-E",
"FordHandsFreeCluster": True,
})
monkeypatch.setattr(params, "all_keys", lambda: ["CarMake", "CarModel", "CarModelName", "FordHandsFreeCluster"], raising=False)
monkeypatch.setattr(params, "get_default_value", lambda key: "mock" if key == "CarMake" else False, raising=False)
monkeypatch.setattr(the_galaxy, "_params_raw", params)
monkeypatch.setattr(the_galaxy, "update_starpilot_toggles", lambda: None)
monkeypatch.setattr(the_galaxy.HARDWARE, "reboot", lambda: None)
assert client.post("/api/toggles/reset_default").status_code == 200
assert params.values["CarMake"] == "Ford"
assert params.values["CarModel"] == "FORD_MUSTANG_MACH_E_MK1"
assert params.values["CarModelName"] == "Mustang Mach-E"
assert params.values["FordHandsFreeCluster"] is False
def test_vehicle_make_recovers_from_persistent_car_params_after_reset(monkeypatch):
@contextmanager
def ford_params(_):
yield SimpleNamespace(brand="ford", carFingerprint="FORD_MUSTANG_MACH_E_MK1")
client, params = _client(monkeypatch, {"CarMake": "mock", "CarParamsPersistent": b"saved-ford-params"})
monkeypatch.setattr(the_galaxy, "_safe_params_get_live_raw", lambda key, default=None, block=False: params.values.get(key, default))
monkeypatch.setattr(the_galaxy.car.CarParams, "from_bytes", ford_params)
assert the_galaxy._get_effective_car_make("mock") == "Ford"
assert the_galaxy._get_effective_car_make("Toyota") == "Toyota"
assert client.get("/api/params/all").get_json()["CarMake"] == "Ford"
@pytest.mark.parametrize("device_state", [
{"IsOnroad": True, "IsOffroad": False},
{"IsOnroad": False, "IsOffroad": False},
+21 -1
View File
@@ -3762,6 +3762,23 @@ def _get_detected_truck_tuning():
return False
def _get_effective_car_make(stored_make):
if isinstance(stored_make, bytes):
stored_make = stored_make.decode("utf-8", errors="replace")
if str(stored_make or "").strip().lower() not in ("", "mock"):
return stored_make
cp_bytes = _safe_params_get_live_raw("CarParamsPersistent")
if cp_bytes:
try:
with car.CarParams.from_bytes(cp_bytes) as cp:
if cp.brand and cp.brand != "mock":
make_key = str(cp.carFingerprint).split("_", 1)[0]
return next((make for make in FINGERPRINT_MAKE_LABELS if make.lower() == make_key.lower()), cp.brand.title())
except Exception:
pass
return stored_make
def _get_effective_legacy_custom_accel_curve(
ev_tuning: bool, truck_tuning: bool, *, acceleration_profile=None, custom_enabled: bool | None = None,
) -> list[float]:
@@ -6773,6 +6790,8 @@ def setup(app):
if request_key == "IsRHD" and not params.get_bool("IsRHDOverride"):
return ("1" if params.get_bool("IsRhdDetected") else "0"), 200
value = params.get(request_key) or ""
if request_key == "CarMake":
return _get_effective_car_make(value), 200
if request_key in ("Model", "DrivingModel"):
if isinstance(value, bytes):
value = value.decode("utf-8", errors="replace")
@@ -6813,6 +6832,7 @@ def setup(app):
except Exception:
result[key] = None
result["CarMake"] = _get_effective_car_make(result.get("CarMake"))
result["TeslaCANWakeAvailable"] = supports_tesla_can_wake(params)
result["HasRadar"] = _get_has_radar()
result["VehicleParked"] = _get_vehicle_parked()
@@ -10546,7 +10566,7 @@ def setup(app):
for raw_key in _params_raw.all_keys():
key = raw_key.decode() if isinstance(raw_key, bytes) else str(raw_key)
if key in EXCLUDED_KEYS:
if key in EXCLUDED_KEYS or key in ("CarMake", "CarModel", "CarModelName"):
continue
default_value = _params_raw.get_default_value(raw_key)