概述
目录
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
参数意义:
输出 | 输入 |
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
将s-function模块拖入工作区,双击模块,在s-function名称中添加刚刚保存的s函数,在s-function参数中输入传参,没有传参可以不输入。
2. 连续系统模型案例
由于我主要使用的是连续模型,所以在这里我分享一下连续的系统模型和代码
连续模型主要是状态空间方程:
x为连续变量,u为输入
在s-function模块中是单输入、单输出,我们可以使用Mux和Dmux增加输入输出
输入n个信号分别用u(1)、u(2)....u(n)来区分,输出m个信号在‘case 3’时,sys=[输出1;输出2;...;输出m]
连续系统模型:
代码:
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 = [];
最后
以上就是稳重老鼠为你收集整理的Matlab中s函数的使用的全部内容,希望文章能够帮你解决Matlab中s函数的使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复