上篇讲了一阶二阶系统的响应特性,你知道了阻尼比、自然频率这些参数怎么影响系统的动态行为。但有一个更根本的问题还没聊——你怎么判断一个系统到底稳不稳定?
稳定性是控制理论的命根子。一个控制系统如果不稳定,那它根本没法用——输出要么发散到无穷大,要么来回震荡停不下来。你在设计任何控制器之前,第一件事就是确保闭环系统是稳定的。
面试中,稳定性分析是高频考点。面试官喜欢问"你知道哪些稳定性判据",然后根据你的回答往深了追。今天这篇把几种主要的稳定性判定方法讲清楚。
稳定性的定义
先说清楚什么是"稳定"。一个系统如果受到扰动后,能自动回到平衡状态,就是稳定的。如果扰动让系统越跑越远回不来,就是不稳定的。
用控制理论的语言说:一个线性时不变(LTI)系统稳定的充要条件是——传递函数的所有极点都在s平面的左半边(极点的实部全部为负)。
这个结论非常重要,你一定要记住。极点实部为负,对应的时域响应是指数衰减的,最终趋于零。极点实部为正,对应的时域响应是指数增长的,系统发散。
import numpy as np # 判断系统稳定性:检查极点位置 def check_stability(denominator_coeffs): """根据分母系数判断系统稳定性""" poles = np.roots(denominator_coeffs) print(f"极点: {poles}") stable = all(poles.real < 0) print(f"稳定: {stable}") return stable, poles # 稳定系统: s² + 3s + 2 = (s+1)(s+2) check_stability([1, 3, 2]) # 极点: -1, -2 # 不稳定系统: s² - s + 2 = 0 check_stability([1, -1, 2]) # 有正实部极点劳斯判据:不用解方程就能判断
对于高阶系统,直接求极点可能很困难(高次方程没有解析解)。劳斯判据(Routh Criterion)提供了一种不需要求解方程就能判断稳定性的方法。
劳斯判据的核心思想:根据传递函数分母多项式的系数,构造一个表格(劳斯表),通过观察表格第一列元素的符号变化次数来判断右半平面极点的个数。
规则很简单:劳斯表第一列元素全部为正,系统稳定。第一列出现负数,系统不稳定,符号变化的次数等于右半平面极点的个数。
def routh_table(coeffs): """构造劳斯表(简化版)""" n = len(coeffs) - 1 # 多项式阶数 # 初始化劳斯表 rows = (n + 2) // 2 table = np.zeros((rows + 1, (n + 1) // 2 + 1)) # 填充前两行 table[0, :len(coeffs[0::2])] = coeffs[0::2] table[1, :len(coeffs[1::2])] = coeffs[1::2] # 计算后续行 for i in range(2, rows + 1): for j in range(table.shape[1] - 1): if table[i-1, 0] != 0: table[i, j] = -(table[i-2, 0] * table[i-1, j+1] - table[i-1, 0] * table[i-2, j+1]) / table[i-1, 0] # 检查第一列符号变化 first_col = table[:, 0] sign_changes = sum(1 for i in range(len(first_col)-1) if first_col[i] * first_col[i+1] < 0) print(f"劳斯表第一列: {first_col}") print(f"符号变化次数: {sign_changes}") print(f"右半平面极点数: {sign_changes}") return sign_changes == 0 # 测试: s³ + 6s² + 11s + 6 = (s+1)(s+2)(s+3) 稳定 is_stable = routh_table([1, 6, 11, 6]) print(f"系统稳定: {is_stable}")劳斯判据在面试中经常出现,特别是这种问法:"给你一个带参数的传递函数,比如s³+6s²+11s+K,问K在什么范围内系统稳定?"这时候你需要构造含K的劳斯表,令第一列全部为正,解出K的范围。
奈奎斯特判据:频域里的稳定性
奈奎斯特判据是另一种非常强大的稳定性判据,它从频域角度来判断闭环系统的稳定性。
核心思想:画出开环传递函数G(s)H(s)的奈奎斯特图(频率响应在复平面上的轨迹),然后根据这条曲线包围(-1, 0)点的圈数来判断闭环系统的稳定性。
简单说就是:如果开环稳定,闭环稳定的条件是奈奎斯特曲线不包围(-1, 0)点。(-1, 0)点离曲线越远,系统的"稳定裕度"越大。
这就是为什么伯德图和奈奎斯特图在工程上这么重要——它们不仅能告诉你系统稳不稳定,还能告诉你"有多稳定"。
from scipy import signal import numpy as np # 开环传递函数 # G(s) = 10 / (s(s+1)(s+5)) num = [10] den = np.polymul([1, 0], np.polymul([1, 1], [1, 5])) sys = signal.TransferFunction(num, den) # 计算频率响应 w = np.logspace(-2, 2, 500) w, mag, phase = signal.bode(sys, w) # 增益裕度和相位裕度 # 从伯德图中可以读出 gm, pm, wg, wp = signal.margin(sys) print(f"增益裕度: {20*np.log10(gm):.1f} dB") print(f"相位裕度: {pm:.1f} 度")增益裕度和相位裕度是工程中衡量"系统有多稳定"的两个关键指标。一般来说,相位裕度大于45度、增益裕度大于6dB,系统才算有足够的稳定裕度。
为什么需要裕度?因为你的模型不可能完全精确,实际系统的参数会变化(比如负载变化导致惯量变化),传感器有噪声,执行器有非线性。如果稳定裕度太小,这些不确定因素随便来一个扰动,系统就可能越过稳定边界变成不稳定。工程上留裕度,说白了就是给自己留余地。
面试中怎么聊稳定性
面试官问稳定性,从简单到难大概分三个层次。
第一层:"系统稳定的条件是什么?"答:所有极点在s平面左半边。
第二层:"怎么判断高阶系统的稳定性?"答:劳斯判据(时域)或奈奎斯特判据(频域)。能说出劳斯表怎么构造、第一列符号变化的含义,就够用了。
第三层:"增益裕度和相位裕度是什么意思?"答:增益裕度是系统在变得不稳定之前,增益还能增大多少倍。相位裕度是系统在变得不稳定之前,相位还能再滞后多少度。这两个指标越大,系统越"稳"。
之前面试一家做自动驾驶的公司,面试官问了一个很实际的问题:"你的控制系统在仿真里稳定,到了实际车上发散了,可能是什么原因?"这个问题考的是你对实际工程中稳定性问题的理解。常见原因包括:传感器延迟导致相位裕度降低、未建模的高频动态(比如结构谐振)被激发、采样频率太低导致离散化效应。
补充一个我在项目中排查稳定性问题的经验。当时做一台四足机器人的平衡控制,控制器在仿真中跑得好好的,上了真机后机器人走了几步就开始剧烈晃动然后摔倒。用示波器抓了控制信号发现,电机驱动器的响应有一个大约2ms的延迟,这个延迟在仿真中没有建模。2ms的延迟在100Hz的控制频率下对应7.2度的相位滞后,直接吃掉了大部分相位裕度。解决办法有两个:第一,在控制器设计时把这个延迟考虑进去(用Padé近似把延迟加到模型里);第二,把控制频率从100Hz提高到500Hz,这样2ms延迟对应的相位滞后从7.2度降到了1.4度。改完之后系统就稳定了。这个经历告诉我,仿真和实际之间的差距往往就藏在这种小延迟里。
下一篇讲PID控制原理——P/I/D三项各自的物理意义,这是控制理论面试的必考内容。
如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。
「机器人软件开发面试·从入门到精通」连载系列
上一篇:第180篇 一阶/二阶系统响应——理解动态特性的基础
下一篇预告:第182篇 PID控制原理——P/I/D三项各自的物理意义
有任何问题欢迎评论区留言,我会尽量回复。