• Non ci sono risultati.

5.4 Bug Servomotori

5.4.3 MotorPanel.java

Questa classe si è rivelata essere la responsabile della maggior parte dei bug relativi alla simulazione dei servomotori da parte di NXTSimulator. Verrà ora proposta una panoramica delle modifiche correttive più rilevanti che sono state ad essa apportate.

Innanzitutto è stata ritoccata l'interfaccia grafica, utile per la visualizzazione della simulazione dei singoli servomotori, e definita dalla classe MotorPanel. Nella figura a pagina seguente sono riportate rispettivamente la versione antecedente e quella conseguente al ritocco.

Figura 5.4: Vecchia e nuova interfaccia grafica dei servomotori nel simulatore

Come emerge dal confronto tra le due immagini allegate qui sopra, si nota che nella nuova versione della grafica dei servomotori sono stati rimossi i pulsanti tramite i quali era possibile scegliere se far girare il motore in questione mediante le specifiche istruzioni del programma .RXE da simulare (Programmato), o se incaricare l'utente di impostare la potenza da applicare al medesimo (Test), specificandola mediante l'apposita barra scorrevole rappresenta in figura. Tale distinzione, infatti, si è rivelata a lungo andare inutile, e si è quindi propenso per far funzionare i motori solamente con la prima delle due modalità appena descritte. Si è, inoltre, aggiunto un oggetto di tipo javax.swing.JLabel [16s], denominato

rotationLab e cerchiato in rosso in figura 5.4, utilizzato per visualizzare durante una

simulazione il numero di giri completi (rotazioni di 360°) effettuati da un motore. Oltre ad aver ritoccato l'aspetto grafico della classe MotorPanel, si è anche rivisitata e modificata la sua porzione di codice sorgente responsabile dell'aggiornamento periodico della grafica medesima, attuato per simulare il movimento del servomotore. Il codice in questione è quello contenuto all'interno del costruttore della classe, il quale essenzialmente istanzia un oggetto di classe

javax.swing.Timer [16s], il quale funge da timer temporale, che si occupa di invocare

di continuo l'aggiornamento della posizione angolare del servomotore, sulla base delle proprietà specificate in ingresso per esso. Durante una simulazione l'aggiornamento della grafica relativa ad un motore avveniva, nella versione 0.9b di

NXTSimulator, attuando una distinzione sulla base della modalità operativa in cui si

trovava di volta in volta ad operare il servomotore. Quest'ultimo poteva trovarsi in una tra cinque distinte modalità: ciò che esso faceva in ognuna di esse era tuttavia implementato in modo errato o lacunoso. Si è dunque dovuto procedere di conseguenza.

Nella versione 0.9c del simulatore il modus operandi adottato per simulare un motore ha previsto la conservazione dell'approccio di cui sopra, ritoccando, però, ove necessario, l'implementazione delle singole modalità operative.

Le cinque modalità in cui un servomotore può agire sono le seguenti: running,

rampdown, rampup, idle e coast. Verrà ora descritto per ciascuna di queste, il modo

in cui essa è stata ritoccata nella versione 0.9c del simulatore.

La modalità running prevede semplicemente che un servomotore percorra un certo numero di gradi ruotando con una determinata potenza, specificata dalla proprietà

SPEED dell'istanza di MotorData ad esso relativa. Questa modalità era stata già

implementata in modo sostanzialmente corretto, eccezion fatta per il modo in cui era aggiornata di volta in volta la posizione angolare del motore, nel caso di rotazione in senso antiorario: era, infatti, adottata una formula errata per il calcolo della medesima, e ciò comportava il comportamento bizzarro della simulazione, di cui si è parlato all'inizio di questa sezione. L'errore appena discusso era presente, ed è stato perciò corretto, anche nelle modalità rampdown e rampup.

La modalità rampdown obbliga un motore a percorrere un certo numero di gradi, diminuendo gradualmente la propria potenza iniziale, fino ad azzerarla. Questa modalità era stata implementata in modo completamente scorretto. La formula utilizzata per il decremento graduale della potenza era, infatti, errata e provocava il lancio dell'ArithmeticException, di cui si è parlato al principio di questa sezione, causata da una divisione di un numero per zero, che in certe circostanze veniva effettuata.

Per far ridurre progressivamente la potenza di un motore si è scelto di utilizzare la legge fisica del moto circolare uniformemente accelerato [8t], secondo la quale la velocità angolare ω di un corpo in un certo istante di tempo t è data dalla seguente:

ω(t) = ω0 + α(t - t0)

dove ω0 è la velocità angolare iniziale del corpo, α è la sua accelerazione angolare, e

t0 è l'istante di tempo iniziale; la posizione angolare θ del corpo all'istante di tempo t è data, invece, dalla seguente:

θ(t) = θ0 + ω0(t - t0) + 1/2*α(t - t0)2

dove θ0 è la posizione angolare iniziale del corpo.

Dal momento che nel moto circolare uniformemente accelerato l'accelerazione angolare è costante, ossia in ogni istante essa assume il medesimo valore, per calcolare quest'ultimo è sufficiente fissare un certo istante di tempo ed andare a ricavarne il valore in quel preciso istante: vediamo ora come è stato applicato quanto detto nel nostro caso. Impostando come tempo iniziale l'istante t0 pari a '0', e

considerando le due formule precedenti all'istante di tempo t, in cui sono stati percorsi i gradi desiderati e si è raggiunta la velocità obiettivo, si ha che ω(t) è uguale alla velocità obiettivo, che chiamiamo per comodità ωF, mentre θ(t) è uguale alla posizione angolare finale del motore, data dalla somma tra la sua posizione angolare iniziale e i gradi percorsi, e quindi pari alla somma di θ0 con quest'ultimi, i quali chiamiamo per comodità θP. Andando ora a sostituire questi valori nelle formule soprastanti, otteniamo le seguenti:

ωF = ω0 + α*t

θ0 + θP = θ0 + ω0*t + 1/2*α*t2

dalle quali, mediante semplice manipolazione algebrica, si ottiene la formula per determinare il valore dell'accelerazione angolare in gradi al millisecondo quadrato:

α = (ωF2 - ω02)/(2*θP)

Il valore costante dell'accelerazione angolare così ottenuto si può quindi applicare alla formula standard della velocità angolare riportata a pagina precedente, per determinare ad ogni istante di tempo il valore della medesima.

Giacché nel nostro contesto non si opera propriamente riducendo di volta in volta il valore della velocità angolare di un servomotore, ma bensì quello della potenza ad esso applicata, è stato necessario utilizzare anche la formula seguente, al fine di convertire il valore della velocità angolare effettiva del motore nel corrispondente valore di potenza da applicare ad esso, per farlo ruotare a quella velocità:

Potenza = (100 * ω(t))/0.9612

dove 0.9612 esprime la velocità angolare (in gradi al millisecondo) alla quale ruota un servomotore al quale è fornita massima potenza, ossia potenza pari a 100 [6t]. Con l'implementazione appena descritta la modalità rampdown funziona ora correttamente, permettendo la graduale diminuzione della potenza di un motore, fino a farlo arrestare, e non provocando più l'eccezione di cui era, invece, responsabile nella versione 0.9b del simulatore.

La modalità rampup impone ad un servomotore di percorrere un certo numero di gradi, accrescendo gradualmente la propria potenza iniziale, fino a toccare una determinata potenza obiettivo, specificata dalla proprietà SPEED dell'istanza di MotorData ad esso relativa. Questa modalità presentava gli stessi problemi della precedente, ed è stata ristrutturata in modo assolutamente analogo a quest'ultima.

L'unica differenza tra queste due modalità sta nel fatto che la rampdown provoca una diminuzione progressiva della potenza di un motore, mentre la rampup ne suscita un aumento graduale.

La modalità idle disabilita semplicemente qualsiasi entità di potenza per un motore, rendendolo di fatto “disoccupato”. La modalità coast prevede, invece, che il motore ruoti liberamente, senza alcun freno o potenza applicata. Queste due modalità sembrano, a prima vista, causare il medesimo comportamento di un servomotore, ma in realtà non è così. Studiando attentamente il comportamento del firmware LEGO®

[1s], si è, infatti, appreso che un motore entra in modalità idle quando è già fermo e quindi non ha alcuna potenza ad esso applicata. Quando, invece, un servomotore è in modalità coast, significa che esso è ancora in movimento e che è lasciato ruotare liberamente, un po' come accade quando si mette in folle un'automobile lanciata in corsa. Nella versione precedente del simulatore l'implementazione di queste due modalità era stata di fatto “invertita”, facendo fare alla modalità idle ciò che, invece, avrebbe dovuto fare la coast, e viceversa. Si è quindi dovuto provvedere a risolvere tale malfunzionamento, ed a raffinare qualche semplice dettaglio implementativo ad esse relativo. La modalità idle non svolge quindi alcun tipo di operazione sul servomotore in questione, mentre la coast diminuisce di una unità la potenza residua del motore, ad ogni intervento del timer per aggiornare la grafica del motore nel simulatore, fino a che il motore medesimo non si arresta.

Grazie agli aggiornamenti correttivi effettuati sulle classi MotorData, OutputPortConfigurationProperties e MotorPanel si sono risolti tutti i bug relativi alla simulazione dei servomotori, descritti all'inizio di questa sezione, ottenendo così una versione finalmente corretta e funzionante degli stessi all'interno di

NXTSimulator.