示例#1
0
    def test_reverse_sign_mimo(self):
        """Negate a MIMO system."""
        num1 = [[[1., 2.], [0., 3.], [2., -1.]], [[1.], [4., 0.],
                                                  [1., -4., 3.]]]
        num3 = [[[-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.]]]

        sys1 = TransferFunction(num1, den1)
        sys2 = -sys1
        sys3 = TransferFunction(num3, den1)

        for i in range(sys3.outputs):
            for j in range(sys3.inputs):
                np.testing.assert_array_equal(sys2.num[i][j], sys3.num[i][j])
                np.testing.assert_array_equal(sys2.den[i][j], sys3.den[i][j])
def test_phase_crossover_frequencies_mimo():
    """Test MIMO exception"""
    tf = TransferFunction([[[1], [2]],
                           [[3], [4]]],
                          [[[1, 2, 3, 4], [1, 1]],
                           [[1, 1], [1, 1]]])
    with pytest.raises(ControlMIMONotImplemented):
        omega, gain = phase_crossover_frequencies(tf)
示例#3
0
    def setUp(self):
        """This contains some random LTI systems and scalars for testing."""

        # Two random SISO systems.
        sys1 = TransferFunction([1, 2], [1, 2, 3])
        sys2 = StateSpace([[1., 4.], [3., 2.]], [[1.], [-4.]],
            [[1., 0.]], [[0.]])
        self.systems = (sys1, sys2)
示例#4
0
    def test_pole_mimo(self):
        """Test for correct MIMO poles."""

        sys = TransferFunction(
            [[[1.], [1.]], [[1.], [1.]]],
            [[[1., 2.], [1., 3.]], [[1., 4., 4.], [1., 9., 14.]]])
        p = sys.pole()

        np.testing.assert_array_almost_equal(p, [-2., -2., -7., -3., -2.])

        # non proper transfer function
        sys2 = TransferFunction(
            [[[1., 2., 3., 4.], [1.]], [[1.], [1.]]],
            [[[1., 2.], [1., 3.]], [[1., 4., 4.], [1., 9., 14.]]])
        p2 = sys2.pole()

        np.testing.assert_array_almost_equal(p2, [-2., -2., -7., -3., -2.])
示例#5
0
 def testNyquist(self):
     h1 = TransferFunction([1], [1, 2, 2])
     omega = np.logspace(-1, 2, 40)
     f1 = FRD(h1, omega, smooth=True)
     freqplot.nyquist(f1, np.logspace(-1, 2, 100))
     # plt.savefig('/dev/null', format='svg')
     plt.figure(2)
     freqplot.nyquist(f1, f1.omega)
    def testPoleMIMO(self):
        """Test for correct MIMO poles."""

        sys = TransferFunction([[[1.], [1.]], [[1.], [1.]]],
            [[[1., 2.], [1., 3.]], [[1., 4., 4.], [1., 9., 14.]]])
        p = sys.pole()

        np.testing.assert_array_almost_equal(p, [-7., -3., -2., -2.])
示例#7
0
    def testNegSISO(self):
        """Negate a SISO system."""

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

        np.testing.assert_array_equal(sys2.num, [[[-1., -3., -5.]]])
        np.testing.assert_array_equal(sys2.den, [[[1., 6., 2., -1.]]])
示例#8
0
    def testNegScalar(self):
        """Negate a direct feedthrough system."""

        sys1 = TransferFunction(2., np.array([-3.]))
        sys2 = -sys1

        np.testing.assert_array_equal(sys2.num, [[[-2.]]])
        np.testing.assert_array_equal(sys2.den, [[[-3.]]])
示例#9
0
def test_phase_crossover_frequencies():
    """Test phase_crossover_frequencies() function"""
    omega, gain = phase_crossover_frequencies(tsys[1][0])
    assert_allclose(omega, [1.73205, 0.], atol=1.5e-3)
    assert_allclose(gain, [-0.5, 0.25], atol=1.5e-3)

    tf = TransferFunction([1], [1, 1])
    omega, gain = phase_crossover_frequencies(tf)
    assert_allclose(omega, [0.], atol=1.5e-3)
    assert_allclose(gain, [1.], atol=1.5e-3)

    # testing MIMO, only (0,0) element is considered
    tf = TransferFunction([[[1], [2]], [[3], [4]]],
                          [[[1, 2, 3, 4], [1, 1]], [[1, 1], [1, 1]]])
    omega, gain = phase_crossover_frequencies(tf)
    assert_allclose(omega, [1.73205, 0.], atol=1.5e-3)
    assert_allclose(gain, [-0.5, 0.25], atol=1.5e-3)
 def test_latex_repr(self):
     """ Test latex printout for TransferFunction """
     Hc = TransferFunction([1e-5, 2e5, 3e-4], [1.2e34, 2.3e-4, 2.3e-45])
     Hd = TransferFunction([1e-5, 2e5, 3e-4], [1.2e34, 2.3e-4, 2.3e-45], .1)
     # TODO: make the multiplication sign configurable
     expmul = r'\times'
     for var, H, suffix in zip(['s', 'z'], [Hc, Hd],
                               ['', r'\quad dt = 0.1']):
         ref = (r'$$\frac{'
                r'1 ' + expmul + ' 10^{-5} ' + var + '^2 '
                r'+ 2 ' + expmul + ' 10^{5} ' + var + ' + 0.0003'
                r'}{'
                r'1.2 ' + expmul + ' 10^{34} ' + var + '^2 '
                r'+ 0.00023 ' + var + ' '
                r'+ 2.3 ' + expmul + ' 10^{-45}'
                r'}' + suffix + '$$')
         self.assertEqual(H._repr_latex_(), ref)
    def test_div(self):
        # Make sure that sampling times work correctly
        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1])
        sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]], True)
        sys3 = sys1 / sys2
        self.assertEqual(sys3.dt, True)

        sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]], 0.5)
        sys3 = sys1 / sys2
        self.assertEqual(sys3.dt, 0.5)

        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1], 0.1)
        self.assertRaises(ValueError, TransferFunction.__truediv__, sys1, sys2)

        sys1 = sample_system(rss(4, 1, 1), 0.5)
        sys3 = TransferFunction.__rtruediv__(sys2, sys1)
        self.assertEqual(sys3.dt, 0.5)
示例#12
0
    def test_constructor_bad_input_type(self):
        """Give the constructor invalid input types."""
        # MIMO requires lists of lists of vectors (not lists of vectors)
        with pytest.raises(TypeError):
            TransferFunction([[0., 1.], [2., 3.]], [[5., 2.], [3., 0.]])
        # good input
        TransferFunction([[[0., 1.], [2., 3.]]],
                         [[[5., 2.], [3., 0.]]])

        # Single argument of the wrong type
        with pytest.raises(TypeError):
            TransferFunction([1])

        # Too many arguments
        with pytest.raises(ValueError):
            TransferFunction(1, 2, 3, 4)

        # Different numbers of elements in numerator rows
        with pytest.raises(ValueError):
            TransferFunction([[[0, 1], [2, 3]],
                              [[4, 5]]],
                             [[[6, 7], [4, 5]],
                              [[2, 3], [0, 1]]])
        with pytest.raises(ValueError):
            TransferFunction([[[0, 1], [2, 3]],
                              [[4, 5], [6, 7]]],
                             [[[6, 7], [4, 5]],
                              [[2, 3]]])
        # good input
        TransferFunction([[[0, 1], [2, 3]],
                          [[4, 5], [6, 7]]],
                         [[[6, 7], [4, 5]],
                          [[2, 3], [0, 1]]])
示例#13
0
    def testSISOtf(self):
        # get a SISO transfer function
        h = TransferFunction([1], [1, 2, 2])
        omega = np.logspace(-1, 2, 10)
        frd = FRD(h, omega)
        assert isinstance(frd, FRD)

        np.testing.assert_array_almost_equal(frd.freqresp([1.0]),
                                             h.freqresp([1.0]))
示例#14
0
    def test_printing_polynomial(self):
        """Cover all _tf_polynomial_to_string code branches"""
        # Note: the assertions below use plain assert statements instead of
        # unittest methods so that debugging with pytest is easier

        assert str(TransferFunction([0], [1])) == "\n0\n-\n1\n"
        assert str(TransferFunction([1.0001], [-1.1111])) == \
            "\n  1\n------\n-1.111\n"
        assert str(TransferFunction([0, 1], [0, 1.])) == "\n1\n-\n1\n"
        for var, dt, dtstring in zip(["s", "z", "z"],
                                     [None, True, 1],
                                     ['', '', '\ndt = 1\n']):
            assert str(TransferFunction([1, 0], [2, 1], dt)) == \
                "\n   {var}\n-------\n2 {var} + 1\n{dtstring}".format(
                    var=var, dtstring=dtstring)
            assert str(TransferFunction([2, 0, -1], [1, 0, 0, 1.2], dt)) == \
                "\n2 {var}^2 - 1\n---------\n{var}^3 + 1.2\n{dtstring}".format(
                    var=var, dtstring=dtstring)
示例#15
0
 def test_ss2tf(self):
     A = np.array([[-4, -1], [-1, -4]])
     B = np.array([[1], [3]])
     C = np.array([[3, 1]])
     D = 0
     sys = ss2tf(A, B, C, D)
     true_sys = TransferFunction([6., 14.], [1., 8., 15.])
     np.testing.assert_almost_equal(sys.num, true_sys.num)
     np.testing.assert_almost_equal(sys.den, true_sys.den)
示例#16
0
 def test_discrete_bode(self):
     # Create a simple discrete time system and check the calculation
     sys = TransferFunction([1], [1, 0.5], 1)
     omega = [1, 2, 3]
     mag_out, phase_out, omega_out = bode(sys, omega)
     H_z = list(map(lambda w: 1. / (np.exp(1.j * w) + 0.5), omega))
     np.testing.assert_array_almost_equal(omega, omega_out)
     np.testing.assert_array_almost_equal(mag_out, np.absolute(H_z))
     np.testing.assert_array_almost_equal(mag_out, np.absolute(H_z))
示例#17
0
    def test_dcgain_discr(self):
        """Test DC gain for discrete-time transfer functions"""
        # static gain
        sys = TransferFunction(6, 3, True)
        np.testing.assert_equal(sys.dcgain(), 2)

        # averaging filter
        sys = TransferFunction(0.5, [1, -0.5], True)
        np.testing.assert_almost_equal(sys.dcgain(), 1)

        # differencer
        sys = TransferFunction(1, [1, -1], True)
        with pytest.warns(RuntimeWarning, match="divide by zero"):
            np.testing.assert_equal(sys.dcgain(), np.inf)

        # summer
        sys = TransferFunction([1, -1], [1], True)
        np.testing.assert_equal(sys.dcgain(), 0)
示例#18
0
 def testMinreal(self):
     """Try the minreal function, and also test easy entry by creation
     of a Laplace variable s"""
     s = TransferFunction([1, 0], [1])
     h = (s + 1) * (s + 2.00000000001) / (s + 2) / (s**2 + s + 1)
     hm = h.minreal()
     hr = (s + 1) / (s**2 + s + 1)
     np.testing.assert_array_almost_equal(hm.num[0][0], hr.num[0][0])
     np.testing.assert_array_almost_equal(hm.den[0][0], hr.den[0][0])
示例#19
0
    def test_div(self):
        # Make sure that sampling times work correctly
        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1], None)
        sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]], True)
        sys3 = sys1 / sys2
        assert sys3.dt is True

        sys2 = TransferFunction([[[-1., 3.]]], [[[1., 0., -1.]]], 0.5)
        sys3 = sys1 / sys2
        assert sys3.dt == 0.5

        sys1 = TransferFunction([1., 3., 5], [1., 6., 2., -1], 0.1)
        with pytest.raises(ValueError):
            TransferFunction.__truediv__(sys1, sys2)

        sys1 = sample_system(rss(4, 1, 1), 0.5)
        sys3 = TransferFunction.__rtruediv__(sys2, sys1)
        assert sys3.dt == 0.5
示例#20
0
    def test_common_den_nonproper(self):
        """ Test _common_den with order(num)>order(den) """
        tf1 = TransferFunction(
                [[[1., 2., 3.]], [[1., 2.]]],
                [[[1., -2.]], [[1., -3.]]])
        tf2 = TransferFunction(
                [[[1., 2.]], [[1., 2., 3.]]],
                [[[1., -2.]], [[1., -3.]]])

        common_den_ref = np.array([[1., -5., 6.]])

        np.testing.assert_raises(ValueError, tf1._common_den)
        np.testing.assert_raises(ValueError, tf2._common_den)

        _, den1, _ = tf1._common_den(allow_nonproper=True)
        np.testing.assert_array_almost_equal(den1, common_den_ref)
        _, den2, _ = tf2._common_den(allow_nonproper=True)
        np.testing.assert_array_almost_equal(den2, common_den_ref)
示例#21
0
    def testOperators(self):
        # get two SISO transfer functions
        h1 = TransferFunction([1], [1, 2, 2])
        h2 = TransferFunction([1], [0.1, 1])
        omega = np.logspace(-1, 2, 10)
        f1 = FRD(h1, omega)
        f2 = FRD(h2, omega)

        np.testing.assert_array_almost_equal(
            (f1 + f2).frequency_response([0.1, 1.0, 10])[0],
            (h1 + h2).frequency_response([0.1, 1.0, 10])[0])
        np.testing.assert_array_almost_equal(
            (f1 + f2).frequency_response([0.1, 1.0, 10])[1],
            (h1 + h2).frequency_response([0.1, 1.0, 10])[1])
        np.testing.assert_array_almost_equal(
            (f1 - f2).frequency_response([0.1, 1.0, 10])[0],
            (h1 - h2).frequency_response([0.1, 1.0, 10])[0])
        np.testing.assert_array_almost_equal(
            (f1 - f2).frequency_response([0.1, 1.0, 10])[1],
            (h1 - h2).frequency_response([0.1, 1.0, 10])[1])

        # multiplication and division
        np.testing.assert_array_almost_equal(
            (f1 * f2).frequency_response([0.1, 1.0, 10])[1],
            (h1 * h2).frequency_response([0.1, 1.0, 10])[1])
        np.testing.assert_array_almost_equal(
            (f1 / f2).frequency_response([0.1, 1.0, 10])[1],
            (h1 / h2).frequency_response([0.1, 1.0, 10])[1])

        # with default conversion from scalar
        np.testing.assert_array_almost_equal(
            (f1 * 1.5).frequency_response([0.1, 1.0, 10])[1],
            (h1 * 1.5).frequency_response([0.1, 1.0, 10])[1])
        np.testing.assert_array_almost_equal(
            (f1 / 1.7).frequency_response([0.1, 1.0, 10])[1],
            (h1 / 1.7).frequency_response([0.1, 1.0, 10])[1])
        np.testing.assert_array_almost_equal(
            (2.2 * f2).frequency_response([0.1, 1.0, 10])[1],
            (2.2 * h2).frequency_response([0.1, 1.0, 10])[1])
        np.testing.assert_array_almost_equal(
            (1.3 / f2).frequency_response([0.1, 1.0, 10])[1],
            (1.3 / h2).frequency_response([0.1, 1.0, 10])[1])
示例#22
0
 def testMatrixMult(self):
     """MIMO transfer functions should be multiplyable by constant 
     matrices"""
     s = TransferFunction([1, 0], [1])
     b0 = 0.2
     b1 = 0.1
     b2 = 0.5
     a0 = 2.3
     a1 = 6.3
     a2 = 3.6
     a3 = 1.0
     h = (b0 + b1 * s + b2 * s**2) / (a0 + a1 * s + a2 * s**2 + a3 * s**3)
     H = TransferFunction([[h.num[0][0]], [(h * s).num[0][0]]],
                          [[h.den[0][0]], [h.den[0][0]]])
     H1 = (np.matrix([[1.0, 0]]) * H).minreal()
     H2 = (np.matrix([[0, 1.0]]) * H).minreal()
     np.testing.assert_array_almost_equal(H.num[0][0], H1.num[0][0])
     np.testing.assert_array_almost_equal(H.den[0][0], H1.den[0][0])
     np.testing.assert_array_almost_equal(H.num[1][0], H2.num[0][0])
     np.testing.assert_array_almost_equal(H.den[1][0], H2.den[0][0])
示例#23
0
 def testMIMO(self):
     """Test conversion of a single input, two-output state-space
     system against the same TF"""
     s = TransferFunction([1, 0], [1])
     b0 = 0.2
     b1 = 0.1
     b2 = 0.5
     a0 = 2.3
     a1 = 6.3
     a2 = 3.6
     a3 = 1.0
     h = (b0 + b1 * s + b2 * s**2) / (a0 + a1 * s + a2 * s**2 + a3 * s**3)
     H = TransferFunction([[h.num[0][0]], [(h * s).num[0][0]]],
                          [[h.den[0][0]], [h.den[0][0]]])
     sys = _convertToStateSpace(H)
     H2 = _convertToTransferFunction(sys)
     np.testing.assert_array_almost_equal(H.num[0][0], H2.num[0][0])
     np.testing.assert_array_almost_equal(H.den[0][0], H2.den[0][0])
     np.testing.assert_array_almost_equal(H.num[1][0], H2.num[1][0])
     np.testing.assert_array_almost_equal(H.den[1][0], H2.den[1][0])
示例#24
0
 def test_mag_phase_omega(self):
     # test for bug reported in gh-58
     sys = TransferFunction(15, [1, 6, 11, 6])
     out = stability_margins(sys)
     omega = np.logspace(-1, 1, 100)
     mag, phase, omega = sys.freqresp(omega)
     out2 = stability_margins((mag, phase * 180 / np.pi, omega))
     ind = [0, 1, 3, 4]  # indices of gm, pm, wg, wp -- ignore sm
     marg1 = np.array(out)[ind]
     marg2 = np.array(out2)[ind]
     np.testing.assert_array_almost_equal(marg1, marg2, 4)
示例#25
0
def test_mag_phase_omega():
    """Test for bug reported in gh-58"""
    sys = TransferFunction(15, [1, 6, 11, 6])
    out = stability_margins(sys)
    omega = np.logspace(-2, 2, 1000)
    mag, phase, omega = sys.frequency_response(omega)
    out2 = stability_margins((mag, phase * 180 / np.pi, omega))
    ind = [0, 1, 3, 4]  # indices of gm, pm, wg, wp -- ignore sm
    marg1 = np.array(out)[ind]
    marg2 = np.array(out2)[ind]
    assert_allclose(marg1, marg2, atol=1.5e-3)
示例#26
0
    def test_evalfr_deprecated(self):
        sys = TransferFunction([1., 3., 5], [1., 6., 2., -1])

        # Deprecated version of the call (should generate warning)
        import warnings
        with warnings.catch_warnings():
            # Make warnings generate an exception
            warnings.simplefilter('error')

            # Make sure that we get a pending deprecation warning
            self.assertRaises(PendingDeprecationWarning, sys.evalfr, 1.)
示例#27
0
 def testMinreal2(self):
     """This one gave a problem, due to poly([]) giving simply 1 
     instead of numpy.array([1])"""
     s = TransferFunction([1, 0], [1])
     G = 6205 / (s * (s**2 + 13 * s + 1281))
     Heq = G.feedback(1)
     H1 = 1 / (s + 5)
     H2a = Heq / H1
     H2b = H2a.minreal()
     hr = 6205 / (s**2 + 8 * s + 1241)
     np.testing.assert_array_almost_equal(H2b.num[0][0], hr.num[0][0])
     np.testing.assert_array_almost_equal(H2b.den[0][0], hr.den[0][0])
示例#28
0
def test_to_pandas():
    # Create a SISO frequency response
    h1 = TransferFunction([1], [1, 2, 2])
    omega = np.logspace(-1, 2, 10)
    resp = FRD(h1, omega)

    # Convert to pandas
    df = resp.to_pandas()

    # Check to make sure the data make senses
    np.testing.assert_equal(df['omega'], resp.omega)
    np.testing.assert_equal(df['H_{y[0], u[0]}'], resp.fresp[0, 0])
示例#29
0
    def testSISOtf(self):
        # get a SISO transfer function
        h = TransferFunction([1], [1, 2, 2])
        omega = np.logspace(-1, 2, 10)
        frd = FRD(h, omega)
        assert isinstance(frd, FRD)

        mag1, phase1, omega1 = frd.frequency_response([1.0])
        mag2, phase2, omega2 = h.frequency_response([1.0])
        np.testing.assert_array_almost_equal(mag1, mag2)
        np.testing.assert_array_almost_equal(phase1, phase2)
        np.testing.assert_array_almost_equal(omega1, omega2)
示例#30
0
    def testFeedback(self):
        h1 = TransferFunction([1], [1, 2, 2])
        omega = np.logspace(-1, 2, 10)
        f1 = FRD(h1, omega)
        np.testing.assert_array_almost_equal(
            f1.feedback(1).frequency_response([0.1, 1.0, 10])[0],
            h1.feedback(1).frequency_response([0.1, 1.0, 10])[0])

        # Make sure default argument also works
        np.testing.assert_array_almost_equal(
            f1.feedback().frequency_response([0.1, 1.0, 10])[0],
            h1.feedback().frequency_response([0.1, 1.0, 10])[0])