mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-29 19:23:41 +08:00
use old controller for now
This commit is contained in:
+2
-7
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+206
-132
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user