0

I have been using a BNO055 sensor (9° dof IMU) for a project which will use angular velocity to the mouse cursor on 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.

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, 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");
  }
1
  • Sorry if this overlaps with any of my previous questions, I felt it was different enough that it would be more confusing to edit a already closed one. Thank you for your time. Apr 20, 2021 at 8:40

1 Answer 1

1

Consider building on Sebastian Madgwick's PhD IMU research. A GitHub Arduino project based on Madgwick's work can be found here.

3
  • Thanks for your response. The BNO sensor uses a proprietary fusion algorithm, but I've seen this implementation on a different sensor. I think my question boils down to if it's going to be more accurate to polled the sensor for quaternions from which to calculate angular velocity, or to poll the gyroscope only. Is the only difference that one is out of orientation, and the other is absolute? Apr 20, 2021 at 14:58
  • I am not sure. I have not worked with IMU chips that create quaternions. Only with IMU chips which provide X,Y & Z values from accelerometers and gyroscopes.
    – st2000
    Apr 21, 2021 at 13:13
  • There is also an Adafruit library for this and other fusion algos. Sep 24, 2021 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.