willpower2727
willpower2727

Reputation: 789

Offset Euler Angles using rotation matrix

I'm looking for the correct way to apply an offset to a set of Euler rotations. I would like to have a transformation where given a specific set of Euler angles (x1,y1,z1), if I transform them I would get an Euler sequence of (0,0,0). All other Euler sequences (xi,yi,zi) transformed would then act like (x1,y1,z1) were (0,0,0).

Background:

I'm using Oculus DK2 HMD to display a virtual environment (Vizard 5, Python 2.7.5) while using a Vicon motion capture system (Nexus 2) to update the position and orientation. I can get the Euler angles of the HMD (from a marker cluster, not the DK2 gyroscope) from the Vicon system, but when facing my desired (0,0,0) orientation the HMD has a non-zero rotation sequence.

Problem:

I'm having a hard time thinking about what transformation (rotation matrix?) I could find that could take a sequence like (-105, 110, -30) and make it (0,0,0) without being a useless matrix of zeros. If the rotation matrix was all zeros, any sequence would be transformed to (0,0,0)). The formula I have in mind is (please ignore syntax):

[0,0,0] = (3x3)R*(3x1)[-105,110,-30] what is R? R cannot be 3x3 zero matrix.

Attempt:

I stupidly tried to simply subtract the offest euler angles like so:

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

Alas,

enter image description here

I'm sure this is possible, in fact I've done similar things in the past where I had to transform marker clusters into a rigid body's frame at a calibration position. But I just can't get around the trivial solution in this case (zeros matrix). If by chance anyone would explain this using quaternions, I can also use those.

Upvotes: 3

Views: 2441

Answers (1)

willpower2727
willpower2727

Reputation: 789

The right way to do this is to determine the transformation between the hmd orientation and the desired view orientation at a desired point. I call this time zero, even though time has little to do with it, really it's the "home" orientation. Once the transformation is known, it can be used to determine the view orientation using the data from the hmd, since the coordinate frames of the hmd and view can be thought of as mounted on the same rigid body (meaning their relative transformation will not change with time).

Here is the math: enter image description here

Here is how I coded it (it works!):

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)

Upvotes: 1

Related Questions