根轨迹法大概是最容易被低估的一个控制器设计工具。课堂上它是画图题:给一个开环传递函数,画根轨迹、判断稳定性、算分离点。但在实际工程里,它的真实用途是解决"我想要系统又快又稳,控制器参数到底该取多少"这种具体问题。配合Simulink的仿真建模,根轨迹法可以从纸上的一条特征根曲线,变成一套可以直接验证、反复微调的控制器参数。
这篇文章就聚焦一件事:从性能指标出发,用根轨迹法设计一个控制器,然后在Simulink里把整个闭环系统搭出来,跑通仿真、量化指标、再处理实际工程中常见的偏差。适合正在学自动控制原理、对Simulink建模还不太熟的同学,也适合刚入行、需要快速完成控制器整定的工程师。后面所有步骤我都会给出能被复现的具体数值和操作细节,不是泛泛而谈。
1. 先搞清楚根轨迹法到底在设计什么
我在看很多初学者接触根轨迹的时候,注意力全放在"怎么画图"上,结果画完之后不知道拿这张图干什么。其实根轨迹法的核心思想特别直白:系统的闭环极点决定动态特性,而闭环极点会随着开环增益变化。根轨迹就是描述"开环增益从0变到无穷时,闭环极点走了哪些位置"的一套曲线。
1.1 根轨迹画的不是轨迹,是闭环极点的"搬迁路线"
假设有一个单位负反馈系统,开环传递函数为G(s),闭环传递函数是G(s)/(1+G(s)),闭环极点就是1+G(s)=0的根。如果把G(s)写成K·N(s)/D(s)的形式,那么特征方程就是1 + K·N(s)/D(s)=0,整理一下就是D(s) + K·N(s)=0。K从0开始增大时,特征方程的根会在复平面上移动,这些移动路径就是根轨迹。
图上的"x"和"o"分别表示开环极点和开环零点,"x"是D(s)=0的点,"o"是N(s)=0的点。根轨迹从开环极点出发,终止于开环零点或无穷远。你通过改变K,就能让闭环极点"走到"目标位置。而闭环极点落在哪里,直接决定了超调量、调节时间、振荡频率这些性能指标。所以根轨迹法本质上是在回答一个问题:我想要极点落在某个位置,开环增益K应该取多少,或者控制器结构要改成什么样。
1.2 设计控制器就是给系统"装根装零"
如果只用增益K,你能做的只是沿着已经存在的根轨迹移动极点,但有时候这根轨迹根本不会经过你想要的位置。好比一条路是固定的,你想去的地方不在路上,那光踩油门没用。这时候就需要控制器C(s)来"修路"——通过给系统加零点和极点,硬生生把根轨迹掰到目标区域附近。
超前校正、滞后校正、PID,本质上都是加零点和极点。超前校正在左半平面加一个零点和一个更靠左的极点,用来增大相角裕度、把根轨迹往左拉,让系统更快更稳;滞后校正在原点附近加一个极点和一个零点,用来提高低频增益、改善稳态误差。理解了这一步,你就明白了:Simulink里那些一两行的仿真案例,背后就是这套"搬极点、拉轨迹"的思路。
2. 一个二阶积分对象,先建模再画根轨迹找差距
纸上谈兵没有意义。为了把整个流程串起来,我选一个很典型的被控对象:一个电枢控制的直流电机位置系统,经过简化之后可以用二阶积分环节来描述。这个模型在自动控制教材里很常见,真实系统中不少转速控制、位置控制对象也都能近似成这样。
2.1 用传递函数描述被控对象:为什么选4/[s(s+2)]
这类系统的典型传递函数是
G(s) = K / [s·(s + a)]
这里分母里有一个积分环节s,意味着系统是Ⅰ型系统,对阶跃输入天然无静差;另一个惯性环节s+a来自电机的机电时间常数。为了让数值好算,我取K=4、a=2,即:
G(s) = 4 / [s(s + 2)]
这个对象开环极点两个:0和-2,没有开环零点。这是一个结构最简单又不失代表性的模型——它有一个积分环节,有真实的惯性,能体现设计过程中各种典型问题。你在MATLAB命令行敲下面三行,就能得到它的根轨迹图:
s = tf('s'); G = 4/(s*(s+2)); rlocus(G);2.2 未校正系统的根轨迹与性能差距
先看这个系统直接用单位负反馈、什么都不加时的表现。它的闭环特征方程是s^2+2s+4=0,闭环极点是-1±j√3,阻尼比ζ=0.5,自然频率ωn=2 rad/s。按照经典二阶系统公式估算,阶跃响应超调量大约是
σ≈exp(-πζ/√(1-ζ^2))≈16.3%
调节时间(按2%误差带)约为
ts≈4/(ζ·ωn)=4s
现在给出一组设计指标:超调量不超过15%,调节时间不超过3秒。对比一下,16.3%和4秒全部超标,而且不是差一点。更关键的是,如果我只把K往大调,根轨迹会沿着一条固定曲线走:K增大时,闭环极点从实轴上的0和-2汇合,然后沿着垂直于实轴的方向进到复平面。K取不同值时,阻尼比会变,系统不一定能同时满足又快又稳。我需要的是在根轨迹上找到一个位置,同时满足阻尼比够大、自然频率够高,这个位置还得是能通过调整K到达的。
2.3 性能指标翻译成期望主导极点位置
设计控制器之前,第一步是把时域指标变成复平面上的"期望区域"。这里要用到两组经典近似公式:
超调量与阻尼比的关系:
σ≈exp(-πζ/√(1-ζ^2))
调节时间与阻尼比、自然频率的关系(2%误差带近似):
ts≈4/(ζ·ωn)
按照ζ=0.55左右,ωn取大一点,可以计算得到σ大约9.6%、ts大约3s以内,留出余量。我取期望主导极点为
s_d = -1.4 ± j1.9
这个点对应的阻尼比约0.59,自然频率约2.36 rad/s,理论上超调10%上下,调节时间2.9秒左右,满足15%、3秒的指标。后面所有设计工作,就是想办法让闭环主导极点落到这个点附近。在MATLAB里可以用sgrid把阻尼比和自然频率网格叠到根轨迹上:
sgrid(0.55, 2.36);这样你一眼就能看出,未校正系统想要通过调K让主导极点落在期望区域还差多少。
3. 超前校正设计:手算零极点与增益的完整过程
目标明确了,接下来就需要设计控制器。这一步我不建议直接打开Simulink拖模块,而是先在MATLAB里或者手算把控制器结构定下来。原因很简单:Simulink是验证工具,不是设计工具。你在仿真里盲目调参数,调出来的结果往往只对当前工况有效,换个输入信号就露馅。先有了理论依据,后面仿真才有对照。
3.1 为什么要加超前校正而不是直接调增益
理论上,未校正系统的根轨迹上确实存在阻尼比大于0.5的点,比如K=4时闭环极点就在ζ=0.5的等阻尼比线上,但是自然频率只有2 rad/s,调节时间要到4秒。如果继续增大K,阻尼比会下降,超调变大;如果减小K,响应变慢。换句话说,仅靠调增益,无法把期望极点"搬"到-1.4±j1.9的位置,因为-1.4±j1.9根本不在未校正系统的根轨迹上。
超前校正的作用就是通过加一个零点和一个更靠左的极点,把根轨迹往左"掰",让期望极点成为闭环极点。从另一个角度看,超前校正和PD控制的思路是相通的,但PD控制器的纯微分项会放大高频噪声,物理实现上也不如用一个零点加极点的超前网络来得自然。所以在Simulink里,我用连续传递函数的形式搭超前校正器,这也是实际工程中最常见的做法。
3.2 相角补偿量怎么算
超前校正的设计逻辑是:如果期望极点是闭环极点,那它必须满足根轨迹的相角条件和幅值条件。具体来说,校正后开环传递函数C(s)G(s)在s_d处的相角必须是-180°(或者180°,取决于你习惯的写法)。把C(s)写成Kc(s+z)/(s+p)的形式,我们需要满足:
∠(s_d+z) - ∠(s_d+p) + ∠G(s_d) = -180°
先算一下未校正的∠G(s_d)。s_d=-1.4+j1.9,两个极点分别在0和-2。从s_d到极点0的向量是-1.4+j1.9,相角约是126.4°;到极点-2的向量是0.6+j1.9,相角约72.4°。所以:
∠G(s_d) = -126.4° - 72.4° = -198.8°
等价换算一下,这里离-180°差了大约18.8°。理论上校正器只需提供约18.8°的相位,但工程上我都会留一点余量,取20°到25°。这里取20°,这样即使后续增益略偏,系统也不至于马上掉到指标之外。通过上面的公式,可以反推零点和极点的几何关系。
3.3 零极点位置与增益的求法
设计超前校正零极点位置,有标准的几何做法。第一步先放零点,我把零点放在s_d左侧后方附近,比如z=2.2。这个选择有一定自由度,但会影响最终增益和实际响应,先不深究,下文第5章我专门讲这个。
当z=2.2时,从s_d到零点-2.2的向量是0.8+j1.9,相角约67.2°。要在s_d处产生20°的超前相位,那么从s_d到极点-p的向量相角必须是67.2°-20°=47.2°。于是存在单调关系:
设s_d+p = (p-1.4)+j1.9,其相角为47.2°,即1.9/(p-1.4) = tan(47.2°)。算出来p-1.4约等于1.76,所以p≈3.16。
这样校正器的零极点就确定了,初步形式为:
C0(s) = (s+2.2)/(s+3.16)
接着用幅值条件求增益Kc。幅值条件要求校正后开环幅值在s_d处为1,即:
|Kc·C0(s_d)·G(s_d)| = 1
逐个算模长:|s_d|=√(1.4^2+1.9^2)≈2.36;|s_d+2|≈1.99;|s_d+2.2|≈2.06;|s_d+3.16|≈2.59。代入得到:
Kc·4·2.06/(2.36·1.99·2.59) = 1
解出来Kc约等于1.48,我取整到1.5。最终校正器就是:
C(s) = 1.5(s+2.2)/(s+3.16)
注意,这里的Kc不是根轨迹图上那个K。根轨迹图默认的是C(s)G(s)的整体环路增益,C0(s)里面增益是1,Kc是作为额外增益叠上去的。这一步搞混的话,后面验证会陷入混乱。
3.4 用rlocus验证设计结果
设计完就赶紧验证。在MATLAB里把C0和G乘起来,画根轨迹:
C0 = (s + 2.2)/(s + 3.16); L0 = G * C0; rlocus(L0); sgrid(0.55, 2.36);这时你会看到,校正后的根轨迹恰好从期望极点附近弯了过去。再用rlocfind点一下期望极点附近,查看对应的增益:
K = rlocfind(L0);点选-1.4+j1.9附近,返回的K应该非常接近1.5。这说明前面手算的零极点位置和增益是自洽的。到这里,控制器设计的关键数值已经全部确定:C(s)=1.5(s+2.2)/(s+3.16),就等仿真验证了。
4. Simulink仿真模型搭建:模块选择、参数与接线细节
控制器设计完了,进入Simulink仿真建模环节。这一步不需要什么高深技巧,但有几个细节处理不好会让结果完全不可信,甚至模型跑出奇奇怪怪的波形。我按搭建顺序一步步说。
4.1 模型整体结构与信号流程
先明确闭环结构:Step阶跃信号作为输入,经过Sum求和节点,进入控制器C(s),再到被控对象G(s),对象输出就是系统响应。把对象输出引回Sum求和节点的负输入端,形成单位负反馈。这样闭环传递函数就是C(s)G(s)/(1+C(s)G(s))。
在模型里我习惯用Transfer Fcn模块而不是Pole-Zero模块。Transfer Fcn直接填分子分母系数,出错概率低;Pole-Zero模块虽然也能填零极点,但对初学者来说反而容易把增益和零极点搞混。控制器Transfer Fcn参数这样填:
- Numerator:
[1.5 3.3],因为C(s)=1.5(s+2.2)=1.5s+3.3,注意这是分子展开后的系数,不是零极点形式。 - Denominator:
[1 3.16],因为分母是s+3.16。
被控对象Transfer Fcn参数这样填:
- Numerator:
[4] - Denominator:
[1 2 0],对应s^2+2s+0,千万别漏了最后一个0,漏了就成了1+2s,物理含义完全错误。
Sum求和模块在Math Operations库,双击打开参数对话框,把List of signs设置为|+-。竖线表示信号主输入路径,加号是给定输入,减号是反馈输入。如果保持默认的++,系统就变成正反馈了,仿真一跑必飞。
4.2 各模块参数与连线顺序
从Simulink库浏览器里拖出Step、Sum、Transfer Fcn(两个)、Scope,按顺序连线,最后用一条线从对象输出端拉回Sum的负输入。这个连线顺序不要乱,先连"Step→Sum→控制器→对象→Scope",再连反馈线。如果先连反馈线,容易把主线擦掉。
双击Step设置参数,我一般把Step time设为0,Initial value设为0,Final value设为1。这样结果就是标准的单位阶跃响应。
Scope不需要特别设置,但只靠Scope肉眼读指标很吃力,所以更推荐加一个To Workspace模块。接线方式是:对象输出接一个Mux或直接给To Workspace,我通常是再复制一条线到To Workspace。设置变量名yout,保存格式选Timeseries。仿真完在命令窗口就能用plot(yout.Time, yout.Data)自己画图。
4.3 求解器、步长与Scope的配置
Simulink默认的求解器是变步长ode45,多数连续系统仿真的确够用。这个模型是连续的线性系统,用ode45没问题,但有个隐患:如果Max step size不限制,快速非线性或者大增益系统的瞬态可能被跳过。所以我习惯把Model Settings里的Max step size设成0.01秒,仿真停止时间设成5秒,既能看到完整的调节过程,又不会因为步长过大把峰值"切掉"。
有一个很实用的检查方法:看信号线上的颜色。Simulink里连续时间信号是黑色线,离散信号是点划线。如果出现红色虚线,说明信号类型不匹配,多半是有模块把连续信号当离散处理了。这个模型里所有模块都是连续时间模块,正常连线应该全是黑线。出现彩色线时先别急着仿真,停下来检查。
5. 仿真结果校验:指标差在哪里、为什么差、怎么调
模型搭完之后,仿真只是几秒钟的事。但真正有价值的,是把仿真结果和设计指标放在一起对比。这里最容易踩坑的地方在:根轨迹法设计的是一个"期望闭环极点",但系统在动态过程中不只是那一对主导极点在工作,设计时的近似误差会在这里暴露无遗。
5.1 从Scope数据量化超调和调节时间
点击Run之后,Scope里应该出现一条先上升、到峰值后回落、最终稳定在1.0附近的曲线。看个大概不是目的,我要的是量化数据。如果刚才加了To Workspace,可以在命令窗口写:
y = yout.Data; t = yout.Time; S = stepinfo(y, t, 1)stepinfo会直接返回超调量Overshoot、调节时间SettlingTime、峰值Peak等指标。这个比肉眼看Scope精准得多,也方便你在调整参数时做前后对比。把这个结果和初始设计指标对一下。如果超调在13%~15%左右、调节时间在3秒上下,说明设计基本合格,可以直接用了。
5.2 超调比理论高,罪魁往往是零点效应
这里有一个所有根轨迹设计者都会遇到的现象:手算的时候,期望主导极点对应的超调理论值是10%左右,但Simulink仿真跑出来往往偏高,达到14%甚至超过15%。这不是算错了,而是"零点效应"在起作用。
我在第3章选择的零点z=2.2,距离主导极点-1.4+j1.9并不算远。这个零点虽然不改变闭环极点位置,但它会让阶跃响应的初始阶段出现"额外抬升",直观表现就是超调变大。极点p=3.16也离主导极点不远,它的影响相对小一些,但和零点一叠加,实际响应就不可能和理想二阶模型完全一致。
遇到这种情况不要急着改结构,可以分两步调整:第一,把增益Kc从1.5降到1.35~1.4重新仿真,观察超调是否回到允许范围。增益降低会让实际闭环极点略向下移动,虽然不完全在期望位置,但往往能换取更低的超调。第二,如果降增益导致调节时间变长,那就把零点往左移动,比如z=2.8,重新算一遍p和Kc,让零点离主导极点更远,零点效应会减弱,超调也会更接近理论值。
这个微调过程,就是工程和教科书的差别。教科书给你一个精确解,工程则是在精确解附近找一个满足所有约束的可行解。仿真模型的价值就在这里:你可以放心大胆地试,几秒钟就能看到结果。
5.3 工程约束:增益调整与执行器饱和
单纯的线性仿真通过指标之后,还可以往前再走一步:加入工程约束。最常见的就是执行器饱和。控制器输出范围是有限的,电机力矩、阀门开度不可能无限大。在Simulink里,可以在控制器和被控对象之间加一个Saturation模块,设置上下限,比如±5。然后给一个较大的阶跃输入(比如从0到5),再看系统响应。这时候会出现一个新现象:控制器输出顶到饱和限,相当于开环增益被临时降低,系统的有效动态变成非线性,实际响应会和线性仿真差别很大,超调率反而可能更低,但调节过程会拖出更长的"尾巴"。
这个现象本身不是坏事,它说明你选的控制器增益在正常工作范围内是合适的。真正要警惕的是:如果线性仿真结果非常漂亮,但你给控制器输出加一个很窄的饱和限后系统出现极限环振荡,那说明校正器增益或者零极点位置在非线性约束下不够鲁棒。这时候通常的做法是降低Kc、重新评估期望极点位置,或者干脆换结构。
6. 进阶:让根轨迹设计在Simulink里形成闭环
最后再讲两个提升效率的技巧。这套流程走熟之后,你会发现根轨迹法和Simulink仿真建模其实是同一个工作流的两个阶段:根轨迹负责"设计",Simulink负责"验证"。但如果能掌握图形化工具和几种常用校正结构的切换,整个过程的迭代速度还能再快一个量级。
6.1 用Control System Designer做图形化拖拽
MATLAB里有一款叫Control System Designer的交互工具,输入controlSystemDesigner(G)就能打开。它会同时显示根轨迹图、波特图和闭环阶跃响应,你可以直接用鼠标拖拽校正器的零点和极点位置,每拖一下,根轨迹曲线和阶跃响应曲线都会实时更新。这样就不用手算一轮、仿真一次,再回来调整,人眼能直观判断"极点往哪边挪,超调会变大还是变小"。
这个工具的用法和手算并不冲突。手算给出了一个合理起点,图形化拖拽是在这个起点附近做局部搜索。Simulink模型搭好之后,还可以把MATLAB里设计好的C(s)直接导成Simulink中的Transfer Fcn参数,不需要手动展开多项式,减少出错。
6.2 什么时候该换滞后校正或PID
这篇文章用的例子,性能差距集中在"响应不够快",所以超前校正是最合适的选择。但实际项目里往往还有稳态精度的问题。比如系统开环增益不够,斜坡输入下稳态误差超标,这时超前校正帮不上忙,需要在前面串一个滞后网络:在原点和左侧较近处加一个极点和一个零点,比如( s+0.1 )/( s+0.01 ),用"低频抬增益"的方式改善稳态误差。
更通用的做法是直接设计PID。PID的P和D部分等价于一个超前校正的效应,I部分承担稳态精度。在Simulink里用PID Controller模块时,把PID的零点极点规律和根轨迹图对照着看,调试起来会非常有方向感——你现在知道P是"改变增益、把极点沿轨迹移动",D是"加零点、把轨迹往左拉",I是"在原点附近加极点、抬高低频增益"。知道这些之后,调PID就不再是黑盒试错了。根轨迹法给静态公式注入了动态直觉,这也是我建议每个做控制的都把它吃透的根本原因。