Matlab中s函数的使用

目录

0. 写在前面

1. s函数的编写

2. 连续系统模型

3. 中文注释的sfuntmpl


 

0. 写在前面

        最近做毕设用到了matlab的s函数,在这里分享一下我的收获,欢迎大家指正

        关于s函数的一些概念就不在叙述了,网上一查一大堆。本文主要分享s函数编写的步骤和自己对代码的一些理解

        (第一篇文章,多多关照)

 

1. s函数的编写

         首先,打开模板函数,复制sfuntmpl中的代码到自己的m文件中

>> edit sfuntmpl

        

        ② 然后,修改函数名字(名字得和文件名一样,这里我用的是systemP.m)

        sfuntmpl代码:

function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)

        修改后代码:(无模块参数)

function [sys,x0,str,ts,simStateCompliance] = systemP(t,x,u,flag)

        修改后代码:(带三个模块参数)

function [sys,x0,str,ts,simStateCompliance] = systemP(t,x,u,flag,name1,name2,name3)

        使用带模块参数时需要在simulink中传参进来。例如下图,传参1,2,3,对应name1,name2,name3

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_20,color_FFFFFF,t_70,g_se,x_16

 

        参数意义:

输出输入
sys:通用返回值t:时间
x0:状态初始值x:状态
str:保留项(目前没用) u:输入
ts:采样时间设置

flag:标志位

simStateCompliance:仿真状态设置可以添加任意个simulink模块参数的输入

        

        修改初始化参数(也就是flag等于0)

%case 0:初始化
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes

sizes = simsizes;           %用于设置模块参数的结构体

sizes.NumContStates  = 0;   %连续变量个数
sizes.NumDiscStates  = 0;   %离散变量个数
sizes.NumOutputs     = 0;   %输出个数
sizes.NumInputs      = 0;   %输入个数
sizes.DirFeedthrough = 1;   %输入是否直接影响输出
sizes.NumSampleTimes = 1;   %至少一个采样时间

sys = simsizes(sizes);

%初始化初始条件
x0  = [];

%保留项
str = [];

% 初始化采样时间
ts  = [0 0]; %[0 0] 连续采样
             %[0 1] 小步长的连续采样
			 %[PERIOD OFFSET] 离散采用时间 [采样时间 步长]
			 %[-2 0] 变步长的采样时间 FLAG=4时获取下一次采样时间

%指定simStateCompliance块值
simStateCompliance = 'UnknownSimState'; %'UnknownSimState'  默认设置
										%'DefaultSimState'  与内置块的模拟状态相同
										%'HasNoSimState'    没有模拟状态
										%'DisallowSimState' 保存或恢复模型模拟状态时出错

        在这一步主要分三种情况阐述:

  • 连续系统

        连续系统修改:连续变量个数、输入个数、输出个数、x0初始条件

  • 离散系统

        离散系统修改:离散变量个数、输入个数、输出个数、x0初始条件、采样时间

  • 纯数学计算

        由输入计算输出的函数修改:输入个数、输出个数

        simStateCompliance的选择:这里一般情况使用‘默认设置’是没有问题的。我在做毕设时,仅一次遇到matlab跑simulink仿真程序时出现状态的问题,我把默认设置改成‘与内置块的模拟状态相同’也就好了。

 

        根据‘步骤③’中提到的三种情况对应修改‘case 1+case 3’、‘case 2+case 3’、‘case 3’

        大多数情况的传参就是在这里使用的

        (如果你想在初始化中使用传参也不是不可以,注意事项一样)

        传参除了在‘步骤②’中提到的位置修改外,还应该修改两个地方

第一,switch-case的函数中,如果调用该函数需要传参,则需要在对应函数后面加上参数

switch flag
  case 0   
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;

  case 1   
    sys=mdlDerivatives(t,x,u,name1,name2,name3);

  case 2    
    sys=mdlUpdate(t,x,u);

  case 3   
    sys=mdlOutputs(t,x,u,name1,name3);

  case 4  
    sys=mdlGetTimeOfNextVarHit(t,x,u);

  case 9   
    sys=mdlTerminate(t,x,u);

  otherwise 
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));

end

第二,参数定义的时候

function sys=mdlDerivatives(t,x,u,name1,name2,name3)
sys = [];

function sys=mdlUpdate(t,x,u)
sys = [];

function sys=mdlOutputs(t,x,u,name1,name3)
sys = [];

以上两个地方必须配套使用

 

        创建simulink模块

        s函数写完后,保存,打开simulink,搜索s-function

        

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_15,color_FFFFFF,t_70,g_se,x_16

         将s-function模块拖入工作区,双击模块,在s-function名称中添加刚刚保存的s函数,在s-function参数中输入传参,没有传参可以不输入。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU3Vkb1JlYm9vdA==,size_15,color_FFFFFF,t_70,g_se,x_16

 

2. 连续系统模型案例

        由于我主要使用的是连续模型,所以在这里我分享一下连续的系统模型和代码

连续模型主要是状态空间方程:

gif.latex?%5Chat%7BX%7D%20%3D%20Ax+Bu

gif.latex?Y%20%3D%20Cx+Du

        x为连续变量,u为输入

        在s-function模块中是单输入、单输出,我们可以使用Mux和Dmux增加输入输出

        输入n个信号分别用u(1)、u(2)....u(n)来区分,输出m个信号在‘case 3’时,sys=[输出1;输出2;...;输出m]

 

连续系统模型:

gif.latex?%5Cbegin%7Bbmatrix%7D%20%5Cdot%7Bx%7D1%28t%29%5C%5C%20%5Cdot%7Bx%7D2%28t%29%20%5Cend%7Bbmatrix%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200%20%26%201%5C%5C%200%20%26%201%20%5Cend%7Bbmatrix%7D%5Cbegin%7Bbmatrix%7D%20x1%28t%29%29%5C%5C%20x2%28t%29%29%20%5Cend%7Bbmatrix%7D+%5Cbegin%7Bbmatrix%7D%201%5C%5C0%20%5Cend%7Bbmatrix%7D%20u%28t%29%20-%20%5Cbegin%7Bbmatrix%7D%200%5C%5C1%20%5Cend%7Bbmatrix%7D%20M%28t%29

gif.latex?y%20%3D%20%5Cbegin%7Bbmatrix%7D%201%20%26%200%20%5Cend%7Bbmatrix%7D%5Cbegin%7Bbmatrix%7D%20x1%28t%29%5C%5C%20x2%28t%29%5Cend%7Bbmatrix%7D

代码:

function [sys,x0,str,ts,simStateCompliance] = systemP(t,x,u,flag)

switch flag
  case 0   %初始化
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;

  case 1   %计算连续状态的微分
    sys=mdlDerivatives(t,x,u);

  case 2   %计算下一个离散状态  
    sys=mdlUpdate(t,x,u);

  case 3   %计算输出
    sys=mdlOutputs(t,x,u);

  case 4   %计算下一次采样的时间
    sys=mdlGetTimeOfNextVarHit(t,x,u);

  case 9   %系统结束
    sys=mdlTerminate(t,x,u);

  otherwise %其他情况
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));

end

%case 0:初始化
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes

sizes = simsizes;           %用于设置模块参数的结构体

sizes.NumContStates  = 2;   %连续变量个数
sizes.NumDiscStates  = 0;   %离散变量个数
sizes.NumOutputs     = 1;   %输出个数
sizes.NumInputs      = 2;   %输入个数
sizes.DirFeedthrough = 0;   %输入是否直接影响输出
sizes.NumSampleTimes = 1;   %至少一个采样时间

sys = simsizes(sizes);

%初始化初始条件
x0  = [0;0];

%保留项
str = [];

% 初始化采样时间
ts  = [0 0]; %[0 0] 连续采样
             %[0 1] 小步长的连续采样
			 %[PERIOD OFFSET] 离散采用时间 [采样时间 步长]
			 %[-2 0] 变步长的采样时间 FLAG=4时获取下一次采样时间

%指定simStateCompliance块值
simStateCompliance = 'UnknownSimState'; %'UnknownSimState'  默认设置
										%'DefaultSimState'  与内置块的模拟状态相同
										%'HasNoSimState'    没有模拟状态
										%'DisallowSimState' 保存或恢复模型模拟状态时出错


%case 1:计算连续状态的微分
function sys=mdlDerivatives(~,x,u)
ut = u(2);
Ml = u(1);
sys = [0 1;0 1]*x+[1;0]*ut-[0;1]*Ml;

%case 2:计算下一个离散状态  
%sys=AX+BU
function sys=mdlUpdate(~,~,~)
sys = [];

%case 3:计算输出           
function sys=mdlOutputs(~,x,~)
sys = [1 0]*x;

%case 4:计算下一次采样的时间[-2 0]时使用该函数
function sys=mdlGetTimeOfNextVarHit(t,~,~)
sampleTime = 1;    %例如设置下一次的采样时间是1s后
sys = t + sampleTime;

%case 9:系统结束
function sys=mdlTerminate(~,~,~)
sys = [];

 

3. 中文注释的sfuntmpl

  最后,在这里放一份完整的做了中文注释的sfuntmpl版本

function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)

switch flag
  case 0   %初始化
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;

  case 1   %计算连续状态的微分
    sys=mdlDerivatives(t,x,u);

  case 2   %计算下一个离散状态  
    sys=mdlUpdate(t,x,u);

  case 3   %计算输出
    sys=mdlOutputs(t,x,u);

  case 4   %计算下一次采样的时间
    sys=mdlGetTimeOfNextVarHit(t,x,u);

  case 9   %系统结束
    sys=mdlTerminate(t,x,u);

  otherwise %其他情况
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));

end

%case 0:初始化
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes

sizes = simsizes;           %用于设置模块参数的结构体

sizes.NumContStates  = 0;   %连续变量个数
sizes.NumDiscStates  = 0;   %离散变量个数
sizes.NumOutputs     = 0;   %输出个数
sizes.NumInputs      = 0;   %输入个数
sizes.DirFeedthrough = 1;   %输入是否直接影响输出
sizes.NumSampleTimes = 1;   %至少一个采样时间

sys = simsizes(sizes);

%初始化初始条件
x0  = [];

%保留项
str = [];

% 初始化采样时间
ts  = [0 0]; %[0 0] 连续采样
             %[0 1] 小步长的连续采样
			 %[PERIOD OFFSET] 离散采用时间 [采样时间 步长]
			 %[-2 0] 变步长的采样时间 FLAG=4时获取下一次采样时间

%指定simStateCompliance块值
simStateCompliance = 'UnknownSimState'; %'UnknownSimState'  默认设置
										%'DefaultSimState'  与内置块的模拟状态相同
										%'HasNoSimState'    没有模拟状态
										%'DisallowSimState' 保存或恢复模型模拟状态时出错


%case 1:计算连续状态的微分
%sys=AX+BU
function sys=mdlDerivatives(t,x,u)
sys = [];

%case 2:计算下一个离散状态  
%sys=AX+BU
function sys=mdlUpdate(t,x,u)
sys = [];

%case 3:计算输出           
%sys = CX+DU
function sys=mdlOutputs(t,x,u)
sys = [];

%case 4:计算下一次采样的时间[-2 0]时使用该函数
function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1;    %例如设置下一次的采样时间是1s后
sys = t + sampleTime;

%case 9:系统结束
function sys=mdlTerminate(t,x,u)
sys = [];

 

 

  • 47
    点赞
  • 138
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SudoReboot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值