球形坐标旋转中的麻烦/ python实现

时间:2019-04-26 16:30:52

标签: python math rotation coordinates spherical-coordinate

我正在尝试实现在球坐标系中旋转的功能。 最后,我需要用Javascript实现,但首先,我想使其在python中工作,因为我对这种语言更加熟悉。

我想要一个以参数为参数的功能 rotate

  • 旋转角(alpha)
  • 要旋转的点的球坐标theta和phi(theta,phi)
  • 参考轴通过球体原点的球坐标theta和phi,围绕球体发生旋转(THETA,PHI)

到目前为止,我使用http://stla.github.io/stlapblog/posts/RotationSphericalCoordinates.html中的方法:

执行:

import numpy as np
from math import cos, sin, atan, pi
from cmath import exp, phase

#####################################################

def rotate(alpha, theta, phi, THETA, PHI, degrees=True):

    ## DEGREES TO RAD
    if degrees:
        alpha = pi/180 * alpha
        theta = pi/180 * theta
        phi = pi/180 * phi
        THETA = pi/180 * THETA
        PHI = pi/180 * PHI

    psi_ = Psi_(alpha, theta, phi, THETA, PHI)

    theta_  = 2 * atan(abs(psi_[1][1])/abs(psi_[0][0]))
    phi_ = phase(psi_[1][1]) - phase(psi_[0][0])

    ## RAD TO DEGREES
    if degrees:
        return theta_ * 180/pi, phi_ * 180/pi

    return theta_, phi_

#####################################################

def Psi_(alpha, theta, phi, THETA, PHI):

    return Rn(THETA, PHI, alpha) * \
           Psi(alpha, theta, phi)

#####################################################

def Psi(alpha, theta, phi):

    return np.array([
        [cos(theta)/2], 
        [exp(1j*phi) * sin(theta/2)]
    ])

#####################################################

def Rn(THETA, PHI, alpha):

    return Rz(PHI) * \
           Ry(THETA) * \
           Rz(alpha) * \
           Ry(THETA).conj().T * \
           Rz(PHI).conj().T

#####################################################

def Rx(alpha):

    return np.array([
        [cos(alpha/2), -1j * sin(alpha/2)], 
        [-1j * sin(alpha/2), cos(alpha/2)]
    ])

#####################################################

def Ry(alpha):

    return np.array([
        [cos(alpha/2), -sin(alpha/2)], 
        [sin(alpha/2), cos(alpha/2)]
    ])

#####################################################

def Rz(alpha):

    return np.array([
        [exp(-1j * alpha/2), 0], 
        [0, exp(1j * alpha/2)]
    ])

#####################################################

if __name__ == "__main__":

    print(rotate(
        alpha = 90,        # roation angle
        theta = 90,        # point theta
        phi = 0,           # point phi
        THETA = 0,         # axis theta
        PHI = 0,           # axis phi
        degrees = True     # angles in degrees
    ))

这应该提供一个新的cothenate theta = 90和phi =90。我得到的是theta = 180和phi = 90。

以下是一些其他输入和输出/预期的输出: results of rotation()

我真正不确定的部分是旋转函数中theta_和psi_的计算。在文章中,它说psi_应该是2x1矩阵,但是我得到的是2x2矩阵。

这是我的实现尝试:

{{1}}

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

如我的评论中所述,我不认为如果实际上想围绕任意<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <input type="text" v-model.number="count" @input="alert"> <button @click="add">+1</button> </div>xy旋转是最聪明的解决方案轴。所以我会用四元数。这实际上使用了zxy向量,但是qubit解决方案也使用了所有的zsine方法,因此这里没有优点也没有缺点

atan

提供

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

class Quaternion( object ):
    """ 
    Simplified Quaternion class for rotation of normalized vectors only!
    """

    def __init__( self, q0, qx, qy, qz ):
        """ 
        Internally uses floats to avoid integer division issues.

        @param q0: int or float
        @param qx: int or float
        @param qy: int or float
        @param qz: int or float
        """
        self._q0 = float( q0 )
        self._qx = float( qx )
        self._qy = float( qy )
        self._qz = float( qz )
        """
        Note if interpreted as rotation q0 -> -q0 doesn't make a difference
        q0 = cos( w ) so -cos( w ) = cos( w + pi ) and as the rotation
        is by twice the angle it is either 2w or 2w + 2pi, the latter being equivalent to the former.
        """

    def conjugate(q):
        """
        @return Quaternion
        """
        conjq = Quaternion( q._q0, -q._qx, -q._qy, -q._qz )
        return conjq

    def __mul__(q, r):
        """ 
        Non commutative quaternion multiplication.
        @return Quaternion
        """
        if isinstance(r, Quaternion):
            mq0 = q._q0 * r._q0 - q._qx * r._qx - q._qy * r._qy - q._qz * r._qz
            mqx = q._q0 * r._qx + q._qx * r._q0 + q._qy * r._qz - q._qz * r._qy
            mqy = q._q0 * r._qy - q._qx * r._qz + q._qy * r._q0 + q._qz * r._qx
            mqz = q._q0 * r._qz + q._qx * r._qy - q._qy * r._qx + q._qz * r._q0
            out = Quaternion(mq0, mqx, mqy, mqz)
        elif isinstance( r, ( int, long, float ) ):
            out = r * q
        else:
            raise TypeError
        return out

    def __getitem__( q, idx ):
        """
        @return float
        """
        if idx < 0:
            idx = 4 + idx
        if idx in [ 0, 1, 2, 3 ]:
            out = (q._q0, q._qx, q._qy, q._qz)[idx]
        else:
            raise IndexError
        return out

theta, phi = .4, .89
xA, yA, zA = np.sin( theta ) * np.cos( phi ), np.sin( theta ) * np.sin( phi ), np.cos( theta ) 
Theta, Phi = .5, 1.13
xB, yB, zB = np.sin( Theta ) * np.cos( Phi ), np.sin( Theta ) * np.sin( Phi ), np.cos( Theta ) 

qB = Quaternion( 0, xB, yB, zB  )

cX = [ xB ]
cY = [ yB ]
cZ = [ zB ]

for alpha in np.linspace( 0.1, 6, 20 ):
    qA = Quaternion( np.cos( 0.5 * alpha ), xA * np.sin( 0.5 * alpha ), yA * np.sin( 0.5 * alpha ), zA * np.sin( 0.5 * alpha )  )
    qAi = qA.conjugate()
    qBr = qA * ( qB * qAi )
    cX += [ qBr[1] ]
    cY += [ qBr[2] ]
    cZ += [ qBr[3] ]
    print np.arccos( qBr[3] ), np.arctan2( qBr[2], qBr[1] )


fig = plt.figure()
ax = fig.add_subplot( 111, projection='3d' )

u = np.linspace( 0, 2 * np.pi, 50 )
v = np.linspace( 0, np.pi, 25 )
x = .9 * np.outer( np.cos( u ), np.sin( v ) )
y = .9 * np.outer( np.sin( u ), np.sin( v ) )
z = .9 * np.outer( np.ones( np.size( u ) ), np.cos( v ) )

ax.plot_wireframe( x, y, z, color='g', alpha=.3 )
ax.plot( [ 0, xA ], [ 0, yA ],[ 0, zA ], color='r' )
ax.plot( [ 0, xB ], [ 0, yB ],[ 0, zB ], color='b' )
ax.plot( cX, cY, cZ , color='b' )


plt.show()

rotate B around A