
上篇讲了一阶二阶系统的响应特性你知道了阻尼比、自然频率这些参数怎么影响系统的动态行为。但有一个更根本的问题还没聊——你怎么判断一个系统到底稳不稳定稳定性是控制理论的命根子。一个控制系统如果不稳定那它根本没法用——输出要么发散到无穷大要么来回震荡停不下来。你在设计任何控制器之前第一件事就是确保闭环系统是稳定的。面试中稳定性分析是高频考点。面试官喜欢问你知道哪些稳定性判据然后根据你的回答往深了追。今天这篇把几种主要的稳定性判定方法讲清楚。稳定性的定义先说清楚什么是稳定。一个系统如果受到扰动后能自动回到平衡状态就是稳定的。如果扰动让系统越跑越远回不来就是不稳定的。用控制理论的语言说一个线性时不变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 (s1)(s2) 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, j1] - table[i-1, 0] * table[i-2, j1]) / 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[i1] 0) print(f劳斯表第一列: {first_col}) print(f符号变化次数: {sign_changes}) print(f右半平面极点数: {sign_changes}) return sign_changes 0 # 测试: s³ 6s² 11s 6 (s1)(s2)(s3) 稳定 is_stable routh_table([1, 6, 11, 6]) print(f系统稳定: {is_stable})劳斯判据在面试中经常出现特别是这种问法给你一个带参数的传递函数比如s³6s²11sK问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(s1)(s5)) 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三项各自的物理意义有任何问题欢迎评论区留言我会尽量回复。