Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GLM conversion from euler angles to quaternion and back does not hold

I am trying to convert the orientation of an OpenVR controller that I have stored as a glm::vec3 of Euler angles into a glm::fquat and back, but I get wildly different results and the in-game behavior is just wrong (hard to explain, but the orientation of the object behaves normally for a small range of angles, then flips in weird axes).

This is my conversion code:

// get `orientation` from OpenVR controller sensor data

const glm::vec3 eulerAnglesInDegrees{orientation[PITCH], orientation[YAW], orientation[ROLL]};
debugPrint(eulerAnglesInDegrees);

const glm::fquat quaternion{glm::radians(eulerAnglesInDegrees)};
const glm::vec3 result{glm::degrees(glm::eulerAngles(quaternion))};
debugPrint(result);

// `result` should represent the same orientation as `eulerAnglesInDegrees`

I would expect eulerAnglesInDegrees and result to either be the same or equivalent representations of the same orientation, but that is apparently not the case. These are some example values I get printed out:

39.3851 5.17816 3.29104 
39.3851 5.17816 3.29104 

32.7636 144.849 44.3845 
-147.236 35.1512 -135.616 

39.3851 5.17816 3.29104 
39.3851 5.17816 3.29104 

32.0103 137.415 45.1592 
-147.99 42.5846 -134.841 

As you can see above, for some orientation ranges the conversion is correct, but for others it is completely different.

What am I doing wrong?

I've looked at existing questions and attempted a few things, including trying out every possible rotation order listed here, conjugating the quaternion, and other random things like flipping pitch/yaw/roll. Nothing gave me the expected result.

How can I convert euler angles to quaternions and back, representing the original orientation, using glm?


Some more examples of discrepancies:

original:      4; 175;   26; 
computed:   -175;   4; -153; 
difference:  179; 171;  179; 

original:     -6; 173;   32; 
computed:    173;   6; -147; 
difference: -179; 167;  179; 

original:      9; 268;  -46; 
computed:   -170; -88;  133; 
difference:  179; 356; -179; 

original:    -27; -73;  266; 
computed:    -27; -73;  -93; 
difference:    0;   0;  359; 

original:    -33; 111;  205; 
computed:    146;  68;   25; 
difference: -179;  43;  180; 

I tried to find a pattern to fix the final computed results, but it doesn't seem like there's one easy to identify.


GIF + video of the behavior:

Video excerpt

  • Full video on YouTube

Visual representation of my intuition/current understanding:

Visual diagram

  • The above picture shows a sphere, and I'm in the center. When I aim the gun towards the green half of the sphere, the orientation is correct. When I aim the gun towards the red half of the sphere, it is incorrect - it seems like every axis is inverted, but I am not 100% sure that is the case.
like image 324
Vittorio Romeo Avatar asked Mar 02 '23 19:03

Vittorio Romeo


1 Answers

32.7636 144.849 44.3845 -147.236 35.1512 -135.616

Those are the same. Left 33 or right 147. You are 180 from each other. Now look up 145 - that's past up that's 35 from horizon, your back is arched. Now roll to get your back to the sky.

If you need to use Euler, try to keep pitch in -90 to +90, and roll in -180 to +180;

if (pitch > 90) {
   pitch -= 90;
   yaw += 180;
   roll += 180;
}
if (roll > 180) {
   roll = 360 - roll;
}

or something like that.

like image 84
tony Avatar answered Mar 05 '23 08:03

tony