B
    &]\6                 @   s   d Z ddlmZmZmZ ddlZddlZddlmZmZm	Z	m
Z
mZmZmZmZmZmZ ddlmZ ddlmZmZmZ dd	d
dddgZdd Zdd Zdd Zdd Zdd Zdd Zddd	Zd dd
Zdd Z d!ddZ!d"ddZ"dS )#zr
ltisys -- a collection of functions to convert linear time invariant systems
from one representation to another.
    )divisionprint_functionabsolute_importN)
r_eye
atleast_2dpolydotasarrayproductzerosarrayouter)linalg   )tf2zpkzpk2tf	normalizetf2ssabcd_normalizess2tfzpk2ssss2zpkcont2discretec             C   s  t | |\} }t| j}|dkr.t| g| j} | jd }t|}||krTd}t||dksd|dkrtg ttg ttg ttg tfS tdt	| jd || f| j| f } | jd dkrt
| dddf }ntdggt}|dkr || j}t	dt	d|jd ft	|jd df|fS t|dd g }t|t|d |d f }t|d d}	| ddddf t| dddf |dd  }
||
jd |	jd f}||	|
|fS )	a  Transfer function to state-space representation.

    Parameters
    ----------
    num, den : array_like
        Sequences representing the coefficients of the numerator and
        denominator polynomials, in order of descending degree. The
        denominator needs to be at least as long as the numerator.

    Returns
    -------
    A, B, C, D : ndarray
        State space representation of the system, in controller canonical
        form.

    Examples
    --------
    Convert the transfer function:

    .. math:: H(s) = \frac{s^2 + 3s + 3}{s^2 + 2s + 1}

    >>> num = [1, 3, 3]
    >>> den = [1, 2, 1]

    to the state-space representation:

    .. math::

        \dot{\textbf{x}}(t) =
        \begin{bmatrix} -2 & -1 \\ 1 & 0 \end{bmatrix} \textbf{x}(t) +
        \begin{bmatrix} 1 \\ 0 \end{bmatrix} \textbf{u}(t) \\

        \textbf{y}(t) = \begin{bmatrix} 1 & 2 \end{bmatrix} \textbf{x}(t) +
        \begin{bmatrix} 1 \end{bmatrix} \textbf{u}(t)

    >>> from scipy.signal import tf2ss
    >>> A, B, C, D = tf2ss(num, den)
    >>> A
    array([[-2., -1.],
           [ 1.,  0.]])
    >>> B
    array([[ 1.],
           [ 0.]])
    >>> C
    array([[ 1.,  2.]])
    >>> D
    array([[ 1.]])
    r   z7Improper transfer function. `num` is longer than `den`.r   z-1N)r   r      )r   lenshaper
   dtype
ValueErrorr   floatr   r   r   Zreshaper   r   )numdenZnnMKmsgDZfrowABC r*   :lib/python3.7/site-packages/scipy/signal/lti_conversion.pyr      s4    8

$
2c             C   s   | d krt dS | S d S )N)r   r   )r   )argr*   r*   r+   _none_to_empty_2du   s    r-   c             C   s   | d k	rt | S d S )N)r   )r,   r*   r*   r+   _atleast_2d_or_none|   s    r.   c             C   s   | d k	r| j S dS d S )N)NN)r   )r#   r*   r*   r+   _shape_or_none   s    r/   c              G   s   x| D ]}|d k	r|S qW d S )Nr*   )argsr,   r*   r*   r+   _choice_not_none   s    
r1   c             C   s,   | j dkrt|S | j |kr$td| S d S )N)r   r   z*The input arrays have incompatible shapes.)r   r   r   )r#   r   r*   r*   r+   _restore   s
    

r2   c             C   s   t t| |||f\} }}}t| \}}t|\}}t|\}}	t|\}
}t|||	}t||}t||
}|dks|dks|dkrtdt t| |||f\} }}}t| ||f} t|||f}t|||f}t|||f}| |||fS )a  Check state-space matrices and ensure they are two-dimensional.

    If enough information on the system is provided, that is, enough
    properly-shaped arrays are passed to the function, the missing ones
    are built from this information, ensuring the correct number of
    rows and columns. Otherwise a ValueError is raised.

    Parameters
    ----------
    A, B, C, D : array_like, optional
        State-space matrices. All of them are None (missing) by default.
        See `ss2tf` for format.

    Returns
    -------
    A, B, C, D : array
        Properly shaped state-space matrices.

    Raises
    ------
    ValueError
        If not enough information on the system was provided.

    Nz%Not enough information on the system.)mapr.   r/   r1   r   r-   r2   )r'   r(   r)   r&   ZMAZNAZMBZNBZMCZNCZMDZNDpqrr*   r*   r+   r      s     

c             C   s  t | |||\} }}}|j\}}||kr0td|dd||d f }|dd||d f }yt| }W n tk
r   d}Y nX t|jdddkrt|jdddkrt|}t|jdddkrt| jdddkrg }||fS | jd }	| dddf |dddf  |dddf  | }
t||	d f|
j}xLt	|D ]@}t
||ddf }t| t|| || d |  ||< qBW ||fS )a  State-space to transfer function.

    A, B, C, D defines a linear state-space system with `p` inputs,
    `q` outputs, and `n` state variables.

    Parameters
    ----------
    A : array_like
        State (or system) matrix of shape ``(n, n)``
    B : array_like
        Input matrix of shape ``(n, p)``
    C : array_like
        Output matrix of shape ``(q, n)``
    D : array_like
        Feedthrough (or feedforward) matrix of shape ``(q, p)``
    input : int, optional
        For multiple-input systems, the index of the input to use.

    Returns
    -------
    num : 2-D ndarray
        Numerator(s) of the resulting transfer function(s).  `num` has one row
        for each of the system's outputs. Each row is a sequence representation
        of the numerator polynomial.
    den : 1-D ndarray
        Denominator of the resulting transfer function(s).  `den` is a sequence
        representation of the denominator polynomial.

    Examples
    --------
    Convert the state-space representation:

    .. math::

        \dot{\textbf{x}}(t) =
        \begin{bmatrix} -2 & -1 \\ 1 & 0 \end{bmatrix} \textbf{x}(t) +
        \begin{bmatrix} 1 \\ 0 \end{bmatrix} \textbf{u}(t) \\

        \textbf{y}(t) = \begin{bmatrix} 1 & 2 \end{bmatrix} \textbf{x}(t) +
        \begin{bmatrix} 1 \end{bmatrix} \textbf{u}(t)

    >>> A = [[-2, -1], [1, 0]]
    >>> B = [[1], [0]]  # 2-dimensional column vector
    >>> C = [[1, 2]]    # 2-dimensional row vector
    >>> D = 1

    to the transfer function:

    .. math:: H(s) = \frac{s^2 + 3s + 3}{s^2 + 2s + 1}

    >>> from scipy.signal import ss2tf
    >>> ss2tf(A, B, C, D)
    (array([[1, 3, 3]]), array([ 1.,  2.,  1.]))
    z)System does not have the input specified.Nr   r   )Zaxis)r   r   r   r   r   numpyZravelr   r   ranger   r	   )r'   r(   r)   r&   inputZnoutZninr"   r!   Z
num_statesZ	type_testkZCkr*   r*   r+   r      s,    :

$
$
4,c             C   s   t t| || S )a:  Zero-pole-gain representation to state-space representation

    Parameters
    ----------
    z, p : sequence
        Zeros and poles.
    k : float
        System gain.

    Returns
    -------
    A, B, C, D : ndarray
        State space representation of the system, in controller canonical
        form.

    )r   r   )zr4   r:   r*   r*   r+   r     s    c             C   s   t t| ||||d S )a  State-space representation to zero-pole-gain representation.

    A, B, C, D defines a linear state-space system with `p` inputs,
    `q` outputs, and `n` state variables.

    Parameters
    ----------
    A : array_like
        State (or system) matrix of shape ``(n, n)``
    B : array_like
        Input matrix of shape ``(n, p)``
    C : array_like
        Output matrix of shape ``(q, n)``
    D : array_like
        Feedthrough (or feedforward) matrix of shape ``(q, p)``
    input : int, optional
        For multiple-input systems, the index of the input to use.

    Returns
    -------
    z, p : sequence
        Zeros and poles.
    k : float
        System gain.

    )r9   )r   r   )r'   r(   r)   r&   r9   r*   r*   r+   r   3  s    zohc             C   s  t | dkr|  S t | dkrbtt| d | d |||d}t|d |d |d |d |f S t | dkrtt| d | d | d |||d}t|d |d |d |d |f S t | dkr| \}}}}ntd|dkr|d	krtd
n|dk s|dkrtd|dkrt	|j
d || |  }	t|	t	|j
d d| | |  }
t|	|| }t|	 | }| }||t||  }n4|dks|dkrt| |dddS |dks|dkrt| |dddS |dkrt| |dddS |dkrt||f}tt|j
d |j
d ft|j
d |j
d ff}t||f}t|| }|d	|j
d d	d	f }|d	d	d|j
d f }
|d	d	|j
d d	f }|}|}ntd| |
||||fS )a  
    Transform a continuous to a discrete state-space system.

    Parameters
    ----------
    system : a tuple describing the system or an instance of `lti`
        The following gives the number of elements in the tuple and
        the interpretation:

            * 1: (instance of `lti`)
            * 2: (num, den)
            * 3: (zeros, poles, gain)
            * 4: (A, B, C, D)

    dt : float
        The discretization time step.
    method : {"gbt", "bilinear", "euler", "backward_diff", "zoh"}, optional
        Which method to use:

            * gbt: generalized bilinear transformation
            * bilinear: Tustin's approximation ("gbt" with alpha=0.5)
            * euler: Euler (or forward differencing) method ("gbt" with alpha=0)
            * backward_diff: Backwards differencing ("gbt" with alpha=1.0)
            * zoh: zero-order hold (default)

    alpha : float within [0, 1], optional
        The generalized bilinear transformation weighting parameter, which
        should only be specified with method="gbt", and is ignored otherwise

    Returns
    -------
    sysd : tuple containing the discrete system
        Based on the input type, the output will be of the form

        * (num, den, dt)   for transfer function input
        * (zeros, poles, gain, dt)   for zeros-poles-gain input
        * (A, B, C, D, dt) for state-space system input

    Notes
    -----
    By default, the routine uses a Zero-Order Hold (zoh) method to perform
    the transformation.  Alternatively, a generalized bilinear transformation
    may be used, which includes the common Tustin's bilinear approximation,
    an Euler's method technique, or a backwards differencing technique.

    The Zero-Order Hold (zoh) method is based on [1]_, the generalized bilinear
    approximation is based on [2]_ and [3]_.

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Discretization#Discretization_of_linear_state_space_models

    .. [2] http://techteach.no/publications/discretetime_signals_systems/discrete.pdf

    .. [3] G. Zhang, X. Chen, and T. Chen, Digital redesign via the generalized
        bilinear transformation, Int. J. Control, vol. 82, no. 4, pp. 741-754,
        2009.
        (https://www.mypolyuweb.hk/~magzhang/Research/ZCC09_IJC.pdf)

    r   r   r   )methodalpha      zKFirst argument must either be a tuple of 2 (tf), 3 (zpk), or 4 (ss) arrays.ZgbtNzUAlpha parameter must be specified for the generalized bilinear transform (gbt) methodzDAlpha parameter must be within the interval [0,1] for the gbt methodg      ?ZbilinearZtusting      ?ZeulerZforward_diffg        Zbackward_diffr<   z"Unknown transformation method '%s')r   Zto_discreter   r   r   r   r   r   npr   r   r   ZsolveZ	transposer	   Zhstackr   ZvstackZexpm)systemZdtr=   r>   ZsysdabcdZimaZadZbdZcdZddZem_upperZem_lowerZemZmsr*   r*   r+   r   Q  sX    =$
$


(

)NNNN)r   )r   )r<   N)#__doc__Z
__future__r   r   r   r7   rA   r   r   r   r   r	   r
   r   r   r   r   Zscipyr   Zfilter_designr   r   r   __all__r   r-   r.   r/   r1   r2   r   r   r   r   r   r*   r*   r*   r+   <module>   s&   0
a	
/
Y
