Put Cruise Intervals In Wheel Controls

This commit is contained in:
firestar5683
2026-10-29 12:31:54 -05:00
parent 3b04ff3cc4
commit 53b82a1726
7 changed files with 33 additions and 22 deletions
@@ -152,12 +152,13 @@ class TestControllerCruise(unittest.TestCase):
def test_actual_settings_capability_dependency_and_runtime_refresh(self):
with tempfile.TemporaryDirectory() as directory:
params=Params(directory)
vehicle=cp(True,'toyota')
vehicle=car.CarParams.new_message(pcmCruise=True, brand='toyota', carFingerprint='TEST',
openpilotLongitudinalControl=True)
owner=FeatureSettingsOwner(params,lambda group:group in ('long', 'toyota_cruise'),
vehicle_fingerprint=lambda:vehicle.carFingerprint,
vehicle_params=lambda:vehicle)
def rows():
return {r.key:r for r in owner.snapshot(FeaturePage.PROFILES,parked=True,system_long=True,
return {r.key:r for r in owner.snapshot(FeaturePage.WHEEL,parked=True,system_long=True,
lateral_context=False,metric=True).rows}
self.assertNotIn('CustomCruise',rows())
self.assertNotIn('CustomCruiseLong',rows())
@@ -99,9 +99,9 @@ class TestOffroadConfigurationPages(unittest.TestCase):
'conditional/cem': ('Speed threshold', 'Speed with lead', 'Stop lights'),
'lane_change': ('Allow lane changes', 'Minimum lane-change speed', 'Automatic Lane Changes', 'Lane Change Speed'),
'slc': ('Speed Limit Controller', 'Automatic adoption'),
'profiles': ('Short press', 'Hold', 'Force Stop', 'Selected Acceleration Profile', 'Selected Deceleration Profile'),
'profiles': ('Force Stop', 'Selected Acceleration Profile', 'Selected Deceleration Profile'),
'torque': ('Steering Controller', 'Turn Assist', 'Lat Accel', 'Friction'),
'wheel': ('Distance long press', 'MODE press', 'Star button'),
'wheel': ('Short press', 'Hold', 'Distance long press', 'MODE press', 'Star button'),
}
for selection in (None, 'HYUNDAI_IONIQ_6'):
self.params.put('VehicleSelection', json.loads(encode(selection)), block=True)
@@ -153,11 +153,13 @@ class TestOffroadConfigurationPages(unittest.TestCase):
selection = self.params.get('VehicleSelection')
profiles = self.page('profiles')
rows = {row['label']: row for row in profiles['rows']}
for label in ('Short press', 'Hold', 'Force Stop'):
self.assertTrue(rows[label]['available'], label)
self.assertTrue(rows['Force Stop']['available'])
self.assertNotIn('Short press', rows)
self.assertNotIn('Hold', rows)
for label, key in (('Short press', 'CustomCruise'), ('Hold', 'CustomCruiseLong')):
current = self.page('profiles')
current = self.page('wheel')
index = next(i for i, row in enumerate(current['rows']) if row['label'] == label)
self.assertTrue(current['rows'][index]['available'], label)
before = float(current['rows'][index]['value'])
intent = self.gateway.preview(current['view'], index, 1, 'session', b'generation')
self.assertTrue(self.gateway.confirm(intent['intent'], 'session', b'generation'))
@@ -184,8 +186,9 @@ class TestOffroadConfigurationPages(unittest.TestCase):
def test_alpha_off_allows_saved_long_preferences_without_runtime_activation(self):
self.params.put_bool('AlphaLongitudinalEnabled', False, block=True)
rows = {row['label']: row for row in self.page('profiles')['rows']}
for label in ('Short press', 'Hold', 'Force Stop'):
self.assertTrue(next(row for row in self.page('profiles')['rows'] if row['label'] == 'Force Stop')['available'])
rows = {row['label']: row for row in self.page('wheel')['rows']}
for label in ('Short press', 'Hold'):
self.assertTrue(rows[label]['available'], label)
self.assertFalse(self.context.sample().cp.openpilotLongitudinalControl)
self.assertFalse(self.params.get_bool('AlphaLongitudinalEnabled'))
@@ -157,8 +157,10 @@ class SettingsGatewayTest(unittest.TestCase):
self.params.put('CustomCruise', 2.0, block=True)
self.params.put('CustomCruiseLong', 8.0, block=True)
before = {key: read_saved(self.params, key, 128)[0] for key in ('CustomCruise', 'CustomCruiseLong')}
self.assertFalse(any(row['label'] in ('Short press', 'Hold', 'Swap Toyota Cruise Steps')
for row in self.page('profiles')['rows']))
for value, enabled in (('On', True), ('Off', False)):
page = self.page('profiles')
page = self.page('wheel')
self.assertFalse(any(row['label'] in ('Short press', 'Hold') for row in page['rows']))
index = next(i for i, row in enumerate(page['rows']) if row['label'] == 'Swap Toyota Cruise Steps')
self.assertTrue(page['rows'][index]['available'])
@@ -170,7 +172,7 @@ class SettingsGatewayTest(unittest.TestCase):
self.gateway.confirm(intent['intent'], self.session, self.generation)
self.assertEqual({key: read_saved(self.params, key, 128)[0] for key in before}, before)
self.context.value.cp.brand = 'honda'
self.assertFalse(any(row['label'] == 'Swap Toyota Cruise Steps' for row in self.page('profiles')['rows']))
self.assertFalse(any(row['label'] == 'Swap Toyota Cruise Steps' for row in self.page('wheel')['rows']))
def test_row_revision_is_stable_only_for_same_source_vehicle_and_session(self):
first, second = self.page("lane"), self.page("lane")
@@ -192,8 +194,13 @@ class SettingsGatewayTest(unittest.TestCase):
self.gateway.preview(changed_vehicle["revision"], 0, 1, self.session, self.generation)
def test_direct_switch_and_slider_values_preserve_source_checks(self):
page = self.page("profiles")
page = self.page("profiles")
vehicle = ToyotaInterface.get_non_essential_params(ToyotaCar.TOYOTA_COROLLA_TSS2)
vehicle.pcmCruise = False
vehicle.openpilotLongitudinalControl = True
self.context.value = AuthorityContext(True, vehicle, vehicle.to_bytes())
self.assertFalse(any(row['label'] in ('Short press', 'Hold', 'Swap Toyota Cruise Steps')
for row in self.page('profiles')['rows']))
page = self.page("wheel")
index = next(i for i, row in enumerate(page["rows"]) if row["label"] == "Short press")
for invalid in (True, "nan", float("inf"), 0, 151, 2.5, "bogus"):
with self.subTest(value=invalid), self.assertRaises(SettingsChanged):
@@ -203,7 +210,7 @@ class SettingsGatewayTest(unittest.TestCase):
self.assertEqual(self.params.get("CustomCruise"), 7.0)
with self.assertRaises(SettingsChanged):
self.gateway.preview(page["view"], index, 0, self.session, self.generation, value=9)
page = self.page("profiles")
page = self.page("wheel")
intent = self.gateway.preview(page["view"], index, 0, self.session, self.generation, value=9)
self.context.value = AuthorityContext(False, self.context.value.cp, self.context.value.cp_raw)
self.assertTrue(self.gateway.confirm(intent["intent"], self.session, self.generation))
@@ -1054,6 +1054,8 @@ class FeatureSettingsOwner:
repair_value="0" if not threshold_valid and unit_valid else "", default_value="0"))
elif page == FeaturePage.WHEEL:
title = "Wheel Controls"
if self.show_cruise_intervals or toyota_cruise_capability(self.vehicle_params()) is not None:
rows.extend(self._cruise_rows(configurable))
rows.extend(self.wheel.rows())
elif page == FeaturePage.SLC:
system_long = (system_long if self.vehicle_params() is None else self.longitudinal_available()) and self.authority("slc")
@@ -1130,8 +1132,6 @@ class FeatureSettingsOwner:
rows.append(self._bool_row(PLANNER_SELECTION_KEY, "Use StarPilot Longitudinal Planner", self.authority("preferences"),
reason="Off uses the upstream planner. Supported longitudinal control stays active. Changes apply on the next drive."))
allowed = configurable and system_long
if self.show_cruise_intervals or toyota_cruise_capability(self.vehicle_params()) is not None:
rows.extend(self._cruise_rows(configurable))
force_enabled, _, _ = self._value("ForceStops")
rows.append(self._bool_row("ForceStops", "Force Stop", allowed or
(force_enabled == "1" and self.authority("preferences")),
@@ -1,11 +1,11 @@
"""Parked exact-source edits for host-only cruise intervals."""
from dataclasses import replace
from types import SimpleNamespace
import tempfile
import unittest
from openpilot.common.params import Params
from opendbc.car.structs import car
from openpilot.starpilot.galaxy.settings import AuthorityContext, SettingsChanged, SettingsGateway
from openpilot.starpilot.longitudinal.cruise_intervals import CruiseIntervals, read_cruise_intervals
from openpilot.starpilot.ui.feature_settings_owner import FeatureSettingsOwner
@@ -25,7 +25,7 @@ class CruiseIntervalFeatureTests(unittest.TestCase):
temp = tempfile.TemporaryDirectory()
self.addCleanup(temp.cleanup)
self.params = Params(temp.name)
self.cp = SimpleNamespace(carFingerprint="HYUNDAI_IONIQ_6", openpilotLongitudinalControl=True,
self.cp = car.CarParams.new_message(carFingerprint="HYUNDAI_IONIQ_6", openpilotLongitudinalControl=True,
pcmCruise=False, notCar=False, passive=False, dashcamOnly=False)
self.context = Context(self.cp)
self.owner = FeatureSettingsOwner(self.params, lambda group: self.context.value.parked and group == "long",
@@ -34,7 +34,7 @@ class CruiseIntervalFeatureTests(unittest.TestCase):
self.gateway = SettingsGateway(self.params, self.context, clock=lambda: 100.0)
def rows(self):
state = self.owner.snapshot(FeaturePage.PROFILES, parked=self.context.value.parked, system_long=True,
state = self.owner.snapshot(FeaturePage.WHEEL, parked=self.context.value.parked, system_long=True,
lateral_context=False, metric=False)
return {row.key: row for row in state.rows if row.key in ("QOLLongitudinal", "CustomCruise", "CustomCruiseLong")}
@@ -47,7 +47,7 @@ class CruiseIntervalFeatureTests(unittest.TestCase):
def test_galaxy_direct_intervals_without_retired_master(self):
self.params.put("CustomCruise", 5.0, block=True)
self.params.put("CustomCruiseLong", 1.0, block=True)
page = self.gateway.page("profiles", "session", b"generation")
page = self.gateway.page("wheel", "session", b"generation")
rows = {row["label"]: (index, row) for index, row in enumerate(page["rows"])}
self.assertNotIn("Custom cruise intervals", rows)
self.assertTrue(rows["Short press"][1]["available"])
@@ -126,7 +126,7 @@ class FeatureNavigationTests(unittest.TestCase):
self.assertTrue(session._feature_authority('long'))
self.assertTrue(session._feature_authority('toyota_cruise'))
for expected in (True, False):
state = session.feature_owner.snapshot('profiles', parked=True, system_long=False,
state = session.feature_owner.snapshot('wheel', parked=True, system_long=False,
lateral_context=False, metric=False)
rows = {row.key: row for row in state.rows}
self.assertNotIn('CustomCruise', rows)
@@ -179,7 +179,7 @@ class ValueEditorTests(unittest.TestCase):
def test_cruise_interval_editor_keeps_the_owners_required_confirmation(self):
self.owner.show_cruise_intervals = True
self.owner.vehicle_params().pcmCruise = False
self.session.feature_page = FeaturePage.PROFILES
self.session.feature_page = FeaturePage.WHEEL
editor = self.open_feature("CustomCruise")
dialogs = []
with patch("openpilot.system.ui.widgets.confirm_dialog.ConfirmDialog", side_effect=lambda *args, **kw: NS(callback=kw["callback"])), \