mirror of
https://jihulab.com/mr-one/openpilot.git
synced 2026-10-26 20:43:49 +08:00
test: remove ExperimentalMode UI/param usage (stage 3d)
This commit is contained in:
@@ -178,7 +178,7 @@ class Car:
|
||||
self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP)
|
||||
|
||||
self.is_metric = self.params.get_bool("IsMetric")
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode")
|
||||
self.initial_cruise_speed = self.params.get("InitialCruiseSpeedKph", return_default=True)
|
||||
|
||||
# card is driven by can recv, expected at 100Hz
|
||||
self.rk = Ratekeeper(100, print_delay_threshold=None)
|
||||
@@ -211,7 +211,7 @@ class Car:
|
||||
self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric)
|
||||
if self.sm['carControl'].enabled and not self.CC_prev.enabled:
|
||||
# Use CarState w/ buttons from the step selfdrived enables on
|
||||
self.v_cruise_helper.initialize_v_cruise(self.CS_prev, self.experimental_mode)
|
||||
self.v_cruise_helper.initialize_v_cruise(self.CS_prev, self.initial_cruise_speed)
|
||||
|
||||
# TODO: mirror the carState.cruiseState struct?
|
||||
CS.vCruise = float(self.v_cruise_helper.v_cruise_kph)
|
||||
@@ -296,7 +296,7 @@ class Car:
|
||||
def params_thread(self, evt):
|
||||
while not evt.is_set():
|
||||
self.is_metric = self.params.get_bool("IsMetric")
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl
|
||||
self.initial_cruise_speed = self.params.get("InitialCruiseSpeedKph", return_default=True)
|
||||
|
||||
# sunnypilot
|
||||
self.v_cruise_helper.read_custom_set_speed_params()
|
||||
|
||||
@@ -13,7 +13,6 @@ V_CRUISE_MIN = 8
|
||||
V_CRUISE_MAX = 145
|
||||
V_CRUISE_UNSET = 255
|
||||
V_CRUISE_INITIAL = 40
|
||||
V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 105
|
||||
IMPERIAL_INCREMENT = round(CV.MPH_TO_KPH, 1) # round here to avoid rounding errors incrementing set speed
|
||||
|
||||
ButtonEvent = car.CarState.ButtonEvent
|
||||
@@ -138,16 +137,14 @@ class VCruiseHelper(VCruiseHelperSP):
|
||||
self.button_timers[b.type.raw] = 1 if b.pressed else 0
|
||||
self.button_change_states[b.type.raw] = {"standstill": CS.cruiseState.standstill, "enabled": enabled}
|
||||
|
||||
def initialize_v_cruise(self, CS, experimental_mode: bool) -> None:
|
||||
def initialize_v_cruise(self, CS, initial_speed: int) -> None:
|
||||
# initializing is handled by the PCM
|
||||
if self.CP.pcmCruise:
|
||||
return
|
||||
|
||||
initial = V_CRUISE_INITIAL_EXPERIMENTAL_MODE if experimental_mode else V_CRUISE_INITIAL
|
||||
|
||||
if any(b.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for b in CS.buttonEvents) and self.v_cruise_initialized:
|
||||
self.v_cruise_kph = self.v_cruise_kph_last
|
||||
else:
|
||||
self.v_cruise_kph = int(round(np.clip(CS.vEgo * CV.MS_TO_KPH, initial, V_CRUISE_MAX)))
|
||||
self.v_cruise_kph = int(round(np.clip(max(CS.vEgo * CV.MS_TO_KPH, initial_speed), V_CRUISE_INITIAL, V_CRUISE_MAX)))
|
||||
|
||||
self.v_cruise_cluster_kph = self.v_cruise_kph
|
||||
|
||||
@@ -14,7 +14,7 @@ ButtonEvent = car.CarState.ButtonEvent
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
|
||||
def run_cruise_simulation(cruise, e2e, personality, t_end=20.):
|
||||
def run_cruise_simulation(cruise, personality, t_end=20.):
|
||||
man = Maneuver(
|
||||
'',
|
||||
duration=t_end,
|
||||
@@ -24,7 +24,6 @@ def run_cruise_simulation(cruise, e2e, personality, t_end=20.):
|
||||
cruise_values=[cruise],
|
||||
prob_lead_values=[0.0],
|
||||
breakpoints=[0.],
|
||||
e2e=e2e,
|
||||
personality=personality,
|
||||
)
|
||||
valid, output = man.evaluate()
|
||||
@@ -32,8 +31,7 @@ def run_cruise_simulation(cruise, e2e, personality, t_end=20.):
|
||||
return output[-1, 3]
|
||||
|
||||
|
||||
@parameterized_class(("e2e", "personality", "speed"), itertools.product(
|
||||
[True, False], # e2e
|
||||
@parameterized_class(("personality", "speed"), itertools.product(
|
||||
log.LongitudinalPersonality.schema.enumerants, # personality
|
||||
[5,35])) # speed
|
||||
class TestCruiseSpeed(OpenpilotTestCase):
|
||||
@@ -41,7 +39,7 @@ class TestCruiseSpeed(OpenpilotTestCase):
|
||||
print(f'Testing {self.speed} m/s')
|
||||
cruise_speed = float(self.speed)
|
||||
|
||||
simulation_steady_state = run_cruise_simulation(cruise_speed, self.e2e, self.personality)
|
||||
simulation_steady_state = run_cruise_simulation(cruise_speed, self.personality)
|
||||
self.assertAlmostEqual(simulation_steady_state, cruise_speed, delta=.01, msg=f'Did not reach {self.speed} m/s')
|
||||
|
||||
|
||||
@@ -59,16 +57,16 @@ class TestVCruiseHelper(OpenpilotTestCase):
|
||||
for _ in range(2):
|
||||
self.v_cruise_helper.update_v_cruise(car.CarState(cruiseState={"available": False}), enabled=False, is_metric=False)
|
||||
|
||||
def enable(self, v_ego, experimental_mode):
|
||||
def enable(self, v_ego):
|
||||
# Simulates user pressing set with a current speed
|
||||
self.v_cruise_helper.initialize_v_cruise(car.CarState(vEgo=v_ego), experimental_mode)
|
||||
self.v_cruise_helper.initialize_v_cruise(car.CarState(vEgo=v_ego), V_CRUISE_INITIAL)
|
||||
|
||||
def test_adjust_speed(self):
|
||||
"""
|
||||
Asserts speed changes on falling edges of buttons.
|
||||
"""
|
||||
|
||||
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False)
|
||||
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS)
|
||||
|
||||
for btn in (ButtonType.accelCruise, ButtonType.decelCruise):
|
||||
for pressed in (True, False):
|
||||
@@ -92,7 +90,7 @@ class TestVCruiseHelper(OpenpilotTestCase):
|
||||
CS.buttonEvents = [ButtonEvent(type=ButtonType.decelCruise, pressed=pressed)]
|
||||
self.v_cruise_helper.update_v_cruise(CS, enabled=enabled, is_metric=False)
|
||||
if pressed:
|
||||
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False)
|
||||
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS)
|
||||
|
||||
# Expected diff on enabling. Speed should not change on falling edge of pressed
|
||||
assert (not pressed) == (self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last)
|
||||
@@ -102,7 +100,7 @@ class TestVCruiseHelper(OpenpilotTestCase):
|
||||
Asserts we don't increment set speed if user presses resume/accel to exit cruise standstill.
|
||||
"""
|
||||
|
||||
self.enable(0, False)
|
||||
self.enable(0)
|
||||
|
||||
for standstill in (True, False):
|
||||
for pressed in (True, False):
|
||||
@@ -122,7 +120,7 @@ class TestVCruiseHelper(OpenpilotTestCase):
|
||||
|
||||
for v_ego in np.linspace(0, 100, 101):
|
||||
self.reset_cruise_speed_state()
|
||||
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False)
|
||||
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS)
|
||||
|
||||
# first decrement speed, then perform gas pressed logic
|
||||
expected_v_cruise_kph = self.v_cruise_helper.v_cruise_kph - IMPERIAL_INCREMENT
|
||||
@@ -143,11 +141,10 @@ class TestVCruiseHelper(OpenpilotTestCase):
|
||||
Asserts allowed cruise speeds on enabling with SET.
|
||||
"""
|
||||
|
||||
for experimental_mode in (True, False):
|
||||
for v_ego in np.linspace(0, 100, 101):
|
||||
self.reset_cruise_speed_state()
|
||||
assert not self.v_cruise_helper.v_cruise_initialized
|
||||
for v_ego in np.linspace(0, 100, 101):
|
||||
self.reset_cruise_speed_state()
|
||||
assert not self.v_cruise_helper.v_cruise_initialized
|
||||
|
||||
self.enable(float(v_ego), experimental_mode)
|
||||
assert V_CRUISE_INITIAL <= self.v_cruise_helper.v_cruise_kph <= V_CRUISE_MAX
|
||||
assert self.v_cruise_helper.v_cruise_initialized
|
||||
self.enable(float(v_ego))
|
||||
assert V_CRUISE_INITIAL <= self.v_cruise_helper.v_cruise_kph <= V_CRUISE_MAX
|
||||
assert self.v_cruise_helper.v_cruise_initialized
|
||||
|
||||
@@ -29,7 +29,6 @@ from openpilot.common.hardware import HARDWARE
|
||||
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
|
||||
from openpilot.sunnypilot import get_sanitize_int_param
|
||||
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
|
||||
from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper
|
||||
from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement
|
||||
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
|
||||
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
||||
@@ -55,7 +54,7 @@ TurnDirection = custom.ModelDataV2SP.TurnDirection
|
||||
IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
|
||||
|
||||
|
||||
class SelfdriveD(CruiseHelper):
|
||||
class SelfdriveD:
|
||||
def __init__(self, CP=None, CP_SP=None):
|
||||
self.params = Params()
|
||||
|
||||
@@ -123,8 +122,6 @@ class SelfdriveD(CruiseHelper):
|
||||
# cleanup old params
|
||||
if not self.CP.alphaLongitudinalAvailable:
|
||||
self.params.remove("AlphaLongitudinalEnabled")
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
self.params.remove("ExperimentalMode")
|
||||
|
||||
self.CS_prev = car.CarState.new_message()
|
||||
self.AM = AlertManager()
|
||||
@@ -141,7 +138,6 @@ class SelfdriveD(CruiseHelper):
|
||||
self.events_prev = []
|
||||
self.logged_comm_issue = None
|
||||
self.not_running_prev = None
|
||||
self.experimental_mode = False
|
||||
self.personality = get_sanitize_int_param(
|
||||
"LongitudinalPersonality",
|
||||
min(log.LongitudinalPersonality.schema.enumerants.values()),
|
||||
@@ -183,7 +179,6 @@ class SelfdriveD(CruiseHelper):
|
||||
|
||||
self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP)
|
||||
|
||||
CruiseHelper.__init__(self, self.CP)
|
||||
self.button_state_tracker = ButtonStateTracker()
|
||||
|
||||
def update_events(self, CS):
|
||||
@@ -514,16 +509,12 @@ class SelfdriveD(CruiseHelper):
|
||||
if CS.gearShifter == car.CarState.GearShifter.park and self.mads.enabled:
|
||||
self.events.remove(EventName.canBusMissing)
|
||||
|
||||
CruiseHelper.update(self, CS, self.events_sp, self.experimental_mode)
|
||||
|
||||
# decrement personality on distance button press
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if any(not be.pressed and be.type == ButtonType.gapAdjustCruise for be in CS.buttonEvents):
|
||||
if not self.experimental_mode_switched:
|
||||
self.personality = (self.personality - 1) % 3
|
||||
self.params.put('LongitudinalPersonality', self.personality)
|
||||
self.events.add(EventName.personalityChanged)
|
||||
self.experimental_mode_switched = False
|
||||
self.personality = (self.personality - 1) % 3
|
||||
self.params.put('LongitudinalPersonality', self.personality)
|
||||
self.events.add(EventName.personalityChanged)
|
||||
|
||||
self.icbm.run(CS, self.sm['carControl'], self.sm['longitudinalPlanSP'], self.is_metric)
|
||||
|
||||
@@ -600,7 +591,6 @@ class SelfdriveD(CruiseHelper):
|
||||
ss.active = self.active
|
||||
ss.state = self.state_machine.state
|
||||
ss.engageable = not self.events.contains(ET.NO_ENTRY)
|
||||
ss.experimentalMode = self.experimental_mode
|
||||
ss.personality = self.personality
|
||||
|
||||
ss.alertText1 = self.AM.current_alert.alert_text_1
|
||||
@@ -667,7 +657,6 @@ class SelfdriveD(CruiseHelper):
|
||||
self.is_metric = self.params.get_bool("IsMetric")
|
||||
self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled")
|
||||
self.disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator")
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl
|
||||
self.personality = self.params.get("LongitudinalPersonality", return_default=True)
|
||||
|
||||
self.mads.read_params()
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import time
|
||||
import pyray as rl
|
||||
from collections.abc import Callable
|
||||
from enum import IntEnum
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.ui.widgets.offroad_alerts import UpdateAlert, OffroadAlert
|
||||
from openpilot.selfdrive.ui.widgets.exp_mode_button import ExperimentalModeButton
|
||||
from openpilot.selfdrive.ui.widgets.prime import PrimeWidget
|
||||
from openpilot.selfdrive.ui.widgets.setup import SetupWidget
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
@@ -39,7 +37,6 @@ class HomeLayout(Widget):
|
||||
|
||||
self.current_state = HomeLayoutState.HOME
|
||||
self.last_refresh = 0
|
||||
self.settings_callback: Callable[[], None] | None = None
|
||||
|
||||
self.update_available = False
|
||||
self.alert_count = 0
|
||||
@@ -60,29 +57,20 @@ class HomeLayout(Widget):
|
||||
self._prime_widget = PrimeWidget()
|
||||
self._setup_widget = SetupWidget()
|
||||
|
||||
self._exp_mode_button = ExperimentalModeButton()
|
||||
self._setup_callbacks()
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._exp_mode_button.show_event()
|
||||
self.last_refresh = time.monotonic()
|
||||
self._refresh()
|
||||
|
||||
def _setup_callbacks(self):
|
||||
self.update_alert.set_dismiss_callback(lambda: self._set_state(HomeLayoutState.HOME))
|
||||
self.offroad_alert.set_dismiss_callback(lambda: self._set_state(HomeLayoutState.HOME))
|
||||
self._exp_mode_button.set_click_callback(lambda: self.settings_callback() if self.settings_callback else None)
|
||||
|
||||
def set_settings_callback(self, callback: Callable):
|
||||
self.settings_callback = callback
|
||||
|
||||
def _set_state(self, state: HomeLayoutState):
|
||||
# propagate show/hide events
|
||||
if state != self.current_state:
|
||||
if state == HomeLayoutState.HOME:
|
||||
self._exp_mode_button.show_event()
|
||||
|
||||
if state in self._layout_widgets:
|
||||
self._layout_widgets[state].show_event()
|
||||
if self.current_state in self._layout_widgets:
|
||||
@@ -235,19 +223,7 @@ class HomeLayout(Widget):
|
||||
self._prime_widget.render(self.left_column_rect)
|
||||
|
||||
def _render_right_column(self):
|
||||
exp_height = 125
|
||||
exp_rect = rl.Rectangle(
|
||||
self.right_column_rect.x, self.right_column_rect.y, self.right_column_rect.width, exp_height
|
||||
)
|
||||
self._exp_mode_button.render(exp_rect)
|
||||
|
||||
setup_rect = rl.Rectangle(
|
||||
self.right_column_rect.x,
|
||||
self.right_column_rect.y + exp_height + SPACING,
|
||||
self.right_column_rect.width,
|
||||
self.right_column_rect.height - exp_height - SPACING,
|
||||
)
|
||||
self._setup_widget.render(setup_rect)
|
||||
self._setup_widget.render(self.right_column_rect)
|
||||
|
||||
def _refresh(self):
|
||||
self._version_text = self._get_version_text()
|
||||
|
||||
@@ -63,7 +63,6 @@ class MainLayout(Widget):
|
||||
on_flag=self._on_bookmark_clicked,
|
||||
open_settings=lambda: self.open_settings(PanelType.TOGGLES))
|
||||
self._layouts[MainState.HOME]._setup_widget.set_open_settings_callback(lambda: self.open_settings(PanelType.FIREHOSE))
|
||||
self._layouts[MainState.HOME].set_settings_callback(lambda: self.open_settings(PanelType.TOGGLES))
|
||||
self._layouts[MainState.SETTINGS].set_callbacks(on_close=self._set_mode_for_state)
|
||||
|
||||
for layout in (self._layouts[MainState.ONROAD], self._home_body_layout):
|
||||
|
||||
@@ -178,7 +178,6 @@ class DeveloperLayout(Widget):
|
||||
|
||||
def _on_lat_maneuver_mode(self, state: bool):
|
||||
self._params.put_bool("LateralManeuverMode", state, block=True)
|
||||
self._params.put_bool("ExperimentalMode", False, block=True)
|
||||
self._params.put_bool("JoystickDebugMode", False, block=True)
|
||||
self._joystick_toggle.action_item.set_state(False)
|
||||
self._params.put_bool("LongitudinalManeuverMode", False, block=True)
|
||||
|
||||
@@ -46,13 +46,6 @@ class TogglesLayout(Widget):
|
||||
|
||||
# param, title, desc, icon, needs_restart
|
||||
self._toggle_defs = {
|
||||
"ExperimentalMode": (
|
||||
lambda: tr("Experimental Mode"),
|
||||
"",
|
||||
"experimental_white.png",
|
||||
False,
|
||||
),
|
||||
|
||||
"IsLdwEnabled": (
|
||||
lambda: tr("Enable Lane Departure Warnings"),
|
||||
DESCRIPTIONS["IsLdwEnabled"],
|
||||
@@ -109,11 +102,7 @@ class TogglesLayout(Widget):
|
||||
|
||||
self._toggles[param] = toggle
|
||||
|
||||
# insert longitudinal personality after NDOG toggle
|
||||
if param == "ExperimentalMode":
|
||||
self._toggles["LongitudinalPersonality"] = self._long_personality_setting
|
||||
|
||||
self._update_experimental_mode_icon()
|
||||
self._toggles["LongitudinalPersonality"] = self._long_personality_setting
|
||||
self._scroller = Scroller(list(self._toggles.values()), line_separator=True, spacing=0)
|
||||
|
||||
ui_state.add_engaged_transition_callback(self._update_toggles)
|
||||
@@ -133,45 +122,8 @@ class TogglesLayout(Widget):
|
||||
def _update_toggles(self):
|
||||
ui_state.update_params()
|
||||
|
||||
e2e_description = tr(
|
||||
"sunnypilot defaults to driving in chill mode. Experimental mode enables alpha-level features that aren't ready for chill mode. " +
|
||||
"Experimental features are listed below:<br>" +
|
||||
"<h4>End-to-End Longitudinal Control</h4><br>" +
|
||||
"Let the driving model control the gas and brakes. sunnypilot will drive as it thinks a human would, including stopping for red lights and stop signs. " +
|
||||
"Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; " +
|
||||
"mistakes should be expected.<br>" +
|
||||
"<h4>New Driving Visualization</h4><br>" +
|
||||
"The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. " +
|
||||
"The Experimental mode logo will also be shown in the top right corner."
|
||||
)
|
||||
|
||||
if ui_state.CP is not None:
|
||||
if ui_state.has_longitudinal_control:
|
||||
self._toggles["ExperimentalMode"].action_item.set_enabled(True)
|
||||
self._toggles["ExperimentalMode"].set_description(e2e_description)
|
||||
self._long_personality_setting.action_item.set_enabled(True)
|
||||
else:
|
||||
# no long for now
|
||||
self._toggles["ExperimentalMode"].action_item.set_enabled(False)
|
||||
self._toggles["ExperimentalMode"].action_item.set_state(False)
|
||||
self._long_personality_setting.action_item.set_enabled(False)
|
||||
self._params.remove("ExperimentalMode")
|
||||
|
||||
unavailable = tr("Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control.")
|
||||
|
||||
long_desc = unavailable + " " + tr("sunnypilot longitudinal control may come in a future update.")
|
||||
if ui_state.CP.alphaLongitudinalAvailable:
|
||||
if self._is_release:
|
||||
long_desc = unavailable + " " + tr("An alpha version of sunnypilot longitudinal control can be tested, along with " +
|
||||
"Experimental mode, on non-release branches.")
|
||||
else:
|
||||
long_desc = tr("Enable the sunnypilot longitudinal control (alpha) toggle to allow Experimental mode.")
|
||||
|
||||
self._toggles["ExperimentalMode"].set_description("<b>" + long_desc + "</b><br><br>" + e2e_description)
|
||||
else:
|
||||
self._toggles["ExperimentalMode"].set_description(e2e_description)
|
||||
|
||||
self._update_experimental_mode_icon()
|
||||
self._long_personality_setting.action_item.set_enabled(ui_state.has_longitudinal_control)
|
||||
|
||||
# TODO: make a param control list item so we don't need to manage internal state as much here
|
||||
# refresh toggles from params to mirror external changes
|
||||
@@ -186,35 +138,7 @@ class TogglesLayout(Widget):
|
||||
def _render(self, rect):
|
||||
self._scroller.render(rect)
|
||||
|
||||
def _update_experimental_mode_icon(self):
|
||||
icon = "experimental.png" if self._toggles["ExperimentalMode"].action_item.get_state() else "experimental_white.png"
|
||||
self._toggles["ExperimentalMode"].set_icon(icon)
|
||||
|
||||
def _handle_experimental_mode_toggle(self, state: bool):
|
||||
confirmed = self._params.get_bool("ExperimentalModeConfirmed")
|
||||
if state and not confirmed:
|
||||
def confirm_callback(result: DialogResult):
|
||||
if result == DialogResult.CONFIRM:
|
||||
self._params.put_bool("ExperimentalMode", True, block=True)
|
||||
self._params.put_bool("ExperimentalModeConfirmed", True, block=True)
|
||||
else:
|
||||
self._toggles["ExperimentalMode"].action_item.set_state(False)
|
||||
self._update_experimental_mode_icon()
|
||||
|
||||
# show confirmation dialog
|
||||
content = (f"<h1>{self._toggles['ExperimentalMode'].title}</h1><br>" +
|
||||
f"<p>{self._toggles['ExperimentalMode'].description}</p>")
|
||||
dlg = ConfirmDialog(content, tr("Enable"), rich=True, callback=confirm_callback)
|
||||
gui_app.push_widget(dlg)
|
||||
else:
|
||||
self._update_experimental_mode_icon()
|
||||
self._params.put_bool("ExperimentalMode", state, block=True)
|
||||
|
||||
def _toggle_callback(self, state: bool, param: str):
|
||||
if param == "ExperimentalMode":
|
||||
self._handle_experimental_mode_toggle(state)
|
||||
return
|
||||
|
||||
self._params.put_bool(param, state, block=True)
|
||||
if self._toggle_defs[param][3]:
|
||||
self._params.put_bool("OnroadCycleRequested", True, block=True)
|
||||
|
||||
@@ -2,7 +2,6 @@ from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import math
|
||||
import time
|
||||
|
||||
from openpilot.cereal import log
|
||||
import pyray as rl
|
||||
@@ -127,13 +126,8 @@ class MiciHomeLayout(Widget):
|
||||
self._on_alerts_click: Callable | None = None
|
||||
self._alert_count_callback: Callable[[], int] | None = None
|
||||
|
||||
self._mouse_down_t: None | float = None
|
||||
self._did_long_press = False
|
||||
self._is_pressed_prev = False
|
||||
|
||||
self._version_text = self._get_version_text()
|
||||
|
||||
self._experimental_icon = IconWidget("icons_mici/experimental_mode.png", (48, 48))
|
||||
self._usb_icon = IconWidget("icons_mici/usb.png", (62, 40))
|
||||
self._chestnut_icon = IconWidget("icons_mici/chestnut_green.png", (54, 40))
|
||||
self._chestnut_loading_icon = IconWidget("icons_mici/chestnut.png", (68, 40))
|
||||
@@ -146,7 +140,6 @@ class MiciHomeLayout(Widget):
|
||||
self._status_bar_layout = HBoxLayout([
|
||||
IconWidget("icons_mici/settings.png", (48, 48), opacity=0.9),
|
||||
NetworkIcon(),
|
||||
self._experimental_icon,
|
||||
self._usb_icon,
|
||||
self._chestnut_icon,
|
||||
self._chestnut_loading_icon,
|
||||
@@ -162,23 +155,6 @@ class MiciHomeLayout(Widget):
|
||||
self._branch_label = UnifiedLabel("", font_size=36, text_color=rl.GRAY, font_weight=FontWeight.ROMAN, scroll=True)
|
||||
self._version_commit_label = UnifiedLabel("", font_size=36, text_color=rl.GRAY, font_weight=FontWeight.ROMAN, max_width=480, wrap_text=False)
|
||||
|
||||
def _update_state(self):
|
||||
if self.is_pressed and not self._is_pressed_prev:
|
||||
self._mouse_down_t = time.monotonic()
|
||||
elif not self.is_pressed and self._is_pressed_prev:
|
||||
self._mouse_down_t = None
|
||||
self._did_long_press = False
|
||||
self._is_pressed_prev = self.is_pressed
|
||||
|
||||
if self._mouse_down_t is not None:
|
||||
if time.monotonic() - self._mouse_down_t > 0.5:
|
||||
# long gating for experimental mode - only allow toggle if longitudinal control is available
|
||||
if ui_state.has_longitudinal_control and ui_state.experimental_mode_confirmed:
|
||||
ui_state.experimental_mode = not ui_state.experimental_mode
|
||||
ui_state.params.put("ExperimentalMode", ui_state.experimental_mode, block=True)
|
||||
self._mouse_down_t = None
|
||||
self._did_long_press = True
|
||||
|
||||
def set_callbacks(self, on_settings: Callable | None = None, on_alerts: Callable | None = None,
|
||||
alert_count_callback: Callable[[], int] | None = None,
|
||||
alert_icon_callback: Callable[[], rl.Texture | None] | None = None):
|
||||
@@ -188,15 +164,13 @@ class MiciHomeLayout(Widget):
|
||||
self._alerts_pill.set_alert_count_callback(alert_count_callback, alert_icon_callback)
|
||||
|
||||
def _handle_mouse_release(self, mouse_pos: MousePos):
|
||||
if not self._did_long_press:
|
||||
relative_x = mouse_pos.x - self.rect.x
|
||||
has_alerts = self._alert_count_callback and self._alert_count_callback() > 0
|
||||
if has_alerts and relative_x > self.rect.width - ALERTS_ZONE_WIDTH:
|
||||
if self._on_alerts_click:
|
||||
self._on_alerts_click()
|
||||
elif self._on_settings_click:
|
||||
self._on_settings_click()
|
||||
self._did_long_press = False
|
||||
relative_x = mouse_pos.x - self.rect.x
|
||||
has_alerts = self._alert_count_callback and self._alert_count_callback() > 0
|
||||
if has_alerts and relative_x > self.rect.width - ALERTS_ZONE_WIDTH:
|
||||
if self._on_alerts_click:
|
||||
self._on_alerts_click()
|
||||
elif self._on_settings_click:
|
||||
self._on_settings_click()
|
||||
|
||||
def _get_version_text(self) -> tuple[str, str, str, str] | None:
|
||||
version = ui_state.params.get("Version")
|
||||
@@ -249,7 +223,6 @@ class MiciHomeLayout(Widget):
|
||||
usb_connected = ui_state.usb_connected
|
||||
usb_unknown = ui_state.usb_unknown
|
||||
chestnut_state = ui_state.chestnut_state
|
||||
self._experimental_icon.set_visible(ui_state.experimental_mode)
|
||||
if gui_app.sunnypilot_ui():
|
||||
self._set_chestnut_visibility()
|
||||
else:
|
||||
|
||||
@@ -83,6 +83,8 @@ class DeveloperLayoutMici(NavScroller):
|
||||
toggle_callback=self._on_alpha_long_enabled,
|
||||
description="Use alpha openpilot longitudinal control instead of stock ACC. This may disable Automatic Emergency " +
|
||||
"Braking (AEB).")
|
||||
self._navigation_toggle = BigParamControl("navigation (alpha)", "NavigationEnabled",
|
||||
description="Turn-by-turn navigation with a route map. Set a destination from comma connect.")
|
||||
self._debug_mode_toggle = BigParamControl("ui debug mode", "ShowDebugInfo",
|
||||
toggle_callback=lambda checked: (gui_app.set_show_touches(checked), gui_app.set_show_fps(checked)),
|
||||
description="Show touch locations and the UI frame rate.")
|
||||
@@ -96,6 +98,7 @@ class DeveloperLayoutMici(NavScroller):
|
||||
self._lat_maneuver_toggle,
|
||||
self._alpha_long_toggle,
|
||||
self._debug_mode_toggle,
|
||||
self._navigation_toggle,
|
||||
])
|
||||
|
||||
# Toggle lists
|
||||
@@ -107,9 +110,10 @@ class DeveloperLayoutMici(NavScroller):
|
||||
("LateralManeuverMode", self._lat_maneuver_toggle),
|
||||
("AlphaLongitudinalEnabled", self._alpha_long_toggle),
|
||||
("ShowDebugInfo", self._debug_mode_toggle),
|
||||
("NavigationEnabled", self._navigation_toggle),
|
||||
)
|
||||
onroad_blocked_toggles = (self._adb_toggle, self._joystick_toggle)
|
||||
release_blocked_toggles = (self._joystick_toggle, self._long_maneuver_toggle, self._lat_maneuver_toggle, self._alpha_long_toggle)
|
||||
release_blocked_toggles = (self._joystick_toggle, self._long_maneuver_toggle, self._lat_maneuver_toggle, self._alpha_long_toggle, self._navigation_toggle)
|
||||
engaged_blocked_toggles = (self._long_maneuver_toggle, self._lat_maneuver_toggle, self._alpha_long_toggle)
|
||||
|
||||
# Hide non-release toggles on release builds
|
||||
@@ -180,7 +184,6 @@ class DeveloperLayoutMici(NavScroller):
|
||||
|
||||
def _on_lat_maneuver_mode(self, state: bool):
|
||||
ui_state.params.put_bool("LateralManeuverMode", state, block=True)
|
||||
ui_state.params.put_bool("ExperimentalMode", False, block=True)
|
||||
ui_state.params.put_bool("JoystickDebugMode", False, block=True)
|
||||
self._joystick_toggle.set_checked(False)
|
||||
ui_state.params.put_bool("LongitudinalManeuverMode", False, block=True)
|
||||
|
||||
@@ -1,59 +1,27 @@
|
||||
from collections.abc import Callable
|
||||
|
||||
from openpilot.cereal import log
|
||||
|
||||
from openpilot.system.ui.widgets.scroller import NavScroller
|
||||
from openpilot.selfdrive.ui.mici.widgets.button import BigParamControl, BigMultiParamToggle, BigToggle, GreyBigButton
|
||||
from openpilot.selfdrive.ui.mici.widgets.dialog import BigConfirmationCircleButton
|
||||
from openpilot.selfdrive.ui.mici.widgets.button import BigToggle, BigParamControl, BigMultiParamToggle
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.selfdrive.ui.layouts.settings.common import restart_needed_callback
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.selfdrive.ui.mici.layouts.settings.initial_cruise_speed import InitialCruiseSpeedButton
|
||||
|
||||
PERSONALITY_TO_INT = log.LongitudinalPersonality.schema.enumerants
|
||||
|
||||
|
||||
class ExperimentalModeConfirmPage(NavScroller):
|
||||
def __init__(self, on_confirm: Callable[[], None]):
|
||||
super().__init__()
|
||||
|
||||
accept = BigConfirmationCircleButton("enable\nexperimental mode",
|
||||
gui_app.texture("icons_mici/setup/driver_monitoring/dm_check.png", 64, 64),
|
||||
lambda: self.dismiss(on_confirm))
|
||||
|
||||
self._scroller.add_widgets([
|
||||
GreyBigButton("enabling\nexperimental mode", "scroll to continue",
|
||||
gui_app.texture("icons_mici/setup/warning.png", 64, 64)),
|
||||
GreyBigButton("", "openpilot defaults to driving in chill mode."),
|
||||
GreyBigButton("", "Experimental mode enables alpha-level features that aren't ready for chill mode."),
|
||||
GreyBigButton("End-to-End Longitudinal Control"),
|
||||
GreyBigButton("", "Let the driving model control the gas and brakes."),
|
||||
GreyBigButton("", "openpilot will drive as it thinks a human would, including stopping for red lights and stop signs."),
|
||||
GreyBigButton("", "The set speed will only act as an upper bound."),
|
||||
GreyBigButton("", "This is an alpha quality feature; mistakes should be expected."),
|
||||
GreyBigButton("New Driving Visualization"),
|
||||
GreyBigButton("", "The path will change colors to communicate acceleration intent."),
|
||||
GreyBigButton("", "Red for braking, green for acceleration, and gray for coasting."),
|
||||
accept,
|
||||
])
|
||||
|
||||
|
||||
class TogglesLayoutMici(NavScroller):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self._personality_toggle = BigMultiParamToggle("driving personality", "LongitudinalPersonality", ["aggressive", "standard", "relaxed"],
|
||||
self._personality_toggle = BigMultiParamToggle("following distance", "LongitudinalPersonality", ["aggressive", "standard", "relaxed"],
|
||||
description="Standard is recommended.\n" +
|
||||
"Aggressive follows closer, with firmer gas and braking.\n" +
|
||||
"Relaxed leaves more space.\n" +
|
||||
"Use the steering wheel distance button on supported cars.")
|
||||
self._experimental_btn = BigToggle("experimental mode", description_icon=gui_app.texture("icons_mici/experimental_mode.png", 64, 64),
|
||||
initial_state=ui_state.params.get_bool("ExperimentalMode"), toggle_callback=self._on_experimental_mode,
|
||||
description="Let the driving model control gas and brakes.\n" +
|
||||
"Includes stopping for red lights and stop signs.\n" +
|
||||
"Set speed is a maximum, not a target.\n" +
|
||||
"These are alpha features. Expect mistakes.\n" +
|
||||
"The path colors show acceleration and braking.")
|
||||
is_metric_toggle = BigParamControl("use metric units", "IsMetric")
|
||||
self._initial_cruise_speed = InitialCruiseSpeedButton()
|
||||
self._initial_cruise_speed.set_visible(lambda: ui_state.CP is not None and ui_state.has_longitudinal_control and not ui_state.CP.pcmCruise)
|
||||
is_metric_toggle = BigToggle("use metric units", initial_state=ui_state.params.get_bool("IsMetric"), toggle_callback=self._on_metric_toggle)
|
||||
ldw_toggle = BigParamControl("lane departure warnings", "IsLdwEnabled",
|
||||
description="Warn when you drift across a detected lane line.\n" +
|
||||
"Only above 31 mph (50 km/h), with no turn signal.")
|
||||
@@ -72,7 +40,7 @@ class TogglesLayoutMici(NavScroller):
|
||||
|
||||
self._scroller.add_widgets([
|
||||
self._personality_toggle,
|
||||
self._experimental_btn,
|
||||
self._initial_cruise_speed,
|
||||
is_metric_toggle,
|
||||
ldw_toggle,
|
||||
always_on_dm_toggle,
|
||||
@@ -83,7 +51,6 @@ class TogglesLayoutMici(NavScroller):
|
||||
|
||||
# Toggle lists
|
||||
self._refresh_toggles = (
|
||||
("ExperimentalMode", self._experimental_btn),
|
||||
("IsMetric", is_metric_toggle),
|
||||
("IsLdwEnabled", ldw_toggle),
|
||||
("AlwaysOnDM", always_on_dm_toggle),
|
||||
@@ -115,35 +82,17 @@ class TogglesLayoutMici(NavScroller):
|
||||
super().show_event()
|
||||
self._update_toggles()
|
||||
|
||||
def _on_metric_toggle(self, state: bool):
|
||||
ui_state.params.put_bool("IsMetric", state, block=True)
|
||||
self._update_toggles()
|
||||
|
||||
def _update_toggles(self):
|
||||
ui_state.update_params()
|
||||
self._initial_cruise_speed.refresh()
|
||||
|
||||
# CP gating for experimental mode
|
||||
if ui_state.CP is not None:
|
||||
if ui_state.has_longitudinal_control:
|
||||
self._experimental_btn.set_visible(True)
|
||||
self._personality_toggle.set_visible(True)
|
||||
else:
|
||||
# no long for now
|
||||
self._experimental_btn.set_visible(False)
|
||||
self._experimental_btn.set_checked(False)
|
||||
self._personality_toggle.set_visible(False)
|
||||
ui_state.params.remove("ExperimentalMode")
|
||||
self._personality_toggle.set_visible(ui_state.has_longitudinal_control)
|
||||
|
||||
# Refresh toggles from params to mirror external changes
|
||||
for key, item in self._refresh_toggles:
|
||||
item.set_checked(ui_state.params.get_bool(key))
|
||||
|
||||
def _on_experimental_mode(self, state: bool):
|
||||
if state and not ui_state.params.get_bool("ExperimentalModeConfirmed"):
|
||||
# Don't show enabled state until confirm
|
||||
self._experimental_btn.set_checked(False)
|
||||
|
||||
def on_confirm():
|
||||
ui_state.params.put_bool("ExperimentalModeConfirmed", True)
|
||||
ui_state.params.put_bool("ExperimentalMode", True)
|
||||
self._experimental_btn.set_checked(True)
|
||||
|
||||
gui_app.push_widget(ExperimentalModeConfirmPage(on_confirm))
|
||||
else:
|
||||
ui_state.params.put_bool("ExperimentalMode", state)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import pyray as rl
|
||||
from dataclasses import dataclass
|
||||
from openpilot.common.constants import CV
|
||||
from openpilot.selfdrive.ui.onroad.exp_button import ExpButton
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
@@ -18,11 +17,9 @@ CRUISE_DISABLED_CHAR = '–'
|
||||
class UIConfig:
|
||||
header_height: int = 300
|
||||
border_size: int = 30
|
||||
button_size: int = 192
|
||||
set_speed_width_metric: int = 200
|
||||
set_speed_width_imperial: int = 172
|
||||
set_speed_height: int = 204
|
||||
wheel_icon_size: int = 144
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -71,7 +68,6 @@ class HudRenderer(Widget):
|
||||
self._font_medium: rl.Font = gui_app.font(FontWeight.MEDIUM)
|
||||
self._font_speed: rl.Font = gui_app.high_res_speed_font()
|
||||
|
||||
self._exp_button: ExpButton = ExpButton(UI_CONFIG.button_size, UI_CONFIG.wheel_icon_size)
|
||||
|
||||
def _update_state(self) -> None:
|
||||
"""Update HUD state based on car state and controls state."""
|
||||
@@ -118,13 +114,6 @@ class HudRenderer(Widget):
|
||||
|
||||
self._draw_current_speed(rect)
|
||||
|
||||
button_x = rect.x + rect.width - UI_CONFIG.border_size - UI_CONFIG.button_size
|
||||
button_y = rect.y + UI_CONFIG.border_size
|
||||
self._exp_button.render(rl.Rectangle(button_x, button_y, UI_CONFIG.button_size, UI_CONFIG.button_size))
|
||||
|
||||
def user_interacting(self) -> bool:
|
||||
return self._exp_button.is_pressed
|
||||
|
||||
def _draw_set_speed(self, rect: rl.Rectangle) -> None:
|
||||
"""Draw the MAX speed indicator box."""
|
||||
set_speed_width = UI_CONFIG.set_speed_width_metric if ui_state.is_metric else UI_CONFIG.set_speed_width_imperial
|
||||
|
||||
@@ -85,7 +85,6 @@ class CruiseLayout(Widget):
|
||||
)
|
||||
|
||||
items = [
|
||||
self._toggles_layout._toggles["ExperimentalMode"],
|
||||
self._toggles_layout._toggles["LongitudinalPersonality"],
|
||||
self._toggles_layout._toggles["IsMetric"],
|
||||
self.scc_v_toggle,
|
||||
|
||||
@@ -8,6 +8,7 @@ from enum import Enum
|
||||
|
||||
from openpilot.cereal import messaging, log, custom
|
||||
from opendbc.car.structs import car
|
||||
from opendbc.sunnypilot.car.interfaces import has_bsm
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.display import OnroadBrightness
|
||||
from openpilot.sunnypilot.models.helpers import ACTIVE_BUNDLE_KEYS, get_active_source
|
||||
@@ -35,7 +36,7 @@ class UIStateSP:
|
||||
self.is_sp_release: bool = self.params.get_bool("IsReleaseSpBranch")
|
||||
self.sm_services_ext = [
|
||||
"modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP",
|
||||
"gpsLocation", "lateralTorqueParameters", "carStateSP", "liveMapDataSP", "carParamsSP", "lateralDelay"
|
||||
"lateralTorqueParameters", "carStateSP", "liveMapDataSP", "carParamsSP", "lateralDelay"
|
||||
]
|
||||
|
||||
self.sunnylink_state = SunnylinkState()
|
||||
@@ -212,7 +213,7 @@ class UIStateSP:
|
||||
self.params.remove("AlphaLongitudinalEnabled")
|
||||
|
||||
# BSM not available: clear BSM-dependent settings
|
||||
if not CP.enableBsm:
|
||||
if not has_bsm(CP, self.CP_SP):
|
||||
self.params.remove("AutoLaneChangeBsmDelay")
|
||||
else:
|
||||
# No CarParams: clear all car-dependent params as safety default
|
||||
@@ -221,10 +222,6 @@ class UIStateSP:
|
||||
self.params.remove("LateralJerkTorqueController")
|
||||
self.params.remove("AlphaLongitudinalEnabled")
|
||||
|
||||
# No longitudinal control: no experimental mode
|
||||
if not has_long:
|
||||
self.params.remove("ExperimentalMode")
|
||||
|
||||
# ICBM: clear if not available or if full longitudinal control is active
|
||||
if self.CP_SP is not None:
|
||||
if not self.CP_SP.intelligentCruiseButtonManagementAvailable or has_long:
|
||||
|
||||
@@ -12,8 +12,9 @@ from openpilot.common.swaglog import cloudlog
|
||||
from openpilot.selfdrive.ui.lib.prime_state import PrimeState
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.common.hardware import HARDWARE, PC
|
||||
from openpilot.common.hardware.usb import TYPEC_CC_ORIENTATION_PATH, get_usb_state, is_chestnut_usb_id, read_int
|
||||
from openpilot.common.hardware.usb import cable_connected, get_usb_state, is_chestnut_usb_id
|
||||
from openpilot.selfdrive.modeld.helpers import chestnut_compiled
|
||||
from openpilot.selfdrive.selfdrived.alertmanager import OFFROAD_ALERTS
|
||||
|
||||
from openpilot.selfdrive.ui.sunnypilot.ui_state import UIStateSP, DeviceSP
|
||||
|
||||
@@ -69,6 +70,8 @@ class UIState(UIStateSP):
|
||||
"selfdriveState",
|
||||
"longitudinalPlan",
|
||||
"gpsLocationExternal",
|
||||
"gpsLocation",
|
||||
"navInstruction",
|
||||
"carOutput",
|
||||
"carControl",
|
||||
"vehicleParameters",
|
||||
@@ -88,14 +91,16 @@ class UIState(UIStateSP):
|
||||
|
||||
# Core state variables
|
||||
self.is_metric: bool = self.params.get_bool("IsMetric")
|
||||
self.initial_cruise_speed: int = self.params.get("InitialCruiseSpeedKph", return_default=True)
|
||||
self.is_release = False # self.params.get_bool("IsReleaseBranch")
|
||||
self.always_on_dm: bool = self.params.get_bool("AlwaysOnDM")
|
||||
self.experimental_mode: bool = self.params.get_bool("ExperimentalMode")
|
||||
self.experimental_mode_confirmed: bool = self.params.get_bool("ExperimentalModeConfirmed")
|
||||
self.navigation_enabled: bool = self.params.get_bool("NavigationEnabled")
|
||||
self.nav_destination_set: bool = self.params.get("NavDestination") is not None
|
||||
self.chestnut_present: bool = False
|
||||
self.chestnut_compiled: bool = chestnut_compiled()
|
||||
self.chestnut_active: bool | None = None
|
||||
self.chestnut_loading: bool = False
|
||||
self.chestnut_alert: bool = False
|
||||
self.usb_connected: bool = False
|
||||
self.usb_connected_ts: float | None = None
|
||||
self.usb_disconnected_ts: float | None = None
|
||||
@@ -210,7 +215,7 @@ class UIState(UIStateSP):
|
||||
self.status = UIStatus.DISENGAGED
|
||||
self.started_frame = self.sm.frame
|
||||
self.started_time = time.monotonic()
|
||||
self.chestnut_present = self.sm["deviceState"].chestnutPresent
|
||||
self.chestnut_present = self.sm["deviceState"].chestnutPresent or (self.chestnut_compiled and self.usb_connected)
|
||||
|
||||
for callback in self._offroad_transition_callbacks:
|
||||
callback()
|
||||
@@ -221,7 +226,8 @@ class UIState(UIStateSP):
|
||||
detected = self.sm["deviceState"].chestnutPresent
|
||||
if not self.started:
|
||||
self.chestnut_present = detected
|
||||
self.chestnut_state = (ChestnutState.READY if detected and self.chestnut_compiled else
|
||||
self.chestnut_state = (ChestnutState.FAILED if self.chestnut_alert else
|
||||
ChestnutState.READY if detected and self.chestnut_compiled else
|
||||
ChestnutState.UNCOMPILED if detected else ChestnutState.DISCONNECTED)
|
||||
return
|
||||
|
||||
@@ -230,10 +236,10 @@ class UIState(UIStateSP):
|
||||
self.chestnut_state = ChestnutState.DISCONNECTED
|
||||
elif not self.chestnut_compiled:
|
||||
self.chestnut_state = ChestnutState.UNCOMPILED
|
||||
elif self.chestnut_state == ChestnutState.FAILED or not detected or (model_seen and (not self.sm.alive["modelV2"] or not self.sm["modelV2"].big)):
|
||||
self.chestnut_state = ChestnutState.FAILED
|
||||
elif self.chestnut_loading or not model_seen:
|
||||
self.chestnut_state = ChestnutState.LOADING
|
||||
elif self.chestnut_state == ChestnutState.FAILED or not detected or (model_seen and (not self.sm.alive["modelV2"] or not self.sm["modelV2"].big)):
|
||||
self.chestnut_state = ChestnutState.FAILED
|
||||
elif self.chestnut_active is False:
|
||||
self.chestnut_state = ChestnutState.FAILED
|
||||
else:
|
||||
@@ -252,15 +258,15 @@ class UIState(UIStateSP):
|
||||
|
||||
self.recording_audio = self.params.get_bool("RecordAudio") and self.started
|
||||
self.is_metric = self.params.get_bool("IsMetric")
|
||||
self.initial_cruise_speed = self.params.get("InitialCruiseSpeedKph", return_default=True)
|
||||
self.always_on_dm = self.params.get_bool("AlwaysOnDM")
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode")
|
||||
self.experimental_mode_confirmed = self.params.get_bool("ExperimentalModeConfirmed")
|
||||
if not self.chestnut_compiled:
|
||||
self.chestnut_compiled = chestnut_compiled()
|
||||
self.navigation_enabled = self.params.get_bool("NavigationEnabled")
|
||||
self.nav_destination_set = self.params.get("NavDestination") is not None
|
||||
self.chestnut_active = self.params.get("ChestnutActive")
|
||||
self.chestnut_loading = self.params.get_bool("ChestnutLoading")
|
||||
self.chestnut_alert = any(self.params.get(k) is not None for k, a in OFFROAD_ALERTS.items() if k.startswith("Offroad_Chestnut") and a["severity"] >= 0)
|
||||
now = time.monotonic()
|
||||
if read_int(TYPEC_CC_ORIENTATION_PATH) != 0:
|
||||
if cable_connected():
|
||||
self.usb_disconnected_ts = None
|
||||
if not self.usb_connected:
|
||||
self.usb_connected = True
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import pyray as rl
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
|
||||
class ExperimentalModeButton(Widget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.img_width = 80
|
||||
self.horizontal_padding = 25
|
||||
self.button_height = 125
|
||||
|
||||
self.params = Params()
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode")
|
||||
|
||||
self.chill_pixmap = gui_app.texture("icons/couch.png", self.img_width, self.img_width)
|
||||
self.experimental_pixmap = gui_app.texture("icons/experimental_grey.png", self.img_width, self.img_width)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode")
|
||||
|
||||
def _get_gradient_colors(self):
|
||||
alpha = 0xCC if self.is_pressed else 0xFF
|
||||
|
||||
if self.experimental_mode:
|
||||
return rl.Color(255, 155, 63, alpha), rl.Color(219, 56, 34, alpha)
|
||||
else:
|
||||
return rl.Color(20, 255, 171, alpha), rl.Color(35, 149, 255, alpha)
|
||||
|
||||
def _draw_gradient_background(self, rect):
|
||||
start_color, end_color = self._get_gradient_colors()
|
||||
rl.draw_rectangle_gradient_h(int(rect.x), int(rect.y), int(rect.width), int(rect.height),
|
||||
start_color, end_color)
|
||||
|
||||
def _render(self, rect):
|
||||
rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height))
|
||||
self._draw_gradient_background(rect)
|
||||
rl.draw_rectangle_rounded_lines_ex(self._rect, 0.19, 10, 5, rl.BLACK)
|
||||
rl.end_scissor_mode()
|
||||
|
||||
# Draw vertical separator line
|
||||
line_x = rect.x + rect.width - self.img_width - (2 * self.horizontal_padding)
|
||||
separator_color = rl.Color(0, 0, 0, 77) # 0x4d = 77
|
||||
rl.draw_line_ex(rl.Vector2(line_x, rect.y), rl.Vector2(line_x, rect.y + rect.height), 3, separator_color)
|
||||
|
||||
# Draw text label (left aligned)
|
||||
text = tr("EXPERIMENTAL MODE ON") if self.experimental_mode else tr("CHILL MODE ON")
|
||||
text_x = rect.x + self.horizontal_padding
|
||||
text_y = rect.y + rect.height / 2 - 45 * FONT_SCALE // 2 # Center vertically
|
||||
|
||||
rl.draw_text_ex(gui_app.font(FontWeight.NORMAL), text, rl.Vector2(int(text_x), int(text_y)), 45, 0, rl.BLACK)
|
||||
|
||||
# Draw icon (right aligned)
|
||||
icon_x = rect.x + rect.width - self.horizontal_padding - self.img_width
|
||||
icon_y = rect.y + (rect.height - self.img_width) / 2
|
||||
icon_rect = rl.Rectangle(icon_x, icon_y, self.img_width, self.img_width)
|
||||
|
||||
# Draw current mode icon
|
||||
current_icon = self.experimental_pixmap if self.experimental_mode else self.chill_pixmap
|
||||
source_rect = rl.Rectangle(0, 0, current_icon.width, current_icon.height)
|
||||
rl.draw_texture_pro(current_icon, source_rect, icon_rect, rl.Vector2(0, 0), 0, rl.WHITE)
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
#include "tools/replay/filereader.h"
|
||||
#include "tools/replay/py_downloader.h"
|
||||
#include "tools/replay/py_tools.h"
|
||||
#include "tools/replay/util.h"
|
||||
#include "common/util.h"
|
||||
|
||||
@@ -142,7 +142,6 @@ void LogReader::migrateOldEvents() {
|
||||
new_state.setAlertType(old_dep.getAlertType());
|
||||
new_state.setEnabled(old_dep.getEnabled());
|
||||
new_state.setEngageable(old_dep.getEngageable());
|
||||
new_state.setExperimentalMode(old_dep.getExperimentalMode());
|
||||
new_state.setPersonality(old_dep.getPersonality());
|
||||
new_state.setState(old_dep.getState());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user