K iddlmZmZmZmZmZmZmZmZ m Z ddl m Z ddl mZddlmZmZddlmZddlmZddgZGd de ZGd dZd Zy ) ) diffexpandsincossympifyeyezerosImmutableMatrix MatrixBase)Symbol)trigsimp)Vector _check_vector) translate)warn CoordinateSymReferenceFramecJeZdZdZfdZdZedZdZdZ dZ xZ S)ra A coordinate symbol/base scalar associated wrt a Reference Frame. Ideally, users should not instantiate this class. Instances of this class must only be accessed through the corresponding frame as 'frame[index]'. CoordinateSyms having the same frame and index parameters are equal (even though they may be instantiated separately). Parameters ========== name : string The display name of the CoordinateSym frame : ReferenceFrame The reference frame this base scalar belongs to index : 0, 1 or 2 The index of the dimension denoted by this coordinate variable Examples ======== >>> from sympy.physics.vector import ReferenceFrame, CoordinateSym >>> A = ReferenceFrame('A') >>> A[1] A_y >>> type(A[0]) >>> a_y = CoordinateSym('a_y', A, 1) >>> a_y == A[1] True ci}t|||t|||fi|}t||t ddvr t d||f|_|S)NrzInvalid index specified)super _sanitize__xnew__ _check_framerange ValueError_id)clsnameframeindex assumptionsobj __class__s `/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/physics/vector/frame.py__new__zCoordinateSym.__new__3sa  +s+gsD8K8U a #67 7%. c:|jg|jifSN)rrselfs r%__getnewargs_ex__zCoordinateSym.__getnewargs_ex__?s %DHH%r))r'c |jdS)Nr)rr*s r%r zCoordinateSym.frameBsxx{r'cXt|tr|j|jk(ryy)NTF) isinstancerrr+others r%__eq__zCoordinateSym.__eq__Fs$ e] +yyDHH$r'c||k( Sr)r0s r%__ne__zCoordinateSym.__ne__Ns5=  r'cv|jdj|jdfjS)Nr)r__hash__r*s r%r8zCoordinateSym.__hash__Qs/ $$& 4==??r') __name__ __module__ __qualname____doc__r&r,propertyr r2r5r8 __classcell__)r$s@r%rr s7#J *!@r'ceZdZdZdZd)dZdZdZdZeZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZd*dZ d+dZdZdZedZedZedZ edZ!edZ"ed Z#ed!Z$ed"Z%ed#Z&ed$Z'ed%Z(ed&Z)ed'Z*d(Z+y),raA reference frame in classical mechanics. ReferenceFrame is a class used to represent a reference frame in classical mechanics. It has a standard basis of three unit vectors in the frame's x, y, and z directions. It also can have a rotation relative to a parent frame; this rotation is defined by a direction cosine matrix relating this frame's basis vectors to the parent frame's basis vectors. It can also have an angular velocity vector, defined in another frame. rNct|ts td|3t|ttfs tdt |dk7r t d|D]}t|trtd|dz|dzd z|dz|d zd z|dz|d zd zg|_|jd z|dz|jd z|d z|jd z|d zg|_ d |jd|ddd |jd|d dd |jd|d dg|_ ||_ n|dz|dz|dzg|_|jdz|jdz|jdzg|_ d|jzd|jzd|jzg|_ gd|_ |ct|ttfs tdt |dk7r t d|D]}t|trtd||_ ||_ i|_ i|_i|_i|_i|_|j|j |j"g|_d|_t)t+gd|fg|_t)t+gd|fg|_t)t+gd|fg|_|]t|ttfs tdt |dk7r t d|D]}t|trtd n|dz|dz|dzg}t3|d|dt3|d |d t3|d |d f|_t6xj8d z c_t6j8|_y)!ab ReferenceFrame initialization method. A ReferenceFrame has a set of orthonormal basis vectors, along with orientations relative to other ReferenceFrames and angular velocities relative to other ReferenceFrames. Parameters ========== indices : tuple of str Enables the reference frame's basis unit vectors to be accessed by Python's square bracket indexing notation using the provided three indice strings and alters the printing of the unit vectors to reflect this choice. latexs : tuple of str Alters the LaTeX printing of the reference frame's basis unit vectors to the provided three valid LaTeX strings. Examples ======== >>> from sympy.physics.vector import ReferenceFrame, vlatex >>> N = ReferenceFrame('N') >>> N.x N.x >>> O = ReferenceFrame('O', indices=('1', '2', '3')) >>> O.x O['1'] >>> O['1'] O['1'] >>> P = ReferenceFrame('P', latexs=('A1', 'A2', 'A3')) >>> vlatex(P.x) 'A1' ``symbols()`` can be used to create multiple Reference Frames in one step, for example: >>> from sympy.physics.vector import ReferenceFrame >>> from sympy import symbols >>> A, B, C = symbols('A B C', cls=ReferenceFrame) >>> D, E = symbols('D E', cls=ReferenceFrame, indices=('1', '2', '3')) >>> A[0] A_x >>> D.x D['1'] >>> E.y E['2'] >>> type(A) == type(D) True Unit dyads for the ReferenceFrame can be accessed through the attributes ``xx``, ``xy``, etc. For example: >>> from sympy.physics.vector import ReferenceFrame >>> N = ReferenceFrame('N') >>> N.yz (N.y|N.z) >>> N.zx (N.z|N.x) >>> P = ReferenceFrame('P', indices=['1', '2', '3']) >>> P.xx (P['1']|P['1']) >>> P.zy (P['3']|P['2']) Unit dyadic is also accessible via the ``u`` attribute: >>> from sympy.physics.vector import ReferenceFrame >>> N = ReferenceFrame('N') >>> N.u (N.x|N.x) + (N.y|N.y) + (N.z|N.z) >>> P = ReferenceFrame('P', indices=['1', '2', '3']) >>> P.u (P['1']|P['1']) + (P['2']|P['2']) + (P['3']|P['3']) zNeed to supply a valid nameNzSupply the indices as a listrzSupply 3 indiceszIndices must be stringsz['rz']r7_z \mathbf{\hat{z}_{z}}z.xz.yz.z_x_y_zz\mathbf{\hat{%s}_x}z\mathbf{\hat{%s}_y}z\mathbf{\hat{%s}_z})xyzzLatex entries must be stringsr7rrrr7rrrr7z)Supply the variable names as a list/tuplezSupply 3 variable nameszVariable names must be strings)r/str TypeErrortuplelistlenrstr_vecslower pretty_vecs latex_vecsindicesr _var_dict _dcm_dict _dcm_cache _ang_vel_dict _ang_acc_dict_dlist_currMatrixrCrDrErvarlistr_countr!)r+rrUlatexs variablesis r%__init__zReferenceFrame.__init__dsZ$$9: :  gt}5 >??7|q  !344 ?!!S)#$=>> ?#UlWQZ7%?"UlWQZ7%?"UlWQZ7%?BDM"&!3gaj!@!%!3gaj!@!%!3gaj!@ CD >BZZ\=DQZ!I=AZZ\=DQZ!I=AZZ\=DQZ!I KDO #DL#TkTD[D4KIDM $ t 3 $ t 3 $ t 3 5D !7 E 6 E 6 EHDO+DL  fudm4 >??6{a !344 E!!S)#$CDD E%DO  ~~t'9'94;M;MN  6),d3456),d3456),d345  i%7 KLL9~" !:;; F!!S)#$DEE FdTk4$;?I%ilD!<%ilD!<%ilD!<>  "#** r'c*t|ts|dkr|j|Std|jd|k(r |j S|jd|k(r |j S|jd|k(r |jStd)z Returns basis vector for the provided index, if the index is a string. If the index is a number, returns the coordinate variable correspon- -ding to that index. rzInvalid index providedrr7rAzNot a defined index)r/rLr^rrUrFrGrH)r+inds r% __getitem__zReferenceFrame.__getitem__s#s#Qw||C(( !9:: <<?c !66M <<?c !66M <<?c !66M23 3r'cZt|j|j|jgSr))iterrFrGrHr*s r%__iter__zReferenceFrame.__iter__s TVVTVVTVV,--r'c|jS)zReturns the name of the frame. )rr*s r%__str__zReferenceFrame.__str__s yyr'c(dddd}||jvr td|gg}gg}||k7re|j}|D]J}|dj|j}|D]#}||vs||gz} | |vs|j | %L||k7re|D]} | d|k7s |j | |j tt|dk7r|dSd } t| j|||j|j) aReturns an inclusive list of reference frames that connect this reference frame to the provided reference frame. Parameters ========== other : ReferenceFrame The other reference frame to look for a connecting relationship to. num : integer ``0``, ``1``, and ``2`` will look for orientation, angular velocity, and angular acceleration relationships between the two frames, respectively. Returns ======= list Inclusive list of reference frames that connect this reference frame to the other reference frame. Examples ======== >>> from sympy.physics.vector import ReferenceFrame >>> A = ReferenceFrame('A') >>> B = ReferenceFrame('B') >>> C = ReferenceFrame('C') >>> D = ReferenceFrame('D') >>> B.orient_axis(A, A.x, 1.0) >>> C.orient_axis(B, B.x, 1.0) >>> D.orient_axis(C, C.x, 1.0) >>> D._dict_list(A, 0) [D, C, B, A] Raises ====== ValueError When no path is found between the two reference frames or ``num`` is an incorrect value. orientationzangular velocityzangular acceleration)rr7rAz$Valid values for num are 0, 1, or 2.)keyrz.No connecting {} path found between {} and {}.) keysrcopyr[appendremovesortrPformatr) r+r1num connect_typepossible_connecting_pathsoldlist frame_listframes_adjacent_to_lastadjacent_frameconnecting_pathmsgs r% _dict_listzReferenceFrame._dict_listsUT)-13  l'') )CD D&*VH!$'72/446G7 N *4R.*?*?*D*I*I*K'&=NN%Z7*47G*G*2KK5<<_M N N(72 ' BOr"e+)00A B "&&3&/ ( )Q .,Q/ />L$5tyy%**MNNr'cNddlm}|j|}|j|j}||j z}t t|dd}t t|dd}t t|dd}tt|||g|fgS)z4Angular velocity from time differentiating the DCM. rdynamicsymbolsT) recursiverAr) sympy.physics.vector.functionsrdcmr_tTr rrr]) r+ otherframerdcm2diffdiffed angvelmatw1w2w3s r% _w_diff_dcmzReferenceFrame._w_diff_dcmesA>>$'~001XZZ' fYq\*d ; fYq\*d ; fYq\*d ;B|,j9:;;r'ct||tjf|jvr|j|tjfS|j |t |j z}i}t|D]K\}}tjr!t||d||j |<7||||j |<M||j|tjf<|S)a4 Returns a dictionary which expresses the coordinate variables of this frame in terms of the variables of otherframe. If Vector.simp is True, returns a simplified version of the mapped values. Else, returns them without simplification. Simplification of the expressions may take time. Parameters ========== otherframe : ReferenceFrame The other frame to map the variables to Examples ======== >>> from sympy.physics.vector import ReferenceFrame, dynamicsymbols >>> A = ReferenceFrame('A') >>> q = dynamicsymbols('q') >>> B = A.orientnew('B', 'Axis', [q, A.z]) >>> A.variable_map(B) {A_x: B_x*cos(q(t)) - B_y*sin(q(t)), A_y: B_x*sin(q(t)) + B_y*cos(q(t)), A_z: B_z} fu)method) rrsimprVrr]r^ enumerater )r+r vars_matrixmappingrbrFs r% variable_mapzReferenceFrame.variable_mapps8 Z  $ 6>>:v{{";< <((:. 8J8J1KKKG!$ >1;;/7 A?C0EGDLLO,0;1~GDLLO,  > 9@DNNJ 4 5Nr'ct|||jvr|j|S|j|j|S)aReturns the angular acceleration Vector of the ReferenceFrame. Effectively returns the Vector: ``N_alpha_B`` which represent the angular acceleration of B in N, where B is self, and N is otherframe. Parameters ========== otherframe : ReferenceFrame The ReferenceFrame which the angular acceleration is returned in. Examples ======== >>> from sympy.physics.vector import ReferenceFrame >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> V = 10 * N.x >>> A.set_ang_acc(N, V) >>> A.ang_acc_in(N) 10*N.x )rrZ ang_vel_indt)r+rs r% ang_acc_inzReferenceFrame.ang_acc_insE: Z ++ +%%j1 1??:.11*= =r'ct||j|d}td}tt |dz D]}|||j ||dzz }|S)aReturns the angular velocity Vector of the ReferenceFrame. Effectively returns the Vector: ^N omega ^B which represent the angular velocity of B in N, where B is self, and N is otherframe. Parameters ========== otherframe : ReferenceFrame The ReferenceFrame which the angular velocity is returned in. Examples ======== >>> from sympy.physics.vector import ReferenceFrame >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> V = 10 * N.x >>> A.set_ang_vel(N, V) >>> A.ang_vel_in(N) 10*N.x r7r)rrrrrPrY)r+rflistoutvecrbs r%rzReferenceFrame.ang_vel_insg: Z  A.s5zA~& ;A eAh,,U1q5\: :F ; r'cNt|||jvr|j|S|j|d}td}t t |dz D]}|||j ||dzz}||j|<|j|j|<|S)aReturns the direction cosine matrix of this reference frame relative to the provided reference frame. The returned matrix can be used to express the orthogonal unit vectors of this frame in terms of the orthogonal unit vectors of ``otherframe``. Parameters ========== otherframe : ReferenceFrame The reference frame which the direction cosine matrix of this frame is formed relative to. Examples ======== The following example rotates the reference frame A relative to N by a simple rotation and then calculates the direction cosine matrix of N relative to A. >>> from sympy import symbols, sin, cos >>> from sympy.physics.vector import ReferenceFrame >>> q1 = symbols('q1') >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> A.orient_axis(N, q1, N.x) >>> N.dcm(A) Matrix([ [1, 0, 0], [0, cos(q1), -sin(q1)], [0, sin(q1), cos(q1)]]) The second row of the above direction cosine matrix represents the ``N.y`` unit vector in N expressed in A. Like so: >>> Ny = 0*A.x + cos(q1)*A.y - sin(q1)*A.z Thus, expressing ``N.y`` in A should return the same result: >>> N.y.express(A) cos(q1)*A.y - sin(q1)*A.z Notes ===== It is important to know what form of the direction cosine matrix is returned. If ``B.dcm(A)`` is called, it means the "direction cosine matrix of B rotated relative to A". This is the matrix :math:`{}^B\mathbf{C}^A` shown in the following relationship: .. math:: \begin{bmatrix} \hat{\mathbf{b}}_1 \\ \hat{\mathbf{b}}_2 \\ \hat{\mathbf{b}}_3 \end{bmatrix} = {}^B\mathbf{C}^A \begin{bmatrix} \hat{\mathbf{a}}_1 \\ \hat{\mathbf{a}}_2 \\ \hat{\mathbf{a}}_3 \end{bmatrix}. :math:`{}^B\mathbf{C}^A` is the matrix that expresses the B unit vectors in terms of the A unit vectors. rrr7)rrXrrrrPrWr)r+rroutdcmrbs r%rzReferenceFrame.dcmsP Z  (??:. . A.Qs5zA~& ?AeAh00q1u>>F ?'- #&,hh d# r'c.|jj}g}g}||vrg|D]}||jvr||gz }||gz }|D]}|j|=|D]}|j|=ix|_|jd<i|_ng}t |}d} |rs| rq|j d} | |vrW|j | | jj} | D]'} | |k(rtdd} n|j | )|r| rq|jj||ji|jj||i|jj||ji|jj||iy)NrTzxLoops are defined among the orientation of frames. This is likely not desired and may cause errors in your calculations.F) rXrprWr[rOpoprrrupdater) r+parent parent_orientframes dcm_dict_del dcm_cache_delr visitedqueuecontnode neighborsneighbors r%_dcmzReferenceFrame._dcm8s%%'  V  )DNN* UG+L%(  )& *OOD) *& +$$T* +/1 0DNT[[^ DOGLEDDyy|w&NN4( $ 3 3 5I$-/#v- "FG$)D! X./ D v}78} 56  89  $ !67r'c<ddlm}t|t|tst|tr||}}t |}t |}|j|dk(s td|j|j}|jdd}td||jzz t|ztd|d |dg|dd|d g|d |ddggt!|zz||jzz}|j#|||j%|j&} | |j|jz} |j(j+|| i|j(j+|| ii|_y)aZSets the orientation of this reference frame with respect to a parent reference frame by rotating through an angle about an axis fixed in the parent reference frame. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. axis : Vector Vector fixed in the parent frame about about which this frame is rotated. It need not be a unit vector and the rotation follows the right hand rule. angle : sympifiable Angle in radians by which it the frame is to be rotated. Warns ====== UserWarning If the orientation creates a kinematic loop. Examples ======== Setup variables for the examples: >>> from sympy import symbols >>> from sympy.physics.vector import ReferenceFrame >>> q1 = symbols('q1') >>> N = ReferenceFrame('N') >>> B = ReferenceFrame('B') >>> B.orient_axis(N, N.x, q1) The ``orient_axis()`` method generates a direction cosine matrix and its transpose which defines the orientation of B relative to N and vice versa. Once orient is called, ``dcm()`` outputs the appropriate direction cosine matrix: >>> B.dcm(N) Matrix([ [1, 0, 0], [0, cos(q1), sin(q1)], [0, -sin(q1), cos(q1)]]) >>> N.dcm(B) Matrix([ [1, 0, 0], [0, cos(q1), -sin(q1)], [0, sin(q1), cos(q1)]]) The following two lines show that the sense of the rotation can be defined by negating the vector direction or the angle. Both lines produce the same result. >>> B.orient_axis(N, -N.x, q1) >>> B.orient_axis(N, N.x, -q1) rrzAxis cannot be time-varying.rrAr7N)rrrr/rrrrrexpress normalizeargsrrrr]rrrrrYrrV) r+raxisanglertheta unit_axisunit_colparent_orient_axisthetadwvecs r% orient_axiszReferenceFrame.orient_axismsz BV$'Juf,E%DT"wwv!#;< <LL(224 >>!$Q' Vh+ +s5z 9 Q! hqk2a[!hqk\2qk\8A;24 5 J  "HJJ.  /  &,-n//0dll6*4466 !!64.1##TD5M2r'ct|t|ts td|j ||j y)aSets the orientation of this reference frame relative to another (parent) reference frame using a direction cosine matrix that describes the rotation from the parent to the child. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. dcm : Matrix, shape(3, 3) Direction cosine matrix that specifies the relative rotation between the two reference frames. Warns ====== UserWarning If the orientation creates a kinematic loop. Examples ======== Setup variables for the examples: >>> from sympy import symbols, Matrix, sin, cos >>> from sympy.physics.vector import ReferenceFrame >>> q1 = symbols('q1') >>> A = ReferenceFrame('A') >>> B = ReferenceFrame('B') >>> N = ReferenceFrame('N') A simple rotation of ``A`` relative to ``N`` about ``N.x`` is defined by the following direction cosine matrix: >>> dcm = Matrix([[1, 0, 0], ... [0, cos(q1), -sin(q1)], ... [0, sin(q1), cos(q1)]]) >>> A.orient_explicit(N, dcm) >>> A.dcm(N) Matrix([ [1, 0, 0], [0, cos(q1), sin(q1)], [0, -sin(q1), cos(q1)]]) This is equivalent to using ``orient_axis()``: >>> B.orient_axis(N, N.x, q1) >>> B.dcm(N) Matrix([ [1, 0, 0], [0, cos(q1), sin(q1)], [0, -sin(q1), cos(q1)]]) **Note carefully that** ``N.dcm(B)`` **(the transpose) would be passed into** ``orient_explicit()`` **for** ``A.dcm(N)`` **to match** ``B.dcm(N)``: >>> A.orient_explicit(N, N.dcm(B)) >>> A.dcm(N) Matrix([ [1, 0, 0], [0, cos(q1), sin(q1)], [0, -sin(q1), cos(q1)]]) +Amounts must be a SymPy Matrix type object.N)rr/r rM orient_dcmr)r+rrs r%orient_explicitzReferenceFrame.orient_explicits7D V#z*IJ J &r'c.t|t|ts td|j ||j |j |}|jj||i|jj|| ii|_ y)aUSets the orientation of this reference frame relative to another (parent) reference frame using a direction cosine matrix that describes the rotation from the child to the parent. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. dcm : Matrix, shape(3, 3) Direction cosine matrix that specifies the relative rotation between the two reference frames. Warns ====== UserWarning If the orientation creates a kinematic loop. Examples ======== Setup variables for the examples: >>> from sympy import symbols, Matrix, sin, cos >>> from sympy.physics.vector import ReferenceFrame >>> q1 = symbols('q1') >>> A = ReferenceFrame('A') >>> B = ReferenceFrame('B') >>> N = ReferenceFrame('N') A simple rotation of ``A`` relative to ``N`` about ``N.x`` is defined by the following direction cosine matrix: >>> dcm = Matrix([[1, 0, 0], ... [0, cos(q1), sin(q1)], ... [0, -sin(q1), cos(q1)]]) >>> A.orient_dcm(N, dcm) >>> A.dcm(N) Matrix([ [1, 0, 0], [0, cos(q1), sin(q1)], [0, -sin(q1), cos(q1)]]) This is equivalent to using ``orient_axis()``: >>> B.orient_axis(N, N.x, q1) >>> B.dcm(N) Matrix([ [1, 0, 0], [0, cos(q1), sin(q1)], [0, -sin(q1), cos(q1)]]) rN) rr/r rMrrrrYrrV)r+rrrs r%rzReferenceFrame.orient_dcmsp V#z*IJ J &#%% ' !!64.1##TD5M2r'c |dk(r;tgddt|t| gdt|t|ggS|dk(r;tt|dt|ggdt| dt|ggS|dk(r;tt|t| dgt|t|dggdgSy) z'DCM for simple axis 1,2,or 3 rotations.r7rIrrArJrrKN)r]rr)r+rrs r%_rotzReferenceFrame._rotUs 199s5zCJ;7s5z3u:689 9QYCJ3u:6$ ZKCJ79: :QYCJU Q7JE A6$&' 'r'ct|}t|D]$\}}t|trt |||<&d}t t |dd}||vr td|Dcgc] }t|}}t|dt|zcxk(rdk(stdtdt||D cgc]\} } |j| | } } } ||| fScc}wcc} } w)aHelper for orient_body_fixed and orient_space_fixed. Parameters ========== angles : 3-tuple of sympifiable Three angles in radians used for the successive rotations. rotation_order : 3 character string or 3 digit integer Order of the rotations. The order can be specified by the strings ``'XZX'``, ``'131'``, or the integer ``131``. There are 12 unique valid rotation orders. Returns ======= amounts : list List of sympifiables corresponding to the rotation angles. rot_order : list List of integers corresponding to the axis of rotation. rot_matrices : list List of DCM around the given axis with corresponding magnitude. 123231312132213321121131212232313323XYZxyz123123z(The rotation order is not a valid order.rz*Body orientation takes 3 values & 3 orders) rOrr/rrrrLrMintrPzipr) r+anglesrotation_orderamountsrbvapproved_orders rot_orderrorderamount rot_matricess r%_parse_consecutive_rotationsz+ReferenceFrame._parse_consecutive_rotationsds .v,g& (DAqa($QZ  (Bc.18XF O +FG G%./SV/ /G C N 27a7HI I8HI I/29g/FH+UF %0H H <// 0Hs )C'C,cddlm}t||j||\}}}|j ||d|dz|dzt dDcgc]}t dd} }t|D],\} } || j|j| | | dz <.| d|dj| d|dj| dzzzz\} } }| |jz| |jzz||jzz}|jj||i|jj|| ii|_ycc}w)a,Rotates this reference frame relative to the parent reference frame by right hand rotating through three successive body fixed simple axis rotations. Each subsequent axis of rotation is about the "body fixed" unit vectors of a new intermediate reference frame. This type of rotation is also referred to rotating through the `Euler and Tait-Bryan Angles`_. .. _Euler and Tait-Bryan Angles: https://en.wikipedia.org/wiki/Euler_angles The computed angular velocity in this method is by default expressed in the child's frame, so it is most preferable to use ``u1 * child.x + u2 * child.y + u3 * child.z`` as generalized speeds. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. angles : 3-tuple of sympifiable Three angles in radians used for the successive rotations. rotation_order : 3 character string or 3 digit integer Order of the rotations about each intermediate reference frames' unit vectors. The Euler rotation about the X, Z', X'' axes can be specified by the strings ``'XZX'``, ``'131'``, or the integer ``131``. There are 12 unique valid rotation orders (6 Euler and 6 Tait-Bryan): zxz, xyx, yzy, zyz, xzx, yxy, xyz, yzx, zxy, xzy, zyx, and yxz. Warns ====== UserWarning If the orientation creates a kinematic loop. Examples ======== Setup variables for the examples: >>> from sympy import symbols >>> from sympy.physics.vector import ReferenceFrame >>> q1, q2, q3 = symbols('q1, q2, q3') >>> N = ReferenceFrame('N') >>> B = ReferenceFrame('B') >>> B1 = ReferenceFrame('B1') >>> B2 = ReferenceFrame('B2') >>> B3 = ReferenceFrame('B3') For example, a classic Euler Angle rotation can be done by: >>> B.orient_body_fixed(N, (q1, q2, q3), 'XYX') >>> B.dcm(N) Matrix([ [ cos(q2), sin(q1)*sin(q2), -sin(q2)*cos(q1)], [sin(q2)*sin(q3), -sin(q1)*sin(q3)*cos(q2) + cos(q1)*cos(q3), sin(q1)*cos(q3) + sin(q3)*cos(q1)*cos(q2)], [sin(q2)*cos(q3), -sin(q1)*cos(q2)*cos(q3) - sin(q3)*cos(q1), -sin(q1)*sin(q3) + cos(q1)*cos(q2)*cos(q3)]]) This rotates reference frame B relative to reference frame N through ``q1`` about ``N.x``, then rotates B again through ``q2`` about ``B.y``, and finally through ``q3`` about ``B.x``. It is equivalent to three successive ``orient_axis()`` calls: >>> B1.orient_axis(N, N.x, q1) >>> B2.orient_axis(B1, B1.y, q2) >>> B3.orient_axis(B2, B2.x, q3) >>> B3.dcm(N) Matrix([ [ cos(q2), sin(q1)*sin(q2), -sin(q2)*cos(q1)], [sin(q2)*sin(q3), -sin(q1)*sin(q3)*cos(q2) + cos(q1)*cos(q3), sin(q1)*cos(q3) + sin(q3)*cos(q1)*cos(q2)], [sin(q2)*cos(q3), -sin(q1)*cos(q2)*cos(q3) - sin(q3)*cos(q1), -sin(q1)*sin(q3) + cos(q1)*cos(q2)*cos(q3)]]) Acceptable rotation orders are of length 3, expressed in as a string ``'XYZ'`` or ``'123'`` or integer ``123``. Rotations about an axis twice in a row are prohibited. >>> B.orient_body_fixed(N, (q1, q2, 0), 'ZXZ') >>> B.orient_body_fixed(N, (q1, q2, 0), '121') >>> B.orient_body_fixed(N, (q1, q2, q3), 123) rrr7rArNrrrrrrr rrrrrFrGrHrYrrVr+rrrrrrrrBrot_vecsrbru1u2u3rs r%orient_body_fixedz ReferenceFrame.orient_body_fixedsVd BV+/+L+L N,$(L &,q/LO;l1oMN).q2AE!QK22!), HHAu%,QZ__^5F5F%GHQK " Ha[<?#4#4 QK,q/++hqk9 9$;; BDFF{R$&&[(2;6 !!64.1##TD5M23E cddlm}t||j||\}}}|j ||d|dz|dzt dDcgc]}t dd} }t|D],\} } || j|j| | | dz <.| d|dj| d|dj| dzzzz\} } }| |jz| |jzz||jzz}|jj||i|jj|| ii|_ycc}w)a[Rotates this reference frame relative to the parent reference frame by right hand rotating through three successive space fixed simple axis rotations. Each subsequent axis of rotation is about the "space fixed" unit vectors of the parent reference frame. The computed angular velocity in this method is by default expressed in the child's frame, so it is most preferable to use ``u1 * child.x + u2 * child.y + u3 * child.z`` as generalized speeds. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. angles : 3-tuple of sympifiable Three angles in radians used for the successive rotations. rotation_order : 3 character string or 3 digit integer Order of the rotations about the parent reference frame's unit vectors. The order can be specified by the strings ``'XZX'``, ``'131'``, or the integer ``131``. There are 12 unique valid rotation orders. Warns ====== UserWarning If the orientation creates a kinematic loop. Examples ======== Setup variables for the examples: >>> from sympy import symbols >>> from sympy.physics.vector import ReferenceFrame >>> q1, q2, q3 = symbols('q1, q2, q3') >>> N = ReferenceFrame('N') >>> B = ReferenceFrame('B') >>> B1 = ReferenceFrame('B1') >>> B2 = ReferenceFrame('B2') >>> B3 = ReferenceFrame('B3') >>> B.orient_space_fixed(N, (q1, q2, q3), '312') >>> B.dcm(N) Matrix([ [ sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), sin(q1)*cos(q2), sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1)], [-sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1), cos(q1)*cos(q2), sin(q1)*sin(q3) + sin(q2)*cos(q1)*cos(q3)], [ sin(q3)*cos(q2), -sin(q2), cos(q2)*cos(q3)]]) is equivalent to: >>> B1.orient_axis(N, N.z, q1) >>> B2.orient_axis(B1, N.x, q2) >>> B3.orient_axis(B2, N.y, q3) >>> B3.dcm(N).simplify() Matrix([ [ sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), sin(q1)*cos(q2), sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1)], [-sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1), cos(q1)*cos(q2), sin(q1)*sin(q3) + sin(q2)*cos(q1)*cos(q3)], [ sin(q3)*cos(q2), -sin(q2), cos(q2)*cos(q3)]]) It is worth noting that space-fixed and body-fixed rotations are related by the order of the rotations, i.e. the reverse order of body fixed will give space fixed and vice versa. >>> B.orient_space_fixed(N, (q1, q2, q3), '231') >>> B.dcm(N) Matrix([ [cos(q1)*cos(q2), sin(q1)*sin(q3) + sin(q2)*cos(q1)*cos(q3), -sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1)], [ -sin(q2), cos(q2)*cos(q3), sin(q3)*cos(q2)], [sin(q1)*cos(q2), sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1), sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3)]]) >>> B.orient_body_fixed(N, (q3, q2, q1), '132') >>> B.dcm(N) Matrix([ [cos(q1)*cos(q2), sin(q1)*sin(q3) + sin(q2)*cos(q1)*cos(q3), -sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1)], [ -sin(q2), cos(q2)*cos(q3), sin(q3)*cos(q2)], [sin(q1)*cos(q2), sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1), sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3)]]) rrrAr7rNrrs r%orient_space_fixedz!ReferenceFrame.orient_space_fixedsV` BV+/+L+L N,$(L &,q/LO;l1oMN).q2AE!QK22!), HHAu%,QZ__^5F5F%GHQK " Ha[<?#4#4 QK,q/++hqk9 9$;; BDFF{R$&&[(2;6 !!64.1##TD5M23rc Hddlm}t|t|}t |D]$\}}t |t rt|||<&t |ttft|dk(zs td|\}}}} t|dz|dzz|dzz | dzz d||z|| zz zd||z|| zzzgd||z|| zzz|dz|dzz |dzz| dzz d|| z||zz zgd|| z||zz zd||z|| zzz|dz|dzz |dzz | dzzgg} |j|| |j} |\}}}} t|| } t|| } t|| }t| | }d| |z|| zz||zz | |zz z}d||z||zz| | zz | |zz z}d||z| |zz||zz | | zz z}t t|||g|fg}|jj!||i|jj!|| ii|_y)a Sets the orientation of this reference frame relative to a parent reference frame via an orientation quaternion. An orientation quaternion is defined as a finite rotation a unit vector, ``(lambda_x, lambda_y, lambda_z)``, by an angle ``theta``. The orientation quaternion is described by four parameters: - ``q0 = cos(theta/2)`` - ``q1 = lambda_x*sin(theta/2)`` - ``q2 = lambda_y*sin(theta/2)`` - ``q3 = lambda_z*sin(theta/2)`` See `Quaternions and Spatial Rotation `_ on Wikipedia for more information. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. numbers : 4-tuple of sympifiable The four quaternion scalar numbers as defined above: ``q0``, ``q1``, ``q2``, ``q3``. Warns ====== UserWarning If the orientation creates a kinematic loop. Examples ======== Setup variables for the examples: >>> from sympy import symbols >>> from sympy.physics.vector import ReferenceFrame >>> q0, q1, q2, q3 = symbols('q0 q1 q2 q3') >>> N = ReferenceFrame('N') >>> B = ReferenceFrame('B') Set the orientation: >>> B.orient_quaternion(N, (q0, q1, q2, q3)) >>> B.dcm(N) Matrix([ [q0**2 + q1**2 - q2**2 - q3**2, 2*q0*q3 + 2*q1*q2, -2*q0*q2 + 2*q1*q3], [ -2*q0*q3 + 2*q1*q2, q0**2 - q1**2 + q2**2 - q3**2, 2*q0*q1 + 2*q2*q3], [ 2*q0*q2 + 2*q1*q3, -2*q0*q1 + 2*q2*q3, q0**2 - q1**2 - q2**2 + q3**2]]) rrz'Amounts are a list or tuple of length 4rAN)rrrrOrr/rrrNrPrMr]rrrrYrrV)r+rnumbersrrbrq0q1q2q3parent_orient_quaterniontq0dq1dq2dq3drrrrs r%orient_quaternionz ReferenceFrame.orient_quaternionTsj BVw-g& (DAqa($QZ  (7T5M2c'la6GHEF F BB RURU]RU*RU2"r'BG+,"r'BG+,."r'BG+,URU]RU*RU2"r'BG+,."r'BG+,"r'BG+,URU]RU*RU24 5 6 ! &23    BB2qk2qk2qk2qk #(S2X%b038; < #(S2X%b038; < #(S2X%b038; <B|,d345 !!64.1##TD5M2r'ct|d}tt|dd}|j}||vr t d|dk(r|j ||d|dy |dk(r|j ||y |d k(r|j|||y |d k(r|j|||y |d k(r|j||y td )aSets the orientation of this reference frame relative to another (parent) reference frame. .. note:: It is now recommended to use the ``.orient_axis, .orient_body_fixed, .orient_space_fixed, .orient_quaternion`` methods for the different rotation types. Parameters ========== parent : ReferenceFrame Reference frame that this reference frame will be rotated relative to. rot_type : str The method used to generate the direction cosine matrix. Supported methods are: - ``'Axis'``: simple rotations about a single common axis - ``'DCM'``: for setting the direction cosine matrix directly - ``'Body'``: three successive rotations about new intermediate axes, also called "Euler and Tait-Bryan angles" - ``'Space'``: three successive rotations about the parent frames' unit vectors - ``'Quaternion'``: rotations defined by four parameters which result in a singularity free direction cosine matrix amounts : Expressions defining the rotation angles or direction cosine matrix. These must match the ``rot_type``. See examples below for details. The input types are: - ``'Axis'``: 2-tuple (expr/sym/func, Vector) - ``'DCM'``: Matrix, shape(3,3) - ``'Body'``: 3-tuple of expressions, symbols, or functions - ``'Space'``: 3-tuple of expressions, symbols, or functions - ``'Quaternion'``: 4-tuple of expressions, symbols, or functions rot_order : str or int, optional If applicable, the order of the successive of rotations. The string ``'123'`` and integer ``123`` are equivalent, for example. Required for ``'Body'`` and ``'Space'``. Warns ====== UserWarning If the orientation creates a kinematic loop. rrr*The supplied order is not an approved typeAXISr7rDCMBODYSPACE QUATERNION#That is not an implemented rotationN) rrrLupperrMrrrrrNotImplementedError)r+rrot_typerrrs r%orientzReferenceFrame.orientsh VBc)nhA >># O +HI I v    VWQZ <     1    " "67I >   # #FGY ?  %  " "67 3&&KL Lr'c|j||||}d} tt|dd}|j}|| vr t d|dk(r|j ||d|d|S|d k(r|j |||S|d k(r|j||||S|d k(r|j||||S|d k(r|j|||Std )al Returns a new reference frame oriented with respect to this reference frame. See ``ReferenceFrame.orient()`` for detailed examples of how to orient reference frames. Parameters ========== newname : str Name for the new reference frame. rot_type : str The method used to generate the direction cosine matrix. Supported methods are: - ``'Axis'``: simple rotations about a single common axis - ``'DCM'``: for setting the direction cosine matrix directly - ``'Body'``: three successive rotations about new intermediate axes, also called "Euler and Tait-Bryan angles" - ``'Space'``: three successive rotations about the parent frames' unit vectors - ``'Quaternion'``: rotations defined by four parameters which result in a singularity free direction cosine matrix amounts : Expressions defining the rotation angles or direction cosine matrix. These must match the ``rot_type``. See examples below for details. The input types are: - ``'Axis'``: 2-tuple (expr/sym/func, Vector) - ``'DCM'``: Matrix, shape(3,3) - ``'Body'``: 3-tuple of expressions, symbols, or functions - ``'Space'``: 3-tuple of expressions, symbols, or functions - ``'Quaternion'``: 4-tuple of expressions, symbols, or functions rot_order : str or int, optional If applicable, the order of the successive of rotations. The string ``'123'`` and integer ``123`` are equivalent, for example. Required for ``'Body'`` and ``'Space'``. indices : tuple of str Enables the reference frame's basis unit vectors to be accessed by Python's square bracket indexing notation using the provided three indice strings and alters the printing of the unit vectors to reflect this choice. latexs : tuple of str Alters the LaTeX printing of the reference frame's basis unit vectors to the provided three valid LaTeX strings. Examples ======== >>> from sympy import symbols >>> from sympy.physics.vector import ReferenceFrame, vlatex >>> q0, q1, q2, q3 = symbols('q0 q1 q2 q3') >>> N = ReferenceFrame('N') Create a new reference frame A rotated relative to N through a simple rotation. >>> A = N.orientnew('A', 'Axis', (q0, N.x)) Create a new reference frame B rotated relative to N through body-fixed rotations. >>> B = N.orientnew('B', 'Body', (q1, q2, q3), '123') Create a new reference frame C rotated relative to N through a simple rotation with unique indices and LaTeX printing. >>> C = N.orientnew('C', 'Axis', (q0, N.x), indices=('1', '2', '3'), ... latexs=(r'\hat{\mathbf{c}}_1',r'\hat{\mathbf{c}}_2', ... r'\hat{\mathbf{c}}_3')) >>> C['1'] C['1'] >>> print(vlatex(C['1'])) \hat{\mathbf{c}}_1 )rarUr`rrrrrr7rrrrrr) r$rrLrrMrrrrrr) r+newnamerrrrarUr`newframers r% orientnewzReferenceFrame.orientnewsd>>'Y*1&"BBc)nhA >># O +HI I v   wqz71: >    $ $T7 3   & &tWi @  ' 'gy A  %  & &tW 5&&KL Lr'c|dk(r td}t|}t||jj ||i|jj || iy)a-Define the angular acceleration Vector in a ReferenceFrame. Defines the angular acceleration of this ReferenceFrame, in another. Angular acceleration can be defined with respect to multiple different ReferenceFrames. Care must be taken to not create loops which are inconsistent. Parameters ========== otherframe : ReferenceFrame A ReferenceFrame to define the angular acceleration in value : Vector The Vector representing angular acceleration Examples ======== >>> from sympy.physics.vector import ReferenceFrame >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> V = 10 * N.x >>> A.set_ang_acc(N, V) >>> A.ang_acc_in(N) 10*N.x rN)rrrrZrr+rvalues r% set_ang_acczReferenceFrame.set_ang_accpY: A:1IEe$Z  !!:u"56  ''v7r'c|dk(r td}t|}t||jj ||i|jj || iy)aDefine the angular velocity vector in a ReferenceFrame. Defines the angular velocity of this ReferenceFrame, in another. Angular velocity can be defined with respect to multiple different ReferenceFrames. Care must be taken to not create loops which are inconsistent. Parameters ========== otherframe : ReferenceFrame A ReferenceFrame to define the angular velocity in value : Vector The Vector representing angular velocity Examples ======== >>> from sympy.physics.vector import ReferenceFrame >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> V = 10 * N.x >>> A.set_ang_vel(N, V) >>> A.ang_vel_in(N) 10*N.x rN)rrrrYrr s r% set_ang_velzReferenceFrame.set_ang_velrr'c|jS)z=The basis Vector for the ReferenceFrame, in the x direction. )rCr*s r%rFzReferenceFrame.x wwr'c|jS)z=The basis Vector for the ReferenceFrame, in the y direction. )rDr*s r%rGzReferenceFrame.yrr'c|jS)z=The basis Vector for the ReferenceFrame, in the z direction. )rEr*s r%rHzReferenceFrame.zrr'cVtj|j|jS)z:Unit dyad of basis Vectors x and x for the ReferenceFrame.)routerrFr*s r%xxzReferenceFrame.xx||DFFDFF++r'cVtj|j|jS)z:Unit dyad of basis Vectors x and y for the ReferenceFrame.)rrrFrGr*s r%xyzReferenceFrame.xyrr'cVtj|j|jS)z:Unit dyad of basis Vectors x and z for the ReferenceFrame.)rrrFrHr*s r%xzzReferenceFrame.xzrr'cVtj|j|jS)z:Unit dyad of basis Vectors y and x for the ReferenceFrame.)rrrGrFr*s r%yxzReferenceFrame.yxrr'cVtj|j|jS)z:Unit dyad of basis Vectors y and y for the ReferenceFrame.)rrrGr*s r%yyzReferenceFrame.yyrr'cVtj|j|jS)z:Unit dyad of basis Vectors y and z for the ReferenceFrame.)rrrGrHr*s r%yzzReferenceFrame.yzrr'cVtj|j|jS)z:Unit dyad of basis Vectors z and x for the ReferenceFrame.)rrrHrFr*s r%zxzReferenceFrame.zxrr'cVtj|j|jS)z:Unit dyad of basis Vectors z and y for the ReferenceFrame.)rrrHrGr*s r%zyzReferenceFrame.zyrr'cVtj|j|jS)z:Unit dyad of basis Vectors z and z for the ReferenceFrame.)rrrHr*s r%zzzReferenceFrame.zzrr'cN|j|jz|jzS)z#Unit dyadic for the ReferenceFrame.)rr"r*r*s r%uzReferenceFrame.us ww 477**r'cddlm}|j|}||g||d}t|dk(r|dSt |S)aReturns the partial angular velocities of this frame in the given frame with respect to one or more provided generalized speeds. Parameters ========== frame : ReferenceFrame The frame with which the angular velocity is defined in. gen_speeds : functions of time The generalized speeds. Returns ======= partial_velocities : tuple of Vector The partial angular velocity vectors corresponding to the provided generalized speeds. Examples ======== >>> from sympy.physics.vector import ReferenceFrame, dynamicsymbols >>> N = ReferenceFrame('N') >>> A = ReferenceFrame('A') >>> u1, u2 = dynamicsymbols('u1, u2') >>> A.set_ang_vel(N, u1 * A.x + u2 * N.y) >>> A.partial_velocity(N, u1) A.x >>> A.partial_velocity(N, u1, u2) (A.x, N.y) r)partial_velocityr7)rr.rrPrN)r+r gen_speedsr.velpartialss r%r.zReferenceFrame.partial_velocitysL@ Dooe$#SE:u=a@ x=A A; ? "r')NNN)r)rNNN),r9r:r;r<r_rcrfrirk__repr__rrrrrrrrrrrrrrrrr rrr=rFrGrHrrrr r"r$r&r(r*r,r.r4r'r%rrUs FY+v4*.HFOP <)V!>F"HTl38jWrH'TCJ '(0TbH`DZxNM`?A7;n`"8H"8H,,,,,,,,,,,,,,,,,,++(#r'cTddlm}t|ts||tdy)Nr7)VectorTypeErrorA)vectorr4r/r)r1r4s r%rr$s&' e^ ,e^C%899 -r'N)sympyrrrrrrr r r]r sympy.core.symbolr sympy.simplify.trigsimpr sympy.physics.vector.vectorrrsympy.utilities.miscrwarningsr__all__rrrr4r'r%r>sTGGG$,=* , -E@FE@PL#L#^.:r'