Compare commits
2 Commits
d6f928ec31
...
6048ed9066
| Author | SHA1 | Date | |
|---|---|---|---|
| 6048ed9066 | |||
| ad72c2aad5 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@ Unreal/Intermediate/
|
|||||||
Unreal/Plugins/WinBluetoothLE/Intermediate/
|
Unreal/Plugins/WinBluetoothLE/Intermediate/
|
||||||
Unreal/Binaries/
|
Unreal/Binaries/
|
||||||
Unreal/Plugins/WinBluetoothLE/Binaries/
|
Unreal/Plugins/WinBluetoothLE/Binaries/
|
||||||
|
Unreal/Plugins/PS_Win_BLE/Binaries/
|
||||||
|
Unreal/Plugins/PS_Win_BLE/Intermediate/
|
||||||
|
|||||||
@ -44,6 +44,9 @@ debug_mode = 3 # 0=OFF, 1=RAW, 2=TRIGGERS, 3=FULL (actif par défaut)
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
X = np.arange(WINDOW_SIZE) # axe X fixe, ne change jamais
|
X = np.arange(WINDOW_SIZE) # axe X fixe, ne change jamais
|
||||||
|
|
||||||
|
# Fenêtre de moyenne glissante en samples (60ms window / 50ms debug rate = ~1.2 → 3 samples min)
|
||||||
|
AVG_WINDOW = 3 # correspond à la accelWindow/gyroWindow/audioWindow envoyée au XIAO (60ms @ 20Hz)
|
||||||
|
|
||||||
# ─── BLE ────────────────────────────────────────────────
|
# ─── BLE ────────────────────────────────────────────────
|
||||||
def debug_callback(sender, data):
|
def debug_callback(sender, data):
|
||||||
global audio_max_global, shot_pending
|
global audio_max_global, shot_pending
|
||||||
@ -192,9 +195,12 @@ from matplotlib.animation import FuncAnimation
|
|||||||
BG = '#1a1a2e'
|
BG = '#1a1a2e'
|
||||||
PANEL = '#16213e'
|
PANEL = '#16213e'
|
||||||
TEXT = '#e0e0e0'
|
TEXT = '#e0e0e0'
|
||||||
CA = '#4fc3f7' # accel
|
CA = '#4fc3f7' # accel brut
|
||||||
CG = '#81c784' # gyro
|
CG = '#81c784' # gyro brut
|
||||||
CM = '#ce93d8' # audio
|
CM = '#ce93d8' # audio brut
|
||||||
|
CA2 = '#0288d1' # accel moyenne (plus foncé)
|
||||||
|
CG2 = '#388e3c' # gyro moyenne
|
||||||
|
CM2 = '#7b1fa2' # audio moyenne
|
||||||
CT = '#ef5350' # trigger / seuil
|
CT = '#ef5350' # trigger / seuil
|
||||||
CS = '#ff9800' # shot (orange vif)
|
CS = '#ff9800' # shot (orange vif)
|
||||||
GRID = '#2a2a4a'
|
GRID = '#2a2a4a'
|
||||||
@ -222,15 +228,23 @@ axes[3].set_ylim(-0.1, 1.5)
|
|||||||
axes[3].set_yticks([]) # pas de graduations Y sur la timeline
|
axes[3].set_yticks([]) # pas de graduations Y sur la timeline
|
||||||
|
|
||||||
# Créer les artistes UNE SEULE FOIS — on ne les recrée jamais
|
# Créer les artistes UNE SEULE FOIS — on ne les recrée jamais
|
||||||
line_a, = axes[0].plot(X, list(accel_buf), color=CA, lw=1.5)
|
line_a, = axes[0].plot(X, list(accel_buf), color=CA, lw=1.0, alpha=0.5, label='Brut')
|
||||||
line_g, = axes[1].plot(X, list(gyro_buf), color=CG, lw=1.5)
|
line_g, = axes[1].plot(X, list(gyro_buf), color=CG, lw=1.0, alpha=0.5, label='Brut')
|
||||||
line_m, = axes[2].plot(X, list(audio_buf), color=CM, lw=1.5)
|
line_m, = axes[2].plot(X, list(audio_buf), color=CM, lw=1.0, alpha=0.5, label='Brut')
|
||||||
line_s, = axes[3].plot(X, list(shot_buf), color=CS, lw=0, marker='|',
|
line_a2, = axes[0].plot(X, list(accel_buf), color=CA2, lw=2.0, label=f'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
||||||
|
line_g2, = axes[1].plot(X, list(gyro_buf), color=CG2, lw=2.0, label=f'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
||||||
|
line_m2, = axes[2].plot(X, list(audio_buf), color=CM2, lw=2.0, label=f'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
||||||
|
line_s, = axes[3].plot(X, list(shot_buf), color=CS, lw=0, marker='|',
|
||||||
markersize=20, markeredgewidth=2.5) # barres verticales
|
markersize=20, markeredgewidth=2.5) # barres verticales
|
||||||
|
|
||||||
thr_a = axes[0].axhline(thresholds["accel"], color=CT, ls='--', lw=1.5)
|
thr_a = axes[0].axhline(thresholds["accel"], color=CT, ls='--', lw=1.5, label='Seuil')
|
||||||
thr_g = axes[1].axhline(thresholds["gyro"], color=CT, ls='--', lw=1.5)
|
thr_g = axes[1].axhline(thresholds["gyro"], color=CT, ls='--', lw=1.5, label='Seuil')
|
||||||
thr_m = axes[2].axhline(thresholds["audio"], color=CT, ls='--', lw=1.5)
|
thr_m = axes[2].axhline(thresholds["audio"], color=CT, ls='--', lw=1.5, label='Seuil')
|
||||||
|
|
||||||
|
# Légendes
|
||||||
|
for ax in axes[:3]:
|
||||||
|
ax.legend(loc='upper left', fontsize=7, facecolor=PANEL, edgecolor='#444466',
|
||||||
|
labelcolor=TEXT, framealpha=0.8)
|
||||||
|
|
||||||
from matplotlib.patches import Rectangle
|
from matplotlib.patches import Rectangle
|
||||||
from matplotlib.collections import PatchCollection
|
from matplotlib.collections import PatchCollection
|
||||||
@ -262,17 +276,30 @@ def update_spans(spans, trig_list):
|
|||||||
for i, span in enumerate(spans):
|
for i, span in enumerate(spans):
|
||||||
span.set_alpha(0.25 if i < len(tl) and tl[i] else 0)
|
span.set_alpha(0.25 if i < len(tl) and tl[i] else 0)
|
||||||
|
|
||||||
|
def rolling_avg(arr, window):
|
||||||
|
"""Moyenne glissante simple — même logique que le XIAO"""
|
||||||
|
kernel = np.ones(window) / window
|
||||||
|
return np.convolve(arr, kernel, mode='same')
|
||||||
|
|
||||||
def update(frame):
|
def update(frame):
|
||||||
# Snapshot des buffers (rapide)
|
# Snapshot des buffers (rapide)
|
||||||
a = np.array(accel_buf)
|
a = np.array(accel_buf)
|
||||||
g = np.array(gyro_buf)
|
g = np.array(gyro_buf)
|
||||||
m = np.array(audio_buf)
|
m = np.array(audio_buf, dtype=float)
|
||||||
s = np.array(shot_buf)
|
s = np.array(shot_buf)
|
||||||
|
|
||||||
|
# Moyennes glissantes (même fenêtre que le XIAO)
|
||||||
|
a_avg = rolling_avg(a, AVG_WINDOW)
|
||||||
|
g_avg = rolling_avg(g, AVG_WINDOW)
|
||||||
|
m_avg = rolling_avg(m, AVG_WINDOW)
|
||||||
|
|
||||||
# Mise à jour des données des lignes
|
# Mise à jour des données des lignes
|
||||||
line_a.set_ydata(a)
|
line_a.set_ydata(a)
|
||||||
line_g.set_ydata(g)
|
line_g.set_ydata(g)
|
||||||
line_m.set_ydata(m)
|
line_m.set_ydata(m)
|
||||||
|
line_a2.set_ydata(a_avg)
|
||||||
|
line_g2.set_ydata(g_avg)
|
||||||
|
line_m2.set_ydata(m_avg)
|
||||||
line_s.set_ydata(s)
|
line_s.set_ydata(s)
|
||||||
|
|
||||||
# Mise à jour des seuils
|
# Mise à jour des seuils
|
||||||
@ -319,7 +346,7 @@ def update(frame):
|
|||||||
f"Debug XIAO : {DEBUG_MODE_NAMES[debug_mode]} [NUM0 = cycle OFF->RAW->TRIGGERS->FULL] | "
|
f"Debug XIAO : {DEBUG_MODE_NAMES[debug_mode]} [NUM0 = cycle OFF->RAW->TRIGGERS->FULL] | "
|
||||||
f"MinSensors : {min_sensors}/3 [NUM6=+1 NUM4=-1]")
|
f"MinSensors : {min_sensors}/3 [NUM6=+1 NUM4=-1]")
|
||||||
|
|
||||||
return (line_a, line_g, line_m, line_s,
|
return (line_a, line_g, line_m, line_a2, line_g2, line_m2, line_s,
|
||||||
thr_a, thr_g, thr_m,
|
thr_a, thr_g, thr_m,
|
||||||
*titles, status_txt, debug_txt)
|
*titles, status_txt, debug_txt)
|
||||||
|
|
||||||
|
|||||||
8
Unreal/Plugins/PS_Win_BLE/Config/FilterPlugin.ini
Normal file
8
Unreal/Plugins/PS_Win_BLE/Config/FilterPlugin.ini
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[FilterPlugin]
|
||||||
|
; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and
|
||||||
|
; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively.
|
||||||
|
;
|
||||||
|
; Examples:
|
||||||
|
; /README.txt
|
||||||
|
; /Extras/...
|
||||||
|
; /Binaries/ThirdParty/*.dll
|
||||||
Loading…
x
Reference in New Issue
Block a user