diff --git a/selfdrive/monitoring/dmonitoringd.py b/selfdrive/monitoring/dmonitoringd.py index a82d318a9..a4846ebec 100644 --- a/selfdrive/monitoring/dmonitoringd.py +++ b/selfdrive/monitoring/dmonitoringd.py @@ -14,7 +14,13 @@ def dmonitoringd_thread(): params = Params() pm = messaging.PubMaster(['driverMonitoringState']) - sm = messaging.SubMaster(['driverStateV2', 'liveCalibration', 'carState', 'selfdriveState', 'modelV2'], poll='driverStateV2') + sm = messaging.SubMaster( + ['driverStateV2', 'liveCalibration', 'carState', 'selfdriveState', 'modelV2', 'starpilotCarState'], + poll='driverStateV2', + ignore_alive=['starpilotCarState'], + ignore_avg_freq=['starpilotCarState'], + ignore_valid=['starpilotCarState'], + ) DM = DriverMonitoring( rhd_saved=params.get_bool("IsRhdDetected"), diff --git a/selfdrive/monitoring/policy.py b/selfdrive/monitoring/policy.py index 877897c9a..ca8ffdc3d 100644 --- a/selfdrive/monitoring/policy.py +++ b/selfdrive/monitoring/policy.py @@ -17,6 +17,26 @@ MonitoringPolicy = log.DriverMonitoringState.MonitoringPolicy def to_percent(v): return int(min(max(v * 100., 0.), 100.)) + +def starpilot_aol_enabled(sm): + service = 'starpilotCarState' + if service not in getattr(sm, 'data', {}): + return False + + alive = getattr(sm, 'alive', None) + if alive is not None and not alive.get(service, False): + return False + + valid = getattr(sm, 'valid', None) + if valid is not None and not valid.get(service, False): + return False + + try: + return bool(sm[service].alwaysOnLateralEnabled) + except (AttributeError, KeyError): + return False + + # ****************************************************************************************** # NOTE: To fork maintainers. # Disabling or nerfing safety features will get you and your users banned from our servers. @@ -431,7 +451,7 @@ class DriverMonitoring: rpyCalib = [0., 0., 0.] else: car_speed = sm['carState'].vEgo - enabled = sm['selfdriveState'].enabled + enabled = sm['selfdriveState'].enabled or starpilot_aol_enabled(sm) wrong_gear = sm['carState'].gearShifter not in (car.CarState.GearShifter.drive, car.CarState.GearShifter.low) lowspeed = car_speed < self.settings._ALERT_MIN_SPEED driver_engaged = sm['carState'].steeringPressed or sm['carState'].gasPressed diff --git a/selfdrive/monitoring/test_monitoring.py b/selfdrive/monitoring/test_monitoring.py index 69319450d..fc557effc 100644 --- a/selfdrive/monitoring/test_monitoring.py +++ b/selfdrive/monitoring/test_monitoring.py @@ -1,6 +1,8 @@ +from types import SimpleNamespace + from cereal import log from openpilot.common.realtime import DT_DMON -from openpilot.selfdrive.monitoring.policy import DriverMonitoring, DRIVER_MONITOR_SETTINGS +from openpilot.selfdrive.monitoring.policy import DriverMonitoring, DRIVER_MONITOR_SETTINGS, starpilot_aol_enabled EventName = log.OnroadEvent.EventName dm_settings = DRIVER_MONITOR_SETTINGS() @@ -46,6 +48,17 @@ always_distracted = [msg_DISTRACTED] * int(TEST_TIMESPAN / DT_DMON) always_true = [True] * int(TEST_TIMESPAN / DT_DMON) always_false = [False] * int(TEST_TIMESPAN / DT_DMON) + +class FakeSubMaster: + def __init__(self, aol_enabled, alive=True, valid=True): + self.data = {'starpilotCarState': SimpleNamespace(alwaysOnLateralEnabled=aol_enabled)} + self.alive = {'starpilotCarState': alive} + self.valid = {'starpilotCarState': valid} + + def __getitem__(self, service): + return self.data[service] + + class TestMonitoring: def _run_seq(self, msgs, interaction, engaged, lowspeed): DM = DriverMonitoring() @@ -71,6 +84,13 @@ class TestMonitoring: assert not DM.wheel_on_right + def test_starpilot_aol_counts_as_dm_engaged(self): + assert starpilot_aol_enabled(FakeSubMaster(True)) + assert not starpilot_aol_enabled(FakeSubMaster(False)) + assert not starpilot_aol_enabled(FakeSubMaster(True, alive=False)) + assert not starpilot_aol_enabled(FakeSubMaster(True, valid=False)) + + # engaged, driver is attentive all the time def test_fully_aware_driver(self): alert_lvls, d_status = self._run_seq(always_attentive, always_false, always_true, always_false) diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 234365355..37efb181d 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -36,6 +36,16 @@ AudibleAlert = log.SelfdriveState.AudibleAlert StarPilotAudibleAlert = custom.StarPilotCarControl.HUDControl.AudibleAlert +# StarPilot mirrors stock audible alerts at 0-8. Keep those raw values so themed +# stock sounds still work, and only offset custom random-event sounds. +STARPILOT_CUSTOM_ALERT_OFFSET = 1000 +STARPILOT_CUSTOM_ALERT_START = int(StarPilotAudibleAlert.angry) + + +def starpilot_alert_key(alert): + raw_alert = int(alert) + return STARPILOT_CUSTOM_ALERT_OFFSET + raw_alert if raw_alert >= STARPILOT_CUSTOM_ALERT_START else raw_alert + sound_list: dict[int, tuple[str, int | None, float]] = { # AudibleAlert, file name, play count (none for infinite) @@ -52,20 +62,20 @@ sound_list: dict[int, tuple[str, int | None, float]] = { AudibleAlert.warningSoft: ("warning_soft.wav", None, MAX_VOLUME), AudibleAlert.warningImmediate: ("warning_immediate.wav", None, MAX_VOLUME), - StarPilotAudibleAlert.angry: ("angry.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.continued: ("continued.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.dejaVu: ("dejaVu.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.doc: ("doc.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.fart: ("fart.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.firefox: ("firefox.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.goat: ("goat.wav", None, MAX_VOLUME), - StarPilotAudibleAlert.hal9000: ("hal9000.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.mail: ("mail.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.nessie: ("nessie.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.noice: ("noice.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.startup: ("startup.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.thisIsFine: ("this_is_fine.wav", 1, MAX_VOLUME), - StarPilotAudibleAlert.uwu: ("uwu.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.angry): ("angry.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.continued): ("continued.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.dejaVu): ("dejaVu.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.doc): ("doc.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.fart): ("fart.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.firefox): ("firefox.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.goat): ("goat.wav", None, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.hal9000): ("hal9000.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.mail): ("mail.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.nessie): ("nessie.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.noice): ("noice.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.startup): ("startup.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.thisIsFine): ("this_is_fine.wav", 1, MAX_VOLUME), + starpilot_alert_key(StarPilotAudibleAlert.uwu): ("uwu.wav", 1, MAX_VOLUME), } if HARDWARE.get_device_type() in ("tici", "tizi"): sound_list.update({ @@ -216,11 +226,11 @@ class Soundd: critical_full_alert = sm['selfdriveState'].alertStatus == log.SelfdriveState.AlertStatus.critical critical_full_alert &= sm['selfdriveState'].alertSize == log.SelfdriveState.AlertSize.full if self.starpilot_toggles.goat_scream_critical_alerts and critical_full_alert: - new_alert = StarPilotAudibleAlert.goat + new_alert = starpilot_alert_key(StarPilotAudibleAlert.goat) new_starpilot_alert = sm['starpilotSelfdriveState'].alertSound.raw if new_alert == AudibleAlert.none and new_starpilot_alert != StarPilotAudibleAlert.none: - new_alert = new_starpilot_alert + new_alert = starpilot_alert_key(new_starpilot_alert) new_alert_type = sm['starpilotSelfdriveState'].alertType self.current_alert_type = new_alert_type @@ -337,8 +347,8 @@ class Soundd: AudibleAlert.warningSoft: self.starpilot_toggles.warningSoft_volume / 100.0, AudibleAlert.warningImmediate: self.starpilot_toggles.warningImmediate_volume / 100.0, - StarPilotAudibleAlert.goat: self.starpilot_toggles.prompt_volume / 100.0, - StarPilotAudibleAlert.startup: self.starpilot_toggles.engage_volume / 100.0 + starpilot_alert_key(StarPilotAudibleAlert.goat): self.starpilot_toggles.prompt_volume / 100.0, + starpilot_alert_key(StarPilotAudibleAlert.startup): self.starpilot_toggles.engage_volume / 100.0 } for sound in sound_list: