如何编写simulink library
由于simulink中没有非线性系统的状态空间模块,即形如
x'=f(x)+g(x)u
y=h(x)
的模块,因此对于非线性系统,使用simulink建模比较困难。
但是现在这不是问题了,因为我们有了一个第三方的simulink library:NelinSys
下载下来之后,顺便分析了这个库的实现方法,发现真的是very easy!下面介绍一下如何编写simulink library:
1.打开simulink,选择File->new->library,这样就能在里面随便添加文本,等。。东西。然后保存为.mdl文件。
2.然后就得添加一个模块,这里我没找到如何用可视化的方法进行设计,但是我发现可以直接修改.mdl文件实现。比如有一个library中的一个模块叫做Nonlinear MIMO system,它对应的代码如下:
Block {
BlockType SubSystem
Name "Nonlinear MIMO system\n(State-Space model)"
Ports [1, 2, 0, 0, 0]
Position [255, 20, 385, 95]
ShowPortLabels off
MaskType "Nonlinear MIMO system - state-space model"
MaskDescription "Nonlinear MIMO system is described by follo"
"wing nonlinear differential equations:\n dx/dt = f(x) +"
" g(x) u\n y = h(x)\n\n states vector: x ="
" [x1; x2; ; xN]\n system input: u (vector)\n syste"
"m output: y (vector)\n\nParameters f(x), g(x), h(x) can be specified either a"
"s a symbolic expression or as an identifier of a symbolic variable.\n\nFor a "
"detailed description of parameters, click \"Help\" button."
MaskHelp "web(fullfile(cd,'help','stavp_mimo.html'));"
MaskPromptString "System order (number of states, N)|f(x) - s"
"ymbolic expression:|f(x) - variable identifier:|g(x) - symbolic expression:|g"
"(x) - variable identifier:|h(x) - symbolic expression:|h(x) - variable identi"
"fier:|Initial conditions (initial states):"
MaskStyleString "edit,edit,edit,edit,edit,edit,edit,edit"
MaskTunableValueString "on,on,on,on,on,on,on,on"
MaskVariables "n=@1;F=&2;Fp=@3;G=&4;Gp=@5;H=&6;Hp=@7;pp=@8"
";"
MaskInitialization "% Overenie spravnosti zadania parametrov bl"
"oku %\nif ~isempty(F) & (Fp == 0)\n F = sym(F);\nelseif isempty(F) & (any(F"
"p ~= 0))\n F = sym(Fp);\nelse\n error(['Matrix f(x) unspecified or specif"
"ied more than once - cannot continue!']);\nend\n\nif ~isempty(G) & (Gp == 0)"
"\n G = sym(G);\nelseif isempty(G) & (any(Gp ~= 0))\n G = sym(Gp);\nelse\n"
" error(['Matrix g(x) unspecified or specified more than once - cannot conti"
"nue!']);\nend\n\nif ~isempty(H) & (Hp == 0)\n H = sym(H);\nelseif isempty(H"
") & (any(Hp ~= 0))\n H = sym(Hp);\nelse\n error(['Matrix h(x) unspecified"
" or specified more than once - cannot continue!']);\nend\n\n% Zisti si symbol"
"icke premenne, ktore vystupuju vo vyrazoch %\npremF = strrep(strrep(findsym(s"
"ym(F)),', ',''),',',' ');\npremG = strrep(strrep(findsym(sym(G)),', ',''),','"
",' ');\npremH = strrep(strrep(findsym(sym(H)),', ',''),',',' ');\n\n% Premenn"
"e x1, x2, , xN su korektne, preskoc ich %\nfor k = 1 : n\n premF = strre"
"p(premF, sprintf('x%d',k), '');\n premG = strrep(premG, sprintf('x%d',k), '"
"');\n premH = strrep(premH, sprintf('x%d',k), '');\nend\n\n% Ak niektory re"
"tazec nezostal prazdny, vyhlas chybu %\nif ~isempty(premF)\n error(['Unknow"
"n symbol in f(x) expression - cannot continue!']);\nend\nif ~isempty(premG)\n"
" error(['Unknown symbol in g(x) expression - cannot continue!']);\nend\nif "
"~isempty(premH)\n error(['Unknown symbol in h(x) expression - cannot contin"
"ue!']);\nend\n\n% Otestovanie spravnosti rozmerov matic F,G,H (podla \"n\") %"
"\nif ~all(size(F) == [n,1])\n error(['Invalid matrix dimensions: f(x) - can"
"not continue!']);\n return;\nend\n\nnin = size(G);\nif (nin(1,1) ~= n)\n "
"error(['Invalid matrix dimensions: g(x) - cannot continue!']);\n return;\ne"
"nd\nnin = nin(1,2);\n\nnout = size(H);\nif (nout(1,2) ~= 1)\n error(['Inval"
"id matrix dimensions: h(x) - cannot continue!']);\n return;\nend\nnout = no"
"ut(1,1);\n\n% Kontrola vektora pociatocnych podmienok (pociatocnych stavov) %"
"\nif ~all(size(pp) == [n,1])\n error(['Initial conditions vector: invalid d"
"imensions - cannot continue!']);\n return;\nend\n\n% Nahradenie identifikat"
"orov \"xI\" identifikatormi \"x(I)\" %\nco_str = '{''x1'; cim_str = '{''x(1)'"
";\n\nfor k = 2 : n\n co_str = sprintf('%s'',''x%d', co_str, k);\n cim_s"
"tr = sprintf('%s'',''x(%d)', cim_str, k);\nend\n\nco_str = strcat(co_str, '''"
"}'); cim_str = strcat(cim_str, '''}');\n\nF = eval(sprintf('subs(F,%s,%s)', c"
"o_str, cim_str));\nG = eval(sprintf('subs(G,%s,%s)', co_str, cim_str));\nH = "
"eval(sprintf('subs(H,%s,%s)', co_str, cim_str));\n"
MaskDisplay "disp('Nonlinear MIMO system\\n\\nx'' = f(x)"
" + g(x) u\\ny = h(x)');"
MaskIconFrame on
MaskIconOpaque on
MaskIconRotate none
MaskIconUnits autoscale
MaskValueString "3|[84.249*x2*x3; -165.8654*x1*x3-62.5*x2; -"
"15.3846*x3]|0|[0 0; 2500 0; 0 0.9799]|0|[x1; x3]|0|[0; 0; 1e-9]"
System {
Name "Nonlinear MIMO system\n(State-Space model"
")"
Location [124, 225, 456, 399]
Open off
ToolBar off
StatusBar off
ScreenColor white
PaperOrientation landscape
PaperPositionMode auto
PaperType usletter
PaperUnits inches
Block {
BlockType Inport
Name "Vstup"
Position [15, 78, 45, 92]
Port "1"
PortWidth "-1"
SampleTime "-1"
}
Block {
BlockType Demux
Name "Demux"
Ports [1, 2, 0, 0, 0]
Position [235, 6, 240, 159]
BackgroundColor black
ShowName off
Outputs "[nout n]"
}
Block {
BlockType "S-Function"
Name "S-funkcia realizujuca\nnelinearny syste"
"m"
Ports [1, 1, 0, 0, 0]
Position [85, 60, 195, 110]
FunctionName "stavp_mimo"
Parameters "n,nin,nout,F,G,H,pp"
PortCounts "[]"
SFunctionModules "''"
}
Block {
BlockType Outport
Name "Vystup"
Position [280, 38, 310, 52]
Port "1"
OutputWhenDisabled held
InitialOutput "0"
}
Block {
BlockType Outport
Name "Stavovy\nvektor"
Position [280, 113, 310, 127]
Port "2"
OutputWhenDisabled held
InitialOutput "[]"
}
Line {
SrcBlock "Demux"
SrcPort 2
DstBlock "Stavovy\nvektor"
DstPort 1
}
Line {
SrcBlock "Demux"
SrcPort 1
DstBlock "Vystup"
DstPort 1
}
Line {
SrcBlock "S-funkcia realizujuca\nnelinearny syste"
"m"
SrcPort 1
DstBlock "Demux"
DstPort 1
}
Line {
SrcBlock "Vstup"
SrcPort 1
DstBlock "S-funkcia realizujuca\nnelinearny syste"
"m"
DstPort 1
}
}
}
BlockType SubSystem
Name "Nonlinear MIMO system\n(State-Space model)"
Ports [1, 2, 0, 0, 0]
Position [255, 20, 385, 95]
ShowPortLabels off
MaskType "Nonlinear MIMO system - state-space model"
MaskDescription "Nonlinear MIMO system is described by follo"
"wing nonlinear differential equations:\n dx/dt = f(x) +"
" g(x) u\n y = h(x)\n\n states vector: x ="
" [x1; x2; ; xN]\n system input: u (vector)\n syste"
"m output: y (vector)\n\nParameters f(x), g(x), h(x) can be specified either a"
"s a symbolic expression or as an identifier of a symbolic variable.\n\nFor a "
"detailed description of parameters, click \"Help\" button."
MaskHelp "web(fullfile(cd,'help','stavp_mimo.html'));"
MaskPromptString "System order (number of states, N)|f(x) - s"
"ymbolic expression:|f(x) - variable identifier:|g(x) - symbolic expression:|g"
"(x) - variable identifier:|h(x) - symbolic expression:|h(x) - variable identi"
"fier:|Initial conditions (initial states):"
MaskStyleString "edit,edit,edit,edit,edit,edit,edit,edit"
MaskTunableValueString "on,on,on,on,on,on,on,on"
MaskVariables "n=@1;F=&2;Fp=@3;G=&4;Gp=@5;H=&6;Hp=@7;pp=@8"
";"
MaskInitialization "% Overenie spravnosti zadania parametrov bl"
"oku %\nif ~isempty(F) & (Fp == 0)\n F = sym(F);\nelseif isempty(F) & (any(F"
"p ~= 0))\n F = sym(Fp);\nelse\n error(['Matrix f(x) unspecified or specif"
"ied more than once - cannot continue!']);\nend\n\nif ~isempty(G) & (Gp == 0)"
"\n G = sym(G);\nelseif isempty(G) & (any(Gp ~= 0))\n G = sym(Gp);\nelse\n"
" error(['Matrix g(x) unspecified or specified more than once - cannot conti"
"nue!']);\nend\n\nif ~isempty(H) & (Hp == 0)\n H = sym(H);\nelseif isempty(H"
") & (any(Hp ~= 0))\n H = sym(Hp);\nelse\n error(['Matrix h(x) unspecified"
" or specified more than once - cannot continue!']);\nend\n\n% Zisti si symbol"
"icke premenne, ktore vystupuju vo vyrazoch %\npremF = strrep(strrep(findsym(s"
"ym(F)),', ',''),',',' ');\npremG = strrep(strrep(findsym(sym(G)),', ',''),','"
",' ');\npremH = strrep(strrep(findsym(sym(H)),', ',''),',',' ');\n\n% Premenn"
"e x1, x2, , xN su korektne, preskoc ich %\nfor k = 1 : n\n premF = strre"
"p(premF, sprintf('x%d',k), '');\n premG = strrep(premG, sprintf('x%d',k), '"
"');\n premH = strrep(premH, sprintf('x%d',k), '');\nend\n\n% Ak niektory re"
"tazec nezostal prazdny, vyhlas chybu %\nif ~isempty(premF)\n error(['Unknow"
"n symbol in f(x) expression - cannot continue!']);\nend\nif ~isempty(premG)\n"
" error(['Unknown symbol in g(x) expression - cannot continue!']);\nend\nif "
"~isempty(premH)\n error(['Unknown symbol in h(x) expression - cannot contin"
"ue!']);\nend\n\n% Otestovanie spravnosti rozmerov matic F,G,H (podla \"n\") %"
"\nif ~all(size(F) == [n,1])\n error(['Invalid matrix dimensions: f(x) - can"
"not continue!']);\n return;\nend\n\nnin = size(G);\nif (nin(1,1) ~= n)\n "
"error(['Invalid matrix dimensions: g(x) - cannot continue!']);\n return;\ne"
"nd\nnin = nin(1,2);\n\nnout = size(H);\nif (nout(1,2) ~= 1)\n error(['Inval"
"id matrix dimensions: h(x) - cannot continue!']);\n return;\nend\nnout = no"
"ut(1,1);\n\n% Kontrola vektora pociatocnych podmienok (pociatocnych stavov) %"
"\nif ~all(size(pp) == [n,1])\n error(['Initial conditions vector: invalid d"
"imensions - cannot continue!']);\n return;\nend\n\n% Nahradenie identifikat"
"orov \"xI\" identifikatormi \"x(I)\" %\nco_str = '{''x1'; cim_str = '{''x(1)'"
";\n\nfor k = 2 : n\n co_str = sprintf('%s'',''x%d', co_str, k);\n cim_s"
"tr = sprintf('%s'',''x(%d)', cim_str, k);\nend\n\nco_str = strcat(co_str, '''"
"}'); cim_str = strcat(cim_str, '''}');\n\nF = eval(sprintf('subs(F,%s,%s)', c"
"o_str, cim_str));\nG = eval(sprintf('subs(G,%s,%s)', co_str, cim_str));\nH = "
"eval(sprintf('subs(H,%s,%s)', co_str, cim_str));\n"
MaskDisplay "disp('Nonlinear MIMO system\\n\\nx'' = f(x)"
" + g(x) u\\ny = h(x)');"
MaskIconFrame on
MaskIconOpaque on
MaskIconRotate none
MaskIconUnits autoscale
MaskValueString "3|[84.249*x2*x3; -165.8654*x1*x3-62.5*x2; -"
"15.3846*x3]|0|[0 0; 2500 0; 0 0.9799]|0|[x1; x3]|0|[0; 0; 1e-9]"
System {
Name "Nonlinear MIMO system\n(State-Space model"
")"
Location [124, 225, 456, 399]
Open off
ToolBar off
StatusBar off
ScreenColor white
PaperOrientation landscape
PaperPositionMode auto
PaperType usletter
PaperUnits inches
Block {
BlockType Inport
Name "Vstup"
Position [15, 78, 45, 92]
Port "1"
PortWidth "-1"
SampleTime "-1"
}
Block {
BlockType Demux
Name "Demux"
Ports [1, 2, 0, 0, 0]
Position [235, 6, 240, 159]
BackgroundColor black
ShowName off
Outputs "[nout n]"
}
Block {
BlockType "S-Function"
Name "S-funkcia realizujuca\nnelinearny syste"
"m"
Ports [1, 1, 0, 0, 0]
Position [85, 60, 195, 110]
FunctionName "stavp_mimo"
Parameters "n,nin,nout,F,G,H,pp"
PortCounts "[]"
SFunctionModules "''"
}
Block {
BlockType Outport
Name "Vystup"
Position [280, 38, 310, 52]
Port "1"
OutputWhenDisabled held
InitialOutput "0"
}
Block {
BlockType Outport
Name "Stavovy\nvektor"
Position [280, 113, 310, 127]
Port "2"
OutputWhenDisabled held
InitialOutput "[]"
}
Line {
SrcBlock "Demux"
SrcPort 2
DstBlock "Stavovy\nvektor"
DstPort 1
}
Line {
SrcBlock "Demux"
SrcPort 1
DstBlock "Vystup"
DstPort 1
}
Line {
SrcBlock "S-funkcia realizujuca\nnelinearny syste"
"m"
SrcPort 1
DstBlock "Demux"
DstPort 1
}
Line {
SrcBlock "Vstup"
SrcPort 1
DstBlock "S-funkcia realizujuca\nnelinearny syste"
"m"
DstPort 1
}
}
}
值得注意的是其中一个s-function子模块:stavp_mimo,其实这个子模块才是最核心的地方,打开这个文件发现果然是一个标准的s-function模块:
function [sys,x0,str,ts] = stavp_mimo(t,x,u,flag,n,nin,nout,F,G,H,pp)
% NelinSys - a program tool for analysis and synthesis of nonlinear control systems
% based on MATLAB/Simulink 5.2
%
% (C) 2002-2005, Martin Ondera (eskimo@pobox.sk) (Martin.Ondera@stuba.sk)
% This program is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License
% as published by the Free Software Foundation; either version 2
% of the License, or (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
%
% Please, see the LICENSE.TXT file to read the full license.
switch flag,
% =========================== Inicializacna cast s-funkcie ============================== %
case 0
% Definicia stavov, vstupov a vystupov nelinearneho systemu %
sizes = simsizes;
sizes.NumContStates = n;
sizes.NumDiscStates = 0;
sizes.NumOutputs = nout+n;
sizes.NumInputs = nin;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
% Inicializacia pociatocnych podmienok %
x0 = pp;
% Inicializacia "str" ako prazdna matica %
str = [];
% Sample times in TS %
ts = [0 0];
% ========================== Vypocet podla 1. stavovej rovnice ========================== %
case 1
sys = eval(sym(F)) + eval(sym(G)) * u;
% ========================== Vypocet podla 2. stavovej rovnice ========================== %
case 3
sys(1:nout,:) = eval(sym(H)); % Ako vystup bloku sa berie nielen vystup systemu %
sys(nout+1:nout+n,:) = x; % ale aj cely stavovy vektor nelinearneho systemu %
% ================================= Nepouzite priznaky ================================== %
case {2, 4, 9}
sys = [];
% ================================= Spracovanie chyby =================================== %
otherwise
error(['Unknown flag = ',num2str(flag)]);
end
ok,现在分析结束。以后有了新的进展,我会随时汇报。% NelinSys - a program tool for analysis and synthesis of nonlinear control systems
% based on MATLAB/Simulink 5.2
%
% (C) 2002-2005, Martin Ondera (eskimo@pobox.sk) (Martin.Ondera@stuba.sk)
% This program is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License
% as published by the Free Software Foundation; either version 2
% of the License, or (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
%
% Please, see the LICENSE.TXT file to read the full license.
switch flag,
% =========================== Inicializacna cast s-funkcie ============================== %
case 0
% Definicia stavov, vstupov a vystupov nelinearneho systemu %
sizes = simsizes;
sizes.NumContStates = n;
sizes.NumDiscStates = 0;
sizes.NumOutputs = nout+n;
sizes.NumInputs = nin;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
% Inicializacia pociatocnych podmienok %
x0 = pp;
% Inicializacia "str" ako prazdna matica %
str = [];
% Sample times in TS %
ts = [0 0];
% ========================== Vypocet podla 1. stavovej rovnice ========================== %
case 1
sys = eval(sym(F)) + eval(sym(G)) * u;
% ========================== Vypocet podla 2. stavovej rovnice ========================== %
case 3
sys(1:nout,:) = eval(sym(H)); % Ako vystup bloku sa berie nielen vystup systemu %
sys(nout+1:nout+n,:) = x; % ale aj cely stavovy vektor nelinearneho systemu %
% ================================= Nepouzite priznaky ================================== %
case {2, 4, 9}
sys = [];
% ================================= Spracovanie chyby =================================== %
otherwise
error(['Unknown flag = ',num2str(flag)]);
end