Device: Quiet Mode (#654)

* init quiet mode

* only for sunny

* static

* toggle

* let's back this up

* review sugg

* oh okay

* review

* fix: ensure boolean conversion for QuietDrive parameter

* Refactor return statement to use boolean conversion for clarity in quiet mode logic

* Update selfdrive/ui/sunnypilot/quietmode.py

* rename

* sunny

* Revert "sunny"

This reverts commit 6ac4cf4b8d3b0f8576cdec0146f3815a662a01a5.

* sunny

* Revert "sunny"

This reverts commit c2bffddc052bdc2e269f3f7070934037c490810a.

* sunny

* ui: support dynamic state updates for `PushButtonSP`

* test btn

* override mouse release events

* Revert "test btn"

This reverts commit cd9c9dde9a37a8b2c7de7ad123cbb53f80e9e5e6.

* Reapply "test btn"

This reverts commit 9b36b2e08500d81cecb95f6c47a66a43e2dcd1b4.

* abstract param flipping

* Revert "Reapply "test btn""

This reverts commit 8104a262b02303b1c6fe2df00b2d65408fa010ea.

* use new button state for PushButtonSP

* Quiet Drive -> Quiet Mode

* driver camera btn moved

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
This commit is contained in:
Kumar
2025-03-23 20:15:11 -07:00
committed by GitHub
parent 982674b4a7
commit 029a601674
6 changed files with 53 additions and 3 deletions
+1
View File
@@ -128,6 +128,7 @@ inline static std::unordered_map<std::string, uint32_t> keys = {
{"ModelRunnerTypeCache", CLEAR_ON_ONROAD_TRANSITION},
{"OffroadMode", CLEAR_ON_MANAGER_START},
{"OffroadMode_Status", CLEAR_ON_MANAGER_START},
{"QuietMode", PERSISTENT | BACKUP},
// MADS params
{"Mads", PERSISTENT | BACKUP},
+8 -2
View File
@@ -13,6 +13,8 @@ from openpilot.common.swaglog import cloudlog
from openpilot.system import micd
from openpilot.selfdrive.ui.sunnypilot.quiet_mode import QuietMode
SAMPLE_RATE = 48000
SAMPLE_BUFFER = 4096 # (approx 100ms)
MAX_VOLUME = 1.0
@@ -50,8 +52,10 @@ def check_selfdrive_timeout_alert(sm):
return False
class Soundd:
class Soundd(QuietMode):
def __init__(self):
super().__init__()
self.load_sounds()
self.current_alert = AudibleAlert.none
@@ -81,7 +85,7 @@ class Soundd:
ret = np.zeros(frames, dtype=np.float32)
if self.current_alert != AudibleAlert.none:
if self.should_play_sound(self.current_alert):
num_loops = sound_list[self.current_alert][1]
sound_data = self.loaded_sounds[self.current_alert]
written_frames = 0
@@ -144,6 +148,8 @@ class Soundd:
while True:
sm.update(0)
self.load_param()
if sm.updated['microphone'] and self.current_alert == AudibleAlert.none: # only update volume filter when not playing alert
self.spl_filter_weighted.update(sm["microphone"].soundPressureWeightedDb)
self.current_volume = self.calculate_volume(float(self.spl_filter_weighted.x))
@@ -17,6 +17,7 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) {
device_grid_layout->setVerticalSpacing(25);
std::vector<std::tuple<QString, QString, QString>> device_btns = {
{"quietModeBtn", tr("Quiet Mode"), "QuietMode"},
{"dcamBtn", tr("Driver Camera Preview"), ""},
{"retrainingBtn", tr("Training Guide"), ""},
{"regulatoryBtn", tr("Regulatory"), ""},
@@ -45,6 +46,8 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) {
connect(buttons["dcamBtn"], &PushButtonSP::clicked, [=]() { emit showDriverView(); });
connect(buttons["quietModeBtn"], &PushButtonSP::clicked, buttons["quietModeBtn"], &PushButtonSP::updateButton);
connect(buttons["retrainingBtn"], &PushButtonSP::clicked, [=]() {
if (ConfirmationDialog::confirm(tr("Are you sure you want to review the training guide?"), tr("Review"), this)) {
emit reviewTrainingGuide();
+39
View File
@@ -0,0 +1,39 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from cereal import car
from openpilot.common.params import Params
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
ALERTS_ALWAYS_PLAY = {
AudibleAlert.warningSoft,
AudibleAlert.warningImmediate,
AudibleAlert.promptDistracted,
AudibleAlert.promptRepeat,
}
class QuietMode:
def __init__(self):
self.params = Params()
self.enabled: bool = self.params.get_bool("QuietMode")
self._frame = 0
def load_param(self) -> None:
self._frame += 1
if self._frame % 50 == 0: # 2.5 seconds
self.enabled = self.params.get_bool("QuietMode")
def should_play_sound(self, current_alert: int) -> bool:
"""
Check if a sound should be played based on the Quiet Mode setting
and the current alert.
"""
if not self.enabled:
return bool(current_alert != AudibleAlert.none)
return current_alert in ALERTS_ALWAYS_PLAY
+1 -1
View File
@@ -151,7 +151,7 @@ def setup_keyboard_uppercase(click, pm: PubMaster, scroll=None):
def setup_driver_camera(click, pm: PubMaster, scroll=None):
setup_settings_device(click, pm)
click(950, 620)
click(1720, 620)
DATA['deviceState'].deviceState.started = False
setup_onroad(click, pm)
DATA['deviceState'].deviceState.started = True
+1
View File
@@ -51,6 +51,7 @@ def manager_init() -> None:
("ModelManager_LastSyncTime", "0"),
("ModelManager_ModelsCache", ""),
("NeuralNetworkLateralControl", "0"),
("QuietMode", "0"),
]
if params.get_bool("RecordFrontLock"):