Пример #1
0
def test_interconnect_docstring():
    """Test the examples from the interconnect() docstring"""

    # MIMO interconnection (note: use [C, P] instead of [P, C] for state order)
    P = ct.LinearIOSystem(
           ct.rss(2, 2, 2, strictly_proper=True), name='P')
    C = ct.LinearIOSystem(ct.rss(2, 2, 2), name='C')
    T = ct.interconnect(
        [C, P],
        connections = [
          ['P.u[0]', 'C.y[0]'], ['P.u[1]', 'C.y[1]'],
          ['C.u[0]', '-P.y[0]'], ['C.u[1]', '-P.y[1]']],
        inplist = ['C.u[0]', 'C.u[1]'],
        outlist = ['P.y[0]', 'P.y[1]'],
    )
    T_ss = ct.feedback(P * C, ct.ss([], [], [], np.eye(2)))
    np.testing.assert_almost_equal(T.A, T_ss.A)
    np.testing.assert_almost_equal(T.B, T_ss.B)
    np.testing.assert_almost_equal(T.C, T_ss.C)
    np.testing.assert_almost_equal(T.D, T_ss.D)

    # Implicit interconnection (note: use [C, P, sumblk] for proper state order)
    P = ct.tf2io(ct.tf(1, [1, 0]), inputs='u', outputs='y')
    C = ct.tf2io(ct.tf(10, [1, 1]), inputs='e', outputs='u')
    sumblk = ct.summing_junction(inputs=['r', '-y'], output='e')
    T = ct.interconnect([C, P, sumblk], inplist='r', outlist='y')
    T_ss = ct.feedback(P * C, 1)
    np.testing.assert_almost_equal(T.A, T_ss.A)
    np.testing.assert_almost_equal(T.B, T_ss.B)
    np.testing.assert_almost_equal(T.C, T_ss.C)
    np.testing.assert_almost_equal(T.D, T_ss.D)
Пример #2
0
def test_interconnect_exceptions():
    # First make sure the docstring example works
    P = ct.tf2io(ct.tf(1, [1, 0]), input='u', output='y')
    C = ct.tf2io(ct.tf(10, [1, 1]), input='e', output='u')
    sumblk = ct.summing_junction(inputs=['r', '-y'], output='e')
    T = ct.interconnect((P, C, sumblk), input='r', output='y')
    assert (T.ninputs, T.noutputs, T.nstates) == (1, 1, 2)

    # Unrecognized arguments
    # LinearIOSystem
    with pytest.raises(TypeError, match="unknown parameter"):
        P = ct.LinearIOSystem(ct.rss(2, 1, 1), output_name='y')

    # Interconnect
    with pytest.raises(TypeError, match="unknown parameter"):
        T = ct.interconnect((P, C, sumblk), input_name='r', output='y')

    # Interconnected system
    with pytest.raises(TypeError, match="unknown parameter"):
        T = ct.InterconnectedSystem((P, C, sumblk), input_name='r', output='y')

    # NonlinearIOSytem
    with pytest.raises(TypeError, match="unknown parameter"):
        nlios =  ct.NonlinearIOSystem(
            None, lambda t, x, u, params: u*u, input_count=1, output_count=1)

    # Summing junction
    with pytest.raises(TypeError, match="input specification is required"):
        sumblk = ct.summing_junction()

    with pytest.raises(TypeError, match="unknown parameter"):
        sumblk = ct.summing_junction(input_count=2, output_count=2)
Пример #3
0
    def test_signals_naming_convention(self):
        """Enforce generic names to be present when systems are created
        without explicit signal names:
        input: 'u[i]'
        state: 'x[i]'
        output: 'y[i]'
        """
        ct.InputOutputSystem.idCounter = 0
        sys = ct.LinearIOSystem(self.mimo_linsys1)
        for statename in ["x[0]", "x[1]"]:
            self.assertTrue(statename in sys.state_index)
        for inputname in ["u[0]", "u[1]"]:
            self.assertTrue(inputname in sys.input_index)
        for outputname in ["y[0]", "y[1]"]:
            self.assertTrue(outputname in sys.output_index)
        self.assertEqual(len(sys.state_index), sys.nstates)
        self.assertEqual(len(sys.input_index), sys.ninputs)
        self.assertEqual(len(sys.output_index), sys.noutputs)

        namedsys = ios.NonlinearIOSystem(
            updfcn = lambda t, x, u, params: x,
            outfcn = lambda t, x, u, params: u,
            inputs = ('u0'),
            outputs = ('y0'),
            states = ('x0'),
            name = 'namedsys')
        unnamedsys = ct.NonlinearIOSystem(
            lambda t,x,u,params: x, inputs=1, outputs=1, states=1
        )
        self.assertTrue('u0' in namedsys.input_index)
        self.assertTrue('y0' in namedsys.output_index)
        self.assertTrue('x0' in namedsys.state_index)

        # Unnamed/named connections
        un_series = unnamedsys * namedsys
        un_parallel = unnamedsys + namedsys
        un_feedback = unnamedsys.feedback(namedsys)
        un_dup = unnamedsys * namedsys.copy()
        un_hierarchical = un_series*unnamedsys
        u_neg = - unnamedsys

        self.assertTrue("sys[1].x[0]" in un_series.state_index)
        self.assertTrue("namedsys.x0" in un_series.state_index)
        self.assertTrue("sys[1].x[0]" in un_parallel.state_index)
        self.assertTrue("namedsys.x0" in un_series.state_index)
        self.assertTrue("sys[1].x[0]" in un_feedback.state_index)
        self.assertTrue("namedsys.x0" in un_feedback.state_index)
        self.assertTrue("sys[1].x[0]" in un_dup.state_index)
        self.assertTrue("copy of namedsys.x0" in un_dup.state_index)
        self.assertTrue("sys[1].x[0]" in un_hierarchical.state_index)
        self.assertTrue("sys[2].sys[1].x[0]" in un_hierarchical.state_index)
        self.assertTrue("sys[1].x[0]" in u_neg.state_index)

        # Same system conflict
        with warnings.catch_warnings(record=True) as warnval:
            same_name_series = unnamedsys * unnamedsys
            self.assertEquals(len(warnval), 1)
            self.assertTrue("sys[1].x[0]" in same_name_series.state_index)
            self.assertTrue("copy of sys[1].x[0]" in same_name_series.state_index)
Пример #4
0
def test_string_inputoutput():
    # regression test for gh-692
    P1 = ct.rss(2, 1, 1)
    P1_iosys = ct.LinearIOSystem(P1, inputs='u1', outputs='y1')
    P2 = ct.rss(2, 1, 1)
    P2_iosys = ct.LinearIOSystem(P2, inputs='y1', outputs='y2')

    P_s1 = ct.interconnect([P1_iosys, P2_iosys], inputs='u1', outputs=['y2'])
    assert P_s1.input_index == {'u1' : 0}

    P_s2 = ct.interconnect([P1_iosys, P2_iosys], input='u1', outputs=['y2'])
    assert P_s2.input_index == {'u1' : 0}

    P_s1 = ct.interconnect([P1_iosys, P2_iosys], inputs=['u1'], outputs='y2')
    assert P_s1.output_index == {'y2' : 0}

    P_s2 = ct.interconnect([P1_iosys, P2_iosys], inputs=['u1'], output='y2')
    assert P_s2.output_index == {'y2' : 0}
Пример #5
0
    def test_sys_naming_convention(self):
        """Enforce generic system names 'sys[i]' to be present when systems are created
        without explicit names."""

        ct.InputOutputSystem.idCounter = 0
        sys = ct.LinearIOSystem(self.mimo_linsys1)
        self.assertEquals(sys.name, "sys[0]")
        self.assertEquals(sys.copy().name, "copy of sys[0]")
        
        namedsys = ios.NonlinearIOSystem(
            updfcn = lambda t, x, u, params: x,
            outfcn = lambda t, x, u, params: u,
            inputs = ('u[0]', 'u[1]'),
            outputs = ('y[0]', 'y[1]'),
            states = self.mimo_linsys1.states,
            name = 'namedsys')
        unnamedsys1 = ct.NonlinearIOSystem(
            lambda t,x,u,params: x, inputs=2, outputs=2, states=2
        )
        unnamedsys2 = ct.NonlinearIOSystem(
            None, lambda t,x,u,params: u, inputs=2, outputs=2
        )
        self.assertEquals(unnamedsys2.name, "sys[2]")

        # Unnamed/unnamed connections
        uu_series = unnamedsys1 * unnamedsys2
        uu_parallel = unnamedsys1 + unnamedsys2
        u_neg = - unnamedsys1
        uu_feedback = unnamedsys2.feedback(unnamedsys1)
        uu_dup = unnamedsys1 * unnamedsys1.copy()
        uu_hierarchical = uu_series*unnamedsys1

        self.assertEquals(uu_series.name, "sys[3]")
        self.assertEquals(uu_parallel.name, "sys[4]")
        self.assertEquals(u_neg.name, "sys[5]")
        self.assertEquals(uu_feedback.name, "sys[6]")
        self.assertEquals(uu_dup.name, "sys[7]")
        self.assertEquals(uu_hierarchical.name, "sys[8]")

        # Unnamed/named connections
        un_series = unnamedsys1 * namedsys
        un_parallel = unnamedsys1 + namedsys
        un_feedback = unnamedsys2.feedback(namedsys)
        un_dup = unnamedsys1 * namedsys.copy()
        un_hierarchical = uu_series*unnamedsys1

        self.assertEquals(un_series.name, "sys[9]")
        self.assertEquals(un_parallel.name, "sys[10]")
        self.assertEquals(un_feedback.name, "sys[11]")
        self.assertEquals(un_dup.name, "sys[12]")
        self.assertEquals(un_hierarchical.name, "sys[13]")

        # Same system conflict
        with warnings.catch_warnings(record=True) as warnval:
            unnamedsys1 * unnamedsys1
            self.assertEqual(len(warnval), 1)
Пример #6
0
    def test_duplicates(self):
        nlios =  ios.NonlinearIOSystem(lambda t,x,u,params: x, \
                                       lambda t, x, u, params: u*u, \
                                       inputs=1, outputs=1, states=1, name="sys")

        # Turn off deprecation warnings
        warnings.simplefilter("ignore", category=DeprecationWarning)
        warnings.simplefilter("ignore", category=PendingDeprecationWarning)

        # Duplicate objects
        with warnings.catch_warnings(record=True) as warnval:
            # Trigger a warning
            ios_series = nlios * nlios

            # Verify that we got a warning
            self.assertEqual(len(warnval), 1)
            self.assertTrue(issubclass(warnval[-1].category, UserWarning))
            self.assertTrue("Duplicate object" in str(warnval[-1].message))

        # Nonduplicate objects
        nlios1 = nlios.copy()
        nlios2 = nlios.copy()
        with warnings.catch_warnings(record=True) as warnval:
            ios_series = nlios1 * nlios2
            self.assertEquals(len(warnval), 1)
            # when subsystems have the same name, duplicates are
            # renamed <subsysname_i>
            self.assertTrue("copy of sys_1.x[0]" in ios_series.state_index.keys())
            self.assertTrue("copy of sys.x[0]" in ios_series.state_index.keys())

        # Duplicate names
        iosys_siso = ct.LinearIOSystem(self.siso_linsys)
        nlios1 = ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1, name="sys")
        nlios2 = ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1, name="sys")
        with warnings.catch_warnings(record=True) as warnval:
            # Trigger a warning
            iosys = ct.InterconnectedSystem(
                (nlios1, iosys_siso, nlios2), inputs=0, outputs=0, states=0)

            # Verify that we got a warning
            self.assertEqual(len(warnval), 1)
            self.assertTrue(issubclass(warnval[-1].category, UserWarning))
            self.assertTrue("Duplicate name" in str(warnval[-1].message))

        # Same system, different names => everything should be OK
        nlios1 = ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1, name="nlios1")
        nlios2 = ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1, name="nlios2")
        with warnings.catch_warnings(record=True) as warnval:
            iosys = ct.InterconnectedSystem(
                (nlios1, iosys_siso, nlios2), inputs=0, outputs=0, states=0)
            self.assertEqual(len(warnval), 0)
def sys_dict():
    sdict = {}
    sdict['ss'] = ct.ss([[-1]], [[1]], [[1]], [[0]])
    sdict['tf'] = ct.tf([1], [0.5, 1])
    sdict['tfx'] = ct.tf([1, 1], [1])  # non-proper transfer function
    sdict['frd'] = ct.frd([10 + 0j, 9 + 1j, 8 + 2j], [1, 2, 3])
    sdict['lio'] = ct.LinearIOSystem(ct.ss([[-1]], [[5]], [[5]], [[0]]))
    sdict['ios'] = ct.NonlinearIOSystem(sdict['lio']._rhs, sdict['lio']._out,
                                        1, 1, 1)
    sdict['arr'] = np.array([[2.0]])
    sdict['flt'] = 3.
    return sdict
Пример #8
0
    def test_lineariosys_statespace(self):
        """Make sure that a LinearIOSystem is also a StateSpace object"""
        iosys_siso = ct.LinearIOSystem(self.siso_linsys)
        self.assertTrue(isinstance(iosys_siso, ct.StateSpace))

        # Make sure that state space functions work for LinearIOSystems
        np.testing.assert_array_equal(
            iosys_siso.pole(), self.siso_linsys.pole())
        omega = np.logspace(.1, 10, 100)
        mag_io, phase_io, omega_io = iosys_siso.freqresp(omega)
        mag_ss, phase_ss, omega_ss = self.siso_linsys.freqresp(omega)
        np.testing.assert_array_equal(mag_io, mag_ss)
        np.testing.assert_array_equal(phase_io, phase_ss)
        np.testing.assert_array_equal(omega_io, omega_ss)

        # LinearIOSystem methods should override StateSpace methods
        io_mul = iosys_siso * iosys_siso
        self.assertTrue(isinstance(io_mul, ct.InputOutputSystem))

        # But also retain linear structure
        self.assertTrue(isinstance(io_mul, ct.StateSpace))

        # And make sure the systems match
        ss_series = self.siso_linsys * self.siso_linsys
        np.testing.assert_array_equal(io_mul.A, ss_series.A)
        np.testing.assert_array_equal(io_mul.B, ss_series.B)
        np.testing.assert_array_equal(io_mul.C, ss_series.C)
        np.testing.assert_array_equal(io_mul.D, ss_series.D)

        # Make sure that series does the same thing
        io_series = ct.series(iosys_siso, iosys_siso)
        self.assertTrue(isinstance(io_series, ct.InputOutputSystem))
        self.assertTrue(isinstance(io_series, ct.StateSpace))
        np.testing.assert_array_equal(io_series.A, ss_series.A)
        np.testing.assert_array_equal(io_series.B, ss_series.B)
        np.testing.assert_array_equal(io_series.C, ss_series.C)
        np.testing.assert_array_equal(io_series.D, ss_series.D)

        # Test out feedback as well
        io_feedback = ct.feedback(iosys_siso, iosys_siso)
        self.assertTrue(isinstance(io_series, ct.InputOutputSystem))

        # But also retain linear structure
        self.assertTrue(isinstance(io_series, ct.StateSpace))

        # And make sure the systems match
        ss_feedback = ct.feedback(self.siso_linsys, self.siso_linsys)
        np.testing.assert_array_equal(io_feedback.A, ss_feedback.A)
        np.testing.assert_array_equal(io_feedback.B, ss_feedback.B)
        np.testing.assert_array_equal(io_feedback.C, ss_feedback.C)
        np.testing.assert_array_equal(io_feedback.D, ss_feedback.D)
Пример #9
0
def sys_dict():
    sdict = {}
    sdict['ss'] = ct.StateSpace([[-1]], [[1]], [[1]], [[0]])
    sdict['tf'] = ct.TransferFunction([1], [0.5, 1])
    sdict['tfx'] = ct.TransferFunction([1, 1], [1])  # non-proper TF
    sdict['frd'] = ct.frd([10 + 0j, 9 + 1j, 8 + 2j, 7 + 3j], [1, 2, 3, 4])
    sdict['lio'] = ct.LinearIOSystem(ct.ss([[-1]], [[5]], [[5]], [[0]]))
    sdict['ios'] = ct.NonlinearIOSystem(sdict['lio']._rhs,
                                        sdict['lio']._out,
                                        inputs=1,
                                        outputs=1,
                                        states=1)
    sdict['arr'] = np.array([[2.0]])
    sdict['flt'] = 3.
    return sdict
Пример #10
0
def test_trdata_labels():
    # Create an I/O system with labels
    sys = ct.rss(4, 3, 2)
    iosys = ct.LinearIOSystem(sys)

    T = np.linspace(1, 10, 10)
    U = [np.sin(T), np.cos(T)]

    # Create a response
    response = ct.input_output_response(iosys, T, U)

    # Make sure the labels got created
    np.testing.assert_equal(
        response.output_labels, ["y[%d]" % i for i in range(sys.noutputs)])
    np.testing.assert_equal(
        response.state_labels, ["x[%d]" % i for i in range(sys.nstates)])
    np.testing.assert_equal(
        response.input_labels, ["u[%d]" % i for i in range(sys.ninputs)])
Пример #11
0
J_HAT_0 = 5
B_HAT_0 = 0.1

# Flag to disable adaptive control
IS_ADAPTIVE = 1

# Plant
# u_input: u
# x_state: x
# y_output: x
SS_PLANT = control.StateSpace(-B/J, 1/J, 1, 0)

IO_DC_MOTOR = control.LinearIOSystem(
    SS_PLANT,
    inputs=('u'),
    outputs=('x'),
    states=('x'),
    name='plant'
)

def adaptive_pi_state(_t, x_state, u_input, _params):
    """Internal state of adpative PI controller"""

    # Controller inputs
    x_d = u_input[0]
    x_d_dot = u_input[1]
    x = u_input[2]

    # Controller state
    e_i = x_state[2]
Пример #12
0
K_0 = 1.1
BETA_DELTA_0 = 0
E_DELTA_0 = 0

# Actuator saturation limit
U_MAX = 10

# Gains
GAMMA_1 = 0.1
GAMMA_2 = 0.1
GAMMA_3 = 1

# Define plant
IO_PLANT = control.LinearIOSystem(control.StateSpace(A_P, B_P, C_P, D_P),
                                  inputs=('u'),
                                  outputs=('x_p'),
                                  states=('x_p'),
                                  name='plant')

# Define reference model
IO_REF_MODEL = control.LinearIOSystem(control.StateSpace(A_M, B_M, C_M, D_M),
                                      inputs=('r'),
                                      outputs=('x_m'),
                                      states=('x_m'),
                                      name='ref_model')


def adaptive_state(_t, x_state, u_input, _params):  # pylint: disable=too-many-locals
    """Internal state of adpative controller"""

    # Controller inputs
Пример #13
0
    if u > Pmax:  #300Watt heating element
        u = Pmax
    dP = u - power
    return dP


# https://python-control.readthedocs.io/en/0.8.3/iosys.html
#  Heater system
heater_IO = ctl.NonlinearIOSystem(hupdate,
                                  None,
                                  inputs='p',
                                  outputs='ph',
                                  states='p')

ctl_PID_IO = ctl.iosys.tf2io(conpid)  # includes Kd
plant_IO = ctl.LinearIOSystem(ss_mod)
ufb_IO = ctl.iosys.tf2io(ufb)  # unity feedback

clsysSat = ctl.feedback(
    ctl.series(ctl_PID_IO, heater_IO, plant_IO), ufb_IO,
    sign=-1)  # negative fb closed loop  system w/ Saturation

# Saturation test:
#input = Texp  # simple ramp
#for i,iN in enumerate(input):
#input[i] = 2*iN - 250 # expose the saturation
# saturation only
#t4,y4 = ctl.input_output_response(heater_IO, Texp, input)

# closed loop non linear response (experimental)
#t4,y4 = ctl.input_output_response(clsysSat, Texp, [ Rexp ])
Пример #14
0
import matplotlib.pyplot as plt

# Plant parameters
# input: u
# state: x_p
# output: x_p
A_P = np.array([[-2, -1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, -4, -2, 0],
                [0, 0, 2, 0, 0], [0, 0, 0, 0, 3]])
B_P = np.array([[1, 0], [0, 0], [0, 1], [0, 0], [0, 1]])
C_P = np.array([[1, 1, 0, 1, 0], [0, 1, 0, 0, 1]])
D_P = np.array([[0, 0], [0, 0]])

# Define plant
IO_PLANT = control.LinearIOSystem(control.StateSpace(A_P, B_P, C_P, D_P),
                                  inputs=2,
                                  outputs=2,
                                  states=5,
                                  name='plant')

# Stable Hermite form
A = 1

# # Reference Model
NUM_WM = [[np.array([0]) for i in range(2)] for j in range(2)]
DEN_WM = [[np.array([1]) for i in range(2)] for j in range(2)]

NUM_WM[0][0] = np.array([A])
DEN_WM[0][0] = np.array([1., A])
NUM_WM[1][1] = np.array([A])
DEN_WM[1][1] = np.array([1., A])
Пример #15
0
                                          name='sysFullNonLin')
sysLin = sysFullNonLin.linearize([0.0, 0.0, 0.0, 0.0], 0.0,
                                 params=sysParams)  # linearize on up position

A = sysLin.A
B = sysLin.B
BF = np.concatenate([B, Vd, 0.0 * B],
                    axis=1)  # augment inputs to include disturbance and noise
C_full = sysLin.C
C_part = np.array([1, 0, 0, 0], dtype=np.float)

ssFull = control.StateSpace(A, BF, C_full, np.zeros(
    BF.shape))  # system with full state output, disturbance, no noise
sysFull = control.LinearIOSystem(ssFull,
                                 inputs=('u', 'vd0', 'vd1', 'vd2', 'vd3',
                                         'vn'),
                                 outputs=('x', 'xdot', 'theta', 'thetadot'),
                                 states=('x', 'xdot', 'theta', 'thetadot'),
                                 name='sysFull')

ssPart = control.StateSpace(A, BF, C_part, np.array(
    [0, 0, 0, 0, 0, Vn]))  # build big state space system... with single output

# Kalman estimator
# Kf, P, E = control.lqe(A, Vd, C, Vd, Vn)  # design Kalman filter
Kf, _, _ = control.lqr(
    np.transpose(A), np.expand_dims(C_part, axis=1), Vd,
    Vn)  # alternatively, possible to design using "LQR" code
Kf = np.transpose(Kf)

ssKF = control.StateSpace(
    A - Kf * C_part, np.concatenate([B, Kf], axis=1), np.eye(4),