Go Down

Topic: Accuracy: Euler vs Quaternion (Read 164 times) previous topic - next topic

Feargaill

I'm using a Trinket M0 w/ a BNO055 to act as a mouse, which will give the most precision, Euler or Quaternion?

jremington

Precision is the same either way.

Feargaill

Thanks, any opinion on which is easier to program with?

jremington

#3
Aug 21, 2019, 01:47 am Last Edit: Aug 21, 2019, 02:20 am by jremington
About the same, but Euler angles cannot uniquely represent all possible 3D orientations.

What does the body 3D orientation have to do with mouse function?

Feargaill

I'm trying to make a head mouse. All I actually need is the x,y axis and acceleration for pointer speed. I'm using a pro micro/mpu9250 but it's not great w/ small motions, i.e typing. I have a trinketm0 and bno055 , I'll see if that works better. Here's the promicro sketch if you're curious

Code: [Select]
/

#include<Wire.h>
#include<Mouse.h>


const int MPU=0x68;
int16_t GyX, GyY, GyZ, AcX, AcY, AcZ, BAcX, BAcY, BAcZ, TAcX, TAcY, TAcZ;

int buttonGyro = 6;
int buttonAccel = 4;
int buttonState = 0;

int gyroLock = 0;
int AccelLock = 0;
int AccelLockToggle = 0;
int AccelLockSide = 0;
int GyroLockToggle = 0;
int GyroLockSide = 0;
int i = 0;
int i2 = 0;
int w = 0, a = 0, j = 0;
int threshold = 1;
int X, Y, Z;
int minX, maxX, minY, maxY, minZ, maxZ;
int accelLock = 0;
int TGY = 0;
void setup(){

  pinMode(buttonGyro, INPUT);
  digitalWrite(buttonGyro, HIGH);
  pinMode(buttonAccel, INPUT);
  digitalWrite(buttonAccel, HIGH);
 
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B); 
  Wire.write(0);     
  Wire.endTransmission(true);
  Serial.begin(1);
  Mouse.begin();
}
void loop(){
  gyroLock = digitalRead(buttonGyro);
  if (gyroLock == LOW) {
    if (GyroLockSide == 0) {
      GyroLockSide = 1;
      if (GyroLockToggle == 0) {
        GyroLockToggle = 1;
      }
      else {
        GyroLockToggle = 0;
      }
    }
  }
  else {
    if (GyroLockSide == 1) {
      GyroLockSide = 0;
    }
  }
  if (GyroLockToggle == 0) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43); 
    Wire.endTransmission(false);
    Wire.requestFrom(MPU,6,true);
    GyX = Wire.read()<<8|Wire.read();
    GyY = Wire.read()<<8|Wire.read();
    GyZ = Wire.read()<<8|Wire.read();//
    if (AccelLockToggle == 1) {
      Mouse.move( -GyZ / 1000, GyX / 1000, 0 );
    }
    else {
      Mouse.move( -GyZ / 2000, GyX / 2000, 0 );
    }
    TGY -= GyY / 1000;
    if (AccelLockToggle == 1) {
      if (TGY > 1000) {

      }
      else if (TGY < -1000) {
        //
      }
    }
    else {
      TGY = 0;
    }
    if (GyX > 2000 || GyY > 2000 || GyZ > 2000) {
      accelLock = 0;
    }
    else {
      accelLock = 1;
    }
  }
  AccelLock = digitalRead(buttonAccel);
  if (AccelLock == LOW) {
    if (AccelLockSide == 0) {
      AccelLockSide = 1;
      if (AccelLockToggle == 0) {
        AccelLockToggle = 1;
      }
      else {
        AccelLockToggle = 0;
      }
    }
  }
  else {
    if (AccelLockSide == 1) {
      AccelLockSide = 0;
    }
  }
  if (AccelLockToggle == 1) {
    if (true) {
      if (i == 0) {
        Wire.beginTransmission(MPU);
        Wire.write(0x3B); 
        Wire.endTransmission(false);
        Wire.requestFrom(MPU, 6, true);  //
        BAcX=Wire.read()<<8|Wire.read();// 0x3B     
        BAcY=Wire.read()<<8|Wire.read();
        BAcZ=Wire.read()<<8|Wire.read();// 0x40
        i = 1;
        minX = BAcX;
        maxX = BAcX;
        minY = BAcY;
        maxY = BAcY;
        minZ = BAcZ;
        maxZ = BAcZ;
        BAcX /= 500;
        BAcY /= 500;
        BAcZ /= 500;
      }
      Wire.beginTransmission(MPU);
      Wire.write(0x3B);  //
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 6, true);  //
      AcX=Wire.read()<<8|Wire.read();// 0x3B     
      AcY=Wire.read()<<8|Wire.read();
      AcZ=Wire.read()<<8|Wire.read();// 0x40
      if (AcX < minX) {
        minX = AcX;
      }
      else if (AcX > maxX) {
        maxX = AcX;
      }
      if (AcY < minY) {
        minY = AcY;
      }
      else if (AcY > maxY) {
        maxY = AcY;
      }
      if (AcZ < minZ) {
        minZ = AcZ;
      }
      else if (AcZ > maxZ) {
        maxZ = AcZ;
      }
//   
      AcX /= 8000;
      TAcX = AcX;
      AcX -= BAcX;
      BAcX = TAcX;
      AcY /= 8000;
      TAcY = AcY;
      AcY -= BAcY;
      BAcY = TAcY;
      AcZ /= 8000;
      TAcZ = AcZ;
      AcZ -= BAcZ;
      BAcZ = TAcZ;
      Y = -AcX;
      X = -AcY;
      Z = AcZ;
      Y = 0;
 
      if (X > threshold) {
        if (w == 0) {
          w = 1;
        }
        else if (w == -1) {
          w = -2;
        }
        else if (w == 4) {
          w = 0;
        }
        else if (w == -3) {
          w = -4;
        }
      }
      else if (X < -threshold) {
        if (w == 1) {
          w = 2;
        }
        else if (w == 0) {
          w = -1;
        }
        else if (w == 3) {
          w = 4;
        }
        else if (w == -4) {
          w = 0;
        }
      }
      else {
        if (w == 2) {
          w = 3;
        }
        else if (w == -2) {
          w = -3;
        }
      }
      if (Y > threshold) {
        if (a == 0) {
          a = 1;
        }
        else if (a == -1) {
          a = -2;
        }
        else if (a == 4) {
          a = 0;
        }
        else if (a == -3) {
          a = -4;
        }
      }
      else if (Y < -threshold) {
        if (a == 1) {
          a = 2;
        }
        else if (a == 0) {
          a = -1;
        }
        else if (a == 3) {
          a = 4;
        }
        else if (a == -4) {
          a = 0;
        }
      }
      else {
        if (a == 2) {
          a = 3;
        }
        else if (a == -2) {
          a = -3;
        }
      }
      if (Z > threshold) {
        if (j == 0) {
          j = 1;
        }
        else if (j == -1) {
          j = -2;
        }
        else if (j == 4) {
          j = 0;
        }
        else if (j == -3) {
          j = -4;
        }
      }
      else if (Z < -threshold) {
        if (j == 1) {
          j = 2;
        }
        else if (j == 0) {
          j = -1;
        }
        else if (j == 3) {
          j = 4;
        }
        else if (j == -4) {
          j = 0;
        }
      }
      else {
        if (j == 2) {
          j = 3;
        }
        else if (j == -2) {
          j = -3;
        }
      }
    }
    }
 
 
  delay(0);
}


MarkT

#6
Aug 21, 2019, 01:21 pm Last Edit: Aug 21, 2019, 01:23 pm by MarkT
About the same, but Euler angles cannot uniquely represent all possible 3D orientations.
Euler angles cannot be used easily to handle arbitrary rotations due to the gimbal lock problem,
you'd avoid using them for calculation, only for presenting the results.

Unit quaternions or DCM (direction cosine matrix) are the representations to use internally, Quaternions
being more compact.  Both are reasonably stable computationally if you re-normalize after each operation, re-normalizing is easy with quarterions.

BTW unit quarternions have double cover over 3D rotation/orientation, so they cannot uniquely represent them
either, but its not an issue, the maths always works - rotating clockwise about up is the same as rotating
anticlockwise about down.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up