使用旋转矩阵偏移欧拉角

Offset Euler Angles using rotation matrix

我正在寻找将偏移应用于一组欧拉旋转​​的正确方法。我想在给定一组特定的欧拉角 (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

唉,

我相信这是可能的,事实上我在过去做过类似的事情,我不得不在校准位置将标记簇转换成刚体的框架。但在这种情况下,我无法解决简单的解决方案(零矩阵)。如果碰巧有人会用四元数来解释这个,我也可以使用它们。

正确的做法是在所需点确定 hmd 方向和所需视图方向之间的转换。我称这个时间为零,尽管时间与它关系不大,实际上它是 "home" 方向。一旦转换已知,就可以使用来自头戴式显示器的数据来确定视图方向,因为头戴式显示器和视图的坐标系可以被认为安装在同一个刚体上(意味着它们的相对转换不会改变随着时间的推移)。

这是数学:

这是我的编码方式(有效!):

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)