Una procedura per controllare un telescopio
Questo laboratorio è stato sviluppato da Matteo Cirenza, Veronica Civerchia, Lorenzo Fiorentini, Lisa Incollingo, Ilaria Lepori in collaborazione con Gianluigi Liberti (CNR-ISMAR), il progetto è stato coordinato da Gualtiero Grassucci (lss G.B. Grassi di Latina).
Materiale didattico a supporto
- Il fascicolo (in formato PDF di circa 15MB);
- La libreria di funzioni sviluppata con Blockly;
- La libreria in Python e in XML (così come generata da Blockly, in formato ZIP);
- La libreria per implementare le matrici in Blockly (file in formato XML compattato in formato ZIP).
Il LIDAR (Laser Imaging Detection and Ranging) è un’apparecchiatura per analizzare l’atmosfera. Il funzionamento, almeno teoricamente, è piuttosto semplice: un raggio laser viene inviato verticalmente nell’atmosfera, la luce emessa è rifratta e riflessa dall’atmosfera stessa a causa delle differenze
di pressione, di umidità, di temperatura, della presenza di particelle in sospensione (l’aerosol). La radiazione riflessa (o meglio, retro-riflessa) è captata da una serie di undici telescopi e analizzata per dedurre le condizioni e la composizione dell’atmosfera.
Prerequisiti
Per questo laboratorio è necessario:
- conoscere, almeno in maniera elementare, cos’è una matrice e saper identificare le caselle (le celle) di una matrice attraverso il numero di riga e di colonna.
Obiettivi
Il nostro obiettivo è quello di trovare un algoritmo in grado di allineare automaticamente il telescopio del LIDAR in modo tale che, ogni volta, esso occupi la posizione migliore per ricevere il segnale laser retro-riflesso.
La libreria
Contestualmente alla soluzione del problema, nel corso del laboratorio le funzioni realizzate sono state implementate mediante Blockly. Attualmente il generatore di codice di Google non supporta le matrici (anche se è previsto uno sviluppo in tal senso) per cui, per maneggiare la matrice del problema abbiamo dovuto progettare e realizzare alcune funzioni apposite. Qui presentiamo la libreria e la sua struttura.
Variabili globali e impostazioni
La libreria fa uso di alcune variabili globali che impostano le dimensioni della matrice e i parametri della funzione gaussiana usata per simulare il segnale (e il disturbo dovuto alle condizioni dell’atmosfera):
- righe, colonne: il numero di righe e di colonne della matrice;
- mux, muy: il valore atteso lungo l’asse delle ascisse e lungo l’asse delle ordinate e quindi, in pratica, la colonna e la riga della casella della matrice in cui, teoricamente, si dovrebbe trovare il segnale migliore;
- sigmax, sigmay: la radice della varianza lungo l’asse delle ascisse (colonne) e lungo l’asse delle ordinate (righe);
- noisemax: il vallore massimo da attribuire al disturbo;
- scala: un fattore per cui moltiplicare i valori della distrubuzione normale del segnale.
Tutte le variabili globali sono impostate nella stessa funzione:
InizializzazioneParametri(righe, colonne, mux, muy, sigmax, sigmay,
noisemax, scala)
Funzioni per la gestione delle matrici
Le matrici sono implementate come liste di righe, ogni riga a sua volta è una lista di elementi. Le posizioni nella matrice sono mappate su un sistema di riferimento che ha origine in alto a sinistra, l’asse delle ascisse che va da sinistra verso destra e quello delle ordinate dall’alto verso il basso.
Convertire una matrice in una stringa di testo
Converte una matrice in una stringa di testo in cui gli elementi sono separati da virgole e le righe racchiuse tra parentesi quadre.
MatriceTesto(m)
dove m è la matrice. Restituisce una stringa di testo costruita come descritto sopra.
Accedere agli elementi della matrice
Recupera il valore di un elemento della matrice.
ElementoMatrice(m, x, y)
dove m è la matrice e x, y rispettivamente la colonna e la riga dell’elemento del quale recuperare il valore. Restituisce il valore dell’elemento specificato.
Imposta il valore di un elemento della matrice.
ImpostaElementoMatrice(m, x, y, valore)
dove m è la matrice, x, y rispettivamente la colonna e la riga dell’elemento di cui impostare il valore e valore è proprio il valore da assegnare a quell’elemento.
Numero di righe e colonne della matrice
Recupera il numero di righe o di colonne della matrice.
RigheMatrice(m)
ColonneMatrice(m)
dove, in entrambe le funzioni, m è la matrice. La prima restituisce il numero di righe della matrice, la seconda il numero di colonne.
Funzioni per la inizializzazione degli esempi
Matrici di esempio
Costruiscono matrici di esempio statiche, costanti, usate per testare le procedure di allineamento.
MatriceEsempio5x5()
MatriceEsempio21x21()
La prima costruisce una matrice di esempio con cinque righe e cinque colonne, la stessa usata nel fascicolo per i primi esempi, la seconda costruisce una matrice di 21 righe e 21 colonne che simula una distribuzione normale, anche questa presente nel fascicolo (cfr 2.4 Il problema vero e proprio a pagina 10, la matrice è a pagina 11).
Emtrambe restituiscono una matrice, implementata come una lista di righe (e ciascuna riga come una lista di elementi).
Funzione gaussiana e distribuzione del segnale
La prima funzione calcola il valore di una gaussiana bidimensionale:
Gaussiana(x, y)
dove x, y sono rispettivamente colonna e riga della posizione della matrice in cui calcolare il valore della funzione (cfr. 2.4 Il problema vero e proprio a pagina 10 del fascicolo). Fa uso delle variabili globali che abbiamo descritto all’inizio. Restituisce un numero reale.
La seconda calcola un valore simile ma disturbato dall’errore:
GaussianaErrore(x, y)
dove x, y sono rispettivamente colonna e riga della posizione (nella matrice) in cui calcolare il valore (cfr. Costruiamo la matrice a pagina 12 nel fascicolo). Usa Gaussiana(x, y). Restituisce un numero intero positivo: il valore del segnale moltiplicato per il fattore di scala.
Infine una funzione che costruisce la matrice che simula la distribuzione del segnale, disturbo compreso:
CreaMatriceTest(righe, colonne)
dove righe, colonne sono, ovviamente, il numero di righe e colonne della matrice da creare. Usa GaussianaErrore(x, y). Restituisce una matrice come lista di righe, come di consueto.
Funzioni per la risoluzione del problema
Determinare la posizione vicina con il valore maggiore
Determina la casella della matrice vicina a quella attuale con il valore maggiore (in cui il segnale è migliore).
VicinaMaggiore(m, x, y)
dove m è la matrice e x, y rispettivamente colonna e riga della posizione (casella) attuale. Usa ElementoMatrice(x, y). Restituisce una lista [x_m, y_m] contenente colonna e riga della casella vicina con il valore più alto.
Spostare il telescopio nella posizione migliore
Sposta il telescopio di casella in casella fino ad arrivare a quella in cui il valore del segnale è maggiore.
Allineamento(m, x_0, y_0)
dove m è la matrice presa in considerazione e x_0, y_0 colonna e riga della posizione di partenza. Usa VicinaMaggiore(m, x, y) e ElementoMatrice(m, x, y). Restituisce il percorso fatto dal telescopio sotto forma di una lista in cui ogni elemento è una lista del tipo [x, y] dove x, y sono colonna e riga delle caselle attraversate (il primo elemento della lista è la casella di partenza, l’ultimo
la casella di arrivo). Il percorso è quello effettivamente seguito dal telescopio, in particolare uno spostamento in diagonale è memorizzato come due spostamenti: il primo in verticale e il secondo in orizzontale.
Infine una funzione per convertire in una stringa di testo il percorso del telescopio:
PercorsoInTesto(percorso)
dove percorso è, come già detto, una lista del tipo [x, y] dove x, y sono colonna e riga delle caselle attraversate (il primo elemento della lista è la casella di partenza, l’ultimo la casella di arrivo). Restituisce una stringa di testo con l’elenco delle caselle attraversate.
Miglioramenti
La rilevazione dell’intensità del segnale è piuttosto laboriosa e richiede parecchio tempo, nell’ordine dei minuti per cui un miglioramento possibile, che abbiamo in programma ma che non abbiamo ancora implementato, cerca di ridurre per quanto possibile le misurazioni utilizzando valori già rilevati in precedenza (possiamo ipotizzare che le condizioni dell’atmosfera siano abbastanza
stabili nel periodo di osservazione). Tenete conto che ogni volta che si esegue un’istruzione del tipo M(…, …) nelle funzioni che abbiamo mostrato, c’è una misura dell’intensità del segnale.
La miglioria riguarda soprattutto la funzione VicinaMaggiore(…) che crea una matrice ausiliaria, chiamata nel seguito M_2 e inizialmente vuota, in cui sono memorizzati i valori del segnale via via rilevati, questi valori sono usati successivamente per evitare di misurare più volte l’intensità del segnale nella stessa posizione. La formalizzazione di questa funzione è presente già nel fascicolo.