# target_simulator A brief description of target_simulator. ## Features - Feature 1 - Feature 2 ## Getting Started ... ## Contributing ... ## License ... ## Note: debug GUI vs simulation command behaviour The project provides two different code paths for sending target update commands: - Debug GUI (SFP Packet Inspector / Simple Target Sender): - When you press "Send Target" from the debug window, the GUI sends a `tgtset` command that includes state qualifiers such as `/s` (active), `/t` (traceable) and `/r` (restart) if the corresponding checkboxes are set. - This behaviour is intentional: the debug UI is meant for manual testing and for explicitly toggling target flags. - Runtime Simulation: - The simulation engine and continuous updates use `tgtset` commands that contain only the positional/kinematic parameters (range, azimuth, velocity, heading, altitude) and do not include the state qualifiers. This avoids unintentionally changing target lifecycle flags during normal simulation. Why this matters - Historically the code used `tgtinit` in some debug flows. `tgtinit` sets some different internal parameters (for example `heading_start`) and can change target motion in unintended ways. To preserve correct simulation behaviour, the debug window now sends `tgtset` + qualifiers while the simulation keeps sending `tgtset` without qualifiers. Where to look in the code - Debug GUI sender: `target_simulator/gui/sfp_debug_window.py` (`_on_send_target`). - Command builders: `target_simulator/core/command_builder.py` (`build_tgtset_from_target_state`, `build_tgtset_selective`, `build_tgtinit`). - Settings: debug file names and options are in `settings.json` (section `debug`) and `target_simulator/config.py` contains defaults. If you want the debug UI to exactly mimic runtime behaviour, uncheck the Active/Traceable/Restart checkboxes before sending, or use the runtime APIs to send `tgtset` without qualifiers. ## Debug logging (attivazione localizzata) Il progetto utilizza il modulo `logging` di Python con logger a livello di modulo (per esempio `target_simulator.analysis.simulation_state_hub`). In diversi punti del codice è stato standardizzato l'uso di `logger = logging.getLogger(__name__)` e aggiunto un helper `temporary_log_level` in `target_simulator/utils/logger.py` per attivare temporaneamente livelli di log più verbosi. Di seguito alcuni esempi rapidi per attivare/disattivare il DEBUG solo per la parte del codice che ti interessa analizzare. ### Attivare DEBUG per un modulo (a runtime) Apri una shell Python o esegui lo snippet nel tuo script/main e imposta il livello del logger del modulo che vuoi investigare. Esempio — abilitare DEBUG solo per lo state hub: ```python import logging logging.getLogger('target_simulator.analysis.simulation_state_hub').setLevel(logging.DEBUG) ``` Per tornare a INFO (o disattivare DEBUG): ```python logging.getLogger('target_simulator.analysis.simulation_state_hub').setLevel(logging.INFO) ``` I nomi dei logger corrispondono ai path dei moduli. Esempi utili: - `target_simulator.analysis.simulation_state_hub` - `target_simulator.gui.sfp_debug_window` - `target_simulator.gui.ppi_display` - `target_simulator.gui.payload_router` - `target_simulator.core.sfp_transport` ### Attivare DEBUG solo per un blocco di codice (temporaneo) Usa il context manager `temporary_log_level` fornito in `target_simulator.utils.logger`: ```python from logging import getLogger from target_simulator.utils.logger import temporary_log_level mod_logger = getLogger('target_simulator.gui.payload_router') with temporary_log_level(mod_logger, logging.DEBUG): # dentro questo blocco il logger è DEBUG router.process_some_payload(...) # esempio # All'uscita il livello viene ripristinato automaticamente ``` ### Debug ancora più granulare — child logger e filtri Per messaggi molto verbosi puoi creare child logger o usare `extra` + `Filter`: Child logger: ```python base = logging.getLogger('target_simulator.analysis.simulation_state_hub') diag = base.getChild('diagnostics') # 'target_simulator.analysis.simulation_state_hub.diagnostics' diag.setLevel(logging.DEBUG) diag.debug("dettagli diagnostici: ...") ``` Esempio di filtro basato su `extra`: ```python class ExtraKeyFilter(logging.Filter): def __init__(self, key, allowed_values): super().__init__() self.key = key self.allowed = set(allowed_values) def filter(self, record): return getattr(record, self.key, None) in self.allowed handler = logging.StreamHandler() handler.addFilter(ExtraKeyFilter('topic', ['diagnostic'])) logging.getLogger('target_simulator').addHandler(handler) # Emetti: logging.getLogger('target_simulator.analysis.simulation_state_hub').debug("...", extra={'topic':'diagnostic'}) ``` ### Esecuzione rapida da PowerShell Esempio per aprire REPL con PYTHONPATH corretto (Windows PowerShell): ```powershell $env:PYTHONPATH='C:\src\____GitProjects\target_simulator' python # dentro REPL eseguire i comandi logging mostrati sopra ``` Oppure eseguire un singolo comando: ```powershell $env:PYTHONPATH='C:\src\____GitProjects\target_simulator'; python -c "import logging; logging.getLogger('target_simulator.gui.payload_router').setLevel(logging.DEBUG); print('DEBUG enabled')" ``` Se vuoi, possiamo aggiungere un piccolo pannello nella GUI per controllare i livelli dei logger a runtime; fammi sapere se preferisci questa opzione.