
1. 为什么还要用Matlab搭控制系统模型控制系统这门课很多人第一次接触的时候都会有一种割裂感。课堂上老师写微分方程、画根轨迹、算传递函数一套流程下来行云流水但真到了要自己动手做一个控制器、调一组参数的时候往往不知道从哪里下手。我当年也是这样纸面上会算实际面对一个电机或者一个温控系统脑子里一片空白。后来带过几个做课设和项目的同学我发现问题的根源不在于数学没学好而在于缺少一个能把“理论”和“实物”连起来的中间环节。Matlab就是这个中间环节。它不需要你立刻去焊电路、接传感器而是让你先在软件里把系统的行为描述清楚然后观察它到底怎么响应、怎么振荡、怎么稳定下来。这个过程反复几轮之后你对控制系统的直觉就建立起来了。这篇笔记要聊的就是怎么用Matlab从零开始建立一个控制系统模型。我会从最基础的传递函数讲起一路走到状态空间、时域响应、频域分析最后落到一个完整的建模流程上。内容偏向实操适合正在学自动控制原理、做课程设计或者工作中需要快速验证控制方案的朋友。不需要你有多深的Matlab基础但最好对拉普拉斯变换和微分方程有一点概念不然有些地方会卡住。我个人的习惯是拿到一个控制系统问题先在Matlab里把模型搭出来跑一遍看看它的开环特性、闭环响应再决定用什么控制器。这个顺序比上来就调PID要靠谱得多因为你得先知道对手长什么样才知道用什么招式。2. 控制系统建模的核心思路拆解2.1 从物理系统到数学模型的映射逻辑建立控制系统模型本质上就是做一次翻译。把物理世界里那些电机、弹簧、电容、热阻之类的东西翻译成数学语言。这个翻译过程有固定的套路但每一步都有坑。最常见的翻译路径是这样的先根据物理定律写出微分方程然后对微分方程做拉普拉斯变换得到传递函数最后把传递函数输入到Matlab里。听起来很简单但实际操作中很多人卡在第一步——微分方程写不对。比如一个简单的质量-弹簧-阻尼系统牛顿第二定律列出来是 $m\ddot{x} c\dot{x} kx F$这个没问题。但如果是一个电机系统涉及到电磁转矩和反电动势方程就会复杂很多稍不注意就漏掉一项。我的建议是写微分方程的时候不要急着化简先把所有相关的物理关系都列出来包括本构方程、守恒方程、几何约束然后再消元。这样虽然看起来笨但不容易出错。Matlab在这里的作用是你不需要手动去解这些方程只需要把系数提取出来就行。注意微分方程的阶数决定了传递函数的分母阶数也决定了状态变量的个数。如果你发现传递函数的阶数和预期不符大概率是微分方程列错了。2.2 传递函数、状态空间、零极点增益三种模型怎么选Matlab提供了三种主要的模型表示方式传递函数tf、状态空间ss、零极点增益zpk。很多人一开始会纠结用哪种其实它们之间可以互相转换选哪种主要看你的使用场景。传递函数适合单输入单输出系统形式直观就是分子多项式除以分母多项式。你在经典控制理论里学的根轨迹、伯德图、奈奎斯特图都是基于传递函数的。如果你做的是SISO系统的频域设计用tf最方便。状态空间适合多输入多输出系统或者需要分析系统内部状态的场景。现代控制理论里的极点配置、LQR、卡尔曼滤波都依赖状态空间模型。状态空间的好处是它把系统内部的所有状态变量都显式地表示出来了你能看到每个状态怎么演化。零极点增益形式则介于两者之间它把传递函数写成增益乘以若干一阶环节的乘积每个环节对应一个零点或极点。这种形式在分析系统的主导极点、做模型降阶的时候特别有用。我个人的习惯是先用tf把模型搭起来快速看一下时域和频域响应。如果发现系统是多变量的或者需要做状态反馈再转成ss。zpk一般用在需要手动配置零极点的时候比如设计超前滞后校正器。模型类型适用场景优点缺点传递函数 tfSISO系统、频域设计形式直观、工具函数丰富不适合MIMO、内部状态不可见状态空间 ssMIMO系统、现代控制内部状态可见、适合数值计算矩阵形式不够直观零极点增益 zpk零极点配置、模型降阶零极点一目了然不适合复杂系统2.3 建模精度与复杂度的平衡取舍建模的时候很多人会陷入一个误区追求越精确越好。但实际上控制系统的模型从来都是对现实的近似关键是要抓住主导动态忽略次要因素。举个例子一个直流电机完整的模型要考虑电枢电感、电枢电阻、转动惯量、粘性摩擦、负载转矩甚至还有磁饱和、温度漂移。但如果你只是设计一个速度控制器电枢电感的时间常数通常远小于机械时间常数可以忽略这样模型就从三阶降到二阶分析和设计都简单很多。Matlab在这里的好处是你可以很方便地做模型降阶和对比。先用完整模型跑一遍再用简化模型跑一遍看看两者的响应差异有多大。如果差异在可接受范围内就用简化模型省时省力。提示模型降阶的常用方法有主导极点法、平衡截断法、奇异值分解法。Matlab的balred和modred函数可以直接做这件事。3. 核心细节解析与实操要点3.1 传递函数建模的完整操作流程传递函数是Matlab里最常用的模型形式建立过程分三步定义分子分母系数、创建tf对象、验证模型。假设我们要建立一个二阶系统传递函数是 $G(s) \frac{10}{s^2 2s 10}$。在Matlab里代码是这样的num [10]; den [1 2 10]; G tf(num, den);这里num和den分别是分子和分母多项式的系数向量按降幂排列。注意系数向量里不能有缺项缺的项要补零。比如 $s^2 10$分母系数是[1 0 10]中间的s项系数是0不能省略。创建完tf对象后可以用G直接查看模型信息Matlab会输出分子分母、极点和零点。也可以用pole(G)和zero(G)单独查看。对于更复杂的系统比如多个环节串联、并联、反馈Matlab提供了series、parallel、feedback函数。但更简洁的方式是用运算符G1 * G2表示串联G1 G2表示并联feedback(G1, G2)表示反馈连接。G1 tf([1], [1 1]); G2 tf([10], [1 5]); G_series G1 * G2; G_parallel G1 G2; G_feedback feedback(G1, G2);注意feedback函数默认是负反馈如果是正反馈需要加第三个参数1。3.2 状态空间建模的关键参数与矩阵构建状态空间模型的形式是 $\dot{x} Ax Bu$$y Cx Du$。在Matlab里用ss函数创建A [0 1; -10 -2]; B [0; 10]; C [1 0]; D 0; sys ss(A, B, C, D);A矩阵是系统矩阵描述状态变量之间的耦合关系B矩阵是输入矩阵描述输入如何影响状态C矩阵是输出矩阵描述状态如何组合成输出D矩阵是直接传递矩阵通常为0除非系统有直接馈通。构建状态空间模型的关键是确定状态变量。对于机械系统状态变量通常选位置和速度对于电路系统选电容电压和电感电流对于热系统选各节点的温度。状态变量的个数等于系统中独立储能元件的个数。从传递函数转状态空间可以用ss(G)反过来从状态空间转传递函数用tf(sys)。这两个转换在Matlab里是一行代码的事但要注意转换后的模型可能不是最小实现也就是说可能存在零极点对消。可以用minreal函数做最小实现。sys_min minreal(sys);3.3 时域响应分析的操作细节模型建好之后第一件事就是看时域响应。Matlab提供了step、impulse、lsim三个常用函数。step(sys)画阶跃响应这是最常用的因为阶跃信号能激发系统的全部动态。impulse(sys)画冲激响应适合分析系统的自然特性。lsim(sys, u, t)画任意输入的响应u是输入信号t是时间向量。t 0:0.01:10; step(sys, t); grid on;阶跃响应图上能读出几个关键指标上升时间、峰值时间、超调量、调节时间、稳态误差。这些指标直接反映了系统的动态性能。比如超调量太大说明阻尼不够调节时间太长说明系统响应慢。提示stepinfo(sys)可以直接输出这些性能指标不用手动读图。对于多输入多输出系统step会画出多个子图每个子图对应一个输入输出对。这时候图会比较乱建议用step(sys(1,1))单独看某个通道。3.4 频域分析的核心要点频域分析是控制系统设计的重头戏。Matlab提供了bode、nyquist、nichols三个函数。bode(sys)画伯德图包括幅频特性和相频特性。从伯德图上能读出幅值裕度和相位裕度这两个指标直接反映了系统的稳定性和鲁棒性。幅值裕度大于6dB、相位裕度大于45度通常认为是比较安全的。bode(sys); grid on; margin(sys);margin(sys)会直接在图上标出幅值裕度和相位裕度非常方便。nyquist(sys)画奈奎斯特图用来判断闭环系统的稳定性。奈奎斯特判据是如果开环传递函数的奈奎斯特曲线包围(-1, j0)点的圈数等于开环右半平面极点数则闭环系统稳定。nichols(sys)画尼科尔斯图在需要同时看幅值和相位的时候比较有用。注意频域分析的前提是系统是线性的。如果系统有非线性环节比如饱和、死区频域分析的结果只能作为参考。4. 实操过程与核心环节实现4.1 一个直流电机速度控制系统的完整建模光讲函数太干我们用一个完整的例子串一遍。假设要建立一个直流电机的速度控制系统电机的物理参数如下电枢电阻 $R 1\Omega$电枢电感 $L 0.5H$转动惯量 $J 0.01kg\cdot m^2$粘性摩擦系数 $b 0.1N\cdot m\cdot s$转矩常数 $K_t 0.01N\cdot m/A$反电动势常数 $K_e 0.01V\cdot s/rad$。第一步列微分方程。电枢回路$L\frac{di}{dt} Ri u - K_e\omega$。机械方程$J\frac{d\omega}{dt} b\omega K_t i$。第二步拉普拉斯变换。设初始条件为零得到 $LsI(s) RI(s) U(s) - K_e\Omega(s)$$Js\Omega(s) b\Omega(s) K_t I(s)$。第三步消去电流$I(s)$得到传递函数。从电枢方程解出 $I(s) \frac{U(s) - K_e\Omega(s)}{Ls R}$代入机械方程整理后得到$$\frac{\Omega(s)}{U(s)} \frac{K_t}{(Ls R)(Js b) K_t K_e}$$代入参数R 1; L 0.5; J 0.01; b 0.1; Kt 0.01; Ke 0.01; num [Kt]; den conv([L R], [J b]) [0 0 Kt*Ke]; G tf(num, den);这里conv函数用来做多项式乘法[0 0 Kt*Ke]是为了对齐阶数。运行后得到传递函数然后用step(G)看阶跃响应。4.2 模型验证与参数敏感性分析模型建好之后不能直接用得先验证。验证的方法有两种一是和实验数据对比二是做参数敏感性分析。参数敏感性分析在Matlab里很容易做。比如你想看转动惯量$J$变化对系统响应的影响可以写一个循环J_values [0.005 0.01 0.02 0.05]; figure; hold on; for J J_values den conv([L R], [J b]) [0 0 Kt*Ke]; G tf(num, den); step(G); end legend(J0.005, J0.01, J0.02, J0.05); hold off;这样一张图上就能看到不同$J$值下的阶跃响应。实测下来$J$越大系统响应越慢超调越小。这个结论和理论分析一致说明模型是合理的。提示参数敏感性分析不仅能验证模型还能帮你找到对系统性能影响最大的参数后续优化的时候就知道该调哪个。4.3 从模型到控制器的过渡模型验证完之后下一步就是设计控制器。Matlab提供了pidtune函数可以自动整定PID参数C pidtune(G, PID); T feedback(C*G, 1); step(T);pidtune会根据系统的开环特性自动选择一个合适的PID参数使得闭环系统满足一定的相位裕度和带宽要求。当然自动整定出来的参数不一定最优但至少是一个不错的起点。如果想手动调可以用sisotool打开控制系统设计工具图形化地拖拽零极点实时看响应变化。这个工具对于理解控制器参数的影响非常有帮助。注意pidtune默认设计的是串联PID控制器如果系统结构不是标准的单位反馈需要先调整结构。5. 常见问题与排查技巧实录5.1 模型不稳定的排查思路模型跑出来发散是最常见的问题。排查思路分三步先看开环极点再看闭环极点最后看数值问题。开环极点用pole(G)查看。如果有右半平面极点说明开环系统本身就不稳定这时候需要先做镇定。闭环极点用pole(feedback(G,1))查看如果有右半平面极点说明闭环系统不稳定需要调整控制器。数值问题比较隐蔽。比如传递函数的分子分母系数数量级差异太大可能导致数值计算误差。这时候可以用zpk形式重新表示或者做归一化。提示isstable(sys)可以直接判断系统是否稳定省得手动看极点。5.2 仿真结果与理论不符的常见原因有时候仿真结果和理论计算对不上原因通常有这几个一是单位不一致比如角频率用Hz还是rad/s二是系数向量补零错误三是反馈极性搞反了。单位问题最容易被忽略。Matlab默认的频率单位是rad/s如果你用Hz输入结果会差$2\pi$倍。系数向量补零的问题前面提过缺项必须补零。反馈极性feedback默认负反馈如果系统实际是正反馈结果会完全不一样。问题现象可能原因排查方法响应发散闭环右半平面极点pole(feedback(G,1))响应与理论差$2\pi$倍频率单位混淆检查bode图的频率轴单位响应完全不对反馈极性错误检查feedback的第三个参数数值误差大系数数量级差异大用zpk形式或归一化5.3 模型降阶的实操技巧模型降阶不是必须的但如果模型阶数太高分析和设计都会很麻烦。Matlab的balred函数可以做平衡截断降阶sys_reduced balred(sys, 2);第二个参数是目标阶数。降阶之后一定要对比降阶前后模型的频域响应确保在关心的频段内差异不大。bode(sys, sys_reduced); legend(原始模型, 降阶模型);如果差异太大说明降阶阶数选得太低需要增加阶数。我个人的经验是降阶后的模型阶数至少要能覆盖系统的主导动态否则降阶就失去意义了。注意降阶之前最好先做最小实现去掉零极点对消否则降阶结果可能不准。6. 建模之后的扩展方向模型建好、验证完、控制器设计好这只是第一步。后续还有很多可以做的事情。一个是做鲁棒性分析。实际系统的参数不会一成不变比如电机随着温度升高电阻会变化。可以用robuststab和robustperf函数分析系统在参数不确定情况下的稳定性。另一个是做离散化。如果控制器要在数字平台上实现需要把连续模型离散化。Matlab的c2d函数支持多种离散化方法比如零阶保持、双线性变换。sys_d c2d(sys, 0.01, zoh);采样时间的选择很关键一般要求采样频率至少是系统带宽的10倍。采样太快计算负担重采样太慢离散化误差大。还有一个方向是做硬件在环测试。Matlab支持和多种硬件平台联合仿真可以把模型部署到实际控制器上验证算法在真实环境下的表现。这一步是从仿真走向实物的关键。我个人在实际操作中的体会是建模这件事快就是慢慢就是快。前期花时间把模型建准确、验证充分后期调控制器的时候会省很多事。反过来如果模型本身有问题后面怎么调都是白搭。另外Matlab的函数很多不用都记住用到的时候查文档就行关键是要理解背后的控制理论知道每个函数在做什么。