# Quaternion angle calculation

I'm working on a programming project, in this project I'm receiving an angle as a quaternion value, I partially understand how they work but I don't find any math to get the values I need.
What I would need is the angle between a fictional line/vector going to the the quaternion point from the origin (yes I know what you are thinking, but I couldn't think of a better explanation) and the "earth" a plane that is perpendicular to the gravitational vector, in this case one of your planes of reference.
Also I would need to get the rotation of the line/vector, this time the rotation should be according to the plane perpendicular to itself.
If possible all angles should be described as an angle between -180° and 180° (that's were my troubles are from.

In this picture γ complementary angle of the first questing and R is the secondary angle.
Angles

PS: This is the last formula I tried to use.

• From my best understanding it sounds like you want to convert the quaternion to lat/lon values. – ratchet freak Jan 16 at 10:00
• Are you using a math package? Do you have a Quaternion class or is the value provided by an array? – Jay Jan 16 at 12:22
• All I have is the values, and these are given as an int, I need to do all math without a lib – Tim Jager Jan 16 at 16:31
• When you say "the quaternion point", do you mean a vector representing the axis of rotation specified by the quaternion, or the image of a particular input vector (say, a standard "forward" vector) after rotation by the quaternion? – DMGregory Jan 16 at 17:12

## 2 Answers

Calculate the "shadow" on i,j plane $$A\alpha= \sqrt{(Ax)^2+(Ay)^2}$$

Get the γ angle $$\gamma = tan({A\alpha \over Az})$$

Middle solution : $$\alpha'=tan({Ay \over Ax})$$ $$\beta'=tan({Ax \over Ay})$$

You maybe draw α and β wrong if not I cannot help you more :(

• Usually the length of a vector is indicated by ||A|| — but I'm still not clear where you're working with the quaternion? – DMGregory Jan 16 at 15:40
• q=w+xi+yj+zk | w = R, x = Ax, y = Ay, z = Az $$\alpha = arccos({Ax*A \over |Ax|-|A|})$$ – Sky-08 Jan 16 at 16:13
• Great! Now make that part of your answer. You don't seem to be using the real part w or R anywhere — is there a reason for that? – DMGregory Jan 16 at 16:14
• Yes and no, At this point I don't undestand what he need in euler axis and what he receive – Sky-08 Jan 16 at 16:17
• The sensor only gives me some quaternions, and I would need those angles/rotations. – Tim Jager Jan 16 at 16:34

You should always use atan2(y,x) instead of atan(y/x). It is a common mistake. – Somos

He wrote this on a math form were I asked this too, and that was my stupid mistake -_-

My new version is:

float gx = 2 * (x*z - w*y);
float gy = 2 * (w*x + y*z);
float gz = w*w - x*x - y*y + z*z;
float yaw = atan2(2*x*y - 2*w*z, 2*w*w + 2*x*x - 1); // about Z axis
float pitch = atan2(gx, sqrt(gy*gy + gz*gz)); // about Y axis
float roll = atan2(gy, gz); // about X axis

/*Serial.print("  yaw ");
Serial.print(yaw * 180/M_PI,0);*/
Serial.print("  pitch ");
Serial.print(pitch * 180/M_PI,2);
Serial.print("  sideways ");
// Please don't pay  attention to the extra function I made for the project but it doesn't have to do with the problem
if(pitch > 0) Serial.println((roll * 180/M_PI) * (1/(1+pow(1.293,((pitch * 180/M_PI)-51.57)))), 2);
else if(pitch == 0) Serial.println(roll * 180/M_PI, 2);
else if(pitch < 0) Serial.println((roll * 180/M_PI) * (1/(1+pow(1.293,(((pitch) * (-180)/M_PI)-51.57)))), 2);