mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 05:23:41 +08:00
fd4ca85d61
Provide alert playback and volume control with a native audio callback that does not depend on the Python GIL. Co-authored-by: Daniel Koepping <elkoled@gmail.com>
67 lines
3.1 KiB
Python
67 lines
3.1 KiB
Python
from openpilot.cereal import log
|
|
from openpilot.starpilot.aol.runtime import current_intent
|
|
from openpilot.starpilot.aol.wire import INTENT_SERVICE
|
|
|
|
AudibleAlert = log.SelfdriveState.AudibleAlert
|
|
COALESCE_NS = 250_000_000
|
|
|
|
|
|
class _Transition:
|
|
def __init__(self):
|
|
self.session = None
|
|
self.sequence = 0
|
|
self.active = False
|
|
self.observed_at = 0
|
|
|
|
def update(self, session, sequence: int, active: bool, now_ns: int) -> int:
|
|
changed = 0
|
|
if session is None:
|
|
self.session = None
|
|
elif session != self.session or now_ns - self.observed_at > COALESCE_NS:
|
|
self.session, self.sequence, self.active, self.observed_at = session, sequence, active, now_ns
|
|
elif sequence > self.sequence:
|
|
changed = int(active) - int(self.active)
|
|
self.sequence, self.active, self.observed_at = sequence, active, now_ns
|
|
return changed
|
|
|
|
|
|
class AxisAlerts:
|
|
def __init__(self):
|
|
self.lateral = _Transition()
|
|
self.longitudinal = _Transition()
|
|
self.last_sound = AudibleAlert.none
|
|
self.last_sound_at = 0
|
|
self.native_sound = AudibleAlert.none
|
|
|
|
def update(self, sm, native_sound: int, now_ns: int) -> int:
|
|
intent = (current_intent(sm, car_state_ns=int(sm.logMonoTime[INTENT_SERVICE]), now_ns=now_ns)
|
|
if INTENT_SERVICE in sm.logMonoTime else None)
|
|
# Engagement is persistent driver intent. Temporary native permission loss,
|
|
# pedal override and output suppression must not replay engagement sounds.
|
|
state_ns = int(sm.logMonoTime.get('selfdriveState', 0))
|
|
state_fresh = (state_ns > 0 and 0 <= now_ns - state_ns <= 100_000_000 and
|
|
sm.valid['selfdriveState'] and sm.alive['selfdriveState'])
|
|
lateral_known = intent is not None and (intent.pauseLateral or intent.lateralArmed or state_fresh)
|
|
lateral = self.lateral.update(intent.producerSessionId if lateral_known else None, intent.sequence if intent else 0,
|
|
bool(intent and not intent.pauseLateral and
|
|
(intent.lateralArmed or (state_fresh and sm['selfdriveState'].active))), now_ns)
|
|
longitudinal = self.longitudinal.update(
|
|
intent.producerSessionId if intent is not None and state_fresh else None,
|
|
intent.sequence if intent is not None else 0,
|
|
bool(intent is not None and state_fresh and sm['selfdriveState'].enabled and not intent.pauseLongitudinal), now_ns)
|
|
extra_sound = (AudibleAlert.disengage if min(lateral, longitudinal) < 0 else
|
|
AudibleAlert.engage if max(lateral, longitudinal) > 0 else AudibleAlert.none)
|
|
|
|
if native_sound != AudibleAlert.none:
|
|
if native_sound != self.native_sound and native_sound in (AudibleAlert.engage, AudibleAlert.disengage):
|
|
self.last_sound, self.last_sound_at = native_sound, now_ns
|
|
self.native_sound = native_sound
|
|
return native_sound
|
|
|
|
self.native_sound = native_sound
|
|
if extra_sound != AudibleAlert.none:
|
|
if extra_sound == self.last_sound and now_ns - self.last_sound_at < COALESCE_NS:
|
|
return AudibleAlert.none
|
|
self.last_sound, self.last_sound_at = extra_sound, now_ns
|
|
return extra_sound
|