* new engage/disengage + amp config

* first family

* cleanup audible alerts

* tici isn't special

* fix up debug cycle alerts

* these were better

* extend range

* use distracted sound

* log scaling

* getting closer

* slightly louder

* prompt

* update tests

* update refs

* fix c2 test

* resolve todo

* adjust tolerance

* revert for now

* should work

Co-authored-by: Comma Device <device@comma.ai>
old-commit-hash: e679d05d9e
commatwo_master
Adeeb Shihadeh 4 years ago committed by GitHub
parent 2a57577b9d
commit dccb8b4010
  1. 2
      cereal
  2. 1
      release/files_tici
  3. 3
      selfdrive/assets/sounds/disengage.wav
  4. 3
      selfdrive/assets/sounds/disengaged.wav
  5. 3
      selfdrive/assets/sounds/engage.wav
  6. 3
      selfdrive/assets/sounds/engaged.wav
  7. 3
      selfdrive/assets/sounds/error.wav
  8. 3
      selfdrive/assets/sounds/prompt.wav
  9. 3
      selfdrive/assets/sounds/refuse.wav
  10. 3
      selfdrive/assets/sounds/warning_1.wav
  11. 3
      selfdrive/assets/sounds/warning_2.wav
  12. 3
      selfdrive/assets/sounds/warning_immediate.wav
  13. 3
      selfdrive/assets/sounds/warning_repeat.wav
  14. 3
      selfdrive/assets/sounds/warning_soft.wav
  15. 3
      selfdrive/assets/sounds_tici/disengaged.wav
  16. 3
      selfdrive/assets/sounds_tici/engaged.wav
  17. 3
      selfdrive/assets/sounds_tici/error.wav
  18. 3
      selfdrive/assets/sounds_tici/warning_1.wav
  19. 3
      selfdrive/assets/sounds_tici/warning_2.wav
  20. 3
      selfdrive/assets/sounds_tici/warning_repeat.wav
  21. 21
      selfdrive/controls/lib/alertmanager.py
  22. 65
      selfdrive/controls/lib/events.py
  23. 47
      selfdrive/debug/cycle_alerts.py
  24. 15
      selfdrive/hardware/tici/amplifier.py
  25. 4
      selfdrive/hardware/tici/hardware.h
  26. 2
      selfdrive/test/process_replay/ref_commit
  27. 14
      selfdrive/ui/soundd/sound.cc
  28. 17
      selfdrive/ui/soundd/sound.h
  29. 19
      selfdrive/ui/tests/test_soundd.py
  30. 2
      selfdrive/ui/ui.h

@ -1 +1 @@
Subproject commit d6f233bf7bd6d1ee3508b17667e44420ce38de0d Subproject commit 9ce45916c6c27e8cfbbe2aa6b796fac41eeeba00

@ -4,7 +4,6 @@ selfdrive/timezoned.py
selfdrive/assets/navigation/* selfdrive/assets/navigation/*
selfdrive/assets/training_wide/* selfdrive/assets/training_wide/*
selfdrive/assets/sounds_tici/*
selfdrive/camerad/cameras/camera_qcom2.cc selfdrive/camerad/cameras/camera_qcom2.cc
selfdrive/camerad/cameras/camera_qcom2.h selfdrive/camerad/cameras/camera_qcom2.h

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4b1294c17f2c19a390d1d5f09c0ef887496e46b5494fe7e94289c5b536e1e014
size 155804

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5db18c6fb1e975d6d2bdb62372214a981e179d9af790a0e579e7d7a4c32bbb75
size 40662

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ad87ff4f54b3b058a00d6dd2142b881c583be5124940cd90ec91a6c714ec4567
size 92172

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:165a121885f67004ffbeb34d6ad265c6e54dc5456674379434ff6f66ca6f688a
size 40654

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bfe1b73efabfcbd36dae63d39d0c1e2d4c1ead63daac0430a648e4686307e06c
size 40650

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3007836472db496398397eb409778b2e0018cce66033afc791b108e5202ad371
size 127172

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:079121f2e0272117afc21074d79602c9939a1a4f0c19ca0ed82547d7d9537c22
size 209238

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:80b08552196740078647d35ef20781018a8fe97e75a1ff99e297f40fc3721b72
size 21468

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:29ea3f93348689ce82b2bb0815cc9c99bdf91aabd3be36076bbb601e3572e30e
size 124708

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b5e3b2d20d604902eb19fb773bce89fa6fdc9a7e0610ec6ac729fd1512455f98
size 133412

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3c776220f534ba5776a6bd831050ba767b5439badc74b67666fe70e44cd62692
size 62760

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cc0b574afbee712a971b7347dc01eadaf824b14b7365ae6b3e0639de8917a1cd
size 76108

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c6ef7f760160e1c5d9ec7a9b2cd46a79866acfdd3dbba6a8fd49051490b37aa7
size 50316

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5429a1633695013bcd69a6d8e529e4ac95a9e0e4c50e8ae0027b06003ed662e2
size 50288

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1c31dab68d1498b84912c6e424fd783d054942242ca40a5dfb311edd148b744a
size 50304

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:209c3328f1eb924917f78438c2faf43d9c23ae7f39b7ba6105b7ca509e279e15
size 31094

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8687abcc94d4bb30dd18be37ed03e2a224cc6ddc227c1e8c0c3ba9bdfc85b302
size 134392

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:92a69b8847a51b7d60af4447f930b50e343f7f04316a765d0a13ae4d0152160f
size 70114

@ -41,6 +41,7 @@ class AlertManager:
self.activealerts: Dict[str, AlertEntry] = defaultdict(AlertEntry) self.activealerts: Dict[str, AlertEntry] = defaultdict(AlertEntry)
def reset(self) -> None: def reset(self) -> None:
self.alert: Optional[Alert] = None
self.alert_type: str = "" self.alert_type: str = ""
self.alert_text_1: str = "" self.alert_text_1: str = ""
self.alert_text_2: str = "" self.alert_text_2: str = ""
@ -74,13 +75,13 @@ class AlertManager:
# clear current alert # clear current alert
self.reset() self.reset()
a = current_alert.alert self.alert = current_alert.alert
if a is not None: if self.alert is not None:
self.alert_type = a.alert_type self.alert_type = self.alert.alert_type
self.audible_alert = a.audible_alert self.audible_alert = self.alert.audible_alert
self.visual_alert = a.visual_alert self.visual_alert = self.alert.visual_alert
self.alert_text_1 = a.alert_text_1 self.alert_text_1 = self.alert.alert_text_1
self.alert_text_2 = a.alert_text_2 self.alert_text_2 = self.alert.alert_text_2
self.alert_status = a.alert_status self.alert_status = self.alert.alert_status
self.alert_size = a.alert_size self.alert_size = self.alert.alert_size
self.alert_rate = a.alert_rate self.alert_rate = self.alert.alert_rate

@ -139,11 +139,10 @@ class Alert:
class NoEntryAlert(Alert): class NoEntryAlert(Alert):
def __init__(self, alert_text_2, audible_alert=AudibleAlert.chimeError, def __init__(self, alert_text_2, visual_alert=VisualAlert.none):
visual_alert=VisualAlert.none):
super().__init__("openpilot Unavailable", alert_text_2, AlertStatus.normal, super().__init__("openpilot Unavailable", alert_text_2, AlertStatus.normal,
AlertSize.mid, Priority.LOW, visual_alert, AlertSize.mid, Priority.LOW, visual_alert,
audible_alert, 3.) AudibleAlert.refuse, 3.)
class SoftDisableAlert(Alert): class SoftDisableAlert(Alert):
@ -151,7 +150,7 @@ class SoftDisableAlert(Alert):
super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2, super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2,
AlertStatus.userPrompt, AlertSize.full, AlertStatus.userPrompt, AlertSize.full,
Priority.MID, VisualAlert.steerRequired, Priority.MID, VisualAlert.steerRequired,
AudibleAlert.chimeWarningRepeatInfinite, 2.), AudibleAlert.warningSoft, 2.),
class ImmediateDisableAlert(Alert): class ImmediateDisableAlert(Alert):
@ -159,7 +158,7 @@ class ImmediateDisableAlert(Alert):
super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2, super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2,
AlertStatus.critical, AlertSize.full, AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.steerRequired, Priority.HIGHEST, VisualAlert.steerRequired,
AudibleAlert.chimeWarningRepeatInfinite, 4.), AudibleAlert.warningImmediate, 4.),
class EngagementAlert(Alert): class EngagementAlert(Alert):
@ -201,7 +200,7 @@ def below_steer_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric:
f"Steer Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}", f"Steer Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}",
"", "",
AlertStatus.userPrompt, AlertSize.small, AlertStatus.userPrompt, AlertSize.small,
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 0.4) Priority.MID, VisualAlert.steerRequired, AudibleAlert.prompt, 0.4)
def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert: def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
@ -321,7 +320,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"BRAKE!", "BRAKE!",
"Risk of Collision", "Risk of Collision",
AlertStatus.critical, AlertSize.full, AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.chimeWarningRepeatInfinite, 2.), Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.),
}, },
EventName.ldw: { EventName.ldw: {
@ -329,7 +328,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"TAKE CONTROL", "TAKE CONTROL",
"Lane Departure Detected", "Lane Departure Detected",
AlertStatus.userPrompt, AlertSize.mid, AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.ldw, AudibleAlert.chimePrompt, 3.), Priority.LOW, VisualAlert.ldw, AudibleAlert.prompt, 3.),
}, },
# ********** events only containing alerts that display while engaged ********** # ********** events only containing alerts that display while engaged **********
@ -360,7 +359,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"Steering Temporarily Unavailable", "Steering Temporarily Unavailable",
"", "",
AlertStatus.userPrompt, AlertSize.small, AlertStatus.userPrompt, AlertSize.small,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1.), Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 1.),
}, },
EventName.preDriverDistracted: { EventName.preDriverDistracted: {
@ -376,7 +375,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"KEEP EYES ON ROAD", "KEEP EYES ON ROAD",
"Driver Distracted", "Driver Distracted",
AlertStatus.userPrompt, AlertSize.mid, AlertStatus.userPrompt, AlertSize.mid,
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, .1), Priority.MID, VisualAlert.steerRequired, AudibleAlert.prompt, .1),
}, },
EventName.driverDistracted: { EventName.driverDistracted: {
@ -384,7 +383,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"DISENGAGE IMMEDIATELY", "DISENGAGE IMMEDIATELY",
"Driver Distracted", "Driver Distracted",
AlertStatus.critical, AlertSize.full, AlertStatus.critical, AlertSize.full,
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeatInfinite, .1), Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1),
}, },
EventName.preDriverUnresponsive: { EventName.preDriverUnresponsive: {
@ -400,7 +399,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"TOUCH STEERING WHEEL", "TOUCH STEERING WHEEL",
"Driver Unresponsive", "Driver Unresponsive",
AlertStatus.userPrompt, AlertSize.mid, AlertStatus.userPrompt, AlertSize.mid,
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, .1), Priority.MID, VisualAlert.steerRequired, AudibleAlert.prompt, .1),
}, },
EventName.driverUnresponsive: { EventName.driverUnresponsive: {
@ -408,7 +407,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"DISENGAGE IMMEDIATELY", "DISENGAGE IMMEDIATELY",
"Driver Unresponsive", "Driver Unresponsive",
AlertStatus.critical, AlertSize.full, AlertStatus.critical, AlertSize.full,
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeatInfinite, .1), Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1),
}, },
EventName.manualRestart: { EventName.manualRestart: {
@ -452,7 +451,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"Car Detected in Blindspot", "Car Detected in Blindspot",
"", "",
AlertStatus.userPrompt, AlertSize.small, AlertStatus.userPrompt, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.chimePrompt, .1), Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1),
}, },
EventName.laneChange: { EventName.laneChange: {
@ -468,7 +467,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"TAKE CONTROL", "TAKE CONTROL",
"Turn Exceeds Steering Limit", "Turn Exceeds Steering Limit",
AlertStatus.userPrompt, AlertSize.mid, AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, 1.), Priority.LOW, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 1.),
}, },
# Thrown when the fan is driven at >50% but is not rotating # Thrown when the fan is driven at >50% but is not rotating
@ -496,44 +495,44 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# ********** events that affect controls state transitions ********** # ********** events that affect controls state transitions **********
EventName.pcmEnable: { EventName.pcmEnable: {
ET.ENABLE: EngagementAlert(AudibleAlert.chimeEngage), ET.ENABLE: EngagementAlert(AudibleAlert.engage),
}, },
EventName.buttonEnable: { EventName.buttonEnable: {
ET.ENABLE: EngagementAlert(AudibleAlert.chimeEngage), ET.ENABLE: EngagementAlert(AudibleAlert.engage),
}, },
EventName.pcmDisable: { EventName.pcmDisable: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
}, },
EventName.buttonCancel: { EventName.buttonCancel: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
}, },
EventName.brakeHold: { EventName.brakeHold: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("Brake Hold Active"), ET.NO_ENTRY: NoEntryAlert("Brake Hold Active"),
}, },
EventName.parkBrake: { EventName.parkBrake: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("Park Brake Engaged"), ET.NO_ENTRY: NoEntryAlert("Park Brake Engaged"),
}, },
EventName.pedalPressed: { EventName.pedalPressed: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("Pedal Pressed During Attempt", ET.NO_ENTRY: NoEntryAlert("Pedal Pressed During Attempt",
visual_alert=VisualAlert.brakePressed), visual_alert=VisualAlert.brakePressed),
}, },
EventName.wrongCarMode: { EventName.wrongCarMode: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: wrong_car_mode_alert, ET.NO_ENTRY: wrong_car_mode_alert,
}, },
EventName.wrongCruiseMode: { EventName.wrongCruiseMode: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("Enable Adaptive Cruise"), ET.NO_ENTRY: NoEntryAlert("Enable Adaptive Cruise"),
}, },
@ -627,14 +626,12 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# ten times the regular interval, or the average interval is more than 10% too high. # ten times the regular interval, or the average interval is more than 10% too high.
EventName.commIssue: { EventName.commIssue: {
ET.SOFT_DISABLE: SoftDisableAlert("Communication Issue between Processes"), ET.SOFT_DISABLE: SoftDisableAlert("Communication Issue between Processes"),
ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes", ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes"),
audible_alert=AudibleAlert.chimeDisengage),
}, },
# Thrown when manager detects a service exited unexpectedly while driving # Thrown when manager detects a service exited unexpectedly while driving
EventName.processNotRunning: { EventName.processNotRunning: {
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device", ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device"),
audible_alert=AudibleAlert.chimeDisengage),
}, },
EventName.radarFault: { EventName.radarFault: {
@ -670,15 +667,13 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
EventName.lowMemory: { EventName.lowMemory: {
ET.SOFT_DISABLE: SoftDisableAlert("Low Memory: Reboot Your Device"), ET.SOFT_DISABLE: SoftDisableAlert("Low Memory: Reboot Your Device"),
ET.PERMANENT: NormalPermanentAlert("Low Memory", "Reboot your Device"), ET.PERMANENT: NormalPermanentAlert("Low Memory", "Reboot your Device"),
ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device", ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"),
audible_alert=AudibleAlert.chimeDisengage),
}, },
EventName.highCpuUsage: { EventName.highCpuUsage: {
#ET.SOFT_DISABLE: SoftDisableAlert("System Malfunction: Reboot Your Device"), #ET.SOFT_DISABLE: SoftDisableAlert("System Malfunction: Reboot Your Device"),
#ET.PERMANENT: NormalPermanentAlert("System Malfunction", "Reboot your Device"), #ET.PERMANENT: NormalPermanentAlert("System Malfunction", "Reboot your Device"),
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device", ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device"),
audible_alert=AudibleAlert.chimeDisengage),
}, },
EventName.accFaulted: { EventName.accFaulted: {
@ -782,7 +777,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"openpilot Canceled", "openpilot Canceled",
"No close lead car", "No close lead car",
AlertStatus.normal, AlertSize.mid, AlertStatus.normal, AlertSize.mid,
Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, 3.), Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.),
ET.NO_ENTRY: NoEntryAlert("No Close Lead Car"), ET.NO_ENTRY: NoEntryAlert("No Close Lead Car"),
}, },
@ -791,7 +786,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"openpilot Canceled", "openpilot Canceled",
"Speed too low", "Speed too low",
AlertStatus.normal, AlertSize.mid, AlertStatus.normal, AlertSize.mid,
Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, 3.), Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.),
}, },
# When the car is driving faster than most cars in the training data the model outputs can be unpredictable # When the car is driving faster than most cars in the training data the model outputs can be unpredictable
@ -800,7 +795,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
"Speed Too High", "Speed Too High",
"Model uncertain at this speed", "Model uncertain at this speed",
AlertStatus.userPrompt, AlertSize.mid, AlertStatus.userPrompt, AlertSize.mid,
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, 4.), Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 4.),
ET.NO_ENTRY: NoEntryAlert("Slow down to engage"), ET.NO_ENTRY: NoEntryAlert("Slow down to engage"),
}, },

@ -7,18 +7,31 @@ import time
from cereal import car, log from cereal import car, log
import cereal.messaging as messaging import cereal.messaging as messaging
from common.realtime import DT_CTRL
from selfdrive.car.honda.interface import CarInterface from selfdrive.car.honda.interface import CarInterface
from selfdrive.controls.lib.events import ET, EVENTS, Events from selfdrive.controls.lib.events import ET, EVENTS, Events
from selfdrive.controls.lib.alertmanager import AlertManager from selfdrive.controls.lib.alertmanager import AlertManager
EventName = car.CarEvent.EventName EventName = car.CarEvent.EventName
def cycle_alerts(duration=2000, is_metric=False): def cycle_alerts(duration=200, is_metric=False):
alerts = list(EVENTS.keys()) # all alerts
print(alerts) #alerts = list(EVENTS.keys())
alerts = [EventName.preDriverDistracted, EventName.promptDriverDistracted, EventName.driverDistracted] # this plays each type of audible alert
#alerts = [EventName.preLaneChangeLeft, EventName.preLaneChangeRight] alerts = [
(EventName.buttonEnable, ET.ENABLE),
(EventName.buttonCancel, ET.USER_DISABLE),
(EventName.wrongGear, ET.NO_ENTRY),
(EventName.vehicleModelInvalid, ET.SOFT_DISABLE),
(EventName.accFaulted, ET.IMMEDIATE_DISABLE),
# DM sequence
(EventName.preDriverDistracted, ET.WARNING),
(EventName.promptDriverDistracted, ET.WARNING),
(EventName.driverDistracted, ET.WARNING),
]
CP = CarInterface.get_params("HONDA CIVIC 2016") CP = CarInterface.get_params("HONDA CIVIC 2016")
sm = messaging.SubMaster(['deviceState', 'pandaStates', 'roadCameraState', 'modelV2', 'liveCalibration', sm = messaging.SubMaster(['deviceState', 'pandaStates', 'roadCameraState', 'modelV2', 'liveCalibration',
@ -30,23 +43,24 @@ def cycle_alerts(duration=2000, is_metric=False):
AM = AlertManager() AM = AlertManager()
frame = 0 frame = 0
idx, last_alert_millis = 0, 0 while True:
while 1:
if frame % duration == 0:
idx = (idx + 1) % len(alerts)
events.clear()
events.add(alerts[idx])
current_alert_types = [ET.PERMANENT, ET.USER_DISABLE, ET.IMMEDIATE_DISABLE, current_alert_types = [ET.PERMANENT, ET.USER_DISABLE, ET.IMMEDIATE_DISABLE,
ET.SOFT_DISABLE, ET.PRE_ENABLE, ET.NO_ENTRY, ET.SOFT_DISABLE, ET.PRE_ENABLE, ET.NO_ENTRY,
ET.ENABLE, ET.WARNING] ET.ENABLE, ET.WARNING]
a = events.create_alerts(current_alert_types, [CP, sm, is_metric])
for alert, et in alerts:
events.clear()
events.add(alert)
a = events.create_alerts([et, ], [CP, sm, is_metric])
AM.add_many(frame, a) AM.add_many(frame, a)
AM.process_alerts(frame) AM.process_alerts(frame)
print(AM.alert)
for _ in range(duration):
dat = messaging.new_message() dat = messaging.new_message()
dat.init('controlsState') dat.init('controlsState')
dat.controlsState.enabled = True
dat.controlsState.alertText1 = AM.alert_text_1 dat.controlsState.alertText1 = AM.alert_text_1
dat.controlsState.alertText2 = AM.alert_text_2 dat.controlsState.alertText2 = AM.alert_text_2
dat.controlsState.alertSize = AM.alert_size dat.controlsState.alertSize = AM.alert_size
@ -66,7 +80,8 @@ def cycle_alerts(duration=2000, is_metric=False):
dat.pandaStates[0].pandaType = log.PandaState.PandaType.uno dat.pandaStates[0].pandaType = log.PandaState.PandaType.uno
pm.send('pandaStates', dat) pm.send('pandaStates', dat)
time.sleep(0.01) frame += 1
time.sleep(DT_CTRL)
if __name__ == '__main__': if __name__ == '__main__':
cycle_alerts() cycle_alerts()

@ -31,17 +31,18 @@ BASE_CONFIG = [
AmpConfig("Enable PLL2", 0b1, 0x1A, 7, 0b10000000), AmpConfig("Enable PLL2", 0b1, 0x1A, 7, 0b10000000),
AmpConfig("DAI1: I2S mode", 0b00100, 0x14, 2, 0b01111100), AmpConfig("DAI1: I2S mode", 0b00100, 0x14, 2, 0b01111100),
AmpConfig("DAI2: I2S mode", 0b00100, 0x1C, 2, 0b01111100), AmpConfig("DAI2: I2S mode", 0b00100, 0x1C, 2, 0b01111100),
AmpConfig("Right speaker output volume", 0x1a, 0x3E, 0, 0b00011111), AmpConfig("Right speaker output volume", 0x1c, 0x3E, 0, 0b00011111),
AmpConfig("DAI1 Passband filtering: music mode", 0b1, 0x18, 7, 0b10000000), AmpConfig("DAI1 Passband filtering: music mode", 0b1, 0x18, 7, 0b10000000),
AmpConfig("DAI1 voice mode gain (DV1G)", 0b00, 0x2F, 4, 0b00110000), AmpConfig("DAI1 voice mode gain (DV1G)", 0b00, 0x2F, 4, 0b00110000),
AmpConfig("DAI1 attenuation (DV1)", 0x0, 0x2F, 0, 0b00001111), AmpConfig("DAI1 attenuation (DV1)", 0x0, 0x2F, 0, 0b00001111),
AmpConfig("DAI2 attenuation (DV2)", 0x0, 0x31, 0, 0b00001111), AmpConfig("DAI2 attenuation (DV2)", 0x0, 0x31, 0, 0b00001111),
AmpConfig("DAI2: DC blocking", 0b1, 0x20, 0, 0b00000001), AmpConfig("DAI2: DC blocking", 0b1, 0x20, 0, 0b00000001),
AmpConfig("DAI2: High sample rate", 0b0, 0x20, 3, 0b00001000), AmpConfig("DAI2: High sample rate", 0b0, 0x20, 3, 0b00001000),
AmpConfig("ALC enable", 0b0, 0x43, 7, 0b10000000), AmpConfig("ALC enable", 0b1, 0x43, 7, 0b10000000),
AmpConfig("ALC/excursion limiter release time", 0b101, 0x43, 4, 0b01110000), AmpConfig("ALC/excursion limiter release time", 0b101, 0x43, 4, 0b01110000),
AmpConfig("ALC multiband enable", 0b1, 0x43, 3, 0b00001000),
AmpConfig("DAI1 EQ enable", 0b0, 0x49, 0, 0b00000001), AmpConfig("DAI1 EQ enable", 0b0, 0x49, 0, 0b00000001),
AmpConfig("DAI2 EQ enable", 0b0, 0x49, 1, 0b00000010), AmpConfig("DAI2 EQ enable", 0b1, 0x49, 1, 0b00000010),
AmpConfig("DAI2 EQ clip detection disabled", 0b1, 0x32, 4, 0b00010000), AmpConfig("DAI2 EQ clip detection disabled", 0b1, 0x32, 4, 0b00010000),
AmpConfig("DAI2 EQ attenuation", 0x5, 0x32, 0, 0b00001111), AmpConfig("DAI2 EQ attenuation", 0x5, 0x32, 0, 0b00001111),
AmpConfig("Excursion limiter upper corner freq", 0b100, 0x41, 4, 0b01110000), AmpConfig("Excursion limiter upper corner freq", 0b100, 0x41, 4, 0b01110000),
@ -62,11 +63,11 @@ BASE_CONFIG = [
AmpConfig("Zero-crossing detection disabled", 0b0, 0x49, 5, 0b00100000), AmpConfig("Zero-crossing detection disabled", 0b0, 0x49, 5, 0b00100000),
] ]
BASE_CONFIG += configs_from_eq_params(0x84, EQParams(0x65C4, 0xC07C, 0x3D66, 0x07D9, 0x120F)) BASE_CONFIG += configs_from_eq_params(0x84, EQParams(0x274F, 0xC0FF, 0x3BF9, 0x0B3C, 0x1656))
BASE_CONFIG += configs_from_eq_params(0x8E, EQParams(0x1009, 0xC6BF, 0x2952, 0x1C97, 0x30DF)) BASE_CONFIG += configs_from_eq_params(0x8E, EQParams(0x1009, 0xC6BF, 0x2952, 0x1C97, 0x30DF))
BASE_CONFIG += configs_from_eq_params(0x98, EQParams(0x2822, 0xC1C7, 0x3B50, 0x0EF8, 0x180A)) BASE_CONFIG += configs_from_eq_params(0x98, EQParams(0x0F75, 0xCBE5, 0x0ED2, 0x2528, 0x3E42))
BASE_CONFIG += configs_from_eq_params(0xA2, EQParams(0x1009, 0xC5C2, 0x271F, 0x1A87, 0x32A6)) BASE_CONFIG += configs_from_eq_params(0xA2, EQParams(0x091F, 0x3D4C, 0xCE11, 0x1266, 0x2807))
BASE_CONFIG += configs_from_eq_params(0xAC, EQParams(0x2000, 0xCA1E, 0x4000, 0x2287, 0x0000)) BASE_CONFIG += configs_from_eq_params(0xAC, EQParams(0x0A9E, 0x3F20, 0xE573, 0x0A8B, 0x3A3B))
class Amplifier: class Amplifier:
AMP_I2C_BUS = 0 AMP_I2C_BUS = 0

@ -9,8 +9,8 @@
class HardwareTici : public HardwareNone { class HardwareTici : public HardwareNone {
public: public:
static constexpr float MAX_VOLUME = 1.0; static constexpr float MAX_VOLUME = 0.9;
static constexpr float MIN_VOLUME = 0.4; static constexpr float MIN_VOLUME = 0.3;
static bool TICI() { return true; } static bool TICI() { return true; }
static std::string get_os_version() { static std::string get_os_version() {
return "AGNOS " + util::read_file("/VERSION"); return "AGNOS " + util::read_file("/VERSION");

@ -1 +1 @@
e0926a8b9f7cffc35808109a710648a7f57c0b71 9cbef406393a83b35a8f25aa75099da8f8d68276

@ -1,5 +1,9 @@
#include "selfdrive/ui/soundd/sound.h" #include "selfdrive/ui/soundd/sound.h"
#include <QAudio>
#include <QAudioDeviceInfo>
#include <QDebug>
#include "cereal/messaging/messaging.h" #include "cereal/messaging/messaging.h"
#include "selfdrive/common/util.h" #include "selfdrive/common/util.h"
@ -7,14 +11,15 @@
// TODO: detect when we can't display the UI // TODO: detect when we can't display the UI
Sound::Sound(QObject *parent) : sm({"carState", "controlsState", "deviceState"}) { Sound::Sound(QObject *parent) : sm({"carState", "controlsState", "deviceState"}) {
const QString sound_asset_path = Hardware::TICI() ? "../../assets/sounds_tici/" : "../../assets/sounds/"; qInfo() << "default audio device: " << QAudioDeviceInfo::defaultOutputDevice().deviceName();
for (auto &[alert, fn, loops] : sound_list) { for (auto &[alert, fn, loops] : sound_list) {
QSoundEffect *s = new QSoundEffect(this); QSoundEffect *s = new QSoundEffect(this);
QObject::connect(s, &QSoundEffect::statusChanged, [=]() { QObject::connect(s, &QSoundEffect::statusChanged, [=]() {
assert(s->status() != QSoundEffect::Error); assert(s->status() != QSoundEffect::Error);
}); });
s->setVolume(Hardware::MIN_VOLUME); s->setVolume(Hardware::MIN_VOLUME);
s->setSource(QUrl::fromLocalFile(sound_asset_path + fn)); s->setSource(QUrl::fromLocalFile("../../assets/sounds/" + fn));
sounds[alert] = {s, loops}; sounds[alert] = {s, loops};
} }
@ -42,8 +47,9 @@ void Sound::update() {
// scale volume with speed // scale volume with speed
if (sm.updated("carState")) { if (sm.updated("carState")) {
float volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f, float volume = std::clamp(sm["carState"].getCarState().getVEgo() / 29.f, 0.1f, 1.0f);
Hardware::MIN_VOLUME, Hardware::MAX_VOLUME); volume = QAudio::convertVolume(volume, QAudio::LogarithmicVolumeScale, QAudio::LinearVolumeScale);
volume = util::map_val(volume, 0.f, 1.f, Hardware::MIN_VOLUME, Hardware::MAX_VOLUME);
for (auto &[s, loops] : sounds) { for (auto &[s, loops] : sounds) {
s->setVolume(std::round(100 * volume) / 100); s->setVolume(std::round(100 * volume) / 100);
} }

@ -7,14 +7,15 @@
const std::tuple<AudibleAlert, QString, int> sound_list[] = { const std::tuple<AudibleAlert, QString, int> sound_list[] = {
// AudibleAlert, file name, loop count // AudibleAlert, file name, loop count
{AudibleAlert::CHIME_DISENGAGE, "disengaged.wav", 0}, {AudibleAlert::ENGAGE, "engage.wav", 0},
{AudibleAlert::CHIME_ENGAGE, "engaged.wav", 0}, {AudibleAlert::DISENGAGE, "disengage.wav", 0},
{AudibleAlert::CHIME_WARNING1, "warning_1.wav", 0}, {AudibleAlert::REFUSE, "refuse.wav", 0},
{AudibleAlert::CHIME_WARNING_REPEAT, "warning_repeat.wav", 10},
{AudibleAlert::CHIME_WARNING_REPEAT_INFINITE, "warning_repeat.wav", QSoundEffect::Infinite}, {AudibleAlert::PROMPT, "prompt.wav", 0},
{AudibleAlert::CHIME_WARNING2_REPEAT_INFINITE, "warning_2.wav", QSoundEffect::Infinite}, {AudibleAlert::PROMPT_REPEAT, "prompt.wav", QSoundEffect::Infinite},
{AudibleAlert::CHIME_ERROR, "error.wav", 0},
{AudibleAlert::CHIME_PROMPT, "error.wav", 0}, {AudibleAlert::WARNING_SOFT, "warning_soft.wav", QSoundEffect::Infinite},
{AudibleAlert::WARNING_IMMEDIATE, "warning_immediate.wav", 10},
}; };
class Sound : public QObject { class Sound : public QObject {

@ -15,14 +15,13 @@ AudibleAlert = car.CarControl.HUDControl.AudibleAlert
SOUNDS = { SOUNDS = {
# sound: total writes # sound: total writes
AudibleAlert.none: 0, AudibleAlert.none: 0,
AudibleAlert.chimeEngage: 173, AudibleAlert.engage: 197,
AudibleAlert.chimeDisengage: 173, AudibleAlert.disengage: 230,
AudibleAlert.chimeError: 173, AudibleAlert.refuse: 223,
AudibleAlert.chimePrompt: 173, AudibleAlert.prompt: 217,
AudibleAlert.chimeWarning1: 163, AudibleAlert.promptRepeat: 475,
AudibleAlert.chimeWarningRepeat: 468, AudibleAlert.warningSoft: 477,
AudibleAlert.chimeWarningRepeatInfinite: 468, AudibleAlert.warningImmediate: 468,
AudibleAlert.chimeWarning2RepeatInfinite: 470,
} }
def get_total_writes(): def get_total_writes():
@ -40,7 +39,7 @@ class TestSoundd(unittest.TestCase):
pm = messaging.PubMaster(['deviceState', 'controlsState']) pm = messaging.PubMaster(['deviceState', 'controlsState'])
# make sure they're all defined # make sure they're all defined
alert_sounds = {v: k for k, v in car.CarControl.HUDControl.AudibleAlert.schema.enumerants.items()} alert_sounds = {v: k for k, v in car.CarControl.HUDControl.AudibleAlert.schema.enumerants.items() if not k.endswith('DEPRECATED')}
diff = set(SOUNDS.keys()).symmetric_difference(alert_sounds.keys()) diff = set(SOUNDS.keys()).symmetric_difference(alert_sounds.keys())
assert len(diff) == 0, f"not all sounds defined in test: {diff}" assert len(diff) == 0, f"not all sounds defined in test: {diff}"
@ -65,7 +64,7 @@ class TestSoundd(unittest.TestCase):
pm.send('controlsState', msg) pm.send('controlsState', msg)
time.sleep(DT_CTRL) time.sleep(DT_CTRL)
tolerance = (expected_writes % 100) * 2 tolerance = expected_writes / 10
actual_writes = get_total_writes() - start_writes actual_writes = get_total_writes() - start_writes
assert abs(expected_writes - actual_writes) <= tolerance, f"{alert_sounds[sound]}: expected {expected_writes} writes, got {actual_writes}" assert abs(expected_writes - actual_writes) <= tolerance, f"{alert_sounds[sound]}: expected {expected_writes} writes, got {actual_writes}"

@ -78,7 +78,7 @@ struct Alert {
// car is started, but controls is lagging or died // car is started, but controls is lagging or died
return {"TAKE CONTROL IMMEDIATELY", "Controls Unresponsive", return {"TAKE CONTROL IMMEDIATELY", "Controls Unresponsive",
"controlsUnresponsive", cereal::ControlsState::AlertSize::FULL, "controlsUnresponsive", cereal::ControlsState::AlertSize::FULL,
AudibleAlert::CHIME_WARNING_REPEAT}; AudibleAlert::WARNING_IMMEDIATE};
} }
} }
return {}; return {};

Loading…
Cancel
Save