def test_constructor_inconsistent_columns(self):
     """Give the constructor inputs that do not have the same number of
     columns in each row."""
     with pytest.raises(ValueError):
         TransferFunction(1., [[[1.]], [[2.], [3.]]])
     with pytest.raises(ValueError):
         TransferFunction([[[1.]], [[2.], [3.]]], 1.)
Beispiel #2
0
    def setUp(self):
        """Set up a SISO and MIMO system to test operations on."""

        # Single input, single output continuous and discrete time systems
        sys = matlab.rss(3, 1, 1)
        self.siso_ss1 = StateSpace(sys.A, sys.B, sys.C, sys.D)
        self.siso_ss1c = StateSpace(sys.A, sys.B, sys.C, sys.D, 0.0)
        self.siso_ss1d = StateSpace(sys.A, sys.B, sys.C, sys.D, 0.1)
        self.siso_ss2d = StateSpace(sys.A, sys.B, sys.C, sys.D, 0.2)
        self.siso_ss3d = StateSpace(sys.A, sys.B, sys.C, sys.D, True)

        # Two input, two output continuous time system
        A = [[-3., 4., 2.], [-1., -3., 0.], [2., 5., 3.]]
        B = [[1., 4.], [-3., -3.], [-2., 1.]]
        C = [[4., 2., -3.], [1., 4., 3.]]
        D = [[-2., 4.], [0., 1.]]
        self.mimo_ss1 = StateSpace(A, B, C, D)
        self.mimo_ss1c = StateSpace(A, B, C, D, 0)

        # Two input, two output discrete time system
        self.mimo_ss1d = StateSpace(A, B, C, D, 0.1)

        # Same system, but with a different sampling time
        self.mimo_ss2d = StateSpace(A, B, C, D, 0.2)

        # Single input, single output continuus and discrete transfer function
        self.siso_tf1 = TransferFunction([1, 1], [1, 2, 1])
        self.siso_tf1c = TransferFunction([1, 1], [1, 2, 1], 0)
        self.siso_tf1d = TransferFunction([1, 1], [1, 2, 1], 0.1)
        self.siso_tf2d = TransferFunction([1, 1], [1, 2, 1], 0.2)
        self.siso_tf3d = TransferFunction([1, 1], [1, 2, 1], True)
    def test_freqresp_mimo(self):
        """Evaluate the MIMO magnitude and phase at multiple frequencies."""
        num = [[[1., 2.], [0., 3.], [2., -1.]],
               [[1.], [4., 0.], [1., -4., 3.]]]
        den = [[[-3., 2., 4.], [1., 0., 0.], [2., -1.]],
               [[3., 0., .0], [2., -1., -1.], [1.]]]
        sys = TransferFunction(num, den)

        true_omega = [0.1, 1., 10.]
        true_mag = [[[0.49628709, 0.30714755, 0.03347381],
                    [300., 3., 0.03], [1., 1., 1.]],
                    [[33.333333, 0.33333333, 0.00333333],
                     [0.39028569, 1.26491106, 0.19875914],
                    [3.01663720, 4.47213595, 104.92378186]]]
        true_phase = [[[3.7128711e-4, 0.18534794,
                        1.30770596], [-np.pi, -np.pi, -np.pi],
                       [0., 0., 0.]],
                      [[-np.pi, -np.pi, -np.pi],
                       [-1.66852323, -1.89254688, -1.62050658],
                       [-0.13298964, -1.10714871, -2.75046720]]]

        mag, phase, omega = sys.frequency_response(true_omega)

        np.testing.assert_array_almost_equal(mag, true_mag)
        np.testing.assert_array_almost_equal(phase, true_phase)
        np.testing.assert_allclose(omega, true_omega)
Beispiel #4
0
def winding_number_condition(plant_1: TransferFunction,
                             plant_2: TransferFunction) -> bool:
    """
        :param plant_1: Transferfunction of linearized SISO plant
        :param plant_2: Transferfunction of linearized SISO plant

        returns: True if plant_1 and plant_2 satisfy the winding number condition. (False if not)
    """

    plant_2_c = conjugate_plant(plant_2)

    def f(x):
        p = abs(evalfr(1 + plant_2_c * plant_1, 1j * x))
        return p

    min_obj = minimize_scalar(f, method="golden")
    if f(min_obj.x) == 0:
        return False

    wno = nyquist_plot(1 + plant_2_c * plant_1)
    eta_0 = 0
    eta_1 = 0
    eta_2 = 0
    plant_1_poles = plant_1.pole()
    plant_2_poles = plant_2.pole()
    for p in plant_1_poles:
        if np.real(p) > 0:
            eta_1 = eta_1 + 1
    for p in plant_2_poles:
        if np.real(p) > 0:
            eta_2 = eta_2 + 1
        if np.real(p) == 0:
            eta_0 = eta_0 + 1
    return wno + eta_1 - eta_2 - eta_0 == 0
 def test_constructor_zero_denominator(self):
     """Give the constructor a transfer function with a zero denominator."""
     with pytest.raises(ValueError):
         TransferFunction(1., 0.)
     with pytest.raises(ValueError):
         TransferFunction([[[1.], [2., 3.]], [[-1., 4.], [3., 2.]]],
                          [[[1., 0.], [0.]], [[0., 0.], [2.]]])
Beispiel #6
0
    def testSystemInitialization(self, tsys):
        # Check to make sure systems are discrete time with proper variables
        assert tsys.siso_ss1.dt is None
        assert tsys.siso_ss1c.dt == 0
        assert tsys.siso_ss1d.dt == 0.1
        assert tsys.siso_ss2d.dt == 0.2
        assert tsys.siso_ss3d.dt is True
        assert tsys.mimo_ss1c.dt == 0
        assert tsys.mimo_ss1d.dt == 0.1
        assert tsys.mimo_ss2d.dt == 0.2
        assert tsys.siso_tf1.dt is None
        assert tsys.siso_tf1c.dt == 0
        assert tsys.siso_tf1d.dt == 0.1
        assert tsys.siso_tf2d.dt == 0.2
        assert tsys.siso_tf3d.dt is True

        # keyword argument check
        # dynamic systems
        assert TransferFunction(1, [1, 1], dt=0.1).dt == 0.1
        assert TransferFunction(1, [1, 1], 0.1).dt == 0.1
        assert StateSpace(1,1,1,1, dt=0.1).dt == 0.1
        assert StateSpace(1,1,1,1, 0.1).dt == 0.1
        # static gain system, dt argument should still override default dt
        assert TransferFunction(1, [1,], dt=0.1).dt == 0.1
        assert TransferFunction(1, [1,], 0.1).dt == 0.1
        assert StateSpace(0,0,1,1, dt=0.1).dt == 0.1
        assert StateSpace(0,0,1,1, 0.1).dt == 0.1
Beispiel #7
0
    def tsys(self):
        """Create some systems for testing"""
        class Tsys:
            pass
        T = Tsys()
        # Single input, single output continuous and discrete time systems
        sys = rss(3, 1, 1)
        T.siso_ss1 = StateSpace(sys.A, sys.B, sys.C, sys.D, None)
        T.siso_ss1c = StateSpace(sys.A, sys.B, sys.C, sys.D, 0.0)
        T.siso_ss1d = StateSpace(sys.A, sys.B, sys.C, sys.D, 0.1)
        T.siso_ss2d = StateSpace(sys.A, sys.B, sys.C, sys.D, 0.2)
        T.siso_ss3d = StateSpace(sys.A, sys.B, sys.C, sys.D, True)

        # Two input, two output continuous time system
        A = [[-3., 4., 2.], [-1., -3., 0.], [2., 5., 3.]]
        B = [[1., 4.], [-3., -3.], [-2., 1.]]
        C = [[4., 2., -3.], [1., 4., 3.]]
        D = [[-2., 4.], [0., 1.]]
        T.mimo_ss1 = StateSpace(A, B, C, D, None)
        T.mimo_ss1c = StateSpace(A, B, C, D, 0)

        # Two input, two output discrete time system
        T.mimo_ss1d = StateSpace(A, B, C, D, 0.1)

        # Same system, but with a different sampling time
        T.mimo_ss2d = StateSpace(A, B, C, D, 0.2)

        # Single input, single output continuus and discrete transfer function
        T.siso_tf1 = TransferFunction([1, 1], [1, 2, 1], None)
        T.siso_tf1c = TransferFunction([1, 1], [1, 2, 1], 0)
        T.siso_tf1d = TransferFunction([1, 1], [1, 2, 1], 0.1)
        T.siso_tf2d = TransferFunction([1, 1], [1, 2, 1], 0.2)
        T.siso_tf3d = TransferFunction([1, 1], [1, 2, 1], True)

        return T
    def test_multiply_mimo(self):
        """Multiply two MIMO systems."""
        num1 = [[[1., 2.], [0., 3.], [2., -1.]],
                [[1.], [4., 0.], [1., -4., 3.]]]
        den1 = [[[-3., 2., 4.], [1., 0., 0.], [2., -1.]],
                [[3., 0., .0], [2., -1., -1.], [1.]]]
        num2 = [[[0., 1., 2.]],
                [[1., -5.]],
                [[-2., 1., 4.]]]
        den2 = [[[1., 0., 0., 0.]],
                [[-2., 1., 3.]],
                [[4., -1., -1., 0.]]]
        num3 = [[[-24., 52., -14., 245., -490., -115., 467., -95., -56., 12.,
                  0., 0., 0.]],
                [[24., -132., 138., 345., -768., -106., 510., 41., -79., -69.,
                 -23., 17., 6., 0.]]]
        den3 = [[[48., -92., -84., 183., 44., -97., -2., 12., 0., 0., 0., 0.,
                  0., 0.]],
                [[-48., 60., 84., -81., -45., 21., 9., 0., 0., 0., 0., 0., 0.]]]

        sys1 = TransferFunction(num1, den1)
        sys2 = TransferFunction(num2, den2)
        sys3 = sys1 * sys2

        for i in range(sys3.noutputs):
            for j in range(sys3.ninputs):
                np.testing.assert_allclose(sys3.num[i][j], num3[i][j])
                np.testing.assert_allclose(sys3.den[i][j], den3[i][j])
    def test_divide_scalar(self):
        """Divide two direct feedthrough systems."""
        sys1 = TransferFunction(np.array([3.]), -4.)
        sys2 = TransferFunction(5., 2.)
        sys3 = sys1 / sys2

        np.testing.assert_allclose(sys3.num, [[[6.]]])
        np.testing.assert_allclose(sys3.den, [[[-20.]]])
    def test_subtract_scalar(self):
        """Subtract two direct feedthrough systems."""
        sys1 = TransferFunction(1., [[[1.]]])
        sys2 = TransferFunction(np.array([2.]), [1.])
        sys3 = sys1 - sys2

        np.testing.assert_allclose(sys3.num, -1.)
        np.testing.assert_allclose(sys3.den, 1.)
Beispiel #11
0
    def test_timebase_conversions(self, tsys):
        '''Check to make sure timebases transfer properly'''
        tf1 = TransferFunction([1, 1], [1, 2, 3], None)  # unspecified
        tf2 = TransferFunction([1, 1], [1, 2, 3], 0)     # cont time
        tf3 = TransferFunction([1, 1], [1, 2, 3], True)  # dtime, unspec
        tf4 = TransferFunction([1, 1], [1, 2, 3], .1)    # dtime, dt=.1

        # Make sure unspecified timebase is converted correctly
        assert timebase(tf1*tf1) == timebase(tf1)
        assert timebase(tf1*tf2) == timebase(tf2)
        assert timebase(tf1*tf3) == timebase(tf3)
        assert timebase(tf1*tf4) == timebase(tf4)
        assert timebase(tf3*tf4) == timebase(tf4)
        assert timebase(tf2*tf1) == timebase(tf2)
        assert timebase(tf3*tf1) == timebase(tf3)
        assert timebase(tf4*tf1) == timebase(tf4)
        assert timebase(tf1+tf1) == timebase(tf1)
        assert timebase(tf1+tf2) == timebase(tf2)
        assert timebase(tf1+tf3) == timebase(tf3)
        assert timebase(tf1+tf4) == timebase(tf4)
        assert timebase(feedback(tf1, tf1)) == timebase(tf1)
        assert timebase(feedback(tf1, tf2)) == timebase(tf2)
        assert timebase(feedback(tf1, tf3)) == timebase(tf3)
        assert timebase(feedback(tf1, tf4)) == timebase(tf4)

        # Make sure discrete time without sampling is converted correctly
        assert timebase(tf3*tf3) == timebase(tf3)
        assert timebase(tf3*tf4) == timebase(tf4)
        assert timebase(tf3+tf3) == timebase(tf3)
        assert timebase(tf3+tf4) == timebase(tf4)
        assert timebase(feedback(tf3, tf3)) == timebase(tf3)
        assert timebase(feedback(tf3, tf4)) == timebase(tf4)

        # Make sure all other combinations are errors
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf2 * tf3
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf3 * tf2
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf2 * tf4
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf4 * tf2
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf2 + tf3
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf3 + tf2
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf2 + tf4
        with pytest.raises(ValueError, match="incompatible timebases"):
            tf4 + tf2
        with pytest.raises(ValueError, match="incompatible timebases"):
            feedback(tf2, tf3)
        with pytest.raises(ValueError, match="incompatible timebases"):
            feedback(tf3, tf2)
        with pytest.raises(ValueError, match="incompatible timebases"):
            feedback(tf2, tf4)
        with pytest.raises(ValueError, match="incompatible timebases"):
            feedback(tf4, tf2)
    def test_add_siso(self):
        """Add two SISO systems."""
        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
        sys2 = TransferFunction([[np.array([-1., 3.])]], [[[1., 0., -1.]]])
        sys3 = sys1 + sys2

        # If sys3.num is [[[0., 20., 4., -8.]]], then this is wrong!
        np.testing.assert_allclose(sys3.num, [[[20., 4., -8]]])
        np.testing.assert_allclose(sys3.den, [[[1., 6., 1., -7., -2., 1.]]])
 def test_minreal_4(self):
     """Check minreal on discrete TFs."""
     T = 0.01
     z = TransferFunction([1, 0], [1], T)
     h = (z - 1.00000000001) * (z + 1.0000000001) / (z**2 - 1)
     hm = h.minreal()
     hr = TransferFunction([1], [1], T)
     np.testing.assert_allclose(hm.num[0][0], hr.num[0][0])
     np.testing.assert_allclose(hr.dt, hm.dt)
 def test_constructor_inconsistent_dimension(self):
     """Give constructor numerators, denominators of different sizes."""
     with pytest.raises(ValueError):
         TransferFunction([[[1.]]], [[[1.], [2., 3.]]])
     with pytest.raises(ValueError):
         TransferFunction([[[1.]]], [[[1.]], [[2., 3.]]])
     with pytest.raises(ValueError):
         TransferFunction([[[1.]]],
                          [[[1.], [1., 2.]], [[5., 2.], [2., 3.]]])
    def test_subtract_siso(self):
        """Subtract two SISO systems."""
        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
        sys2 = TransferFunction([[np.array([-1., 3.])]], [[[1., 0., -1.]]])
        sys3 = sys1 - sys2
        sys4 = sys2 - sys1

        np.testing.assert_allclose(sys3.num, [[[2., 6., -12., -10., -2.]]])
        np.testing.assert_allclose(sys3.den, [[[1., 6., 1., -7., -2., 1.]]])
        np.testing.assert_allclose(sys4.num, [[[-2., -6., 12., 10., 2.]]])
        np.testing.assert_allclose(sys4.den, [[[1., 6., 1., -7., -2., 1.]]])
    def test_multiply_siso(self):
        """Multiply two SISO systems."""
        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
        sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
        sys3 = sys1 * sys2
        sys4 = sys2 * sys1

        np.testing.assert_allclose(sys3.num, [[[-1., 0., 4., 15.]]])
        np.testing.assert_allclose(sys3.den, [[[1., 6., 1., -7., -2., 1.]]])
        np.testing.assert_allclose(sys3.num, sys4.num)
        np.testing.assert_allclose(sys3.den, sys4.den)
    def test_multiply_scalar(self):
        """Multiply two direct feedthrough systems."""
        sys1 = TransferFunction(2., [1.])
        sys2 = TransferFunction(1., 4.)
        sys3 = sys1 * sys2
        sys4 = sys1 * sys2

        np.testing.assert_allclose(sys3.num, [[[2.]]])
        np.testing.assert_allclose(sys3.den, [[[4.]]])
        np.testing.assert_allclose(sys3.num, sys4.num)
        np.testing.assert_allclose(sys3.den, sys4.den)
    def test_divide_siso(self):
        """Divide two SISO systems."""
        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
        sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]])
        sys3 = sys1 / sys2
        sys4 = sys2 / sys1

        np.testing.assert_allclose(sys3.num, [[[1., 3., 4., -3., -5.]]])
        np.testing.assert_allclose(sys3.den, [[[-1., -3., 16., 7., -3.]]])
        np.testing.assert_allclose(sys4.num, sys3.den)
        np.testing.assert_allclose(sys4.den, sys3.num)
Beispiel #19
0
def calc_psi_and_phi_lists(s1, TF):
    zeros_a = TF.zero()  #this returns an array
    zeros = zeros_a.tolist()
    zeros.reverse()  #arrays don't have the reverse method that lists do
    poles_a = TF.pole()
    poles = poles_a.tolist()
    poles.reverse()

    psi_list = calc_angle_list(s1, zeros)
    phi_list = calc_angle_list(s1, poles)
    return psi_list, phi_list
Beispiel #20
0
def calc_psi_and_phi_lists(s1, TF):
    zeros_a = TF.zero()#this returns an array
    zeros = zeros_a.tolist()
    zeros.reverse()#arrays don't have the reverse method that lists do
    poles_a = TF.pole()
    poles = poles_a.tolist()
    poles.reverse()

    psi_list = calc_angle_list(s1, zeros)
    phi_list = calc_angle_list(s1, poles)
    return psi_list, phi_list
    def test_feedback_siso(self):
        """Test for correct SISO transfer function feedback."""
        sys1 = TransferFunction([-1., 4.], [1., 3., 5.])
        sys2 = TransferFunction([2., 3., 0.], [1., -3., 4., 0])

        sys3 = sys1.feedback(sys2)
        sys4 = sys1.feedback(sys2, 1)

        np.testing.assert_allclose(sys3.num, [[[-1., 7., -16., 16., 0.]]])
        np.testing.assert_allclose(sys3.den, [[[1., 0., -2., 2., 32., 0.]]])
        np.testing.assert_allclose(sys4.num, [[[-1., 7., -16., 16., 0.]]])
        np.testing.assert_allclose(sys4.den, [[[1., 0., 2., -8., 8., 0.]]])
Beispiel #22
0
    def test_constructor_nodt(self):
        """Test the constructor when an object without dt is passed"""
        sysin = TransferFunction([[[0., 1.], [2., 3.]]],
                                 [[[5., 2.], [3., 0.]]])
        del sysin.dt  # this doesn't make sense and now breaks
        sys = TransferFunction(sysin)
        assert sys.dt == defaults['control.default_dt']

        # test for static gain
        sysin = TransferFunction([[[2.], [3.]]], [[[1.], [.1]]])
        del sysin.dt  # this doesn't make sense and now breaks
        sys = TransferFunction(sysin)
        assert sys.dt is None
Beispiel #23
0
    def test__isstatic(self):
        numstatic = 1.1
        denstatic = 1.2
        numdynamic = [1, 1]
        dendynamic = [2, 1]
        numstaticmimo = [[[
            1.1,
        ], [
            1.2,
        ]], [[
            1.2,
        ], [
            0.8,
        ]]]
        denstaticmimo = [[[
            1.9,
        ], [
            1.2,
        ]], [[
            1.2,
        ], [
            0.8,
        ]]]
        numdynamicmimo = [[[1.1, 0.9], [1.2]], [[1.2], [0.8]]]
        dendynamicmimo = [[[1.1, 0.7], [0.2]], [[1.2], [0.8]]]
        assert TransferFunction(numstatic, denstatic)._isstatic()
        assert TransferFunction(numstaticmimo, denstaticmimo)._isstatic()

        assert not TransferFunction(numstatic, dendynamic)._isstatic()
        assert not TransferFunction(numdynamic, dendynamic)._isstatic()
        assert not TransferFunction(numdynamic, denstatic)._isstatic()
        assert not TransferFunction(numstatic, dendynamic)._isstatic()

        assert not TransferFunction(numstaticmimo, dendynamicmimo)._isstatic()
        assert not TransferFunction(numdynamicmimo, denstaticmimo)._isstatic()
Beispiel #24
0
    def test_step_robustness(self):
        "Test robustness os step_response against denomiantors: gh-240"
        # Create 2 input, 2 output system
        num =  [[[0], [1]],           [[1],    [0]]]

        den1 = [[[1], [1,1]],         [[1, 4], [1]]]
        sys1 = TransferFunction(num, den1)

        den2 = [[[1], [1e-10, 1, 1]], [[1, 4], [1]]]   # slight perturbation
        sys2 = TransferFunction(num, den2)

        t1, y1 = step_response(sys1, input=0, T=2, T_num=100)
        t2, y2 = step_response(sys2, input=0, T=2, T_num=100)
        np.testing.assert_array_almost_equal(y1, y2)
    def test_repr(self, Hargs, ref):
        """Test __repr__ printout."""
        H = TransferFunction(*Hargs)

        assert repr(H) == ref

        # and reading back
        array = np.array  # noqa
        H2 = eval(H.__repr__())
        for p in range(len(H.num)):
            for m in range(len(H.num[0])):
                np.testing.assert_array_almost_equal(H.num[p][m], H2.num[p][m])
                np.testing.assert_array_almost_equal(H.den[p][m], H2.den[p][m])
            assert H.dt == H2.dt
Beispiel #26
0
    def test_common_den(self):
        """ Test the helper function to compute common denomitators."""
        # _common_den() computes the common denominator per input/column.
        # The testing columns are:
        # 0: no common poles
        # 1: regular common poles
        # 2: poles with multiplicity,
        # 3: complex poles
        # 4: complex poles below threshold

        eps = np.finfo(float).eps
        tol_imag = np.sqrt(eps * 5 * 2 * 2) * 0.9

        numin = [[[1.], [1.], [1.], [1.], [1.]], [[1.], [1.], [1.], [1.],
                                                  [1.]]]
        denin = [
            [
                [1., 3., 2.],  # 0: poles: [-1, -2]
                [1., 6., 11., 6.],  # 1: poles: [-1, -2, -3]
                [1., 6., 11., 6.],  # 2: poles: [-1, -2, -3]
                [1., 6., 11., 6.],  # 3: poles: [-1, -2, -3]
                [1., 6., 11., 6.]
            ],  # 4: poles: [-1, -2, -3],
            [
                [1., 12., 47., 60.],  # 0: poles: [-3, -4, -5]
                [1., 9., 26., 24.],  # 1: poles: [-2, -3, -4]
                [1., 7., 16., 12.],  # 2: poles: [-2, -2, -3]
                [1., 7., 17., 15.],  # 3: poles: [-2+1J, -2-1J, -3],
                np.poly([-2 + tol_imag * 1J, -2 - tol_imag * 1J, -3])
            ]
        ]
        numref = np.array([[[0., 0., 1., 12., 47., 60.],
                            [0., 0., 0., 1., 4., 0.], [0., 0., 0., 1., 2., 0.],
                            [0., 0., 0., 1., 4., 5.], [0., 0., 0., 1., 2.,
                                                       0.]],
                           [[0., 0., 0., 1., 3., 2.], [0., 0., 0., 1., 1., 0.],
                            [0., 0., 0., 1., 1., 0.], [0., 0., 0., 1., 3., 2.],
                            [0., 0., 0., 1., 1., 0.]]])
        denref = np.array([[1., 15., 85., 225., 274., 120.],
                           [1., 10., 35., 50., 24., 0.],
                           [1., 8., 23., 28., 12., 0.],
                           [1., 10., 40., 80., 79., 30.],
                           [1., 8., 23., 28., 12., 0.]])
        sys = TransferFunction(numin, denin)
        num, den, denorder = sys._common_den()
        np.testing.assert_array_almost_equal(num[:2, :, :], numref)
        np.testing.assert_array_almost_equal(num[2:, :, :], np.zeros(
            (3, 5, 6)))
        np.testing.assert_array_almost_equal(den, denref)
Beispiel #27
0
 def testCopyConstructor(self, tsys):
     for sys in (tsys.siso_ss1, tsys.siso_ss1c, tsys.siso_ss1d):
         newsys = StateSpace(sys)
         assert sys.dt == newsys.dt
     for sys in (tsys.siso_tf1, tsys.siso_tf1c, tsys.siso_tf1d):
         newsys = TransferFunction(sys)
         assert sys.dt == newsys.dt
    def test_call_siso(self, dt, omega, resp):
        """Evaluate the frequency response of a SISO system at one frequency."""
        sys = TransferFunction([1., 3., 5], [1., 6., 2., -1])

        if dt:
            sys = sample_system(sys, dt)
            s = np.exp(omega * 1j * dt)
        else:
            s = omega * 1j

        # Correct versions of the call
        np.testing.assert_allclose(evalfr(sys, s), resp, atol=1e-3)
        np.testing.assert_allclose(sys(s), resp, atol=1e-3)
        # Deprecated version of the call (should generate exception)
        with pytest.raises(AttributeError):
            np.testing.assert_allclose(sys.evalfr(omega), resp, atol=1e-3)
    def test_frequency_response_siso(self):
        """Evaluate the magnitude and phase of a SISO system at
        multiple frequencies."""

        sys = TransferFunction([1., 3., 5], [1., 6., 2., -1])

        truemag = [[[4.63507337473906, 0.707106781186548, 0.0866592803995351]]]
        truephase = [[[-2.89596891081488, -2.35619449019234,
                       -1.32655885133871]]]
        trueomega = [0.1, 1., 10.]

        mag, phase, omega = sys.frequency_response(trueomega, squeeze=False)

        np.testing.assert_array_almost_equal(mag, truemag)
        np.testing.assert_array_almost_equal(phase, truephase)
        np.testing.assert_array_almost_equal(omega, trueomega)
    def test_step_info(self):
        # From matlab docs:
        sys = TransferFunction([1, 5, 5], [1, 1.65, 5, 6.5, 2])
        Strue = {
            'RiseTime': 3.8456,
            'SettlingTime': 27.9762,
            'SettlingMin': 2.0689,
            'SettlingMax': 2.6873,
            'Overshoot': 7.4915,
            'Undershoot': 0,
            'Peak': 2.6873,
            'PeakTime': 8.0530,
            'SteadyStateValue': 2.50
        }

        S = step_info(sys)

        Sk = sorted(S.keys())
        Sktrue = sorted(Strue.keys())
        assert Sk == Sktrue
        # Very arbitrary tolerance because I don't know if the
        # response from the MATLAB is really that accurate.
        # maybe it is a good idea to change the Strue to match
        # but I didn't do it because I don't know if it is
        # accurate either...
        rtol = 2e-2
        np.testing.assert_allclose([S[k] for k in Sk],
                                   [Strue[k] for k in Sktrue],
                                   rtol=rtol)
Beispiel #31
0
 def testCopyConstructor(self):
     for sys in (self.siso_ss1, self.siso_ss1c, self.siso_ss1d):
         newsys = StateSpace(sys)
         self.assertEqual(sys.dt, newsys.dt)
     for sys in (self.siso_tf1, self.siso_tf1c, self.siso_tf1d):
         newsys = TransferFunction(sys)
         self.assertEqual(sys.dt, newsys.dt)