为什么 python 的 scipy.signal.dimpulse 会在脉冲响应中引入延迟?

信息处理 过滤器 Python 冲动反应 scipy
2022-02-19 05:01:05

考虑一个简单的线性时不变系统,其形式为:

yk=cyk1+(1c)xk

该系统的脉冲响应可以通过 dimpulse 或通过将 lfilter 应用于由 1 后跟 0 组成的向量来计算:

import scipy.signal as sp_signal
import numpy as np

Ts = 1
c = 0.9
A = [1, -c]
B = [1-c]
time, imp_resp1 = sp_signal.dimpulse((B, A, Ts))
x = np.zeros(100)
x[0] = 1
imp_resp2 = sp_signal.lfilter(B, A, x)
print(imp_resp1[0][:5,0])
print(imp_resp2[:5])

产生:

array([ 0.    ,  0.1   ,  0.09  ,  0.081 ,  0.0729])

[ 0.1      0.09     0.081    0.0729   0.06561]

为什么dimpulse会在脉冲响应中引入一个样本延迟?

2个回答

在 lfilter 中,传递函数以 z 的递减幂来描述,如下所示,复制自 signal.lfilter 的 python 文档:

                    -1              -M
         b[0] + b[1]z  + ... + b[M] z 
Y(z) = -------------------------------- X(z)
                    -1              -N
         a[0] + a[1]z  + ... + a[N] z

而dimpulse中的参数B和A以z的递增幂表示,如signal.TransferFunction的文档中所述:

如果 (numerator, denominator) 为 *system 传入,则分子和分母的系数应按指数降序指定(例如 s^2 + 3s + 5 或 z^2 + 3z + 5 将表示为 [1 , 3, 5])

连同以下示例:

z2+3z+3z2+2z+1

Contruct the transfer function with a sampling time of 0.1 seconds:

H(z)=z2+3z+3z2+2z+1 
H(z)=z2+3z+3z2+2z+1

>>>>signal.TransferFunction(num, den, dt=0.1) 
TransferFunctionDiscrete( 
array([ 1.,  3.,  3.]), 
array([ 1.,  2.,  1.]), 
dt: 0.1 
)

所以在你的情况下,对于酒窝:

H1(z)=10.9z10.1

对于 lfilter:

H2(z)=z0.90.1

所以

H1(z)=H2(z)z1

谜团解开了!

我不认为这是因为 lfilter 和 dimpulse transfert 函数定义之间的差异。您必须注意 num 和 den 定义中 z 的幂,并在两种情况下获得相同的结果。

请只考虑这些等式:

H(z)=10.9z10.1=z(10.9z1)z0.1=z0.90.1z0

然后,您必须指定您的分子 B 照顾 z 幂:

import scipy.signal as sp_signal
import numpy as np

Ts = 1
c = 0.9
A = [1, -c]
B = [1-c, 0] # <---- this is the good numerator definition 
time, imp_resp1 = sp_signal.dimpulse((B, A, Ts))
x = np.zeros(100)
x[0] = 1
imp_resp2 = sp_signal.lfilter(B, A, x)
print(imp_resp1[0][:5,0])
print(imp_resp2[:5])

通过此更改,您将在两种情况下得到相同的响应:

[ 0.1      0.09     0.081    0.0729   0.06561]
[ 0.1      0.09     0.081    0.0729   0.06561]

没有样品延迟问题。让我知道你们是否都同意我的观点