mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-11 02:33:51 +08:00
FrogPilot 0.9.7
This commit is contained in:
+104
-7
@@ -3,6 +3,7 @@ import numpy as np
|
||||
import time
|
||||
import wave
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from cereal import car, messaging
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
@@ -13,6 +14,8 @@ from openpilot.common.swaglog import cloudlog
|
||||
|
||||
from openpilot.system import micd
|
||||
|
||||
from openpilot.selfdrive.frogpilot.frogpilot_variables import ACTIVE_THEME_PATH, RANDOM_EVENTS_PATH, get_frogpilot_toggles, params_memory
|
||||
|
||||
SAMPLE_RATE = 48000
|
||||
SAMPLE_BUFFER = 4096 # (approx 100ms)
|
||||
MAX_VOLUME = 1.0
|
||||
@@ -38,6 +41,23 @@ 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),
|
||||
|
||||
# FrogPilot sounds
|
||||
AudibleAlert.angry: ("angry.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.continued: ("continued.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.dejaVu: ("dejaVu.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.doc: ("doc.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.fart: ("fart.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.firefox: ("firefox.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.goat: ("goat.wav", None, MAX_VOLUME),
|
||||
AudibleAlert.hal9000: ("hal9000.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.mail: ("mail.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.nessie: ("nessie.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.noice: ("noice.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.promptRepeat: ("prompt_repeat.wav", None, MAX_VOLUME),
|
||||
AudibleAlert.startup: ("startup.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.thisIsFine: ("this_is_fine.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.uwu: ("uwu.wav", 1, MAX_VOLUME),
|
||||
}
|
||||
|
||||
def check_controls_timeout_alert(sm):
|
||||
@@ -52,8 +72,6 @@ def check_controls_timeout_alert(sm):
|
||||
|
||||
class Soundd:
|
||||
def __init__(self):
|
||||
self.load_sounds()
|
||||
|
||||
self.current_alert = AudibleAlert.none
|
||||
self.current_volume = MIN_VOLUME
|
||||
self.current_sound_frame = 0
|
||||
@@ -62,6 +80,33 @@ class Soundd:
|
||||
|
||||
self.spl_filter_weighted = FirstOrderFilter(0, 2.5, FILTER_DT, initialized=False)
|
||||
|
||||
# FrogPilot variables
|
||||
self.frogpilot_toggles = get_frogpilot_toggles()
|
||||
|
||||
self.auto_volume = 0
|
||||
|
||||
self.previous_sound_pack = None
|
||||
|
||||
self.random_events_directory = Path(RANDOM_EVENTS_PATH) / "sounds"
|
||||
|
||||
self.random_events_map = {
|
||||
AudibleAlert.angry: MAX_VOLUME,
|
||||
AudibleAlert.continued: MAX_VOLUME,
|
||||
AudibleAlert.dejaVu: MAX_VOLUME,
|
||||
AudibleAlert.doc: MAX_VOLUME,
|
||||
AudibleAlert.fart: MAX_VOLUME,
|
||||
AudibleAlert.firefox: MAX_VOLUME,
|
||||
AudibleAlert.goat: MAX_VOLUME,
|
||||
AudibleAlert.hal9000: MAX_VOLUME,
|
||||
AudibleAlert.mail: MAX_VOLUME,
|
||||
AudibleAlert.nessie: MAX_VOLUME,
|
||||
AudibleAlert.noice: MAX_VOLUME,
|
||||
AudibleAlert.thisIsFine: MAX_VOLUME,
|
||||
AudibleAlert.uwu: MAX_VOLUME,
|
||||
}
|
||||
|
||||
self.update_frogpilot_sounds()
|
||||
|
||||
def load_sounds(self):
|
||||
self.loaded_sounds: dict[int, np.ndarray] = {}
|
||||
|
||||
@@ -69,7 +114,17 @@ class Soundd:
|
||||
for sound in sound_list:
|
||||
filename, play_count, volume = sound_list[sound]
|
||||
|
||||
wavefile = wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r')
|
||||
if sound in self.random_events_map:
|
||||
wavefile = wave.open(str(self.random_events_directory / filename), 'r')
|
||||
else:
|
||||
try:
|
||||
wavefile = wave.open(str(self.sound_directory / filename), 'r')
|
||||
except FileNotFoundError:
|
||||
if filename == "prompt_repeat.wav":
|
||||
filename = "prompt.wav"
|
||||
if filename == "startup.wav":
|
||||
filename = "engage.wav"
|
||||
wavefile = wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r')
|
||||
|
||||
assert wavefile.getnchannels() == 1
|
||||
assert wavefile.getsampwidth() == 2
|
||||
@@ -136,18 +191,31 @@ class Soundd:
|
||||
# sounddevice must be imported after forking processes
|
||||
import sounddevice as sd
|
||||
|
||||
sm = messaging.SubMaster(['controlsState', 'microphone'])
|
||||
sm = messaging.SubMaster(['controlsState', 'microphone', 'frogpilotPlan'])
|
||||
|
||||
with self.get_stream(sd) as stream:
|
||||
rk = Ratekeeper(20)
|
||||
|
||||
cloudlog.info(f"soundd stream started: {stream.samplerate=} {stream.channels=} {stream.dtype=} {stream.device=}, {stream.blocksize=}")
|
||||
while True:
|
||||
while not params_memory.get_bool("TestingSound"):
|
||||
sm.update(0)
|
||||
|
||||
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))
|
||||
if self.frogpilot_toggles.alert_volume_control:
|
||||
self.spl_filter_weighted.update(sm["microphone"].soundPressureWeightedDb)
|
||||
self.auto_volume = self.calculate_volume(float(self.spl_filter_weighted.x))
|
||||
self.current_volume = 0.0
|
||||
else:
|
||||
self.spl_filter_weighted.update(sm["microphone"].soundPressureWeightedDb)
|
||||
self.current_volume = self.calculate_volume(float(self.spl_filter_weighted.x))
|
||||
|
||||
elif self.frogpilot_toggles.alert_volume_control and self.current_alert in self.volume_map:
|
||||
self.current_volume = self.volume_map[self.current_alert] / 100.0
|
||||
if self.current_volume == 1.01:
|
||||
self.current_volume = self.auto_volume
|
||||
|
||||
elif self.current_alert in self.random_events_map:
|
||||
self.current_volume = self.random_events_map[self.current_alert]
|
||||
|
||||
self.get_audible_alert(sm)
|
||||
|
||||
@@ -155,6 +223,35 @@ class Soundd:
|
||||
|
||||
assert stream.active
|
||||
|
||||
# Update FrogPilot parameters
|
||||
if sm['frogpilotPlan'].togglesUpdated:
|
||||
self.frogpilot_toggles = get_frogpilot_toggles()
|
||||
self.update_frogpilot_sounds()
|
||||
|
||||
def update_frogpilot_sounds(self):
|
||||
self.volume_map = {
|
||||
AudibleAlert.engage: self.frogpilot_toggles.engage_volume,
|
||||
AudibleAlert.disengage: self.frogpilot_toggles.disengage_volume,
|
||||
AudibleAlert.refuse: self.frogpilot_toggles.refuse_volume,
|
||||
|
||||
AudibleAlert.prompt: self.frogpilot_toggles.prompt_volume,
|
||||
AudibleAlert.promptRepeat: self.frogpilot_toggles.prompt_volume,
|
||||
AudibleAlert.promptDistracted: self.frogpilot_toggles.promptDistracted_volume,
|
||||
|
||||
AudibleAlert.warningSoft: self.frogpilot_toggles.warningSoft_volume,
|
||||
AudibleAlert.warningImmediate: self.frogpilot_toggles.warningImmediate_volume,
|
||||
|
||||
AudibleAlert.goat: self.frogpilot_toggles.prompt_volume,
|
||||
}
|
||||
|
||||
if self.frogpilot_toggles.sound_pack != "stock":
|
||||
self.sound_directory = Path(ACTIVE_THEME_PATH) / "sounds"
|
||||
else:
|
||||
self.sound_directory = Path(BASEDIR) / "selfdrive" / "assets" / "sounds"
|
||||
|
||||
if self.frogpilot_toggles.sound_pack != self.previous_sound_pack:
|
||||
self.load_sounds()
|
||||
self.previous_sound_pack = self.frogpilot_toggles.sound_pack
|
||||
|
||||
def main():
|
||||
s = Soundd()
|
||||
|
||||
Reference in New Issue
Block a user