Beispiel #1
0
        protected MatrixLibrary.Matrix magneticCompensation(MyQuaternion q, double m_x, double m_y, double m_z)
        {
            MatrixLibrary.Matrix h = new MatrixLibrary.Matrix(4, 1);
            MatrixLibrary.Matrix temp;
            //compute the direction of the magnetic field
            MatrixLibrary.Matrix quaternion           = q.getQuaternionAsVector();
            MatrixLibrary.Matrix quaternion_conjugate = q.getConjugate();

            //magnetic field compensation
            temp = MyQuaternion.quaternionProduct(quaternion, new MyQuaternion(0.0, m_x, m_y, m_z).getQuaternionAsVector());
            h    = MyQuaternion.quaternionProduct(temp, quaternion_conjugate);
            double bx = Math.Sqrt((h[1, 0] * h[1, 0] + h[2, 0] * h[2, 0]));
            double bz = h[3, 0];

            double norm = Math.Sqrt(bx * bx + bz * bz);

            bx /= norm;
            bz /= norm;
            MatrixLibrary.Matrix result = new MatrixLibrary.Matrix(3, 1);
            result[0, 0] = bx;
            result[1, 0] = 0;
            result[2, 0] = bz;
            return(result);
        }
        public override void filterStep(double w_x, double w_y, double w_z, double a_x, double a_y, double a_z, double m_x, double m_y, double m_z)
        {
            // normalise the accelerometer measurement
            double norm = Math.Sqrt(a_x * a_x + a_y * a_y + a_z * a_z);

            a_x /= norm;
            a_y /= norm;
            a_z /= norm;

            // normalise the magnetometer measurement
            norm = Math.Sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
            m_x /= norm;
            m_y /= norm;
            m_z /= norm;

            if (AccObservX.Count < 10)
            {
                AccObservX.Add(a_x);
                AccObservY.Add(a_y);
                AccObservZ.Add(a_z);
            }
            else
            {
                AccObservX.RemoveAt(0);
                AccObservY.RemoveAt(0);
                AccObservZ.RemoveAt(0);

                AccObservX.Add(a_x);
                AccObservY.Add(a_y);
                AccObservZ.Add(a_z);
            }
            if (MagnObservX.Count < 10)
            {
                MagnObservX.Add(m_x);
                MagnObservY.Add(m_y);
                MagnObservZ.Add(m_z);
            }
            else
            {
                MagnObservX.RemoveAt(0);
                MagnObservY.RemoveAt(0);
                MagnObservZ.RemoveAt(0);
                MagnObservX.Add(m_x);
                MagnObservY.Add(m_y);
                MagnObservZ.Add(m_z);

                //Filter stabilization
                accFilter.Applyfilter(AccObservX, out AccFiltX);
                accFilter.Applyfilter(AccObservY, out AccFiltY);
                accFilter.Applyfilter(AccObservZ, out AccFiltZ);

                magnFilter.Applyfilter(MagnObservX, out MagnFiltX);
                magnFilter.Applyfilter(MagnObservY, out MagnFiltY);
                magnFilter.Applyfilter(MagnObservZ, out MagnFiltZ);
            }

            if (step < 10)
            {
            }
            else
            {
                accFilter.Applyfilter(AccObservX, out AccFiltX);
                accFilter.Applyfilter(AccObservY, out AccFiltY);
                accFilter.Applyfilter(AccObservZ, out AccFiltZ);

                magnFilter.Applyfilter(MagnObservX, out MagnFiltX);
                magnFilter.Applyfilter(MagnObservY, out MagnFiltY);
                magnFilter.Applyfilter(MagnObservZ, out MagnFiltZ);

                a_x = AccFiltX.Last();
                a_y = AccFiltY.Last();
                a_z = AccFiltZ.Last();

                m_x = MagnFiltX.Last();
                m_y = MagnFiltY.Last();
                m_z = MagnFiltZ.Last();

                //Magnetometer Calibration values
                //m_x =m_x*1.2+ 0.3;
                //m_y = m_y*1.1+0.04;
                //m_z += -0.08;

                double normA = Math.Sqrt(a_x * a_x + a_y * a_y + a_z * a_z);
                double normM = Math.Sqrt(m_x * m_x + m_y * m_y + m_z * m_z);

                a_x /= normA;
                a_y /= normA;
                a_z /= normA;

                m_x /= normM;
                m_y /= normM;
                m_z /= normM;

                w_x = (w_x - gyroOffRoll) * Math.PI / 180;
                w_y = (w_y - gyroOffPitch) * Math.PI / 180;
                w_z = (w_z - gyroOffYaw) * Math.PI / 180;

                MatrixLibrary.Matrix dq = 0.5 * (MyQuaternion.quaternionProduct(qFilt, new MyQuaternion(0, w_x, w_y, w_z).getQuaternionAsVector()));
                qGyroFilt = qFilt + dq * dt;

                norm       = Math.Sqrt(qGyroFilt[0, 0] * qGyroFilt[0, 0] + qGyroFilt[1, 0] * qGyroFilt[1, 0] + qGyroFilt[2, 0] * qGyroFilt[2, 0] + qGyroFilt[3, 0] * qGyroFilt[3, 0]);
                qGyroFilt /= norm;

                double dqNorm = Math.Sqrt(dq[0, 0] * dq[0, 0] + dq[1, 0] * dq[1, 0] + dq[2, 0] * dq[2, 0] + dq[3, 0] * dq[3, 0]);

                double mu = 10 * dqNorm * dt;
                if (this.obsMethod == 0)
                {
                    qObserv = GradientDescent(a_x, a_y, a_z, m_x, m_y, m_z, mu, qFilt);
                }
                else
                {
                    qObserv = gaussNewtonMethod(a_x, a_y, a_z, m_x, m_y, m_z, qFilt);
                }

                qFilt  = qGyroFilt * k + qObserv * (1 - k);
                norm   = Math.Sqrt(qFilt[0, 0] * qFilt[0, 0] + qFilt[1, 0] * qFilt[1, 0] + qFilt[2, 0] * qFilt[2, 0] + qFilt[3, 0] * qFilt[3, 0]);
                qFilt /= norm;
            }

            step++;
        }
        public override void filterStep(double w_x, double w_y, double w_z, double a_x, double a_y, double a_z, double m_x, double m_y, double m_z)
        {
            double norm;
            Matrix temp;//=new Matrix(4,4);
            Matrix dq = new Matrix(4, 1);
            double mu;
            double k;

            // normalise the accelerometer measurement
            norm = Math.Sqrt(a_x * a_x + a_y * a_y + a_z * a_z);
            a_x /= norm;
            a_y /= norm;
            a_z /= norm;

            // normalise the magnetometer measurement
            norm = Math.Sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
            m_x /= norm;
            m_y /= norm;
            m_z /= norm;

            /*   if (AccObservX.Count < 10)
             *  {
             *      AccObservX.Add(a_x);
             *      AccObservY.Add(a_y);
             *      AccObservZ.Add(a_z);
             *  }
             *  else
             *  {
             *      AccObservX.RemoveAt(0);
             *      AccObservY.RemoveAt(0);
             *      AccObservZ.RemoveAt(0);
             *
             *      AccObservX.Add(a_x);
             *      AccObservY.Add(a_y);
             *      AccObservZ.Add(a_z);
             *  }
             *  if (MagnObservX.Count < 10)
             *  {
             *      MagnObservX.Add(m_x);
             *      MagnObservY.Add(m_y);
             *      MagnObservZ.Add(m_z);
             *  }
             *  else
             *  {
             *      MagnObservX.RemoveAt(0);
             *      MagnObservY.RemoveAt(0);
             *      MagnObservZ.RemoveAt(0);
             *      MagnObservX.Add(m_x);
             *      MagnObservY.Add(m_y);
             *      MagnObservZ.Add(m_z);
             *
             *      //Filter stabilization
             *      accFilter.Applyfilter(AccObservX, out AccFiltX);
             *      accFilter.Applyfilter(AccObservY, out AccFiltY);
             *      accFilter.Applyfilter(AccObservZ, out AccFiltZ);
             *
             *      magnFilter.Applyfilter(MagnObservX, out MagnFiltX);
             *      magnFilter.Applyfilter(MagnObservY, out MagnFiltY);
             *      magnFilter.Applyfilter(MagnObservZ, out MagnFiltZ);
             *  }
             *
             *  if (countdata > 10)
             *  {
             *      a_x = AccFiltX.Last();
             *      a_y = AccFiltY.Last();
             *      a_z = AccFiltZ.Last();
             *
             *      m_x = MagnFiltX.Last();
             *      m_y = MagnFiltY.Last();
             *      m_z = MagnFiltZ.Last();
             *
             *      // normalise the accelerometer measurement
             *
             *      norm = Math.Sqrt(a_x * a_x + a_y * a_y + a_z * a_z);
             *      a_x /= norm;
             *      a_y /= norm;
             *      a_z /= norm;
             *
             *
             *      // normalise the magnetometer measurement
             *      norm = Math.Sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
             *      m_x /= norm;
             *      m_y /= norm;
             *      m_z /= norm;
             *  }
             *
             *
             *
             * countdata++;
             */
            //  w_x = w_x - gyroOffRoll;
            //  w_y = w_y - gyroOffPitch;
            // w_z = w_z - gyroOffYaw;

            w_x = w_x * Math.PI / 180;
            w_y = w_y * Math.PI / 180;
            w_z = w_z * Math.PI / 180;


            if (this.obsMethod == 0)
            {
                dq             = 0.5 * (MyQuaternion.quaternionProduct(state_observed, new MyQuaternion(0.0, w_x, w_y, w_z).getQuaternionAsVector()));
                norm           = Math.Sqrt(dq[0, 0] * dq[0, 0] + dq[1, 0] * dq[1, 0] + dq[2, 0] * dq[2, 0] + dq[3, 0] * dq[3, 0]);
                mu             = 10 * norm * dt;
                state_observed = GradientDescent(a_x, a_y, a_z, m_x, m_y, m_z, mu, state_filtered);
            }
            else
            {
                state_observed = gaussNewtonMethod(a_x, a_y, a_z, m_x, m_y, m_z, state_filtered);
            }

            //KALMAN FILTERING

            //F matrix computing
            F[0, 0] = 1;
            F[0, 1] = -dt / 2 * w_x;
            F[0, 2] = -dt / 2 * w_y;
            F[0, 3] = -dt / 2 * w_z;
            F[1, 0] = dt / 2 * w_x;
            F[1, 1] = 1;
            F[1, 2] = dt / 2 * w_z;
            F[1, 3] = -dt / 2 * w_y;
            F[2, 0] = dt / 2 * w_y;
            F[2, 1] = -dt / 2 * w_z;
            F[2, 2] = 1;
            F[2, 3] = dt / 2 * w_x;
            F[3, 0] = dt / 2 * w_z;
            F[3, 1] = dt / 2 * w_y;
            F[3, 2] = -dt / 2 * w_x;
            F[3, 3] = 1;

            //state prediction
            state_predicted = Matrix.Multiply(F, state_filtered);

            //calculate the variance of the prediction
            P_predicted = Matrix.Multiply(F, P_Update);
            P_predicted = Matrix.Multiply(P_predicted, Matrix.Transpose(F)) + Q;

            //compute the gain of the filter K
            temp = Matrix.Add(Matrix.Multiply(Matrix.Multiply(H, P_predicted), Matrix.Transpose(H)), R);
            temp = Matrix.Inverse(temp);
            K    = Matrix.Multiply(Matrix.Multiply(P_predicted, Matrix.Transpose(H)), temp);

            //update the state of the system (this is the output of the filter)
            temp           = Matrix.Subtract(state_observed, Matrix.Multiply(H, state_predicted));
            state_filtered = Matrix.Add(state_predicted, Matrix.Multiply(K, temp));

            //compute the variance of the state filtered
            temp     = Matrix.Subtract((new Matrix(Matrix.Identity(4))), Matrix.Multiply(K, H));
            P_Update = Matrix.Multiply(temp, P_predicted);

            norm           = Math.Sqrt(state_filtered[0, 0] * state_filtered[0, 0] + state_filtered[1, 0] * state_filtered[1, 0] + state_filtered[2, 0] * state_filtered[2, 0] + state_filtered[3, 0] * state_filtered[3, 0]);
            state_filtered = Matrix.ScalarDivide(norm, state_filtered);
            q_filt1        = (float)state_filtered[0, 0];
            q_filt2        = (float)state_filtered[1, 0];
            q_filt3        = (float)state_filtered[2, 0];
            q_filt4        = (float)state_filtered[3, 0];
        }