def test_dcgain(self):
        """Test function dcgain with different systems"""
        #Test MIMO systems
        A, B, C, D = self.make_MIMO_mats()

        gain1 = dcgain(ss(A, B, C, D))
        gain2 = dcgain(A, B, C, D)
        sys_tf = ss2tf(A, B, C, D)
        gain3 = dcgain(sys_tf)
        gain4 = dcgain(sys_tf.num, sys_tf.den)
        #print("gain1:", gain1)

        assert_array_almost_equal(gain1,
                                  array([[0.0269, 0.    ],
                                         [0.    , 0.0269]]),
                                  decimal=4)
        assert_array_almost_equal(gain1, gain2)
        assert_array_almost_equal(gain3, gain4)
        assert_array_almost_equal(gain1, gain4)

        #Test SISO systems
        A, B, C, D = self.make_SISO_mats()

        gain1 = dcgain(ss(A, B, C, D))
        assert_array_almost_equal(gain1,
                                  array([[0.0269]]),
                                  decimal=4)
예제 #2
0
    def testMinrealBrute(self):
        for n, m, p in permutations(range(1,6), 3):
            s = matlab.rss(n, p, m)
            sr = s.minreal()
            if s.states > sr.states:
                self.nreductions += 1
            else:
                np.testing.assert_array_almost_equal(
                    np.sort(eigvals(s.A)), np.sort(eigvals(sr.A)))
                for i in range(m):
                    for j in range(p):
                        ht1 = matlab.tf(
                            matlab.ss(s.A, s.B[:,i], s.C[j,:], s.D[j,i]))
                        ht2 = matlab.tf(
                            matlab.ss(sr.A, sr.B[:,i], sr.C[j,:], sr.D[j,i]))
                        try:
                            self.assert_numden_almost_equal(
                                ht1.num[0][0], ht2.num[0][0],
                                ht1.den[0][0], ht2.den[0][0])
                        except Exception as e:
                            # for larger systems, the tf minreal's
                            # the original rss, but not the balanced one
                            if n < 6:
                                raise e

        self.assertEqual(self.nreductions, 2)
    def test_impulse(self):
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)

        figure()

        #everything automatically
        t, y = impulse(sys)
        plot(t, y, label='Simple Case')

        #supply time and X0
        T = linspace(0, 2, 100)
        X0 = [0.2, 0.2]
        t, y = impulse(sys, T, X0)
        plot(t, y, label='t=0..2, X0=[0.2, 0.2]')

        #Test system with direct feed-though, the function should print a warning.
        D = [[0.5]]
        sys_ft = ss(A, B, C, D)
        t, y = impulse(sys_ft)
        plot(t, y, label='Direct feedthrough D=[[0.5]]')

        #Test MIMO system
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)
        t, y = impulse(sys)
        plot(t, y, label='MIMO System')

        legend(loc='best')
예제 #4
0
    def testMinrealBrute(self):
        for n, m, p in permutations(range(1, 6), 3):
            s = matlab.rss(n, p, m)
            sr = s.minreal()
            if s.states > sr.states:
                self.nreductions += 1
            else:
                np.testing.assert_array_almost_equal(np.sort(eigvals(s.A)),
                                                     np.sort(eigvals(sr.A)))
                for i in range(m):
                    for j in range(p):
                        ht1 = matlab.tf(
                            matlab.ss(s.A, s.B[:, i], s.C[j, :], s.D[j, i]))
                        ht2 = matlab.tf(
                            matlab.ss(sr.A, sr.B[:, i], sr.C[j, :], sr.D[j,
                                                                         i]))
                        try:
                            self.assert_numden_almost_equal(
                                ht1.num[0][0], ht2.num[0][0], ht1.den[0][0],
                                ht2.den[0][0])
                        except Exception as e:
                            # for larger systems, the tf minreal's
                            # the original rss, but not the balanced one
                            if n < 6:
                                raise e

        self.assertEqual(self.nreductions, 2)
    def test_step(self):
        """Test function ``step``."""
        figure(); plot_shape = (1, 3)

        #Test SISO system
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)
        #print(sys)
        #print("gain:", dcgain(sys))

        subplot2grid(plot_shape, (0, 0))
        t, y = step(sys)
        plot(t, y)

        subplot2grid(plot_shape, (0, 1))
        T = linspace(0, 2, 100)
        X0 = array([1, 1])
        t, y = step(sys, T, X0)
        plot(t, y)

        #Test MIMO system
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)

        subplot2grid(plot_shape, (0, 2))
        t, y = step(sys)
        plot(t, y)
예제 #6
0
 def testConnect2(self):
     """Test append and connect() case 2"""
     sys = append(ss([[-5, -2.25],
                      [4, 0]],
                     [[2],
                      [0]],
                     [[0, 1.125]],
                     [[0]]),
                  ss([[-1.6667, 0],
                      [1, 0]],
                     [[2], [0]],
                     [[0, 3.3333]], [[0]]),
                  1)
     Q = [[1, 3],
          [2, 1],
          [3, -2]]
     sysc = connect(sys, Q, [3], [3, 1, 2])
     np.testing.assert_array_almost_equal(
         sysc.A, np.array([[-5, -2.25, 0, -6.6666],
                           [4, 0, 0, 0],
                           [0, 2.25, -1.6667, 0],
                           [0, 0, 1, 0]]))
     np.testing.assert_array_almost_equal(
         sysc.B, np.array([[2], [0], [0], [0]]))
     np.testing.assert_array_almost_equal(
         sysc.C, np.array([[0, 0, 0, -3.3333],
                           [0, 1.125, 0, 0],
                           [0, 0, 0, 3.3333]]))
     np.testing.assert_array_almost_equal(
         sysc.D, np.array([[1], [0], [0]]))
예제 #7
0
    def testCombi01(self):
        """Test from a "real" case, combines tf, ss, connect and margin.

        This is a type 2 system, with phase starting at -180. The
        margin command should remove the solution for w = nearly zero.
        """
        # Example is a concocted two-body satellite with flexible link
        Jb = 400
        Jp = 1000
        k = 10
        b = 5

        # can now define an "s" variable, to make TF's
        s = tf([1, 0], [1])
        hb1 = 1 / (Jb * s)
        hb2 = 1 / s
        hp1 = 1 / (Jp * s)
        hp2 = 1 / s

        # convert to ss and append
        sat0 = append(ss(hb1), ss(hb2), k, b, ss(hp1), ss(hp2))

        # connection of the elements with connect call
        Q = [
            [1, -3, -4],  # link moment (spring, damper), feedback to body
            [2, 1, 0],  # link integrator to body velocity
            [3, 2, -6],  # spring input, th_b - th_p
            [4, 1, -5],  # damper input
            [5, 3, 4],  # link moment, acting on payload
            [6, 5, 0]
        ]
        inputs = [1]
        outputs = [1, 2, 5, 6]
        sat1 = connect(sat0, Q, inputs, outputs)

        # matched notch filter
        wno = 0.19
        z1 = 0.05
        z2 = 0.7
        Hno = (1 + 2 * z1 / wno * s + s**2 / wno**2) / (1 + 2 * z2 / wno * s +
                                                        s**2 / wno**2)

        # the controller, Kp = 1 for now
        Kp = 1.64
        tau_PD = 50.
        Hc = (1 + tau_PD * s) * Kp

        # start with the basic satellite model sat1, and get the
        # payload attitude response
        Hp = tf(np.array([0, 0, 0, 1]) * sat1)

        # total open loop
        Hol = Hc * Hno * Hp

        gm, pm, wg, wp = margin(Hol)
        # print("%f %f %f %f" % (gm, pm, wg, wp))
        np.testing.assert_allclose(gm, 3.32065569155)
        np.testing.assert_allclose(pm, 46.9740430224)
        np.testing.assert_allclose(wg, 0.176469728448)
        np.testing.assert_allclose(wp, 0.0616288455466)
예제 #8
0
    def test_step(self):
        """Test function ``step``."""
        figure()
        plot_shape = (1, 3)

        #Test SISO system
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)
        #print(sys)
        #print("gain:", dcgain(sys))

        subplot2grid(plot_shape, (0, 0))
        t, y = step(sys)
        plot(t, y)

        subplot2grid(plot_shape, (0, 1))
        T = linspace(0, 2, 100)
        X0 = array([1, 1])
        t, y = step(sys, T, X0)
        plot(t, y)

        #Test MIMO system
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)

        subplot2grid(plot_shape, (0, 2))
        t, y = step(sys)
        plot(t, y)
예제 #9
0
    def test_lsim(self):
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)

        figure()
        plot_shape = (2, 2)

        #Test with arrays
        subplot2grid(plot_shape, (0, 0))
        t = linspace(0, 1, 100)
        u = r_[1:1:50j, 0:0:50j]
        y, _t, _x = lsim(sys, u, t)
        plot(t, y, label='y')
        plot(t, u / 10, label='u/10')
        legend(loc='best')

        #Test with U=None - uses 2nd algorithm which is much faster.
        subplot2grid(plot_shape, (0, 1))
        t = linspace(0, 1, 100)
        x0 = [-1, -1]
        y, _t, _x = lsim(sys, U=None, T=t, X0=x0)
        plot(t, y, label='y')
        legend(loc='best')

        #Test with U=0, X0=0
        #Correct reaction to zero dimensional special values
        subplot2grid(plot_shape, (0, 1))
        t = linspace(0, 1, 100)
        y, _t, _x = lsim(sys, U=0, T=t, X0=0)
        plot(t, y, label='y')
        legend(loc='best')

        #Test with MIMO system
        subplot2grid(plot_shape, (1, 1))
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)
        t = array(linspace(0, 1, 100))
        u = array([r_[1:1:50j, 0:0:50j], r_[0:1:50j, 0:0:50j]])
        x0 = [0, 0, 0, 0]
        y, t_out, _x = lsim(sys, u, t, x0)
        plot(t_out, y[0], label='y[0]')
        plot(t_out, y[1], label='y[1]')
        plot(t_out, u[0] / 10, label='u[0]/10')
        plot(t_out, u[1] / 10, label='u[1]/10')
        legend(loc='best')

        #Test with wrong values for t
        #T is None; - special handling: Value error
        self.assertRaises(ValueError, lsim(sys, U=0, T=None, x0=0))
        #T="hello" : Wrong type
        #TODO: better wording of error messages of ``lsim`` and
        #      ``_check_convert_array``, when wrong type is given.
        #      Current error message is too cryptic.
        self.assertRaises(TypeError, lsim(sys, U=0, T="hello", x0=0))
        #T=0; - T can not be zero dimensional, it determines the size of the
        #       input vector ``U``
        self.assertRaises(ValueError, lsim(sys, U=0, T=0, x0=0))
        #T is not monotonically increasing
        self.assertRaises(ValueError,
                          lsim(sys, U=0, T=[0., 1., 2., 2., 3.], x0=0))
예제 #10
0
    def test_impulse(self):
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)

        figure()

        #everything automatically
        t, y = impulse(sys)
        plot(t, y, label='Simple Case')

        #supply time and X0
        T = linspace(0, 2, 100)
        X0 = [0.2, 0.2]
        t, y = impulse(sys, T, X0)
        plot(t, y, label='t=0..2, X0=[0.2, 0.2]')

        #Test system with direct feed-though, the function should print a warning.
        D = [[0.5]]
        sys_ft = ss(A, B, C, D)
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            t, y = impulse(sys_ft)
            plot(t, y, label='Direct feedthrough D=[[0.5]]')

        #Test MIMO system
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)
        t, y = impulse(sys)
        plot(t, y, label='MIMO System')

        legend(loc='best')
예제 #11
0
    def test_dcgain(self):
        """Test function dcgain with different systems"""
        if slycot_check():
            #Test MIMO systems
            A, B, C, D = self.make_MIMO_mats()

            gain1 = dcgain(ss(A, B, C, D))
            gain2 = dcgain(A, B, C, D)
            sys_tf = ss2tf(A, B, C, D)
            gain3 = dcgain(sys_tf)
            gain4 = dcgain(sys_tf.num, sys_tf.den)
            #print("gain1:", gain1)

            assert_array_almost_equal(gain1,
                                      array([[0.0269, 0.], [0., 0.0269]]),
                                      decimal=4)
            assert_array_almost_equal(gain1, gain2)
            assert_array_almost_equal(gain3, gain4)
            assert_array_almost_equal(gain1, gain4)

        #Test SISO systems
        A, B, C, D = self.make_SISO_mats()

        gain1 = dcgain(ss(A, B, C, D))
        assert_array_almost_equal(gain1, array([[0.0269]]), decimal=4)
예제 #12
0
    def test_step(self, SISO_mats, MIMO_mats, mplcleanup):
        """Test function ``step``."""
        figure()
        plot_shape = (1, 3)

        #Test SISO system
        A, B, C, D = SISO_mats
        sys = ss(A, B, C, D)
        #print(sys)
        #print("gain:", dcgain(sys))

        subplot2grid(plot_shape, (0, 0))
        y, t = step(sys)
        plot(t, y)

        subplot2grid(plot_shape, (0, 1))
        T = linspace(0, 2, 100)
        X0 = array([1, 1])
        y, t = step(sys, T, X0)
        plot(t, y)

        # Test output of state vector
        y, t, x = step(sys, return_x=True)

        #Test MIMO system
        A, B, C, D = MIMO_mats
        sys = ss(A, B, C, D)

        subplot2grid(plot_shape, (0, 2))
        y, t = step(sys)
        plot(t, y[:, 0, 0])
예제 #13
0
    def __init__(self, Ts):
        # steady state wind defined in the inertial frame
        self._steady_state = np.array([[0., 0., 0.]]).T
        # self.steady_state = np.array([[3., 1., 0.]]).T

        #   Dryden gust model parameters (pg 56 UAV book)

        # HACK:  Setting Va to a constant value is a hack.  We set a nominal airspeed for the gust model.
        # Could pass current Va into the gust function and recalculate A and B matrices.
        Va = 17

        # self._A = np.array([[1-Ts*c, -Ts*d],[Ts, 1]])
        # self._B = np.array([[Ts],[0]])
        # self._C = np.array([[a, b]])

        suv = 1.06
        sw = 0.7
        luv = 200
        lw = 50

        hu_n = np.array([suv * np.sqrt(2 * Va / luv)])
        hu_d = np.array([1, Va / luv])

        hv_n = suv * np.sqrt(3 * Va / luv) * np.array(
            [1, Va / (np.sqrt(3) * luv)])
        hv_d = np.array([1, 2 * Va / luv, (Va / luv)**2])

        hw_n = sw * np.sqrt(3 * Va / lw) * np.array(
            [1, Va / (np.sqrt(3) * lw)])
        hw_d = np.array([1, 2 * Va / lw, (Va / lw)**2])

        self.hu = ctl.ss(ctl.tf(hu_n, hu_d, Ts))
        self.hv = ctl.ss(ctl.tf(hv_n, hv_d, Ts))
        self.hw = ctl.ss(ctl.tf(hw_n, hw_d, Ts))
        self.huA = np.asarray(self.hu.A)
        self.huB = np.asarray(self.hu.B)
        self.huC = np.asarray(self.hu.C)

        self.hvA = np.asarray(self.hv.A)
        self.hvB = np.asarray(self.hv.B)
        self.hvC = np.asarray(self.hv.C)

        self.hwA = np.asarray(self.hw.A)
        self.hwB = np.asarray(self.hw.B)
        self.hwC = np.asarray(self.hw.C)

        self._gust_state_u = np.array([0.])
        self._gust_state_v = np.array([[0.], [0.]])
        self._gust_state_w = np.array([[0.], [0.]])
        self._Ts = Ts
def test_dcgain_2():
    """Test function dcgain with different systems"""
    #Create different forms of a SISO system
    A, B, C, D = make_SISO_mats()
    Z, P, k = scipy.signal.ss2zpk(A, B, C, D)
    num, den = scipy.signal.ss2tf(A, B, C, D)
    sys_ss = ss(A, B, C, D)

    #Compute the gain with ``dcgain``
    gain_abcd = dcgain(A, B, C, D)
    gain_zpk = dcgain(Z, P, k)
    gain_numden = dcgain(np.squeeze(num), den)
    gain_sys_ss = dcgain(sys_ss)
    print 'gain_abcd:', gain_abcd, 'gain_zpk:', gain_zpk
    print 'gain_numden:', gain_numden, 'gain_sys_ss:', gain_sys_ss

    #Compute the gain with a long simulation
    t = linspace(0, 1000, 1000)
    _t, y = step(sys_ss, t)
    gain_sim = y[-1]
    print 'gain_sim:', gain_sim

    #All gain values must be approximately equal to the known gain
    assert_array_almost_equal([
        gain_abcd[0, 0], gain_zpk[0, 0], gain_numden[0, 0], gain_sys_ss[0, 0],
        gain_sim
    ], [0.026948, 0.026948, 0.026948, 0.026948, 0.026948],
                              decimal=6)

    #Test with MIMO system
    A, B, C, D = make_MIMO_mats()
    gain_mimo = dcgain(A, B, C, D)
    print 'gain_mimo: \n', gain_mimo
    assert_array_almost_equal(gain_mimo, [[0.026948, 0], [0, 0.026948]],
                              decimal=6)
예제 #15
0
class dc:
    __slots__ = [
        'name', 'sysc', 'Ts', 'sysd', 'x_0', 'y_0', 'p', 'i', 'd', 'ref',
        'est', 'slot', 't_arr', 't_attack', 't_detect', 'attacks', 'y_index',
        'safeset', 'target_set', 'control_limit', 'max_k',
        'worst_case_control', 'k', 'epsilon', 'sep_graph', 'y_label', 'x_left',
        'y_up', 'y_lo', 'total', 'thres', 'drift', 'y_real_arr', 's', 'score',
        'ymeasure', 'yreal', 'att', 'cin', 'place', 'maxc', 'xreal', 'xmeasure'
    ]
    count = 0
    J = 0.01
    b = 0.1
    K = 0.01
    R = 1
    L = 0.5

    A = [[0, 1, 0], [0, -b / J, K / J], [0, -K / L, -R / L]]
    B = [[0], [0], [1 / L]]
    C = [[1, 0, 0]]
    D = [[0]]
    sysc_default = ss(A, B, C, D)
    dt_default = 0.2

    def __init__(self, sysc=sysc_default, Ts=dt_default, epsilon=1e-7):
        self.sysd = c2d(sysc, Ts)
        self.Ts = Ts
        self.sysc = sysc
        self.epsilon = epsilon
        self.est = Estimator(self.sysd, 500, self.epsilon)
        self.y_index = None
        self.worst_case_control = 'current'
        self.k = None
        self.y_up = None
        self.y_lo = None
        # diy
        self.p = 11
        self.i = 0
        self.d = 5
        self.total = 24
        self.slot = int(self.total / Ts)
        self.t_arr = linspace(0, self.total, self.slot + 1)
        self.ref = [math.pi / 2] * 71 + [math.pi / 2] * 50
        self.thres = 0.2
        self.drift = 0.01
        self.x_0 = [0]
        self.y_real_arr = []
        self.s = 0
        self.att = 0
        self.cin = 0
        self.ymeasure = 0
        self.yreal = 0
        self.score = []
        self.place = 20
        self.maxc = 20
        self.xmeasure = [[0], [0], [0]]
        self.xreal = [[0], [0], [0]]
        self.safeset = {
            'lo': [-4, -1000000000, -100000000],
            'up': [4, 1000000000, 100000000]
        }
예제 #16
0
def asym_flight(ac: FlightParams):
    # Construct the asymmetric flight state-space system for an aircraft
    C1a =np.matrix([[(ac.CYbdot-2*ac.mub)*ac.b/ac.V, 0 , 0 , 0],
                   [0 , -0.5*ac.b/ac.V, 0 , 0],
                   [0 , 0 , -4*ac.mub*ac.KX2*ac.b/ac.V , 4*ac.mub*ac.KXZ*ac.b/ac.V],
                   [ac.Cnbdot*ac.b/ac.V, 0 , 4*ac.mub*ac.KXZ*ac.b/ac.V , -4*ac.mub*ac.KZ2*ac.b/ac.V]])

    C2a =np.matrix([[-ac.CYb, -ac.CL , -ac.CYp , -ac.CYr+4*ac.mub],
                   [0 , 0, -1 , 0],
                   [-ac.Clb , 0 , -ac.Clp , -ac.Clr],
                   [-ac.Cnb, 0 , -ac.Cnp , -ac.Cnr]])

    C3a = np.matrix([[-ac.CYda, -ac.CYdr],
                    [0 , 0],
                    [-ac.Clda, -ac.Cldr],
                    [-ac.Cnda, -ac.Cndr]])

    C1ainv = np.linalg.inv(C1a)

    Aa = C1ainv*C2a
    Ba = C1ainv*C3a
    Ca = np.identity(4)
    Ca[1,:] = Aa[1,:]
    Da = np.zeros([4 , 2])
    Da[1,:] = Ba[1,:]
    return ml.ss(Aa , Ba , Ca , Da)
예제 #17
0
def sym_flight(ac: FlightParams):
    # Construct the symmetric flight state-space system for an aircraft
    C1s = np.matrix([[-2*ac.muc*ac.c/ac.Vtas, 0 , 0 , 0],
                     [0 , (ac.CZadot -2*ac.muc)*ac.c/ac.Vtas, 0 , 0],
                     [0 , 0 , -ac.c/ac.Vtas , 0],
                     [0, ac.Cmadot*ac.c/ac.Vtas , 0 , -2*ac.muc*ac.KY2*ac.c/ac.Vtas]])

    C2s = np.matrix([[-ac.CXu, -ac.CXa , -ac.CZ0 , -ac.CXq],
                     [-ac.CZu , -ac.CZa, ac.CX0 , -ac.CZq - 2*ac.muc],
                     [0 , 0 , 0 , -1],
                     [-ac.Cmu, -ac.Cma , 0 , -ac.Cmq]])

    C3s = np.matrix([[-ac.CXde],
                     [-ac.CZde],
                     [0],
                     [-ac.Cmde]])

    C1sinv = np.linalg.inv(C1s)

    As = C1sinv*C2s
    Bs = C1sinv*C3s
    Cs = np.identity(4)
    Ds =np.zeros([4,1])

    return ml.ss(As, Bs, Cs, Ds)
예제 #18
0
def asym_flight(ac: FlightParams):
    # Construct the asymmetric flight state-space system for an aircraft
    C1a = np.matrix([[(ac.CYbdot - 2 * ac.mub), 0, 0, 0],
                     [0, -1 / 2 * ac.b / ac.V0, 0, 0],
                     [
                         0, 0, -4 * ac.mub * ac.KX2 * ac.b / ac.V0,
                         4 * ac.mub * ac.KXZ * ac.b / ac.V0
                     ],
                     [
                         ac.Cnbdot * ac.b / ac.V0, 0,
                         4 * ac.mub * ac.KXZ * ac.b / ac.V0,
                         -4 * ac.mub * ac.KX2 * ac.b / ac.V0
                     ]])

    C2a = np.matrix([[ac.CYb, ac.CL, ac.CYp, ac.CYr - 4 * ac.mub],
                     [0, 0, 1, 0], [ac.Clb, 0, ac.Clp, ac.Clr],
                     [ac.Cnb, 0, ac.Cnp, ac.Cnr]])

    C3a = np.matrix([[ac.CYda, ac.CYdr], [0, 0], [ac.Clda, ac.Cldr],
                     [ac.Cnda, ac.Cndr]])

    C1ainv = np.linalg.inv(C1a)

    Aa = -C1ainv * C2a
    Ba = -C1ainv * C3a
    Ca = np.identity(4)
    Da = np.zeros([4, 2])

    return ml.ss(Aa, Ba, Ca, Da)
    def test_dcgain_2(self):
        """Test function dcgain with different systems"""
        #Create different forms of a SISO system
        A, B, C, D = self.make_SISO_mats()
        Z, P, k = scipy.signal.ss2zpk(A, B, C, D)
        num, den = scipy.signal.ss2tf(A, B, C, D)
        sys_ss = ss(A, B, C, D)

        #Compute the gain with ``dcgain``
        gain_abcd = dcgain(A, B, C, D)
        gain_zpk = dcgain(Z, P, k)
        gain_numden = dcgain(np.squeeze(num), den)
        gain_sys_ss = dcgain(sys_ss)
        print('gain_abcd:', gain_abcd, 'gain_zpk:', gain_zpk)
        print('gain_numden:', gain_numden, 'gain_sys_ss:', gain_sys_ss)

        #Compute the gain with a long simulation
        t = linspace(0, 1000, 1000)
        y, _t = step(sys_ss, t)
        gain_sim = y[-1]
        print('gain_sim:', gain_sim)

        #All gain values must be approximately equal to the known gain
        assert_array_almost_equal([gain_abcd[0,0],   gain_zpk[0,0],
                                   gain_numden[0,0], gain_sys_ss[0,0], gain_sim],
                                  [0.026948, 0.026948, 0.026948, 0.026948,
                                   0.026948],
                                  decimal=6)

        #Test with MIMO system
        A, B, C, D = self.make_MIMO_mats()
        gain_mimo = dcgain(A, B, C, D)
        print('gain_mimo: \n', gain_mimo)
        assert_array_almost_equal(gain_mimo, [[0.026948, 0       ],
                                              [0,        0.026948]], decimal=6)
예제 #20
0
    def to_siso(self, iu, iy):
        """Return a SISO system given input and output indices.

        **Parameters:**

        - *iu*: Index or name of the input

             This must be specified unless the system has only one input.

        - *iy*: Index or name of the output

             This must be specified unless the system has only one output.

        **Example:**

        >>> lin = LinRes('examples/PID.mat')
        >>> lin.to_siso()
        A = [[   0.    0.]
         [   0. -100.]]
        <BLANKLINE>
        B = [[   2.]
         [ 100.]]
        <BLANKLINE>
        C = [[  1. -10.]]
        <BLANKLINE>
        D = [[ 11.]]
        <BLANKLINE>
        """
        return ss(self.sys.A, self.sys.B[:, iu],
                  self.sys.C[iy, :], self.sys.D[iy, iu])
예제 #21
0
    def test_dcgain_2(self):
        """Test function dcgain with different systems"""
        #Create different forms of a SISO system
        A, B, C, D = self.make_SISO_mats()
        num, den = scipy.signal.ss2tf(A, B, C, D)
        # numerator is only a constant here; pick it out to avoid numpy warning
        Z, P, k = scipy.signal.tf2zpk(num[0][-1], den)
        sys_ss = ss(A, B, C, D)

        #Compute the gain with ``dcgain``
        gain_abcd = dcgain(A, B, C, D)
        gain_zpk = dcgain(Z, P, k)
        gain_numden = dcgain(np.squeeze(num), den)
        gain_sys_ss = dcgain(sys_ss)
        # print('gain_abcd:', gain_abcd, 'gain_zpk:', gain_zpk)
        # print('gain_numden:', gain_numden, 'gain_sys_ss:', gain_sys_ss)

        #Compute the gain with a long simulation
        t = linspace(0, 1000, 1000)
        y, _t = step(sys_ss, t)
        gain_sim = y[-1]
        # print('gain_sim:', gain_sim)

        #All gain values must be approximately equal to the known gain
        assert_array_almost_equal([gain_abcd[0,0],   gain_zpk[0,0],
                                   gain_numden[0,0], gain_sys_ss[0,0], gain_sim],
                                  [0.026948, 0.026948, 0.026948, 0.026948,
                                   0.026948],
                                  decimal=6)
예제 #22
0
    def test_dcgain_2(self):
        """Test function dcgain with different systems"""
        #Create different forms of a SISO system
        A, B, C, D = self.make_SISO_mats()
        num, den = scipy.signal.ss2tf(A, B, C, D)
        # numerator is only a constant here; pick it out to avoid numpy warning
        Z, P, k = scipy.signal.tf2zpk(num[0][-1], den)
        sys_ss = ss(A, B, C, D)

        #Compute the gain with ``dcgain``
        gain_abcd = dcgain(A, B, C, D)
        gain_zpk = dcgain(Z, P, k)
        gain_numden = dcgain(np.squeeze(num), den)
        gain_sys_ss = dcgain(sys_ss)
        # print('gain_abcd:', gain_abcd, 'gain_zpk:', gain_zpk)
        # print('gain_numden:', gain_numden, 'gain_sys_ss:', gain_sys_ss)

        #Compute the gain with a long simulation
        t = linspace(0, 1000, 1000)
        y, _t = step(sys_ss, t)
        gain_sim = y[-1]
        # print('gain_sim:', gain_sim)

        #All gain values must be approximately equal to the known gain
        assert_array_almost_equal(
            [gain_abcd, gain_zpk, gain_numden, gain_sys_ss, gain_sim],
            [0.026948, 0.026948, 0.026948, 0.026948, 0.026948],
            decimal=6)
예제 #23
0
    def testMinreal(self, verbose=False):
        """Test a minreal model reduction"""
        # A = [-2, 0.5, 0; 0.5, -0.3, 0; 0, 0, -0.1]
        A = [[-2, 0.5, 0], [0.5, -0.3, 0], [0, 0, -0.1]]
        # B = [0.3, -1.3; 0.1, 0; 1, 0]
        B = [[0.3, -1.3], [0.1, 0.], [1.0, 0.0]]
        # C = [0, 0.1, 0; -0.3, -0.2, 0]
        C = [[0., 0.1, 0.0], [-0.3, -0.2, 0.0]]
        # D = [0 -0.8; -0.3 0]
        D = [[0., -0.8], [-0.3, 0.]]
        # sys = ss(A, B, C, D)

        sys = ss(A, B, C, D)
        sysr = minreal(sys, verbose=verbose)
        assert sysr.nstates == 2
        assert sysr.ninputs == sys.ninputs
        assert sysr.noutputs == sys.noutputs
        np.testing.assert_array_almost_equal(
            eigvals(sysr.A), [-2.136154, -0.1638459])

        s = tf([1, 0], [1])
        h = (s+1)*(s+2.00000000001)/(s+2)/(s**2+s+1)
        hm = minreal(h, verbose=verbose)
        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])
예제 #24
0
    def system(self):
        """ Organizes the obtained state-space matrices into a state-space object utilizing :class:`ss`

        :return: State-space system utilizing the control library
        :rtype: control.matlab.ss
        """
        return ss(self.a_matrix, self.b_matrix, self.c_matrix, self.d_matrix)
예제 #25
0
    def test_impulse_mimo(self, MIMO_mats, mplcleanup):
        #Test MIMO system
        A, B, C, D = MIMO_mats
        sys = ss(A, B, C, D)
        y, t = impulse(sys)
        plot(t, y[:, :, 0], label='MIMO System')

        legend(loc='best')
예제 #26
0
파일: test_dsf.py 프로젝트: nwoodbury/pydsf
    def test_accept_sys(self):
        """
        Tests if passing a StateSpace as ``sys`` raises no errors.
        """

        [A, B, C, D] = self.__build_standard_abcd()
        sys = ss(A, B, C, D)
        dsf(sys=sys)
예제 #27
0
    def test_dcgain_siso(self, SISO_mats):
        """Test function dcgain with SISO systems"""
        A, B, C, D = SISO_mats

        gain1 = dcgain(ss(A, B, C, D))
        assert_array_almost_equal(gain1,
                                  array([[0.0269]]),
                                  decimal=4)
예제 #28
0
    def test_mimo(self):
        # MIMO
        B = np.matrix('1,0;0,1')
        D = np.matrix('0,0')
        sysMIMO = ss(self.A, B, self.C, D)

        frqMIMO = sysMIMO.freqresp(self.omega)
        tfMIMO = tf(sysMIMO)
예제 #29
0
 def test_doubleint(self):
    # 30 May 2016, RMM: added to replicate typecast bug in freqresp.py
    A = np.matrix('0, 1; 0, 0');
    B = np.matrix('0; 1');
    C = np.matrix('1, 0');
    D = 0;
    sys = ss(A, B, C, D);
    bode(sys);
예제 #30
0
 def test_doubleint(self):
     # 30 May 2016, RMM: added to replicate typecast bug in freqresp.py
     A = np.matrix('0, 1; 0, 0')
     B = np.matrix('0; 1')
     C = np.matrix('1, 0')
     D = 0
     sys = ss(A, B, C, D)
     bode(sys)
예제 #31
0
 def testConnect(self):
     """Test append() and  connect()"""
     sys1 = ss([[1., -2], [3., -4]], [[5.], [7]], [[6, 8]], [[9.]])
     sys2 = ss(-1., 1., 1., 0.)
     sys = append(sys1, sys2)
     Q = np.array([
         [1, 2],  # basically feedback, output 2 in 1
         [2, -1]
     ])
     sysc = connect(sys, Q, [2], [1, 2])
     # print(sysc)
     np.testing.assert_array_almost_equal(
         sysc.A, np.array([[1, -2, 5], [3, -4, 7], [-6, -8, -10]]))
     np.testing.assert_array_almost_equal(sysc.B, np.array([[0], [0], [1]]))
     np.testing.assert_array_almost_equal(sysc.C,
                                          np.array([[6, 8, 9], [0, 0, 1]]))
     np.testing.assert_array_almost_equal(sysc.D, np.array([[0], [0]]))
예제 #32
0
   def test_mimo(self):
      # MIMO
      B = np.matrix('1,0;0,1')
      D = np.matrix('0,0')
      sysMIMO = ss(self.A,B,self.C,D)

      frqMIMO = sysMIMO.freqresp(self.omega)
      tfMIMO = tf(sysMIMO)
예제 #33
0
def ss_siso_ct():
    A = np.diag([-1 / 75.0])
    B = np.array([[1.0]]) / 75.0
    C = np.array([[87.8]])
    D = np.zeros((1, 1))
    T = TSys(ss(A, B, C, D))
    T.omegas = [0.0, np.array([0.0, 0.01])]
    T.sigmas = [np.array([[87.8]]), np.array([[87.8, 70.24]])]
    return T
예제 #34
0
def main():
    # 制御対象を定義(今回はモータを想定)
    J = 0.6  # 慣性
    D = 0.2  # 粘性
    Kt = 0.15  # トルク定数
    P = crl.tf([Kt], [J, D, 0])  # モータ角度の電流制御

    # 参照モデルの定義
    M = crl.tf([50], [1, 50])

    # シミュレーション条件を定義
    Ts = 0.001  # サンプリング時間

    # 制御器構造の定義
    beta = crl.ss("0", "1", "0; 1", "1; 0")  # PI制御器
    print(crl.tf(beta))
    beta = crl.c2d(beta, Ts)

    # 制御対象と参照モデルのゲイン線図
    plt.figure(1)
    crl.bode([P, M])
    plt.legend(["Plant", "Ref. model"])

    # prbsを生成する
    n = 12  # m系列信号の次数
    Tp = 5  # 何周期印加するか?
    Ap = 0.5  # 振幅 [A]
    u0 = 2 * prbs(n)
    u0 = Ap * (u0 - np.average(u0))
    u0 = np.tile(u0, Tp)
    t = np.linspace(0, Ts * u0.shape[0], u0.shape[0])
    plt.figure(2)
    plt.plot(t, u0)
    plt.xlabel("Time [s]")
    plt.ylabel("Current [A]")

    # 実験データの取得
    print("=== Start Experiment ===")
    Pd = crl.c2d(P, Ts, "tustin")  # 双一次変換で離散時間モデルを作成
    t = np.arange(start=0, stop=Tp * Ts * (2**n - 1), step=Ts)
    (y0, t0, xout) = crl.lsim(Pd, u0[:], t[:])  # 応答を取得
    plt.figure(3)
    plt.plot(y0)

    # VRFTを実行する
    print("=== Start VRFT ===")
    W = crl.tf([50], [1, 50])  # 周波数重み
    L = crl.minreal((1 - M) * M * W)  # プレフィルタ
    Ld = crl.c2d(L, Ts, "tustin")
    (ul, tl, xlout) = crl.lsim(Ld, u0, t)
    (phi_l, tl, xlout) = crl.lsim(beta, y0[:])
    print(phi_l)
    rho = np.linalg.solve(phi_l, ul)
    print(rho)

    plt.show()
예제 #35
0
 def mimo(self):
     """Create MIMO system, contains ``siso_ss1`` twice"""
     m = tsystems()
     A = np.array([[1., -2., 0., 0.], [3., -4., 0., 0.], [0., 0., 1., -2.],
                   [0., 0., 3., -4.]])
     B = np.array([[5., 0.], [7., 0.], [0., 5.], [0., 7.]])
     C = np.array([[6., 8., 0., 0.], [0., 0., 6., 8.]])
     D = np.array([[9., 0.], [0., 9.]])
     m.ss1 = ss(A, B, C, D)
     return m
예제 #36
0
    def testMinrealBrute(self):
        for n, m, p in permutations(range(1, 6), 3):
            s = matlab.rss(n, p, m)
            sr = s.minreal()
            if s.states > sr.states:
                self.nreductions += 1
            else:
                # Check to make sure that poles and zeros match

                # For poles, just look at eigenvalues of A
                np.testing.assert_array_almost_equal(np.sort(eigvals(s.A)),
                                                     np.sort(eigvals(sr.A)))

                # For zeros, need to extract SISO systems
                for i in range(m):
                    for j in range(p):
                        # Extract SISO dynamixs from input i to output j
                        s1 = matlab.ss(s.A, s.B[:, i], s.C[j, :], s.D[j, i])
                        s2 = matlab.ss(sr.A, sr.B[:, i], sr.C[j, :], sr.D[j,
                                                                          i])

                        # Check that the zeros match
                        # Note: sorting doesn't work => have to do the hard way
                        z1 = matlab.zero(s1)
                        z2 = matlab.zero(s2)

                        # Start by making sure we have the same # of zeros
                        self.assertEqual(len(z1), len(z2))

                        # Make sure all zeros in s1 are in s2
                        for zero in z1:
                            # Find the closest zero
                            self.assertAlmostEqual(min(abs(z2 - zero)), 0.)

                        # Make sure all zeros in s2 are in s1
                        for zero in z2:
                            # Find the closest zero
                            self.assertAlmostEqual(min(abs(z1 - zero)), 0.)

        # Make sure that the number of systems reduced is as expected
        # (Need to update this number if you change the seed at top of file)
        self.assertEqual(self.nreductions, 2)
예제 #37
0
    def siso(self):
        """Set up some systems for testing out MATLAB functions"""
        s = tsystems()

        A = np.array([[1., -2.], [3., -4.]])
        B = np.array([[5.], [7.]])
        C = np.array([[6., 8.]])
        D = np.array([[9.]])
        s.ss1 = ss(A, B, C, D)

        # Create some transfer functions
        s.tf1 = tf([1], [1, 2, 1])
        s.tf2 = tf([1, 1], [1, 2, 3, 1])

        # Conversions
        s.tf3 = tf(s.ss1)
        s.ss2 = ss(s.tf2)
        s.ss3 = tf2ss(s.tf3)
        s.tf4 = ss2tf(s.ss2)
        return s
예제 #38
0
def test_doubleint():
    """Test typcast bug with double int

    30 May 2016, RMM: added to replicate typecast bug in frequency_response.py
    """
    A = np.array([[0, 1], [0, 0]])
    B = np.array([[0], [1]])
    C = np.array([[1, 0]])
    D = 0
    sys = ss(A, B, C, D)
    bode(sys)
예제 #39
0
def test_mimo():
    """Test MIMO frequency response calls"""
    A = np.array([[1, 1], [0, 1]])
    B = np.array([[1, 0], [0, 1]])
    C = np.array([[1, 0]])
    D = np.array([[0, 0]])
    omega = np.linspace(10e-2, 10e2, 1000)
    sysMIMO = ss(A, B, C, D)

    sysMIMO.freqresp(omega)
    tf(sysMIMO)
예제 #40
0
    def testMinrealBrute(self):
        for n, m, p in permutations(range(1,6), 3):
            s = matlab.rss(n, p, m)
            sr = s.minreal()
            if s.states > sr.states:
                self.nreductions += 1
            else:
                # Check to make sure that poles and zeros match

                # For poles, just look at eigenvalues of A
                np.testing.assert_array_almost_equal(
                    np.sort(eigvals(s.A)), np.sort(eigvals(sr.A)))

                # For zeros, need to extract SISO systems
                for i in range(m):
                    for j in range(p):
                        # Extract SISO dynamixs from input i to output j
                        s1 = matlab.ss(s.A, s.B[:,i], s.C[j,:], s.D[j,i])
                        s2 = matlab.ss(sr.A, sr.B[:,i], sr.C[j,:], sr.D[j,i])

                        # Check that the zeros match
                        # Note: sorting doesn't work => have to do the hard way
                        z1 = matlab.zero(s1)
                        z2 = matlab.zero(s2)

                        # Start by making sure we have the same # of zeros
                        self.assertEqual(len(z1), len(z2))

                        # Make sure all zeros in s1 are in s2
                        for zero in z1:
                            # Find the closest zero
                            self.assertAlmostEqual(min(abs(z2 - zero)), 0.)

                        # Make sure all zeros in s2 are in s1
                        for zero in z2:
                            # Find the closest zero
                            self.assertAlmostEqual(min(abs(z1 - zero)), 0.)

        # Make sure that the number of systems reduced is as expected
        # (Need to update this number if you change the seed at top of file)
        self.assertEqual(self.nreductions, 2)
    def test_initial(self):
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)

        figure(); plot_shape = (1, 3)

        #X0=0 : must produce line at 0
        subplot2grid(plot_shape, (0, 0))
        t, y = initial(sys)
        plot(t, y)

        #X0=[1,1] : produces a spike
        subplot2grid(plot_shape, (0, 1))
        t, y = initial(sys, X0=matrix("1; 1"))
        plot(t, y)

        #Test MIMO system
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)
        #X0=[1,1] : produces same spike as above spike
        subplot2grid(plot_shape, (0, 2))
        t, y = initial(sys, X0=[1, 1, 0, 0])
        plot(t, y)
예제 #42
0
    def testFreqResp(self):
        """Compare the bode reponses of the SS systems and TF systems to the original SS
           They generally are different realizations but have same freq resp. 
           Currently this test may only be applied to SISO systems.
        """              
        for states in range(1,self.maxStates):
            for testNum in range(self.numTests):                       
                for inputs in range(1,1):
                    for outputs in range(1,1):       
                        ssOriginal = matlab.rss(states, inputs, outputs)
                        
                        tfOriginal_Actrb, tfOriginal_Bctrb, tfOriginal_Cctrb, tfOrigingal_nctrb, tfOriginal_index,\
                            tfOriginal_dcoeff, tfOriginal_ucoeff = tb04ad(states,inputs,outputs,\
                            ssOriginal.A,ssOriginal.B,ssOriginal.C,ssOriginal.D,tol1=0.0)
                        
                        ssTransformed_nr, ssTransformed_A, ssTransformed_B, ssTransformed_C, ssTransformed_D\
                            = td04ad('R',inputs,outputs,tfOriginal_index,tfOriginal_dcoeff,tfOriginal_ucoeff,tol=0.0)
                        
                        tfTransformed_Actrb, tfTransformed_Bctrb, tfTransformed_Cctrb, tfTransformed_nctrb,\
                            tfTransformed_index, tfTransformed_dcoeff, tfTransformed_ucoeff = tb04ad(\
                            ssTransformed_nr,inputs,outputs,ssTransformed_A, ssTransformed_B, ssTransformed_C,\
                            ssTransformed_D,tol1=0.0)

                        numTransformed = np.array(tfTransformed_ucoeff)
                        denTransformed = np.array(tfTransformed_dcoeff)
                        numOriginal = np.array(tfOriginal_ucoeff)
                        denOriginal = np.array(tfOriginal_dcoeff)
                                              
                        ssTransformed = matlab.ss(ssTransformed_A,ssTransformed_B,ssTransformed_C,ssTransformed_D)
                        for inputNum in range(inputs):
                            for outputNum in range(outputs):
                                [ssOriginalMag,ssOriginalPhase,freq] = matlab.bode(ssOriginal,Plot=False) 
                                [tfOriginalMag,tfOriginalPhase,freq] = matlab.bode(matlab.tf(numOriginal[outputNum][inputNum],denOriginal[outputNum]),Plot=False)
                                [ssTransformedMag,ssTransformedPhase,freq] = matlab.bode(ssTransformed,freq,Plot=False)
                                [tfTransformedMag,tfTransformedPhase,freq] = matlab.bode(matlab.tf(numTransformed[outputNum][inputNum],denTransformed[outputNum]),freq,Plot=False)
                                #print 'numOrig=',numOriginal[outputNum][inputNum]
                                #print 'denOrig=',denOriginal[outputNum]
                                #print 'numTrans=',numTransformed[outputNum][inputNum]
                                #print 'denTrans=',denTransformed[outputNum]
                                np.testing.assert_array_almost_equal(ssOriginalMag,tfOriginalMag,decimal=3)
                                np.testing.assert_array_almost_equal(ssOriginalPhase,tfOriginalPhase,decimal=3)       
                                np.testing.assert_array_almost_equal(ssOriginalMag,ssTransformedMag,decimal=3)
                                np.testing.assert_array_almost_equal(ssOriginalPhase,ssTransformedPhase,decimal=3)
                                np.testing.assert_array_almost_equal(tfOriginalMag,tfTransformedMag,decimal=3)
                                np.testing.assert_array_almost_equal(tfOriginalPhase,tfTransformedPhase,decimal=2)
예제 #43
0
 def testTF(self, verbose=False):
     """ Directly tests the functions tb04ad and td04ad through direct comparison of transfer function coefficients.
         Similar to convert_test, but tests at a lower level.
     """
     from slycot import tb04ad, td04ad
     for states in range(1, self.maxStates):
         for inputs in range(1, self.maxI+1):
             for outputs in range(1, self.maxO+1):
                 for testNum in range(self.numTests):
                     ssOriginal = matlab.rss(states, inputs, outputs)
                     if (verbose):
                         print('====== Original SS ==========')
                         print(ssOriginal)
                         print('states=', states)
                         print('inputs=', inputs)
                         print('outputs=', outputs)
                     
                     
                     tfOriginal_Actrb, tfOriginal_Bctrb, tfOriginal_Cctrb, tfOrigingal_nctrb, tfOriginal_index,\
                         tfOriginal_dcoeff, tfOriginal_ucoeff = tb04ad(states,inputs,outputs,\
                         ssOriginal.A,ssOriginal.B,ssOriginal.C,ssOriginal.D,tol1=0.0)
                     
                     ssTransformed_nr, ssTransformed_A, ssTransformed_B, ssTransformed_C, ssTransformed_D\
                         = td04ad('R',inputs,outputs,tfOriginal_index,tfOriginal_dcoeff,tfOriginal_ucoeff,tol=0.0)
                     
                     tfTransformed_Actrb, tfTransformed_Bctrb, tfTransformed_Cctrb, tfTransformed_nctrb,\
                         tfTransformed_index, tfTransformed_dcoeff, tfTransformed_ucoeff = tb04ad(ssTransformed_nr,\
                         inputs,outputs,ssTransformed_A, ssTransformed_B, ssTransformed_C,ssTransformed_D,tol1=0.0)
                     #print 'size(Trans_A)=',ssTransformed_A.shape
                     if (verbose):
                         print('===== Transformed SS ==========')
                         print(matlab.ss(ssTransformed_A, ssTransformed_B, ssTransformed_C, ssTransformed_D))
                         # print 'Trans_nr=',ssTransformed_nr                      
                         # print 'tfOrig_index=',tfOriginal_index
                         # print 'tfOrig_ucoeff=',tfOriginal_ucoeff
                         # print 'tfOrig_dcoeff=',tfOriginal_dcoeff
                         # print 'tfTrans_index=',tfTransformed_index
                         # print 'tfTrans_ucoeff=',tfTransformed_ucoeff
                         # print 'tfTrans_dcoeff=',tfTransformed_dcoeff
                    #Compare the TF directly, must match
                     #numerators
                     np.testing.assert_array_almost_equal(tfOriginal_ucoeff,tfTransformed_ucoeff,decimal=3)
                     #denominators
                     np.testing.assert_array_almost_equal(tfOriginal_dcoeff,tfTransformed_dcoeff,decimal=3)
    def testTF(self, verbose=False):
        """ Directly tests the functions tb04ad and td04ad through direct
            comparison of transfer function coefficients.
            Similar to convert_test, but tests at a lower level.
        """
        from slycot import tb04ad, td04ad
        for states in range(1, self.maxStates):
            for inputs in range(1, self.maxI+1):
                for outputs in range(1, self.maxO+1):
                    for testNum in range(self.numTests):
                        ssOriginal = matlab.rss(states, outputs, inputs)
                        if (verbose):
                            print('====== Original SS ==========')
                            print(ssOriginal)
                            print('states=', states)
                            print('inputs=', inputs)
                            print('outputs=', outputs)

                        tfOriginal_Actrb, tfOriginal_Bctrb, tfOriginal_Cctrb,\
                            tfOrigingal_nctrb, tfOriginal_index,\
                            tfOriginal_dcoeff, tfOriginal_ucoeff =\
                            tb04ad(states, inputs, outputs,
                                   ssOriginal.A, ssOriginal.B,
                                   ssOriginal.C, ssOriginal.D, tol1=0.0)

                        ssTransformed_nr, ssTransformed_A, ssTransformed_B,\
                            ssTransformed_C, ssTransformed_D\
                            = td04ad('R', inputs, outputs, tfOriginal_index,
                                     tfOriginal_dcoeff, tfOriginal_ucoeff,
                                     tol=0.0)

                        tfTransformed_Actrb, tfTransformed_Bctrb,\
                            tfTransformed_Cctrb, tfTransformed_nctrb,\
                            tfTransformed_index, tfTransformed_dcoeff,\
                            tfTransformed_ucoeff = tb04ad(
                                ssTransformed_nr, inputs, outputs,
                                ssTransformed_A, ssTransformed_B,
                                ssTransformed_C, ssTransformed_D, tol1=0.0)
                        # print('size(Trans_A)=',ssTransformed_A.shape)
                        if (verbose):
                            print('===== Transformed SS ==========')
                            print(matlab.ss(ssTransformed_A, ssTransformed_B,
                                            ssTransformed_C, ssTransformed_D))
예제 #45
0
파일: dsf.py 프로젝트: nwoodbury/pydsf
    def __build_sys(self, **kwargs):
        if 'A' not in kwargs:
            raise ValueError('Must pass either a StateSpace instance or A')

        A = np.matrix(kwargs['A'])
        if A.shape[0] != A.shape[1]:
            # TODO Verify that A must be square, or if this can be relaxed
            raise ValueError('A must be square.')
        size = A.shape[0]

        B = np.matrix(kwargs.get('B', np.identity(size)))
        C = np.matrix(kwargs.get('C', np.identity(size)))
        D = np.matrix(kwargs.get('D', np.zeros((size, size))))

        #print 'A = ', A
        #print 'B = ', B
        #print 'C = ', C
        #print 'D = ', D

        return ss(A, B, C, D)
예제 #46
0
파일: dsf.py 프로젝트: nwoodbury/pydsf
def __build_sys(A, B, C, D):
    """
    If a :mod:`control.statesp.StateSpace` instance is not given, in dsf,
    this takes the A, B, and C (required) and D (optional) parameters
    and returns a ``StateSpace`` instance.
    """
    if (A is None) or (B is None) or (C is None):
        raise ValueError('Must either pass a StateSpace instance or (A, B, C)')

    if isinstance(A, list):
        A = np.matrix(A)

    if isinstance(B, list):
        B = np.matrix(B)

    if isinstance(C, list):
        C = np.matrix(C)

    if D is None:
        D = np.zeros_like(B)
    elif isinstance(D, list):
        D = np.matrix(D)

    return ss(A, B, C, D)
예제 #47
0
def readlin(fname):
    r"""Load Dymola\ :sup:`®`-formatted linearization results.

    **Parameters:**

    - *fname*: Name of the results file, including the path and extension

    **Returns:**

    - An instance of :class:`control.StateSpace`, which contains:

         - *A*, *B*, *C*, *D*: Matrices of the linear system

              .. code-block:: modelica

                 der(x) = A*x + B*u;
                      y = C*x + D*u;

         - *state_names*: List of names of the states (*x*)

         - *input_names*: List of names of the inputs (*u*)

         - *output_names*: List of names of the outputs (*y*)

    **Example:**

    >>> sys = readlin('examples/PID.mat')
    >>> sys.state_names
    ['I.y', 'D.x']
    """
    # This does the task of mfiles/traj/tloadlin.m in the Dymola installation.

    # pylint: disable=I0011, W0621

    # Load the file.
    data, Aclass = read(fname)

    # Check the type of results.
    if Aclass[0] == 'Atrajectory':
        raise AssertionError(fname + " is a simulation result.  Use SimRes "
                             "instead.")
    assert Aclass[0] == 'AlinearSystem', (fname + " isn't a simulation or "
                                          "linearization result.")

    # Determine the number of states, inputs, and outputs.
    ABCD = data['ABCD']
    nx = data['nx'][0]
    nu = ABCD.shape[1] - nx
    ny = ABCD.shape[0] - nx

    # Extract the system matrices.
    A = ABCD[:nx, :nx] if nx > 0 else [[]]
    B = ABCD[:nx, nx:] if nx > 0 and nu > 0 else [[]]
    C = ABCD[nx:, :nx] if nx > 0 and ny > 0 else [[]]
    D = ABCD[nx:, nx:] if nu > 0 and ny > 0 else [[]]
    sys = ss(A, B, C, D)

    # Extract the variable names.
    xuyName = data['xuyName']
    sys.state_names = xuyName[:nx]
    sys.input_names = xuyName[nx:nx + nu]
    sys.output_names = xuyName[nx + nu:]

    return sys
예제 #48
0
    def testConvert(self):
        """Test state space to transfer function conversion."""
        verbose = self.debug
        from control.statesp import _mimo2siso
        
        #print __doc__

        # Machine precision for floats.
        eps = np.finfo(float).eps

        for states in range(1, self.maxStates):
            for inputs in range(1, self.maxIO):
                for outputs in range(1, self.maxIO):
                    # start with a random SS system and transform to TF then
                    # back to SS, check that the matrices are the same.
                    ssOriginal = matlab.rss(states, outputs, inputs)
                    if (verbose):
                        self.printSys(ssOriginal, 1)

                    # Make sure the system is not degenerate
                    Cmat = control.ctrb(ssOriginal.A, ssOriginal.B)
                    if (np.linalg.matrix_rank(Cmat) != states):
                        if (verbose):
                            print("  skipping (not reachable)")
                        continue
                    Omat = control.obsv(ssOriginal.A, ssOriginal.C)
                    if (np.linalg.matrix_rank(Omat) != states):
                        if (verbose):
                            print("  skipping (not observable)")
                        continue

                    tfOriginal = matlab.tf(ssOriginal)
                    if (verbose):
                        self.printSys(tfOriginal, 2)
                    
                    ssTransformed = matlab.ss(tfOriginal)
                    if (verbose):
                        self.printSys(ssTransformed, 3)

                    tfTransformed = matlab.tf(ssTransformed)
                    if (verbose):
                        self.printSys(tfTransformed, 4)

                    # Check to see if the state space systems have same dim
                    if (ssOriginal.states != ssTransformed.states):
                        print("WARNING: state space dimension mismatch: " + \
                            "%d versus %d" % \
                            (ssOriginal.states, ssTransformed.states))

                    # Now make sure the frequency responses match
                    # Since bode() only handles SISO, go through each I/O pair
                    # For phase, take sine and cosine to avoid +/- 360 offset
                    for inputNum in range(inputs):
                        for outputNum in range(outputs):
                            if (verbose):
                                print("Checking input %d, output %d" \
                                    % (inputNum, outputNum))
                            ssorig_mag, ssorig_phase, ssorig_omega = \
                                control.bode(_mimo2siso(ssOriginal, \
                                                        inputNum, outputNum), \
                                                 deg=False, Plot=False)
                            ssorig_real = ssorig_mag * np.cos(ssorig_phase)
                            ssorig_imag = ssorig_mag * np.sin(ssorig_phase)

                            #
                            # Make sure TF has same frequency response
                            #
                            num = tfOriginal.num[outputNum][inputNum]
                            den = tfOriginal.den[outputNum][inputNum]
                            tforig = control.tf(num, den)
                                                
                            tforig_mag, tforig_phase, tforig_omega = \
                                control.bode(tforig, ssorig_omega, \
                                                 deg=False, Plot=False)

                            tforig_real = tforig_mag * np.cos(tforig_phase)
                            tforig_imag = tforig_mag * np.sin(tforig_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, tforig_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, tforig_imag)

                            #
                            # Make sure xform'd SS has same frequency response
                            #
                            ssxfrm_mag, ssxfrm_phase, ssxfrm_omega = \
                                control.bode(_mimo2siso(ssTransformed, \
                                                        inputNum, outputNum), \
                                                 ssorig_omega, \
                                                 deg=False, Plot=False)
                            ssxfrm_real = ssxfrm_mag * np.cos(ssxfrm_phase)
                            ssxfrm_imag = ssxfrm_mag * np.sin(ssxfrm_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, ssxfrm_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, ssxfrm_imag)

                            #
                            # Make sure xform'd TF has same frequency response
                            #
                            num = tfTransformed.num[outputNum][inputNum]
                            den = tfTransformed.den[outputNum][inputNum]
                            tfxfrm = control.tf(num, den)
                            tfxfrm_mag, tfxfrm_phase, tfxfrm_omega = \
                                control.bode(tfxfrm, ssorig_omega, \
                                                 deg=False, Plot=False)
                            
                            tfxfrm_real = tfxfrm_mag * np.cos(tfxfrm_phase)
                            tfxfrm_imag = tfxfrm_mag * np.sin(tfxfrm_phase)
                            np.testing.assert_array_almost_equal( \
                                ssorig_real, tfxfrm_real)
                            np.testing.assert_array_almost_equal( \
                                ssorig_imag, tfxfrm_imag)
예제 #49
0
    def _load(self, fname='dslin.mat'):
        """Load a linearized Modelica_ model from *fname*.

        See :meth:`__init__` for details about the file format.

        Returns *None* if the file contains simulation results rather than
        linearization results.  Otherwise, it raises an error.
        """
        # This performs the task of tloadlin.m from Dymola version 7.4:
        #     on Unix/Linux: /opt/dymola/mfiles/traj/tloadlin.m
        #     on Windows: C:\Program Files\Dymola 7.4\Mfiles\traj\tloadlin.m

        # Load the file.
        try:
            dslin = loadmat(fname)
        except IOError:
            print('File "%s" could not be loaded.  Check that it exists.' %
                  fname)
            raise

        # Check if the file contains the correct variable names.
        assert 'Aclass' in dslin, ('There is no linear system in file "%s" '
            '(matrix "Aclass" is missing).' % fname)
        assert 'nx' in dslin, ('There is no linear system in file "%s" '
            '(matrix "nx" is missing).' % fname)
        assert 'xuyName' in dslin, ('There is no linear system in file "%s" '
            '(matrix "xuyName" is missing).' % fname)
        assert 'ABCD' in dslin, ('There is no linear system in file "%s" '
            '(matrix "ABCD" is missing).' % fname)

        # Check if the file has the correct class name.
        if not dslin['Aclass'][0].startswith('AlinearSystem'):
            if dslin['Aclass'][0].startswith('Atrajectory'):
                return None # The file contains simulation results.
            raise AssertionError('File "%s" is not of class AlinearSystem or '
                                 'Atrajectory.' % fname)

        # Extract variables from the dictionary (for convenience).
        ABCD = dslin['ABCD']
        xuyName = dslin['xuyName']

        # Check if the matrices have compatible dimensions.
        n_x = dslin['nx'][0]
        dim1 = ABCD.shape[0]
        dim2 = ABCD.shape[1]
        assert n_x <= dim1 and n_x <= dim2, (
            'nx > number of rows/columns of matrix ABCD in file "%s"' % fname)
        n_u = dim2 - n_x
        n_y = dim1 - n_x
        assert n_x > 0 and n_y > 0, ("As of version 0.4b, the control module "
            "cannot accept systems with empty matrixes.")

        # Extract the matrices.
        if n_x > 0:
            A = ABCD[:n_x, :n_x]
            if n_u > 0:
                B = ABCD[:n_x, n_x:]
            else:
                B = []
            if n_y > 0:
                C = ABCD[n_x:, :n_x]
            else:
                C = []
        else:
            A = []
            B = []
            C = []
        if n_u > 0 and n_y > 0:
            D = ABCD[n_x:, n_x:]
        else:
            D = []
        self.sys = ss(A, B, C, D)

        # Extract the names.
        if n_x > 0: # States
            self.sys.stateName = [name.rstrip() for name in xuyName[:n_x]]
        else:
            self.sys.stateName = []
        if n_u > 0: # Inputs
            self.sys.inputName = [name.rstrip() for name in xuyName[n_x:
                                                                    n_x+n_u]]
        else:
            self.sys.inputName = []
        if n_y > 0: # Outputs
            self.sys.outputName = [name.rstrip() for name in xuyName[n_x+n_u:]]
        else:
            self.sys.outputName = []
예제 #50
0
    def bode(self, axes=None, pairs=None, label='bode',
             title=None, colors=['b', 'g', 'r', 'c', 'm', 'y', 'k'],
             styles=[(None,None), (3,3), (1,1), (3,2,1,2)], **kwargs):
        """Create a Bode plot of the system's response.

        The Bode plots of a MIMO system are overlayed. This is different than
        MATLAB\ :sup:`®`, which creates an array of subplots.

        **Arguments:**

        - *axes*: Tuple (pair) of axes for the magnitude and phase plots

             If *axes* is not provided, then axes will be created in a new
             figure.

        - *pairs*: List of (input index, output index) tuples of each transfer
          function to be evaluated

             If not provided, all of the transfer functions will be plotted.

        - *label*: Label for the figure (ignored if *axes* is provided)

             This will be used as the base filename if the figure is saved.

        - *title*: Title for the figure

             If *title* is *None* (default), then the title will be "Bode Plot
             of *fbase*", where *fbase* is the base filename of the data.  Use
             '' for no title.

        - *colors*: Color or list of colors that will be used sequentially

             Each may be a character, grayscale, or rgb value.

             .. Seealso:: http://matplotlib.sourceforge.net/api/colors_api.html

        - *styles*: Line/dash style or list of line/dash styles that will be
          used sequentially

             Each style is a string representing a linestyle (e.g., "--") or a
             tuple of on/off lengths representing dashes.  Use "" for no line
             and "-" for a solid line.

             .. Seealso::
                http://matplotlib.sourceforge.net/api/collections_api.html

        - *\*\*kwargs*: Additional arguments for :meth:`control.freqplot.bode`

        **Returns:**

        1. *axes*: Tuple (pair) of axes for the magnitude and phase plots

        **Example:**

        .. code-block:: python

           >>> from modelicares import LinRes, save
           >>> from numpy import pi, logspace

           >>> lin = LinRes('examples/PID.mat')
           >>> lin.bode(label='examples/PID-bode', omega=2*pi*logspace(-2, 3),
           ...          title="Bode Plot of Modelica.Blocks.Continuous.PID") # doctest: +ELLIPSIS
           (<matplotlib.axes._subplots.AxesSubplot object at 0x...>, <matplotlib.axes._subplots.AxesSubplot object at 0x...>)
           >>> save()
           Saved examples/PID-bode.pdf
           Saved examples/PID-bode.png

        .. only:: html

           .. image:: ../examples/PID-bode.png
              :scale: 70 %
              :alt: example for LinRes.bode()

        .. only:: latex

           .. figure:: ../examples/PID-bode.pdf
              :scale: 80 %

              Results of example for :meth:`LinRes.bode`.
        """
        # Create axes if necessary.
        if axes is None or (None, None):
            fig = base.figure(label)
            axes = (fig.add_subplot(211), fig.add_subplot(212))

        # Create a title if necessary.
        if title is None:
            title = r"Bode Plot of %s" % self.fbase

        # Set up the color(s) and line style(s).
        if not iterable(colors):
            # Use the single color for all plots.
            colors = (colors,)
        if not iterable(styles):
            # Use the single line style for all plots.
            styles = [styles]
        elif type(styles[0]) is int:
            # One dashes tuple has been provided; use its value for all plots.
            styles = [styles]
        n_colors = len(colors)
        n_styles = len(styles)

        # If input/output pair(s) aren't specified, generate a list of all
        # pairs.
        if not pairs:
            pairs = [(i_u, i_y) for i_u in range(self.sys.inputs)
                     for i_y in range(self.sys.outputs)]

        # Create the plots.
        for i, (i_u, i_y) in enumerate(pairs):
            # Extract the SISO TF. TODO: Is there a better way to do this?
            sys = ss(self.sys.A, self.sys.B[:, i_u], self.sys.C[i_y, :],
                     self.sys.D[i_y, i_u])
            bode(sys, Hz=True, label=r'$Y_{%i}/U_{%i}$' % (i_y, i_u),
                 color=colors[np.mod(i, n_colors)], axes=axes,
                 style=styles[np.mod(i, n_styles)], **kwargs)
            # Note: controls.freqplot.bode() is currently only implemented for
            # SISO systems.
            # 5/23/11: Since controls.freqplot.bode() already uses subplots for
            # the magnitude and phase plots, it would be difficult to modify
            # the code to put the Bode plots of a MIMO system into an array of
            # subfigures like MATLAB does.

        # Decorate and finish.
        axes[0].set_title(title)
        if len(pairs) > 1:
            axes[0].legend()
            axes[1].legend()
        return axes
예제 #51
0
    def nyquist(self, ax=None, pairs=None, label="nyquist", title=None,
                xlabel="Real Axis", ylabel="Imaginary Axis",
                colors=['b','g','r','c','m','y','k'], **kwargs):
        """Create a Nyquist plot of the system's response.

        The Nyquist plots of a MIMO system are overlayed. This is different
        than MATLAB\ :sup:`®`, which creates an array of subplots.

        **Arguments:**

        - *ax*: Axes onto which the Nyquist diagram should be plotted

             If *ax* is not provided, then axes will be created in a new figure.

        - *pairs*: List of (input index, output index) tuples of each transfer
          function to be evaluated

             If not provided, all of the transfer functions will be plotted.

        - *label*: Label for the figure (ignored if ax is provided)

             This will be used as the base filename if the figure is saved.

        - *title*: Title for the figure

             If *title* is *None* (default), then the title will be "Nyquist
             Plot of *fbase*", where *fbase* is the base filename of the data.
             Use '' for no title.

        - *xlabel*: x-axis label

        - *ylabel*: y-axis label

        - *colors*: Color or list of colors that will be used sequentially

             Each may be a character, grayscale, or rgb value.

             .. Seealso:: http://matplotlib.sourceforge.net/api/colors_api.html

        - *\*\*kwargs*: Additional arguments for
          :meth:`control.freqplot.nyquist`

        **Returns:**

        1. *ax*: Axes of the Nyquist plot

        **Example:**

        .. testsetup::
           >>> from modelicares import closeall
           >>> closeall()

        .. code-block:: python

           >>> from modelicares import LinRes, save
           >>> from numpy import pi, logspace

           >>> lin = LinRes('examples/PID.mat')
           >>> lin.nyquist(label='examples/PID-nyquist',
           ...             omega=2*pi*logspace(0, 3, 61), labelFreq=20,
           ...             title="Nyquist Plot of Modelica.Blocks.Continuous.PID") # doctest: +ELLIPSIS
           <matplotlib.axes._subplots.AxesSubplot object at 0x...>
           >>> save()
           Saved examples/PID-nyquist.pdf
           Saved examples/PID-nyquist.png

        .. only:: html

           .. image:: ../examples/PID-nyquist.png
              :scale: 70 %
              :alt: example for LinRes.nyquist()

        .. only:: latex

           .. figure:: ../examples/PID-nyquist.pdf
              :scale: 70 %

              Results of example for :meth:`LinRes.nyquist`.
        """
        # Create axes if necessary.
        if not ax:
            fig = base.figure(label)
            ax = fig.add_subplot(111, aspect='equal')

        # Create a title if necessary.
        if title is None:
            title = r"Nyquist Plot of %s" % self.fbase

        # Set up the color(s).
        if not iterable(colors):
            # Use the single color for all plots.
            colors = (colors,)
        n_colors = len(colors)

        # If input/output pair(s) aren't specified, generate a list of all
        # pairs.
        if not pairs:
            pairs = [(i_u, i_y) for i_u in range(self.sys.inputs)
                     for i_y in range(self.sys.outputs)]

        # Create the plots.
        for i, (i_u, i_y) in enumerate(pairs):
            # Extract the SISO TF. TODO: Is there a better way to do this?
            sys = ss(self.sys.A, self.sys.B[:, i_u], self.sys.C[i_y, :],
                     self.sys.D[i_y, i_u])
            nyquist(sys, mark=False, label=r'$Y_{%i}/U_{%i}$' % (i_y, i_u),
                    color=colors[np.mod(i, n_colors)], ax=ax, **kwargs)
            # Note: controls.freqplot.nyquist() is currently only implemented
            # for SISO systems.

        # Decorate and finish.
        if len(pairs) > 1:
            ax.legend()
        base.add_hlines(ax, color='k', linestyle='--', linewidth=0.5)
        base.add_vlines(ax, color='k', linestyle='--', linewidth=0.5)
        ax.set_title(title)
        if xlabel: # Without this check, xlabel=None will give a label of "None".
            ax.set_xlabel(xlabel)
        if ylabel: # Same purpose
            ax.set_ylabel(ylabel)
        return ax
    def test_convert_MIMO_to_SISO(self):
        '''Convert mimo to siso systems'''
        #Test with our usual systems --------------------------------------------
        #SISO PT2 system
        As, Bs, Cs, Ds = self.make_SISO_mats()
        sys_siso = ss(As, Bs, Cs, Ds)
        #MIMO system that contains two independent copies of the SISO system above
        Am, Bm, Cm, Dm = self.make_MIMO_mats()
        sys_mimo = ss(Am, Bm, Cm, Dm)
        #    t, y = step(sys_siso)
        #    plot(t, y, label='sys_siso d=0')

        sys_siso_00 = _mimo2siso(sys_mimo, input=0, output=0,
                                         warn_conversion=False)
        sys_siso_11 = _mimo2siso(sys_mimo, input=1, output=1,
                                         warn_conversion=False)
        #print("sys_siso_00 ---------------------------------------------")
        #print(sys_siso_00)
        #print("sys_siso_11 ---------------------------------------------")
        #print(sys_siso_11)

        #gain of converted system and equivalent SISO system must be the same
        self.assert_systems_behave_equal(sys_siso, sys_siso_00)
        self.assert_systems_behave_equal(sys_siso, sys_siso_11)

        #Test with additional systems --------------------------------------------
        #They have crossed inputs and direct feedthrough
        #SISO system
        As = matrix([[-81.82, -45.45],
                     [ 10.,    -1.  ]])
        Bs = matrix([[9.09],
                     [0.  ]])
        Cs = matrix([[0, 0.159]])
        Ds = matrix([[0.02]])
        sys_siso = ss(As, Bs, Cs, Ds)
        #    t, y = step(sys_siso)
        #    plot(t, y, label='sys_siso d=0.02')
        #    legend(loc='best')

        #MIMO system
        #The upper left sub-system uses : input 0, output 1
        #The lower right sub-system uses: input 1, output 0
        Am = array([[-81.82, -45.45,   0,      0   ],
                    [ 10,     -1,      0,      0   ],
                    [  0,      0,    -81.82, -45.45],
                    [  0,      0,     10,     -1,  ]])
        Bm = array([[9.09, 0   ],
                    [0   , 0   ],
                    [0   , 9.09],
                    [0   , 0   ]])
        Cm = array([[0, 0,     0, 0.159],
                    [0, 0.159, 0, 0    ]])
        Dm = matrix([[0,   0.02],
                     [0.02, 0  ]])
        sys_mimo = ss(Am, Bm, Cm, Dm)


        sys_siso_01 = _mimo2siso(sys_mimo, input=0, output=1,
                                         warn_conversion=False)
        sys_siso_10 = _mimo2siso(sys_mimo, input=1, output=0,
                                         warn_conversion=False)
        print("sys_siso_01 ---------------------------------------------")
        print(sys_siso_01)
        print("sys_siso_10 ---------------------------------------------")
        print(sys_siso_10)

        #gain of converted system and equivalent SISO system must be the same
        self.assert_systems_behave_equal(sys_siso, sys_siso_01)
        self.assert_systems_behave_equal(sys_siso, sys_siso_10)
    def test_lsim(self):
        A, B, C, D = self.make_SISO_mats()
        sys = ss(A, B, C, D)

        figure(); plot_shape = (2, 2)

        #Test with arrays
        subplot2grid(plot_shape, (0, 0))
        t = linspace(0, 1, 100)
        u = r_[1:1:50j, 0:0:50j]
        y, _t, _x = lsim(sys, u, t)
        plot(t, y, label='y')
        plot(t, u/10, label='u/10')
        legend(loc='best')

        #Test with U=None - uses 2nd algorithm which is much faster.
        subplot2grid(plot_shape, (0, 1))
        t = linspace(0, 1, 100)
        x0 = [-1, -1]
        y, _t, _x = lsim(sys, U=None, T=t, X0=x0)
        plot(t, y, label='y')
        legend(loc='best')

        #Test with U=0, X0=0
        #Correct reaction to zero dimensional special values
        subplot2grid(plot_shape, (0, 1))
        t = linspace(0, 1, 100)
        y, _t, _x = lsim(sys, U=0, T=t, X0=0)
        plot(t, y, label='y')
        legend(loc='best')

        #Test with matrices
        subplot2grid(plot_shape, (1, 0))
        t = matrix(linspace(0, 1, 100))
        u = matrix(r_[1:1:50j, 0:0:50j])
        x0 = matrix("0.; 0")
        y, t_out, _x = lsim(sys, u, t, x0)
        plot(t_out, y, label='y')
        plot(t_out, asarray(u/10)[0], label='u/10')
        legend(loc='best')

        #Test with MIMO system
        subplot2grid(plot_shape, (1, 1))
        A, B, C, D = self.make_MIMO_mats()
        sys = ss(A, B, C, D)
        t = matrix(linspace(0, 1, 100))
        u = array([r_[1:1:50j, 0:0:50j],
                   r_[0:1:50j, 0:0:50j]])
        x0 = [0, 0, 0, 0]
        y, t_out, _x = lsim(sys, u, t, x0)
        plot(t_out, y[0], label='y[0]')
        plot(t_out, y[1], label='y[1]')
        plot(t_out, u[0]/10, label='u[0]/10')
        plot(t_out, u[1]/10, label='u[1]/10')
        legend(loc='best')


        #Test with wrong values for t
        #T is None; - special handling: Value error
        self.assertRaises(ValueError, lsim(sys, U=0, T=None, x0=0))
        #T="hello" : Wrong type
        #TODO: better wording of error messages of ``lsim`` and
        #      ``_check_convert_array``, when wrong type is given.
        #      Current error message is too cryptic.
        self.assertRaises(TypeError, lsim(sys, U=0, T="hello", x0=0))
        #T=0; - T can not be zero dimensional, it determines the size of the
        #       input vector ``U``
        self.assertRaises(ValueError, lsim(sys, U=0, T=0, x0=0))
        #T is not monotonically increasing
        self.assertRaises(ValueError, lsim(sys, U=0, T=[0., 1., 2., 2., 3.], x0=0))