3

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.

willpower2727
  • 769
  • 2
  • 8
  • 23
  • I probably miss something very fundamental here but let's say you have `[-105,110,-30]` and want to turn it into `[0,0,0]` using a matrix `R`. Could you then not just use e.g. `[0, 1, 110/30]` in each row of `R`!? If so, then there are apparently arbitrarily many solutions to this problem; if not I do not really get your question. – Cleb Mar 04 '16 at 22:31
  • Ok, could you then explain in more detail what you are actually looking for? I gave only one arbitrary example; you could also choose `[-1, 1, 43/6]` which would then apparently not return `(0, 0, 0)` for `(-105+45,110,-30)`. So if you could explain the desired properties of `R` in more detail it would be great! You could also try [here](http://math.stackexchange.com/questions) if you are able to define the properties of `R` in a detailed manner. – Cleb Mar 05 '16 at 13:13
  • @Cleb sorry for the confusion, I think what you are describing is transforming a vector by multiplying it with the rotation matrix. There are many matrices R that can turn a vector into zeros. However with Euler angles you can't simply multiply the Euler angles by the rotation matrix. That wouldn't make sense. Instead you multiply with another rotation matrix and use inverse kinematics to get the new Euler angles out. I hope I'm making sense. thanks for your response – willpower2727 Mar 08 '16 at 21:16
  • Ok, thanks for the explanation; I could learn something :) – Cleb Mar 08 '16 at 21:55

1 Answers1

1

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)
willpower2727
  • 769
  • 2
  • 8
  • 23