2017-12-10 61 views
2

オイラー行列を使ってロール(または円柱)を回転しようとしています。その目的のために私は以下の関数を使用します。オイラー回転行列が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]]))ある場合Pythonのオイラー行列を使ったオブジェクトの回転

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 

機能がうまく機能します。 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程度です。

+2

通常、np.dotは行列乗算です。なぜあなたはマルチを使うのですか?どのモジュールから入手できますか? –

+0

私はそれを知らなかった。だから、私は行列乗算@BMのために私自身の関数を書きました。 –

+1

何がマルチですか? –

答えて

3

あなたはほとんどそこにいました。いくつかの事があります:

実際にはcylindrical coordinates球体ではありませんです。 numpyのはcyl2catを持っている場合、私はチェックしませんでしたが、これは自分で作成することも本当に難しいことではありません。

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

次の2つのステップでそれを作る、なぜ私はかなり理解していない回転のために。

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

と回転座標再構築:一緒それを置く

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あなたは関数meshgridの回転を行うためにnumpyののravelを使用することができますあなたは何をしますか:

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() 

ほらをEt:

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(...とした後にこれを追加円柱は円形の曲率で現れる。

関連する問題