o
    ohYC                     @   s   d gZ ddlmZmZmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZ ddlmZ ddlmZ G d	d  d Zd
d ZdS )
Linearizer    )MatrixeyezerosDummy)flatten)dynamicsymbols)msubs_parse_linear_solver)
namedtuple)Iterablec                   @   sJ   e Zd ZdZ			dddZdd Zdd	 Zd
d Zdd ZdddZ	dS )r   aI  This object holds the general model form for a dynamic system. This
    model is used for computing the linearized form of the system, while
    properly dealing with constraints leading to  dependent coordinates and
    speeds. The notation and method is described in [1]_.

    Attributes
    ==========

    f_0, f_1, f_2, f_3, f_4, f_c, f_v, f_a : Matrix
        Matrices holding the general system form.
    q, u, r : Matrix
        Matrices holding the generalized coordinates, speeds, and
        input vectors.
    q_i, u_i : Matrix
        Matrices of the independent generalized coordinates and speeds.
    q_d, u_d : Matrix
        Matrices of the dependent generalized coordinates and speeds.
    perm_mat : Matrix
        Permutation matrix such that [q_ind, u_ind]^T = perm_mat*[q, u]^T

    References
    ==========

    .. [1] D. L. Peterson, G. Gede, and M. Hubbard, "Symbolic linearization of
           equations of motion of constrained multibody systems," Multibody
           Syst Dyn, vol. 33, no. 2, pp. 143-161, Feb. 2015, doi:
           10.1007/s11044-014-9436-5.

    NLUc                    s  t || _t|| _t|| _t|| _t|| _t|| _t|| _t|| _	t|| _
t|	| _t|
| _dd }||| _||| _||| _||| _||| _||| _| jtj| _| jtj| _t| j| j t fdd| jD | _t| j}t| j	}t| j}t| j}t| j}t| j}tdg d}|||||||| _d| _d| _d| _ d| _!d| _"d| _#d| _$d| _%d| _&d| _'d| _(dS )	a  
        Parameters
        ==========

        f_0, f_1, f_2, f_3, f_4, f_c, f_v, f_a : array_like
            System of equations holding the general system form.
            Supply empty array or Matrix if the parameter
            does not exist.
        q : array_like
            The generalized coordinates.
        u : array_like
            The generalized speeds
        q_i, u_i : array_like, optional
            The independent generalized coordinates and speeds.
        q_d, u_d : array_like, optional
            The dependent generalized coordinates and speeds.
        r : array_like, optional
            The input variables.
        lams : array_like, optional
            The lagrange multipliers
        linear_solver : str, callable
            Method used to solve the several symbolic linear systems of the
            form ``A*x=b`` in the linearization process. If a string is
            supplied, it should be a valid method that can be used with the
            :meth:`sympy.matrices.matrixbase.MatrixBase.solve`. If a callable is
            supplied, it should have the format ``x = f(A, b)``, where it
            solves the equations and returns the solution. The default is
            ``'LU'`` which corresponds to SymPy's ``A.LUsolve(b)``.
            ``LUsolve()`` is fast to compute but will often result in
            divide-by-zero and thus ``nan`` results.

        c                 S   s   | rt | S t  S )N)r   )x r   u/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/physics/mechanics/linearize.py<lambda>^   s    z%Linearizer.__init__.<locals>.<lambda>c                    s   g | ]}| vr
|nt  qS r   r   ).0vardup_varsr   r   
<listcomp>m   s    z'Linearizer.__init__.<locals>.<listcomp>dims)lmnoskNF))r   linear_solverr   f_0f_1f_2f_3f_4f_cf_vf_aquq_iq_du_iu_drlamsdiffr	   _t_qd_udsetintersection_qd_duplenr   _dims_Pq_Pqi_Pqd_Pu_Pui_Pud_C_0_C_1_C_2perm_mat_setup_done)selfr    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r   none_handlerr   r   r   r   r   r   r   r   r   r   __init__,   sV   
#























zLinearizer.__init__c                 C   s"   |    |   |   d| _d S )NT)_form_permutation_matrices_form_block_matrices_form_coefficient_matricesrC   )rD   r   r   r   _setup   s   
zLinearizer._setupc           	      C   s^  | j \}}}}}}|dkrAt| jt| j| jg| _|dkr9| jddd| f | _| jdd| df | _n| j| _t | _|dkryt| j	t| j
| jg| _|dkrq| jddd| f | _| jdd| df | _n| j| _t | _t| jt|| || g}tt||| | jt||| g}|r|r||| _dS || _dS || _dS )z(Form the permutation matrices Pq and Pu.r   N)r8   permutation_matrixr(   r   r*   r+   r9   r:   r;   r)   r,   r-   r<   r=   r>   r   row_joinrB   )	rD   r   r   r   r   r   r   P_col1P_col2r   r   r   rG      s,   $

z%Linearizer._form_permutation_matricesc                 C   s   | j \}}}}}}|dkr)| j| j}t|| j| || j |  | j | _nt|| _|dkrn| j	| j
}|| j }	|dkrU| j	| j}
| j | |	|
 | _nt||| _t|| j| |	|  | j | _dS t||| _t|| _dS )z0Form the coefficient matrices C_0, C_1, and C_2.r   N)r8   r%   jacobianr(   r   r;   r   r:   r?   r&   r)   r>   r@   r   r=   rA   )rD   r   r   r   r   r   r   	f_c_jac_q	f_v_jac_utemp	f_v_jac_qr   r   r   rI      s2   





z%Linearizer._form_coefficient_matricesc                 C   s"  | j \}}}}}}|dkr"| j| j| _| j| j | j | _nt | _t | _|dkrD|dkrD| j	| j
| _| j	| j | _nt | _t | _|dkrp|| | dkrp| j| j
| _| j| j | j | j | _nt | _t | _|dkr|dkr| j	| j| _| j	| j | _nt | _t | _|dkr|| | dkr| j| j| _| j| j | j | _nt | _t | _|dkr|dkr| j| j | _nt | _|dkr|| | dkr| j| j| _nt | _|dkr|| | dkr| j| j | _dS t | _dS )z2Form the block matrices for composing M, A, and B.r   N)r8   r    rO   r2   _M_qqr!   r(   _A_qqr   r'   r6   _M_uqc_A_uqcr#   _M_uqdr"   r$   _A_uqdr3   _M_uucr)   _A_uuc_M_uud_A_uud_A_qur/   _M_uldr.   _B_u)rD   r   r   r   r   r   r   r   r   r   rH      sF    zLinearizer._form_block_matricesFc           -      C   sr  | j s|   t|tr|}nt|tr!i }|D ]}|| qni }| j\}}}}	}
}| j}| j}| j	}| j
}| j}| j}| j}| j}| j}| j}| j}| j}| j}| j}| j}| j}|	dkrjtt||	||g}|dkrytt|| ||g}|dkrt|||g}|	dkr|dkr|||}n|	dkr||}n|}n|dkr||}n|}t||} |dkr|}!|	dkr|!|| 7 }!|!| }!|dkr|}"|	dkr|"|| 7 }"|"| }"nt }"|	| | dkr|}#|	dkr|#|| 7 }#|#| }#nt }#t|!|"|#g}nt }|	dkr?|dkr|| }$nt }$|dkr#|| }%nt }%|	| | dkr4|| }&nt }&t|$|%|&g}nt }|rQ|rN||}'n|}'n|}'t|'|}(|
dkrv|	| | dkrvt|| |
|})t|)|}*nt }*|r| jj| | |( }+|*r| jj| | |* },n|*},|r|+  |,  |+|,fS |r|   |(  |*  | |(|*fS )a!  Linearize the system about the operating point. Note that
        q_op, u_op, qd_op, ud_op must satisfy the equations of motion.
        These may be either symbolic or numeric.

        Parameters
        ==========
        op_point : dict or iterable of dicts, optional
            Dictionary or iterable of dictionaries containing the operating
            point conditions for all or a subset of the generalized
            coordinates, generalized speeds, and time derivatives of the
            generalized speeds. These will be substituted into the linearized
            system before the linearization is complete. Leave set to ``None``
            if you want the operating point to be an arbitrary set of symbols.
            Note that any reduction in symbols (whether substituted for numbers
            or expressions with a common parameter) will result in faster
            runtime.
        A_and_B : bool, optional
            If A_and_B=False (default), (M, A, B) is returned and of
            A_and_B=True, (A, B) is returned. See below.
        simplify : bool, optional
            Determines if returned values are simplified before return.
            For large expressions this may be time consuming. Default is False.

        Returns
        =======
        M, A, B : Matrices, ``A_and_B=False``
            Matrices from the implicit form:
                ``[M]*[q', u']^T = [A]*[q_ind, u_ind]^T + [B]*r``
        A, B : Matrices, ``A_and_B=True``
            Matrices from the explicit form:
                ``[q_ind', u_ind']^T = [A]*[q_ind, u_ind]^T + [B]*r``

        Notes
        =====

        Note that the process of solving with A_and_B=True is computationally
        intensive if there are many symbolic parameters. For this reason, it
        may be more desirable to use the default A_and_B=False, returning M, A,
        and B. More values may then be substituted in to these matrices later
        on. The state space form can then be found as A = P.T*M.LUsolve(A), B =
        P.T*M.LUsolve(B), where P = Linearizer.perm_mat.

        r   ) rC   rJ   
isinstancedictr   updater8   rT   rV   rX   rZ   r\   r_   rU   rW   rY   r^   r[   r]   r`   r?   r@   rA   r   r   rL   r
   col_joinrB   Tr   simplify)-rD   op_pointA_and_Brf   op_point_dictopr   r   r   r   r   r   M_qqM_uqcM_uqdM_uucM_uudM_uldA_qqA_uqcA_uqdA_quA_uucA_uudB_uC_0C_1C_2col2col3col1MM_eqr1c1r2c1r3c1r1c2r2c2r3c2AmatAmat_eqBmatBmat_eqA_contB_contr   r   r   	linearize  s   .













zLinearizer.linearize)NNNNNNr   )NFF)
__name__
__module____qualname____doc__rF   rJ   rG   rI   rH   r   r   r   r   r   r      s    
[! 2c                    s   t  ttfst  t |ttfst|}t t|kr"td fdd|D }tt }t|D ]
\}}d|||f< q5|S )ak  Compute the permutation matrix to change order of
    orig_vec into order of per_vec.

    Parameters
    ==========

    orig_vec : array_like
        Symbols in original ordering.
    per_vec : array_like
        Symbols in new ordering.

    Returns
    =======

    p_matrix : Matrix
        Permutation matrix such that orig_vec == (p_matrix * per_vec).
    zKorig_vec and per_vec must be the same length, and contain the same symbols.c                    s   g | ]}  |qS r   )index)r   iorig_vecr   r   r     s    z&permutation_matrix.<locals>.<listcomp>   )	ra   listtupler   r4   
ValueErrorr   r7   	enumerate)r   per_vecind_listp_matrixr   jr   r   r   rK     s   rK   N)__all__sympyr   r   r   sympy.core.symbolr   sympy.utilities.iterablesr   sympy.physics.vectorr	   !sympy.physics.mechanics.functionsr
   r   collectionsr   collections.abcr   r   rK   r   r   r   r   <module>   s       3