s function

randolf2022年6月6日
大约 17 分钟

s function

S Function

定义

S-functions (system-function) provide a mechanism for extending the capability of simulink environment using the mex utility.

S-function 定义了在仿真环境中一个 block 是如何执行的,包含:initialization, update, derivates, output 和 termination. 在其中的每一个步骤,simulink engine 都会调用一个 method 去实现具体的细节。

首先,为了理解 s function 怎么工作的,可以参考 simulink 执行细节

一个 Simulink 模块可以认为有以下成分组成:

  • 输入集合
  • 状态集合
  • 参数集合
  • 输出集合

可以表示成下面的数学形式:

其中 是系统状态, 是系统输入, 是系统输出。

仿真阶段分析

可以参考 simulink 执行细节

S Function 回调函数

在 simulink 仿真过程中,会执行不同的回调函数,可以分类为下列部分:

  • 编译阶段: Simulink engine 初始化 s function
    • 将库块合并到模型中,并传播信号宽度、数据类型和样本时间
    • 设置输入输出端口数量和维度
    • 计算模块参数,分配模块内存
  • 计算输出阶段
    • 计算系统输出,满足所有输出端口的条件,使得下次仿真正常执行
  • 更新离散状态
    • 更新系统的模块状态
  • 初始化和终止方法
    • 这些可选方法只执行一次 S-function 所需的初始化和终止活动。初始化活动可能包括设置用户数据,或在 s 函数中初始化状态向量。终止方法执行诸如在终止仿真或从模型中删除 S-function 块时所需的内存释放等任何操作
  • 集成部分
    • 这适用于具有连续状态和/或非抽样零交叉的模型。如果你的 s 函数有连续的状态,引擎在小的时间步上调用你的 s 函数的输出和导数部分。这样求解器就可以计算 s 函数的状态。如果您的 s 函数具有非采样的零交叉点,引擎也会在较小的时间步骤中调用 s 函数的输出和零交叉点部分,以便它可以定位零交叉点。

更细致的结构可以参考 S-Function Conceptsopen in new window

此外,需要注意 s function 与其余实现方式的区别,参考下表:

Compare and contrast features supported by different types of S-function implementations.

S-Function Features

The following tables give overviews of the features supported by different types of S-functions. The first table focuses on handwritten S-functions. The second table compares the features of S-functions automatically generated by the S-Function Builder or Legacy Code Tool.

Features of Hand-Written S-Functions

FeatureLevel-1 MATLAB S-FunctionLevel-2 MATLAB S-FunctionHandwritten C MEX S-Function
Data typesSupports signals with a data type of double.Supports any data type supported by Simulink® software, including fixed-point types.Supports any data type supported by Simulink software, including fixed-point types.
Numeric typesSupports only real signals.Supports real and complex signals.Supports real and complex signals.
Frame supportDoes not support frame-based signals.Supports framed and unframed signals.Supports framed and unframed signals.
Port dimensionsSupports vector inputs and outputs. Does not support multiple input and output ports.Supports scalar, 1-D, and multidimensional input and output signals.Supports scalar, 1-D, and multidimensional input and output signals.
S-function APISupports only mdlInitializeSizes, mdlDerivatives, mdlUpdate, mdlOutputs, mdlGetTimeOfNextVarHit, and mdlTerminate.Supports a larger set of the S-function API. See Level-2 MATLAB S-Function Callback Methods for a list of supported methods.Supports the entire S-function API.
Code generation supportDoes not support code generation.Requires a handwritten TLC file to generate code.Natively supports code generation. Requires a handwritten TLC file to inline the S-function during code generation.
Simulink Accelerator modeRuns interpretively and is, therefore, not accelerated.Provides the option to use a TLC file in Accelerator mode, instead of running interpretively.Provides the option to use a TLC or MEX file in Accelerator mode.
Model referenceCannot be used in a referenced model.Supports Normal and Accelerator mode simulations when used in a referenced model. Requires a TLC file for Accelerator mode.Provides options for sample time inheritance and Normal mode support when used in a referenced model. See Model Reference Requirements and Limitations
Simulink.
AliasType
and Simulink.
NumericType
support
Does not support these classes.Supports Simulink. NumericType and Simulink. AliasType classes (see Configure Custom Data Types).Supports all of these classes (see Configure Custom Data Types).
Bus input and output signalsDoes not support bus input or output signals.Does not support bus input or output signals.Supports nonvirtual bus input or output signals.
Tunable and run-time parametersSupports tunable parameters during simulation. Does not support run-time parameters.Supports tunable and run-time parameters.Supports tunable and run-time parameters.
Work vectorsDoes not support work vectors.Supports DWork vectors (see Using DWork Vectors in Level-2 MATLAB S-Functions).Supports all work vector types (see Types of DWork Vectors).

Features of Automatically Generated S-Functions

FeatureS-Function BuilderLegacy Code Tool
Data typesSupports any data type supported by Simulink software, including fixed-point types.Supports all built-in data types. To use a fixed-point data type, you must specify the data type as a Simulink.NumericType. You cannot use a fixed-point type with unspecified scaling.
Numeric typesSupports real and complex signals.Supports complex signals only for built-in data types.
Frame supportSupports framed and unframed signals.Does not support frame-based signals.
Port dimensionsSupports scalar, 1-D, and multidimensional input and output signals.Supports scalar, 1-D, and multidimensional input and output signals.
S-function APISupports creation of custom mdlInitializeSizes, mdlInitializeSampleTimes, mdlDerivatives, mdlUpdate, and mdlOutputs. Also allows for automatic generation of mdlStart and mdlTerminate.Supports mdlInitializeSizes, mdlInitializeSampleTimes, mdlStart, mdlInitializeConditions, mdlOutputs, and mdlTerminate.
Code generation supportNatively supports code generation. Also, automatically generates a TLC file for inlining the S-function during code generation.Natively supports code generation optimized for embedded systems. Also, automatically generates a TLC file that supports expression folding for inlining the S-function during code generation.

Simulink Accelerator™ mode

Uses a TLC file in Accelerator mode, if the file was generated. Otherwise, uses the MEX file.Provides the option to use a TLC or MEX file in Accelerator mode.
Model referenceUses default behaviors when used in a referenced model.Uses default behaviors when used in a referenced model.
Simulink.AliasType and Simulink.NumericTypeDoes not support these classes.Supports Simulink.AliasType and Simulink.NumericType.
Bus input and output signalsSupports bus input and output signals. See sfbuilder_bususage for an example.Supports bus input and output signals. You must define a Simulink.Bus object in the MATLAB® workspace that is equivalent to the structure of the input or output used in the legacy code. Does not support bus parameters.
Tunable and run-time parametersSupports tunable parameters only during simulation. Supports run-time parameters.Supports tunable and run-time parameters.
Work vectorsDoes not provide access to work vectors.Supports DWork vectors with the usage type SS_DWORK_USED_AS_DWORK. See Types of DWork Vectors for a discussion on the different DWork vector usage types.

S-Function Limitations

The following table summarizes the major limitations of the different types of S-functions.

ImplementationLimitations
Level-1 MATLAB S-functionDoes not support the majority of S-function features. See the S-Function Features and Limitations section for information on what features a Level-1 MATLAB S-function does support.
Level-2 MATLAB S-functions
  • Does not support bus input and output signals.

  • Cannot incorporate legacy code during simulation, only during code generation through a TLC file.

Handwritten C MEX S-functionSupports model reference with some limitations. See S-Functions in Referenced Models.
S-Function Builder
  • Generates S-function code using a wrapper function which incurs additional overhead.

  • Does not support the following S-function features:

    • Work vectors

    • Port-based sample times

    • Multiple sample times or a nonzero offset time

    • Dynamically-sized input and output signals for an S-function with multiple input and output ports

Note

S-functions with one input and one output port can have dynamically-sized signals

Legacy Code Tool
  • Generates C MEX S-functions for existing functions written in C or C++ only. The tool does not support transformation of MATLAB or Fortran functions.

  • Can interface with C++ functions, but not C++ objects.

  • Does not support simulating continuous or discrete states.

  • Does not support use of function pointers as the output of the legacy function being called.

  • Always sets the S-function's flag for direct feedthrough (sizes.DirFeedthrough) to true.

  • Supports only the continuous, but fixed in minor time step, sample time and offset option.

  • Supports complex numbers, but only with Simulink built-in data types.

  • Does not support the following S-function features:

    • Work vectors, other than general DWork vectors

    • Frame-based input and output signals

    • Port-based sample times

    • Multiple block-based sample times

可以发现,建议使用 level-2 s-function。

实现 S-function

基本介绍

参考: Write Level-2 MATLAB S-Functions - MATLAB & Simulink (mathworks.com)open in new window

需要注意,实现 s-function (level-2) 在细节上有很多和实现 C MEX s-function 接近,因此也可以参考 C MEX 的实现方式。

为了实现 s-function (level-2) 的功能,matlab 将一个运行时对象作为参数传送到回调方法中。运行时对象实际上充当了 matlab 的 s-function 模块代理,使其能够在仿真期间设置、访问模型属性。

在 simulink engine 调用 level-2 的 s-function 回调函数时,它将一个 Simulink.MSFcnRunTimeBlockopen in new window 类的实例作为运行时对象传递给回调函数 (和 CMEX s function 的 SimStruct 结构体作用类似)。注意,运行时对象不支持 matlab sparse matrices,因此 speye 等函数不支持使用。

note

collapse: open title: Note Other MATLAB programs besides MATLAB S-functions can use run-time objects to obtain information about a MATLAB S-function in a model that is simulating. See Access Block Data During Simulationopen in new window in Using Simulink for more information.

从模板开始

使用 Level-2 MATLAB S-function template `msfuntmpl_basic ,其中带有较多的注释。

参考 Level-2 MATLAB S-Function Callback Methodsopen in new window 后,逐步介绍如何完成一个 s function。

模型可以参考 [msfcndemo_sfundsc2](assets/msfcndemo_sfundsc2](./assets/msfcn_unit_delay.m) :

模型 Setup

  • 修改运行时对象的属性:NumInputPortsNumOutputPorts 为 1 来实现 1 in 1 out。

  • 调用运行时对象的方法: SetPreCompInpPortInfoToDynamicopen in new windowSetPreCompOutPortInfoToDynamicopen in new window SetPreCompOutPortInfoToDynamicopen in new window 来表明输入输出 ports 从模型继承编译的属性,比如数据类型,数据维度,采样率等。

  • 设置运行时对象的 InputPortDirectFeedthrough 属性为 false,表明输入 port 没有直接的反馈输入。为所有其余的输入输出 port 的属性保留原样,并为 Dimensions、DatatypeID 和 Complexity 属性设置的值覆盖使用 SetPreCompInpPortInfoToDynamic 和 SetPreCompOutPortInfoToDynamic 方法继承的值。

  • 设置 NumDialogPrms 属性为 1 来初始化 s function 的的 dialog parameter。

  • 设置 SampleTimes 属性为 [-1, 0] 来继承采样时间。关于采样时间,可以参考 采样时间类型

  • 调用 RegBlockMethod 方法来注册下列回调函数

    • PostPropagationSetup

    • InitializeConditions

    • Outputs

    • Update

      将模板中其余注册的回调函数删除。此外,在调用 RegBlockMethod 方法时,第一个参数是 s function API method 的名字,第二个输入参数是对应本地处理这些函数的名字,比如 block.RegBlockMethod('PostPropagationSetup',@DoPostPropSetup);

    下面这是一个初始化的例子,来源于 `msfcn_unit_delay

    function setup(block)
    
    %% Register a single dialog parameter
    block.NumDialogPrms  = 1;
    
    %% Register number of input and output ports
    block.NumInputPorts  = 1;
    block.NumOutputPorts = 1;
    
    %% Setup functional port properties to dynamically
    %% inherited.
    block.SetPreCompInpPortInfoToDynamic;
    block.SetPreCompOutPortInfoToDynamic;
    
    %% Hard-code certain port properties(choose from this and upper one)
    block.InputPort(1).Dimensions        = 1;
    block.InputPort(1).DirectFeedthrough = false;
    
    block.OutputPort(1).Dimensions       = 1;
    
    %% Set block sample time to [0.1 0]
    block.SampleTimes = [0.1 0];
    
    %% Register methods
    block.RegBlockMethod('PostPropagationSetup',@DoPostPropSetup);
    block.RegBlockMethod('InitializeConditions',@InitConditions);
    block.RegBlockMethod('Outputs',             @Output);  
    block.RegBlockMethod('Update',              @Update);  
    

    如果 s function 需要连续状态,使用 NumContStates 知名连续状态的数目,离散状态不需要这个。

需要注意,如果使用的s function 作为源信号输出,那么需要指定其输出模式,是采样信号输出还是帧输出。可以参考 Sample- and Frame-Based Concepts - MATLAB & Simulink (mathworks.com)open in new window

具体代码参考如下:

block.OutputPort(1).SamplingMode = 'Sample'; % sample mode
block.OutputPort(1).SamplingMode = 'Frame'; % frame mode

关于 Frame 模式参考 sfundemos 下 matlab s fucntion 中的 Frame signals

我自己实现的输出常值信号的代码如下:

function msfuntmpl_basic(block)
%MSFUNTMPL_BASIC A Template for a Level-2 MATLAB S-Function
%   The MATLAB S-function is written as a MATLAB function with the
%   same name as the S-function. Replace 'msfuntmpl_basic' with the 
%   name of your S-function.

%   Copyright 2003-2018 The MathWorks, Inc.

%%
%% The setup method is used to set up the basic attributes of the
%% S-function such as ports, parameters, etc. Do not add any other
%% calls to the main body of the function.
%%
setup(block);

%endfunction

%% Function: setup ===================================================
%% Abstract:
%%   Set up the basic characteristics of the S-function block such as:
%%   - Input ports
%%   - Output ports
%%   - Dialog parameters
%%   - Options
%%
%%   Required         : Yes
%%   C MEX counterpart: mdlInitializeSizes
%%
function setup(block)

% Register number of ports
block.NumInputPorts  = 0;
block.NumOutputPorts = 1;

% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Override input port properties
% block.InputPort(1).Dimensions        = 1;
% block.InputPort(1).DatatypeID  = 0;  % double
% block.InputPort(1).Complexity  = 'Real';
% block.InputPort(1).DirectFeedthrough = true;

% Override output port properties
block.OutputPort(1).Dimensions       = 1;
block.OutputPort(1).DatatypeID  = 0; % double
block.OutputPort(1).Complexity  = 'Real';

block.OutputPort(1).SamplingMode = 'Sample';

% Register parameters
block.NumDialogPrms     = 1;

% Register sample times
%  [0 offset]            : Continuous sample time
%  [positive_num offset] : Discrete sample time
%
%  [-1, 0]               : Inherited sample time
%  [-2, 0]               : Variable sample time
block.SampleTimes = [0 0];

% Specify the block simStateCompliance. The allowed values are:
%    'UnknownSimState', < The default setting; warn and assume DefaultSimState
%    'DefaultSimState', < Same sim state as a built-in block
%    'HasNoSimState',   < No sim state
%    'CustomSimState',  < Has GetSimState and SetSimState methods
%    'DisallowSimState' < Error out when saving or restoring the model sim state
block.SimStateCompliance = 'DefaultSimState';

%% -----------------------------------------------------------------
%% The MATLAB S-function uses an internal registry for all
%% block methods. You should register all relevant methods
%% (optional and required) as illustrated below. You may choose
%% any suitable name for the methods and implement these methods
%% as local functions within the same file. See comments
%% provided for each function for more information.
%% -----------------------------------------------------------------

% block.RegBlockMethod('PostPropagationSetup',    @DoPostPropSetup);
% block.RegBlockMethod('InitializeConditions', @InitializeConditions);
% block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs);     % Required
% block.RegBlockMethod('Update', @Update);
% block.RegBlockMethod('Derivatives', @Derivatives);
% block.RegBlockMethod('Terminate', @Terminate); % Required

%end setup

%%
%% PostPropagationSetup:
%%   Functionality    : Setup work areas and state variables. Can
%%                      also register run-time methods here
%%   Required         : No
%%   C MEX counterpart: mdlSetWorkWidths
%%
% function DoPostPropSetup(block)
%   block.NumDworks = 1;
  
%   block.Dwork(1).Name            = 'x1';
%   block.Dwork(1).Dimensions      = 1;
%   block.Dwork(1).DatatypeID      = 0;      % double
%   block.Dwork(1).Complexity      = 'Real'; % real
%   block.Dwork(1).UsedAsDiscState = true;


%%
%% InitializeConditions:
%%   Functionality    : Called at the start of simulation and if it is 
%%                      present in an enabled subsystem configured to reset 
%%                      states, it will be called when the enabled subsystem
%%                      restarts execution to reset the states.
%%   Required         : No
%%   C MEX counterpart: mdlInitializeConditions
%%
% function InitializeConditions(block)

%end InitializeConditions


%%
%% Start:
%%   Functionality    : Called once at start of model execution. If you
%%                      have states that should be initialized once, this 
%%                      is the place to do it.
%%   Required         : No
%%   C MEX counterpart: mdlStart
%%
% function Start(block)

% block.Dwork(1).Data = 0;

%end Start

%%
%% Outputs:
%%   Functionality    : Called to generate block outputs in
%%                      simulation step
%%   Required         : Yes
%%   C MEX counterpart: mdlOutputs
%%
function Outputs(block)

block.OutputPort(1).Data = block.DialogPrm(1).Data;

%end Outputs

%%
%% Update:
%%   Functionality    : Called to update discrete states
%%                      during simulation step
%%   Required         : No
%%   C MEX counterpart: mdlUpdate
%%
% function Update(block)

% block.Dwork(1).Data = block.InputPort(1).Data;

%end Update

%%
%% Derivatives:
%%   Functionality    : Called to update derivatives of
%%                      continuous states during simulation step
%%   Required         : No
%%   C MEX counterpart: mdlDerivatives
%%
% function Derivatives(block)

%end Derivatives

%%
%% Terminate:
%%   Functionality    : Called at the end of simulation for cleanup
%%   Required         : Yes
%%   C MEX counterpart: mdlTerminate
%%
% function Terminate(block)
%end Terminate


离散状态属性设置

对应 PostPropagationSetup 回调函数进行实现。注意 level 2 s function 将离散状态信息存储在 DWork Vector 中,参考 Use DWork Vectors in S-Functions - MATLAB & Simulink (mathworks.com)open in new window

If multiple instances of your S-function can occur in a model, your S-function must use DWork vectors instead of global or static memory to store instance-specific values of S-function variables.

下面是对应上面代码中 DoPostPropSetup 的实现部分:

function DoPostPropSetup(block)

  %% Setup Dwork
  block.NumDworks = 1;
  block.Dwork(1).Name = 'x0'; 
  block.Dwork(1).Dimensions      = 1;
  block.Dwork(1).DatatypeID      = 0;
  block.Dwork(1).Complexity      = 'Real';
  block.Dwork(1).UsedAsDiscState = true;

这将 DWork 的名字设定为了 x0

初始化初始条件

初始化初始条件对应的 InitConditions。这里有两种初始化方式:

  • Start 回调函数适用于在仿真开始仅调用一次的情形
  • InitializeConditions 回调函数适用于这个 s function 包含于一个子系统 (subsystem) 中,且这个子系统会被重启的情形。会对重启的子系统中的对应变量重新初始化。

对下面例子,其使用了了 InitializeConditions 来设置离散状态的初值为使用的 dialog parameter 值。

function InitConditions(block)

  %% Initialize Dwork
  block.Dwork(1).Data = block.DialogPrm(1).Data;

这里 DialogPrm 属性可以参考 Pass Dialog Parameters to S-Functions - MATLAB & Simulink (mathworks.com)open in new window,多输入的 Parameters 类似 1.0,2.0,3.0 对应三个输入参数。

note

collapse: open title: Note 注意这里1.0,2.0,3.0不能写成[1.0,2.0,3.0],后者被认为是一个变量

对连续状态而言,使用类似 block.ContStates.Data(1) = 1.0; 的代码来初始化。

计算输出

对应 Outputs 回调函数的实现,这里输出为:

function Output(block)

  block.OutputPort(1).Data = block.Dwork(1).Data;

计算微分

对连续状态而言,使用 Derivatives 回调函数对应的函数,计算连续的微分状态,其结果存储在 Derivatives 的属性中,比如下面这个就将第一个状态的微分设为了第一个输入信号:

block.Derivatives.Data(1) = block.InputPort(1).Data;

注意例子中并没有连续的状态,因此没有实现这一回调函数。

刷新状态

对应 Update 回调函数,实现刷新离散状态的代码。这里就将当前输入的数据付给离散状态的值:

function Update(block)

  block.Dwork(1).Data = block.InputPort(1).Data;

结束程序

Perform any cleanup, such as clearing variables or memory, in the Terminate method. Unlike C MEX S-functions, Level-2 MATLAB S-function are not required to have a Terminate method.

进阶

对于可变 size 的输入输出,参考下面代码实现:

function setup(block)
% Register the properties of the output port
block.OutputPort(1).DimensionsMode = 'Variable';
block.RegBlockMethod('SetInputPortDimensionsMode',  @SetInputDimsMode);

function DoPostPropSetup(block)
%Register dependency rules to update current output size of output port a depending on
%input ports b and c
block.AddOutputDimsDependencyRules(a, [b c], @setOutputVarDims);

%Configure output port b to have the same dimensions as input port a
block.InputPortSameDimsAsOutputPort(a,b);

%Configure DWork a to have its size reset when input size changes.
block.DWorkRequireResetForSignalSize(a,true);

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

function setOutputVarDims(block, opIdx, inputIdx)
% Set current (run-time) dimensions of the output
outDimsAfterReset = block.InputPort(inputIdx(1)).CurrentDimensions;
block.OutputPort(opIdx).CurrentDimensions = outDimsAfterReset;

For information on additional callback methods, see Level-2 MATLAB S-Function Callback Methodsopen in new window. For a list of run-time object properties, see the reference page for Simulink.MSFcnRunTimeBlockopen in new window and the parent class Simulink.RunTimeBlockopen in new window.

更多例子

参考 S-Function Examples - MATLAB & Simulink (mathworks.com)open in new window

个人觉得这个限制积分器比较不错:

msfcn_limintm

msfcndemo_limintm

我自己写了一个倒立摆的模型,使用了连续状态,constates,可以参考一下:

模型物理模式参考:动力学建模-拉格朗日方程 - 知乎 (zhihu.com)open in new window

问题

DWork 目前只能存储向量,如何在 s function 中存储矩阵状态?

注意

  • s function 中支持中间变量,比如下面代码 ok
function Outputs(block)
	 y = block.Dwork(1).Data;
	 block.OutputPort(1).Data = 0.2*sin(y(1));
end
  • 连续状态没有维数的概念,只能为单维度的。

参考

Loading...