# FlyWMS Step 1 - Core/Observer Split Data: 2026-05-29 ## Scopo Ridurre il tempo totale della demo fino a portarlo vicino alla durata reale del video, evitando che la parte visuale OpenCV rallenti il loop critico di acquisizione, inferenza e logica demo. Lo Step 1 non cambia ancora la struttura single-process del core di calcolo, ma separa in modo netto: - `core`: acquisizione, YOLO, tracking, macchina a stati, logging prestazioni - `observer`: processo separato per preview e telemetria L'obiettivo e' ottenere una demo visibile senza riportare nel loop principale il costo della vecchia UI OpenCV. ## Motivazione tecnica I benchmark gia' disponibili dicono: - video reale: `658.3 s` - benchmark headless: `762.13 s` - demo vecchia con UI integrata: molto piu' lenta La UI OpenCV dentro al loop ha gia' dimostrato di pesare in modo determinante. La strada piu' pulita e' quindi: 1. mantenere il core il piu' simile possibile al benchmark 2. spostare la visualizzazione in un processo esterno 3. accettare che l'observer non mostri tutti i frame ## Perimetro di Step 1 Step 1 include: - canale di telemetria `core -> observer` - canale preview `core -> observer` - observer separato e opzionale - modalita' `latest update wins` Step 1 non include ancora: - multiprocessing tra capture e inference - shared memory - zero-copy - nuovo frontend DearPyGUI - protocollo distribuito multi-host ## Architettura proposta ### Processo core Responsabilita': - legge il video o la camera - rispetta i limiti `preview_fps` e `yolo_fps` - esegue YOLO - aggiorna tracking e macchina a stati - salva snapshot e gestisce WMS - scrive `tempistiche.txt` - pubblica telemetria e preview in modo non bloccante Il core non deve mai aspettare l'observer. ### Processo observer Responsabilita': - ricevere dati dal core - mantenere l'ultimo stato disponibile - mostrare: - preview principale - eventuali preview secondarie - comandi/stato - fps/logica macchina a stati L'observer puo' perdere aggiornamenti. Questo e' accettabile. ## Trasporto dati Per Step 1 si usa un trasporto semplice su `localhost`, in modo da ridurre il rischio di complessita' prematura. Scelta: - socket TCP locale per preview e telemetria Motivi: - semplice da debuggare - leggibile anche con strumenti esterni - facile da riusare in seguito - non richiede introdurre subito shared memory ## Formato messaggi ### Telemetria Formato: JSON line-delimited o JSON framed su socket Campi minimi previsti: ```json { "type": "telemetry", "frame_id": 123, "timestamp": 1710000000.123, "state": "scan_level", "command_lines": ["...", "..."], "motion_text": "MOTO: stabile ...", "snapshot_counter": 4, "det_count": 2, "label_count": 1, "track_count": 2, "active_track_count": 2, "run_yolo": true, "last_yolo_ms": 28.4, "loop_fps": 25.8, "yolo_fps": 12.6, "video_fps": 30.0, "preview_fps": 30.0, "yolo_target_fps": 15.0 } ``` ### Preview Formato: messaggio con header JSON + payload JPEG. Campi minimi header: ```json { "type": "preview", "stream": "navigate", "frame_id": 123, "timestamp": 1710000000.123, "width": 960, "height": 540, "encoding": "jpeg", "jpeg_size": 45231 } ``` Il payload binario segue subito dopo l'header. ## Frequenze observer Per non pesare sul core: - telemetria: fino a `5-10 Hz` - preview principale: `3-5 fps` - preview snapshot/etichetta: solo su evento o ultima disponibile Step 1 non ha l'obiettivo di mostrare una preview fluida. Ha l'obiettivo di restare credibile a livello demo senza penalizzare il core. ## Strategia "latest update wins" Il core non accumula backlog per l'observer. Regole: - se l'observer e' lento, gli aggiornamenti vecchi possono essere scartati - il core invia solo l'ultimo stato rilevante - nessuna coda lunga per la preview Questo vale in particolare per: - preview `navigate` - testo comandi - metriche fps ## Gestione overlay Step 1 adotta una soluzione intermedia: - il core genera una preview gia' ridotta - il core puo' continuare a disegnare l'overlay minimo necessario sulla preview inviata - l'observer resta semplice e mostra il risultato Questo non e' il modello finale ideale, ma riduce il lavoro di riscrittura nello Step 1. Evoluzione futura possibile: - inviare frame piu' bbox/stato - disegnare overlay interamente nell'observer ## Modalita' di fallback Il sistema deve funzionare anche senza observer. Regole: - se l'observer non e' avviato, il core continua a lavorare - se il socket non e' disponibile, il core logga e prosegue - se l'observer si scollega, il core non deve bloccarsi Questo e' un requisito fondamentale dello Step 1. ## Parametri di configurazione da introdurre Nuovi parametri suggeriti nel file INI: - `observer_enabled = true/false` - `observer_host = 127.0.0.1` - `observer_port = 8765` - `observer_preview_fps = 4.0` - `observer_preview_width = 960` - `observer_jpeg_quality = 75` - `observer_telemetry_fps = 8.0` ## File previsti ### Nuovo file - `flywms_navigation_observer.py` Responsabilita': - connettersi al core - ricevere messaggi - mantenere ultimo stato per stream - mostrare finestre OpenCV lato observer ### Modifiche a file esistente - `flywms_navigation.py` - aggiunta configurazione observer - serializzazione telemetria - invio preview/telemetria non bloccante - disattivazione progressiva della vecchia UI integrata ## Piano implementativo di Step 1 1. aggiungere parametri observer a config e argparse 2. creare un piccolo publisher non bloccante nel core 3. creare `flywms_navigation_observer.py` 4. pubblicare: - preview `navigate` - preview `snapshot` - preview `etichetta` - telemetria/comandi 5. rendere opzionale la vecchia UI integrata 6. testare: - core senza observer - core con observer - benchmark con observer attivo ma leggero ## Criteri di successo Step 1 e' considerato riuscito se: 1. il core continua a funzionare senza finestre locali 2. l'observer mostra una preview leggibile e lo stato della missione 3. l'observer non blocca il core se rallenta o si chiude 4. il tempo totale della demo si avvicina al benchmark headless, senza ricadere nella penalizzazione della vecchia UI ## Limiti noti - Step 1 non risolve ancora il costo seriale di `cap.read()` e inferenza - Step 1 non introduce ancora il multiprocessing tra capture e inference - Step 1 non ottimizza ancora l'uso adattivo di YOLO Questi temi restano demandati agli Step 2 e 3.