Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
MattPeddlesden's avatar
MattPeddlesden
Honored Guest
11 years ago

Rotation Tracking Problem

Hi,

I'm having a problem with rotation tracking - but before I get to the current issue, let me describe an issue I had during initial integration as I have a rumble in my tummy that my solution was entirely inappropriate and is now coming back to bite me...

So when I did the first integration to DK2 I simply read the values back using basically the same code as from the example in the documentation. I swapped it in-place over the top of a previous DK1 implementation that worked great.

It basically did the trick - with one exception, all the axis were reporting about 50% of their actual movement, so if I looked 90 degrees to the right physically, my view port would only have moved 45 degrees.

You can imagine my solution - multiply all the rotations by two. Yay, now all the rotations go all the way! :)

So... with that knowledge in-hand, let me describe the current issue.

If I look forward and then look up and down - all is good.
If I look 90 degrees to the left or right and then look up and down the movement is VERY disconcerting, appearing like it's doing some roll rotation as well.

As I thought about it tonight, it occurred to me that this might be because it thinks i've only moved my head 45 degrees, in which case there would indeed be an additional factor in the rotation.

So...

Regarding the 50% head tracking rotation issue - is this normal? Is this acceptable? It's possible that it's just the way our engine works and is perfectly fine to multiply up (though it doesn't look like we did this on DK1).

The more fundamental issue (because it *really* makes you queasy :) ) is the latter one - where 90 degrees left and looking up and down causes what looks like a roll along with the pitch.

Help much appreciated!
Matt.

4 Replies

  • Hmm, reading the example again in the manual (for rotation tracking) I don't have it done the same way in turns out.

    I did this:

    ovrPoseStatef pose = ts.HeadPose;

    x = pose.ThePose.Orientation.x * 2;
    y = pose.ThePose.Orientation.y * 2;
    z = pose.ThePose.Orientation.z * 2;

    The manual says to do this:

    Posef pose = trackingState.HeadPose.ThePose;
    float yaw, float eyePitch, float eyeRoll;
    pose.Orientation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &eyePitch, &eyeRoll);

    HOWEVER

    When I try to do that - it fails because "pose.Orientiation" does not contain a member "GetEulerAngles" indeed, it only seems to consist of the x/y/z/w members.

    I'm guessing this is where my rusty C++ is failing me.

    Hints appreciated.

    Matt.
  • You can call it like this:

    Posef pose = ts.HeadPose.ThePose;
    float yaw, pitch, roll;
    pose.Rotation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &pitch, &roll);


    You should not be hacking the numbers by multiplying them by two. Also, keep in mind these are radians. If you want degrees you need to do this:

    cout << "yaw: "   << RadToDegree(yaw)   << endl;
    cout << "pitch: " << RadToDegree(pitch) << endl;
    cout << "roll: " << RadToDegree(roll) << endl;


    Also, be aware of gimbal lock when using Euler angles (it is better to use quaternions or matrices if possible).
  • Fantastic thanks - I was quite sure that the "*2" thing was a bad idea when I did it in fact I seem to recall ending up with this approach after the snippet in the manual failed to work (due to the "Orientation" / "Rotation" mix up) - I'd suggest a review of that for the next update :)

    It's only since I've actually started using it more that i've noticed the problem - the rest of the time i've just been waving the headset around and not actually wearing it, so as long as it did vaguely the right thing that was "good enough".

    I've made that fix now and will test it tomorrow. I'm just trying to get something working well enough to start testing out design and gameplay concepts in the game as there are no "proper" engineers available to do the integration - once we can schedule some dev time it'll be done properly i'm sure :)

    I get what you're saying about gimble lock too (having just had a quick read-up) and will make sure this is taken in to account for the production implementation.

    Thanks for your help, hopefully this fixes both problems when I test it tomorrow :)

    Matt.
  • The orientation/rotation difference here is due to the mix of C and C++ in the api.

    The C api has an ovrPosef structure that contains the orientation as an ovrQuatf called "Orientation".
    The C++ api has a Pose class that contains the orientation as a Quat called "Rotation".
    Both ovrQuatf and Quat are quaternions (a 4D value describing rotations around an axis), but ovrQuatf has no member functions (since it's in C) while Quat is a C++ class with a full range of methods such as GetEulerAngles.

    Quaternions can be tricky to understand. Have a look here for more details: http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions
    A lot of engines use them and they have a lot of good properties.
    It's kind of like poking a stick through an object in any direction, then twisting the stick to rotate the entire object. But the angle of twist and the direction of the stick (rotation axis) aren't stored in the quaternion directly. Instead, the quaternion contains:
    w = cos(angle/2)
    x,y,z = axis * sin(angle/2)