「稳」是一句可以验算的话
到目前为止,「稳定」在这本书里一直是个形容词:它会不会晃、停不停得下来。这一章把它换成一个整数——特征方程有几个根落在右半平面。而更漂亮的是:有一张 1877 年的表,只做加减乘除,不解任何方程,就能把这个整数数出来。
三级惯性的对象(三个 2 秒、3 秒、5 秒的一阶环节串起来,没有任何纯延迟),纯比例控制。
闭环特征方程是 30 s³ + 31 s² + 10 s + (1 + Kp) = 0。
问:Kp 加到多大,这个系统会开始持续振荡?
顺便注意一下选项 A:第 4 章说的其实是「一级惯性不会失稳」。三级呢?
把形容词换成整数
先给「稳定」一个能验算的定义。
一个线性系统的行为,完全由它的特征方程的根决定。这些根一般是复数,写成 σ + jω。而每一个根对应响应里的一项:
根 s = σ + jω 对应响应里的一项 e^(σt) · [ 正弦,频率 ω ]
└──┬──┘ └──────┬──────┘
它长不长大 它晃不晃
★ 所以一个根只说两件事:
实部 σ —— 这一项是在长大(σ > 0)还是在消失(σ < 0)
虚部 ω —— 这一项晃不晃,晃多快
σ < 0,ω = 0 → 安静地衰减(指数下降)
σ < 0,ω ≠ 0 → 一边晃一边衰减(会停)
σ = 0,ω ≠ 0 → 永远等幅晃下去(临界)
σ > 0,ω ≠ 0 → 一边晃一边长大(炸)
σ > 0,ω = 0 → 一路飞出去,连晃都不晃(比如符号接反了)
所以「稳定」的精确定义就一句话:
所有的根,实部都小于零。一个都不能例外。
把复平面画出来,竖轴是虚轴。左半平面 = 安全,右半平面 = 会长大。而稳定与否,就变成了「右半平面有几个根」这个整数是不是 0。
注意这个定义的一个后果:只要有一个根跑到右边,整个系统就完了,不管其他根有多稳。因为那一项会指数增长,最后压倒一切。系统的脾气由最靠右的那个根决定——它有个名字叫主导极点。
1877 年的那张表
那么怎么知道有几个根在右边?最笨的办法是把根都求出来,一个个看。但三阶以上的方程求根很麻烦,而在 1877 年,压根没有计算机。
Edward Routh 给出了一个惊人的答案:你根本不需要求根。把系数排成一张表,做几轮加减乘除,数第一列变了几次符号,那就是右半平面根的个数。
拖动滑杆,左边是那张表,右边是真把根求出来之后的样子:
对三阶方程 a₃s³ + a₂s² + a₁s + a₀,那张表化简成一句话,值得背下来:
★ 三阶系统稳定 ⟺ 所有系数同号,且 a₂ a₁ > a₃ a₀ # 代进我们这个:a₃=30, a₂=31, a₁=10, a₀=1+Kp 31 × 10 > 30 × (1 + Kp) 310 > 30 + 30 Kp Kp < 9.3333… ★ 临界增益就这么解出来了,没解过任何方程。
验算一遍,把 Kp 一路加上去看最靠右的那个根:
| Kp | a₂a₁ − a₃a₀ | Routh 说 | 求根说 | 最靠右的根 |
|---|---|---|---|---|
| 1 | 250 | 0 个 | 0 个 | −0.171477 − 0.259154i |
| 4 | 160 | 0 个 | 0 个 | −0.081485 − 0.429943i |
| 8 | 40 | 0 个 | 0 个 | −0.016667 + 0.547469i |
| 9 | 10 | 0 个 | 0 个 | −0.004012 − 0.570166i |
| 9.3333 | 0 | 临界 | 临界 | 0.000000 + 0.577350i |
| 12 | −80 | 2 个 | 2 个 | +0.029144 − 0.629375i |
盯着「最靠右的根」那一列:它的实部是 −0.171 → −0.081 → −0.017 → −0.004 → 0.000000 → +0.029。那对共轭根在朝着虚轴稳步右移,在 Kp = 9.3333 处精确地踩上去,然后越过。demo 里那条灰色轨迹画的就是这个过程。
顺便,临界那一刻的虚部是 0.577350,正好是 1/√3 = √(a₁/a₃) = √(10/30)——这也是 Routh 表能直接给出的:失稳频率就是那一行为零时辅助方程的根。对应周期 10.8828 秒。
还有一件事必须指出:这个对象一点纯延迟都没有,纯粹靠三级惯性就把相位滞后凑够了 180°(每级最多贡献 90°,三级最多 270°,够用)。所以第 4 章那句「一级惯性怎么加增益都不晃」,确实只对一级成立。这就是选项 A 的陷阱。
三条路,一个答案
那个 demo 里同时跑了三条完全不同的路:
路 ① Routh 判据。只做加减乘除,不解方程,数第一列的符号变化。
路 ② 真把根求出来。用 Aberth–Ehrlich 迭代在复平面上找根,数实部大于零的有几个。
路 ③ 不问理论,真跑一遍。解那个微分方程,踢它一脚,看后半段的包络比前半段大还是小。
三条路用的数学毫无交集:一条是纯代数,一条是复变函数的迭代,一条是数值积分。而它们必须永远给出同一个答案——这是「稳定」这个概念是否自洽的检验。
而这还不够
三条路都是我写的。它们一致,只能说明我没有前后矛盾,不能说明我是对的——三段代码可以一起错。
所以这本书做了第四件事:去找一个和我完全无关的实现来对判。
本机装着 numpy 2.4.6。它求多项式根走的是完全不同的路线:把多项式变成伴随矩阵,然后调用 LAPACK 求特征值——那是几十年来被无数科学计算反复捶打过的数值线性代数库。它和我这台 Aberth 迭代求根器,从算法到实现没有一行共同祖先。
$ node scripts/probe-ctl/snapshot.mjs
Darwin 25.5.0 arm64 · node v24.14.0 · numpy 2.4.6 / python 3.14.6
题目 933 道({"known":400,"random":500,"book":33}),共 3839 个根
求根器 vs numpy:最大偏差 1.786e-11(最差一题:known#232)
右半平面根个数:求根器 933/933 一致,Routh 933/933 一致
已知真值的 400 题:400 题精确还原
三类题目:
- 400 道由已知根反造的——真值已知,三方都必须还原出来(400/400 还原);
- 500 道随机系数的——没有真值,这才是真的考试。两边硬碰硬比根的位置;
- 33 道书里真出现过的闭环特征多项式——包括本章这个三级惯性、第 6 章的 PI 闭环、以及用一阶 Padé 近似延迟环得到的那些。
结果:3839 个根,最大偏差 1.786×10⁻¹¹;而「右半平面有几个根」这个决定生死的整数,933 道题三方全部一致。
这就是这本书对「可信」的标准。我不要求你相信我写的引擎,我要求那台引擎和一个你可以自己去核对的第三方对得上。
日常语言里「稳定」是「不容易出问题」的意思,是程度词。控制论里它不是程度词,是一个二值判断:所有根都在左边,或者不是。
这带来一个初学者常有的困惑:「我这个系统冲过头 90%,晃了十几下,这算稳定吗?」——算。只要它最终停下来,它就是稳定的。稳定不等于好,稳定只是「不会自己长大」。
反过来,「这个系统看起来很平稳」也不等于稳定:一个用了 99% 临界增益的系统,在没有扰动的时候可以安静得像块石头,而任何一点风吹草动都会让它晃很久很久。它在数学上是稳定的,在工程上是随时会出事的。
所以只有「稳不稳」是不够的,你还需要「离不稳还有多远」——那正是下一章的两把尺子。控制论把这两件事分得很清楚:稳定性(stability)是二值的,裕度(margin)是连续的。
Routh 表今天还有用吗?有,但用法变了。今天你要判断稳定性,直接 numpy.roots 一行就完了。Routh 表的价值在于它是符号的:它能直接给你「Kp 必须小于 9.3333」这样一条关于参数的不等式,而不是某一组具体参数的结论。这在设计阶段无可替代——它告诉你的是一整片可行域。
「最靠右的根」是一个能监控的量。如果你能对系统做在线辨识(拟合一个模型出来),那主导极点的实部就是一个直接的健康指标:它朝虚轴移动,说明你的余量在被吃掉——可能是设备老化,可能是有人偷偷加了一层缓存。它比任何业务指标都更早报警。
那个虚部也很有用。失稳时系统会以 ω 这个频率振荡,而这个频率是可以预先算出来的(本章是 0.5774 rad/s,周期 10.88 秒)。所以当你在生产环境看到一个周期 11 秒左右的规律波动时,你有一个很强的线索:去找那个环,它快到极限了。这比「系统有点抖」有用得多。
这个直觉的问题有三层:
- 时长问题。一个最右根实部是 +0.004 的系统,每 250 秒才长大 e 倍。跑 60 秒的测试,你会看到一条几乎平的线,然后签字通过。它确实是发散的。
- 覆盖问题。参数空间是连续的,你不可能跑遍。而 Routh 给你的是一个解析的边界:
Kp < 9.3333,一句话覆盖了全部情况。 - 因果问题。仿真告诉你「炸了」,不告诉你为什么、改哪个参数能救。而看着那对共轭根往右移,你立刻知道该动哪个旋钮、动多少。
本书的立场是两个都要:理论给你边界和方向,仿真给你「我没算错」的检验。这正是那个 demo 同时跑三条路的理由——而且它们必须一致,不一致就说明有一条是错的。
CKp = 9.3333,而且不需要解方程。三阶系统的稳定条件是 a₂a₁ > a₃a₀,代进去 310 > 30 + 30Kp,直接解出 Kp < 9.3333。
把这个值代回去求根,最靠右的那对根实部是 0.000000000000,虚部 0.577350——精确地踩在虚轴上,振荡周期 10.8828 秒。
A 「没有纯延迟就不会失稳」——第 4 章的结论是「一级惯性的对象,纯比例控制怎么加增益都不晃」。三级惯性完全够凑出 180° 的相位滞后(每级最多 90°)。纯延迟不是失稳的必要条件,它只是最便宜、最容易被忽略的那个来源。 B 「要很大,几百以上」——这个直觉大概来自「三级惯性听起来很温和,不像延迟那么凶」。而它的临界增益只有 9.3333,比第 11 章那台带 2 秒延迟的设备(8.5024)大不了多少。多级惯性和纯延迟一样能要命。 D 「没有简单办法」——这正是 Routh 在 1877 年推翻的东西,也是这一章存在的理由。而且它给的不是一个数,是一整条不等式:任何满足Kp < 9.3333 的参数都稳定,一次覆盖全部。
这一章的一句话
「稳定」不是感觉,是一个整数;而这个整数可以不解方程就数出来——所以「我觉得它挺稳的」这句话,从来没有必要说。
下一章解决那个更实用的问题:离那条线还有多远。你会拿到两把标准尺子,其中一把可以直接读成一句人话——「这个环还能再多容忍 2.71 秒的延迟」。有了这个数,「有人在链路里加了一层代理」就从一件说不清的事,变成了一笔能算的账。