From 4531cd7ac6a794fcab487e68343a593d150b1301 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 1 Jun 2025 23:36:55 -0400 Subject: [PATCH] use old controller for now --- cereal/custom.capnp | 9 +- .../speed_limit_controller.py | 338 +++++++++++------- sunnypilot/selfdrive/selfdrived/events.py | 38 +- 3 files changed, 217 insertions(+), 168 deletions(-) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 1a5f06ede0..f3d59f0ffa 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -173,13 +173,8 @@ struct OnroadEventSP @0xda96579883444c35 { pedalPressedAlertOnly @16; speedLimitPreActive @17; speedLimitActive @18; - speedLimitValueChange @19; - speedLimitAdapting @20; - speedLimitEnable @21; - speedLimitDisable @22; - speedLimitUserConfirm @23; - speedLimitUserCancel @24; - speedLimitReached @25; + speedLimitConfirmed @19; + speedLimitValueChange @20; } } diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit_controller/speed_limit_controller.py b/sunnypilot/selfdrive/controls/lib/speed_limit_controller/speed_limit_controller.py index cc62211069..a53fe3a288 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit_controller/speed_limit_controller.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit_controller/speed_limit_controller.py @@ -1,33 +1,34 @@ import numpy as np import time -from cereal import messaging, custom -from opendbc.car import structs +from cereal import custom from openpilot.common.conversions import Conversions as CV from openpilot.common.params import Params from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit_controller import LIMIT_PERC_OFFSET_BP, LIMIT_PERC_OFFSET_V, \ - PARAMS_UPDATE_PERIOD, TEMP_INACTIVE_GUARD_PERIOD, LIMIT_SPEED_OFFSET_TH + PARAMS_UPDATE_PERIOD, TEMP_INACTIVE_GUARD_PERIOD, LIMIT_SPEED_OFFSET_TH, SpeedLimitControlState +from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N +from openpilot.selfdrive.selfdrived.events import ET from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit_controller.common import Source, Policy, Engage, OffsetType -from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit_controller.helpers import debug +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit_controller.helpers import description_for_state, debug from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit_controller.speed_limit_resolver import SpeedLimitResolver -from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit_controller.state import StateMachine -from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP +from openpilot.selfdrive.modeld.constants import ModelConstants EventNameSP = custom.OnroadEventSP.EventName -State = custom.LongitudinalPlanSP.SpeedLimitControlState + +ACTIVE_STATES = (SpeedLimitControlState.active, SpeedLimitControlState.adapting) +ENABLED_STATES = (SpeedLimitControlState.preActive, SpeedLimitControlState.tempInactive, *ACTIVE_STATES) class SpeedLimitController: - def __init__(self, CP: structs.CarParams): + def __init__(self, CP): self._params = Params() self._CP = CP self._policy = Policy(int(self._params.get("SpeedLimitControlPolicy", encoding='utf8'))) self._resolver = SpeedLimitResolver(self._policy) - self._state_machine = StateMachine() self._last_params_update = 0.0 self._last_op_enabled_time = 0.0 self._is_metric = self._params.get_bool("IsMetric") - self._enabled_toggle = self._params.get_bool("SpeedLimitControl") + self._is_enabled = self._params.get_bool("EnableSlc") self._disengage_on_accelerator = self._params.get_bool("DisengageOnAccelerator") self._op_enabled = False self._op_enabled_prev = False @@ -36,48 +37,85 @@ class SpeedLimitController: self._v_offset = 0. self._v_cruise_setpoint = 0. self._v_cruise_setpoint_prev = 0. + self._v_cruise_setpoint_changed = False self._speed_limit = 0. self._speed_limit_prev = 0. + self._speed_limit_changed = False self._distance = 0. self._source = Source.none + self._state = SpeedLimitControlState.inactive + self._state_prev = SpeedLimitControlState.inactive self._gas_pressed = False self._pcm_cruise_op_long = CP.openpilotLongitudinalControl and CP.pcmCruise self._offset_type = int(self._params.get("SpeedLimitOffsetType", encoding='utf8')) self._offset_value = float(self._params.get("SpeedLimitValueOffset", encoding='utf8')) - self._warning_type = int(self._params.get("SpeedLimitWarningType", encoding='utf8')) + self._warning_type_type = int(self._params.get("SpeedLimitWarningType", encoding='utf8')) self._warning_offset_type = int(self._params.get("SpeedLimitWarningOffsetType", encoding='utf8')) self._warning_offset_value = float(self._params.get("SpeedLimitWarningValueOffset", encoding='utf8')) self._engage_type = np.clip(int(self._params.get("SpeedLimitEngageType", encoding='utf8')), Engage.auto, Engage.user_confirm) self._brake_pressed = False self._brake_pressed_prev = False self._current_time = 0. + self._v_cruise_rounded = 0. + self._v_cruise_prev_rounded = 0. + self._speed_limit_offsetted_rounded = 0. + self._speed_limit_warning_offsetted_rounded = 0. self._ms_to_local = CV.MS_TO_KPH if self._is_metric else CV.MS_TO_MPH - # State tracking - self._enabled = False - self._active = False + # Mapping functions to state transitions + self.state_transition_strategy = { + # Transition functions for each state + SpeedLimitControlState.inactive: self.transition_state_from_inactive, + SpeedLimitControlState.tempInactive: self.transition_state_from_temp_inactive, + SpeedLimitControlState.adapting: self.transition_state_from_adapting, + SpeedLimitControlState.active: self.transition_state_from_active, + SpeedLimitControlState.preActive: self.transition_state_from_pre_active, + } + + # FIXME-SP: unused? + # Solution functions mapped to respective states + self.acceleration_solutions = { + # Solution functions for each state + SpeedLimitControlState.tempInactive: self.get_current_acceleration_as_target, + SpeedLimitControlState.inactive: self.get_current_acceleration_as_target, + SpeedLimitControlState.adapting: self.get_adapting_state_target_acceleration, + SpeedLimitControlState.active: self.get_active_state_target_acceleration, + SpeedLimitControlState.preActive: self.get_current_acceleration_as_target, + } @property - def state(self) -> State: - return self._state_machine.state + def state(self): + return self._state + + @state.setter + def state(self, value): + if value != self._state: + debug(f'Speed Limit Controller state: {description_for_state(value)}') + + if value == SpeedLimitControlState.tempInactive: + # Reset previous speed limit to current value as to prevent going out of tempInactive in + # a single cycle when the speed limit changes at the same time the user has temporarily deactivated it. + self._speed_limit_prev = self._speed_limit + + self._state = value @property - def is_enabled(self) -> bool: - return self._enabled and self._enabled_toggle + def is_enabled(self): + return self.state in ENABLED_STATES and self._is_enabled @property - def is_active(self) -> bool: - return self._active and self._enabled_toggle + def is_active(self): + return self.state in ACTIVE_STATES and self._is_enabled @property - def speed_limit_offseted(self) -> float: + def speed_limit_offseted(self): return self._speed_limit + self.speed_limit_offset @property - def speed_limit_offset(self) -> float: + def speed_limit_offset(self): if self._offset_type == OffsetType.default: - return float(np.interp(self._speed_limit, LIMIT_PERC_OFFSET_BP, LIMIT_PERC_OFFSET_V) * self._speed_limit) + return np.interp(self._speed_limit, LIMIT_PERC_OFFSET_BP, LIMIT_PERC_OFFSET_V) * self._speed_limit elif self._offset_type == OffsetType.fixed: return self._offset_value * (CV.KPH_TO_MS if self._is_metric else CV.MPH_TO_MS) elif self._offset_type == OffsetType.percentage: @@ -85,9 +123,9 @@ class SpeedLimitController: return 0. @property - def speed_limit_warning_offset(self) -> float: + def speed_limit_warning_offset(self): if self._warning_offset_type == OffsetType.default: - return float(np.interp(self._speed_limit, LIMIT_PERC_OFFSET_BP, LIMIT_PERC_OFFSET_V) * self._speed_limit) + return np.interp(self._speed_limit, LIMIT_PERC_OFFSET_BP, LIMIT_PERC_OFFSET_V) * self._speed_limit elif self._warning_offset_type == OffsetType.fixed: return self._warning_offset_value * (CV.KPH_TO_MS if self._is_metric else CV.MPH_TO_MS) elif self._warning_offset_type == OffsetType.percentage: @@ -95,24 +133,26 @@ class SpeedLimitController: return 0. @property - def speed_limit(self) -> float: + def speed_limit(self): return self._speed_limit @property - def distance(self) -> float: + def distance(self): return self._distance @property - def source(self) -> Source: + def source(self): return self._source - def _update_params(self) -> None: + def _update_v_cruise_setpoint_prev(self): + self._v_cruise_setpoint_prev = self._v_cruise_setpoint + + def _update_params(self): if self._current_time > self._last_params_update + PARAMS_UPDATE_PERIOD: - self._enabled_toggle = self._params.get_bool("SpeedLimitControl") - self._disengage_on_accelerator = self._params.get_bool("DisengageOnAccelerator") + self._is_enabled = self._params.get_bool("EnableSlc") self._offset_type = int(self._params.get("SpeedLimitOffsetType", encoding='utf8')) self._offset_value = float(self._params.get("SpeedLimitValueOffset", encoding='utf8')) - self._warning_type = int(self._params.get("SpeedLimitWarningType", encoding='utf8')) + self._warning_type_type = int(self._params.get("SpeedLimitWarningType", encoding='utf8')) self._warning_offset_type = int(self._params.get("SpeedLimitWarningOffsetType", encoding='utf8')) self._warning_offset_value = float(self._params.get("SpeedLimitWarningValueOffset", encoding='utf8')) self._policy = Policy(int(self._params.get("SpeedLimitControlPolicy", encoding='utf8'))) @@ -121,113 +161,155 @@ class SpeedLimitController: self._resolver.change_policy(self._policy) self._engage_type = Engage.auto if self._pcm_cruise_op_long else \ np.clip(int(self._params.get("SpeedLimitEngageType", encoding='utf8')), Engage.auto, Engage.user_confirm) - debug(f'Updated Speed limit params. enabled: {self._enabled_toggle}, with offset: {self._offset_type}') + debug(f'Updated Speed limit params. enabled: {self._is_enabled}, with offset: {self._offset_type}') self._last_params_update = self._current_time - def _generate_events(self, events_sp: EventsSP) -> None: - """Generate events based on current conditions""" - if not self._op_enabled or \ - not self._enabled_toggle or \ - self._speed_limit == 0 or \ - (self._gas_pressed and self._disengage_on_accelerator): - return + def _update_calculations(self): + # Update current velocity offset (error) + self._v_offset = self.speed_limit_offseted - self._v_ego - # Track selfdrived enabled time + # Track the time op becomes active to prevent going to tempInactive right away after + # op enabling since controlsd will change the cruise speed every time on enabling and this will + # cause a temp inactive transition if the controller is updated before controlsd sets actual cruise + # speed. if not self._op_enabled_prev and self._op_enabled: self._last_op_enabled_time = self._current_time - # Calculate current state - v_cruise_rounded = int(round(self._v_cruise_setpoint * self._ms_to_local)) - v_cruise_prev_rounded = int(round(self._v_cruise_setpoint_prev * self._ms_to_local)) - speed_limit_offsetted_rounded = 0 if self._speed_limit == 0 else int(round(self.speed_limit_offseted * self._ms_to_local)) + # Update change tracking variables + self._speed_limit_changed = self._speed_limit != self._speed_limit_prev + self._v_cruise_setpoint_changed = self._v_cruise_setpoint != self._v_cruise_setpoint_prev + self._speed_limit_prev = self._speed_limit + if self._engage_type != Engage.user_confirm: + self._update_v_cruise_setpoint_prev() + self._op_enabled_prev = self._op_enabled + self._brake_pressed_prev = self._brake_pressed - v_cruise_changed = self._v_cruise_setpoint != self._v_cruise_setpoint_prev - speed_limit_changed = self._speed_limit != self._speed_limit_prev + self._v_cruise_rounded = int(round(self._v_cruise_setpoint * self._ms_to_local)) + self._v_cruise_prev_rounded = int(round(self._v_cruise_setpoint_prev * self._ms_to_local)) + self._speed_limit_offsetted_rounded = 0 if self._speed_limit == 0 else int(round((self._speed_limit + self.speed_limit_offset) * self._ms_to_local)) + self._speed_limit_warning_offsetted_rounded = 0 if self._speed_limit == 0 else \ + int(round((self._speed_limit + self.speed_limit_warning_offset) * self._ms_to_local)) - # Update velocity offset - self._v_offset = self.speed_limit_offseted - self._v_ego - - # Generate state-specific events - if self._engage_type == Engage.auto: - self._generate_auto_engage_events(events_sp, v_cruise_changed) - elif self._engage_type == Engage.user_confirm: - self._generate_user_confirm_events(events_sp, v_cruise_changed, speed_limit_changed, - v_cruise_rounded, v_cruise_prev_rounded, - speed_limit_offsetted_rounded) - - # Check if we need to adapt (decelerate) to reach speed limit - if self._v_offset < LIMIT_SPEED_OFFSET_TH and self._enabled: - events_sp.add(EventNameSP.speedLimitAdapting) - elif self._v_offset >= LIMIT_SPEED_OFFSET_TH and self._enabled: - events_sp.add(EventNameSP.speedLimitReached) - - # Speed limit value change notification - if speed_limit_changed and self._active: - events_sp.add(EventNameSP.speedLimitValueChange) - - # Warning when over speed limit - if self._speed_limit > 0 and self._warning_type == 2: - speed_limit_warning_offsetted_rounded = int(round((self._speed_limit + self.speed_limit_warning_offset) * self._ms_to_local)) - if speed_limit_warning_offsetted_rounded < int(round(self._v_ego * self._ms_to_local)): - events_sp.add(EventNameSP.speedLimitPreActive) - - def _generate_auto_engage_events(self, events_sp: EventsSP, v_cruise_changed: bool) -> None: - # In auto mode, activate immediately when conditions are met - if not self._enabled: + def transition_state_from_inactive(self): + """ Make state transition from inactive state """ + if self._engage_type == Engage.user_confirm: + if (((self._last_op_enabled_time + 7.) >= self._current_time >= (self._last_op_enabled_time + 2.)) or + self._speed_limit_changed): + if self._speed_limit_changed: + self._last_op_enabled_time = self._current_time - 2. # immediately prompt confirmation + self.state = SpeedLimitControlState.preActive + elif self._engage_type == Engage.auto: if self._v_offset < LIMIT_SPEED_OFFSET_TH: - events_sp.add(EventNameSP.speedLimitAdapting) + self.state = SpeedLimitControlState.adapting else: - events_sp.add(EventNameSP.speedLimitActive) + self.state = SpeedLimitControlState.active - # User changed cruise speed - temporarily disable - if v_cruise_changed and self._current_time > (self._last_op_enabled_time + TEMP_INACTIVE_GUARD_PERIOD): - events_sp.add(EventNameSP.speedLimitUserCancel) + def transition_state_from_temp_inactive(self): + """ Make state transition from temporary inactive state """ + if self._speed_limit_changed: + if self._engage_type == Engage.user_confirm: + self._last_op_enabled_time = self._current_time - 2. # immediately prompt confirmation + self.state = SpeedLimitControlState.preActive + elif self._engage_type == Engage.auto: + self.state = SpeedLimitControlState.inactive - def _generate_user_confirm_events(self, events_sp: EventsSP, v_cruise_changed: bool, speed_limit_changed: bool, - v_cruise_rounded: float, v_cruise_prev_rounded: float, - speed_limit_offsetted_rounded: float) -> None: - # Check if we're in the confirmation window (2-7 seconds after op enabled) - in_confirm_window = (self._last_op_enabled_time + 7.) >= self._current_time >= (self._last_op_enabled_time + 2.) + def transition_state_from_pre_active(self): + """ Make state transition from preActive state """ + if self._current_time >= (self._last_op_enabled_time + 7.): + self.state = SpeedLimitControlState.inactive + elif (self._last_op_enabled_time + 7.) > self._current_time > (self._last_op_enabled_time + 2.): + if self._speed_limit_changed: + self._last_op_enabled_time = self._current_time - 2. # immediately prompt confirmation + elif self._v_cruise_prev_rounded < self._speed_limit_offsetted_rounded: + if self._v_cruise_setpoint > self._v_cruise_setpoint_prev: + self.state = SpeedLimitControlState.active + elif self._v_cruise_prev_rounded > self._speed_limit_offsetted_rounded: + if self._v_cruise_setpoint < self._v_cruise_setpoint_prev: + self.state = SpeedLimitControlState.active + elif self._v_cruise_prev_rounded == self._speed_limit_offsetted_rounded: + self.state = SpeedLimitControlState.active - if not self._enabled: - # Need user confirmation to enable - if in_confirm_window or speed_limit_changed: - if speed_limit_changed: - self._last_op_enabled_time = self._current_time - 2. # immediately prompt - events_sp.add(EventNameSP.speedLimitEnable) + def transition_state_from_adapting(self): + """ Make state transition from adapting state """ + if self._v_offset >= LIMIT_SPEED_OFFSET_TH: + self.state = SpeedLimitControlState.active - elif self.state == State.preActive: - # Check if user confirmed by adjusting cruise speed - if in_confirm_window: - if speed_limit_changed: - self._last_op_enabled_time = self._current_time - 2. - events_sp.add(EventNameSP.speedLimitEnable) - elif v_cruise_prev_rounded < speed_limit_offsetted_rounded: - if self._v_cruise_setpoint > self._v_cruise_setpoint_prev: - events_sp.add(EventNameSP.speedLimitUserConfirm) - elif v_cruise_prev_rounded > speed_limit_offsetted_rounded: - if self._v_cruise_setpoint < self._v_cruise_setpoint_prev: - events_sp.add(EventNameSP.speedLimitUserConfirm) - elif v_cruise_prev_rounded == speed_limit_offsetted_rounded: - events_sp.add(EventNameSP.speedLimitUserConfirm) - else: - # Timeout - cancel - events_sp.add(EventNameSP.speedLimitUserCancel) + def transition_state_from_active(self): + """ Make state transition from active state """ + if self._engage_type == Engage.user_confirm: + if self._state_prev == SpeedLimitControlState.active: + if self._v_cruise_setpoint_changed and self._v_cruise_rounded != self._speed_limit_offsetted_rounded: + self.state = SpeedLimitControlState.tempInactive + elif self._speed_limit_changed: + self._last_op_enabled_time = self._current_time - 2. # immediately prompt confirmation + self.state = SpeedLimitControlState.preActive + elif self._engage_type == Engage.auto: + if self._v_offset < LIMIT_SPEED_OFFSET_TH: + self.state = SpeedLimitControlState.adapting - elif self._active: - # User changed cruise speed while active - if v_cruise_changed and v_cruise_rounded != speed_limit_offsetted_rounded: - events_sp.add(EventNameSP.speedLimitUserCancel) - # Speed limit changed while active - elif speed_limit_changed: - self._last_op_enabled_time = self._current_time - 2. - events_sp.add(EventNameSP.speedLimitEnable) + def _state_transition(self): + self._state_prev = self._state - def update(self, enabled: bool, v_ego: float, a_ego: float, sm: messaging.SubMaster, v_cruise_setpoint: float, events_sp: EventsSP) -> None: + # In any case, if op is disabled, or speed limit control is disabled + # or the reported speed limit is 0 or gas is pressed, deactivate. + if not self._op_enabled or not self._is_enabled or self._speed_limit == 0 or \ + (self._gas_pressed and self._disengage_on_accelerator): + self.state = SpeedLimitControlState.inactive + return + + # In any case, we deactivate the speed limit controller temporarily if the user changes the cruise speed. + # Ignore if a minimum amount of time has not passed since activation. This is to prevent temp inactivations + # due to controlsd logic changing cruise setpoint when going active. + if self._engage_type == Engage.auto and self._v_cruise_setpoint_changed and \ + self._current_time > (self._last_op_enabled_time + TEMP_INACTIVE_GUARD_PERIOD): + self.state = SpeedLimitControlState.tempInactive + return + + self.state_transition_strategy[self.state]() + + if self._engage_type == Engage.user_confirm: + self._update_v_cruise_setpoint_prev() + + def get_current_acceleration_as_target(self): + """ When state is inactive or tempInactive, preserve current acceleration """ + return self._a_ego + + def get_adapting_state_target_acceleration(self): + """ In adapting state, calculate target acceleration based on speed limit and current velocity """ + if self.distance > 0: + return (self.speed_limit_offseted**2 - self._v_ego**2) / (2. * self.distance) + + return self._v_offset / ModelConstants.T_IDXS[CONTROL_N] + + def get_active_state_target_acceleration(self): + """ In active state, aim to keep speed constant around control time horizon """ + return self._v_offset / ModelConstants.T_IDXS[CONTROL_N] + + def _update_events(self, events): + if self._speed_limit > 0 and self._warning_type_type == 2 and \ + self._speed_limit_warning_offsetted_rounded < int(round(self._v_ego * self._ms_to_local)): + events.add(EventNameSP.speedLimitPreActive) + + if not self.is_active: + if self._state == SpeedLimitControlState.preActive and self._state_prev != SpeedLimitControlState.preActive and \ + self._v_cruise_rounded != self._speed_limit_offsetted_rounded: + events.add(EventNameSP.speedLimitPreActive) + else: + if self._engage_type == Engage.user_confirm: + if self._state_prev == SpeedLimitControlState.preActive: + events.add(EventNameSP.speedLimitConfirmed) + events.add(EventNameSP.speedLimitActive) + elif self._engage_type == Engage.auto: + if self._state_prev not in ACTIVE_STATES: + events.add(EventNameSP.speedLimitActive) + elif self._speed_limit_changed != 0: + events.add(EventNameSP.speedLimitValueChange) + + def update(self, enabled, v_ego, a_ego, sm, v_cruise_setpoint, events): _car_state = sm['carState'] - self._op_enabled = enabled and \ + self._op_enabled = enabled and sm['controlsState'].enabled and _car_state.cruiseState.enabled and \ not (_car_state.brakePressed and (not self._brake_pressed_prev or not _car_state.standstill)) and \ - not (_car_state.gasPressed and self._disengage_on_accelerator) + not (events.contains(ET.OVERRIDE_LONGITUDINAL) and self._disengage_on_accelerator) self._v_ego = v_ego self._a_ego = a_ego self._v_cruise_setpoint = v_cruise_setpoint @@ -238,14 +320,6 @@ class SpeedLimitController: self._speed_limit, self._distance, self._source = self._resolver.resolve(v_ego, self.speed_limit, sm) self._update_params() - self._generate_events(events_sp) - - self._enabled, self._active = self._state_machine.update(events_sp) - - self._v_cruise_setpoint_prev = self._v_cruise_setpoint - self._speed_limit_prev = self._speed_limit - self._op_enabled_prev = self._op_enabled - self._brake_pressed_prev = self._brake_pressed - - debug(f'Speed limit controller state: enabled: {self._enabled}, active: {self._active}, ' - f'speed limit: {self._speed_limit}, source: {self._source}, distance: {self._distance}') + self._update_calculations() + self._state_transition() + self._update_events(events) diff --git a/sunnypilot/selfdrive/selfdrived/events.py b/sunnypilot/selfdrive/selfdrived/events.py index 352b2389d8..0f1a777766 100644 --- a/sunnypilot/selfdrive/selfdrived/events.py +++ b/sunnypilot/selfdrive/selfdrived/events.py @@ -152,7 +152,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { "", "", AlertStatus.normal, AlertSize.none, - Priority.MID, VisualAlert.none, AudibleAlert.none, .45), + Priority.MID, VisualAlert.none, AudibleAlert.promptSingleLow, .45), }, EventNameSP.speedLimitActive: { @@ -163,36 +163,16 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { Priority.LOW, VisualAlert.none, AudibleAlert.none, 3.), }, + EventNameSP.speedLimitConfirmed: { + ET.WARNING: Alert( + "", + "", + AlertStatus.normal, AlertSize.none, + Priority.MID, VisualAlert.none, AudibleAlert.promptSingleHigh, .45), + }, + EventNameSP.speedLimitValueChange: { ET.WARNING: speed_limit_adjust_alert, }, - EventNameSP.speedLimitAdapting: { - ET.WARNING: EngagementAlert(AudibleAlert.none), - }, - - EventNameSP.speedLimitEnable: { - ET.ENABLE: EngagementAlert(AudibleAlert.none), - }, - - EventNameSP.speedLimitDisable: { - ET.USER_DISABLE: EngagementAlert(AudibleAlert.none), - }, - - EventNameSP.speedLimitUserConfirm: { - ET.WARNING: Alert( - "Speed Limit Confirmed", - "Set speed changed to match posted speed limit", - AlertStatus.normal, AlertSize.small, - Priority.LOW, VisualAlert.none, AudibleAlert.none, 2.), - }, - - EventNameSP.speedLimitUserCancel: { - ET.WARNING: EngagementAlert(AudibleAlert.none), - }, - - EventNameSP.speedLimitReached: { - ET.WARNING: EngagementAlert(AudibleAlert.none), - }, - }