Ejemplo n.º 1
0
    def test_multioutput(self):
        # Regression test for gh-2669.

        # 4 states
        A = np.array([[-1.0, 0.0, 1.0, 0.0], [-1.0, 0.0, 2.0, 0.0],
                      [-4.0, 0.0, 3.0, 0.0], [-8.0, 8.0, 0.0, 4.0]])

        # 1 input
        B = np.array([[0.3], [0.0], [7.0], [0.0]])

        # 3 outputs
        C = np.array([[0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0],
                      [8.0, 8.0, 0.0, 0.0]])

        D = np.array([[0.0], [0.0], [1.0]])

        # Get the transfer functions for all the outputs in one call.
        b_all, a = ss2tf(A, B, C, D)

        # Get the transfer functions for each output separately.
        b0, a0 = ss2tf(A, B, C[0], D[0])
        b1, a1 = ss2tf(A, B, C[1], D[1])
        b2, a2 = ss2tf(A, B, C[2], D[2])

        # Check that we got the same results.
        assert_allclose(a0, a, rtol=1e-13)
        assert_allclose(a1, a, rtol=1e-13)
        assert_allclose(a2, a, rtol=1e-13)
        assert_allclose(b_all, np.vstack((b0, b1, b2)), rtol=1e-13, atol=1e-14)
Ejemplo n.º 2
0
    def test_simo_round_trip(self):
        # See gh-5753
        tf = ([[1, 2], [1, 1]], [1, 2])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-2]], rtol=1e-13)
        assert_allclose(B, [[1]], rtol=1e-13)
        assert_allclose(C, [[0], [-1]], rtol=1e-13)
        assert_allclose(D, [[1], [1]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[1, 2], [1, 1]], rtol=1e-13)
        assert_allclose(den, [1, 2], rtol=1e-13)

        tf = ([[1, 0, 1], [1, 1, 1]], [1, 1, 1])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-1, -1], [1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0]], rtol=1e-13)
        assert_allclose(C, [[-1, 0], [0, 0]], rtol=1e-13)
        assert_allclose(D, [[1], [1]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[1, 0, 1], [1, 1, 1]], rtol=1e-13)
        assert_allclose(den, [1, 1, 1], rtol=1e-13)

        tf = ([[1, 2, 3], [1, 2, 3]], [1, 2, 3, 4])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-2, -3, -4], [1, 0, 0], [0, 1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0], [0]], rtol=1e-13)
        assert_allclose(C, [[1, 2, 3], [1, 2, 3]], rtol=1e-13)
        assert_allclose(D, [[0], [0]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[0, 1, 2, 3], [0, 1, 2, 3]], rtol=1e-13)
        assert_allclose(den, [1, 2, 3, 4], rtol=1e-13)

        tf = ([1, [2, 3]], [1, 6])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-6]], rtol=1e-31)
        assert_allclose(B, [[1]], rtol=1e-31)
        assert_allclose(C, [[1], [-9]], rtol=1e-31)
        assert_allclose(D, [[0], [2]], rtol=1e-31)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[0, 1], [2, 3]], rtol=1e-13)
        assert_allclose(den, [1, 6], rtol=1e-13)

        tf = ([[1, -3], [1, 2, 3]], [1, 6, 5])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-6, -5], [1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0]], rtol=1e-13)
        assert_allclose(C, [[1, -3], [-4, -2]], rtol=1e-13)
        assert_allclose(D, [[0], [1]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[0, 1, -3], [1, 2, 3]], rtol=1e-13)
        assert_allclose(den, [1, 6, 5], rtol=1e-13)
Ejemplo n.º 3
0
    def test_simo_round_trip(self):
        # See gh-5753
        tf = ([[1, 2], [1, 1]], [1, 2])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-2]], rtol=1e-13)
        assert_allclose(B, [[1]], rtol=1e-13)
        assert_allclose(C, [[0], [-1]], rtol=1e-13)
        assert_allclose(D, [[1], [1]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[1, 2], [1, 1]], rtol=1e-13)
        assert_allclose(den, [1, 2], rtol=1e-13)

        tf = ([[1, 0, 1], [1, 1, 1]], [1, 1, 1])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-1, -1], [1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0]], rtol=1e-13)
        assert_allclose(C, [[-1, 0], [0, 0]], rtol=1e-13)
        assert_allclose(D, [[1], [1]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[1, 0, 1], [1, 1, 1]], rtol=1e-13)
        assert_allclose(den, [1, 1, 1], rtol=1e-13)

        tf = ([[1, 2, 3], [1, 2, 3]], [1, 2, 3, 4])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-2, -3, -4], [1, 0, 0], [0, 1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0], [0]], rtol=1e-13)
        assert_allclose(C, [[1, 2, 3], [1, 2, 3]], rtol=1e-13)
        assert_allclose(D, [[0], [0]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[0, 1, 2, 3], [0, 1, 2, 3]], rtol=1e-13)
        assert_allclose(den, [1, 2, 3, 4], rtol=1e-13)

        tf = ([1, [2, 3]], [1, 6])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-6]], rtol=1e-31)
        assert_allclose(B, [[1]], rtol=1e-31)
        assert_allclose(C, [[1], [-9]], rtol=1e-31)
        assert_allclose(D, [[0], [2]], rtol=1e-31)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[0, 1], [2, 3]], rtol=1e-13)
        assert_allclose(den, [1, 6], rtol=1e-13)

        tf = ([[1, -3], [1, 2, 3]], [1, 6, 5])
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[-6, -5], [1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0]], rtol=1e-13)
        assert_allclose(C, [[1, -3], [-4, -2]], rtol=1e-13)
        assert_allclose(D, [[0], [1]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[0, 1, -3], [1, 2, 3]], rtol=1e-13)
        assert_allclose(den, [1, 6, 5], rtol=1e-13)
Ejemplo n.º 4
0
    def to_tf(self, iu, iy):
        """Return a transfer function given input and output names.

        **Parameters:**

        - *iu*: Index or name of the input

             This must be specified unless the system has only one input.

        - *iy*: Index or name of the output

             This must be specified unless the system has only one output.

        **Example:**

        >>> lin = LinRes('examples/PID.mat')
        >>> lin.to_tf()
        (array([[  11.,  102.,  200.]]), array([   1.,  100.,    0.]))
        """
        # Return the TF.
        return ss2tf(self.sys.A,
                     self.sys.B,
                     self.sys.C[iy, :],
                     self.sys.D[iy, :],
                     input=iu)
Ejemplo n.º 5
0
def makeLGS(filt, transposed=False):
    """
	Factory function to make a LGS Realization

	Option
	- transposed: (boolean) indicates if the realization is transposed

	Returns
	- a dictionary of necessary infos to build the Realization
	"""

    # We compute (Phi,K,L,D) from the initial state-space
    (Phi, K, L, D) = PhiKLD(filt.dSS)
    num, den = signal.ss2tf(Phi, K, L, D)

    # We compute alphas with JSS-transformation
    alpha = JSS_trans(den)

    # We compute the PhiKLD_in
    (Phi_in, K_in, L_in, D) = PhiKLD_in(alpha, Phi, K, L, D)

    # We can compute the (A_in, B_in, C_in, d) abd tge A_in decomposition
    (A_in, B_in, C_in, d) = ABCd_in(Phi_in, K_in, L_in, D)

    Ad = A_decomposition_LGS(alpha, Phi_in)

    # Then, we deduce J to S matrices
    JtoS = Matrice_JtoS_LGS(Ad, A_in, B_in, C_in, d)

    # TODO: use transposed ???

    # return useful infos to build the Realization
    return {"JtoS": JtoS}
Ejemplo n.º 6
0
def ss_to_zpk(A, B, C):
    """Convert a state-space system to sets of Zero-Pole-Gain objects.

    Parameters
    ----------
    A: (n,n) array_like
        State-space dynamics matrix
    B: (n,m) array_like
        Input matrix.
    C: (n,m) array_like
        Output matrix
    """
    zpks = []
    for im in range(B.shape[1]):
        zpks.append([])
        for ip in range(C.shape[0]):
            try:
                num, den = signal.ss2tf(
                    A, B[:, im].reshape((-1, 1)),
                    C[ip, :].reshape((1, -1)), np.zeros((1, 1)))
                nu2 = num

                # strip leading (close to zeros) from num
                while np.allclose(nu2[:, 0], 0, 1e-14) and \
                        nu2.shape[-1] > 1:
                    nu2 = nu2[:, 1:]

                # to zpk
                z, p, k = signal.tf2zpk(nu2, den)
                zpks[-1].append(ZPK(z, p, k))
            except ValueError:
                raise RuntimeWarning("cannot analyse state-space")
    return zpks
Ejemplo n.º 7
0
 def test_all_int_arrays(self):
     A = [[0, 1, 0], [0, 0, 1], [-3, -4, -2]]
     B = [[0], [0], [1]]
     C = [[5, 1, 0]]
     D = [[0]]
     num, den = ss2tf(A, B, C, D)
     assert_allclose(num, [[0.0, 0.0, 1.0, 5.0]], rtol=1e-13, atol=1e-14)
     assert_allclose(den, [1.0, 2.0, 4.0, 3.0], rtol=1e-13)
Ejemplo n.º 8
0
 def __init__(self, *args):
     if len(args) not in [2, 4]:
         raise ValueError("2 (num, den) or 4 (A, B, C, D) arguments "
                          "expected, not {}.".format((len(args))))
     if len(args) == 2:
         super().__init__(args[0], args[1])
     else:
         A, B, C, D = args
         n, d = signal.ss2tf(A, B, C, D)
         super().__init__(n, d)
Ejemplo n.º 9
0
 def H_s(self,num, type):
     ABCD = cir.Circuit.StateSpace(self, num, type)
     HStp=ss2tf(ABCD[0],ABCD[1],ABCD[2],ABCD[3])
     H1S_zn = np.zeros(len(HStp[1]) + 1)
     for i in range(len(HStp[1])):
         H1S_zn[i] = HStp[1][i]
     H1S = HStp[0][0], H1S_zn
     HS = HStp[0][0], HStp[1]
     # Возвращает H(s), H1(s)
     return HS, H1S,ABCD
Ejemplo n.º 10
0
    def to_dTF(self):
        """
		Transform a SISO state-space into a transfer function
		"""
        if self._p != 1 or self._q != 1:
            raise ValueError(
                'dSS: the state-space must be SISO to be converted in transfer function'
            )
        from fixif.LTI import dTF
        num, den = ss2tf(self._A, self._B, self._C, self._D)
        return dTF(num[0], den)
Ejemplo n.º 11
0
    def test_gbt_with_sio_tf_and_zpk(self):
        """Test method='gbt' with alpha=0.25 for tf and zpk cases."""
        # State space coefficients for the continuous SIO system.
        A = -1.0
        B = 1.0
        C = 1.0
        D = 0.5

        # The continuous transfer function coefficients.
        cnum, cden = ss2tf(A, B, C, D)

        # Continuous zpk representation
        cz, cp, ck = ss2zpk(A, B, C, D)

        h = 1.0
        alpha = 0.25

        # Explicit formulas, in the scalar case.
        Ad = (1 + (1 - alpha) * h * A) / (1 - alpha * h * A)
        Bd = h * B / (1 - alpha * h * A)
        Cd = C / (1 - alpha * h * A)
        Dd = D + alpha * C * Bd

        # Convert the explicit solution to tf
        dnum, dden = ss2tf(Ad, Bd, Cd, Dd)

        # Compute the discrete tf using cont2discrete.
        c2dnum, c2dden, dt = d2c((cnum, cden), h, method='gbt', alpha=alpha)

        assert_allclose(dnum, c2dnum)
        assert_allclose(dden, c2dden)

        # Convert explicit solution to zpk.
        dz, dp, dk = ss2zpk(Ad, Bd, Cd, Dd)

        # Compute the discrete zpk using cont2discrete.
        c2dz, c2dp, c2dk, dt = d2c((cz, cp, ck), h, method='gbt', alpha=alpha)

        assert_allclose(dz, c2dz)
        assert_allclose(dp, c2dp)
        assert_allclose(dk, c2dk)
    def test_gbt_with_sio_tf_and_zpk(self):
        """Test method='gbt' with alpha=0.25 for tf and zpk cases."""
        # State space coefficients for the continuous SIO system.
        A = -1.0
        B = 1.0
        C = 1.0
        D = 0.5

        # The continuous transfer function coefficients.
        cnum, cden = ss2tf(A, B, C, D)

        # Continuous zpk representation
        cz, cp, ck = ss2zpk(A, B, C, D)

        h = 1.0
        alpha = 0.25

        # Explicit formulas, in the scalar case.
        Ad = (1 + (1 - alpha) * h * A) / (1 - alpha * h * A)
        Bd = h * B / (1 - alpha * h * A)
        Cd = C / (1 - alpha * h * A)
        Dd = D + alpha * C * Bd

        # Convert the explicit solution to tf
        dnum, dden = ss2tf(Ad, Bd, Cd, Dd)

        # Compute the discrete tf using cont2discrete.
        c2dnum, c2dden, dt = c2d((cnum, cden), h, method='gbt', alpha=alpha)

        assert_allclose(dnum, c2dnum)
        assert_allclose(dden, c2dden)

        # Convert explicit solution to zpk.
        dz, dp, dk = ss2zpk(Ad, Bd, Cd, Dd)

        # Compute the discrete zpk using cont2discrete.
        c2dz, c2dp, c2dk, dt = c2d((cz, cp, ck), h, method='gbt', alpha=alpha)

        assert_allclose(dz, c2dz)
        assert_allclose(dp, c2dp)
        assert_allclose(dk, c2dk)
Ejemplo n.º 13
0
def _ss2tf(A, B, C, D):
    # https://github.com/scipy/scipy/issues/5760
    if not (len(A) or len(B) or len(C)):
        D = np.asarray(D).flatten()
        if len(D) != 1:
            raise ValueError("D must be scalar for zero-order models")
        return (D[0], 1.)  # pragma: no cover; solved in scipy>=0.18rc2
    nums, den = ss2tf(A, B, C, D)
    if len(nums) != 1:
        # TODO: support MIMO systems
        # https://github.com/scipy/scipy/issues/5753
        raise NotImplementedError("System must be SISO")
    return nums[0], den
Ejemplo n.º 14
0
    def test_zero_order_round_trip(self):
        # See gh-5760
        tf = (2, 1)
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[0]], rtol=1e-13)
        assert_allclose(B, [[0]], rtol=1e-13)
        assert_allclose(C, [[0]], rtol=1e-13)
        assert_allclose(D, [[2]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[2, 0]], rtol=1e-13)
        assert_allclose(den, [1, 0], rtol=1e-13)

        tf = ([[5], [2]], 1)
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[0]], rtol=1e-13)
        assert_allclose(B, [[0]], rtol=1e-13)
        assert_allclose(C, [[0], [0]], rtol=1e-13)
        assert_allclose(D, [[5], [2]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[5, 0], [2, 0]], rtol=1e-13)
        assert_allclose(den, [1, 0], rtol=1e-13)
Ejemplo n.º 15
0
    def test_basic(self):
        # Test a round trip through tf2ss and ss2tf.
        b = np.array([1.0, 3.0, 5.0])
        a = np.array([1.0, 2.0, 3.0])

        A, B, C, D = tf2ss(b, a)
        assert_allclose(A, [[-2, -3], [1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0]], rtol=1e-13)
        assert_allclose(C, [[1, 2]], rtol=1e-13)
        assert_allclose(D, [[1]], rtol=1e-14)

        bb, aa = ss2tf(A, B, C, D)
        assert_allclose(bb[0], b, rtol=1e-13)
        assert_allclose(aa, a, rtol=1e-13)
Ejemplo n.º 16
0
    def test_basic(self):
        # Test a round trip through tf2ss and ss2tf.
        b = np.array([1.0, 3.0, 5.0])
        a = np.array([1.0, 2.0, 3.0])

        A, B, C, D = tf2ss(b, a)
        assert_allclose(A, [[-2, -3], [1, 0]], rtol=1e-13)
        assert_allclose(B, [[1], [0]], rtol=1e-13)
        assert_allclose(C, [[1, 2]], rtol=1e-13)
        assert_allclose(D, [[1]], rtol=1e-14)

        bb, aa = ss2tf(A, B, C, D)
        assert_allclose(bb[0], b, rtol=1e-13)
        assert_allclose(aa, a, rtol=1e-13)
Ejemplo n.º 17
0
    def test_zero_order_round_trip(self):
        # See gh-5760
        tf = (2, 1)
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[0]], rtol=1e-13)
        assert_allclose(B, [[0]], rtol=1e-13)
        assert_allclose(C, [[0]], rtol=1e-13)
        assert_allclose(D, [[2]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[2, 0]], rtol=1e-13)
        assert_allclose(den, [1, 0], rtol=1e-13)

        tf = ([[5], [2]], 1)
        A, B, C, D = tf2ss(*tf)
        assert_allclose(A, [[0]], rtol=1e-13)
        assert_allclose(B, [[0]], rtol=1e-13)
        assert_allclose(C, [[0], [0]], rtol=1e-13)
        assert_allclose(D, [[5], [2]], rtol=1e-13)

        num, den = ss2tf(A, B, C, D)
        assert_allclose(num, [[5, 0], [2, 0]], rtol=1e-13)
        assert_allclose(den, [1, 0], rtol=1e-13)
Ejemplo n.º 18
0
    def test_multioutput(self):
        # Regression test for gh-2669.

        # 4 states
        A = np.array([[-1.0, 0.0, 1.0, 0.0],
                      [-1.0, 0.0, 2.0, 0.0],
                      [-4.0, 0.0, 3.0, 0.0],
                      [-8.0, 8.0, 0.0, 4.0]])

        # 1 input
        B = np.array([[0.3],
                      [0.0],
                      [7.0],
                      [0.0]])

        # 3 outputs
        C = np.array([[0.0, 1.0, 0.0, 0.0],
                      [0.0, 0.0, 0.0, 1.0],
                      [8.0, 8.0, 0.0, 0.0]])

        D = np.array([[0.0],
                      [0.0],
                      [1.0]])

        # Get the transfer functions for all the outputs in one call.
        b_all, a = ss2tf(A, B, C, D)

        # Get the transfer functions for each output separately.
        b0, a0 = ss2tf(A, B, C[0], D[0])
        b1, a1 = ss2tf(A, B, C[1], D[1])
        b2, a2 = ss2tf(A, B, C[2], D[2])

        # Check that we got the same results.
        assert_allclose(a0, a, rtol=1e-13)
        assert_allclose(a1, a, rtol=1e-13)
        assert_allclose(a2, a, rtol=1e-13)
        assert_allclose(b_all, np.vstack((b0, b1, b2)), rtol=1e-13, atol=1e-14)
Ejemplo n.º 19
0
def _ss2tf(A, B, C, D):
    # https://github.com/scipy/scipy/issues/5760
    if not (len(A) or len(B) or len(C)):
        D = np.asarray(D).flatten()
        if len(D) != 1:
            raise ValueError("D must be scalar for zero-order models")
        return (D[0], 1.)  # pragma: no cover; solved in scipy>=0.18rc2
    nums, den = ss2tf(A, B, C, D)
    if len(nums) != 1:
        # TODO: support MIMO/SIMO/MISO systems
        # https://github.com/scipy/scipy/issues/5753
        raise NotImplementedError("System (%s, %s, %s, %s) must be SISO to "
                                  "convert to transfer function" %
                                  (A, B, C, D))
    return nums[0], den
Ejemplo n.º 20
0
def ss2tf(ss, u_index, y_index):
    """
    Compute the transfer function of a given input and output of a state-space
    """
    nums, den = signal.ss2tf(ss.A, ss.B, ss.C, ss.D, u_index)

    num = nums[y_index]

    tf = TransferFunction(num, den)

    tf.name = (ss.output_label[y_index] + '/' + ss.input_label[u_index] +
               ' transfer function of ' + ss.name)

    tf.output_label[0] = ss.output_label[y_index]
    tf.output_units[0] = ss.output_units[y_index]
    tf.input_label[0] = ss.input_label[u_index]
    tf.input_units[0] = ss.input_units[u_index]

    return tf
Ejemplo n.º 21
0
    def convert2TF(self):
        '''
        Returns
        -------
        TYPE TransferFunction object
            DESCRIPTION. Convert SS model to TF model

        '''
        
        num_coef, den_coef = signal.ss2tf(self.A, self.B, self.C, self.D)
        if np.rank(num_coef) == 1:
            self.tf = TransferFunction(num_coef, den_coef)
            return self.tf
            
            
        elif np.rank(num_coef) == 2:
            self.tfs = []
            for i in range(len(num_coef)):
                self.tfs.append(TransferFunction(num_coef[i], den_coef))
            return self.tfs
Ejemplo n.º 22
0
def makeLCW(filt, transposed=False):
    """Retourne la forme SIF de la structure LCW correspondant au filtre donné"""
    # Par la fonction de scipy.signal on obtient le state-space associé
    # On calcule ensuite (Phi,K,L,D) qu'on reconverti en fonction de transfert
    (Phi, K, L, D) = PhiKLD(filt.dSS)
    num, den = signal.ss2tf(Phi, K, L, D)
    # On calcule les alpha par la JSS-transformation
    alpha = JSS_trans(den)
    # On calcule les PhiKLD_in
    (Phi_in, K_in, L_in, D) = PhiKLD_in(alpha, Phi, K, L, D)
    # On peut calculer les (A,B,C,d)_in et la
    # décomposition de A_in en produit de matrice.
    (A_ib, B_ib, C_ib, d) = ABCd_in(Phi_in, K_in, L_in, D)
    (As, Bs, Cs, d) = ABCd_star(A_ib, B_ib, C_ib, d, Phi_in, K_in)
    Ad = A_decomposition_LCW(alpha, Phi_in)
    # On construit les matrices qui forment Z
    JtoS = Matrice_JtoS_LCW(Ad, As, Bs, Cs, d)
    # TODO: use transposed ???

    # return useful infos to build the Realization
    return {"JtoS": JtoS}
Ejemplo n.º 23
0
    def to_tf(self, iu, iy):
        """Return a transfer function given input and output names.

        **Parameters:**

        - *iu*: Index or name of the input

             This must be specified unless the system has only one input.

        - *iy*: Index or name of the output

             This must be specified unless the system has only one output.

        **Example:**

        >>> lin = LinRes('examples/PID.mat')
        >>> lin.to_tf()
        (array([[  11.,  102.,  200.]]), array([   1.,  100.,    0.]))
        """
        # Return the TF.
        return ss2tf(self.sys.A, self.sys.B,
                     self.sys.C[iy, :], self.sys.D[iy, :], input=iu)
Ejemplo n.º 24
0
def form_PI_cl(data):
    A = np.array([[1.0]])
    B = np.array([[1.0]])
    for i in range(N):
        C = np.array([[dt*data['Ki_fit'][i]]])
        D = np.array([[data['Kp_fit'][i]]])
        pi_block = ss(A, B, C, D)
        bike_block = ss(data['A_cl'][i], data['B_cl'][i], data['C_cl'][i], 0)
        pc = series(pi_block, bike_block)
        cl = feedback(pc, 1, sign=-1)

        data['yr_cl_evals'][i] = la.eigvals(cl.A)
        assert(np.all(abs(data['yr_cl_evals'][i]) < 1.0))
        data['A_yr_cl'][i] = cl.A
        data['B_yr_cl'][i] = cl.B
        data['C_yr_cl'][i] = cl.C
        assert(cl.D == 0)

        num, den = ss2tf(cl.A, cl.B, cl.C, cl.D)
        data['w_psi_r_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_psi_r_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_psi_r_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_psi_r_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi
Ejemplo n.º 25
0
def form_PI_cl(data):
    A = np.array([[1.0]])
    B = np.array([[1.0]])
    for i in range(N):
        C = np.array([[dt * data['Ki_fit'][i]]])
        D = np.array([[data['Kp_fit'][i]]])
        pi_block = ss(A, B, C, D)
        bike_block = ss(data['A_cl'][i], data['B_cl'][i], data['C_cl'][i], 0)
        pc = series(pi_block, bike_block)
        cl = feedback(pc, 1, sign=-1)

        data['yr_cl_evals'][i] = la.eigvals(cl.A)
        assert (np.all(abs(data['yr_cl_evals'][i]) < 1.0))
        data['A_yr_cl'][i] = cl.A
        data['B_yr_cl'][i] = cl.B
        data['C_yr_cl'][i] = cl.C
        assert (cl.D == 0)

        num, den = ss2tf(cl.A, cl.B, cl.C, cl.D)
        data['w_psi_r_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_psi_r_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_psi_r_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_psi_r_to_psi_dot'][i] = np.unwrap(
            np.angle(y)) * 180.0 / np.pi
#Matriz C
C = np.array([[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0],
              [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]])

#Matriz D
D = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]])

################################################
################################################
#Calculo das variables e funcions de transferencia

#Sistema e funcions de transferencia

sys = signal.lti(A, B, C, D)
num1, den1 = signal.ss2tf(A, B, C, D, 0)
num2, den2 = signal.ss2tf(A, B, C, D, 1)
num3, den3 = signal.ss2tf(A, B, C, D, 2)

transf_11 = cnt.tf(num1[0, :], den1)
transf_12 = cnt.tf(num1[1, :], den1)
transf_13 = cnt.tf(num1[2, :], den1)

transf_21 = cnt.tf(num2[0, :], den2)
transf_22 = cnt.tf(num2[1, :], den2)
transf_23 = cnt.tf(num2[2, :], den2)

transf_31 = cnt.tf(num3[0, :], den3)
transf_32 = cnt.tf(num3[1, :], den3)
transf_33 = cnt.tf(num3[2, :], den3)
Ejemplo n.º 27
0
def calculateQTF(ABCDr):
    """Calculate noise and signal transfer functions for a quadrature modulator

    **Parameters:**

    ABCDr : ndarray
        The ABCD matrix, in real form. You may call :func:`mapQtoR` to convert
        an imaginary (quadrature) ABCD matrix to a real one.

    **Returns:**

    ntf, stf, intf, istf : tuple of zpk tuples
        The quadrature noise and signal transfer functions.

    :raises RuntimeError: if the supplied ABCD matrix results in denominator mismatches.
    """
    A, B, C, D = partitionABCD(ABCDr, 4)

    #Construct an ABCD description of the closed-loop system
    # sys is a tuple in A, B, C, D form
    Acl = A + np.dot(B[:, 2:4], C)
    Bcl = B
    Ccl = C
    Dcl = np.hstack((D[:, 0:2], np.eye(2)))
    #sys = (A + np.dot(B[:, 2:4], C), B, C,
    #       np.hstack((D[:, 0:2], np.eye(2))))

    #Calculate the 2x4 matrix of transfer functions
    tfs = np.empty((2, 4), dtype=object)
    # Each tf is a tuple in num, den form
    # tf[i, j] corresponds to the TF from input j to output i
    for i in range(2):
        for j in range(4):
            tfs[i, j] = ss2tf(Acl, Bcl, Ccl[i, :], Dcl[i, :], input=j)

    #Reduce these to NTF, STF, INTF and ISTF
    if any(tfs[0, 2][1] != tfs[1, 3][1]):
        raise RuntimeError('TF Denominator mismatch. Location 1')

    ntf_x = (0.5 * (tfs[0, 2][0] + tfs[1, 3][0]), tfs[0, 2][1])
    intf_x = (0.5 * (tfs[0, 2][0] - tfs[1, 3][0]), tfs[0, 2][1])

    if any(tfs[0, 3][1] != tfs[1, 2][1]):
        raise RuntimeError('TF Denominator mismatch. Location 2')

    ntf_y = (0.5 * (tfs[1, 2][0] - tfs[0, 3][0]), tfs[1, 2][1])
    intf_y = (0.5 * (tfs[1, 2][0] + tfs[0, 3][0]), tfs[1, 2][1])

    if any(ntf_x[1] != ntf_y[1]):
        raise RuntimeError('TF Denominator mismatch. Location 3')
    if any(tfs[0, 0][1] != tfs[1, 1][1]):
        raise RuntimeError('TF Denominator mismatch. Location 4')

    stf_x = (0.5 * (tfs[0, 0][0] + tfs[1, 1][0]), tfs[0, 0][1])
    istf_x = (0.5 * (tfs[0, 0][0] - tfs[1, 1][0]), tfs[0, 0][1])

    if any(tfs[0, 1][1] != tfs[1, 0][1]):
        raise RuntimeError('TF Denominator mismatch. Location 5')

    stf_y = (0.5 * (tfs[1, 0][0] - tfs[0, 1][0]), tfs[1, 0][1])
    istf_y = (0.5 * (tfs[1, 0][0] + tfs[0, 1][0]), tfs[1, 0][1])

    if any(stf_x[1] != stf_y[1]):
        raise RuntimeError('TF Denominator mismatch. Location 6')

    # suppress warnings about complex TFs
    #warning('off')
    ntf = cancelPZ(tf2zpk(ntf_x[0] + 1j * ntf_y[0], ntf_x[1]))
    intf = cancelPZ(tf2zpk(intf_x[0] + 1j * intf_y[0], intf_x[1]))
    stf = cancelPZ(tf2zpk(stf_x[0] + 1j * stf_y[0], ntf_x[1]))
    istf = cancelPZ(tf2zpk(istf_x[0] + 1j * istf_y[0], intf_x[1]))
    #warning('on')

    return ntf, stf, intf, istf
    def test_state_operators_1(self):
        #test the state space operators to see if they correspond to the correct transfer function

        success = True

        #position and field arguments
        n_f = 6
        n_r = 3
        n_x, n_y, n_z = map(int, np.random.randint(low=1, high=50, size=3))
        del_t = 1.0e-12

        #build random tensors
        inf_x = np.float32(np.random.rand(n_x, n_y, n_z))
        w_0 = np.float32(np.random.rand(n_x, n_y, n_z, n_f // 2, n_r)) * 10**12
        damp = 0.2 * w_0
        del_x = np.float32(np.random.rand(n_x, n_y, n_z, n_f // 2, n_r))

        #produce operators
        sta_ope, _ = ELECTRIC_DISPERSION_OPERATORS(w_0, damp, del_x, del_t,
                                                   inf_x)
        a = sta_ope[0]
        b = sta_ope[1]
        c = sta_ope[2]
        d = sta_ope[3]

        #secondary constants
        beta = np.sqrt(w_0**2 - damp**2)
        A_e = np.exp(-damp * del_t) * np.cos(beta * del_t)
        B_e = np.exp(-damp * del_t) * np.sin(beta * del_t)
        K1 = del_x * (1 - 2 * A_e + A_e**2 + B_e**2)

        #primary constants
        a_1 = 2 * A_e
        a_2 = -(A_e**2 + B_e**2)
        b_1 = -2 * K1
        b_2 = 2 * K1

        #calculate the lorentz transfer function
        tran_num_coeff, tran_den_coeff = LORENTZ_TRANSFER_FUNCTION(
            a_1, a_2, b_1, b_2)

        with tf.Session() as sess:

            d = sess.run(d)
            c = sess.run(c)
            b = sess.run(b)
            a = sess.run(a)

            B = b[0, 0, 0, 0, :, np.newaxis]
            for i in range(len(b[0, 0, 0, 0, :])):
                B[i, 0] = b[0, 0, 0, 0, i]
            A = a[0, 0, 0, 0, :, :]
            C = [c[0, 0, 0, 0, :]]
            D = d[0, 0, 0, 0]

            numden = ss2tf(A, B, C, D)
            num = numden[0]
            den = numden[1]

            np.amax(num - tran_num_coeff[0, 0, 0, 0]) < 5.0e-7 and np.amax(
                den - tran_den_coeff[0, 0, 0, 0]) < 5.0e-7 and success

        self.assertEqual(success, True)
Ejemplo n.º 29
0
    def filter(self, *filt, **kwargs):
        """Apply the given filter to this `Spectrum`.

        Recognised filter arguments are converted into the standard
        ``(numerator, denominator)`` representation before being applied
        to this `Spectrum`.

        Parameters
        ----------
        *filt
            one of:

            - :class:`scipy.signal.lti`
            - ``(numerator, denominator)`` polynomials
            - ``(zeros, poles, gain)``
            - ``(A, B, C, D)`` 'state-space' representation

        Returns
        -------
        result : `Spectrum`
            the filtered version of the input `Spectrum`

        See also
        --------
        scipy.signal.zpk2tf
            for details on converting ``(zeros, poles, gain)`` into
            transfer function format
        scipy.signal.ss2tf
            for details on converting ``(A, B, C, D)`` to transfer function
            format
        scipy.signal.freqs
            for details on the filtering calculation

        Examples
        --------
        To apply a zpk filter with a pole at 0 Hz, a zero at 100 Hz and
        a gain of 25::

            >>> data2 = data.filter([100], [0], 25)

        Raises
        ------
        ValueError
            If ``filt`` arguments cannot be interpreted properly
        """
        # parse filter
        if len(filt) == 1 and isinstance(filt[0], signal.lti):
            filt = filt[0]
            a = filt.den
            b = filt.num
        elif len(filt) == 2:
            b, a = filt
        elif len(filt) == 3:
            b, a = signal.zpk2tf(*filt)
        elif len(filt) == 4:
            b, a = signal.ss2tf(*filt)
        else:
            raise ValueError("Cannot interpret filter arguments. Please give "
                             "either a signal.lti object, or a tuple in zpk "
                             "or ba format. See scipy.signal docs for "
                             "details.")
        # parse keyword args
        inplace = kwargs.pop('inplace', False)
        if kwargs:
            raise TypeError("Spectrum.filter() got an unexpected keyword "
                            "argument '%s'" % list(kwargs.keys())[0])
        fresp = abs(signal.freqs(b, a, self.frequencies * 2 * pi)[1])
        if inplace:
            self *= fresp
            return self
        else:
            new = self * fresp
            return new
Ejemplo n.º 30
0
    def filter(self, *filt):
        """Apply the given filter to this `TimeSeries`.

        All recognised filter arguments are converted either into cascading
        second-order sections (if scipy >= 0.16 is installed), or into the
        ``(numerator, denominator)`` representation before being applied
        to this `TimeSeries`.

        .. note::

           All filters are presumed to be digital (Z-domain), if you have
           an analog ZPK (in Hertz or in rad/s) you should be using
           `TimeSeries.zpk` instead.

        .. note::

           When using `scipy` < 0.16 some higher-order filters may be
           unstable. With `scipy` >= 0.16 higher-order filters are
           decomposed into second-order-sections, and so are much more stable.

        Parameters
        ----------
        *filt
            one of:

            - :class:`scipy.signal.lti`
            - `MxN` `numpy.ndarray` of second-order-sections
              (`scipy` >= 0.16 only)
            - ``(numerator, denominator)`` polynomials
            - ``(zeros, poles, gain)``
            - ``(A, B, C, D)`` 'state-space' representation

        Returns
        -------
        result : `TimeSeries`
            the filtered version of the input `TimeSeries`

        See also
        --------
        TimeSeries.zpk
            for instructions on how to filter using a ZPK with frequencies
            in Hertz
        scipy.signal.sosfilter
            for details on the second-order section filtering method
            (`scipy` >= 0.16 only)
        scipy.signal.lfilter
            for details on the filtering method

        Raises
        ------
        ValueError
            If ``filt`` arguments cannot be interpreted properly
        """
        sos = None
        # single argument given
        if len(filt) == 1:
            filt = filt[0]
            # detect LTI
            if isinstance(filt, signal.lti):
                filt = filt
                a = filt.den
                b = filt.num
            # detect SOS
            elif isinstance(filt, numpy.ndarray) and filt.ndim == 2:
                sos = filt
            # detect taps
            else:
                b = filt
                a = [1]
        # detect TF
        elif len(filt) == 2:
            b, a = filt
        elif len(filt) == 3:
            try:
                sos = signal.zpk2sos(*filt)
            except AttributeError:
                b, a = signal.zpk2tf(*filt)
        elif len(filt) == 4:
            try:
                zpk = signal.ss2zpk(*filt)
                sos = signal.zpk2sos(zpk)
            except AttributeError:
                b, a = signal.ss2tf(*filt)
        else:
            raise ValueError("Cannot interpret filter arguments. Please "
                             "give either a signal.lti object, or a "
                             "tuple in zpk or ba format. See "
                             "scipy.signal docs for details.")
        if sos is not None:
            new = signal.sosfilt(sos, self, axis=0).view(self.__class__)
        else:
            new = signal.lfilter(b, a, self, axis=0).view(self.__class__)
        new.__dict__ = self.copy_metadata()
        return new
             D_true,
             A_ML,
             B_ML,
             C_ML,
             D_ML,
             w_plot,
             save=True)

# convert to transfer function
num_samples = np.shape(A_traces)[0]

# for i in range(num_samples):
tf_nums = np.zeros((num_samples, 7))
tf_dens = np.zeros((num_samples, 7))
for i in range(num_samples):
    tf = ss2tf(A_traces[i, :, :], np.expand_dims(B_traces[i, :], 1),
               np.expand_dims(C_traces[i, :], 0), float(D_traces[i]))
    tf_nums[i, :] = tf[0]
    tf_dens[i, :] = tf[1]

tf_num_mean = np.mean(tf_nums, 0)
tf_den_mean = np.mean(tf_dens, 0)

w, mag_mean, phase_mean = signal.bode((tf_num_mean, tf_den_mean))

#
# plt.semilogx(w,mag_mean)
# plt.show()

hmc_sysid_results = {
    "A_traces": A_traces,
    "B_traces": B_traces,
Ejemplo n.º 32
0
def _get_num_den(arg, input=0):
    """Utility method to convert the input arg to a (num, den) representation.

    **Parameters:**

    arg, which may be:

    * ZPK tuple,
    * num, den tuple,
    * A, B, C, D tuple,
    * a scipy LTI object,
    * a sequence of the tuples of any of the above types.

    input : scalar
        In case the system has multiple inputs, which input is to be
        considered. Input `0` means first input, and so on.

    **Returns:**

    The sequence of ndarrays num, den

    **Raises:**

    TypeError, ValueError

    .. warn: support for MISO transfer functions is experimental.
    """
    num, den = None, None
    if isinstance(arg, np.ndarray):
        # ABCD matrix
        A, B, C, D = partitionABCD(arg)
        num, den = ss2tf(A, B, C, D, input=input)
    elif isinstance(arg, lti):
        arx = arg.to_tf()
        num, den = arx.num, arx.den
    elif _is_num_den(arg):
        num, den = carray(arg[0]).squeeze(), carray(arg[1]).squeeze()
    elif _is_zpk(arg):
        num, den = zpk2tf(*arg)
    elif _is_A_B_C_D(arg):
        num, den = ss2tf(*arg, input=input)
    elif isinstance(arg, collections.Iterable):
        ri = 0
        for i in arg:
            # Note we do not check if the user has assembled a list with
            # mismatched representations.
            if hasattr(i, 'B'):  # lti
                iis = i.B.shape[1]
                if input < ri + iis:
                    num, den = ss2tf(i.A, i.B, i.C, i.D, input=input - ri)
                    break
                else:
                    ri += iis
            else:
                sys = lti(*i)
                iis = sys.B.shape[1]
                if input < ri + iis:
                    num, den = ss2tf(sys.A,
                                     sys.B,
                                     sys.C,
                                     sys.D,
                                     input=input - ri)
                    break
                else:
                    ri += iis

        if (num, den) == (None, None):
            raise ValueError("The LTI representation does not have enough" +
                             "inputs: max %d, looking for input %d" %
                             (ri - 1, input))
    else:
        raise TypeError("Unknown LTI representation: %s" % arg)

    if len(num.shape) > 1:
        num = num.squeeze()
    if len(den.shape) > 1:
        den = den.squeeze()

    # default accuracy: sqrt_ps
    sqrt_eps = np.sqrt(eps)
    while len(num.shape) and len(num):
        if abs(num[0]) < sqrt_eps:
            num = num[1:]
        else:
            break
    while len(den.shape) and len(den):
        if abs(den[0]) < sqrt_eps:
            den = den[1:]
        else:
            break
    den = np.atleast_1d(den)
    num = np.atleast_1d(num)

    return num, den
Ejemplo n.º 33
0
    def filter(self, *filt, **kwargs):
        """Apply the given filter to this `FrequencySeries`.

        Recognised filter arguments are converted into the standard
        ``(numerator, denominator)`` representation before being applied
        to this `FrequencySeries`.

        .. note::

           Unlike the related
           :meth:`TimeSeries.filter <gwpy.timeseries.TimeSeries.filter>`
           method, here all frequency information (e.g. frequencies of
           poles or zeros in a ZPK) is assumed to be in Hertz.

        Parameters
        ----------
        *filt
            one of:

            - :class:`scipy.signal.lti`
            - ``(numerator, denominator)`` polynomials
            - ``(zeros, poles, gain)``
            - ``(A, B, C, D)`` 'state-space' representation

        Returns
        -------
        result : `FrequencySeries`
            the filtered version of the input `FrequencySeries`

        See also
        --------
        FrequencySeries.zpk
            for information on filtering in zero-pole-gain format
        scipy.signal.zpk2tf
            for details on converting ``(zeros, poles, gain)`` into
            transfer function format
        scipy.signal.ss2tf
            for details on converting ``(A, B, C, D)`` to transfer function
            format
        scipy.signal.freqs
            for details on the filtering calculation

        Raises
        ------
        ValueError
            If ``filt`` arguments cannot be interpreted properly
        """
        # parse filter
        if len(filt) == 1 and isinstance(filt[0], signal.lti):
            filt = filt[0]
            a = filt.den
            b = filt.num
        elif len(filt) == 2:
            b, a = filt
        elif len(filt) == 3:
            b, a = signal.zpk2tf(*filt)
        elif len(filt) == 4:
            b, a = signal.ss2tf(*filt)
        else:
            raise ValueError("Cannot interpret filter arguments. Please give "
                             "either a signal.lti object, or a tuple in zpk "
                             "or ba format. See scipy.signal docs for "
                             "details.")
        # parse keyword args
        inplace = kwargs.pop('inplace', False)
        if kwargs:
            raise TypeError("FrequencySeries.filter() got an unexpected "
                            "keyword argument '%s'" % list(kwargs.keys())[0])
        fresp = abs(signal.freqs(b, a, self.frequencies.value)[1])
        if inplace:
            self.value *= fresp
            return self
        else:
            new = (self.value * fresp).view(type(self))
            new.__dict__ = deepcopy(self.__dict__)
            return new
Ejemplo n.º 34
0
Archivo: core.py Proyecto: cpankow/gwpy
    def filter(self, *filt, **kwargs):
        """Apply the given filter to this `Spectrum`.

        Recognised filter arguments are converted into the standard
        ``(numerator, denominator)`` representation before being applied
        to this `Spectrum`.

        .. note::

           Unlike the related
           :meth:`TimeSeries.filter <gwpy.timeseries.TimeSeries.filter>`
           method, here all frequency information (e.g. frequencies of
           poles or zeros in a ZPK) is assumed to be in Hertz.

        Parameters
        ----------
        *filt
            one of:

            - :class:`scipy.signal.lti`
            - ``(numerator, denominator)`` polynomials
            - ``(zeros, poles, gain)``
            - ``(A, B, C, D)`` 'state-space' representation

        Returns
        -------
        result : `Spectrum`
            the filtered version of the input `Spectrum`

        See also
        --------
        Spectrum.zpk
            for information on filtering in zero-pole-gain format
        scipy.signal.zpk2tf
            for details on converting ``(zeros, poles, gain)`` into
            transfer function format
        scipy.signal.ss2tf
            for details on converting ``(A, B, C, D)`` to transfer function
            format
        scipy.signal.freqs
            for details on the filtering calculation

        Raises
        ------
        ValueError
            If ``filt`` arguments cannot be interpreted properly
        """
        # parse filter
        if len(filt) == 1 and isinstance(filt[0], signal.lti):
            filt = filt[0]
            a = filt.den
            b = filt.num
        elif len(filt) == 2:
            b, a = filt
        elif len(filt) == 3:
            b, a = signal.zpk2tf(*filt)
        elif len(filt) == 4:
            b, a = signal.ss2tf(*filt)
        else:
            raise ValueError("Cannot interpret filter arguments. Please give "
                             "either a signal.lti object, or a tuple in zpk "
                             "or ba format. See scipy.signal docs for "
                             "details.")
        # parse keyword args
        inplace = kwargs.pop('inplace', False)
        if kwargs:
            raise TypeError("Spectrum.filter() got an unexpected keyword "
                            "argument '%s'" % list(kwargs.keys())[0])
        fresp = abs(signal.freqs(b, a, self.frequencies.value)[1])
        if inplace:
            self.value *= fresp
            return self
        else:
            new = (self.value * fresp).view(type(self))
            new.__dict__ = deepcopy(self.__dict__)
            return new
Ejemplo n.º 35
0
	[1,2],
	[2,0]
])

B = np.array([
	[1],
	[2]
])

C = np.array([
	[1,0]
])

D = 0

sys = signal.StateSpace(A,B,C,D) #State space to time domain conversion
a,b = signal.ss2tf(A,B,C,D) #Importing Num. and Den. of T.F. from State Space Rep.
#rounding off

num = np.around(a[0],decimals = 0)

den = np.around(b,decimals = 0)

s = sp.symbols('s')

H_s = sp.Poly(num,s)/sp.Poly(den,s) # Getting polynomial expressions

print("THE TRANSFER FUNCTION OF THE SYSTEM ")

print("H(s) =",H_s)
Ejemplo n.º 36
0
import numpy as np
from scipy import signal

dvec = np.array([1, 2, 3, 4])
A1 = np.array([-dvec, [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
B1 = np.array([[1, 0, 0,
                0]]).T  # wrong dimension, this requires D has one column
B1 = np.eye(4)
C1 = np.array([[1, 2, 3, 4]])
D1 = np.zeros((1, 4))
print signal.ss2tf(A1, B1, C1, D1)
#same as http://en.wikipedia.org/wiki/State_space_(controls)#Canonical_realizations

signal.ss2tf(*signal.tf2ss(*signal.ss2tf(A1, B1, C1, D1)))
np.testing.assert_almost_equal(
    signal.ss2tf(*signal.tf2ss(*signal.ss2tf(A1, B1, C1, D1)))[0],
    signal.ss2tf(A1, B1, C1, D1)[0])
'''

dx_t = A x_t + B u_t
 y_t = C x_t + D u_t


>>> dvec = np.array([1,2,3,4])
>>> A = np.array([-dvec,[1,0,0,0],[0,1,0,0],[0,0,1,0]])
>>> B = np.array([[1,0,0,0]]).T  # wrong dimension, this requires D has one column
>>> B = np.eye(4)
>>> C = np.array([[1,2,3,4]])
>>> D = np.zeros((1,4))
>>> num, den = signal.ss2tf(A,B,C,D)
>>> print num
Ejemplo n.º 37
0
def compute_gains(Q, R, W, V, dt):
    """Given LQR Q and R matrices, and Kalman W and V matrices, and sample
    time, compute optimal feedback gain and optimal filter gains."""

    data = np.empty((N, ), dtype=controller_t)

    # Loop over all speeds for which we have system dynamics
    for i in range(N):
        data['theta_R_dot'][i] = theta_R_dot[i]
        data['dt'][i] = dt
        # Convert the bike dynamics to discrete time using a zero order hold
        data['A'][i], data['B'][i], _, _, _ = cont2discrete(
            (A_w[i], B_w[i, :], eye(4), zeros((4, 1))), dt)
        data['plant_evals_d'][i] = la.eigvals(data['A'][i])
        data['plant_evals_c'][i] = np.log(data['plant_evals_d'][i]) / dt

        # Bicycle measurement matrices
        # - steer angle
        # - roll rate
        data['C_m'][i] = C_w[i, :2, :]
        # - yaw rate
        data['C_z'][i] = C_w[i, 2, :]

        A = data['A'][i]
        B = data['B'][i, :, 2].reshape((4, 1))
        C_m = data['C_m'][i]
        C_z = data['C_z'][i]

        # Controllability from steer torque
        data['ctrb_plant'][i] = ctrb(A, B)
        u, s, v = la.svd(data['ctrb_plant'][i])
        assert (np.all(s > 1e-13))

        # Solve discrete algebraic Ricatti equation associated with LQI problem
        P_c = dare(A, B, R, Q)

        # Optimal feedback gain using solution of Ricatti equation
        K_c = -la.solve(R + dot(B.T, dot(P_c, B)), dot(B.T, dot(P_c, A)))
        data['K_c'][i] = K_c
        data['A_c'][i] = A + dot(B, K_c)
        data['B_c'][i] = B
        data['controller_evals'][i] = la.eigvals(data['A_c'][i])
        data['controller_evals_c'][i] = np.log(
            data['controller_evals'][i]) / dt
        assert (np.all(abs(data['controller_evals'][i]) < 1.0))

        # Observability from steer angle and roll rate measurement
        # Note that (A, C_m * A) must be observable in the "current estimator"
        # formulation
        data['obsv_plant'][i] = obsv(A, dot(C_m, A))
        u, s, v = la.svd(data['obsv_plant'][i])
        assert (np.all(s > 1e-13))

        # Solve Riccati equation
        P_e = dare(A.T, C_m.T, V, W)
        # Compute Kalman gain
        K_e = dot(P_e, dot(C_m.T, la.inv(dot(C_m, dot(P_e, C_m.T)) + V)))
        data['K_e'][i] = K_e
        data['A_e'][i] = dot(eye(4) - dot(K_e, C_m), A)
        data['B_e'][i] = np.hstack((dot(eye(4) - dot(K_e, C_m), B), K_e))
        data['estimator_evals'][i] = la.eigvals(data['A_e'][i])
        data['estimator_evals_c'][i] = np.log(data['estimator_evals'][i]) / dt
        # Verify that Kalman estimator eigenvalues are stable
        assert (np.all(abs(data['estimator_evals'][i]) < 1.0))

        # Closed loop state space equations
        A_cl = np.zeros((8, 8))
        A_cl[:4, :4] = A
        A_cl[:4, 4:] = dot(B, K_c)
        A_cl[4:, :4] = dot(K_e, dot(C_m, A))
        A_cl[4:, 4:] = A - A_cl[4:, :4] + A_cl[:4, 4:]
        data['A_cl'][i] = A_cl
        data['closed_loop_evals'][i] = la.eigvals(A_cl)
        assert (np.all(abs(data['closed_loop_evals'][i]) < 1.0))

        B_cl = np.zeros((8, 1))
        B_cl[:4, 0] = B.reshape((4, ))
        B_cl[4:, 0] = dot(eye(4) - dot(K_e, C_m), B).reshape((4, ))
        data['B_cl'][i] = B_cl

        C_cl = np.hstack((C_z, np.zeros((1, 4))))
        data['C_cl'][i] = C_cl

        # Transfer functions from r to yaw rate
        num, den = ss2tf(A_cl, B_cl, C_cl, 0)
        data['w_r_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_r_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_r_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_r_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi

        # Open loop transfer function from e to yaw rate (PI loop not closed,
        # but LQR/LQG loop closed.
        inner_cl = ss(A_cl, B_cl, C_cl, 0)
        pi_block = ss([[1]], [[1]], [[data['Ki_fit'][i] * dt]],
                      [[data['Kp_fit'][i]]])
        e_to_psi_dot = series(pi_block, inner_cl)
        num, den = ss2tf(e_to_psi_dot.A, e_to_psi_dot.B, e_to_psi_dot.C,
                         e_to_psi_dot.D)
        data['w_e_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_e_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_e_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_e_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi

    return data
Ejemplo n.º 38
0
 def check_matrix_shapes(self, p, q, r):
     ss2tf(np.zeros((p, p)),
           np.zeros((p, q)),
           np.zeros((r, p)),
           np.zeros((r, q)), 0)
Ejemplo n.º 39
0
def calculateQTF(ABCDr):
    """Calculate noise and signal transfer functions for a quadrature modulator

    **Parameters:**

    ABCDr : ndarray
        The ABCD matrix, in real form. You may call :func:`mapQtoR` to convert
        an imaginary (quadrature) ABCD matrix to a real one.

    **Returns:**

    ntf, stf, intf, istf : tuple of zpk tuples
        The quadrature noise and signal transfer functions.

    :raises RuntimeError: if the supplied ABCD matrix results in denominator mismatches.
    """
    A, B, C, D = partitionABCD(ABCDr, 4)

    #Construct an ABCD description of the closed-loop system
    # sys is a tuple in A, B, C, D form
    Acl = A + np.dot(B[:, 2:4], C)
    Bcl = B
    Ccl = C
    Dcl = np.hstack((D[:, 0:2], np.eye(2)))
    #sys = (A + np.dot(B[:, 2:4], C), B, C,
    #       np.hstack((D[:, 0:2], np.eye(2))))

    #Calculate the 2x4 matrix of transfer functions
    tfs = np.empty((2, 4), dtype=object)
    # Each tf is a tuple in num, den form
    # tf[i, j] corresponds to the TF from input j to output i
    for i in range(2):
        for j in range(4):
            tfs[i, j] = ss2tf(Acl, Bcl, Ccl[i, :], Dcl[i, :], input=j)

    #Reduce these to NTF, STF, INTF and ISTF
    if any(tfs[0, 2][1] != tfs[1, 3][1]):
        raise RuntimeError('TF Denominator mismatch. Location 1')

    ntf_x = (0.5 * (tfs[0, 2][0] + tfs[1, 3][0]), tfs[0, 2][1])
    intf_x = (0.5 * (tfs[0, 2][0] - tfs[1, 3][0]), tfs[0, 2][1])

    if any(tfs[0, 3][1] != tfs[1, 2][1]):
        raise RuntimeError('TF Denominator mismatch. Location 2')

    ntf_y = (0.5 * (tfs[1, 2][0] - tfs[0, 3][0]), tfs[1, 2][1])
    intf_y = (0.5 * (tfs[1, 2][0] + tfs[0, 3][0]), tfs[1, 2][1])

    if any(ntf_x[1] != ntf_y[1]):
        raise RuntimeError('TF Denominator mismatch. Location 3')
    if any(tfs[0, 0][1] != tfs[1, 1][1]):
        raise RuntimeError('TF Denominator mismatch. Location 4')

    stf_x = (0.5 * (tfs[0, 0][0] + tfs[1, 1][0]), tfs[0, 0][1])
    istf_x = (0.5 * (tfs[0, 0][0] - tfs[1, 1][0]), tfs[0, 0][1])

    if any(tfs[0, 1][1] != tfs[1, 0][1]):
        raise RuntimeError('TF Denominator mismatch. Location 5')

    stf_y = (0.5 * (tfs[1, 0][0] - tfs[0, 1][0]), tfs[1, 0][1])
    istf_y = (0.5 * (tfs[1, 0][0] + tfs[0, 1][0]), tfs[1, 0][1])

    if any(stf_x[1] != stf_y[1]):
        raise RuntimeError('TF Denominator mismatch. Location 6')

    # suppress warnings about complex TFs
    #warning('off')
    ntf = cancelPZ(tf2zpk(ntf_x[0] + 1j*ntf_y[0], ntf_x[1]))
    intf = cancelPZ(tf2zpk(intf_x[0] + 1j*intf_y[0], intf_x[1]))
    stf = cancelPZ(tf2zpk(stf_x[0] + 1j*stf_y[0], ntf_x[1]))
    istf = cancelPZ(tf2zpk(istf_x[0] + 1j*istf_y[0], intf_x[1]))
    #warning('on')

    return ntf, stf, intf, istf
Ejemplo n.º 40
0
 def check_matrix_shapes(self, p, q, r):
     ss2tf(np.zeros((p, p)), np.zeros((p, q)), np.zeros((r, p)),
           np.zeros((r, q)), 0)
Ejemplo n.º 41
0
def compute_gains(Q, R, W, V, dt):
    """Given LQR Q and R matrices, and Kalman W and V matrices, and sample
    time, compute optimal feedback gain and optimal filter gains."""

    data = np.empty((N,), dtype=controller_t)

    # Loop over all speeds for which we have system dynamics
    for i in range(N):
        data['theta_R_dot'][i] = theta_R_dot[i]
        data['dt'][i] = dt
        # Convert the bike dynamics to discrete time using a zero order hold
        data['A'][i], data['B'][i], _, _, _ = cont2discrete(
                        (A_w[i], B_w[i, :], eye(4), zeros((4, 1))), dt)
        data['plant_evals_d'][i] = la.eigvals(data['A'][i])
        data['plant_evals_c'][i] = np.log(data['plant_evals_d'][i]) / dt
        
        # Bicycle measurement matrices
        # - steer angle
        # - roll rate
        data['C_m'][i] = C_w[i, :2, :]
        # - yaw rate
        data['C_z'][i] = C_w[i, 2, :]

        A = data['A'][i]
        B = data['B'][i, :, 2].reshape((4, 1))
        C_m = data['C_m'][i]
        C_z = data['C_z'][i]

        # Controllability from steer torque
        data['ctrb_plant'][i] = ctrb(A, B)
        u, s, v = la.svd(data['ctrb_plant'][i])
        assert(np.all(s > 1e-13))

        # Solve discrete algebraic Ricatti equation associated with LQI problem
        P_c = dare(A, B, R, Q)
        
        # Optimal feedback gain using solution of Ricatti equation
        K_c = -la.solve(R + dot(B.T, dot(P_c, B)),
                                dot(B.T, dot(P_c, A)))
        data['K_c'][i] = K_c
        data['A_c'][i] = A + dot(B, K_c)
        data['B_c'][i] = B
        data['controller_evals'][i] = la.eigvals(data['A_c'][i])
        data['controller_evals_c'][i] = np.log(data['controller_evals'][i]) / dt
        assert(np.all(abs(data['controller_evals'][i]) < 1.0))

        # Observability from steer angle and roll rate measurement
        # Note that (A, C_m * A) must be observable in the "current estimator"
        # formulation
        data['obsv_plant'][i] = obsv(A, dot(C_m, A))
        u, s, v = la.svd(data['obsv_plant'][i])
        assert(np.all(s > 1e-13))

        # Solve Riccati equation
        P_e = dare(A.T, C_m.T, V, W)
        # Compute Kalman gain
        K_e = dot(P_e, dot(C_m.T, la.inv(dot(C_m, dot(P_e, C_m.T)) + V)))
        data['K_e'][i] = K_e
        data['A_e'][i] = dot(eye(4) - dot(K_e, C_m), A)
        data['B_e'][i] = np.hstack((dot(eye(4) - dot(K_e, C_m), B), K_e))
        data['estimator_evals'][i] = la.eigvals(data['A_e'][i])
        data['estimator_evals_c'][i] = np.log(data['estimator_evals'][i]) / dt
        # Verify that Kalman estimator eigenvalues are stable
        assert(np.all(abs(data['estimator_evals'][i]) < 1.0))

        # Closed loop state space equations
        A_cl = np.zeros((8, 8))
        A_cl[:4, :4] = A
        A_cl[:4, 4:] = dot(B, K_c)
        A_cl[4:, :4] = dot(K_e, dot(C_m, A))
        A_cl[4:, 4:] = A - A_cl[4:, :4] + A_cl[:4, 4:]
        data['A_cl'][i] = A_cl
        data['closed_loop_evals'][i] = la.eigvals(A_cl)
        assert(np.all(abs(data['closed_loop_evals'][i]) < 1.0))

        B_cl = np.zeros((8, 1))
        B_cl[:4, 0] = B.reshape((4,))
        B_cl[4:, 0] = dot(eye(4) - dot(K_e, C_m), B).reshape((4,))
        data['B_cl'][i] = B_cl

        C_cl = np.hstack((C_z, np.zeros((1, 4))))
        data['C_cl'][i] = C_cl

        # Transfer functions from r to yaw rate
        num, den = ss2tf(A_cl, B_cl, C_cl, 0)
        data['w_r_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_r_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_r_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_r_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi

        # Open loop transfer function from e to yaw rate (PI loop not closed,
        # but LQR/LQG loop closed.
        inner_cl = ss(A_cl, B_cl, C_cl, 0)
        pi_block = ss([[1]], [[1]], [[data['Ki_fit'][i]*dt]], [[data['Kp_fit'][i]]])
        e_to_psi_dot = series(pi_block, inner_cl)
        num, den = ss2tf(e_to_psi_dot.A, e_to_psi_dot.B, e_to_psi_dot.C, e_to_psi_dot.D)
        data['w_e_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_e_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_e_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_e_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi




    return data
Ejemplo n.º 42
0
#Coded by SRIKANTH
#15th April, 2020
#Released under GNU GPL

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import ss2tf

A = [[-4, -1.5], [4, 0]]
B = [[4], [0]]  # 2-dimensional column vector
C = [[1.5, 0.625]]  # 2-dimensional row vector
D = [[0]]
ss2tf(A, B, C, D)
sys = ss2tf(A, B, C, D)
print(sys)
show()

# ## Geração da Função de Transferência
#
# Devido algumas diferenças toleráveis na computação de valores muito grandes os arrays com numeradores e o denominadores gerados foram **arredondados para 6 casas decimais**. Isto deixa mais clara a representação da função de transferência.

# In[22]:

from scipy.signal import ss2tf
from control import tf
from numpy import around

# In[23]:

(num, den) = ss2tf(Ap, Bp, Cp, Ep, 0)

n_of_decimals = 6
num = around(num, n_of_decimals)
den = around(den, n_of_decimals)

Gi_vg = tf(num[0], den)
Gv_vg = tf(num[1], den)

# In[24]:

print(Gi_vg)
print(Gv_vg)

# In[25]:
Ejemplo n.º 44
0
def _get_num_den(arg, input=0):
    """Utility method to convert the input arg to a (num, den) representation.

    **Parameters:**

    arg, which may be:

    * ZPK tuple,
    * num, den tuple,
    * A, B, C, D tuple,
    * a scipy LTI object,
    * a sequence of the tuples of any of the above types.

    input : scalar
        In case the system has multiple inputs, which input is to be
        considered. Input `0` means first input, and so on.

    **Returns:**

    The sequence of ndarrays num, den

    **Raises:**

    TypeError, ValueError

    .. warn: support for MISO transfer functions is experimental.
    """
    num, den = None, None
    if isinstance(arg, np.ndarray):
        # ABCD matrix
        A, B, C, D = partitionABCD(arg)
        num, den = ss2tf(A, B, C, D, input=input)
    elif hasattr(arg, '__class__') and arg.__class__.__name__ == 'lti':
        num, den = arg.num, arg.den
    elif _is_num_den(arg):
        num, den = carray(arg[0]).squeeze(), carray(arg[1]).squeeze()
    elif _is_zpk(arg):
        num, den = zpk2tf(*arg)
    elif _is_A_B_C_D(arg):
        num, den = ss2tf(*arg, input=input)
    elif isinstance(arg, collections.Iterable):
        ri = 0
        for i in arg:
            # Note we do not check if the user has assembled a list with
            # mismatched representations.
            if hasattr(i, 'B'):  # lti
                iis = i.B.shape[1]
                if input < ri + iis:
                    num, den = ss2tf(i.A, i.B, i.C, i.D, input=input - ri)
                    break
                else:
                    ri += iis
            else:
                sys = lti(*i)
                iis = sys.B.shape[1]
                if input < ri + iis:
                    num, den = ss2tf(
                        sys.A, sys.B, sys.C, sys.D, input=input - ri)
                    break
                else:
                    ri += iis

        if (num, den) == (None, None):
            raise ValueError("The LTI representation does not have enough" +
                             "inputs: max %d, looking for input %d" %
                             (ri - 1, input))
    else:
        raise TypeError("Unknown LTI representation: %s" % arg)

    if len(num.shape) > 1:
        num = num.squeeze()
    if len(den.shape) > 1:
        den = den.squeeze()

    # default accuracy: sqrt_ps
    sqrt_eps = np.sqrt(eps)
    while len(num.shape) and len(num):
        if abs(num[0]) < sqrt_eps:
            num = num[1:]
        else:
            break
    while len(den.shape) and len(den):
        if abs(den[0]) < sqrt_eps:
            den = den[1:]
        else:
            break
    den = np.atleast_1d(den)
    num = np.atleast_1d(num)

    return num, den