soundd: don't loop controls unresponsive sound infinitely (#22839)

* soundd: don't loop controls unresponsive sound infinitely

* update tests

* actually fix
pull/22850/head
Adeeb Shihadeh 4 years ago committed by GitHub
parent 2621e5301d
commit 445a5aaca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      cereal
  2. 16
      selfdrive/controls/lib/events.py
  3. 9
      selfdrive/ui/soundd/sound.cc
  4. 19
      selfdrive/ui/soundd/sound.h
  5. 20
      selfdrive/ui/tests/test_sound.cc
  6. 4
      selfdrive/ui/tests/test_soundd.py

@ -1 +1 @@
Subproject commit aa349f6c314b1fcc7f5a42e6f4bfe0d466335634 Subproject commit 12162ac4dee9537611ee6d075e4b9b2873c6e741

@ -156,7 +156,7 @@ class SoftDisableAlert(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.MID, VisualAlert.steerRequired, Priority.MID, VisualAlert.steerRequired,
AudibleAlert.chimeWarningRepeat, .1, 2., 2.), AudibleAlert.chimeWarningRepeatInfinite, .1, 2., 2.),
class ImmediateDisableAlert(Alert): class ImmediateDisableAlert(Alert):
@ -164,7 +164,7 @@ class ImmediateDisableAlert(Alert):
super().__init__(alert_text_1, alert_text_2, super().__init__(alert_text_1, alert_text_2,
AlertStatus.critical, AlertSize.full, AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.steerRequired, Priority.HIGHEST, VisualAlert.steerRequired,
AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), AudibleAlert.chimeWarningRepeatInfinite, 2.2, 3., 4.),
class EngagementAlert(Alert): class EngagementAlert(Alert):
@ -350,7 +350,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.chimeWarningRepeat, 1., 2., 2.), Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.chimeWarningRepeatInfinite, 1., 2., 2.),
}, },
EventName.ldw: { EventName.ldw: {
@ -410,7 +410,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.chimeWarning2Repeat, .1, .1, .1), Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, .1, .1, .1),
}, },
EventName.driverDistracted: { EventName.driverDistracted: {
@ -418,7 +418,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.chimeWarningRepeat, .1, .1, .1), Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeatInfinite, .1, .1, .1),
}, },
EventName.preDriverUnresponsive: { EventName.preDriverUnresponsive: {
@ -434,7 +434,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.chimeWarning2Repeat, .1, .1, .1), Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, .1, .1, .1),
}, },
EventName.driverUnresponsive: { EventName.driverUnresponsive: {
@ -442,7 +442,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.chimeWarningRepeat, .1, .1, .1), Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeatInfinite, .1, .1, .1),
}, },
EventName.manualRestart: { EventName.manualRestart: {
@ -849,7 +849,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.chimeWarning2Repeat, 2.2, 3., 4.), Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarning2RepeatInfinite, 2.2, 3., 4.),
ET.NO_ENTRY: Alert( ET.NO_ENTRY: Alert(
"Speed Too High", "Speed Too High",
"Slow down to engage", "Slow down to engage",

@ -13,9 +13,9 @@ Sound::Sound(QObject *parent) : sm({"carState", "controlsState"}) {
QObject::connect(s, &QSoundEffect::statusChanged, [=]() { QObject::connect(s, &QSoundEffect::statusChanged, [=]() {
assert(s->status() != QSoundEffect::Error); assert(s->status() != QSoundEffect::Error);
}); });
s->setSource(QUrl::fromLocalFile(sound_asset_path + fn));
s->setVolume(Hardware::MIN_VOLUME); s->setVolume(Hardware::MIN_VOLUME);
sounds[alert] = {s, loops ? QSoundEffect::Infinite : 0}; s->setSource(QUrl::fromLocalFile(sound_asset_path + fn));
sounds[alert] = {s, loops};
} }
QTimer *timer = new QTimer(this); QTimer *timer = new QTimer(this);
@ -25,8 +25,9 @@ Sound::Sound(QObject *parent) : sm({"carState", "controlsState"}) {
void Sound::update() { void Sound::update() {
sm.update(0); sm.update(0);
// scale volume with speed
if (sm.updated("carState")) { if (sm.updated("carState")) {
// scale volume with speed
float volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f, float volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f,
Hardware::MIN_VOLUME, Hardware::MAX_VOLUME); Hardware::MIN_VOLUME, Hardware::MAX_VOLUME);
for (auto &[s, loops] : sounds) { for (auto &[s, loops] : sounds) {
@ -43,7 +44,7 @@ void Sound::setAlert(const Alert &alert) {
// stop sounds // stop sounds
for (auto &[s, loops] : sounds) { for (auto &[s, loops] : sounds) {
// Only stop repeating sounds // Only stop repeating sounds
if (s->loopsRemaining() == QSoundEffect::Infinite) { if (s->loopsRemaining() > 1 || s->loopsRemaining() == QSoundEffect::Infinite) {
s->stop(); s->stop();
} }
} }

@ -5,15 +5,16 @@
#include "selfdrive/hardware/hw.h" #include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/ui.h" #include "selfdrive/ui/ui.h"
const std::tuple<AudibleAlert, QString, bool> sound_list[] = { const std::tuple<AudibleAlert, QString, int> sound_list[] = {
{AudibleAlert::CHIME_DISENGAGE, "disengaged.wav", false}, // AudibleAlert, file name, loop count
{AudibleAlert::CHIME_ENGAGE, "engaged.wav", false}, {AudibleAlert::CHIME_DISENGAGE, "disengaged.wav", 0},
{AudibleAlert::CHIME_WARNING1, "warning_1.wav", false}, {AudibleAlert::CHIME_ENGAGE, "engaged.wav", 0},
{AudibleAlert::CHIME_WARNING2, "warning_2.wav", false}, {AudibleAlert::CHIME_WARNING1, "warning_1.wav", 0},
{AudibleAlert::CHIME_WARNING2_REPEAT, "warning_2.wav", true}, {AudibleAlert::CHIME_WARNING_REPEAT, "warning_repeat.wav", 10},
{AudibleAlert::CHIME_WARNING_REPEAT, "warning_repeat.wav", true}, {AudibleAlert::CHIME_WARNING_REPEAT_INFINITE, "warning_repeat.wav", QSoundEffect::Infinite},
{AudibleAlert::CHIME_ERROR, "error.wav", false}, {AudibleAlert::CHIME_WARNING2_REPEAT_INFINITE, "warning_2.wav", QSoundEffect::Infinite},
{AudibleAlert::CHIME_PROMPT, "error.wav", false}, {AudibleAlert::CHIME_ERROR, "error.wav", 0},
{AudibleAlert::CHIME_PROMPT, "error.wav", 0},
}; };
class Sound : public QObject { class Sound : public QObject {

@ -11,8 +11,6 @@ public:
for (auto i = sounds.constBegin(); i != sounds.constEnd(); ++i) { for (auto i = sounds.constBegin(); i != sounds.constEnd(); ++i) {
QObject::connect(i.value().first, &QSoundEffect::playingChanged, [=, s = i.value().first, a = i.key()]() { QObject::connect(i.value().first, &QSoundEffect::playingChanged, [=, s = i.value().first, a = i.key()]() {
if (s->isPlaying()) { if (s->isPlaying()) {
bool repeat = a == AudibleAlert::CHIME_WARNING_REPEAT || a == AudibleAlert::CHIME_WARNING2_REPEAT;
REQUIRE((s->loopsRemaining() == repeat ? QSoundEffect::Infinite : 1));
sound_stats[a].first++; sound_stats[a].first++;
} else { } else {
sound_stats[a].second++; sound_stats[a].second++;
@ -40,23 +38,31 @@ void controls_thread(int loop_cnt) {
} }
} }
} }
// send no alert sound
for (int j = 0; j < 1000 / DT_CTRL; ++j) {
MessageBuilder msg;
msg.initEvent().initControlsState();
pm.send("controlsState", msg);
QThread::msleep(DT_CTRL);
}
QThread::currentThread()->quit(); QThread::currentThread()->quit();
} }
TEST_CASE("test sound") { TEST_CASE("test soundd") {
QEventLoop loop; QEventLoop loop;
TestSound test_sound; TestSound test_sound;
const int test_loop_cnt = 2; const int test_loop_cnt = 2;
QThread t; QThread t;
QObject::connect(&t, &QThread::started, [=]() { controls_thread(test_loop_cnt); }); QObject::connect(&t, &QThread::started, [=]() { controls_thread(test_loop_cnt); });
QObject::connect(&t, &QThread::finished, [&]() { loop.quit(); }); QObject::connect(&t, &QThread::finished, [&]() { loop.quit(); });
t.start(); t.start();
loop.exec(); loop.exec();
for (auto [play, stop] : test_sound.sound_stats) { for (const AudibleAlert alert : test_sound.sound_stats.keys()) {
auto [play, stop] = test_sound.sound_stats[alert];
REQUIRE(play == test_loop_cnt); REQUIRE(play == test_loop_cnt);
REQUIRE(stop == test_loop_cnt); REQUIRE(stop == test_loop_cnt);
} }

@ -20,9 +20,9 @@ SOUNDS = {
AudibleAlert.chimeError: 173, AudibleAlert.chimeError: 173,
AudibleAlert.chimePrompt: 173, AudibleAlert.chimePrompt: 173,
AudibleAlert.chimeWarning1: 163, AudibleAlert.chimeWarning1: 163,
AudibleAlert.chimeWarning2: 216,
AudibleAlert.chimeWarning2Repeat: 470,
AudibleAlert.chimeWarningRepeat: 468, AudibleAlert.chimeWarningRepeat: 468,
AudibleAlert.chimeWarningRepeatInfinite: 468,
AudibleAlert.chimeWarning2RepeatInfinite: 470,
} }
def get_total_writes(): def get_total_writes():

Loading…
Cancel
Save