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, //
};
}