Detect-360-yaw-roll-pitch

Hi Everyone,

Using FreeIMU and the GetEuler Function, I finally managed to detect a full rotation on Yaw & Roll axis, the FreeIMU::GetEuler function is supposed to use Quaternions, and thus should be Gimbal Lock free, although it seems it only give the following ranges:
-180<Yaw<180
-180<Roll<180
-45<Pitch<45

As my algorithm for the detection of the complete revolution works well with the yaw and roll ranges, I would like the pitch values to have the same ranges so I don't have to create another algorithm for it, I don't know how to use Quaternions directly, it seems complicated...

Do you have any Idea on how to manage this?

You'll find enclosed an excel of the values recorded during a complete revolution over pitch axis, and my code for theses detections with the FreeIMU software.

I am also trying to use the "software interrupt" as described on p70 of the ATMega328P documentationhttp://www.atmel.com/devices/atmega328.aspx?tab=documents.
but this does not work, I don't understand why:

//I set the PCINT0 to output
#define YAW_INTERRUPT 12
pinMode(YAW_INTERRUPT, OUTPUT); 

//And then Fire it up in one of my functions
digitalWrite(YAW_INTERRUPT, HIGH);
//so it can trigger some code
ISR(PCINT0_vect)//ISR Vector Handler(Set the right Port Vector to handle interrupt)
{
    digitalWrite(BLUE_LED_PIN,HIGH);
    Serial.println("INTERRUPTED");
    digitalWrite(RED_LED_PIN,HIGH); 
}

But the only thing it does is trigger the interrupt when I make a voltage variation on that pin by tapping on it with my finger see videohttp://sdrv.ms/13801Bn

Thanks a lot for your answers.

FullPitchValues.xlsx (22.5 KB)

FreeIMU_yaw_pitch_roll_V1_5.ino (8.51 KB)

Get the quarternion or DCM and convert to Euler angles yourself?

Yes 3D rotations are harder than 2D, that goes with the territory I'm afraid. Does FreeIMU
give you the DCM as well?

Hi MarkT,

First of all thanks for your answer,

I am now struggling with the FreeIMU::YawPitchRoll function values, because I found out that the FreeIMU::GetEuler values of Pitch & Roll are dependent, and for my application it is better to have rotation with reference to the ground(it is not an aircraft...)

But the full rotation detection problem is still the same because now I have got these ranges:
-180<Yaw<180
-90<Roll<90
-90<Pitch<90

I was wrong in my last message ranges are not pitch ranges were not 45 but 90° with FreeIMU::GetEuler Function

FreeIMU does not give a DCM (from what I understand, and I don't understand much) the FreeIMU::YawPitchRoll function calculates attitude directly from Quaternions.

You'll find enclosed a copy of my actual code, which does not work for Pitch by the way...I let the Yaw function but set away the Roll function for now until I get the Pitch function working because it should be the same.

Thanks a lot for your help

See Code Bellow for the FreeIMU::YawPitchRoll Function :

/**
 * Returns the yaw pitch and roll angles, respectively defined as the angles in radians between
 * the Earth North and the IMU X axis (yaw), the Earth ground plane and the IMU X axis (pitch)
 * and the Earth ground plane and the IMU Y axis.
 * 
 * @note This is not an Euler representation: the rotations aren't consecutive rotations but only
 * angles from Earth and the IMU. For Euler representation Yaw, Pitch and Roll see FreeIMU::getEuler
 * 
 * @param ypr three floats array which will be populated by Yaw, Pitch and Roll angles in radians
*/
void FreeIMU::getYawPitchRollRad(float * ypr) {
  float q[4]; // quaternion
  float gx, gy, gz; // estimated gravity direction
  getQ(q);
  
  
  gx = 2 * (q[1]*q[3] - q[0]*q[2]);
  gy = 2 * (q[0]*q[1] + q[2]*q[3]);
  gz = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
  
  ypr[0] = atan2(2 * q[1] * q[2] - 2 * q[0] * q[3], 2 * q[0]*q[0] + 2 * q[1] * q[1] - 1);
  ypr[1] = atan(gx / sqrt(gy*gy + gz*gz));
  ypr[2] = atan(gy / sqrt(gx*gx + gz*gz));
}


/**
 * Returns the yaw pitch and roll angles, respectively defined as the angles in degrees between
 * the Earth North and the IMU X axis (yaw), the Earth ground plane and the IMU X axis (pitch)
 * and the Earth ground plane and the IMU Y axis.
 * 
 * @note This is not an Euler representation: the rotations aren't consecutive rotations but only
 * angles from Earth and the IMU. For Euler representation Yaw, Pitch and Roll see FreeIMU::getEuler
 * 
 * @param ypr three floats array which will be populated by Yaw, Pitch and Roll angles in degrees
*/
void FreeIMU::getYawPitchRoll(float * ypr) {
  getYawPitchRollRad(ypr);
  arr3_rad_to_deg(ypr);
}


/**
 * Converts a 3 elements array arr of angles expressed in radians into degrees
*/
void arr3_rad_to_deg(float * arr) {
  arr[0] *= 180/M_PI;
  arr[1] *= 180/M_PI;
  arr[2] *= 180/M_PI;
}

FreeIMU_YPR_45_V2_0_1.ino (30.4 KB)

You may find this useful, but maybe not, yeah, the math is a bit complicated

http://www.chrobotics.com/library/understanding-quaternions

Be careful, since Euler angles are angles between axes, which are rotated with others. Yes, you need yaw, pitch and roll (with respect to ground).

I use freeImu too, but if I don't use quaternions, I allways get "NaN" (not a number) values. And I wonder, if you have any hint for me? The thread is: Free IMU library and MPU6050 - Programming Questions - Arduino Forum

Thanks