Matrix Blockset per Simulink: Un nuovo blockset per la Simulazione di un Sistema Dinamico a Matrici non costanti.

Leonardo Daga

Dipartimento di Informatica e Sistemistica

Università di Roma " La Sapienza"

Via Eudossiana 18 - 00184 ROMA

Email: leonardodaga@libero.it

Introduzione

Una difficoltà comune nella simulazione in ambiente Simulink di un sistema dinamico complesso, il cui modello matematico è caratterizzato da parametri non costanti, è il vincolo presente fino alla versione 1.x di poter trasportare nei collegamenti tra due blocchi solo segnali di tipo scalare o vettoriale.

Una delle notevoli innovazioni apportate dalla versione 2.0 in poi è la possibilità - in verità non molto documentata - di poter definire segnali di tipo differente dai segnali standard di Simulink. Nel Fixed-Point blockset, ad esempio, sono stati introdotti dei nuovi segnali – non compatibili con i blocchi standard – per la gestione di valori a virgola fissa in cui, oltre al valore del segnale viene trasportata l’informazione di scaling e di numero di bit di rappresentazione.

Con lo scopo di estendere le capacità del Simulink alla gestione di segnali di tipo matriciale, utilizzando una procedura analoga a quella che presumibilmente è stata utilizzata nel Fixed-Point blockset, è stato definito un nuovo tipo di dato – il tipo Matrix – e tutta un insieme di blocchi che sono utilizzati nelle operazioni su matrice.

Scopo di questo articolo è la descrizione delle tecniche di programmazione di Simulink utilizzate per la realizzazione del Matrix blockset, quindi la presentazione del blockset e dei suoi componenti. Saranno infine riportati alcuni esempi in cui viene evidenziata la potenzialità di semplificazione che il blockset potrebbe introdurre negli schemi a blocchi per la rappresentazione di sistemi dinamici. Tale semplificazione è particolarmente evidente nel caso in cui le matrici che identificano il sistema dinamico presentino delle caratteristiche di variabilità impossibili da riprodurre utilizzando i blockset di Simulink attualmente a disposizione.

La creazione di un nuovo tipo di dato in Simulink

Dalla versione 2.2 di Simulink [2] in poi è stata introdotta una nuova tipologia di funzione (livello 2) [1] nella quale una più ampia libreria di funzioni di base, soprattutto per le S-functions scritte in linguaggio C, possono essere utilizzate per ottenere migliori prestazioni e maggiori funzionalità.
Una delle funzionalità non riportate nei manuali di Simulink è la possibilità di definire dei nuovi tipi di dato. Le funzioni necessarie a tale scopo sono riportate nel file di dichiarazione simstruct.h [4] e sono parte della struttura Simstruct che viene passata come argomento a tutte le funzioni del livello 2.
In breve, la definizione di un nuovo tipo di dato, è costituita da due passi:

1. La registrazione del nome del tipo di dato: Fatta eccezione per i tipi di dato già presenti e definiti in Simulink (di base sono i 9 standard riportati nella documentazione di Simulink: double, single, int8, uint8, int16, uint16, int32, uint32, boolean), basta scegliere un nome alfanumerico qualsiasi per definire un nuovo tipo di dato. Nel caso del Matrix Blockset, è stato utilizzato il prefisso "Matrix_" per definire il nuovo tipo di dato e il suffisso codificato , ad esempio, "3x5" per indicare un dato di tipo matrice di 3 righe e 5 colonne. Nel caso in cui il nome di dato sia stato già registrato, la funzione di registrazione ritorna l’identificatore associato al dato. La sintassi della funzione di registrazione è la seguente:

int ID = ssRegisterDataType(SimStruct* S, char* dataTypeName)
in cui S è la variabile che viene passata con ogni funzione di livello 2 di Simulink, dataTypeName è il nome della variabile da registrare, ID è l’identificatore del nuovo (o già presente) tipo di dato.

2. La definizione della dimensione del dato: il collegamento tra due blocchi che utilizza il tipo di dato Matrix definito trasporta una quantità di informazioni variabile a seconda delle dimensioni della matrice. Ponendo che ogni elemento della matrice sia un valore reale (double), la quantità di memoria che Simulink deve allocare per trasportare una matrice n´ m sarà pari a n´ m´ sizeof(double). La sintassi della funzione che definisce la dimensione del dato è la seguente:

int RES = ssSetDataTypeSize(SimStruct *S, int ID, int size)
in cui S è la variabile che viene passata con ogni funzione di livello 2 di Simulink, ID è l’identificatore del tipo di dato, size è la dimensione del tipo di dato e il valore di ritorno RES riporta il successo dell’operazione di assegnazione.

3. Un ulteriore passo (opzionale) è costituito dalle funzioni:

ssSetOutputPortDataType(S, port, ID): seleziona il tipo di dato con identificatore numerico ID per la porta di uscita port associata alla S-function;
ssSetInputPortDataType(S, port, ID): seleziona il tipo di dato con identificatore numerico ID per la porta di ingresso port associata alla S-function;
ID = ssGetInputPortDataType(S, port): ritorna il tipo di dato con identificatore numerico ID presente nella porta di ingresso port associata alla S-function;
ID = ssGetOutputPortDataType(S, port): ritorna il tipo di dato con identificatore numerico ID presente nella porta di uscita port associata alla S-function;

che sono necessarie per associare o per verificare il tipo di dato ad una porta di uscita o di ingresso.

Le funzioni qui riportate sono solo un sotto insieme di quelle realmente disponibili e incluse nel file di definizione Simstruct.h per cui, per maggiori approfondimenti sull’argomento, è necessario esplorare la serie di commenti presenti nel file a tal proposito [4].

Sempre a proposito della definizione di nuovi tipi di dato, è necessario ricordare che, con poche eccezioni, i componenti base di Simulink (ad es.: i guadagni matriciali, i componenti lineari, le sorgenti, gli integratori) non accettano in ingresso alcun tipo di dato se non i tipi definiti di base di Simulink. E’ quindi necessario definire dei convertitori di dato per poter usufruire degli strumenti dell’analisi vettoriale, analogamente a quanto fatto per il Fixed-Point Blockset nei blocchi di tipo Gateway.

Il Matrix Blockset per Simulink.

Ogni componente del blockset è stato realizzato tramite una S-function scritta in C. L’insieme dei blockset realizzato è costituito dai componenti fondamentali necessari per la costruzione degli algoritmi di base che utilizzano matrici variabili. E’ previsto lo sviluppo di ulteriori blocchi previsti prima della prima release del blockset, soprattutto per le funzionalità legate al calcolo in virgola fissa, per la compatibilità con il Real-Time Workshop e per il calcolo delle norme di matrici. Una versione beta della libreria sarà presto disponibile su web, all’indirizzo http://digilander.iol.it/LeoDaga insieme ad un breve manuale e ad alcuni esempi di utilizzazione del blockset.
 
Nella lista che segue sono elencati i principali componenti del Matrix Blockset:
wpe2.jpg (1632 byte)
Creazione di una matrice. Equivale al blocco Constant presente nella libreria Sources di Simulink. E’ possibile definire come matrice sorgente una qualsiasi espressione in formato Matlab, anche appartenente al workspace di Matlab.
wpe3.jpg (1489 byte)
Estrae un elemento dato da una o più matrici, purchè queste siano delle stesse dimensioni e compatibili con l’elemento da estrarre.
wpe4.jpg (1663 byte)
Moltiplica due matrici di dimensioni compatibili, dando come risultato la matrice prodotto le cui dimensioni sono compatibili con quelle fornite come parametro.
wpe5.jpg (1515 byte)
Estrae la trasposta di una matrice, dando come risultato una matrice di dimensioni compatibili con quelle fornite come parametro
wpe6.jpg (1653 byte)
Guadagno scalare su una matrice in ingresso, le cui dimensioni devono essere compatibili con quelle fornite come parametro
wpe7.jpg (1545 byte)
Somma due matrici di dimensioni compatibili, dando come risultato la matrice somma le cui dimensioni sono compatibili con quelle fornite come parametro. E’ possibile sommare più di due matrici contemporaneamente indicando in numero di addendi dato come parametro.
wpe8.jpg (1358 byte)
Determinante della matrice data come ingresso. Ritorna un valore scalare.
wpe9.jpg (1511 byte)
Inversa della matrice data come ingresso. La matrice in ingresso deve essere quadrata, delle dimensioni indicate come parametro.
wpeA.jpg (1575 byte)
Blocco che esegue la definizione di uno o più elementi di una matrice. La matrice viene fornita come primo ingresso, mentre i valori da definire vengono inseriti nelle altre porte insieme al valore di riga e colonna in cui devono essere collocati.
wpeB.jpg (1718 byte)
Blocco da utilizzare come input del blocco MxSet. Accetta in ingresso un valore che deve essere utilizzato per modificare un elemento della matrice in ingresso al blocco MxSet. Come parametri devono essere indicati i valori di riga e colonna dell’elemento della matrice da modificare. Restituisce 3 valori in un vettore, così organizzati: [valore, riga, colonna].
wpeC.jpg (1681 byte)
Analogamente al blocco Memory della libreria Continuous di Simulink, memorizza il valore di una matrice restituendolo al ciclo successivo. Il valore iniziale del restituito dal blocco viene fornito come parametro. Le dimensioni della matrice di ingresso e di uscita devono essere conformi alle dimensioni della matrice definita come condizione iniziale.
wpeD.jpg (1832 byte)
Esegue il prodotto di una matrice (primo ingresso) per uno o più vettori (gli altri ingressi) riportando separatamente i risultati in uscita. Le dimensioni della matrice in ingresso devono essere definite da parametro. I vettori in ingresso sono dei vettori di double nativi di Simulink.
 

Esempi di utilizzazione del Matrix Blockset

I componenti del Matrix Blockset si rendono particolarmente utili nel caso in cui il sistema da simulare e da rappresentare sia composto da una o più matrici i cui componenti sono funzione del tempo.

Sia dato il caso, ad esempio, della rappresentazione nello spazio di stato di un sistema del tipo

(Eq. 1)         T(s) = C (sI – A(t))-1 B + D

in cui la matrice dello stato A(t) sia funzione del tempo secondo una relazione matriciale del tipo:

(Eq. 2)         A(t) = A0 * D (t) = A0 *[1, d(1), d(2); 0, 1, d(3); 0, 0, 1] ;

Posto che sia possibile definire in Simulink le funzioni scalari di(t), l’unico modo che è attualmente a disposizione per definire uno schema a blocchi Simulink in grado di compiere tale operazione è creare uno schema a blocchi come in figura 1, in cui il blocco nominato A(t) è realizzato per mezzo di una S-function.

figura 1: Rappresentazione nello spazio di stato di un sistema dinamico con matrice di stato funzione del tempo.

Per mezzo del Matrix Blockset è possibile realizzare la funzione (1) senza ricorrere alla costruzione di una S-function, quest’ultima operazione – tutto sommato – non semplicissima da realizzare e comunque estranea alla concezione di strumento visuale tipica del Simulink. Nella figura 2 è mostrato lo schema a blocchi realizzato dal Matrix Blockset che realizza la funzione (1).

figura 2: Costruzione della matrice A(t) funzione dei tre parametri d1, d2, d3.

Nella figura 2 sono stati evidenziati i tipi in uscita dei blocchi. Ogni blocco appartenente al Matrix Blockset è stato contrassegnato con i caratteri "MX" in basso a destra. Ognuno dei componenti riportati nella figura 2 sono illustrati nella tabella del paragrafo precedente.

Per meglio comprendere le potenzialità del blockset, si consideri il problema di realizzare un filtro di Kalman iterativo, le cui equazioni sono date nella tabella che segue.

Tabella 2: Equazioni del filtro di Kalman iterativo

Dati di ingresso

F k, Ck, Qk, Rk, zk (misura da filtrare), P , x

Aggiornamento della matrice di guadagno

Kk = P× C (Ck P C + Rk)-1

Aggiornamento della matrice di covarianza dello stato

Pk = (I - Kk Ck) P

Correzione dello stato stimato in funzione della misura acquisita

xk = x + Kk(zk - Ck× x)

Stima del prossimo stato

xk+1 = F k xk

Estrapolazione di Pk

Pk+1 = Qk + F k Pk F

Memorizzazione per lo step successivo

x = xk+1 ; P = Pk+1

Il blocco che corrisponde a tali operazioni è rappresentato in figura 3.I valori iniziali P , x corrispondono allo stato iniziale dei blocchi di memoria Pk- e xk- riportati nella parte in basso della figura. Il filtro ha come ingresso i quattro parametri del filtro Fk, Ck, Qk, Rk, più la misura zk. Un esempio di realizzazione per mezzo del Matrix Blockset del blocco che effettua l’aggiornamento della matrice di covarianza Pk dello stato è riportato in figura 4

figura 3: Interno del filtro di Kalman con numero di variabili di stato e misurate pari rispettivamente a 6 e 2, realizzato con il Matrix Blockset

figura 4: Interno del filtro di Kalman con numero di variabili di stato e misurate pari rispettivamente a 6 e 2, realizzante l’operazione Kk = P× C (Ck P C + Rk)-1

Per realizzare uno strumento analogo in Simulink sarebbe stato necessario costruire un S-function [1] scritta in linguaggio Matlab, con ovvi problemi di non semplicità della gestione degli eventi della S-function e di lentezza della simulazione risultante. Una S-function scritta in linguaggio C ha l’ovvio problema di rendere molto complessa la stesura degli algoritmi di calcolo matriciale, o, in caso di utilizzo del MATLAB Engine, di gestione dei puntatori contenente le matrici manipolate. Inoltre, il filtro di Kalman realizzato come in figura 3 rende facilmente accessibile la possibilità di parametrizzare totalmente l’intero blocco, comprese le dimensioni della matrice Pk e dello stato xk.

Conclusioni

In questo articolo è stata evidenziata la mancanza di uno strumento fondamentale come quello del calcolo matriciale in uno degli ambienti di simulazione visuale più evoluti attualmente in commercio ed è stata proposta una semplice soluzione a tale mancanza. La soluzione si chiama Matrix Blockset e si pone come alternativa importante alla realizzazione delle stesse funzionalità per mezzo di metodi classici (S-function in linguaggio Matlab o C) soprattutto per la sua semplicità di utilizzo. Alcuni esempi sono stati portati a dimostrazione delle potenzialità del nuovo strumento.

Lo sviluppo logico di questo blockset sarà l’ampliamento del numero di blocchi disponibili, la compatibilità con altri blockset fondamentali quali il Fixed-Point Blockset, e la compatibilità con il Real-Time Workshop attraverso la realizzazione della versione per il Target Language Compiler.

Riferimenti

[1] AA. VV. , 'Simulink, Writing S-functions', ver 3.0, The Mathworks, October 1998.

[2] AA. VV. , 'Simulink, Using Simulink', ver 3.0, The Mathworks, January 1999.

[3] AA. VV. , 'Matlab, The User Guide', The Mathworks 1996.

[4] AA. VV. , /Matlab5/Simulink/Include/Simstruc.h, Release 1.121, 29/01/1999.

Leonardo Daga's Warehouseâ, http://leonardodaga.insyde.it
Send any Comments to: leonardo.daga@gmail.com