2017-12-10 3 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]]))을 때파이썬에서 오일러 매트릭스를 사용하는 객체의 회전

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

나는 그것을 몰랐다. 그래서 저는 행렬 곱셈을위한 함수를 작성했습니다. –

+1

무엇이 멀티입니까? –

답변

3

거의 다 왔었습니다. 몇 가지 :

실제로는이 아닌 cylindrical coordinates을 사용하고 있습니다. NumPy와는 cyl2cat이있는 경우 내가 확인하지 않았지만이 직접 작성하는 것이 정말 어려운 일이 아니다 :

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

을 두 단계에서 그것을 만들 이유가 확실히 이해하지 못하는 회전하십시오. 당신은 meshgrid의 회전 할 NumPy와의 ravel를 사용할 수 있습니다

# ... 
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 원하는 것을하십시오 :

,515,
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에 동일한 축 얻기 간단하지 않지만 (거의/SO 대답 this에서 붙여 복사) 입방 경계 상자 플롯에 의해 해결을 달성 할 수 있습니다

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(...과 후이 추가를 실린더는 원형 곡률로 나타납니다.

관련 문제