寻求RC滤波器等效数字滤波器:波特图不匹配问题排查
看起来你在把一阶RC低通滤波器转换成数字滤波器时,波特图不匹配的问题出在手动预畸变的步骤上——双线性变换函数scipy.signal.bilinear已经内置了预畸变处理,你额外手动调整模拟滤波器参数的操作反而打乱了等效关系。
先拆解你的核心问题:
你的模拟RC滤波器传递函数是:
$$ H(s) = \frac{1}{\tau s + 1} $$
截止角频率 $ \omega_c = 1/\tau = 1000 , \text{rad/s} $
你尝试手动做预畸变:计算 $ w_a = 2/T \tan(\omega_c T/2) $,然后用 $ dtau = 1/w_a $ 构造新的模拟传递函数再做双线性变换,这是完全多余的——bilinear函数会自动帮你完成预畸变,保证数字滤波器的截止频率和模拟滤波器在预畸变后的频率对应,你手动修改参数反而让等效关系偏离了。
修正后的代码
import numpy as np import scipy.signal as sig import matplotlib.pyplot as plt # 模拟RC滤波器参数 tau = 0.001 fs = 20000 # 采样率 T = 1 / fs # 1. 原始模拟滤波器 analog_lti = sig.lti([1], [tau, 1]) # 2. 直接用双线性变换得到等效数字滤波器 # 不需要手动计算预畸变参数,直接传入原始模拟传递函数和采样率 dnum, dden = sig.bilinear([1], [tau, 1], fs) digital_lti = sig.dlti(dnum, dden, dt=T) # 绘制波特图对比 # 模拟波特图 w_analog, mag_analog, phase_analog = analog_lti.bode(np.logspace(2, 5, 1000)) # 数字波特图(转换为角频率,单位rad/s) w_digital, mag_digital, phase_digital = digital_lti.bode(np.logspace(2, 5, 1000)) plt.figure(figsize=(12, 8)) # 幅频特性 plt.subplot(211) plt.semilogx(w_analog, mag_analog, label='Analog RC Filter') plt.semilogx(w_digital, mag_digital, '--', label='Digital Equivalent (Bilinear)') plt.title('Bode Plot - Magnitude') plt.ylabel('Magnitude (dB)') plt.grid(True, which='both') plt.legend() # 相频特性 plt.subplot(212) plt.semilogx(w_analog, phase_analog, label='Analog RC Filter') plt.semilogx(w_digital, phase_digital, '--', label='Digital Equivalent (Bilinear)') plt.title('Bode Plot - Phase') plt.xlabel('Frequency (rad/s)') plt.ylabel('Phase (degrees)') plt.grid(True, which='both') plt.legend() plt.tight_layout() plt.show()
为什么你的原代码会出错?
你手动计算的wa是预畸变后的模拟截止频率,然后用dtau=1/wa构造了一个截止频率更高的模拟滤波器,再对这个修改后的滤波器做双线性变换,得到的数字滤波器自然和原始RC的波特图不匹配——相当于你先把模拟滤波器的截止频率改了,再转数字,结果肯定不对。
scipy.signal.bilinear的工作逻辑是:
- 接收原始模拟传递函数的分子分母
- 自动应用预畸变公式,将模拟频率映射到数字频率
- 输出对应的数字滤波器传递函数
所以直接传入原始的[1], [tau,1]就可以得到和原始RC滤波器截止频率匹配的数字等效滤波器。另外,你的原代码中dlti = sig.dlti(dn...有截断,修正后的代码补全了这部分,确保数字LTI对象正确创建。
运行修正后的代码,你会看到数字滤波器的波特图在截止频率附近和模拟滤波器几乎重合(双线性变换在低频段的匹配度很好,高频段因为频率压缩会有偏差,但这是该方法的固有特性)。
内容的提问来源于stack exchange,提问作者dvc

