Numpy convolve: сравнение шаговой и импульсной характеристики - PullRequest
0 голосов
/ 17 июня 2020

Я новичок в цифровой обработке сигналов, и при разработке моего первого подхода к управлению на основе моделей я впервые столкнулся с необходимостью вычислить свертку вне любого школьного контекста (мой опыт - еще одна область численного моделирования). Я адаптировал код из этого вопроса к своей проблеме, для которой я эмпирически знаю время шага отклика, и все отлично подходит. Я понимаю необходимость без труда умножить impulse_response из моей системы на временной шаг.

tend = 600.0  # Total time [s]
dt = 15.0     # Time step [s]
k = 0.01      # Time constant [s]
sp = 0.15     # Step height [a.u.]

# Time interval
t = np.arange(0, tend + 1, dt)

# Define step function.
H = np.ones_like(t)
H[0] = 0.5

def impulse_response(t):
    """ Unit response. """
    return k * np.exp(-k * t) * H

# Response to step. Multiply by dt in discrete case.
response = np.convolve(H, impulse_response(t) * dt, 'full')
response = response[:len(response)//2]

# Define new, longer, time array for plotting response - must 
# be same length as response, with step dt
tp = np.arange(len(response)) * dt

t = np.arange(-tend, tend, dt)
Hp = sp * np.ones_like(t)
Hp[t < 0] = 0.0

plt.style.use('bmh')
plt.step(t, Hp, label='Unit step function')
plt.plot(tp, sp * response, label='Response')
plt.tight_layout()
plt.xlabel('Time (s)')
plt.ylabel('Response [a.u.]')
plt.xlim(-100, tend + 1)
plt.legend()

Единственный момент, который я не понимаю в приведенном выше коде, - почему я получаю разные результаты, если я не умножайте на H в приведенной ниже функции (как указано в справочном ответе и из моего понимания, поскольку моя высота шага равна нулю для t <0, это не должно иметь никакого значения). </p>

def impulse_response(t):
    """ Unit response. """
    return k * np.exp(-k * t) * H

Моя проблема: в реальном приложении к динамической системе у меня будут произвольные сигналы, для которых нужно будет вычислить свертку. Чтобы убедиться, что я хорошо понял постановку проблемы и проверить следующие шаги в разработке, я попытался проверить, как эта функция будет работать для одного единичного дельта-импульса. Длительность такой дельты равна нулю, я считаю, что это причина того, почему мне не нужно умножать на dt в случае одиночного импульса. Это правильно? Таким образом я получаю ожидаемое аналитическое решение, но не уверен в своем заключении. Здесь следует модифицированный код.

# Define impulse function.
d = np.zeros_like(t)
d[0] = 1.0

def impulse_response(t):
    """ Unit response. """
    return k * np.exp(-k * t)

# Response to impulse. Multiply by dt in discrete case.
response = np.convolve(d, impulse_response(t), 'full')
response = response[:len(response)//2]

# Define new, longer, time array for plotting response - must 
# be same length as response, with step dt
tp = np.arange(len(response)) * dt

plt.style.use('bmh')
plt.plot(tp, response, label='Response')
plt.plot(tp, k * np.exp(-k * tp), label='Analytical')
plt.tight_layout()
plt.xlabel('Time (s)')
plt.ylabel('Response [a.u.]')
plt.legend()

1 Ответ

0 голосов
/ 17 июня 2020

Обычно при свертке ядро ​​(ваш impulse_response) представляет собой довольно мелкую вещь по сравнению с массивом, к которому оно применяется. Может быть, 3, 5 или 9 элементов в ширину. Конечно, в зависимости от случая!

В вашем случае кажется, что он вдвое меньше массива, верно?

Я предполагаю, что в вашем случае результаты, вероятно, не совпадают , но настолько похожи, что вы не замечаете. Огромное ядро ​​все «размазывает» (или усредняет).

...