在simulink中将可变大小的数组填充到固定大小

时间:2017-09-05 02:44:16

标签: arrays matlab vector simulink pad

我对MATLAB比较熟悉,但对Simulink是新手。

我正在尝试构建一个模型,我需要(似乎需要)使用可变大小的数组,其大小随每个时间步长而变化。

考虑以下问题:

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

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

    我尝试创建一个二级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块不接受可变大小的数组作为其输入。

    一个更简单的方法我也试过涉及填充和偏移块,但问题是我无法根据模拟内部的每次指定输出向量的长度。也许我错过了什么?

    任何其他方法或建议或指导都会很棒!

    谢谢!

1 个答案:

答案 0 :(得分:0)

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

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

其他部分有点棘手。我需要修剪A并将修剪后的A连接到零数组,同时保持结果的长度为10.首先,我计算我需要修剪多少A(比如说这个长度是你)。 u可以根据AA和A的长度以及当前时间/迭代计数来计算。然后我用你在最后偏移A.由于我无法使用变量改变每个步骤的截断长度,因此我只需对截断的零件进行零填充。然后我使用这个结果数组将它分配到另一个预定义的零向量,但这一次,其长度大于10.(这部分很难搞清楚)。我认为这次的零向量必须至少是AA的长度+ A的长度。赋值的结果是零直到当前迭代计数,然后是截断的A,然后是一些长度的零。然后可以填充零,因为我们希望AA的长度为10.

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