/// <summary>
 /// Quaternion data received event to set servo angles of gimbal.
 /// </summary>
 void xIMUserial_QuaternionDataReceived(object sender, x_IMU_API.QuaternionData e)
 {
     x_IMU_API.QuaternionData quaternionData;
     if (radioButton_controlMode.Checked)
     {
         quaternionData = e;
     }
     else
     {
         quaternionData = e.ConvertToConjugate();
     }
     try
     {
         float[] EulerAngles = quaternionData.ConvertToEulerAngles();
         gimbalSerial.SetTilt(EulerAngles[0]);
         gimbalSerial.SetRoll(EulerAngles[1]);
         gimbalSerial.SetPan(EulerAngles[2]);
     }
     catch { }
 }
        private void timer1_Tick(object sender, EventArgs e)
        {
            a = (float)Math.Cos((alpha * Math.PI) / (180 * 2));
            b = (float)Math.Sin((alpha * Math.PI) / (180 * 2));
            float[] Quaternion_1 = new float[] { a, 0.0f, b, .0f };
            float[] quaternion = new float[] { 1, 0.0f, 0.0f, 0.0f };
            float[] eulerAngles = new float[] { 0.0f, 0.0f, 0.0f };

            Quaternion_1[0] = a;
            Quaternion_1[1] = 0.0f;
            Quaternion_1[2] = b;
            Quaternion_1[3] = 0.0f;
          
            qw.Quaternion = Quaternion_1;

            /* Refresh rotate matrix on the form object. */
            //Form_3D_DA.RotationMatrix = qw.ConvertToRotationMatrix();
#if DEMO
            Quaternion_1[0] = a;
            Quaternion_1[1] = b;
            Quaternion_1[2] = 0.0f;
            Quaternion_1[3] = 0.0f;

            qw.Quaternion = Quaternion_1;
            Form_3D_DB.RotationMatrix = qw.ConvertToRotationMatrix();
#endif

#if ! ACCEL
            if (Graph_2D_DA != null)
            {
                Graph_2D_DA.DrawGraph(
                                    (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                    (double)Port_1.currentReceivedData.Accelerometer.Axis_X.i16,
                                            0,
                                        10000.0,
                                          200,
                                          zGMaxAmountOfPoints
                                 );


                Graph_2D_DA.DrawGraph(
                         (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                         (double)Port_1.currentReceivedData.Accelerometer.Axis_Y.i16,
                                    1,
                                    10000.0,
                                    200,
                                    zGMaxAmountOfPoints
                        );
                Graph_2D_DA.DrawGraph(
                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                        (double)Port_1.currentReceivedData.Accelerometer.Axis_Z.i16,
                                2,
                            10000.0,
                              200,
                              zGMaxAmountOfPoints
                        );
            }
#else //GYRO
            if (Graph_2D_DA != null)
            {
                Graph_2D_DA.DrawGraph(
                                    (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                    (double)Port_1.currentReceivedData.Gyro.Rot_XY.i16 -2 ,
                                            0,
                                        10000.0,
                                          200,
                                          zGMaxAmountOfPoints
                                 );


                Graph_2D_DA.DrawGraph(
                         (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                         (double)Port_1.currentReceivedData.Gyro.Rot_XZ.i16,
                                    1,
                                    10000.0,
                                    200,
                                    zGMaxAmountOfPoints
                        );
                Graph_2D_DA.DrawGraph(
                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                        (double)Port_1.currentReceivedData.Gyro.Rot_YZ.i16,
                                2,
                            10000.0,
                              200,
                              zGMaxAmountOfPoints
                        );
            }
#endif
          

#if ! Gyro            
            
            if (Graph_2D_DB != null)
            {
                Graph_2D_DB.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)Port_1.currentReceivedData.Magnetometer.Axis_X.i16,
                                                0,
                                            10000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );

                Graph_2D_DB.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)Port_1.currentReceivedData.Magnetometer.Axis_Y.i16,
                                                1,
                                            10000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );
                Graph_2D_DB.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)Port_1.currentReceivedData.Magnetometer.Axis_Z.i16,
                                                2,
                                            10000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );

             }
#else  //GYRO
            if (Graph_2D_DB != null)
            {
                Graph_2D_DB.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)Port_1.currentReceivedData.Gyro.Rot_XY.i16 - 2,
                                                0,
                                            10000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );

                Graph_2D_DB.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)Port_1.currentReceivedData.Gyro.Rot_XZ.i16,
                                                1,
                                            10000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );
                Graph_2D_DB.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)Port_1.currentReceivedData.Gyro.Rot_YZ.i16,
                                                2,
                                            10000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );
            }
#endif

            qw.Quaternion = Port_1.bodyQuaternion;
            quaternion = Port_1.bodyQuaternion;
            label2.Text = Convert.ToString(Port_1.deltaTime);
            
            eulerAngles  = qw.ConvertToEulerAngles();

            
            /******** My Euler Angle  ****************************/
            float Pitch_Real=0;
            float Roll_Real=0;
            float Yaw_Real;

            Pitch_Real = (float)Math.Atan2 (2*(quaternion[0]*quaternion[1]+quaternion[2]*quaternion[3]),1-2*(quaternion[1]*quaternion[1]+quaternion[2]*quaternion[2]));
            Roll_Real = (float)Math.Asin (2*(quaternion[0]*quaternion[2]-quaternion[3]*quaternion[1]));
            Yaw_Real = (float)Math.Atan2(2 * (quaternion[0] * quaternion[3] + quaternion[1] * quaternion[2]), 1 - 2 * (quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3]));
            label76.Text = Convert.ToString(Roll_Real * 180 / (float)Math.PI); // Roll
            label77.Text = Convert.ToString(Pitch_Real * 180 / (float)Math.PI); // Pitch
            label78.Text = Convert.ToString(Yaw_Real * 180 / (float)Math.PI); // Yaw
            /********************************************************************************/


            /****** One more My Euler Angle ************/
            float heading;
		    float attitude;
		    float bank;


          	double test = quaternion[1]*quaternion[2] + quaternion[3]*quaternion[0];
	        if (test > 0.499) 
            { // singularity at north pole
		        heading = 2 * (float)Math.Atan2(quaternion[1],quaternion[0]);
		        attitude = (float)Math.PI/2;
		        bank = 0;
		    }
	        if (test < -0.499) 
            { // singularity at south pole
		        heading = -2 * (float)Math.Atan2(quaternion[1],quaternion[0]);
		        attitude = - (float)Math.PI/2;
		        bank = 0;
			}
            double sqx = quaternion[1]*quaternion[1];
            double sqy = quaternion[2]*quaternion[2];
            double sqz = quaternion[3]*quaternion[3];
            heading = (float)Math.Atan2(2*quaternion[2]*quaternion[0]-2*quaternion[1]*quaternion[3] , 1 - 2*sqy - 2*sqz);
	        attitude = (float)Math.Asin(2*test);
            bank = (float)Math.Atan2(2 * quaternion[1] * quaternion[0] - 2 * quaternion[2] * quaternion[3], 1 - 2 * sqx - 2 * sqz);

            label80.Text = Convert.ToString(heading * 180 / (float)Math.PI); // Pitch
            label81.Text = Convert.ToString(bank * 180 / (float)Math.PI); // Roll
            label82.Text = Convert.ToString(attitude * 180 / (float)Math.PI); // Yaw



            /*********************************************/



            /********* Angle Axis ***********************/
            float angle;

            float x,y,z;

            angle = 2 * (float)Math.Acos(Port_1.bodyQuaternion[0]);
            double s = Math.Sqrt(1 - Port_1.bodyQuaternion[0] * Port_1.bodyQuaternion[0]);
            if (s < 0.001)
            {
                x = Port_1.bodyQuaternion[1]; // if it is important that axis is normalised then replace with x=1; y=z=0;
                y = Port_1.bodyQuaternion[2];
                z = Port_1.bodyQuaternion[3];
            } 
            else 
            {
                x = Port_1.bodyQuaternion[1]/(float)s; 
                y = Port_1.bodyQuaternion[2]/(float)s;
                z = Port_1.bodyQuaternion[3]/(float)s;
            }

            angle = angle * 180 / (float)Math.PI;
            label71.Text = Convert.ToString(angle); 
            label72.Text = Convert.ToString(x); 
            label73.Text = Convert.ToString(y); 
            label74.Text = Convert.ToString(z); 
            /****** End Angle Axis *********************************/




            /* Quaternion PC. */
            
            label16.Text = Convert.ToString(eulerAngles[0]); // Roll
            label17.Text = Convert.ToString(eulerAngles[1]); // Pitch
            label18.Text = Convert.ToString(eulerAngles[2]); // Yaw

            label26.Text = Convert.ToString(Port_1.currentReceivedData.EulerAngle_0.f32);
            label27.Text = Convert.ToString(Port_1.currentReceivedData.EulerAngle_1.f32);
            label28.Text = Convert.ToString(Port_1.currentReceivedData.EulerAngle_2.f32);


            /* Add PIDs */
            /* Static PID */
            /* Roll. */
            label39.Text = Convert.ToString(Port_1.currentReceivedData.Roll.kP.u16);
            label40.Text = Convert.ToString(Port_1.currentReceivedData.Roll.kI.u16);
            label41.Text = Convert.ToString(Port_1.currentReceivedData.Roll.kD.u16);

            /* Pitch. */
            label42.Text = Convert.ToString(Port_1.currentReceivedData.Pitch.kP.u16);
            label43.Text = Convert.ToString(Port_1.currentReceivedData.Pitch.kI.u16);
            label44.Text = Convert.ToString(Port_1.currentReceivedData.Pitch.kD.u16);

            /* Yaw. */
            label45.Text = Convert.ToString(Port_1.currentReceivedData.Yaw.kP.u16);
            label46.Text = Convert.ToString(Port_1.currentReceivedData.Yaw.kI.u16);
            label47.Text = Convert.ToString(Port_1.currentReceivedData.Yaw.kD.u16);

            /* Dynamic PID */

            /* Roll. */
            label48.Text = Convert.ToString(Port_1.currentReceivedData.Roll.kP_dynamic.u16);
            label49.Text = Convert.ToString(Port_1.currentReceivedData.Roll.kI_dynamic.u16);
            label50.Text = Convert.ToString(Port_1.currentReceivedData.Roll.kD_dynamic.u16);

            /* Pitch. */
            label51.Text = Convert.ToString(Port_1.currentReceivedData.Pitch.kP_dynamic.u16);
            label52.Text = Convert.ToString(Port_1.currentReceivedData.Pitch.kI_dynamic.u16);
            label53.Text = Convert.ToString(Port_1.currentReceivedData.Pitch.kD_dynamic.u16);

            /* Yaw. */
            label54.Text = Convert.ToString(Port_1.currentReceivedData.Yaw.kP_dynamic.u16);
            label55.Text = Convert.ToString(Port_1.currentReceivedData.Yaw.kI_dynamic.u16);
            label56.Text = Convert.ToString(Port_1.currentReceivedData.Yaw.kD_dynamic.u16);


#if ! MAGNETOMETER            
            if (Graph_2D_DC != null)
            {
                Graph_2D_DC.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)eulerAngles[0],
                                                0,
                                            100000.0,
                                              200,
                                              3000//zGMaxAmountOfPoints
                                    );

                Graph_2D_DC.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                        (double)eulerAngles[1],
                                                1,
                                            100000.0,
                                              200,
                                              3000//zGMaxAmountOfPoints
                                    );

                /* midle filter.*/
                float angl_sum=0;
                int angl_ind=50;
                angl_sum = 0;
                angl_ind = 0;

                while(angl_ind < 10 )
                {
                    angl_sum = angl_sum + angl_midl[angl_ind];
                    angl_ind++;
                }
                angl_sum = angl_sum /(float) 10.0;
                /******************/
                Graph_2D_DC.DrawGraph(
                                        (double)Port_1.currentReceivedData.ExternalBoardSystemTime.ui32,
                                     //   ((double)eulerAngles[2] + angl_sum) / 51.0,
                                        ((double)angl_sum),
                                       
                                                2,
                                            100000.0,
                                              200,
                                              3000//zGMaxAmountOfPoints
                                    );
                /* midle filter.*/
                angl_sum = 0;
                angl_ind = 9;
                while (angl_ind > 0)
                {
                    angl_midl[angl_ind] = angl_midl[angl_ind-1];
                    angl_ind--;
                }
                //angl_midl[0] = eulerAngles[2];
                angl_midl[0] = Port_1.currentReceivedData.EulerAngle_2.f32;
                /******************/
             }
#endif

            label8.Text  = Convert.ToString(Port_1.bodyQuaternion[0]);
            label9.Text  = Convert.ToString(Port_1.bodyQuaternion[1]);
            label10.Text = Convert.ToString(Port_1.bodyQuaternion[2]);
            label11.Text = Convert.ToString(Port_1.bodyQuaternion[3]);


            label20.Text = Convert.ToString(Port_1.currentReceivedData.Quaternion_0.f32);
            label21.Text = Convert.ToString(Port_1.currentReceivedData.Quaternion_1.f32);
            label22.Text = Convert.ToString(Port_1.currentReceivedData.Quaternion_2.f32);
            label23.Text = Convert.ToString(Port_1.currentReceivedData.Quaternion_3.f32);

            
            qt.Quaternion[0] = Port_1.currentReceivedData.Quaternion_0.f32;
            qt.Quaternion[1] = Port_1.currentReceivedData.Quaternion_1.f32;
            qt.Quaternion[2] = Port_1.currentReceivedData.Quaternion_2.f32;
            qt.Quaternion[3] = Port_1.currentReceivedData.Quaternion_3.f32;


            //Save magnetometer data to file for using in calibration algoritm.
            string text = Convert.ToString(((float)Port_1.currentReceivedData.Magnetometer.Axis_X.i16)) + "\t" +
              Convert.ToString(((float)Port_1.currentReceivedData.Magnetometer.Axis_Y.i16)) + "\t" +
              Convert.ToString(((float)Port_1.currentReceivedData.Magnetometer.Axis_Z.i16));

            file_magnetometer.WriteLine(text);

/*
 * This is test for rotation by rotation matrix
 */

            float alpha_rad = 0.03f / 57.2957795130823f;
            float[] rot_z = new float[] 
            {
                (float)Math.Cos(alpha_rad) , (float)-Math.Sin(alpha_rad),  0,
                (float)Math.Sin(alpha_rad) ,(float) Math.Cos(alpha_rad) ,  0,
                                  0 ,                   0 ,                 1
            };

            float[] rot_x = new float[] 
            {   
                1,0,0,
                0,(float)Math.Cos(alpha_rad) , (float)-Math.Sin(alpha_rad),
                0,(float)Math.Sin(alpha_rad) ,(float) Math.Cos(alpha_rad) 
            };

            Matrix.rotMatrix G = new Matrix.rotMatrix();
            //rotate body by rotation matrix.
            G.MatrixMultiplication(rot_z, Form_3D_DA.RotationMatrix);
            //G.MatrixMultiplication(rot_x, G.A3x3);
            //Rotate body by rotation matrix.
        ///    Form_3D_DA.RotationMatrix = G.A3x3;



/*
 * End of test 
 */
            x_IMU_API.QuaternionData q = new x_IMU_API.QuaternionData();
            q.Quaternion =new float[] { 
                                        (float)Math.Cos(alpha_rad/2.0),
                                        (float)Math.Sin(alpha_rad/2.0)*1.0f,        //Z
                                        (float)Math.Sin(alpha_rad/2.0)*0.0f,        //Y
                                        (float)Math.Sin(alpha_rad/2.0)*0.0f         //Z
                                      };
            //Rotate body by quaternion.
          //  qw.QuaternionMultiplication(q.Quaternion);

            alpha_rad = -0.02f / 57.2957795130823f;
            q.Quaternion[0] = (float)Math.Cos(alpha_rad / 2.0);
            q.Quaternion[1] = (float)Math.Sin(alpha_rad / 2.0) * 0.0f;        //Z
            q.Quaternion[2] = (float)Math.Sin(alpha_rad / 2.0) * 1.0f;        //Y
            q.Quaternion[3] = (float)Math.Sin(alpha_rad / 2.0) * 0.0f;         //Z

          //  qw.QuaternionMultiplication(q.Quaternion);

            Form_3D_DA.RotationMatrix = qw.ConvertToConjugate().ConvertToRotationMatrix();


           // Form_3D_DA.RotationMatrix = qw.ConvertToConjugate().ConvertToRotationMatrix();
            Form_3D_DB.RotationMatrix = qt.ConvertToConjugate().ConvertToRotationMatrix();



#if DEMO  
            if (Graph_2D_DA != null)
            {
                Graph_2D_DA.DrawGraph(
                                    (double)alpha,
                                    (double)a,
                                            0,
                                        1000.0,
                                          200,
                                          zGMaxAmountOfPoints
                                 );


                Graph_2D_DA.DrawGraph(
                                        (double)alpha,
                                        (double)b,
                                                1,
                                            1000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );
            }

            if (Graph_2D_DB != null)
            {
                Graph_2D_DB.DrawGraph(
                                        (double)alpha,
                                        (double)b,
                                                0,
                                            1000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );

                Graph_2D_DB.DrawGraph(
                                        (double)alpha+10.3,
                                        (double)b,
                                                1,
                                            1000.0,
                                              200,
                                              zGMaxAmountOfPoints
                                    );
            }
#endif
            alpha = alpha + 0.05f;
     //       label2.Text = Convert.ToString(alpha);




        }
        private void button1_Click(object sender, EventArgs e)
        {
            //Port_1.MagnetAzimutCalculation(0, 0, -1, -1, 0, 3);

            x_IMU_API.QuaternionData qtest = new x_IMU_API.QuaternionData();
            qtest.Quaternion     = new float [] {1f,0f,0f,0f};
            float alpha_degree = 10;

            float alpha_rad = alpha_degree / 57.2957795130823f;

            float[] q = new float[] { 
                                        (float)Math.Cos(alpha_rad / 2.0), 
                                        (float)Math.Sin(alpha_rad / 2.0), 
                                        (float)Math.Sin(alpha_rad / 2.0), 
                                        (float)Math.Sin(alpha_rad / 2.0) 
                                    };

            qtest.QuaternionMultiplication(q);
        }
 /// <summary>
 /// Quaternion data received event to update rolling ball orientation data.
 /// </summary>
 static void xIMUserial_QuaternionDataReceived(object sender, x_IMU_API.QuaternionData e)
 {
     ballTracking.RotationMatrix = e.ConvertToRotationMatrix();
 }