#include #include #include #define rad M_PI/180.0 #define deg 180.0/M_PI // define the rest position static float restPosition[3] = {1,0,0}; float norm(float *vector, int dim){ float result = 0; int i; for (i=0; i DOT_THRESHOLD) { // If the inputs are too close for comfort, linearly interpolate // and normalize the result. for (i=0; i<4; i++){ result[i] = v0[i] + t*(v1[i] - v0[i]); } normalizeVector(result,4); return; } if (dot<-1) dot = -1; if (dot>1 ) dot = 1; // Robustness: Stay within domain of acos() double theta_0 = acos(dot); // theta_0 = angle between input vectors double theta = theta_0*t; // theta = angle between v0 and result float v2[4] = {0,0,0,0}; for (i=0; i<4; i++){ v2[i] = v1[i] - v0[i]*dot; } normalizeVector(v2,4); // { v0, v2 } is now an orthonormal basis for (i=0; i<4; i++){ result[i] = v0[i]*cos(theta) + v2[i]*sin(theta); } return; } void eulerFromQuaternion(float q[4], float euler[3]){ // heading, attitude, bank float w2 = q[0]*q[0]; float x2 = q[1]*q[1]; float y2 = q[2]*q[2]; float z2 = q[3]*q[3]; #if 0 euler[0] = atan2(2*(q[0]*q[1]-q[2]*q[3]),1-2*(x2+y2)); euler[1] = asin( 2*(q[0]*q[2]+q[1]*q[3])); euler[2] = atan2(2*(q[0]*q[3]-q[1]*q[2]),1-2*(y2+z2)); if (euler[1] <= -M_PI || euler[1] >= M_PI){ euler[2] = 0; euler[0] = atan2(q[1],q[0]); } #else float unit = w2+x2+y2+z2; // if normalised is one, otherwise is correction factor float test = q[1]*q[2] + q[3]*q[0]; if (test > 0.499*unit){ // singularity at north pole euler[0] = 2 * atan2(q[1],q[0]); euler[1] = M_PI/2; euler[2] = 0; } else if (test < -0.499*unit){ // singularity at south pole euler[0] = -2 * atan2(q[1],q[0]); euler[1] = -M_PI/2; euler[2] = 0; } else { euler[0] = atan2(2*q[2]*q[0]-2*q[1]*q[3], w2+x2-y2-z2); euler[1] = asin(2*test/unit); euler[2] = atan2(2*q[1]*q[0]-2*q[2]*q[3] , w2-x2+y2-z2); } #endif } void getRotationMatrixFromVectors(float vin[3], float vout[3], float matrix[4][4]){ normalizeVector(vout,3); float q[4] = {0,0,0,0}; float vin_length = 0; float vout_length = 0; float dotprod = 0; int i; for (i=0; i<3; i++){ vin_length += vin[i]*vin[i]; vout_length+= vout[i]*vout[i]; dotprod += vin[i]*vout[i]; } #if 1 //mila q[0] = sqrt(vin_length * vout_length) + dotprod; q[1] = -1*(vin[1]*vout[2] - vin[2]*vout[1]); q[2] = -1*(vin[2]*vout[0] - vin[0]*vout[2]); q[3] = -1*(vin[0]*vout[1] - vin[1]*vout[0]); #else float axis[3] = {0,0,0}; axis[0] = -1*(vin[1]*vout[2] - vin[2]*vout[1]); axis[1] = -1*(vin[2]*vout[0] - vin[0]*vout[2]); axis[2] = -1*(vin[0]*vout[1] - vin[1]*vout[0]); normalizeVector(axis,3); float angle = acos(vin[0]*vout[0]+vin[1]*vout[1]+vin[2]*vout[2]); quaternionFromAxis(angle, axis, q); #endif normalizeVector(q,4); float attitude = asin( 2*(q[0]*q[2]+q[1]*q[3])); getRotationMatrixFromQuartenion(q,matrix); } #if 0 int main(void) { float accData[3] = {1,0,0}; float rotationMatrix[4][4]; normalizeVector(restPosition,3); int angle; for (angle = 0; angle <90; angle+=30){ getAccellerometerData(angle*rad*1.5,angle*rad,accData); getRotationMatrixFromVectors(restPosition, accData, rotationMatrix); } return 1; } #endif