在 python 中使用欧拉矩阵旋转对象
Rotation of object using Euler Matrix in 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
当欧拉旋转矩阵为 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)
我得到了下图。
但是当我尝试通过欧拉矩阵旋转对象时 Euler = np.array([[1,0,0],[0,1/np.sqrt(2),-1/np.sqrt(2)],[0,1/np.sqrt(2),1/np.sqrt(2)]])
我得到了意想不到的结果。
此处旋转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()]))
并重塑旋转后的坐标:
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()
Etvoilà:
请注意,轴的纵横比不同,这就是圆柱体确实以椭圆曲率出现的原因。 在 Axes3D
中获得等轴并不简单 但可以通过绘制立方边界框(几乎 copy/pasted 来自 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(...
之后加上这个,圆柱体就会出现圆曲率。
我正在尝试使用欧拉矩阵旋转一个卷轴(或圆柱体)。为此,我使用以下函数。
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)
我得到了下图。
但是当我尝试通过欧拉矩阵旋转对象时 Euler = np.array([[1,0,0],[0,1/np.sqrt(2),-1/np.sqrt(2)],[0,1/np.sqrt(2),1/np.sqrt(2)]])
我得到了意想不到的结果。
此处旋转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()]))
并重塑旋转后的坐标:
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()
Etvoilà:
请注意,轴的纵横比不同,这就是圆柱体确实以椭圆曲率出现的原因。 在 Axes3D
中获得等轴并不简单 但可以通过绘制立方边界框(几乎 copy/pasted 来自 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(...
之后加上这个,圆柱体就会出现圆曲率。