文章目录
- 前言
- 题目一览
- 理论知识介绍
-
- [1. 控制系统的三种核心数学模型](#1. 控制系统的三种核心数学模型)
- [2. 模型转换关系](#2. 模型转换关系)
- [3. DEE建模(微分方程建模)](#3. DEE建模(微分方程建模))
- [4. S函数的作用](#4. S函数的作用)
- [5. 连续系统离散化](#5. 连续系统离散化)
- 编程知识介绍
前言
在控制系统工程中,数学建模是连接理论分析与工程实现的核心桥梁。无论是工业中的温度控制、机械系统的运动调节,还是航空航天中的姿态控制,都需要先建立精准的系统模型,才能进一步开展分析、优化与设计。实验四围绕"控制系统建模"展开,核心目标是让学习者掌握传递函数(TF)、零极点(ZPK)等核心模型的构建与转换,熟练运用Matlab编程与Simulink工具,同时攻克DEE建模、S函数编写等实操难点。
本文将从理论铺垫、编程基础、分步实操三个维度,完整拆解实验四的全部内容,适合有Matlab基础、刚接触控制系统建模的学习者参考,跟着步骤走就能顺利完成实验,同时理解背后的核心逻辑。
题目一览
实验四共包含3个核心任务,覆盖"模型构建-转换-属性修改-自定义建模"全流程,具体如下:
-
闭环系统模型构建与转换:

- (1)根据系统结构图,编写程序求闭环传递函数(TF);
- (2)将TF模型转换为零极点(ZPK)模型和部分分式模型,并写出表达式;
- (3)用
set命令修改TF模型属性(输入名、输出名、备注),并查看; - (4)将ZPK模型离散化(采样时间0.1s),查看离散化后属性。
-
多模块串联/并联系统建模:已知多个传递函数模块,用两种不同M文件编写方法求系统总传递函数。

-
天线臂仰角控制系统建模与仿真:
- 根据给定微分方程,用DEE建模、S函数编写、Simulink建模三种方法;
- 输入为单位阶跃、初始状态为0时,仿真输出
x1(仰角)和x2(角速度)的变化波形。

理论知识介绍
在动手实操前,先明确实验涉及的核心理论概念,避免"知其然不知其所以然":
1. 控制系统的三种核心数学模型
- 传递函数(TF) :线性时不变(LTI)系统在零初始条件下,输出拉普拉斯变换与输入拉普拉斯变换的比值,形式为有理多项式分式 G ( s ) = N ( s ) D ( s ) G(s) = \frac{N(s)}{D(s)} G(s)=D(s)N(s)(分子 N ( s ) N(s) N(s)、分母 D ( s ) D(s) D(s)为 s s s 的多项式)。
- 零极点模型(ZPK) :将传递函数分解为零点、极点和增益的形式 G ( s ) = K ⋅ ( s − z 1 ) ( s − z 2 ) . . . ( s − z m ) ( s − p 1 ) ( s − p 2 ) . . . ( s − p n ) G(s) = K \cdot \frac{(s-z_1)(s-z_2)...(s-z_m)}{(s-p_1)(s-p_2)...(s-p_n)} G(s)=K⋅(s−p1)(s−p2)...(s−pn)(s−z1)(s−z2)...(s−zm),其中 z i z_i zi为零点, p j p_j pj为极点, K K K为增益。零点决定系统响应的快速性,极点决定系统稳定性。
- 部分分式模型 :将传递函数分解为简单分式之和(如 A s + a + B s + b + . . . \frac{A}{s+a} + \frac{B}{s+b} + ... s+aA+s+bB+...),便于分析系统的暂态响应(如各极点对应的衰减模态)。
2. 模型转换关系
- TF ↔ ZPK:本质是多项式的因式分解(TF转ZPK)或因式展开(ZPK转TF);
- TF → 部分分式:通过留数计算实现,Matlab中
residue函数可直接求解留数(部分分式的系数)、极点和直接项。
3. DEE建模(微分方程建模)
DEE(Differential Equation Model)即通过微分方程描述系统的动态行为。实验三中的天线臂系统是典型的非线性微分方程系统(含 sin x 1 \sin x_1 sinx1项),其状态方程可整理为:
{ x 1 ˙ = x 2 x 2 ˙ = 9.81 sin x 1 − 2 x 2 + u \begin{cases} \dot{x_1} = x_2 \\ \dot{x_2} = 9.81\sin x_1 - 2x_2 + u \end{cases} {x1˙=x2x2˙=9.81sinx1−2x2+u
其中 x 1 x_1 x1为仰角(输出1), x 2 x_2 x2为角速度(输出2), u u u为输入(单位阶跃),初始状态 x 1 ( 0 ) = 0 , x 2 ( 0 ) = 0 x_1(0)=0, x_2(0)=0 x1(0)=0,x2(0)=0。
4. S函数的作用
S函数(System Function)是Matlab提供的自定义Simulink模块的接口,用于实现Simulink自带模块无法完成的功能(如非线性微分方程、复杂逻辑)。实验中需用S函数封装天线臂系统的微分方程,嵌入Simulink模型。
5. 连续系统离散化
将连续系统(采样时间( T_s=\infty ))转换为离散系统(采样时间( T_s=0.1s )),核心是通过数值方法(如零阶保持ZOH)逼近连续系统的动态特性,Matlab中c2d函数可直接实现。
编程知识介绍
实验四核心依赖Matlab编程与Simulink操作,以下是关键编程工具和函数说明:
1. 核心Matlab函数
| 函数名 | 功能描述 | 应用场景 |
|---|---|---|
tf(num, den) |
创建传递函数模型,num为分子系数,den为分母系数 |
任务1(1)、任务2 |
zpk(G) |
将TF模型转换为ZPK模型 | 任务1(2) |
residue(num, den) |
计算TF模型的部分分式(留数、极点、直接项) | 任务1(2) |
set(G, '属性名', '值') |
修改LTI模型的属性 | 任务1(3) |
get(G) |
查看LTI模型的所有属性 | 任务1(3)、(4) |
c2d(G, Ts, 'zoh') |
连续系统离散化(ZOH方法),Ts为采样时间 |
任务1(4) |
series(G1, G2) |
两个模块串联(传递函数相乘) | 任务2(方法1) |
parallel(G1, G2) |
两个模块并联(传递函数相加) | 任务2(方法1) |
feedback(G, H) |
反馈连接(默认负反馈,正反馈需加+1) |
任务1(1)、任务2 |
2. Simulink核心模块
- 信号源:
Step(单位阶跃输入); - 自定义模块:
S-Function(加载编写的S函数); - 示波器:
Scope(查看x1和x2的波形); - 基础模块:
Transfer Fcn(传递函数)、Gain(增益)、Integrator(积分器)、Sum(求和点)。
实操过程
任务1:闭环系统模型构建与转换
(1)求闭环传递函数(TF)
编写Matlab代码:
matlab
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 控制系统实验:Matlab代码实现(基于Control System Toolbox)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 定义复频率变量s,简化传递函数书写
s = tf('s');
%% (1) 构建闭环系统的传递函数(TF)模型
% 1. 串联各环节得到开环传递函数
G1 = 200 / (s * (s + 5)); % Gain(200) + 积分器(1/s) + 传递函数1/(s+5) 串联
G_tf2 = 3 / (s + 2); % 后续传递函数3/(s+2)
G_open = G1 * G_tf2; % 开环传递函数
% 2. 单位负反馈求闭环传递函数
G_closed = feedback(G_open, 1);
% ========== 补充:构造TF的直观多项式表达式 ==========
[num_tf, den_tf] = tfdata(G_closed, 'v'); % 提取分子、分母系数向量
% 构造分子多项式字符串(如:600)
num_str = poly2str(num_tf, 's');
% 构造分母多项式字符串(如:s^3 + 7 s^2 + 10 s + 600)
den_str = poly2str(den_tf, 's');
% 拼接TF表达式
G_tf_expr = sprintf('G(s) = %s / %s', num_str, den_str);
disp('(1) 闭环系统的传递函数TF模型:');
disp('--- Matlab默认格式 ---');
disp(G_closed);
disp('--- 直观多项式表达式 ---');
disp(G_tf_expr);
直接disp G_closed的话 会有问题 显示出来的是MATLAB里面对tf默认的输出格式,看不到我们需要的式子,所以需要提取然后填充。
运行结果(传递函数表达式):

(2)转换为ZPK模型和部分分式模型
继续添加代码:
matlab
%% (2) 转化为ZPK(零极点)模型和部分分式模型
% 零极点(ZPK)模型
G_zpk = zpk(G_closed);
% ========== 补充:构造连续ZPK的直观表达式 ==========
z = G_zpk.Z{1}; % 提取连续ZPK零点(SISO系统取cell第一个元素)
p = G_zpk.P{1}; % 提取连续ZPK极点
K = G_zpk.K; % 提取连续ZPK增益
% 构造零点项字符串(如:无零点则显示1)
if length(z) == 0
z_terms = '1';
else
z_terms = '';
for i = 1:length(z)
if i == 1
z_terms = sprintf('(s-%.4f)', z(i));
else
z_terms = sprintf('%s(s-%.4f)', z_terms, z(i));
end
end
end
% 构造极点项字符串
p_terms = '';
for i = 1:length(p)
if i == 1
p_terms = sprintf('(s-%.4f)', p(i));
else
p_terms = sprintf('%s(s-%.4f)', p_terms, p(i));
end
end
% 拼接连续ZPK表达式
G_zpk_expr = sprintf('G(s) = %.4f · %s / %s', K, z_terms, p_terms);
disp('\n(2) 零极点(ZPK)模型的传递函数:');
%disp('--- Matlab默认格式 ---');
%disp(G_zpk);
disp('--- 直观ZPK表达式 ---');
disp(G_zpk_expr);
% 部分分式模型(通过residue函数分解)
[num_tf, den_tf] = tfdata(G_closed, 'v'); % 获取TF的分子、分母向量
[r, p, k] = residue(num_tf, den_tf); % 计算留数、极点、直接项
% ========== 补充:构造部分分式的直观表达式 ==========
pf_expr = 'G(s) = ';
% 拼接留数+极点项
for i = 1:length(r)
if i == 1
pf_expr = sprintf('%s %.4f/(s - %.4f)', pf_expr, r(i), p(i));
else
pf_expr = sprintf('%s + %.4f/(s - %.4f)', pf_expr, r(i), p(i));
end
end
% 拼接直接项(如果k≠0)
if k ~= 0
pf_expr = sprintf('%s + %.4f', pf_expr, k);
end
disp('--- 部分分式模型 ---');
disp('参数:');
disp(['留数 r = ', mat2str(r, 4)]);
disp(['极点 p = ', mat2str(p, 4)]);
disp(['直接项 k = ', mat2str(k)]);
disp('直观表达式:');
disp(pf_expr);
运行结果(表达式):

(3)修改TF模型属性并查看
添加代码:
matlab
%% (3) 修改TF模型的属性并查看
set(G_closed, ...
'InputName', '温度设定', ...
'OutputName', '温度输出', ...
'Notes', '温度闭环控制系统');
disp('\n(3) 修改属性后的TF模型信息:');
disp(get(G_closed)); % 查看模型属性
运行结果会显示:输入名=温度设定,输出名=温度输出,备注=温度闭环控制系统。

(4)ZPK模型离散化(采样时间0.1s)
添加代码:
matlab
%% (4) ZPK模型改为离散系统(采样时间0.1s)并查看属性
Ts = 0.1; % 采样时间
% 连续ZPK模型离散化(默认采用零阶保持器)
G_zpk_discrete = c2d(G_zpk, Ts);
% ========== 提取离散ZPK的核心参数,构造直观表达式 ==========
z_d = G_zpk_discrete.Z{1}; % 离散零点数组
p_d = G_zpk_discrete.P{1}; % 离散极点数组
K_d = G_zpk_discrete.K; % 离散增益
% 构造离散零点项字符串
z_d_terms = '';
if length(z_d) == 0
z_d_terms = '1';
else
for i = 1:length(z_d)
if i == 1
z_d_terms = sprintf('(z-%.4f)', z_d(i));
else
z_d_terms = sprintf('%s(z-%.4f)', z_d_terms, z_d(i));
end
end
end
% 构造离散极点项字符串
p_d_terms = '';
for i = 1:length(p_d)
if i == 1
p_d_terms = sprintf('(z-%.4f)', p_d(i));
else
p_d_terms = sprintf('%s(z-%.4f)', p_d_terms, p_d(i));
end
end
% 拼接离散ZPK表达式
G_zpk_d_expr = sprintf('G(z) = %.4f · %s / %s (Ts=%.1fs)', K_d, z_d_terms, p_d_terms, Ts);
% ========== 输出离散ZPK结果 ==========
disp('\n(4) 离散化后ZPK模型(采样时间0.1s):');
%disp('--- 直观表达式 ---');
%disp(G_zpk_d_expr);
disp('--- 完整属性(可选) ---');
disp(get(G_zpk_discrete));
运行结果:

任务2:两种M文件求总传递函数

假设系统结构为:G1与G2并联 → 与G3串联 → 与增益10串联;同时增益1与G4并联 → 与增益3串联;最终两部分串联(可根据实际结构图调整,核心是两种编程思路)。
方法1:用series/parallel函数组合
matlab
% 定义各模块传递函数
G1 = tf(1, [2, 2, 1]);
G2 = tf(1, [0.5, 1]);
G3 = tf(1, [1, 1]);
G4 = tf(1, [4, 1]);
K1 = tf(1); % 增益1
K3 = tf(3); % 增益3
K10 = tf(10); % 增益10
% 第一部分:G1并联G2 → 串联G3 → 串联K10
part1 = series(parallel(G1, G2), G3);
part1 = series(part1, K10);
% 第二部分:K1并联G4 → 串联K3
part2 = series(parallel(K1, G4), K3);
% 总传递函数(两部分串联)
G_total1 = series(part1, part2);
disp('方法1:总传递函数');
G_total1
方法2:直接通过多项式运算(手动展开)
matlab
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear; clc;
syms s;
% 1. 定义各个模块(修正G3)
G1 = 1/(10*s + 1);
G2 = 1/(s + 1);
G3 = 1/(s^2 + 2*s + 1); % 修正:1/(s²+2s+1)(原错误是2*s^2+2*s+1)
G4 = 3/(4*s + 1);
G5 = 1/(0.5*s + 1);
% 2. 计算并联、串联
G_parallel = G3 + G5;
G_series = G2 * G_parallel;
% 3. 总传递函数
T2 = (G1 * G_series) / (1 + G_series * G4);
T2 = simplify(T2);
% 输出结果
disp('================方法2 结果 ================');
disp(T2);
两种方法运行结果一致,验证了模型的正确性。

任务3方法一:天线臂仰角控制系统Simulink建模与仿真

步骤1:编写S函数
新建Matlab脚本,复制"编程知识介绍"中S函数的完整代码,保存为sfun_antenna.m(文件名需与函数名一致)。
输入以下代码:
matlab
function antenna_sfunc(block)
% Level-2 MATLAB S-Function 为天线臂仰角系统建模
setup(block);
% -----------------------------------------------------------------
function setup(block)
% 注册输入和输出端口的数量
block.NumInputPorts = 1; % 输入 u
block.NumOutputPorts = 1; % 输出 [x1; x2]
% 设置输入端口属性
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DirectFeedthrough = false; % 输出不直接依赖输入,依赖状态
% 设置输出端口属性
block.OutputPort(1).Dimensions = 2; % 输出包含 x1 和 x2
% 设置连续状态的数量
block.NumContStates = 2;
% 设置采样时间([0 0] 表示连续系统)
block.SampleTimes = [0 0];
% 注册回调函数
block.RegBlockMethod('InitializeConditions', @InitializeConditions);
block.RegBlockMethod('Outputs', @Outputs);
block.RegBlockMethod('Derivatives', @Derivatives);
% -----------------------------------------------------------------
function InitializeConditions(block)
% 设置初始状态 x1 = 0, x2 = 0
block.ContStates.Data = [0; 0];
% -----------------------------------------------------------------
function Outputs(block)
% 输出当前的两个状态值
block.OutputPort(1).Data = block.ContStates.Data;
% -----------------------------------------------------------------
function Derivatives(block)
% 获取当前状态和输入
x = block.ContStates.Data;
u = block.InputPort(1).Data;
x1 = x(1);
x2 = x(2);
% 根据微分方程计算导数
dx1 = x2;
dx2 = 9.81 * sin(x1) - 2 * x2 + u;
% 将导数写回
block.Derivatives.Data = [dx1; dx2];
步骤2:搭建Simulink模型
-
打开Matlab,输入
simulink启动Simulink,新建空白模型; -
添加模块:

-
信号源:从
Simulink/Sources中拖拽Step(单位阶跃,默认参数:Step time=0,Amplitude=1);

-
自定义模块:从
Simulink/User-Defined Functions中拖拽S-Function,双击模块,在S-function name中输入sfun_antenna(加载编写的S函数)【注意S函数要用Level 2的那个】

-
示波器:从
Simulink/Sinks中拖拽Scope,搜索找到"Dumax"如图所示接线

-
-
连接模块:
Step输出 →S-Function输入;S-Function输出 →Dumax输入Dumax两个输出→ 两个Scope输入; -
保存模型为
antenna_model.slx。
步骤3:运行仿真并查看结果
- 点击Simulink模型中的"运行"按钮(▶️),仿真时长默认10s;
- 查看示波器:x1(仰角)呈现衰减振荡后趋于稳态,x2(角速度)先峰值后衰减至0,符合非线性系统的阶跃响应特性。

任务3方法二:天线臂仰角控制系统DEE建模与仿真
新建MATLAB空白文件,输入以下代码:
matlab
function dxdt = antenna_dynamics(t, x)
% 状态变量:x = [x1; x2]
% 输入u:单位阶跃(t≥0时u=1)
u = 1; % 单位阶跃输入
% 计算状态导数
dx1 = x(2); % dx1/dt = x2
dx2 = 9.81*sin(x(1)) - 2*x(2) + u; % dx2/dt = 9.81*sin(x1) -2x2 + u
dxdt = [dx1; dx2];
end
这个代码保存为antenna_dynamics.m文件
在同一个目录下再次新建空白MATLAB文件,输入以下代码:
matlab
% 初始状态:x1(0)=0, x2(0)=0
x0 = [0; 0];
% 仿真时间范围(0到10秒)
tspan = [0 10];
% 调用ode45求解微分方程
[t, x] = ode45(@antenna_dynamics, tspan, x0);
% 绘制x1和x2的波形
figure('Name','ode45求解结果');
subplot(2,1,1);
plot(t, x(:,1), 'LineWidth',1.5);
xlabel('时间 t (s)'); ylabel('x_1 (仰角)');
title('x_1的变化波形'); grid on;
subplot(2,1,2);
plot(t, x(:,2), 'LineWidth',1.5);
xlabel('时间 t (s)'); ylabel('x_2 (仰角速率)');
title('x_2的变化波形'); grid on;
此代码随便命名,符合规范既可,点击运行结果如下:

总结
实验四围绕"控制系统建模"的核心目标,覆盖了从"线性系统模型转换"到"非线性系统自定义建模"的全流程,核心收获如下:
- 理论层面:理解了TF、ZPK、部分分式模型的本质的转换逻辑,掌握了非线性系统的状态方程描述方法;
- 编程层面:熟练运用Matlab的LTI工具包(
tf/zpk/residue/c2d),学会了S函数的编写逻辑(初始化、导数计算、输出计算); - 实操层面:掌握了Simulink的基础建模流程,能将自定义S函数嵌入模型,实现非线性系统的仿真。
实操中需注意的关键点:
- 模型转换前需准确推导开环传递函数(依赖系统结构图的连接关系);
- S函数的初始化参数(状态个数、输入输出个数)需与系统匹配,否则会报错;
- 离散化时需指定正确的采样时间和方法(实验中用零阶保持ZOH,适合工业控制系统)。