47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
"""Gesture event state machine."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from .events import GestureEvent
|
|
from .recognizer import GestureObservation
|
|
|
|
|
|
@dataclass
|
|
class GestureStateMachine:
|
|
confidence_threshold: float = 0.72
|
|
cooldown_ms: int = 450
|
|
mode: str = "single"
|
|
|
|
def __post_init__(self) -> None:
|
|
self._last_emit_by_gesture: dict[str, int] = {}
|
|
self._seq = 0
|
|
|
|
def accept(self, observation: GestureObservation) -> GestureEvent | None:
|
|
if observation.confidence < self.confidence_threshold:
|
|
return None
|
|
|
|
timestamp_ms = observation.timestamp_ms
|
|
if timestamp_ms is None:
|
|
from .events import now_ms
|
|
|
|
timestamp_ms = now_ms()
|
|
|
|
last_emit_at = self._last_emit_by_gesture.get(observation.gesture)
|
|
if last_emit_at is not None and timestamp_ms - last_emit_at < self.cooldown_ms:
|
|
return None
|
|
|
|
self._seq += 1
|
|
self._last_emit_by_gesture[observation.gesture] = timestamp_ms
|
|
return GestureEvent(
|
|
gesture=observation.gesture,
|
|
confidence=round(max(0.0, min(1.0, observation.confidence)), 4),
|
|
intensity=round(max(0.0, min(1.0, observation.intensity)), 4),
|
|
timestamp_ms=timestamp_ms,
|
|
seq=self._seq,
|
|
mode=self.mode,
|
|
input_mode=self.mode,
|
|
camera_id=observation.camera_id,
|
|
)
|