I have been using a BNO055 sensor (9° dof IMU) for a project which will use angular velocity to move the mouse cursor on a PC screen.
So far, I have gotten quaternion output from the sensor and been able to convert it to angular velocity in a couple of ways. The first, multiplying 1 quaternion sample by its conjugate in the next sample, and then converting the quaternion Delta in Euler angles. The second, converting from quaternions to Euler angles and then finding the change in those between samples.
Both methods result in angular velocity measurement, but each with their advantages and disadvantages. E.g. Quaternion Delta between samples does not suffer from gimbal lock, but it's difficult to isolate y-axis from z-axis movement.
I know that you can ask the sensor for angular velocity data directly, but apparently that's less precise due to the Gyro drift and it's relative orientation only, which is why I opted to work with quaternions.
My question is, is there anything fundamentally wrong with my approach? Is there a better way to go about this? I'm afraid my lack of understanding of the underlying maths may make me blind to some issue.
My code included below for reference with the 2 approaches in case it's helpful/interesting. It uses the Adafruit repository, doing the standard stuff in setup function and then calling the function below in loop.
void quaternion_Delta () {
// Quaternion data 1
imu::Quaternion quat = bno.getQuat();
// Euler 1
imu::Vector<3> euler_one = quat.toEuler();
//delay between samples
delay(BNO055_SAMPLERATE_DELAY_MS);
// Quaternion data 2
imu::Quaternion quat_two = bno.getQuat();
// Euler 2
imu::Vector<3> euler_two = quat_two.toEuler();
// quaternion comparison
imu::Quaternion quatDelta = quat_two * quat.conjugate ();
imu::Vector<3> euler = quatDelta.toEuler();
Serial.print(" X: ");
Serial.print(euler.x()*radius_to_degrees, 2);
Serial.print(" Y: ");
Serial.print(euler.y()*radius_to_degrees, 2);
Serial.print(" Z: ");
Serial.print(euler.z()*radius_to_degrees, 2);
Serial.print("\t\t");
// Euler comparison
imu::Vector<3> euler_comparison = euler_two - euler_one;
Serial.print(" x: ");
Serial.print(euler_comparison.x()*radius_to_degrees, 2);
Serial.print(" y: ");
Serial.print(euler_comparison.y()*radius_to_degrees, 2);
Serial.print(" z: ");
Serial.print(euler_comparison.z()*radius_to_degrees, 2);
Serial.print("\n");
}