def test_connect(self): # Define a couple of (linear) systems to interconnection linsys1 = self.siso_linsys iosys1 = ios.LinearIOSystem(linsys1) linsys2 = self.siso_linsys iosys2 = ios.LinearIOSystem(linsys2) # Connect systems in different ways and compare to StateSpace linsys_series = linsys2 * linsys1 iosys_series = ios.InterconnectedSystem( (iosys1, iosys2), # systems ((1, 0),), # interconnection (series) 0, # input = first system 1 # output = second system ) # Run a simulation and compare to linear response T, U = self.T, self.U X0 = np.concatenate((self.X0, self.X0)) ios_t, ios_y, ios_x = ios.input_output_response( iosys_series, T, U, X0, return_x=True) lti_t, lti_y, lti_x = ct.forced_response(linsys_series, 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) # Connect systems with different timebases linsys2c = self.siso_linsys linsys2c.dt = 0 # Reset the timebase iosys2c = ios.LinearIOSystem(linsys2c) iosys_series = ios.InterconnectedSystem( (iosys1, iosys2c), # systems ((1, 0),), # interconnection (series) 0, # input = first system 1 # output = second system ) self.assertTrue(ct.isctime(iosys_series, strict=True)) ios_t, ios_y, ios_x = ios.input_output_response( iosys_series, T, U, X0, return_x=True) lti_t, lti_y, lti_x = ct.forced_response(linsys_series, 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) # Feedback interconnection linsys_feedback = ct.feedback(linsys1, linsys2) iosys_feedback = ios.InterconnectedSystem( (iosys1, iosys2), # systems ((1, 0), # input of sys2 = output of sys1 (0, (1, 0, -1))), # input of sys1 = -output of sys2 0, # input = first system 0 # output = first system ) ios_t, ios_y, ios_x = ios.input_output_response( iosys_feedback, T, U, X0, return_x=True) lti_t, lti_y, lti_x = ct.forced_response(linsys_feedback, 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)
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)
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)