Inkidu616
Inkidu616

Reputation: 399

How can I calculate a measure of 'rotational mobility' from Euler angles?

Odd question, but I'm having trouble boiling it down to a coherent question.

I have sampled data (60Hz) from Brekel OpenVR recorder, which includes the following parameters for the HMD itself:

I'm processing the data in python. Overall, what I'm trying to do is to calculate measures of mobility: did someone look around more or less during a segment, and did they move around more or less?

For the positional coordinates that wasn't too difficult, I was able to calculate displacement, velocity, etc., by using the distances between subsequent positions. Now for the Euler angles, I'm having more trouble.

I've searched for the answer to my question, but none of the answer seemed to 'click'. What I think I need, is to convert the Euler angles to a directional vector, and then calculate the angle between the directional vectors of subsequent samples to see how much the gaze direction shifted. Once I have those, I can calculate means and SDs per subject, to see which of them looked around more (that's the idea anyway). I am unclear on the mathematics though. It would have been easier if my coordinates were roll, pitch, yaw, but I'm struggling with the Euler angles.

Suppose the Euler angles for two subsequent samples are:

How can I quantify with what angle the direction of the HMD changed between those two samples?

Upvotes: 1

Views: 287

Answers (1)

Cory Kramer
Cory Kramer

Reputation: 117886

You can write a function to convert Euler angles to unit vectors, and another to take the angle between two unit vectors

from math import cos, sin, atan2, degrees, radians, sqrt
from numpy import dot, cross

def to_unit_vector(pitch, yaw, roll):
    # Convert degrees to radians
    pitch = radians(pitch)
    yaw = radians(yaw)
    roll = radians(roll)
    # Calculate unit vector components
    x = cos(yaw) * cos(pitch)
    y = sin(yaw) * cos(pitch)
    z = sin(pitch)
    return x, y, z

def angle_between(a, b):
    # returns angle in degrees
    return degrees(atan2(sqrt(dot(cross(a, b), cross(a, b))), dot(a, b)))

Then for example

>>> u = to_unit_vector(20, 25, 50)
>>> u
(0.8516507396391465, 0.39713126196710286, 0.3420201433256687)
>>> v = to_unit_vector(30, 35, 60)
>>> v
(0.7094064799162225, 0.49673176489215404, 0.49999999999999994)
>>> angle_between(u, v)
13.481723224800309

Upvotes: 1

Related Questions