2017-09-05 8 views
0

Je suis relativement familier avec MATLAB mais nouveau pour Simulink. J'essaye de construire un modèle où je dois (semble avoir besoin) d'employer la rangée variable-variable dont les dimensions changent avec chaque pas de temps.Rembourrage tableau de taille variable à taille fixe en simulink


Tenir compte le problème suivant:

  1. On suppose que ma simulation est de 10 secondes et mon pas de temps est fixé à 1 seconde. Ensuite, je peux construire mon tableau de temps TT = [1 2 3 4 5 6 7 8 9 10].
  2. J'ai un tableau de taille fixe A [5 6 3].
  3. Mon but est de construire un AA de réseau à chaque pas de temps de telle sorte que:

au temps = 0, AA = [5 6 3 0 0 0 0 0 0 0]
au temps = 1, AA = [0 5 6 3 0 0 0 0 0 0]
à l'instant = 2, AA = [0 0 5 6 3 0 0 0 0 0]
...
at time = 7, AA = [ 0 0 0 0 0 0 0 5 6 3]
at time = 8, AA = [0 0 0 0 0 0 0 0 5 6]
at time = 9, AA = [0 0 0 0 0 0 0 0 0 5]
at time = 10, AA = [0 0 0 0 0 0 0 0 0 0]


Quelle serait la meilleure façon d'y parvenir?

J'ai essayé de créer une fonction MATLAB S de niveau 2, en modifiant simplement un exemple donné. Voir le code ci-dessous. La fonction est juste de générer un tableau zéro qui est la taille de l'heure actuelle. Cela entraîne un tableau de taille variable.

Voici la fonction S MATLAB de niveau 2 que j'ai utilisée. J'ai seulement changé la dernière ligne du code d'exemple appelé 'expand' dans msfcndemo_varsize pour générer le tableau zéro [0 0 0 ...] au lieu de [1 2 3 4 ...].

function msfcn_varsize_expand(block) 
% Level-2 MATLAB file S-Function. 
% Takes a scalar input and outputs a vector of length indicated 
% by its input value. The output is given by 1:n where n is the input 
% value. 
% For example 
% f(5) = [1 2 3 4 5] 
% 
% The parameter defines the maximum input value allowed. 
% 
% Copyright 2009 The MathWorks, Inc. 

setup(block); 

function setup(block) 

% Register number of ports and parameters 
block.NumInputPorts = 1; 
block.NumOutputPorts = 1; 
block.NumDialogPrms = 1; 

% Setup functional port properties to dynamically inherited 
block.SetPreCompInpPortInfoToDynamic; 
block.SetPreCompOutPortInfoToDynamic; 

% Register the properties of the input port 
block.InputPort(1).Complexity  = 'Inherited'; 
block.InputPort(1).DataTypeId  = -1; 
block.InputPort(1).SamplingMode  = 'Sample'; 
block.InputPort(1).DimensionsMode = 'Fixed'; 
block.InputPort(1).DirectFeedthrough = true; 

% Register the properties of the output port 
block.OutputPort(1).DimensionsMode = 'Variable'; 
block.OutputPort(1).SamplingMode = 'Sample'; 

% Register sample times 
% [-1, 0] : Inherited sample time 
block.SampleTimes = [-1 0]; 

% Register methods called during update diagram/compilation 
block.RegBlockMethod('SetInputPortDimensions',  @SetInputPortDims); 
block.RegBlockMethod('PostPropagationSetup',  @DoPostPropSetup); 

% Register methods called at run-time 
block.RegBlockMethod('Outputs', @Outputs); 

% ------------------------------------------------------------------------- 
function SetInputDimsMode(block, port, dm) 
% Set dimension mode 
block.InputPort(port).DimensionsMode = dm; 

% ------------------------------------------------------------------------- 
function SetInputPortDims(block, idx, di) 
width = prod(di); 
if width ~= 1 
    DAStudio.error('Simulink:blocks:multirateInvaliDimension'); 
end 
% Set compiled dimensions 
block.InputPort(idx).Dimensions = di; 
block.OutputPort(idx).Dimensions =[1 block.DialogPrm(1).Data]; 

% ------------------------------------------------------------------------- 
function DoPostPropSetup(block) 
% Set the type of signal size to be dependent on input values, i.e., 
% dimensions have to be updated at output 
block.SignalSizesComputeType = 'FromInputValueAndSize'; 

% ------------------------------------------------------------------------- 
function Outputs(block) 
% Output function: 
% -update output values 
% -update signal dimensions 
block.OutputPort(1).CurrentDimensions = [1 block.InputPort(1).Data]; 
block.OutputPort(1).Data = zeros(1,block.InputPort(1).Data); 

J'utilise cette fonction pour générer les zéros dans AA qui précèdent A = [5 6 3]. L'idée était de concaténer ce tableau de zéros avec A, afin que je puisse ensuite tamponner (tronquer) le tableau résultant à la taille de TT. Mais j'ai rencontré des problèmes car le bloc de pad n'accepte pas les tableaux de taille variable comme entrée.

Une méthode plus simple J'ai aussi essayé les blocs de tampons et de déport impliqués, mais le problème était que je ne pouvais pas spécifier la longueur des vecteurs de sortie en fonction de chaque fois dans la simulation. Peut-être qu'il me manque quelque chose? Toutes les autres méthodes, suggestions ou conseils seraient excellents!

Merci!

+0

Montrez-nous votre code! Mais à partir de la description du problème, il n'est pas clair où/pourquoi vous avez un tableau de taille variable. Votre 'A = [5 6 3]' n'est pas de taille variable, pas plus que votre 'AA'. N'importe quel nombre de méthodes peut être utilisé pour générer votre 'AA' dans l'exemple que vous avez donné: Une fonction S, un bloc fonctionnel MATLAB, ... –

+0

@PhilGoddard Merci pour vos aimables commentaires! J'ai édité la question pour inclure ma fonction, qui est vraiment une seule ligne différente de la fonction de démonstration dans Simulink. Avez-vous des méthodes ou des suggestions spécifiques? –

+0

Pourquoi ne pas simplement laisser la fonction S sortir tout le vecteur 'AA'? Initialisez-le en utilisant 'A' et' n' comme paramètres, stockez 'AA' en tant qu'état, et faites simplement pivoter/déplacer les valeurs à chaque pas de temps et affichez le résultat? –

Répondre

0

J'ai trouvé moi-même la réponse. J'ai essayé d'éviter d'utiliser la fonction S autant que possible, et il me semble que je peux le faire en utilisant le bloc if/else, le bloc offset, le bloc d'affectation et le bloc pad.

Le premier if est où mon compte d'itération (ou temps) est tel que je n'ai pas besoin de couper A. Dans ce cas, je peux simplement utiliser le bloc d'affectation pour assigner A sur un tableau prédéfini de zéros.

La partie else est un peu plus compliquée.J'ai besoin de couper A et concaténer le A découpé avec le tableau zéro tout en gardant le résultat à longueur 10. D'abord, je calcule de combien j'ai besoin de couper A (disons que cette longueur est u). u peut être calculé à partir de la longueur de AA et A et compte de temps/itération en cours. Ensuite, je utilise u pour compenser A à la fin. Comme je ne peux pas faire varier la longueur tronquée pour chaque pas avec une variable, je simplifie simplement la partie tronquée. Ensuite, j'utilise ce tableau résultant pour l'assigner à un autre vecteur de zéros prédéfini, mais cette fois, dont la longueur est supérieure à 10. (Cette partie était difficile à comprendre). J'ai supposé que le vecteur zéro cette fois devait être au moins de la longueur de AA + longueur de A. Le résultat de l'assignation est zéros jusqu'à compte de l'itération actuelle, puis le A tronqué, et puis une certaine longueur de zéros. Les zéros peuvent alors être rembourrés puisque nous voulons que la longueur de AA soit 10.

Donc oui, dans mon exemple, il s'avère que je n'ai pas besoin d'utiliser la fonction S pour manipuler le tableau à chaque pas de temps. J'espère qu'éviter la fonction S et utiliser les blocs simulink me permettrait d'économiser du temps de calcul.