Esempio n. 1
0
    def test_nonlinear_iosys(self):
        # Create a simple nonlinear I/O system
        nlsys = ios.NonlinearIOSystem(predprey)
        T = self.T

        # Start by simulating from an equilibrium point
        X0 = [0, 0]
        ios_t, ios_y = ios.input_output_response(nlsys, T, 0, X0)
        np.testing.assert_array_almost_equal(ios_y, np.zeros(np.shape(ios_y)))

        # Now simulate from a nonzero point
        X0 = [0.5, 0.5]
        ios_t, ios_y = ios.input_output_response(nlsys, T, 0, X0)

        #
        # Simulate a linear function as a nonlinear function and compare
        #
        # Create a single input/single output linear system
        linsys = self.siso_linsys

        # Create a nonlinear system with the same dynamics
        nlupd = lambda t, x, u, params: \
            np.reshape(linsys.A * np.reshape(x, (-1, 1)) + linsys.B * u, (-1,))
        nlout = lambda t, x, u, params: \
            np.reshape(linsys.C * np.reshape(x, (-1, 1)) + linsys.D * u, (-1,))
        nlsys = ios.NonlinearIOSystem(nlupd, nlout)

        # Make sure that simulations also line up
        T, U, X0 = self.T, self.U, self.X0
        lti_t, lti_y, lti_x = ct.forced_response(linsys, T, U, X0)
        ios_t, ios_y = ios.input_output_response(nlsys, T, U, X0)
        np.testing.assert_array_almost_equal(lti_t, ios_t)
        np.testing.assert_array_almost_equal(lti_y, ios_y, decimal=3)
Esempio n. 2
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)
Esempio n. 3
0
    def test_linearize(self):
        # Create a single input/single output linear system
        linsys = self.siso_linsys
        iosys = ios.LinearIOSystem(linsys)

        # Linearize it and make sure we get back what we started with
        linearized = iosys.linearize([0, 0], 0)
        np.testing.assert_array_almost_equal(linsys.A, linearized.A)
        np.testing.assert_array_almost_equal(linsys.B, linearized.B)
        np.testing.assert_array_almost_equal(linsys.C, linearized.C)
        np.testing.assert_array_almost_equal(linsys.D, linearized.D)

        # Create a simple nonlinear system to check (kinematic car)
        def kincar_update(t, x, u, params):
            return np.array([np.cos(x[2]) * u[0], np.sin(x[2]) * u[0], u[1]])
        def kincar_output(t, x, u, params):
            return np.array([x[0], x[1]])
        iosys = ios.NonlinearIOSystem(kincar_update, kincar_output)
        linearized = iosys.linearize([0, 0, 0], [0, 0])
        np.testing.assert_array_almost_equal(linearized.A, np.zeros((3,3)))
        np.testing.assert_array_almost_equal(
            linearized.B, [[1, 0], [0, 0], [0, 1]])
        np.testing.assert_array_almost_equal(
            linearized.C, [[1, 0, 0], [0, 1, 0]])
        np.testing.assert_array_almost_equal(linearized.D, np.zeros((2,2)))
Esempio n. 4
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)
Esempio n. 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)
Esempio n. 6
0
    def test_named_signals_linearize_inconsistent(self):
        """Mare sure that providing inputs or outputs not consistent with
           updfcn or outfcn fail
        """

        def updfcn(t, x, u, params):
            """2 inputs, 2 states"""
            return np.array(
                np.dot(self.mimo_linsys1.A, np.reshape(x, (-1, 1)))
                + np.dot(self.mimo_linsys1.B, np.reshape(u, (-1, 1)))
                ).reshape(-1,)

        def outfcn(t, x, u, params):
            """2 states, 2 outputs"""
            return np.array(
                    self.mimo_linsys1.C * np.reshape(x, (-1, 1))
                    + self.mimo_linsys1.D * np.reshape(u, (-1, 1))
                ).reshape(-1,)

        for inputs, outputs in [
                (('u[0]'), ('y[0]', 'y[1]')),  # not enough u
                (('u[0]', 'u[1]', 'u[toomuch]'), ('y[0]', 'y[1]')),
                (('u[0]', 'u[1]'), ('y[0]')),  # not enough y
                (('u[0]', 'u[1]'), ('y[0]', 'y[1]', 'y[toomuch]'))]:
            sys1 = ios.NonlinearIOSystem(updfcn=updfcn,
                                         outfcn=outfcn,
                                         inputs=inputs,
                                         outputs=outputs,
                                         states=self.mimo_linsys1.states,
                                         name='sys1')
            self.assertRaises(ValueError, sys1.linearize, [0, 0], [0, 0])

        sys2 = ios.NonlinearIOSystem(updfcn=updfcn,
                                     outfcn=outfcn,
                                     inputs=('u[0]', 'u[1]'),
                                     outputs=('y[0]', 'y[1]'),
                                     states=self.mimo_linsys1.states,
                                     name='sys1')
        for x0, u0 in [([0], [0, 0]),
                       ([0, 0, 0], [0, 0]),
                       ([0, 0], [0]),
                       ([0, 0], [0, 0, 0])]:
            self.assertRaises(ValueError, sys2.linearize, x0, u0)
Esempio n. 7
0
    def test_feedback(self):
        # Set up parameters for simulation
        T, U, X0 = self.T, self.U, self.X0

        # Linear system with constant feedback (via "nonlinear" mapping)
        ioslin = ios.LinearIOSystem(self.siso_linsys)
        nlios =  ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u, inputs=1, outputs=1)
        iosys = ct.feedback(ioslin, nlios)
        linsys = ct.feedback(self.siso_linsys, 1)

        ios_t, ios_y = ios.input_output_response(iosys, T, U, X0)
        lti_t, lti_y, lti_x = ct.forced_response(linsys, T, U, X0)
        np.testing.assert_array_almost_equal(ios_y, lti_y, decimal=3)
Esempio n. 8
0
    def test_iosys_print(self):
        # Send the output to /dev/null
        import os
        f = open(os.devnull,"w")

        # Simple I/O system
        iosys = ct.ss2io(self.siso_linsys)
        print(iosys, file=f)

        # I/O system without ninputs, noutputs
        ios_unspecified = ios.NonlinearIOSystem(secord_update, secord_output)
        print(ios_unspecified, file=f)

        # I/O system with derived inputs and outputs
        ios_linearized = ios.linearize(ios_unspecified, [0, 0], [0])
        print(ios_linearized, file=f)

        f.close()
Esempio n. 9
0
    def test_rmul(self):
        # Test right multiplication
        # TODO: replace with better tests when conversions are implemented

        # Set up parameters for simulation
        T, U, X0 = self.T, self.U, self.X0

        # Linear system with input and output nonlinearities
        # Also creates a nested interconnected system
        ioslin = ios.LinearIOSystem(self.siso_linsys)
        nlios =  ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1)
        sys1 = nlios * ioslin
        sys2 = ios.InputOutputSystem.__rmul__(nlios, sys1)

        # Make sure we got the right thing (via simulation comparison)
        ios_t, ios_y = ios.input_output_response(sys2, T, U, X0)
        lti_t, lti_y, lti_x = ct.forced_response(ioslin, T, U*U, X0)
        np.testing.assert_array_almost_equal(ios_y, lti_y*lti_y, decimal=3)
Esempio n. 10
0
    def test_neg(self):
        """Test negation of a system"""

        # Set up parameters for simulation
        T, U, X0 = self.T, self.U, self.X0

        # Static nonlinear system
        nlios =  ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1)
        ios_t, ios_y = ios.input_output_response(-nlios, T, U, X0)
        np.testing.assert_array_almost_equal(ios_y, -U*U, decimal=3)

        # Linear system with input nonlinearity
        # Also creates a nested interconnected system
        ioslin = ios.LinearIOSystem(self.siso_linsys)
        sys = (ioslin) * (-nlios)

        # Make sure we got the right thing (via simulation comparison)
        ios_t, ios_y = ios.input_output_response(sys, T, U, X0)
        lti_t, lti_y, lti_x = ct.forced_response(ioslin, T, U*U, X0)
        np.testing.assert_array_almost_equal(ios_y, -lti_y, decimal=3)
Esempio n. 11
0
    def test_static_nonlinearity(self):
        # Linear dynamical system
        linsys = self.siso_linsys
        ioslin = ios.LinearIOSystem(linsys)

        # Nonlinear saturation
        sat = lambda u: u if abs(u) < 1 else np.sign(u)
        sat_output = lambda t, x, u, params: sat(u)
        nlsat =  ios.NonlinearIOSystem(None, sat_output, inputs=1, outputs=1)

        # Set up parameters for simulation
        T, U, X0 = self.T, 2 * self.U, self.X0
        Usat = np.vectorize(sat)(U)

        # Make sure saturation works properly by comparing linear system with
        # saturated input to nonlinear system with saturation composition
        lti_t, lti_y, lti_x = ct.forced_response(linsys, T, Usat, X0)
        ios_t, ios_y, ios_x = ios.input_output_response(
            ioslin * nlsat, T, U, X0, return_x=True)
        np.testing.assert_array_almost_equal(lti_t, ios_t)
        np.testing.assert_array_almost_equal(lti_y, ios_y, decimal=2)
Esempio n. 12
0
    def test_named_signals(self):
        sys1 = ios.NonlinearIOSystem(
            updfcn = lambda t, x, u, params: np.array(
                np.dot(self.mimo_linsys1.A, np.reshape(x, (-1, 1))) \
                + np.dot(self.mimo_linsys1.B, np.reshape(u, (-1, 1)))
            ).reshape(-1,),
            outfcn = lambda t, x, u, params: np.array(
                self.mimo_linsys1.C * np.reshape(x, (-1, 1)) \
                + self.mimo_linsys1.D * np.reshape(u, (-1, 1))
            ).reshape(-1,),
            inputs = ('u[0]', 'u[1]'),
            outputs = ('y[0]', 'y[1]'),
            states = self.mimo_linsys1.states,
            name = 'sys1')
        sys2 = ios.LinearIOSystem(self.mimo_linsys2,
            inputs = ('u[0]', 'u[1]'),
            outputs = ('y[0]', 'y[1]'),
            name = 'sys2')

        # Series interconnection (sys1 * sys2) using __mul__
        ios_mul = sys1 * sys2
        ss_series = self.mimo_linsys1 * self.mimo_linsys2
        lin_series = ct.linearize(ios_mul, 0, 0)
        for M, N in ((ss_series.A, lin_series.A), (ss_series.B, lin_series.B),
                     (ss_series.C, lin_series.C), (ss_series.D, lin_series.D)):
            np.testing.assert_array_almost_equal(M, N)

        # Series interconnection (sys1 * sys2) using series
        ios_series = ct.series(sys2, sys1)
        ss_series = ct.series(self.mimo_linsys2, self.mimo_linsys1)
        lin_series = ct.linearize(ios_series, 0, 0)
        for M, N in ((ss_series.A, lin_series.A), (ss_series.B, lin_series.B),
                     (ss_series.C, lin_series.C), (ss_series.D, lin_series.D)):
            np.testing.assert_array_almost_equal(M, N)

        # Series interconnection (sys1 * sys2) using named + mixed signals
        ios_connect = ios.InterconnectedSystem(
            (sys2, sys1),
            connections=(
                (('sys1', 'u[0]'), 'sys2.y[0]'),
                ('sys1.u[1]', 'sys2.y[1]')
            ),
            inplist=('sys2.u[0]', ('sys2', 1)),
            outlist=((1, 'y[0]'), 'sys1.y[1]')
        )
        lin_series = ct.linearize(ios_connect, 0, 0)
        for M, N in ((ss_series.A, lin_series.A), (ss_series.B, lin_series.B),
                     (ss_series.C, lin_series.C), (ss_series.D, lin_series.D)):
            np.testing.assert_array_almost_equal(M, N)

        # Make sure that we can use input signal names as system outputs
        ios_connect = ios.InterconnectedSystem(
            (sys1, sys2),
            connections=(
                ('sys2.u[0]', 'sys1.y[0]'), ('sys2.u[1]', 'sys1.y[1]'),
                ('sys1.u[0]', '-sys2.y[0]'), ('sys1.u[1]', '-sys2.y[1]')
            ),
            inplist=('sys1.u[0]', 'sys1.u[1]'),
            outlist=('sys2.u[0]', 'sys2.u[1]')  # = sys1.y[0], sys1.y[1]
        )
        ss_feedback = ct.feedback(self.mimo_linsys1, self.mimo_linsys2)
        lin_feedback = ct.linearize(ios_connect, 0, 0)
        np.testing.assert_array_almost_equal(ss_feedback.A, lin_feedback.A)
        np.testing.assert_array_almost_equal(ss_feedback.B, lin_feedback.B)
        np.testing.assert_array_almost_equal(ss_feedback.C, lin_feedback.C)
        np.testing.assert_array_almost_equal(ss_feedback.D, lin_feedback.D)
Esempio n. 13
0
    def test_params(self):
        # Start with the default set of parameters
        ios_secord_default = ios.NonlinearIOSystem(
            secord_update, secord_output, inputs=1, outputs=1, states=2)
        lin_secord_default = ios.linearize(ios_secord_default, [0, 0], [0])
        w_default, v_default = np.linalg.eig(lin_secord_default.A)

        # New copy, with modified parameters
        ios_secord_update = ios.NonlinearIOSystem(
            secord_update, secord_output, inputs=1, outputs=1, states=2,
            params={'omega0':2, 'zeta':0})

        # Make sure the default parameters haven't changed
        lin_secord_check = ios.linearize(ios_secord_default, [0, 0], [0])
        w, v = np.linalg.eig(lin_secord_check.A)
        np.testing.assert_array_almost_equal(np.sort(w), np.sort(w_default))

        # Make sure updated system parameters got set correctly
        lin_secord_update = ios.linearize(ios_secord_update, [0, 0], [0])
        w, v = np.linalg.eig(lin_secord_update.A)
        np.testing.assert_array_almost_equal(np.sort(w), np.sort([2j, -2j]))

        # Change the parameters of the default sys just for the linearization
        lin_secord_local = ios.linearize(ios_secord_default, [0, 0], [0],
                                          params={'zeta':0})
        w, v = np.linalg.eig(lin_secord_local.A)
        np.testing.assert_array_almost_equal(np.sort(w), np.sort([1j, -1j]))

        # Change the parameters of the updated sys just for the linearization
        lin_secord_local = ios.linearize(ios_secord_update, [0, 0], [0],
                                          params={'zeta':0, 'omega0':3})
        w, v = np.linalg.eig(lin_secord_local.A)
        np.testing.assert_array_almost_equal(np.sort(w), np.sort([3j, -3j]))

        # Make sure that changes propagate through interconnections
        ios_series_default_local = ios_secord_default * ios_secord_update
        lin_series_default_local = ios.linearize(
            ios_series_default_local, [0, 0, 0, 0], [0])
        w, v = np.linalg.eig(lin_series_default_local.A)
        np.testing.assert_array_almost_equal(
            np.sort(w), np.sort(np.concatenate((w_default, [2j, -2j]))))

        # Show that we can change the parameters at linearization
        lin_series_override = ios.linearize(
            ios_series_default_local, [0, 0, 0, 0], [0],
            params={'zeta':0, 'omega0':4})
        w, v = np.linalg.eig(lin_series_override.A)
        np.testing.assert_array_almost_equal(w, [4j, -4j, 4j, -4j])

        # Check for warning if we try to set params for LinearIOSystem
        linsys = self.siso_linsys
        iosys = ios.LinearIOSystem(linsys)
        T, U, X0 = self.T, self.U, self.X0
        lti_t, lti_y, lti_x = ct.forced_response(linsys, T, U, X0)
        with warnings.catch_warnings(record=True) as warnval:
            # Turn off deprecation warnings
            warnings.simplefilter("ignore", category=DeprecationWarning)
            warnings.simplefilter("ignore", category=PendingDeprecationWarning)

            # Trigger a warning
            ios_t, ios_y = ios.input_output_response(
                iosys, T, U, X0, params={'something':0})

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

        # Check to make sure results are OK
        np.testing.assert_array_almost_equal(lti_t, ios_t)
        np.testing.assert_array_almost_equal(lti_y, ios_y, decimal=3)
Esempio n. 14
0
    def test_find_eqpts(self):
        """Test find_eqpt function"""
        # Simple equilibrium point with no inputs
        nlsys = ios.NonlinearIOSystem(predprey)
        xeq, ueq, result = ios.find_eqpt(
            nlsys, [1.6, 1.2], None, return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(xeq, [1.64705879, 1.17923874])
        np.testing.assert_array_almost_equal(
            nlsys._rhs(0, xeq, ueq), np.zeros((2,)))

        # Ducted fan dynamics with output = velocity
        nlsys = ios.NonlinearIOSystem(pvtol, lambda t, x, u, params: x[0:2])

        # Make sure the origin is a fixed point
        xeq, ueq, result = ios.find_eqpt(
            nlsys, [0, 0, 0, 0], [0, 4*9.8], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(
            nlsys._rhs(0, xeq, ueq), np.zeros((4,)))
        np.testing.assert_array_almost_equal(xeq, [0, 0, 0, 0])

        # Use a small lateral force to cause motion
        xeq, ueq, result = ios.find_eqpt(
            nlsys, [0, 0, 0, 0], [0.01, 4*9.8], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(
            nlsys._rhs(0, xeq, ueq), np.zeros((4,)), decimal=5)

        # Equilibrium point with fixed output
        xeq, ueq, result = ios.find_eqpt(
            nlsys, [0, 0, 0, 0], [0.01, 4*9.8],
            y0=[0.1, 0.1], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(
            nlsys._out(0, xeq, ueq), [0.1, 0.1], decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys._rhs(0, xeq, ueq), np.zeros((4,)), decimal=5)

        # Specify outputs to constrain (replicate previous)
        xeq, ueq, result = ios.find_eqpt(
            nlsys, [0, 0, 0, 0], [0.01, 4*9.8], y0=[0.1, 0.1],
            iy = [0, 1], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(
            nlsys._out(0, xeq, ueq), [0.1, 0.1], decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys._rhs(0, xeq, ueq), np.zeros((4,)), decimal=5)

        # Specify inputs to constrain (replicate previous), w/ no result
        xeq, ueq = ios.find_eqpt(
            nlsys, [0, 0, 0, 0], [0.01, 4*9.8], y0=[0.1, 0.1], iu = [])
        np.testing.assert_array_almost_equal(
            nlsys._out(0, xeq, ueq), [0.1, 0.1], decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys._rhs(0, xeq, ueq), np.zeros((4,)), decimal=5)

        # Now solve the problem with the original PVTOL variables
        # Constrain the output angle and x velocity
        nlsys_full = ios.NonlinearIOSystem(pvtol_full, None)
        xeq, ueq, result = ios.find_eqpt(
            nlsys_full, [0, 0, 0, 0, 0, 0], [0.01, 4*9.8],
            y0=[0, 0, 0.1, 0.1, 0, 0], iy = [2, 3],
            idx=[2, 3, 4, 5], ix=[0, 1], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(
            nlsys_full._out(0, xeq, ueq)[[2, 3]], [0.1, 0.1], decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys_full._rhs(0, xeq, ueq)[-4:], np.zeros((4,)), decimal=5)

        # Fix one input and vary the other
        nlsys_full = ios.NonlinearIOSystem(pvtol_full, None)
        xeq, ueq, result = ios.find_eqpt(
            nlsys_full, [0, 0, 0, 0, 0, 0], [0.01, 4*9.8],
            y0=[0, 0, 0.1, 0.1, 0, 0], iy=[3], iu=[1],
            idx=[2, 3, 4, 5], ix=[0, 1], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_almost_equal(ueq[1], 4*9.8, decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys_full._out(0, xeq, ueq)[[3]], [0.1], decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys_full._rhs(0, xeq, ueq)[-4:], np.zeros((4,)), decimal=5)

        # PVTOL with output = y velocity
        xeq, ueq, result = ios.find_eqpt(
            nlsys_full, [0, 0, 0, 0.1, 0, 0], [0.01, 4*9.8],
            y0=[0, 0, 0, 0.1, 0, 0], iy=[3],
            dx0=[0.1, 0, 0, 0, 0, 0], idx=[1, 2, 3, 4, 5],
            ix=[0, 1], return_result=True)
        self.assertTrue(result.success)
        np.testing.assert_array_almost_equal(
            nlsys_full._out(0, xeq, ueq)[-3:], [0.1, 0, 0], decimal=5)
        np.testing.assert_array_almost_equal(
            nlsys_full._rhs(0, xeq, ueq)[-5:], np.zeros((5,)), decimal=5)

        # Unobservable system
        linsys = ct.StateSpace(
            [[-1, 1], [0, -2]], [[0], [1]], [[0, 0]], [[0]])
        lnios = ios.LinearIOSystem(linsys)

        # If result is returned, user has to check
        xeq, ueq, result = ios.find_eqpt(
            lnios, [0, 0], [0], y0=[1], return_result=True)
        self.assertFalse(result.success)

        # If result is not returned, find_eqpt should return None
        xeq, ueq = ios.find_eqpt(lnios, [0, 0], [0], y0=[1])
        self.assertEqual(xeq, None)
        self.assertEqual(ueq, None)
Esempio n. 15
0
    def test_algebraic_loop(self):
        # Create some linear and nonlinear systems to play with
        linsys = self.siso_linsys
        lnios = ios.LinearIOSystem(linsys)
        nlios =  ios.NonlinearIOSystem(None, \
            lambda t, x, u, params: u*u, inputs=1, outputs=1)
        nlios1 = nlios.copy()
        nlios2 = nlios.copy()

        # Set up parameters for simulation
        T, U, X0 = self.T, self.U, self.X0

        # Single nonlinear system - no states 
        ios_t, ios_y = ios.input_output_response(nlios, T, U, X0)
        np.testing.assert_array_almost_equal(ios_y, U*U, decimal=3)

        # Composed nonlinear system (series)
        ios_t, ios_y = ios.input_output_response(nlios1 * nlios2, T, U, X0)
        np.testing.assert_array_almost_equal(ios_y, U**4, decimal=3)

        # Composed nonlinear system (parallel)
        ios_t, ios_y = ios.input_output_response(nlios1 + nlios2, T, U, X0)
        np.testing.assert_array_almost_equal(ios_y, 2*U**2, decimal=3)

        # Nonlinear system composed with LTI system (series)
        ios_t, ios_y = ios.input_output_response(
            nlios * lnios * nlios, T, U, X0)
        lti_t, lti_y, lti_x = ct.forced_response(linsys, T, U*U, X0)
        np.testing.assert_array_almost_equal(ios_y, lti_y*lti_y, decimal=3)

        # Nonlinear system in feeback loop with LTI system
        iosys = ios.InterconnectedSystem(
            (lnios, nlios),         # linear system w/ nonlinear feedback
            ((1,),                  # feedback interconnection (sig to 0)
             (0, (1, 0, -1))),
            0,                      # input to linear system
            0                       # output from linear system
        )
        ios_t, ios_y = ios.input_output_response(iosys, T, U, X0)
        # No easy way to test the result

        # Algebraic loop from static nonlinear system in feedback
        # (error will be due to no states)
        iosys = ios.InterconnectedSystem(
            (nlios1, nlios2),       # two copies of a static nonlinear system
            ((0, 1),                # feedback interconnection
             (1, (0, 0, -1))),
            0, 0
        )
        args = (iosys, T, U, X0)
        self.assertRaises(RuntimeError, ios.input_output_response, *args)

        # Algebraic loop due to feedthrough term
        linsys = ct.StateSpace(
            [[-1, 1], [0, -2]], [[0], [1]], [[1, 0]], [[1]])
        lnios = ios.LinearIOSystem(linsys)
        iosys = ios.InterconnectedSystem(
            (nlios, lnios),         # linear system w/ nonlinear feedback
            ((0, 1),                # feedback interconnection
             (1, (0, 0, -1))),
            0, 0
        )
        args = (iosys, T, U, X0)
        # ios_t, ios_y = ios.input_output_response(iosys, T, U, X0)
        self.assertRaises(RuntimeError, ios.input_output_response, *args)
Esempio n. 16
0
 def test_iosys_unspecified(self):
     # System with unspecified inputs and outputs
     sys = ios.NonlinearIOSystem(secord_update, secord_output)
     np.testing.assert_raises(TypeError, sys.__mul__, sys)