# A proper way to get the roll, pitch and yaw values

TL, DR : What is the method(in terms of sensors and algorithm) to get the roll, pitch angles of an aircraft at any instant.

I am planning to build a hobby aircraft. I am so confused about which kind of sensors should I use and how to use them in order to get the roll, pitch and yaw angles of the aircraft.

I think I also have some problems about understanding the concept. I consider these P, R, Y angles similar to the x,y,z coordinates as if they are able to describe the attitude of a body. If something in the below list contains "nonsense" arguments, please also enlighten me about them.

What I want is to be able to know at any instant:

1. what is the pitch angle of the aircraft, i.e how much degrees its nose pointing away from the horizontal plane of the earth.
2. what is the yaw angle, i.e to what direction(north, east etc) is the aircraft pointing through.
3. what is the roll angle, i.e what is the angle between aircrafts body surface ( wing to wing x tail to head surface ) and the horizontal plane of the earth/sky.

In some sources there is something going on as the importance of order of the application of roll,pitch and yaw. But I cannot understand why this is related.

I have used accelerometer values by inputting them into some formulas on the internet(those arctangent formulas, which everybody uses but nobody explains well) to get the roll and pitch values. However could not understand how to manipulate them in order to meet my requirements(different axis orientations of the sensor).

I also have basic understanding about what a gyroscope is.

I have an MPU6050(Accelerometer+Gyroscope).

P.s : my goal is to build a quadcopter but I guess in order to understand these concepts a fixed wing standard plane model.

In some sources there is something going on as the importance of order of the application of roll,pitch and yaw. But I cannot understand why this is related.

Take your right hand: point your thumb upwards, your index finger away from you, and your middle finger to the left. You now have a righthanded coordinate system: your thumb is the x axis, your index finger the y axis, and your middle finger the z axis.

First rotate +90° around the x axis (thumb). Your index finger now points to the left, and your middle finger towards you. Next, rotate +90° around the y axis (index finger). Your thumb now points away from you, your index finger to the left, and your middle finger upwards.

Now, move back to the initial position, and apply the same two rotations in a different order, first around the y axis and then the x axis: Rotate +90° around the y axis (index finger). Your thumb is now pointing to the right, your index finger away from you, and your middle finger upwards. Next, rotate +90° around the x axis (thumb). Your thumb now points to the right, your index finger upwards, and your middle finger towards you.

This is different from the last result: order of rotation matters.

I have used accelerometer values by inputting them into some formulas on the internet(those arctangent formulas, which everybody uses but nobody explains well)

When the aircraft is moving at a constant velocity, the accelerometer just measures the acceleration due to gravity, which is a vector pointing exactly downward, (0, 0, -g) in the global coordinate system. This is always true, regardless of the orientation of the sensor.
If the sensor is perfectly level, the sensor's local coordinate system is aligned with the global coordinate system, so the sensor also measures (0, 0, -g).

When the sensor is tilted, the measured vector also has an x and y components.
To keep things simple, imagine the case where the sensor is tilted around the positive y axis.
The sensor now measures an x component as well as a z component: (x, 0, -z).

As you can see from the following image, the angle of rotation `θ = atan2(x, z)`. The black arrow is the acceleration due to gravity, and the red and blue arrows are the x and z axes of the coordinate system of the (tilted) sensor.

However, accelerometer measurements are not useful for determining the orientation when the sensor is accelerating, because then the measured vector no longer points exactly downward (in the global coordinate system).

Gyroscopes measure angular velocity. By integrating the angular velocity, you get the angle.
There's one caveat: it is impossible to integrate exactly, because we only have measurements at discrete points in time. This means we have to use something like Euler's method, which is known to result in drift of the orientation estimate. To make matters worse, the measurement is noisy, and this noise is integrated as well, resulting in an even larger error.

Luckily, you can combine both imperfect measurements into a single, better orientation estimate using a sensor fusion algorithm. I've successfully used Sebastian Madgwick's algorithm for my quadcopter.
It uses the measurements of the accelerometer to minimize gyro drift.

Note that this algorithm uses quaternions instead of Euler angles (roll, pitch, yaw), because the latter suffer from gimbal lock, and because quaternions geneally require less processing power.

Also note that you cannot determine the yaw angle using the accelerometer, so you'll get some drift on that measurement.

It's a good idea to do all of your calculations using quaternions. You probably won't need Euler angles for your quadcopter, except maybe for debugging purposes.

If you want to, you can also get the quaternion from the acceleration vector directly:

``````    Quaternion quaternionFromDirection(Vec3f v) {
/*
* Formula:
* q = cos(ϑ / 2) + sin(ϑ / 2)·(x·i + y·j + z·k)
* where (x y z) is a unit vector representing the axis about which
* the body is rotated; ϑ is the angle by which it is rotated.
*
* Source:
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Using_quaternion_as_rotations
*
* The rotational axis (x y z) can be calcuated by taking the normalized
* cross product of (0 0 1) and the given vector. The angle of rotation
* ϑ can be found using |A×B| = |A||B|·sin(ϑ).
*/

// First check the edge case where v == (0 0 z), i.e. vertical
if (v.x == 0 && v.y == 0)
return {1, 0, 0, 0};

// Calculate the cross product and its norm.
Vec3f cross     = {v.y, -v.x, 0};
float crossNorm = cross.norm();
cross /= crossNorm;

// Calculate the angle ϑ.
float angle = std::asin(crossNorm / v.norm());

// Calculate the resulting quaternion.
return {
std::cos(angle / 2),            //
std::sin(angle / 2) * cross.x,  //
std::sin(angle / 2) * cross.y,  //
std::sin(angle / 2) * cross.z,  //
};
}
``````
• Well, what can I say, a very well explained answer. Thanks a lot. Jul 27 '19 at 4:33
• One another mystery for me also related to something in your answer: while z axis is pointing upwards and xy plane is level, the accelerometer outputs +g in z component. But you mentioned it to be as -g. So how should I interpret the output of an accelerometer? As gravitional acceleration or the imaginary acceleration due to normal force act on the body? Jul 27 '19 at 4:36
• @muyustan I usually just add minus signs to the appropriate coordinates when reading the accelerometer, so I have a righthanded coordinate system with the z axis pointing upwards (gravity pointing downward). Jul 27 '19 at 13:32