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 pitch from roll.
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.
Is there a better way to go about this?
My code included below for reference with the 2 approaches in case it's helpful/interesting. It uses the Adafruit repository for BNO sensor.
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");
}
Edit: demonstration for quaternion Delta.
When quaternion current * quaternion home and transforming to Euler angles, we get the angular velocity between the 2 quaternions. Please imagine the sheet of paper to be the earth reference frame and to the watch the sensor's reference frame. With no yaw rotation, if with tilt the sensor up that causes a positive change in the y (pitch) axis. With 90° rotation of the sensor in the X (yaw) axis, however, a tilt of the sensor results in a change in the z (roll) axis instead.
My understanding is that this happens because quaternions are a representation of absolute orientation. So with any angle of rotation in the yaw axis we get a mixture of change in the pitch and roll axis whenever we tilt the sensor up or down.
This is what I mean that a change in sensor tilt (moving it up or down) results in a change in either/both the Y and Z axis.
quat_two
,quat
and angular velocity. \$\endgroup\$