Я не думаю, что есть простая векторизованная реализация для процесса обратной реакции.K-й вывод зависит от предыдущих значений нетривиальным образом.Краткий способ записать процесс (при условии x
- это входной массив, а y
- это выходной массив):
y[k] = min(max(y[k-1], x[k] - h), x[k] + h)
, где h
- половина зоны нечувствительности.
Следующий скрипт включает функцию backlash
, которая использует цикл for Python.(Функция использует операторы if
вместо функций min
и max
.) Это просто, но не очень быстро.Если важна высокая производительность, вы можете рассмотреть возможность переопределения функции в Cython или numba .
import numpy as np
def backlash(x, deadband=1.0, initial=0.0):
"""
Backlash process.
This function emulates the Backlash block of Simulink
(https://www.mathworks.com/help/simulink/slref/backlash.html).
x must be a one-dimensional numpy array (or array-like).
deadband must be a nonnegative scalar.
initial must be a scalar.
"""
halfband = 0.5*deadband
y = np.empty_like(x, dtype=np.float64)
current_y = initial
for k in range(len(x)):
current_x = x[k]
xminus = current_x - halfband
if xminus > current_y:
current_y = xminus
else:
xplus = current_x + halfband
if xplus < current_y:
current_y = xplus
y[k] = current_y
return y
if __name__ == "__main__":
import matplotlib.pyplot as plt
t = np.linspace(0, 10, 500)
x = np.sin(t)
deadband = 1
y = backlash(x, deadband=deadband)
plt.plot(t, x, label='x(t)')
plt.plot(t, y, '--', label='backlash(x(t))')
plt.xlabel('t')
plt.legend(framealpha=1, shadow=True)
plt.grid(alpha=0.5)
plt.show()