Mario Marino

progettista e sviluppatore di applicativi gestionali e sistemi basati su LLM

PULSA

Un apparecchio che si pilota da uno smartphone e calcola la portata di un fiume sul posto

Periodo
2016 – 2018
Ruolo
progettazione, sviluppo e test
Tecnologie
PHP · Symfony · Doctrine · MySQL · JavaScript · Raspberry Pi
Stato
concluso

a cosa serve

Misurare quanta acqua passa in un fiume non si fa con uno strumento che dà il numero: si fa attraversando la sezione del corso d'acqua, fermandosi in più punti, e in ciascun punto immergendo un mulinello idrometrico a una o più profondità. Il mulinello gira sospinto dalla corrente, e da quanti giri fa in quanto tempo si ricava la velocità dell'acqua lì. La portata è quello che si ottiene mettendo insieme decine di letture con la forma del fondo.

Il lavoro che questo sostituisce è un taccuino in riva al fiume e un foglio di calcolo in ufficio la sera. Ha due costi. Il primo è che l'esito si conosce ore dopo, quando tornare al guado non è più possibile: se una lettura era sbagliata, la misura è persa. Il secondo è che ogni passaggio — la scelta dei punti, la curva di taratura dello strumento, la media lungo la verticale — è una formula applicata a mano, e nessuno la ricontrolla.

PULSA misura la portata di un corso d'acqua con un mulinello idrometrico, uno strumento che si immerge in un punto del fiume, gira sospinto dalla corrente e ne restituisce la velocità in quel punto.

cosa fa

Guida l'operatore lungo la misura secondo la norma, raccoglie le letture, calcola la portata già sul posto, e più tardi consolida tutto in un archivio dove la stessa misura viene ricalcolata con metodi più raffinati e disegnata in grafici. Qui non c'è AI. La parte difficile è la fedeltà a una norma tecnica e a un fiume vero, che non si assomigliano.

un webserver in tasca

Il client gira su un piccolo apparato hardware dedicato che fa da webserver a se stesso. Non richiede una connessione a Internet. In campo si pilota da un tablet o da uno smartphone qualunque, con il wi-fi acceso e un browser aperto. Dialoga direttamente con il mulinello, registra i tempi di rotazione delle sue letture e, appena la misura è completa, calcola già sul posto la portata di quel tratto di fiume.

La scelta di fare dell'apparato un webserver invece di scrivere un'applicazione per telefono è la decisione che ha retto meglio. Un'applicazione avrebbe voluto due versioni, due negozi, due cicli di aggiornamento e un telefono compatibile, per un apparecchio che sta in un furgone e va in acqua. Un browser ce l'hanno tutti, non si installa, e il giorno in cui il tablet si bagna se ne prende un altro qualunque. Il costo è che l'interfaccia deve funzionare bene su uno schermo piccolo, all'aperto, con i guanti — e quello è un costo che si paga una volta, mentre un pacchetto da mantenere per due sistemi operativi si paga per sempre.

Il server è un portale separato, multi-tenant: un'azienda chiede di essere registrata e autorizzata, poi ogni suo amministratore crea e abilita i propri utenti, e ciascuno vede solo l'archivio della propria azienda. Il ponte fra i due sistemi è un export dal client e un import nel server: il campo lavora scollegato dalla rete, il consolidamento dei dati arriva quando la connessione torna disponibile.

Il ponte è volutamente povero — un file di dati che esce e un file che entra — perché la condizione operativa è quella di un guado in mezzo alla campagna. Qualunque meccanismo che presupponga rete disponibile avrebbe funzionato in ufficio e fallito esattamente dove serve. Ne segue anche che il client resta utilizzabile per intero senza server: chi compra l'apparecchio può non registrarsi mai al portale e misurare lo stesso.

la norma e il fiume

Il vincolo che ha guidato il resto del progetto è la conformità allo standard internazionale ISO 748, che definisce come si esegue una misura di portata perché sia valida. PULSA accompagna l'operatore passo passo con automatismi costruiti su quella norma: propone il numero minimo di verticali richiesto lungo la sezione del fiume e la loro posizione, e per ciascuna verticale le profondità a cui misurare.

Un fiume, però, non è un laboratorio. Una sponda può essere ripida in un punto e piatta in un altro, un masso può occupare esattamente la posizione che la norma suggerirebbe, la corrente può rendere impraticabile la misura standard in un punto preciso. Ogni valore che il sistema propone resta perciò modificabile a mano, e la decisione su quando scostarsi dallo standard resta dell'operatore.

Da qui discende il modo in cui i suggerimenti sono calcolati. La posizione della verticale successiva non è presa da una griglia decisa all'inizio: è ricavata ogni volta dallo spazio che resta fra l'ultima verticale piantata e la sponda opposta, diviso per le verticali che mancano. Se l'operatore ne sposta una perché lì c'è un masso, tutte quelle dopo si ridistribuiscono da sole. Una griglia fissa avrebbe prodotto la stessa cosa solo finché nessuno la toccava, cioè mai.

«il più vicino possibile» è un numero che dipende dallo strumento

I metodi della norma che usano cinque o sei punti chiedono una lettura alla superficie e una al fondo, nei punti più prossimi possibili. È una frase, e il codice deve trasformarla in due numeri.

Non sono la superficie e il fondo: sono il limite fisico dello strumento che si sta usando. Alla superficie il centro dell'elica non può salire più di metà del diametro dell'elica stessa, altrimenti emerge. Al fondo dipende da come il mulinello è montato — su un'asta rigida, oppure appeso sotto un peso zavorrato — perché nel secondo caso è il corpo dello strumento a fermarsi prima, e la quota utile è quella, non il raggio dell'elica.

Il sistema li calcola dai dati dello strumento in uso, letti dalla sua scheda: diametro dell'elica e distanza dal fondo, registrati in millimetri. Cambiare mulinello cambia i due numeri senza toccare nulla. È il primo caso di una regola che in questo progetto ritorna: quello che riguarda lo strumento è dato, non codice.

una misura, verticale per verticale

Il modello dati segue il modo in cui si esegue una misura sul campo. Una misura è composta da più verticali distribuite lungo la larghezza del fiume, ogni verticale ha una o più posizioni in profondità, e ciascuna posizione riceve una lettura del mulinello. Durante la lettura un popup mostra in tempo reale il conteggio dei giri e il tempo residuo stimato; da quei numeri il sistema ricava la velocità dell'acqua in quel punto.

pelo libero sponda v = 0 sponda v = 0 una misura sta in più verticali lungo la larghezza; ogni verticale in più posizioni in profondità; ogni posizione riceve una lettura del mulinello
Le due sponde entrano nel calcolo come verticali a sé, con velocità zero. Non sono un caso particolare da trattare a parte: sono i due estremi che chiudono la sezione.

Ogni lettura conserva anche la serie dei conteggi nel tempo, non solo il totale. Costa spazio e non serve a calcolare niente, ed è la ragione per cui esiste il secondo grafico più sotto: una lettura si giudica dall'andamento dei giri, non dal numero finale, e quell'andamento se non lo si registra durante la misura non lo si ricostruisce più.

dai giri alla portata

La catena che porta da una lettura a un numero è la parte del progetto in cui stanno quasi tutte le decisioni.

giri al secondo velocità nel punto velocità media sulla verticale portata grandezze derivate quadro riassuntivo conteggio e durata della lettura equazione dello strumento metodo della norma, o interpolazione due metodi in parallelo sezione, raggio idraulico, Froude quattro grafici la formula sta nel database, non nel codice tre generazioni, e la prima resta selezionabile media e centrale, così la differenza resta visibile
I tre riquadri marcati sono quelli dove la norma lascia più di una strada. In tutti e tre il sistema non ne sceglie una per conto suo.

lo strumento porta con sé la propria formula

Un mulinello non converte i giri in velocità con una formula universale: ne ha una sua, scritta sul certificato di taratura che lo accompagna, e quasi sempre non è nemmeno una sola. Sono più equazioni valide su intervalli diversi di giri al secondo, perché l'elica si comporta in modo diverso in acqua lenta e in acqua veloce.

Nel sistema quelle equazioni sono righe di database. La formula è conservata come testo con un segnaposto al posto della variabile, e accanto sta la condizione che dice quando si applica: un operatore di confronto e una o due soglie, così che «maggiore di», «compreso fra» e «minore o uguale» siano dati anch'essi. Al momento del calcolo si sostituisce il numero misurato e si valuta l'espressione.

L'alternativa era scrivere le formule nel codice con un identificativo per modello di mulinello. Sarebbe stato più veloce da fare e sbagliato per la natura del prodotto: questo software si vende a chi ha già i suoi strumenti, e non c'è modo di sapere in anticipo quali. Un cliente nuovo con un mulinello mai visto avrebbe richiesto un rilascio; così richiede l'inserimento di una scheda.

Il costo di questa scelta va detto, perché è reale: si finisce a valutare a runtime un'espressione che arriva dal database. La difesa sta nel ripulire l'espressione dai caratteri che non appartengono a una formula prima di valutarla, ed è una difesa che dipende interamente dalla correttezza di quel filtro. Rifacendolo oggi userei un valutatore di espressioni vero, che in PHP allora non era una dipendenza ovvia come lo è adesso.

la media sulla verticale ha tre generazioni, e la prima non è stata tolta

La velocità media lungo una verticale si ottiene dalle letture fatte a profondità diverse, e la norma prevede più modi di combinarle a seconda di quanti punti si sono misurati: un punto solo a sei decimi della profondità, due punti a due e otto decimi mediati, tre punti, cinque, sei, e un metodo di sola superficie con un coefficiente correttivo. Sono tutte medie pesate, e sono implementate una per una.

Sopra queste, negli anni, ne sono state aggiunte due che non sono medie pesate ma interpolazioni: si costruisce la curva della velocità lungo la profondità e se ne prende il valore medio. La prima passa un unico polinomio per tutti i punti misurati e ne calcola l'integrale sulla profondità. La seconda usa una spline di Akima, che è locale: ogni tratto della curva dipende dai punti vicini, e un punto anomalo non deforma la curva lontano da sé, cosa che a un polinomio unico di grado alto capita.

La seconda non ha sostituito la prima. La scelta è un campo della singola misura, quindi due misure nello stesso archivio possono essere calcolate con metodi diversi, e una misura vecchia non cambia numero perché nel frattempo il codice è migliorato. In un archivio di misure che qualcuno confronta nel tempo, ricalcolare tutto con il metodo nuovo sarebbe stato il modo più rapido per rendere non confrontabile la serie storica.

Insieme al risultato viene conservata anche la lista dei coefficienti della curva usata. Non serve a nessun calcolo successivo: serve a poter rispondere, mesi dopo, alla domanda su come è stato ottenuto quel numero.

dove l'acqua tocca, non scorre

Entrambi i metodi per interpolazione aggiungono un punto che non è stato misurato: sul fondo della verticale, con velocità zero. E le due sponde entrano nel calcolo della portata come verticali a sé, anch'esse a velocità zero.

Non è un espediente per far tornare i conti: è la condizione fisica al contorno — l'acqua a contatto con il fondo e con la riva non scorre — scritta dove il calcolo la può usare. Senza quel punto la curva della velocità arriverebbe al fondo con il valore dell'ultima lettura utile, che sta comunque qualche centimetro più in alto, e la media verrebbe più alta del vero. È l'errore che nessuno vede, perché il risultato resta plausibile.

due portate invece di una

La portata viene calcolata con due metodi diversi previsti dalla norma, e conservata due volte. Uno attribuisce a ogni verticale la fascia di sezione che le sta attorno; l'altro procede per trapezi fra una verticale e la successiva, mediando velocità e profondità agli estremi.

Sarebbe stato più semplice sceglierne uno. Tenerli entrambi costa una colonna in più e in cambio dà una cosa che un numero solo non dà: la loro differenza è una misura di quanto la sezione è irregolare rispetto a quante verticali si sono fatte. Se i due valori si somigliano, il numero di verticali era adeguato; se divergono, sono state poche per quel fiume. È un controllo di qualità che non richiede di misurare niente in più.

due definizioni cambiate perché quella comoda era peggiore

Due grandezze di uscita sono calcolate in modo diverso da come le calcolava la prima versione, e la ragione nei due casi è la stessa.

In tutti e due i casi la formula vecchia era più immediata da scrivere e dava un numero verosimile. È il tipo di sbaglio che non si scopre guardando l'uscita: si scopre chiedendosi cosa quel numero dovrebbe significare.

Dalle stesse grandezze escono poi la sezione bagnata, il contorno bagnato, il raggio idraulico, la profondità massima, le velocità massime e superficiali, e il numero di Froude, che dice se la corrente in quel tratto è lenta o veloce rispetto alla propagazione delle onde. Sono le grandezze che rendono la misura leggibile da un idraulico, oltre che archiviabile.

il quadro riassuntivo

A misura completata il server compone un quadro riassuntivo con quattro grafici: il profilo della sezione del fiume rilevata, i profili di velocità su ciascuna verticale, la portata media specifica lungo la sezione e la mappa delle aree a velocità simile, dette isotachie. È la vista che restituisce in un colpo d'occhio l'esito della misura appena fatta.

Quadro misura del server PULSA, con i quattro grafici della sezione rilevata

Un secondo grafico, per ogni singola verticale, sovrappone i tempi di rotazione registrati alle diverse profondità di misura: il confronto fra le curve dà una valutazione d'insieme sulla qualità della rilevazione fatta su quella verticale.

Tempi di rotazione del mulinello registrati su una verticale, alle diverse profondità di misura

È il grafico che giustifica la scelta di conservare la serie dei conteggi. Una verticale in cui le curve si somigliano è una verticale misurata bene; una in cui una curva scarta dalle altre segnala che in quel punto è successo qualcosa — un detrito nell'elica, una corrente instabile, un'asta che si è mossa — e chi era sul posto quel giorno se lo ricorda ancora.

limiti dichiarati

stato

Concluso, scritto in PHP e Symfony. Il portale server non era ospitato da me, e oggi il suo dominio non risolve più. Questo dice che non è raggiungibile in questo momento, non che sia stato dismesso.