Exemple #1
0
    def createFunction(self):

        wo = self.woCalc()  #calculo wo para desnormalizacion
        pzFunction = signal.ZerosPolesGain(self.zeros, self.poles, 1)
        coefFunction = pzFunction.to_tf()  # num/den
        den = coefFunction.den
        num = coefFunction.num
        for i in range(0, len(den)):
            den[i] = den[i].real
        for i in range(0, len(num)):
            num[i] = num[i].real
        k = self.kCalc(den, num)  #calculo constante
        self.normFunction = signal.ZerosPolesGain(
            self.zeros, self.poles, k)  #guardo funcion normalizada
        # desnormalizo segun tipo de filtro
        if self.type == 'LP':
            s = c.tf([1, 0], [wo])
        elif self.type == 'HP':
            s = c.tf([wo], [1, 0])
        elif self.type == 'BP':
            s = c.tf([1, 0, wo**2], [1, 0]) / (wo * self.b)
        elif self.type == 'BR':
            s = c.tf([1, 0], [1, 0, wo**2]) * wo * self.b
        ft = c.tf([1], [1])
        for i in range(0, len(self.poles)):
            aux = 1 / (s - self.poles[i])
            ft = ft * aux
        for i in range(0, len(self.zeros)):
            aux = s - self.zeros[i]
            ft = ft * aux
        #creo funcion final
        self.function = signal.TransferFunction(k * ft.num[0][0], ft.den[0][0])
        return
Exemple #2
0
    def max_gain_for_stage(self, stage):
        if stage['zero'] is None:
            zeros = []
        else:
            zeros = stage['zero']['zeros']
        poles = stage['pole']['poles']
        gain = 10**(stage['gain_data'] / 20)
        transfer_function = ss.ZerosPolesGain(zeros, poles, gain)
        w, mag, phase = ss.bode(transfer_function, n=1000)

        dmag = np.diff(mag) / np.diff(w)

        frequencies_to_check = 10
        zero_condition = 1.0e-4
        gain_needed = 0
        for i in range(len(dmag) - frequencies_to_check):
            values_checked = []
            for j in range(frequencies_to_check):
                values_checked.append(dmag[i + j])

            if all([value < zero_condition for value in values_checked]):
                frequency_to_evaluate = math.floor(i +
                                                   frequencies_to_check / 2)
                max_freq = w[frequency_to_evaluate]
                useless_1, gain_in_passband, useless_2 = ss.bode(
                    transfer_function, [max_freq])
                gain_in_passband = 10**(gain_in_passband[0] / 20)
                gain_needed = gain**2 / gain_in_passband
                break

        transfer_function = ss.ZerosPolesGain(zeros, poles, gain_needed)
        w, mag, phase = ss.bode(transfer_function)
        return max(mag)
Exemple #3
0
    def _denormalised_transfer_function(self) -> ApproximationErrorCode:
        """ Denormalises the transfer function returned by the approximation used. """

        # Unity gain of the normalised transfer function, factor of denormalisation...
        # moving it between the transition band
        self.adjust_function_gain(1)
        wa, aa, wp, ap = self.get_norm_template()
        relative_adjust = self.denormalisation_factor(wa, aa, wp, ap)

        new_zeros = self.h_aux.zeros * relative_adjust
        new_poles = self.h_aux.poles * relative_adjust
        new_gain = self.h_aux.gain * relative_adjust

        self.h_aux = ss.ZerosPolesGain(new_zeros, new_poles, new_gain)
        self.adjust_function_gain(1)

        # Final normalised transfer function being stored, keep working on auxiliar transfer function
        self.h_norm = ss.ZerosPolesGain(self.h_aux.zeros, self.h_aux.poles,
                                        self.h_aux.gain)
        self.adjust_function_gain(10**(self.gain / 20))

        # Frequency transformation to get the desired filter
        if self.type == FilterType.LOW_PASS.value:
            z, p, k = self.denormalise_to_low_pass()
        elif self.type == FilterType.HIGH_PASS.value:
            z, p, k = self.denormalise_to_high_pass()
        elif self.type == FilterType.BAND_PASS.value:
            z, p, k = self.denormalise_to_band_pass()
        elif self.type == FilterType.BAND_REJECT.value:
            z, p, k = self.denormalise_to_band_stop()
        self.h_denorm = ss.ZerosPolesGain(z, p, k)

        return ApproximationErrorCode.OK
 def GetStagesTransferFunctions(self):
     funcs = []
     for i in range(0, len(self.pairs)):
         zero, pole1 = self.pairs[i]
         pole2 = complex(pole1.real, -(pole1.imag))
         aux = signal.ZerosPolesGain(zero, [pole1, pole2], 1)
         funcs.append(aux)
     for i in range(0, len(self.remainingPoles)):
         p1 = self.remainingPoles[i]
         p2 = complex(p1.real, -(p1.imag))
         aux = signal.ZerosPolesGain([], [p1, p2], 1)
         funcs.append(aux)
     self.stages = funcs
Exemple #5
0
    def get_min_max_attenuation(poles, zeros, gain_factor, pass_bands):
        max_at = -math.inf
        min_at = math.inf
        if zeros is not None and poles is not None:
            filter.Filter.re_add_complex(poles)
            filter.Filter.re_add_complex(zeros)


            sys = signal.ZerosPolesGain(zeros, poles, gain_factor)


            for pass_band in pass_bands:
                sup_band = pass_band[1]
                if sup_band == math.inf:
                    sup_band = 10000 * pass_band[0]
                    w = np.logspace(start=math.log10(pass_band[0]), stop=math.log10(sup_band), endpoint=True, base=10)
                    [_, mag, _] = signal.bode(system=sys, w=w)
                    attenuation = -1*mag
                    if min(attenuation) < min_at:
                        min_at = min(attenuation)
                    if max(attenuation) > max_at:
                        max_at = max(attenuation)

            filter.Filter.add_only_one_complex(poles)
            filter.Filter.add_only_one_complex(zeros)

        return [min_at, max_at]
Exemple #6
0
def besselord(omega_p, omega_s, alfa_max, alfa_min, omega_d, max_pc_delay):

    min_order = 0

    # partimos de suponer que al menos será el orden de un Butter o más grande
    start_order, _ = sig.buttord(omega_p,
                                 omega_s,
                                 alfa_max,
                                 alfa_min + alfa_max,
                                 analog=True)

    # de forma iterativa, intentamos cumplimentar la plantilla
    for ii in range(start_order, 20):

        z, p, k = sig.besselap(ii, norm='delay')

        this_lti = sig.ZerosPolesGain(z, p, k).to_tf()

        _, mm, pp = sig.bode(this_lti,
                             w=[0, 0.0001, omega_p, omega_d, omega_d + 0.0001])

        # attenuation in omega_p, i.e. bandpass end
        this_ripple = -mm[2]

        # relative delay
        this_delay = 1 - np.abs((pp[4] - pp[3]) / (pp[1] - pp[0]))

        if this_ripple <= alfa_max and this_delay <= max_pc_delay:
            break

    min_order = ii

    return min_order
Exemple #7
0
 def calculate_tf(positive_poles, positive_zeros, k):
     Filter.re_add_complex(positive_poles)
     Filter.re_add_complex(positive_zeros)
     sys = signal.ZerosPolesGain(positive_zeros, positive_poles, k)
     Filter.add_only_one_complex(positive_poles)
     Filter.add_only_one_complex(positive_zeros)
     return sys.to_tf()
    def plot_stage(self):
        current_item = self.stages_list.currentItem()
        stage_index = self.stages_list.row(current_item)

        if self.accumulative_plot.isChecked():
            start = 0
        else:
            start = stage_index

        poles_list = []
        zeros_list = []
        total_gain = 1
        for i in range(start, stage_index + 1):
            widget = self.stages_list.itemWidget(self.stages_list.item(i))
            if widget.cell_data['zero'] is not None:
                zeros = [
                    zero * 2 * np.pi
                    for zero in widget.cell_data['zero']['zeros']
                ]
            else:
                zeros = []
            zeros_list += zeros
            poles = [
                pole * 2 * np.pi for pole in widget.cell_data['pole']['poles']
            ]
            poles_list += poles

            gain = 10**(widget.cell_data['gain_data'] / 20)
            gain_needed_to_plot = self.adjust_function_gain(zeros, poles, gain)
            total_gain *= gain_needed_to_plot

        tf = ss.ZerosPolesGain(zeros_list, poles_list, total_gain)
        self.plot_attenuation_for_stages(tf)
Exemple #9
0
    def plot_transfer_to_figure(self, figure):
        n_points = 1000
        z = []
        p = []
        # get a list of all the zeros:
        for point_pair in self.zero_pairs:
            for point in point_pair.points:
                z.append(point)

        # get a list of all the poles
        for point_pair in self.pole_pairs:
            for point in point_pair.points:
                p.append(point)

        sys = signal.TransferFunction(signal.ZerosPolesGain(z, p, self.gain))
        w, mag, phase = signal.bode(sys)

        # create and plot
        title = 'Stage {0} - Frequency Response[dB]'.format(self.id)
        legend = 'Frequency Response[dB]'
        # remove axes
        for axes in figure.axes:
            figure.delaxes(axes)
        # create axes
        axes = figure.add_subplot(111, projection='rectilinear')
        axes.semilogx(w, mag, label=legend)
        axes.set_title(title, pad=10)
        axes.legend()
        axes.set_xlabel(r'$\omega [rad/seg]$')
        axes.set_ylabel(r'Mag')
 def compute_normalised_by_order(self, ap, n, aa) -> ApproximationErrorCode:
     """ Generates normalised transfer function prioritising the fixed order """
     # Computing needed constants
     zeros, poles, gain = ss.cheb2ap(n, aa)
     wa, aa, wp, ap = self.get_norm_template()
     self.h_aux = ss.ZerosPolesGain(zeros, poles, gain)
     return ApproximationErrorCode.OK
Exemple #11
0
 def _get_tf(self, n: int):
     """
     Returns the normalized transfer function of the Gauss Approximation
     :param n: Order of the gauss polynomial
     :return: Scipy signal transfer function
     """
     z, p, k = self._get_zpk(n)
     transfer_function = ss.ZerosPolesGain(z, p, k)
     return transfer_function
Exemple #12
0
 def compute_normalised_by_order(self,
                                 ap,
                                 n,
                                 aa=None) -> ApproximationErrorCode:
     """ Generates normalised transfer function prioritising the fixed order """
     # Computing needed constants
     zeros, poles, gain = ss.ellipap(n, ap, aa)
     self.h_aux = ss.ZerosPolesGain(zeros, poles, gain)
     return ApproximationErrorCode.OK
Exemple #13
0
 def gaussDenGenerator(self):
     coef = self.gaussPolynomialCoef()
     auxPoles = np.roots(coef)
     poles = []
     for i in range(0, auxPoles.size):
         if auxPoles[i].real < 0:
             poles.append(auxPoles[i])
     pzfunc = signal.ZerosPolesGain([], poles, 1)
     self.normFunction = pzfunc.to_tf()
     den = self.normFunction.den
     return den
Exemple #14
0
def filter_from_npz(filename, fs):
    with np.load(filename) as data:
        z = data['z']
        p = data['p']
        k = data['k']

    #sos conversion
    zd, pd, kd = zpk_bilinear(z, p, k, fs)
    sys_disc = sig.ZerosPolesGain(zd, pd, kd, dt=1 / fs)
    sos = sig.zpk2sos(sys_disc.zeros, sys_disc.poles, sys_disc.gain)
    return sos
 def H(self):
     # Generate the transfer function
     H = signal.ZerosPolesGain([], [0.25, 2 / 3], 0.25, dt=0.1).to_tf()
     # Generate dicrete frequency response
     w, h = signal.freqz(H.num, H.den, whole=True)
     # Shift the angles to [-pi, pi]
     w = w - np.pi
     # Shift the gain and phase accordingly
     #         h_ph = np.fft.fftshift(np.angle(h, deg=True))
     h = np.abs(np.fft.fftshift(h))
     return w, h
Exemple #16
0
    def computeCancellationLogic(self, deltaSigmas):
        STF = []
        NTF = []
        for df in deltaSigmas:
            # k is the gain of the system
            ntf, stf = calculateTF(df.ABCD, k=1.)
            stf = signal.ZerosPolesGain(*stf)
            ntf = signal.ZerosPolesGain(*ntf)

            STF.append(stf.to_tf())
            NTF.append(ntf.to_tf())

        # Create inverse filter
        # H1 = STF2
        # STF_N H_N = NTF_N-1 H_N-1
        for index in range(len(deltaSigmas)):
            if index == 0:
                self.H = [STF[1]]
            else:
                NTF_over_STF = self.inverseMultiple(NTF[index - 1], STF[index])
                self.H.append(self.concatenateSystems(NTF_over_STF, self.H[-1]))
Exemple #17
0
    def __init__(self,
                 parent=None,
                 width=5,
                 height=4,
                 dpi=100,
                 s1=signal.ZerosPolesGain([], [1], [1])):
        fig = Figure(figsize=(width, height), dpi=dpi)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, \
            QSizePolicy.Expanding)

        FigureCanvas.updateGeometry(self)
    def compute_normalised_by_order(self, ap, n, aa) -> ApproximationErrorCode:
        """ Generates normalised transfer function prioritising the fixed order """
        # Computing needed constants
        epsilon = self.compute_epsilon(ap)
        factor = 1 / np.float_power(epsilon, 1 / n)

        # Getting the Butterworth approximation for the given order
        # and matching it with the given maximum attenuation for pass band
        zeros, poles, gain = ss.buttap(n)
        new_zeros = zeros
        new_poles = [factor * pole for pole in poles]
        new_gain = gain

        # Updating the local transfer function, no errors!
        self.h_aux = ss.ZerosPolesGain(new_zeros, new_poles, new_gain)
        return ApproximationErrorCode.OK
Exemple #19
0
def task3c():
    sys1_num = [1, 2, 1]
    sys1_denom = [1]
    sys2_num = [1, 0]
    sys2_denom = [1, 0.9]
    sys1_gain = 1
    sys1_zeros = [-1, -1]
    sys1_poles = []
    sys1 = sig.dlti(sys1_num, sys1_denom)
    sys2 = sig.dlti(sys2_num, sys2_denom)
    w1, mag1, phase1 = sig.dbode(sys1, n=100000)
    w2, mag2, phase2 = sig.dbode(sys2, n=100000)
    plt.semilogx(w1, mag1)
    plt.title("magnitude response of first system")
    plt.savefig("task3c mag1.pdf")
    plt.show()

    plt.semilogx(w1, phase1)
    plt.title("phase response of first system")
    plt.savefig("task3c phase1.pdf")
    plt.show()

    plt.semilogx(w2, mag2)
    plt.title("magnitude response of second system")
    plt.savefig("task3c mag2.pdf")
    plt.show()

    plt.semilogx(w2, phase2)
    plt.title("phase response of second system")
    plt.savefig("task3c phase2.pdf")
    plt.show()
    sys1 = sig.ZerosPolesGain(sys1_zeros, )
    n = np.arange(1000)
    x = 1 / 2 * np.sin(np.pi * n + np.pi / 4)
    out1 = sig.dlsim(sys1, x)
    out2 = sig.dlsim(sys2, x)

    plt.plot(n, out1)
    plt.title("output of system 1")
    plt.savefig("task3e output1.pdf")
    plt.show()

    plt.plot(n, out2)
    plt.title("output of system 2")
    plt.savefig("task3e output2.pdf")
    plt.show()
Exemple #20
0
    def getPidControlledResponse(t, u, dt, x1_0, x2_0):
        pidOutList = np.full_like(t, 0.0)
        systemOutList = np.full_like(t, 0.0)
        systemOutList[0] = x1_0

        kPid = 1
        numPid = [-1.0, -1.0]
        denPid = [-0.001, -1.0]
        pid = signal.ZerosPolesGain(numPid, denPid, kPid)
        pidSS = pid.to_ss()
        oldStatePid = [0.0, 0.0]
        # oldStatePid = pidSS.B

        numSys = [1.0]
        denSys = [1.0, 1.0, 1.0]
        testSystem = signal.TransferFunction(numSys, denSys)
        testSystemSS = testSystem.to_ss()
        oldStateSys = [0.0, x1_0]
        # oldStateSys = testSystemSS.B

        for tIndex in range(1, len(t)):
            e = [
                u[tIndex - 1] - systemOutList[tIndex - 1],
                u[tIndex - 1] - systemOutList[tIndex - 1]
            ]
            tPid, pidOut, oldStatesPid = signal.lsim(pidSS,
                                                     e, [0.0, dt],
                                                     X0=oldStatePid)
            oldStatePid = oldStatesPid[-1]
            pidOutList[tIndex] = pidOut[-1]

            # clip the pid to 0.0 - 1.0
            if pidOutList[tIndex] > 1.0:
                pidOutList[tIndex] = 1.0
            if pidOutList[tIndex] < 0.0:
                pidOutList[tIndex] = 0.0

            tSys, sysOut, oldStatesSys = signal.lsim(
                testSystemSS, [pidOutList[tIndex], pidOutList[tIndex]],
                [0.0, dt],
                X0=oldStateSys)
            oldStateSys = oldStatesSys[-1]
            systemOutList[tIndex] = sysOut[-1]

        return pidOutList, systemOutList
Exemple #21
0
def plot_DARM_local(start, end, fres, figval=1):
    #ch = 'K1:CAL-CS_PROC_DARM_DISPLACEMENT_DQ'
    data = np.loadtxt(
        'C:\\Users\\ayaka\\Dropbox (個人)\\Shoda\\NoiseSubtraction\\DARMspe.txt')
    ff = data[0]
    spectrum = data[1]
    tf = sig.ZerosPolesGain([10., 10., 10., 10., 10.], [1., 1., 1., 1., 1.],
                            1.e-14)
    freq, mag, phase = sig.bode(tf, ff)
    darm = spectrum * (10.**(mag / 20.))
    fig = plt.figure(figval)
    plt.loglog(freq, darm, label='DARM')
    #plt.loglog(spectrum.frequencies,spectrum.value,label='DARM')
    plt.ylabel(r'Displacement [m/$\sqrt{\rm Hz}$]')
    plt.xlabel('Frequency [Hz]')
    plt.legend()
    plt.grid(True)
    return 0, freq
def plot_DARM(start, end, fres, figval=1):
    ch = 'K1:CAL-CS_PROC_DARM_DISPLACEMENT_DQ'
    try:
        data = TimeSeries.get(ch, start, end, host='k1nds0', port=8088)
    except:
        return 1, 'DARM data cannot be obtained. Try with more recent data.'
    spectrum = data.asd(1. / fres, 1. / fres / 2.)
    tf = sig.ZerosPolesGain([10., 10., 10., 10., 10], [1., 1., 1., 1., 1.],
                            1.e-14)
    freq, mag, phase = sig.bode(tf, spectrum.frequencies.to_value())
    darm = spectrum.value * (10.**(mag / 20.))
    fig = plt.figure(figval)
    plt.loglog(freq, darm, label='DARM')
    #plt.loglog(spectrum.frequencies,spectrum.value,label='DARM')
    plt.ylabel(r'Displacement [m/$\sqrt{\rm Hz}$]')
    plt.xlabel('Frequency [Hz]')
    plt.legend()
    plt.grid(True)
    return 0, freq
Exemple #23
0
def whiten_zpk(signal, fs, flow=0.3, fhigh=30, order=6):

    signal = np.array(signal)
    if len(signal.shape) == 2:
        axis = np.argmax(signal.shape)
    else:
        axis = -1

    zc = [-2*np.pi*flow]*(order//2)
    pc = [-2*np.pi*fhigh]*(order//2)
    kc = 1.0

    sysc = sig.ZerosPolesGain(zc, pc, kc)
    sysd = sysc.to_discrete(dt=1/float(fs), method='bilinear')

    sosW = sig.zpk2sos(sysd.zeros, sysd.poles, sysd.gain)
    signal = sig.sosfiltfilt(sosW, signal, axis=axis)

    return signal
Exemple #24
0
    def single_stage_plots(self, filter_id):
        stages = self.filters[filter_id][0].stages
        st_plots = []
        for stage in stages:
            tf = signal.ZerosPolesGain(stage.zeros, stage.poles,
                                       stage.gain_factor)
            tf = tf.to_tf()

            [w, y, y2] = signal.bode(system=tf, n=1000)
            st_plots.append(
                ContinuousPlotData(x_label="Frequency",
                                   x_units="rad/s",
                                   y_label="Attenuation",
                                   y_units="dB",
                                   x_data=w,
                                   y_data=(-1) * y,
                                   logscale=True,
                                   dB=True))
        return st_plots
Exemple #25
0
def plot_DARM(start, end, fres, figval=1):
    ch = 'K1:CAL-CS_PROC_DARM_DISPLACEMENT_DQ'

    # gps_beg = int(to_gps( start ))
    # gps_end = int(to_gps( end ))
    # gps_beg_head = int(gps_beg/100000)
    # gps_end_head = int(gps_end/100000)
    # if gps_beg_head == gps_end_head:
    #     cache_file="/home/devel/cache/Cache_GPS/%s.cache" % gps_beg_head
    # else:
    #     # merge two cache file
    #     cache1="/home/devel/cache/Cache_GPS/%s.cache" % gps_beg_headelse
    #     cache2="/home/devel/cache/Cache_GPS/%s.cache" % gps_end_head
    #     cache_file="/var/www/html/past_data_viewer/data/%s_%s.cache" % (gps_beg, gps_end)

    #     with open(cache_file, 'w') as outfile:
    #         for i in [cache1, cache2]:
    #             with open(i) as infile:
    #                 outfile.write(infile.read())

    try:
        #data = TimeSeries.read(cache_file, ch, start=gps_beg, end=gps_end, nproc=4)
        data = TimeSeries.get(ch, start, end, host='k1nds2', port=8088)
    except:
        return 1, 'DARM data cannot be obtained. Try with more recent data. %d %d' % (
            gps_beg, gps_end)
    spectrum = data.asd(1. / fres, 1. / fres / 2.)
    tf = sig.ZerosPolesGain([10., 10., 10., 10., 10], [1., 1., 1., 1., 1.],
                            1.e-14)
    freq, mag, phase = sig.bode(tf, spectrum.frequencies.to_value())
    darm = spectrum.value * (10.**(mag / 20.))
    fig = plt.figure(figval)
    plt.loglog(freq, darm, label='DARM')
    #plt.loglog(spectrum.frequencies,spectrum.value,label='DARM')
    plt.ylabel(r'Displacement [m/$\sqrt{\rm Hz}$]')
    plt.xlabel('Frequency [Hz]')
    plt.legend()
    plt.grid(True)
    return 0, freq
Exemple #26
0
 def loadModel(self, filePath):
     _, systemFullName = os.path.split(
         filePath)  # Returns path and file name
     systemName, _ = os.path.splitext(
         systemFullName)  # Returns extension and name
     if self.__UiElems.Sampling_LUT_Combobox.findText(systemName) == -1:
         try:
             with open(filePath, 'r') as inf:
                 systemParameters = ast.literal_eval(inf.read())
             self.__SystemModels[systemName] = signal.ZerosPolesGain(
                 systemParameters['Zeros'], systemParameters['Poles'],
                 systemParameters['Gain'])
             self.__UiElems.Sampling_LUT_Combobox.blockSignals(True)
             self.__UiElems.Sampling_LUT_Combobox.insertItem(0, systemName)
             self.__UiElems.Sampling_LUT_Combobox.blockSignals(False)
         except Exception as e:
             print("Error: Failed to load model \"%s\" with error \"%s\"" %
                   (filePath, e))
     else:
         print(
             "Error: Stopped attempted load of redundant model, existing model at: %s"
             % (self.__UiElems.Sampling_LUT_Combobox.findText(waveName)))
    def adjust_function_gain(zeros: list, poles: list, gain):
        gain_in_db = 20 * np.log10(gain)
        transfer_function = ss.ZerosPolesGain(zeros, poles, gain)
        w, mag, phase = ss.bode(transfer_function, n=1000)

        dmag = np.diff(mag) / np.diff(w)

        frequencies_to_check = 10
        zero_condition = 1.0e-6
        for i in range(len(dmag) - frequencies_to_check):
            values_checked = []
            for j in range(frequencies_to_check):
                values_checked.append(dmag[i + j])

            if all([value < zero_condition for value in values_checked]):
                frequency_to_evaluate = math.floor(i +
                                                   frequencies_to_check / 2)
                max_freq = w[frequency_to_evaluate]
                useless_1, gain_in_passband, useless_2 = ss.bode(
                    transfer_function, [max_freq])
                gain_in_passband = 10**(gain_in_passband[0] / 20)
                gain_needed = gain**2 / gain_in_passband
                return gain_needed
Exemple #28
0
    def from_zpk(self, zeros, poles, gain):
        """Define a SISO system using the zeros, poles, gain representation.

        Parameters
        ----------
        zeros : (num_zeros,) array_like
            system zeros

        poles : (num_poles,) array_like
            system poles

        gain : float
            system gain

        Returns
        -------
        controlboros.StateSpaceBuilder
            intermediate builder object

        """
        zpk = signal.ZerosPolesGain(zeros, poles, gain).to_ss()
        self._a, self._b, self._c, self._d = zpk.A, zpk.B, zpk.C, zpk.D
        return self
Exemple #29
0
def pend_sos(f0, Q, fs, dc_gain=1):
    '''
    Make a digital filter for a pendulum TF in SOS form.
    '''

    if f0 >= fs / 2:
        raise ValueError('f0 too high for nyquist')
    if Q < 0:
        raise ValueError('Q must be >=0')

    w_pole = -2 * np.pi * f0
    angle = np.arccos(1 / 2 / Q)

    zeros = np.array([])
    poles = w_pole * np.array([np.exp(1j * angle), np.exp(-1j * angle)])
    gain = dc_gain * np.prod(poles)

    #sos conversion
    zd, pd, kd = zpk_bilinear(zeros, poles, gain, fs)
    sys_disc = sig.ZerosPolesGain(zd, pd, kd, dt=1 / fs)
    sos = sig.zpk2sos(sys_disc.zeros, sys_disc.poles, sys_disc.gain)

    return sos
    def compute_normalised_by_order(self, ap, n, aa) -> ApproximationErrorCode:
        """ Generates normalised transfer function prioritising the fixed order """
        # Computing needed constants from Legendre Approximation
        epsilon = LegendreApprox.compute_epsilon(ap)**2
        ln = LegendreApprox.compute_odd_integrated_polynomial(n) if (
            n % 2) else LegendreApprox.compute_even_integrated_polynomial(n)
        ln = epsilon * ln
        den = polyadd(poly1d([1]), ln)

        # Normalised transfer function
        new_gain = 1
        new_poles = []
        for pole in 1j * den.roots:
            if pole.real < 0:
                new_pole = complex(
                    pole.real if abs(pole.real) > CONSIDERED_ZERO_LIMIT else 0,
                    pole.imag if abs(pole.imag) > CONSIDERED_ZERO_LIMIT else 0)
                new_gain /= abs(new_pole)
                new_poles.append(new_pole)

        # Updating state of transfer function
        self.h_aux = signal.ZerosPolesGain([], new_poles, new_gain)
        return ApproximationErrorCode.OK