> 文章列表 > Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
讲得真的十分细致!个人感觉看完前4节就差不多了。

今天记录的是S Function。
内容比较多,加个目录:

  • S Function
  • 前置工作
  • 1.1 parameter.m
  • 1.2 plant.m
    • function [sys,x0,str,ts,simStateCompliance] = plant(t,x,u,flag,pa)
    • function [sys,x0,str,ts]=mdlInitializeSizes
    • function sys=mdlDerivatives(t,x,u,pa)
    • function sys=mdlOutputs(t,x,u)
  • 1.3 ctrl.m
    • function [sys,x0,str,ts,simStateCompliance] = ctrl(t,x,u,flag,pa)
    • function [sys,x0,str,ts]=mdlInitializeSizes
    • function sys=mdlOutputs(t,x,u)
  • 1.4 signal.m
    • function [sys,x0,str,ts,simStateCompliance] = plant(t,x,u,flag,pa)
    • function [sys,x0,str,ts]=mdlInitializeSizes
    • function sys=mdlOutputs(t,x,u)
  • 1.5 simulink系统搭建
  • 1.6 demo_plot.m

S Function

可以用Matlab Function轻松搭建方程,(长得下面这样子),具体看视频的

第3节:S-Function/S函数,一个实例带你直接上手(非线性反步法搭建)

第4节:S-Function/S函数补充,滑模控制器完整搭建

演示的是这个方程

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

前置工作

在工作目录下创建四个函数:

plant.m 描述物理方程
ctrl.m 描述控制律
parameter.m 描述常数
demo_plot.m 绘制图形

下面我们依次讲怎么写这些函数。

1.1 parameter.m

写入我们要的参数

pa.k=8;
pa.m=1;
pa.k1=1;
pa.k2=1;
pa.A=5;%生成信号使用
pa.T=20;%生成信号使用

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
填写好以后运行一下,让pa在工作区中可以被调用。

1.2 plant.m

对应公式:

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

输入u,输出x1x_1x1x2x_2x2.
没有直接馈入。

在命令行输入edit sfuntmpl

调出S function的模板:

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
把模板里的内容复制到plant.m中,然后把sfuntmpl改成plant。注意我们调用parameter.m里的pa结构体参数,我们需要注意在用到pa的地方都加上pa。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

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

function [sys,x0,str,ts,simStateCompliance] = plant(t,x,u,flag,pa)switch flag,%%%%%%%%%%%%%%%%%%% Initialization %%%%%%%%%%%%%%%%%%%case 0,[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;%%%%%%%%%%%%%%%% Derivatives %%%%%%%%%%%%%%%%case 1,sys=mdlDerivatives(t,x,u,pa);%%%%%%%%%%% Update %%%%%%%%%%%case 2,sys=mdlUpdate(t,x,u);%连续系统不用管%%%%%%%%%%%% Outputs %%%%%%%%%%%%case 3,sys=mdlOutputs(t,x,u);%%%%%%%%%%%%%%%%%%%%%%%% GetTimeOfNextVarHit %%%%%%%%%%%%%%%%%%%%%%%%case 4,sys=mdlGetTimeOfNextVarHit(t,x,u);%%%%%%%%%%%%%% Terminate %%%%%%%%%%%%%%case 9,sys=mdlTerminate(t,x,u);%%%%%%%%%%%%%%%%%%%%% Unexpected flags %%%%%%%%%%%%%%%%%%%%%otherwiseDAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));end

function [sys,x0,str,ts]=mdlInitializeSizes

设置初始化。

如图输入不是直通的,x1x_1x1x2x_2x2的表达式并没有uuux2x_2x2的导数和uuu有关系,但是x2x_2x2并没有直接和uuu直接产生关系。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

function [sys,x0,str,ts]=mdlInitializeSizes
sizes = simsizes;
sizes.NumContStates  = 2;%连续状态个数为2:x_1和x_2,因为采用连续采样周期仿真
sizes.NumDiscStates  = 0;%离散状态个数为0
sizes.NumOutputs     = 2;%输出量为2个:x_1和x_2
sizes.NumInputs      = 1;%输入量为1个,u
sizes.DirFeedthrough = 0;%方程中输入没有直馈于输出
sizes.NumSampleTimes = 1;%采样周期数是1,默认就不动
sys = simsizes(sizes);
x0=[0,0]:%初始化输出值x_1和x_2都是0
str=[]:%无其他说明
ts=[0 0]:%连续采样,第一个值为0(每隔0秒采样一次),没有偏移,第二个值也设为0

function sys=mdlDerivatives(t,x,u,pa)

设置微分方程。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
输出是左边的导数项,输入是x1x_1x1x2x_2x2uuu,然后kkkmmm是常数从parameter结构体中获取。函数的输入项注意要加上pa。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

function sys=mdlDerivatives(t,x,u,pa)
k=pa.k;
m=pa.m;x1=x(1);
x2=x(2);dx1=x(2);
dx2=-k/m*x1^3+1/m*u;
sys = [dx1;dx2];

function sys=mdlOutputs(t,x,u)

设置输出,我们输出的是x。

function sys=mdlOutputs(t,x,u)sys = x;

1.3 ctrl.m

设置控制律。

在命令行输入edit sfuntmpl

调出S function的模板:

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
把模板里的内容复制到ctrl.m中,然后把sfuntmpl改成ctrl。注意我们调用parameter.m里的pa结构体参数,我们需要注意在用到pa的地方都加上pa。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

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

function [sys,x0,str,ts,simStateCompliance] = ctrl(t,x,u,flag,pa)switch flag,%%%%%%%%%%%%%%%%%%% Initialization %%%%%%%%%%%%%%%%%%%case 0,[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;%%%%%%%%%%%%%%%% Derivatives %%%%%%%%%%%%%%%%case 1,sys=mdlDerivatives(t,x,u);%%%%%%%%%%% Update %%%%%%%%%%%case 2,sys=mdlUpdate(t,x,u);%连续系统不用管%%%%%%%%%%%% Outputs %%%%%%%%%%%%case 3,sys=mdlOutputs(t,x,u,pa);%%%%%%%%%%%%%%%%%%%%%%%% GetTimeOfNextVarHit %%%%%%%%%%%%%%%%%%%%%%%%case 4,sys=mdlGetTimeOfNextVarHit(t,x,u);%%%%%%%%%%%%%% Terminate %%%%%%%%%%%%%%case 9,sys=mdlTerminate(t,x,u);%%%%%%%%%%%%%%%%%%%%% Unexpected flags %%%%%%%%%%%%%%%%%%%%%otherwiseDAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));end

function [sys,x0,str,ts]=mdlInitializeSizes

设置初始化。

对应公式:

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

输入x1dx_{1d}x1dx˙1d\\dot{x}_{1d}x˙1dx¨1d\\ddot{x}_{1d}x¨1dx1x_1x1x2x_2x2,共5个.输出uuu,共1个。

是直接馈入。如图输入是直通的,uuu的输出直接和五个输入参数有关。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

注意没有状态变量,连续状态和离散状态都是0。

function [sys,x0,str,ts]=mdlInitializeSizes
sizes = simsizes;
sizes.NumContStates  = 0;%连续状态个数为0,没有状态
sizes.NumDiscStates  = 0;%离散状态个数为0,没有状态
sizes.NumOutputs     = 1;%输出量为1个:u
sizes.NumInputs      = 5;%输入量为5个,$x_{1d}$、$\\dot{x}_{1d}$、$\\ddot{x}_{1d}$、$x_1$和$x_2$
sizes.DirFeedthrough = 1;%方程中输入有直馈于输出
sizes.NumSampleTimes = 1;%采样周期数是1,默认就不动
sys = simsizes(sizes);
x0=[]:%没有状态变量
str=[]:%无其他说明
ts=[0 0]:%连续采样,第一个值为0(每隔0秒采样一次),没有偏移,第二个值也设为0

function sys=mdlOutputs(t,x,u)

设置输出,用到了parameter的参数所以要在输入参数中添加pa,和前面是一样的。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

function sys=mdlOutputs(t,x,u,pa)k=pa.k;
m=pa.m;
k1=pa.k1;
k2=pa.k2;x1d=u(1);
dx1d=u(2);
ddx1d=u(3);
x1=u(4);
x2=u(5);e1=x1d-x1;
e2=dx1d+k1*e1-x2;uc = m*e1+m*ddx1d+m*k1*(dx1d-x2)+k*x1^3+m*k2*e2;
sys = uc;

1.4 signal.m

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

用到了parameter参数中的pa,注意加上。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag,pa)switch flag,%%%%%%%%%%%%%%%%%%% Initialization %%%%%%%%%%%%%%%%%%%case 0,[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;%%%%%%%%%%%%%%%% Derivatives %%%%%%%%%%%%%%%%case 1,sys=mdlDerivatives(t,x,u);%%%%%%%%%%% Update %%%%%%%%%%%case 2,sys=mdlUpdate(t,x,u);%%%%%%%%%%%% Outputs %%%%%%%%%%%%case 3,sys=mdlOutputs(t,x,u,pa);%%%%%%%%%%%%%%%%%%%%%%%% GetTimeOfNextVarHit %%%%%%%%%%%%%%%%%%%%%%%%case 4,sys=mdlGetTimeOfNextVarHit(t,x,u);%%%%%%%%%%%%%% Terminate %%%%%%%%%%%%%%case 9,sys=mdlTerminate(t,x,u);%%%%%%%%%%%%%%%%%%%%% Unexpected flags %%%%%%%%%%%%%%%%%%%%%otherwiseDAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));end

function [sys,x0,str,ts]=mdlInitializeSizes

信号我们给的是一个正弦信号:
x1d=Asin⁡(2πTt)x˙1d=A2πTcos⁡(2πTt)x¨1d=−A(2πT)2sin⁡(2πTt)\\begin{aligned}x_{1d}&=A\\sin\\left(\\frac{2\\pi}{T}t\\right)\\\\ \\dot{x}_{1d}&=A\\frac{2\\pi}{T}\\cos\\left(\\frac{2\\pi}{T}t\\right)\\\\ \\ddot{x}_{1d}&=-A\\left(\\frac{2\\pi}{T}\\right)^2\\sin\\left(\\frac{2\\pi}{T}t\\right)\\end{aligned}x1dx˙1dx¨1d=Asin(T2πt)=AT2πcos(T2πt)=A(T2π)2sin(T2πt)

三个输出,零个输入,没有反馈直通,无状态变量。信号的导数建议不要使用simulink自带的微分模块,容易出现突变导致仿真的失真。

function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizessizes = simsizes;
sizes.NumContStates  = 0;
sizes.NumDiscStates  = 0;
sizes.NumOutputs     = 3;%三个输出
sizes.NumInputs      = 0;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;   % at least one sample time is needed
sys = simsizes(sizes);x0  = [];
str = [];
ts  = [0 0];

function sys=mdlOutputs(t,x,u)

设置输出,用到了parameter的参数所以要在输入参数中添加pa,和前面是一样的。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

function sys=mdlOutputs(t,x,u,pa)A=pa.A;
T=pa.T;x1d=A*sin(2*pi/T*t);
dx1d=2*pi/T*A*cos(2*pi/T*t);
ddx1d=-(2*pi/T)^2*sin(2*pi/T*t);sys = [x1d;dx1d;ddx1d];

1.5 simulink系统搭建

打开simulink,双击鼠标输入S function。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

选择后然后双击。把Function名称改作我们刚刚设置的函数(下面是ctrl的设置)。注意参数加上pa(外部参数),如果有多个参数就用逗号隔开。外部参数就是上面说的除了模板里原有参数其他的参数。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

变成这样

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

最后连线成这样。我保存为demo_sim.slx,其他名字也可以。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
我们设置一下求解器

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
设置仿真为定步长,步长是0.001.定步长速度比变步长慢,但是精度更高,曲线更加平滑。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
仿真时间设置为50s。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

运行:

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
在scope我们看到仿真结果,可以看到较好地进行了跟踪。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
选择视图->样式。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
我们可以打开样式调整一下画面线型、线宽、画布颜色等。我设置了图窗、坐标区、各个线条属性。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
还可以添加图例。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

如果想把simulink的数据导出到matlab的工作区。需要添加 to workspace模块。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
我们双击修改一下名字叫x.并以数组的形式输出。

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

我们看到前面有一个out.,默认是以结构体的形式输出到工作区的。我们可以再模型设置里设置不要以结构体输出:

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
就没有前面的out了。连接一下。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

工作区就出现了时间tout和我们要的x。
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
我们双击看一下x。
第一列是x1d,第二列是x1。

现在工作区有了数据,我们可以自定义画图了!

1.6 demo_plot.m

新建一个画图的m文件demo_plot.m

figure;
plot(tout,x(:,1),'k',...tout,x(:,2),'r:','LineWidth',2);
legend('x1d','x1');
title('Position Tracking');
xlabel('t/s');
ylabel('Position/mm')

就可以自定义自己想要的图了!
Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例
上述文件可以在我的资源Matlab Simulink S函数使用实例(有讲解)中找到。

其他参考资料

  1. Matlab S-function 使用总结
  2. S-function入门及案例详解(1)——S-function基础介绍及基本案例
  3. S-function入门及案例详解(2)——S-function基本案例介绍
  4. S-function入门及案例详解(3)——S-function进阶案例
  5. S-function入门及案例详解(4)——S-function进阶案例之连续/离散状态空间表达式的S-function实现