在matlab的workspace里打edit sfuntmpl(这是matlab自己提供的s函数模板),我们 看它来具体分析s函数的结构。 它的第一行是这样的:function [sys,x0,str,ts]=sfuntmpl(t,x,u,flag)
先讲输入与输出变量的含义:t是采样时间,x是状态变量,u是输入(是做成simulink模 块的输入),flag是仿真过程中的状态标志(以它来判断当前是初始化还是运行等);sys输出根据flag的不同而不同(下面将结合flag来讲sys的含义),x0是状态变量的初始值,str是保留参数(mathworks公司还没想好该怎么用它,嘻嘻,一般在初始化中将它置空就可以了,str=[]),ts是一个1×2的向量,ts(1)是采样周期,ts(2)是偏移量。
下面结合sfuntmpl.m中的代码来讲具体的结构:
switch flag, %判断flag,看当前处于哪个状态
case 0,
[sys,x0,str,ts]=mdlInitializeSizes
flag=0表示处于初始化状态,此时用函数mdlInitializeSizes进行初始化,此函数在 sfuntmpl.m的149行
我们找到他,在初始化状态下,sys是一个结构体,用它来设置模块的一些参数,各个参 数详细说明如下
size = simsizes%用于设置模块参数的结构体用simsizes来生成
sizes.NumContStates = 0%模块连续状态变量的个数
sizes.NumDiscStates = 0%模块离散状态变量的个数
sizes.NumOutputs = 0%模块输出变量的个数
sizes.NumInputs = 0%模块输入变量的个数
sizes.DirFeedthrough = 1%模块是否存在直接贯通(直接贯通我的理解是输入能 %直接控制输出)
sizes.NumSampleTimes = 1%模块的采样时间个数,至少是一个
sys = simsizes(sizes) %设置完后赋给sys输出
举个例子,考虑如下模型:
dx/dt=fc(t,x,u) 也可以用连续状态方程描述:dx/dt=A*x+B*u
x(k+1)=fd(t,x,u) 也可以用离散状态方程描述:x(k+1)=H*x(k)+G*u(k)
y=fo(t,x,u) 也可以用输出状态方程描述:y=C*x+D*u
设上述模型连续状态变量、离散状态变量、输入变量、输出变量均为1个,我们就只需改上面那一段代码为:
(一般连续状态与离散状态不会一块用,我这儿是为了方便说明)
sizes.NumContStates=1sizes.NumDiscStates=1sizes.NumOutputs=1sizes.NumInpu
ts=1
其他的可以不变。继续在mdlInitializeSizes函数中往下看:
x0 = [] %状态变量设置为空,表示没有状态变量,以我们上面的假设,可改 %为x0=[0,0](离散和连续的状态变量我们都设它初值为0)
str = [] %这个就不用说了,保留参数嘛,置[]就可以了,反正没什么用,可 %能7.0会给它一些意义
ts = [0 0]%采样周期设为0表示是连续系统,如果是离散系统在下面的mdlGet %TimeOfNextVarHit函数中具体介绍
嘻嘻,总算讲完了初始化,后面的应该快了
在sfuntmpl的106行继续往下看:
case 1,
sys=mdlDerivatives(t,x,u)
flag=1表示此时要计算连续状态的微分,即上面提到的dx/dt=fc(t,x,u)中的dx/dt,找到 mdlDerivatives函数(在193行)如果设置连续状态变量个数为0,此处只需sys=[]就可以了(如sfuntmpl中一样),按我们上述讨论的那个模型,此处改成 sys=fc(t,x(1),u)或sys=A*x(1)+B*u %我们这儿x(1)是连续状态变量,而x(2)是离散的 ,这儿只用到连续的,此时的输出sys就是微分
继续,在sfuntmpl的112行:
case 2,
sys=mdlUpdate(t,x,u)
flag=2表示此时要计算下一个离散状态,即上面提到的x(k+1)=fd(t,x,u),找到mdlUpd ate函数(在206行)它这儿sys=[]表示没有离散状态,我们这而可以改成 sys=fd(t,x(2),u)或sys=H*x(2)+G*u%sys即为x(k+1)
看来后面几个一两句话就可了,呵呵,在sfuntmpl的118行
case 3,
sys=mdlOutputs(t,x,u)
flag=3表示此时要计算输出,即y=fo(t,x,u),找到mdlOutputs函数(在218行),如上,如果sys=[]表示没有输出,我们改成sys=fo(t,x,u)或sys=C*x+D*u %sys此时为输出y
好像快完了,嘻嘻,在sfuntmpl的124行
case 4,
sys=mdlGetTimeOfNextVarHit(t,x,u)
flag=4表示此时要计算下一次采样的时间,只在离散采样系统中有用(即上文的mdlInit ializeSizes中提到的ts设置ts(1)不为0)
连续系统中只需在mdlGetTimeOfNextVarHit函数中写上sys=[]这个函数主要用于变步长的设置,具体实现大家可以用edit vsfunc看vsfunc.m这个例子
最后一个,在sfuntmpl的130行
case 9,
sys=mdlTerminate(t,x,u)
flag=9表示此时系统要结束,一般来说写上在mdlTerminate函数中写上sys=[]就可,如 果你在结束时还要设置什么,就在此函数中写
关于sfuntmpl这个s函数的模板讲完了。
s函数还可以带用户参数,下面给个例子,和simulink下的gain模块功能一样,大伙自己 看吧,我睡觉去了,累了
function [sys,x0,str,ts] = sfungain(t,x,u,flag,gain)
switch flag,
case 0,
sizes = simsizes
sizes.NumContStates = 0
sizes.NumDiscStates = 0
sizes.NumOutputs = 1
sizes.NumInputs = 1
sizes.DirFeedthrough = 1
sizes.NumSampleTimes = 1
sys = simsizes(sizes)
x0=[]
str=[]
ts=[0,0]
case 3,
sys=gain*u
case {1,2,4,9},
sys = []
end
做好了s函数后,simulink--user-defined function下拖一个S-Function到你的模型,就可以用了 在simulink----user-defined function还有个s-Function Builder,他可以生成用c语 言写的s函数 在matlab的workspace下打sfundemos,可以看到很多演示s函数的程序。
simulink的代码生成是靠rtw完成的,rtw生成代码的过程大致分为4步:模型分析、由tlc生成c代码、生成联编文件、生成可执行程序。除了第一步之外,其它几步都可以进行定向设置,以生成所需的目标代码,尤其是tlc文件的选择,最为重要。
你可以先生成net网络,经训练后即可调用gensim函数。我给你看一个例子吧:%训练样本集
%输入向量
P=[756.5745 765.3261 762.9077 762.7337 778.0583 768.4183 753.3221 754.777 869.1892 837.8081 850.121 871.7502 886.9313 896.7662 844.2693 878.671 936.677 953.5296 936.9523 972.7305 969.6961 966.8402 967.3992 991.9504
20 20 20 20 45 45 45 45 20 20 20 20 45 45 45 45 20 20 20 20 45 45 45 45]
%目标向量
T=[750 750 750 750 750 750 750 750 850 850 850 850 850 850 850 850 950 950 950 950 950 950 950 950]
%输入向量、目标向量归一化
p=(P-[75020]*ones(1,24))./([95045]*ones(1,24)-[75020]*ones(1,24))
t=(T-750)/(950-750)
%创建BP网络:网络含5个隐层和一个输出层
net=newff([0,10,1],[5,1],{'tansig','logsig'},'trainlm')
%对网络进行训练
net=train(net,p,t)
%保存网络
save cellnet net
%生成模块
gensim(net,-1)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
首先需要指出的是,newff函数是用来产生新的网络的,使用时输入向量的维数可以是任意的。
下面是我写的几行命令,newff命令中的minmax(X)决定了新生成网络的输入为5维
%输入向量
X=[0 0.5398 0.5325 0.5324
0 -0.9341 0.9339 -0.9327
0 -6.4617 0.8567 0.8850
0 10.3576 -10.1934 8.9586
0 10.9531 31.1317 51.2697]
%目标向量
T=[0 10.9630 31.1417 51.2796]
%输入向量、目标向量归一化:你自己补充一下
%创建BP网络:假设网络含5个隐层和一个输出层
net=newff(minmax(X),[5,1],{'tansig','logsig'},'trainlm')
%对网络进行训练
net=train(net,X,T)
%生成模块
gensim(net,-1)
%需要指出的是,上面调用的newff函数的用法是基于MATLABR2007或者早些版本的。MATLABR2008a上调用时会稍微有所不同。你可以用help看看
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
输入输出都是按行归一化的。每一个输入矩阵中,每一列都是一个训练或测试样本,对列输入没有意义的。
我用的是MATLABR2008版的,你的那段程序在语法上除了归一化不正确导致的一些问题和newff调用警告外好像没有其他的bug
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)