python - 在python中使用欧拉矩阵旋转对象

标签 python numpy matplotlib rotation euler-angles

我正在尝试使用欧拉矩阵旋转辊(或圆柱体)。为此,我使用以下函数。

def roll( R, zi, zf, Euler):

    # R is the radius of the cylinder
    # t is the angle which is running from 0 to 2*pi
    # zi is the lower z co-ordinate of cylinder
    # zf is the upper z co-ordinate of cylinder
    t = np.arange( 0, 2* np.pi + 0.1, 0.1)
    z = np.array([zi, zf])    
    t, z = np.meshgrid(t, z)
    p, q = t.shape
    r = R* np.ones([p,q], float)
    # polar co-ordinates to Cartesian co-ordinate
    x, y, z = pol2cart(r,t,z)

    # Euler rotation
    rot0 = np.array([x[0,:], y[0,:], z[0,:]])
    rot1 = np.array([x[1,:], y[1,:], z[1,:]])
    # mult is the matrix multiplication
    mat0 = mult( Euler, rot0)
    mat1 = mult( Euler, rot1)
    #
    x[0,:] = mat0[0,:]
    y[0,:] = mat0[1,:]
    z[0,:] = mat0[2,:]
    #
    x[1,:] = mat1[0,:]
    y[1,:] = mat1[1,:]
    z[1,:] = mat1[2,:]
    #
    return x, y, z

当欧拉旋转矩阵为 Euler = np.array([[1,0,0],[0,1,0],[0,0,1]]) 时,该函数运行良好。函数的输入为 x, y, z = roll(1, -2, 2, np.array([[1,0,0],[0,1,0],[0,0,1]]) ) 。使用ax.plot_surface(x,y,z)我得到了下图。 enter image description here

但是当我尝试通过欧拉矩阵 Euler = np.array([[1,0,0],[0,1/np.sqrt(2),-1/np.sqrt(2)],[0,1/np.sqrt(2),1/np.sqrt(2)]]) 旋转对象时我得到了意想不到的结果。

enter image description here

这里的旋转是45度数是正确的,但物体的形状不正确。

最佳答案

你就快到了。一些事情:

您实际上正在使用cylindrical coordinates不是球形的。我没有检查 numpy 是否有 cyl2cat 但这也不是很难自己编写:

def cyl2cat(r, theta, z):
    return (r*np.cos(theta), r*np.sin(theta), z)

对于旋转,我不太明白为什么你要分两步进行。 你可以使用numpy的ravel旋转网格:

# ...
rot = np.dot(Euler,np.array([x.ravel(), y.ravel(), z.ravel()]))

并 reshape 旋转坐标:

x_rot = rot[0,:].reshape(x.shape)
# ...

放在一起:

import numpy as np

def cyl2cart(r,theta,z):
    return (r*np.cos(theta), r*np.sin(theta), z)

def roll( R, zi, zf, Euler):               
    t = np.arange( 0, 2* np.pi + 0.1, 0.1)          
    z = np.array([zi, zf])                          
    t, z = np.meshgrid(t, z)                        
    p, q = t.shape                                  
    r = R* np.ones([p,q], float)                    
    # cylindrical coordinates to Cartesian coordinate   
    x, y, z = cyl2cart(r,t,z)                       

    # Euler rotation                                
    rot = np.dot(                                                
        Euler,                                            
        np.array([x.ravel(), y.ravel(), z.ravel()]) 
    )                                               
    x_rot = rot[0,:].reshape(x.shape)               
    y_rot = rot[1,:].reshape(y.shape)               
    z_rot = rot[2,:].reshape(z.shape)               
    return x_rot, y_rot, z_rot  

现在 roll 可以满足您的要求:

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

fig = plt.figure()
ax=fig.add_subplot(111, projection='3d')
x,y,z=roll(1,-2,2,np.array([[1,0,0],[0,1/np.sqrt(2),-1/np.sqrt(2)],[0,1/np.sqrt(2),1/np.sqrt(2)]]))
ax.plot_surface(x,y,z)
plt.show()

:

enter image description here

请注意,轴的纵横比不相同,这就是圆柱体确实具有椭圆曲率的原因。 Axes3D 中获取等轴并不简单,但可以通过绘制立方边界框来解决此问题(几乎是从 this SO 答案复制/粘贴):

ax.set_aspect('equal')    
max_range = np.array([x.max()-x.min(), y.max()-y.min(), z.max()-z.min()]).max()
Xb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][0].flatten() + 0.5*(x.max()+x.min())
Yb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][1].flatten() + 0.5*(y.max()+y.min())
Zb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][2].flatten() + 0.5*(z.max()+z.min())
# Comment or uncomment following both lines to test the fake bounding box:
for xb, yb, zb in zip(Xb, Yb, Zb):
   ax.plot([xb], [yb], [zb], 'w')

只需将其添加到 ax.plot_surface(... 后面,圆柱体就会出现圆曲率。

关于python - 在python中使用欧拉矩阵旋转对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47737772/

相关文章:

python - 如何将 request.get 的响应转换为 DataFrame?

python - 根据第 0 个列表的 argsort 对嵌套列表中的列表进行排序

python - 使用 Homebrew 软件为 numpy 安装 gfortran

python - 如何使 x 轴和 y 轴的比例相等?

python - 散点图同一点重复多次python

python - Pandas 在多列上搜索子字符串

python - 使用Python在Mysql数据库中插入一个值

python - 数据库中的平均分数(Django)

python - 有没有办法在一个命令中获取 python 中的中位数索引?

python - bundle_files = 1 使用 matplotlib 的 py2exe 失败