将旋转矩阵正确转换为Mayavi/Vtk的(俯仰、横滚、偏航)
我的问题
我想用一个3x3的旋转矩阵来旋转一个mayavi.mlab.imshow
对象。我找到的唯一旋转这个对象的方法是通过设置对象的actor.orientation
为[pitch, roll, yaw]
(这个顺序是从vtk继承来的)。我唯一的问题是,我找不到将旋转矩阵转换为mayavi所需参数的方法。
我该如何用旋转矩阵在mayavi中旋转一个对象,或者我应该使用什么变换来获得Mayavi/Vtk所需的正确(pitch, roll和yaw)?
接近解决方案
我在这里找到了一些代码(点击查看),可以将旋转矩阵转换为不同类型的欧拉角(根据旋转的顺序)。如果我假设欧拉角等同于pitch、roll和yaw,请在此时纠正我。我尝试了所有不同的转换,但没有找到正确的。
尝试每种组合
我通过用我的旋转矩阵旋转x、y和z向量,测试了所有不同的变换,并在mayavi.mlab.imshow
对象上测试了参数。我在R
和transpose(R)
上使用了所有可用的变换,并尝试了所有9种可用顺序的欧拉参数,但仍然找不到正确的组合:
import pylab as pl
import cameraTools #my own lib
from mayavi import mlab
im = pl.imread('dice.png', format='png')[:,:,0]*255 #1 color channel
rot = pl.r_[30, 80, 230]
R_orig = cameraTools.composeRotation(*(rot*pl.pi/180))
RList = [R_orig, R_orig.T]
for ii, inOrder in enumerate(['sxyz','sxzx','syxz','szxz','rzyx','rxzx','rzxy','rzxz','sxyx','syzx','syxy','szyx','rxyx','rxzy','ryxy','rxyz','sxzy','syzy','szxy','szyz','ryzx','ryzy','ryxz','rzyz']):
tries = 0
for outOrder in [[0,1,2], [0,2,1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]:
for R in RList:
for vector, color in zip([[800, 0, 0], [0, 800, 0], [0, 0, 800]],
[(1., 0., 0.), (0., 1., 0.), (0., 0., 1.)]):
c = pl.c_[[0, tries*1000, ii*1000]]
if ii == 0 and tries == 0: vector = pl.r_[vector]*5 #point out the first vector
lin = R_orig.dot(pl.c_[[0,0,0], vector]) + c
mlab.plot3d(*lin,
color = color,
tube_radius=5)
lin3D = mlab.imshow(im, colormap="gray")
rxyz = pl.array(cameraTools.euler_from_matrix(R, inOrder))*180/pi
i,j,k = outOrder
lin3D.actor.orientation = [rxyz[i], rxyz[j], rxyz[k]]
lin3D.actor.position = c.flatten()
tries +=1
mlab.draw()
mlab.show()
这是Mayavi的输出,左上角的项目是起始点。
1 个回答
1
抱歉,我好像没有集中注意力。答案在第三行,第五列,输入顺序是 syxz
,输出顺序是 '[1,0,2]'
。我现在使用以下函数来把旋转矩阵转换成所需的欧拉角:
def rotationToVtk(R):
'''
Concert a rotation matrix into the Mayavi/Vtk rotation paramaters (pitch, roll, yaw)
'''
def euler_from_matrix(matrix):
"""Return Euler angles (syxz) from rotation matrix for specified axis sequence.
:Author:
`Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>`_
full library with coplete set of euler triplets (combinations of s/r x-y-z) at
http://www.lfd.uci.edu/~gohlke/code/transformations.py.html
Note that many Euler angle triplets can describe one matrix.
"""
# epsilon for testing whether a number is close to zero
_EPS = np.finfo(float).eps * 5.0
# axis sequences for Euler angles
_NEXT_AXIS = [1, 2, 0, 1]
firstaxis, parity, repetition, frame = (1, 1, 0, 0) # ''
i = firstaxis
j = _NEXT_AXIS[i+parity]
k = _NEXT_AXIS[i-parity+1]
M = np.array(matrix, dtype='float', copy=False)[:3, :3]
if repetition:
sy = np.sqrt(M[i, j]*M[i, j] + M[i, k]*M[i, k])
if sy > _EPS:
ax = np.arctan2( M[i, j], M[i, k])
ay = np.arctan2( sy, M[i, i])
az = np.arctan2( M[j, i], -M[k, i])
else:
ax = np.arctan2(-M[j, k], M[j, j])
ay = np.arctan2( sy, M[i, i])
az = 0.0
else:
cy = np.sqrt(M[i, i]*M[i, i] + M[j, i]*M[j, i])
if cy > _EPS:
ax = np.arctan2( M[k, j], M[k, k])
ay = np.arctan2(-M[k, i], cy)
az = np.arctan2( M[j, i], M[i, i])
else:
ax = np.arctan2(-M[j, k], M[j, j])
ay = np.arctan2(-M[k, i], cy)
az = 0.0
if parity:
ax, ay, az = -ax, -ay, -az
if frame:
ax, az = az, ax
return ax, ay, az
r_yxz = pl.array(euler_from_matrix(R))*180/pi
r_xyz = r_yxz[[1, 0, 2]]
return r_xyz