使用旋转矩阵进行偏移欧拉角

3
我正在寻找一种正确的方法来对一组欧拉角进行偏移。我想要这样一种变换:给定一个特定的欧拉角集(x1,y1,z1),如果我对它们进行变换,我将得到一个欧拉角序列(0,0,0)。然后,所有其他欧拉角序列(xi,yi,zi)的变换将像(x1,y1,z1)是(0,0,0)一样。
背景:
我正在使用Oculus DK2 HMD显示虚拟环境(Vizard 5, Python 2.7.5),同时使用Vicon运动捕捉系统(Nexus 2)更新位置和方向。我可以从Vicon系统中获取HMD的欧拉角(从标记簇,而不是DK2陀螺仪),但在面对我所需的(0,0,0)方向时,HMD具有非零的旋转序列。
问题:
我很难想出什么变换(旋转矩阵?)可以将像(-105,110,-30)这样的序列变成(0,0,0)而不是无用的零矩阵。如果旋转矩阵全是零,那么任何序列都将被变换为(0,0,0))。我心中所想的公式是(请忽略语法):
[0,0,0] = (3x3)R*(3x1)[-105,110,-30] R是什么?R不能是3x3的零矩阵。
尝试:
我愚蠢地尝试简单地减去偏移欧拉角,如下所示:
import viz
viz.go()
navigationNode = viz.addGroup() #create node
viewLink = viz.link(navigationNode, viz.MainView) #link it to the main view

#I am not showing how I get variables HMDX HMDY HMDZ but it's not important for this question
navigationNode.setEuler(HMDRZ-90,HMDRX+180,-1*(HMDRY)+30) #update the view orientation

哎呀,

enter image description here

我相信这是可能的,事实上我以前做过类似的事情,我必须将标记簇转换为校准位置处的刚体框架。但是在这种情况下,我无法避免微不足道的解决方案(零矩阵)。如果碰巧有人能使用四元数解释一下这个问题,我也可以使用它们。


我可能在这里错过了一些非常基本的东西,但是假设你有[-105,110,-30]并想使用矩阵R将其转换为[0,0,0]。那么你不能只在R的每一行中使用例如[0,1,110/30]吗?如果可以,那么显然有任意多个解决方案;如果不行,我就真的不明白你的问题了。 - Cleb
好的,那你能详细解释一下你实际上在寻找什么吗?我只给了一个任意的例子;你也可以选择[-1, 1, 43/6],这显然不会对(-105+45,110,-30)返回(0, 0, 0)。所以如果你能更详细地解释R的期望属性,那就太好了!如果你能够详细定义R的属性,你也可以尝试在这里提问。 - Cleb
@Cleb 抱歉造成困惑,我认为您所描述的是通过将向量与旋转矩阵相乘来进行变换。有许多矩阵 R 可以将向量转化为零。然而,使用欧拉角时,您不能简单地将欧拉角乘以旋转矩阵。那样没有意义。相反,您需要用另一个旋转矩阵相乘,并使用逆运动学来获得新的欧拉角。希望我解释清楚了。感谢您的回复。 - willpower2727
好的,谢谢你的解释;我学到了东西 :) - Cleb
1个回答

1
这样做的正确方式是确定在所需点上hmd方向和期望视图方向之间的变换。我称其为时间零,尽管时间与此无关,实际上它是“home”方向。一旦变换已知,就可以使用来自hmd的数据确定视图方向,因为可以将hmd和视图的坐标系视为安装在同一个刚体上(这意味着它们的相对变换不会随时间而改变)。
以下是数学公式: enter image description here 以下是我的编码方式(它可以工作!):
import numpy as np
import math

#setup the desired calibration transformation (hmd orientation that will result in looking straight ahead

#Euler angles for the hmd at desired "zero" orientation
a0 = -177.9*math.pi/180
b0 = 31.2*math.pi/180
g0 = 90.4*math.pi/180

#make the matrices
Ra0 = np.matrix([[1,0,0],[0, float(math.cos(a0)),float(-1*math.sin(a0))],[0,float(math.sin(a0)),float(math.cos(a0))]],dtype=np.float)
Rb0 = np.matrix([[math.cos(b0),0,math.sin(b0)],[0,1,0],[-1*math.sin(b0),0,math.cos(b0)]],dtype=np.float)
Rg0 = np.matrix([[math.cos(g0),-1*math.sin(g0),0],[math.sin(g0),math.cos(g0),0],[0,0,1]],dtype=np.float)

#the hmd rotation matrix in the "zero" orientation
global RhmdU0 
RhmdU0 = Ra0*Rb0*Rg0
#the view orientation when the hmd is in the "zero" orientation (basically a zero degree turn about the Z axis)
global RdU0
RdU0 = np.matrix([[1,0,0],[0,1,0],[0,0,1]],dtype=np.float)

#this can be called in a loop, inputs are Euler angles of the hmd
def InverseK(at,bt,gt):
    global RdU0
    global RhmdU0

    #given 3 Euler sequence of the hmd in universal space, determine the viewpoint
    Rat = np.matrix([[1,0,0],[0, float(math.cos(at)), float(-1*math.sin(at))],[0,float(math.sin(at)),float(math.cos(at))]],dtype=np.float)
    Rbt = np.matrix([[math.cos(bt),0,math.sin(bt)],[0,1,0],[-1*math.sin(bt),0,math.cos(bt)]],dtype=np.float)
    Rgt = np.matrix([[math.cos(gt),-1*math.sin(gt),0],[math.sin(gt),math.cos(gt),0],[0,0,1]],dtype=np.float)

    RhmdUt = Rat*Rbt*Rgt

    RdUt = RhmdUt*RhmdU0.transpose()*RdU0

    #do inverse K to get euler sequence out:
    beta = math.atan2(RdUt[0,2],math.sqrt(RdUt[1,2]**2+RdUt[2,2]**2))
    alpha = math.atan2(-1*RdUt[1,2]/math.cos(beta),RdUt[2,2]/math.cos(beta))
    gamma = math.atan2(-1*RdUt[0,1]/math.cos(beta),RdUt[0,0]/math.cos(beta))

    return(alpha,beta,gamma)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接