Keep Ford steering selection visible with AOL enabled

This commit is contained in:
firestar5683
2026-10-23 19:46:20 -05:00
parent df22d36413
commit 7403185bd8
3 changed files with 86 additions and 3 deletions
@@ -70,7 +70,7 @@ class TestFordAngleSettings(unittest.TestCase):
for identity in (CAR.FORD_EDGE_MK2, CAR.FORD_MONDEO_MK5, CAR.FORD_TRANSIT_MK5):
self.cp = ford_params(identity)
self.assertFalse(any(r["label"] == "Ford steering controller" for r in self.page()["rows"]))
for field, value in (("alternativeExperience", 32), ("passive", True), ("dashcamOnly", True), ("notCar", True)):
for field, value in (("alternativeExperience", 16), ("passive", True), ("dashcamOnly", True), ("notCar", True)):
self.cp = ford_params(CAR.FORD_BRONCO_SPORT_MK1)
setattr(self.cp, field, value)
self.assertFalse(any(r["label"] == "Ford steering controller" for r in self.page()["rows"]))
@@ -0,0 +1,74 @@
import tempfile
import unittest
from pathlib import Path
from types import SimpleNamespace
from opendbc.car import structs
from opendbc.car.ford.values import CAR, FordFlags
from openpilot.starpilot.ui.ford_lateral_feature import FordLateralFeature
class TestFordSelectorVisibility(unittest.TestCase):
def setUp(self):
directory = tempfile.TemporaryDirectory()
self.addCleanup(directory.cleanup)
self.root = Path(directory.name)
self.cp = structs.CarParams(brand='ford', carFingerprint=CAR.FORD_MUSTANG_MACH_E_MK1,
flags=int(FordFlags.CANFD), alternativeExperience=32, pcmCruise=True,
steerControlType='angle', transmissionType='automatic',
safetyConfigs=[{'safetyModel': 'ford', 'safetyParam': 18}])
self.params = SimpleNamespace(get_param_path=lambda key: str(self.root / key))
self.owner = SimpleNamespace(params=self.params, vehicle_params=lambda: self.cp,
authority=lambda _: True, vehicle_fingerprint=lambda: self.cp.carFingerprint)
self.feature = FordLateralFeature(self.owner)
self.save('AlwaysOnLateral', b'1')
self.save('SafeMode', b'0')
def save(self, key, value):
(self.root / key).write_bytes(value)
def test_aol_marked_mach_e_visible_without_mutating_configuration(self):
for alpha in (False, True):
self.cp.openpilotLongitudinalControl = alpha
self.cp.safetyConfigs[0].safetyParam = 18 + int(alpha)
before = self.cp.to_dict()
rows = self.feature.rows(True)
self.assertEqual(len(rows), 1)
self.assertEqual(rows[0].choices, ('Current curvature', 'BluePilot angle'))
self.assertFalse(rows[0].available)
self.assertIn('Turn off Always On Lateral', rows[0].reason)
self.assertEqual(self.cp.to_dict(), before)
def test_saved_aol_off_allows_selection_without_waiting_for_cp_restart(self):
self.save('AlwaysOnLateral', b'0')
self.assertTrue(self.feature.rows(True)[0].available)
self.assertEqual(self.cp.alternativeExperience, 32)
self.assertEqual(self.cp.safetyConfigs[0].safetyParam, 18)
def test_onroad_and_safe_mode_still_deny_selection(self):
self.save('AlwaysOnLateral', b'0')
self.assertFalse(self.feature.rows(False)[0].available)
self.save('SafeMode', b'1')
self.assertFalse(self.feature.rows(True)[0].available)
def test_reader_uses_the_same_display_only_capability(self):
self.cp = self.cp.as_reader()
self.assertEqual(len(self.feature.rows(True)), 1)
self.assertEqual(self.cp.alternativeExperience, 32)
def test_invalid_native_owner_remains_hidden(self):
for word in (0, 2, 130, 65535):
self.cp.safetyConfigs[0].safetyParam = word
self.assertEqual(self.feature.rows(True), ())
def test_unrelated_experience_and_brand_remain_hidden(self):
self.cp.alternativeExperience = 16
self.assertEqual(self.feature.rows(True), ())
self.cp.alternativeExperience = 32
self.cp.brand = 'toyota'
self.assertEqual(self.feature.rows(True), ())
def test_existing_unmarked_mach_e_stays_available(self):
self.cp.alternativeExperience = 0
self.save('AlwaysOnLateral', b'0')
self.assertTrue(self.feature.rows(True)[0].available)
+11 -2
View File
@@ -1,5 +1,7 @@
"""One saved Ford enum shared by Galaxy and the native feature presentation."""
from opendbc.bluepilot_lateral.hosts.starpilot import supported
from opendbc.car import structs
from opendbc.car.ford.aol import qualified as aol_qualified
from openpilot.starpilot.car.ford.lateral_preferences import KEY, CHOICES, read_choice
from openpilot.starpilot.saved_source import read_saved
from openpilot.starpilot.saved_document import commit_exact
@@ -13,8 +15,15 @@ class FordLateralFeature:
def capability(self):
cp = self.owner.vehicle_params()
try:
if cp is None or not supported(cp):
if cp is None:
return None
if not supported(cp):
if not aol_qualified(cp, marked_only=True):
return None
next_drive = structs.CarParams(**cp.to_dict())
next_drive.alternativeExperience = 0
if not supported(next_drive):
return None
return (str(cp.carFingerprint), int(cp.flags), int(cp.alternativeExperience), bool(cp.openpilotLongitudinalControl),
bool(cp.pcmCruise), str(cp.steerControlType), bool(cp.passive), bool(cp.dashcamOnly), bool(cp.notCar),
tuple((str(c.safetyModel), int(c.safetyParam)) for c in cp.safetyConfigs))
@@ -40,7 +49,7 @@ class FordLateralFeature:
choices=tuple(CHOICES.values()), available=parked and self.owner.authority("parked_preferences") and
readable and dependencies is not None, capability=capability,
dependencies=dependencies or (), repair_value="" if valid else CHOICES[0], default_value=CHOICES[0],
reason="Applies next drive. BluePilot angle is available with normal cruise control on supported Ford vehicles."),)
reason="Applies next drive. Turn off Always On Lateral and Safe Mode to select BluePilot angle with normal cruise control."),)
def apply(self, request):
value = next((code for code, label in CHOICES.items() if label == request.value), None)