2017-09-05 92 views
0

我对MATLAB比较熟悉,但是对Simulink来说是新的。在simulink中将可变大小的数组填充到固定大小

我想建立一个模型,我需要(似乎需要)使用可变大小的数组,其尺寸因时间步长而异。


考虑以下问题:

  1. 假设我的模拟长为10秒和我的时间步长固定为1秒。然后我可以构造我的时间数组TT = [1 2 3 4 5 6 7 8 9 10]。
  2. 我有一个固定大小的数组A [5 6 3]。
  3. 我的目标是在每个时间步骤,使得以构成阵列AA:

在时间= 0,AA = [5 6 3 0 0 0 0 0 0 0]
在时间= 1,在时间= 2时,AA = [0 5 6 3 0 0 0 0 0 0]
,AA = [0 0 5 6 3 0 0 0 0 0]
...
在时间=在时间= 8时,AA = [0 0 0 0 0 0 0 5 6]
,AA = [0 0 0 0 0 0 0 0] 0 0 0 0 0 0 0 5 6 3]
0 5]
at time = 10,AA = [0 0 0 0 0 0 0 0 0 0]


什么是最简单的方法来实现这一目标?

我试着创建一个2级MATLAB S函数,只是调整给定的例子。见下面的代码。该函数只是生成一个当前时间大小的零数组。这导致可变大小的数组。

这是我使用的2级MATLAB S函数。我只更改了msfcndemo_varsize中示例代码“expand”的最后一行,以生成零数组[0 0 0 ...]而不是[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); 

我正在使用此函数生成AA中的零,它将在A = [5 6 3]之前生成。这个想法是将这个零数组与A连接起来,这样我就可以将结果数组填充到TT的大小。但是我遇到了问题,因为垫块不接受可变大小的数组作为其输入。

一个更简单的方法我也尝试过使用pad和offset块,但问题是我无法根据模拟中的每次指定输出向量的长度。也许我错过了什么?

任何其他方法或建议或指导将是伟大的!

谢谢!

+0

向我们展示您的代码!但是从问题描述来看,并不清楚你在哪里/为什么有一个可变大小的数组。你的'A = [5 6 3]'不是可变大小的,你的'AA'也不是。可以使用任意数量的方法在您给出的特定示例中生成您的“AA”:一个S函数,一个MATLAB函数块,... –

+0

@PhilGoddard感谢您的好评!我已经编辑了这个问题来包含我的函数,这个函数实际上只是与Simulink中的演示函数不同的一行。你有什么具体的方法或建议? –

+0

为什么不只是S函数输出整个'AA'矢量?使用'A'和'n'作为参数对其进行初始化,将'AA'作为一个状态存储,并且只需在每个时间步进行旋转/移位并输出结果? –

回答

0

我自己找到答案。我尽量避免使用S函数,看来我可以使用if/else块,偏移块,赋值块和填充块。

第一个if如果我的迭代计数(或时间)是这样的,我不需要修剪A.在这种情况下,我可以简单地使用赋值块将A分配到预定义长度为10的零数组上。

其他部分有点棘手。我需要修剪A AND并将修剪过的A与零数组连接起来,同时保持结果长度为10.首先,我计算需要修剪多少A(例如,这个长度是u)。可以从AA和A的长度以及当前时间/迭代计数来计算u。然后我用你最后抵消A.由于我无法通过变量改变每个步骤的截断长度,因此我只是简单地填充截断的部分。然后我使用这个结果数组将其分配到另一个预定义的零矢量,但是这次,它的长度大于10.(这部分很难理解)。我认为这次的零向量必须至少是AA的长度+ A的长度。赋值的结果是零直到当前迭代计数,然后是截断的A,然后是一些零的长度。因为我们希望AA的长度为10,所以零可以被填充掉。

所以,在我的例子中,事实证明,我不需要使用S函数在每个时间步操作数组。我希望避免使用S函数并使用simulink块会节省一些计算时间。