FlyByWire/BiquadFilter.py
2021-07-04 18:56:56 +02:00

105 lines
3.9 KiB
Python

''' Digital Biquadratic filter implementation '''
class BiquadFilter:
''' Implementation of a digital second-order biquadratic filter. '''
def __init__(self, omega, q, dt, ftype='lowpass'):
''' Builds a biquad filter from the given parameters. '''
self.InitFilter(0)
self.ComputeContinuousTFBiquad(omega, q, dt, ftype)
self.ConvertContinuousToDiscrete()
def SetContinuousTF(self, b0, b1, b2, a0, a1, a2, dt):
''' Sets the continuous-time coefficients of the second order transfer function. '''
self.dt = dt
self.b0c = b0
self.b1c = b1
self.b2c = b2
self.a0c = a0
self.a1c = a1
self.a2c = a2
def ComputeContinuousTFBiquad(self, omega, q, dt, ftype='lowpass'):
''' Computes the continuous time transfer function from the given parameters.
b0 + b1*s + b2*s^2
------------------
a0 + a1*s + a2*s^2
'''
self.omega = omega
self.q = q
self.dt = dt
if ftype == 'highpass':
self.b0c = 0
self.b1c = 0
self.b2c = 1
self.a0c = omega**2
self.a1c = omega/q
self.a2c = 1
elif ftype == 'bandpass':
self.b0c = 0
self.b1c = omega
self.b2c = 0
self.a0c = q*omega**2
self.a1c = omega
self.a2c = q
elif ftype == 'notch':
self.b0c = omega**2
self.b1c = 0
self.b2c = 1
self.a0c = omega**2
self.a1c = omega/q
self.a2c = 1
else:
# lowpass filter
self.b0c = omega**2
self.b1c = 0
self.b2c = 0
self.a0c = omega**2
self.a1c = omega/q
self.a2c = 1
def ConvertContinuousToDiscrete(self):
''' Converts the continuous coefficients to discrete coefficients using the bilinear transform. '''
self.b0d = 4*self.b2c - 2*self.b1c*self.dt + self.b0c*self.dt**2
self.b1d = - 8*self.b2c + 2*self.b0c*self.dt**2
self.b2d = 4*self.b2c + 2*self.b1c*self.dt + self.b0c*self.dt**2
self.a0d = 4*self.a2c - 2*self.a1c*self.dt + self.a0c*self.dt**2
self.a1d = - 8*self.a2c + 2*self.a0c*self.dt**2
self.a2d = 4*self.a2c + 2*self.a1c*self.dt + self.a0c*self.dt**2
def PrintContinuousTF(self):
''' Prints the continuous-time transfer function coefficients. '''
print('Continuous-time transfer function :')
print('%f + %f s + %f s**2' % (self.b0c, self.b1c, self.b2c))
print('----------------------------------------')
print('%f + %f s + %f s**2' % (self.a0c, self.a1c, self.a2c))
def PrintDiscreteTF(self):
''' Prints the discrete-time transfer function coefficients. '''
print('Discrete-time transfer function :')
print('%f + %f z + %f z**2' % (self.b0d, self.b1d, self.b2d))
print('----------------------------------------')
print('%f + %f z + %f z**2' % (self.a0d, self.a1d, self.a2d))
print('dt = %f' % self.dt)
def PrintAllTF(self):
self.PrintContinuousTF()
self.PrintDiscreteTF()
def InitFilter(self, v):
''' Initializes the filter with the value v. '''
self.xn_0 = v
self.xn_1 = v
self.xn_2 = v
self.yn_0 = v
self.yn_1 = v
self.yn_2 = v
def Filter(self, xn_0):
''' Applies the filter to the sample xn_0. '''
self.xn_0 = xn_0
self.yn_0 = (self.b2d*self.xn_0 + self.b1d*self.xn_1 + self.b0d*self.xn_2 - self.a1d*self.yn_1 - self.a0d*self.yn_2)/self.a2d
self.xn_2 = self.xn_1
self.xn_1 = self.xn_0
self.yn_2 = self.yn_1
self.yn_1 = self.yn_0
return self.yn_0