def __init__(self, *args, **kwords): """@brief Based on scipy.signal lti class init. Initialize the LTI system using either: - ('string to .mat file containing disSys') - (numerator, denominator) - (zeros, poles, gain) - (A, B, C, D) : state-space. - (A, B, C, D, Ts) : discrete-time state-space @pre .mat files are assumed to contain a discrete-time state-space object disSys which is a MATLAB structure, i.e not the new style MATLAB lti class. To convert to a struct in MATLAB simply use disSys = struct(MATLAB_SS_object) before saving the .mat file. @details the string to the .mat file is the absolute filename without the .mat extension. """ N = len(args) if N == 1: # Assert the file exists assert os.path.isfile(args[0] + '.mat'), \ IOError("File doesn't exist") # Save the path for later self._matPath = args[0] # extract discrete system matrices Dict = loadmat(args[0], variable_names = ['disSys','T']) disSys = Dict['disSys'][0,0] sysMat = [disSys['a'],disSys['b'],disSys['c'],disSys['d']] self._A, self._B, self._C, self._D = abcd_normalize(*sysMat) self._Ts = disSys["Ts"][0,0] #"Ts" is 2-D array for some reason! self.inputs = self.B.shape[-1] self.outputs = self.C.shape[0] self._isDiscrete = True self._T = np.array(Dict['T']) #self._updateDiscrete() elif N <= 4: super(StateSpace, self).__init__(*args, **kwords) elif N == 5: self._A, self._B, self._C, self._D = abcd_normalize(*args[0:4]) # Check Ts is positive. if args[4] <= 0.0: raise ValueError("Ts must be positive") self._Ts = args[4] self.inputs = self.B.shape[-1] self.outputs = self.C.shape[0] self._isDiscrete = True #self._updateDiscrete() else: raise ValueError("Needs 2, 3, 4, or 5 arguments.")
def test_shapes(self): A, B, C, D = abcd_normalize(self.A, self.B, [1, 0], 0) assert_equal(A.shape[0], A.shape[1]) assert_equal(A.shape[0], B.shape[0]) assert_equal(A.shape[0], C.shape[1]) assert_equal(C.shape[0], D.shape[0]) assert_equal(B.shape[1], D.shape[1])
def test_missing_AB(self): A, B, C, D = abcd_normalize(C=self.C, D=self.D) assert_equal(A.shape[0], A.shape[1]) assert_equal(A.shape[0], B.shape[0]) assert_equal(B.shape[1], D.shape[1]) assert_equal(A.shape, (self.C.shape[1], self.C.shape[1])) assert_equal(B.shape, (self.C.shape[1], self.D.shape[1]))
def test_missing_BC(self): A, B, C, D = abcd_normalize(A=self.A, D=self.D) assert_equal(B.shape[0], A.shape[0]) assert_equal(B.shape[1], D.shape[1]) assert_equal(C.shape[0], D.shape[0]) assert_equal(C.shape[1], A.shape[0]) assert_equal(B.shape, (self.A.shape[0], self.D.shape[1])) assert_equal(C.shape, (self.D.shape[0], self.A.shape[0]))
def test_missing_AD(self): A, B, C, D = abcd_normalize(B=self.B, C=self.C) assert_equal(A.shape[0], A.shape[1]) assert_equal(A.shape[0], B.shape[0]) assert_equal(D.shape[0], C.shape[0]) assert_equal(D.shape[1], B.shape[1]) assert_equal(A.shape, (self.B.shape[0], self.B.shape[0])) assert_equal(D.shape, (self.C.shape[0], self.B.shape[1]))
def test_zero_dimension_is_not_none1(self): B_ = np.zeros((2, 0)) D_ = np.zeros((0, 0)) A, B, C, D = abcd_normalize(A=self.A, B=B_, D=D_) assert_equal(A, self.A) assert_equal(B, B_) assert_equal(D, D_) assert_equal(C.shape[0], D_.shape[0]) assert_equal(C.shape[1], self.A.shape[0])
def test_zero_dimension_is_not_none2(self): B_ = np.zeros((2, 0)) C_ = np.zeros((0, 2)) A, B, C, D = abcd_normalize(A=self.A, B=B_, C=C_) assert_equal(A, self.A) assert_equal(B, B_) assert_equal(C, C_) assert_equal(D.shape[0], C_.shape[0]) assert_equal(D.shape[1], B_.shape[1])
def canonical(sys, controllable=True): """Converts SISO to controllable/observable canonical form.""" # TODO: raise nicer error if not SISO sys = LinearSystem(sys) ss = abcd_normalize(*sys.ss) if not _is_ccf(*ss): # TODO: if already observable than this might hurt the accuracy ss = sys2ss(sys2tf(ss)) assert _is_ccf(*ss) if not controllable: ss = (ss[0].T, ss[2].T, ss[1].T, ss[3]) return LinearSystem(ss, sys.analog)
def test_normalized_matrices_unchanged(self): A, B, C, D = abcd_normalize(self.A, self.B, self.C, self.D) assert_equal(A, self.A) assert_equal(B, self.B) assert_equal(C, self.C) assert_equal(D, self.D)
def test_missing_B(self): A, B, C, D = abcd_normalize(A=self.A, C=self.C, D=self.D) assert_equal(B.shape[0], A.shape[0]) assert_equal(B.shape[1], D.shape[1]) assert_equal(B.shape, (self.A.shape[0], self.D.shape[1]))
def test_missing_A(self): A, B, C, D = abcd_normalize(B=self.B, C=self.C, D=self.D) assert_equal(A.shape[0], A.shape[1]) assert_equal(A.shape[0], B.shape[0]) assert_equal(A.shape, (self.B.shape[0], self.B.shape[0]))
def test_missing_D(self): A, B, C, D = abcd_normalize(A=self.A, B=self.B, C=self.C) assert_equal(D.shape[0], C.shape[0]) assert_equal(D.shape[1], B.shape[1]) assert_equal(D.shape, (self.C.shape[0], self.B.shape[1]))