def test_nyquist_exceptions():
    # MIMO not implemented
    sys = ct.rss(2, 2, 2)
    with pytest.raises(ct.exception.ControlMIMONotImplemented,
                       match="only supports SISO"):
        ct.nyquist_plot(sys)

    # Legacy keywords for arrow size
    sys = ct.rss(2, 1, 1)
    with pytest.warns(FutureWarning, match="use `arrow_size` instead"):
        ct.nyquist_plot(sys, arrow_width=8, arrow_length=6)

    # Unknown arrow keyword
    with pytest.raises(ValueError, match="unsupported arrow location"):
        ct.nyquist_plot(sys, arrows='uniform')

    # Bad value for indent direction
    sys = ct.tf([1], [1, 0, 1])
    with pytest.raises(ValueError, match="unknown value for indent"):
        ct.nyquist_plot(sys, indent_direction='up')

    # Discrete time system sampled above Nyquist frequency
    sys = ct.drss(2, 1, 1)
    sys.dt = 0.01
    with pytest.warns(UserWarning, match="above Nyquist"):
        ct.nyquist_plot(sys, np.logspace(-2, 3))
def test_lqe_discrete():
    """Test overloading of lqe operator for discrete time systems"""
    csys = ct.rss(2, 1, 1)
    dsys = ct.drss(2, 1, 1)
    Q = np.eye(1)
    R = np.eye(1)

    # Calling with a system versus explicit A, B should be the sam
    K_csys, S_csys, E_csys = ct.lqe(csys, Q, R)
    K_expl, S_expl, E_expl = ct.lqe(csys.A, csys.B, csys.C, Q, R)
    np.testing.assert_almost_equal(K_csys, K_expl)
    np.testing.assert_almost_equal(S_csys, S_expl)
    np.testing.assert_almost_equal(E_csys, E_expl)

    # Calling lqe() with a discrete time system should call dlqe()
    K_lqe, S_lqe, E_lqe = ct.lqe(dsys, Q, R)
    K_dlqe, S_dlqe, E_dlqe = ct.dlqe(dsys, Q, R)
    np.testing.assert_almost_equal(K_lqe, K_dlqe)
    np.testing.assert_almost_equal(S_lqe, S_dlqe)
    np.testing.assert_almost_equal(E_lqe, E_dlqe)

    # Calling lqe() with no timebase should call lqe()
    asys = ct.ss(csys.A, csys.B, csys.C, csys.D, dt=None)
    K_asys, S_asys, E_asys = ct.lqe(asys, Q, R)
    K_expl, S_expl, E_expl = ct.lqe(csys.A, csys.B, csys.C, Q, R)
    np.testing.assert_almost_equal(K_asys, K_expl)
    np.testing.assert_almost_equal(S_asys, S_expl)
    np.testing.assert_almost_equal(E_asys, E_expl)

    # Calling dlqe() with a continuous time system should raise an error
    with pytest.raises(ControlArgument, match="called with a continuous"):
        K, S, E = ct.dlqe(csys, Q, R)
def test_estimator_iosys():
    sys = ct.drss(4, 2, 2, strictly_proper=True)

    Q, R = np.eye(sys.nstates), np.eye(sys.ninputs)
    K, _, _ = ct.dlqr(sys, Q, R)

    P0 = np.eye(sys.nstates)
    QN = np.eye(sys.ninputs)
    RN = np.eye(sys.noutputs)
    estim = ct.create_estimator_iosystem(sys, QN, RN, P0)

    ctrl, clsys = ct.create_statefbk_iosystem(sys, K, estimator=estim)

    # Extract the elements of the estimator
    est = estim.linearize(0, 0)
    Be1 = est.B[:sys.nstates, :sys.noutputs]
    Be2 = est.B[:sys.nstates, sys.noutputs:]
    A_clchk = np.block(
        [[sys.A, -sys.B @ K],
         [Be1 @ sys.C, est.A[:sys.nstates, :sys.nstates] - Be2 @ K]])
    B_clchk = np.block([[sys.B @ K, sys.B], [Be2 @ K, Be2]])
    C_clchk = np.block([[sys.C, np.zeros((sys.noutputs, sys.nstates))],
                        [np.zeros_like(K), -K]])
    D_clchk = np.block([[np.zeros((sys.noutputs, sys.nstates + sys.ninputs))],
                        [K, np.eye(sys.ninputs)]])

    # Check to make sure everything matches
    cls = clsys.linearize(0, 0)
    nstates = sys.nstates
    np.testing.assert_almost_equal(cls.A[:2 * nstates, :2 * nstates], A_clchk)
    np.testing.assert_almost_equal(cls.B[:2 * nstates, :], B_clchk)
    np.testing.assert_almost_equal(cls.C[:, :2 * nstates], C_clchk)
    np.testing.assert_almost_equal(cls.D, D_clchk)
    def test_lqr_integral_discrete(self):
        # Generate a discrete time system for testing
        sys = ct.drss(4, 4, 2, strictly_proper=True)
        sys.C = np.eye(4)  # reset output to be full state
        C_int = np.eye(2, 4)  # integrate outputs for first two states
        nintegrators = C_int.shape[0]

        # Generate a controller with integral action
        K, _, _ = ct.lqr(sys,
                         np.eye(sys.nstates + nintegrators),
                         np.eye(sys.ninputs),
                         integral_action=C_int)
        Kp, Ki = K[:, :sys.nstates], K[:, sys.nstates:]

        # Create an I/O system for the controller
        ctrl, clsys = ct.create_statefbk_iosystem(sys,
                                                  K,
                                                  integral_action=C_int)

        # Construct the state space matrices by hand
        A_ctrl = np.eye(nintegrators)
        B_ctrl = np.block(
            [[-C_int, np.zeros((nintegrators, sys.ninputs)), C_int]])
        C_ctrl = -K[:, sys.nstates:]
        D_ctrl = np.block([[Kp, np.eye(nintegrators), -Kp]])

        # Check to make sure everything matches
        assert ct.isdtime(clsys)
        np.testing.assert_array_almost_equal(ctrl.A, A_ctrl)
        np.testing.assert_array_almost_equal(ctrl.B, B_ctrl)
        np.testing.assert_array_almost_equal(ctrl.C, C_ctrl)
        np.testing.assert_array_almost_equal(ctrl.D, D_ctrl)
def test_estimator_errors():
    sys = ct.drss(4, 2, 2, strictly_proper=True)
    P0 = np.eye(sys.nstates)
    QN = np.eye(sys.ninputs)
    RN = np.eye(sys.noutputs)

    with pytest.raises(ct.ControlArgument, match="Input system must be I/O"):
        sys_tf = ct.tf([1], [1, 1], dt=True)
        estim = ct.create_estimator_iosystem(sys_tf, QN, RN)

    with pytest.raises(NotImplementedError, match="continuous time not"):
        sys_ct = ct.rss(4, 2, 2, strictly_proper=True)
        estim = ct.create_estimator_iosystem(sys_ct, QN, RN)

    with pytest.raises(ValueError, match="output must be full state"):
        C = np.eye(2, 4)
        estim = ct.create_estimator_iosystem(sys, QN, RN, C=C)

    with pytest.raises(ValueError, match="output is the wrong size"):
        sys_fs = ct.drss(4, 4, 2, strictly_proper=True)
        sys_fs.C = np.eye(4)
        C = np.eye(1, 4)
        estim = ct.create_estimator_iosystem(sys_fs, QN, RN, C=C)
Exemple #6
0
    def __init__(self, states=1) -> None:
        """Create random discrete state space system

        :param states: number of states, defaults to 1
        :type states: int, optional
        """

        system = control.drss(states=states)

        self.A = np.array(system.A)
        self.B = np.array(system.B)
        self.C = np.array(system.C)
        self.D = np.array(system.D)

        self.x = np.zeros((states, 1), dtype=np.float64)
Exemple #7
0
def test_nyquist_exceptions():
    # MIMO not implemented
    sys = ct.rss(2, 2, 2)
    with pytest.raises(ct.exception.ControlMIMONotImplemented,
                       match="only supports SISO"):
        ct.nyquist_plot(sys)

    # Legacy keywords for arrow size
    sys = ct.rss(2, 1, 1)
    with pytest.warns(FutureWarning, match="use `arrow_size` instead"):
        ct.nyquist_plot(sys, arrow_width=8, arrow_length=6)

    # Discrete time system sampled above Nyquist frequency
    sys = ct.drss(2, 1, 1)
    sys.dt = 0.01
    with pytest.warns(UserWarning, match="above Nyquist"):
        ct.nyquist_plot(sys, np.logspace(-2, 3))
Exemple #8
0
    def __init__(self, states=1) -> None:
        """Create random discrete state space system

        Args:
            states (int, optional): number of states. Defaults to 1.

        Returns:
            None: [description]
        """

        import control

        system = control.drss(states=states)

        self.A = np.array(system.A)
        self.B = np.array(system.B)
        self.C = np.array(system.C)
        self.D = np.array(system.D)

        self.x = np.zeros((states, 1), dtype=np.float64)
def random_dtime_sys(Nout, Nin, Ts, Nstate=5):
    np.random.seed(0)
    sys_ = co.drss(Nstate, Nin, Nout)
    sys_.dt = Ts
    sys = co.tf(sys_)
    return sys