L'obiettivo di questa parte è sviluppare un piccolo sistema software di simulazione e controllo per sistemi lineari tempo-invarianti single-input single-output (SISO).
Questa funzione simula il sistema dinamico siso per il tempo specificato dt.
Il sistema siso ha una dinamica del tipo:
dx = a * x + b * u
dove
xè lo stato del sistemauè il controllo del sistemadxè la derivata di x rispetto al tempoaè il coefficiente dello statobè il coefficiente del controllo
Dato che si tratta di sistemi SISO, tutti i valore nella lista sopra sono scalari (di tipo double).
Per simulare il sistema useremo un metodo di integrazione numerica molto semplice: Eulero esplicito.
Dato lo stato corrente x[n] e la sua derivata dx[n], il metodo di Eulero calcola il valore dello stato al prossimo istante discreto n+1 come:
x[n+1] = x[n] + dt * dx[n]
dove dt è la durata del passo di integrazione.
Se dt non è specificato si deve assumere il valore 0.1.
Il controllore da implementare è di tipo Proporzionale-Integrale (PI), ovvero:
u = - kp * x - ki * integral(x)
dove
kpè il guadagno proporzionale (zero se non specificato)kiè il guadagno integrale (zero se non specificato)integral(x)è l'integrale di x
L'integrale di x al passo di integrazione n può essere approssimato con il metodo di Eulero:
x[0]*dt + x[1]*dt + ... + x[n-1]*dt + x[n]*dt
dove dt è la durata del passo di integrazione.
Se dt non è specificato si deve assumere il valore 0.1.
Questa funzione filtra la traiettoria specificata usando una finestra mobile della dimensione specificata window_size.
Il filtraggio consiste nel sostituire l'elemento i-esimo della traiettoria con la media
degli elementi attorno all'i-esimo. Se window_size==3 allora l'elemento i-esimo sarà dato
dalla media degli elementi in posizione i-1, i ed i+1.
Se window_size non dovesse essere un numero dispari, allora il metodo deve comportarsi come se fosse stato chiamato con un valore
uguale a window_size+1.
Se window_size non è specificato si deve assumere il valore 3.
Per i primi e gli ultimi elementi della traiettoria, per i quali non sono disponibili tutti i valori nella finestra, l'algoritmo deve limitarsi a calcolare la media tra i valori disponibili. Si fa riferimento ai test per maggiori chiarimenti sul comportamento atteso.
Funzione per simulare il sistema ad anello chiuso usando le funzioni pi_control e simulate.
In questa parte del compito lo studente deve implementare le funzioni pi_control, simulate e simulate_closed_loop per dei sistemi multi-input multi-output (MIMO).
Queste funzioni hanno le stesse funzionalità descritte sopra, ma questa volta:
xeusono vettoriA,B,KpeKisono matrici In C++, vettori e matrici sono tipicamente rappresentati medianti array. Le matrici devono essere salvate in memoria per riga (ordine row-major).
La dimensioni di questi vettori e matrici non sarà nota a tempo di compilazione, quindi non possono essere usati array statici.
Lo studente dovrà servirsi di array dinamici, allocando la memoria con l'operatore new e deallocandola non appena possibile
con l'operatore delete. La corretta gestione della memoria non è verificata esplicitamente dai test forniti,
ma sarà presa in considerazione nella valutazione del compito.
Oltre alle tre funzioni menzionate sopra, lo studente dovrà anche implementare le funzioni multiply e sum per eseguenre le operazioni di
moltiplicazione matrice-vettore e di somma tra vettori.
Queste funzioni saranno utili per l'implementazione di pi_control e simulate.
Allo scopo di ridurre il numero di parametri delle funzioni e di migliorarne l'usabilità, introduciamo le strutture Vector e Matrix.
Lo studente deve quindi implementare le nuove versioni delle funzioni multiply, sum, pi_control, simulate e simulate_closed_loop.
Per semplificare l'operazione ricorrente di creazione di Vector e Matrix, abbiamo anche aggiunto le funzioni create_vector e
create_matrix.
L'obiettivo di questa parte è sviluppare un piccolo libreria di algebra lineare, che servirà poi per lo sviluppo della Parte 2 del compito.
La libreria consiste principalmente in due classi: Vector e Matrix, entrambe classi derivate di MatrixBase.
Le matrici devono essere salvate in memoria per riga (ordine row-major).
In queste classi lo studente dovrà utilizzare:
- INCAPSULAMENTO: per assicurarsi che i dati degli oggetti non siano modificabili dall'esterno lasciando l'oggetto in uno stato inconsistente (ad es: modificando il puntatore alla memoria contenente i dati della matrice/vettore)
- EREDITARIETÀ: le classi
VectoreMatrixdovranno certamente essere simili e condividere grossa parte del loro codice; per evitare di riscrivere lo stesso codice lo studente dovrà sfruttare l'ereditarietà. - OPERATOR OVERLOADING: per rendere la libreria più facilmente utilizzabile, le operazioni tra vettori e matrici devono essere implementate tramite operatori come: =, +, *, -, +=, -=
L'obiettivo di questa parte è implementare una semplice libreria per la simulazione di sistemi dinamici lineari e controllori lineari, basata sulla libreria di algebra lineare della prima parte.
Le classi principali di questa parte sono: Controller e Simulator.
Questa classe simula un sistema dinamico MIMO. Il sistema MIMO ha una dinamica lineare tempo-invariante del tipo:
x[n+1] = A * x[n] + B * u[u]
dove
x[n]è il vettore di stato del sistema all'istante nu[n]è il vettore di controllo del sistema all'istante nx[n+1]è il vettore di stato del sistema all'istante n+1Aè la matrice di transizione di statoBè la matrice di controllo
La classe Simulator deve permettere di:
- leggere/scrivere le matrici A e B
- cambiare lo stato corrente del sistema
- simulare un passo del sistema dato il vettore di controllo
Questa classe implementa un controllore lineare del tipo:
u[n] = K * x[n]
dove
x[n]è il vettore di stato del sistema all'istante nu[n]è il vettore di controllo del sistema all'istante nKè la matrice dei guadagni