예제 #1
0
        public void CalculatePose(RTVector3 accel, RTVector3 mag, double magDeclination)
        {
            RTQuaternion m;
            RTQuaternion q = new RTQuaternion();

            if (EnableAccel)
            {
                accel.AccelToEuler(out mMeasuredPose);
            }
            else
            {
                mMeasuredPose   = mFusionPose;
                mMeasuredPose.Z = 0;
            }

            if (EnableMag && mMagValid)
            {
                q.FromEuler(mMeasuredPose);
                m = new RTQuaternion(0, mag.X, mag.Y, mag.Z);
                m = q * m * q.Conjugate();
                mMeasuredPose.Z = -Math.Atan2(m.Y, m.X) - magDeclination;
            }
            else
            {
                mMeasuredPose.Z = mFusionPose.Z;
            }

            mMeasuredQPose.FromEuler(mMeasuredPose);

            //  check for quaternion aliasing. If the quaternion has the wrong sign
            //  the filter will be very unhappy.

            int    maxIndex = -1;
            double maxVal   = -1000;

            for (int i = 0; i < 4; i++)
            {
                if (Math.Abs(mMeasuredQPose.data(i)) > maxVal)
                {
                    maxVal   = Math.Abs(mMeasuredQPose.data(i));
                    maxIndex = i;
                }
            }

            //  if the biggest component has a different sign in the measured and kalman poses,
            //  change the sign of the measured pose to match.

            if (((mMeasuredQPose.data(maxIndex) < 0) && (mFusionQPose.data(maxIndex) > 0)) ||
                ((mMeasuredQPose.data(maxIndex) > 0) && (mFusionQPose.data(maxIndex) < 0)))
            {
                mMeasuredQPose.Scalar = -mMeasuredQPose.Scalar;
                mMeasuredQPose.X      = -mMeasuredQPose.X;
                mMeasuredQPose.Y      = -mMeasuredQPose.Y;
                mMeasuredQPose.Z      = -mMeasuredQPose.Z;
                mMeasuredQPose.ToEuler(out mMeasuredPose);
            }
        }
예제 #2
0
        public void CalculatePose(RTVector3 accel, RTVector3 mag, double magDeclination)
        {
            RTQuaternion m;
            RTQuaternion q = new RTQuaternion();

            if (EnableAccel) {
                accel.AccelToEuler(out mMeasuredPose);
            } else {
                mMeasuredPose = mFusionPose;
                mMeasuredPose.Z = 0;
            }

            if (EnableMag && mMagValid) {
                q.FromEuler(mMeasuredPose);
                m = new RTQuaternion(0, mag.X, mag.Y, mag.Z);
                m = q * m * q.Conjugate();
                mMeasuredPose.Z = -Math.Atan2(m.Y, m.X) - magDeclination;
            } else {
                mMeasuredPose.Z = mFusionPose.Z;
            }

            mMeasuredQPose.FromEuler(mMeasuredPose);

            //  check for quaternion aliasing. If the quaternion has the wrong sign
            //  the filter will be very unhappy.

            int maxIndex = -1;
            double maxVal = -1000;

            for (int i = 0; i < 4; i++) {
                if (Math.Abs(mMeasuredQPose.data(i)) > maxVal) {
                    maxVal = Math.Abs(mMeasuredQPose.data(i));
                    maxIndex = i;
                }
            }

            //  if the biggest component has a different sign in the measured and kalman poses,
            //  change the sign of the measured pose to match.

            if (((mMeasuredQPose.data(maxIndex) < 0) && (mFusionQPose.data(maxIndex) > 0)) ||
                    ((mMeasuredQPose.data(maxIndex) > 0) && (mFusionQPose.data(maxIndex) < 0))) {
                mMeasuredQPose.Scalar = -mMeasuredQPose.Scalar;
                mMeasuredQPose.X = -mMeasuredQPose.X;
                mMeasuredQPose.Y = -mMeasuredQPose.Y;
                mMeasuredQPose.Z = -mMeasuredQPose.Z;
                mMeasuredQPose.ToEuler(out mMeasuredPose);
            }
        }
예제 #3
0
        public RTVector3 GetAccelResiduals()
        {
            RTQuaternion rotatedGravity;
            RTQuaternion fusedConjugate;
            RTQuaternion qTemp;
            RTVector3    residuals;

            //  do gravity rotation and subtraction

            // create the conjugate of the pose

            fusedConjugate = mFusionQPose.Conjugate();

            // now do the rotation - takes two steps with qTemp as the intermediate variable

            qTemp          = mGravity * mFusionQPose;
            rotatedGravity = fusedConjugate * qTemp;

            // now adjust the measured accel and change the signs to make sense

            residuals = new RTVector3(-(mAccel.X - rotatedGravity.X), -(mAccel.Y - rotatedGravity.Y), -(mAccel.Z - rotatedGravity.Z));
            return(residuals);
        }
예제 #4
0
        public static RTVector3 PoseFromAccelMag(RTVector3 accel, RTVector3 mag)
        {
            RTVector3    result;
            RTQuaternion m;
            RTQuaternion q;

            accel.AccelToEuler(out result);

            //  q.fromEuler(result);
            //  since result.z() is always 0, this can be optimized a little

            double cosX2 = Math.Cos(result.X / 2.0f);
            double sinX2 = Math.Sin(result.X / 2.0f);
            double cosY2 = Math.Cos(result.Y / 2.0f);
            double sinY2 = Math.Sin(result.Y / 2.0f);

            q = new RTQuaternion(cosX2 * cosY2, sinX2 * cosY2, cosX2 * sinY2, -sinX2 * sinY2);
            m = new RTQuaternion(0, mag.X, mag.Y, mag.Z);

            m        = q * m * q.Conjugate();
            result.Z = -Math.Atan2(m.Y, m.X);
            return(result);
        }
예제 #5
0
        public static RTVector3 PoseFromAccelMag(RTVector3 accel, RTVector3 mag)
        {
            RTVector3 result;
            RTQuaternion m;
            RTQuaternion q;

            accel.AccelToEuler(out result);

            //  q.fromEuler(result);
            //  since result.z() is always 0, this can be optimized a little

            double cosX2 = Math.Cos(result.X / 2.0f);
            double sinX2 = Math.Sin(result.X / 2.0f);
            double cosY2 = Math.Cos(result.Y / 2.0f);
            double sinY2 = Math.Sin(result.Y / 2.0f);

            q = new RTQuaternion(cosX2 * cosY2, sinX2 * cosY2, cosX2 * sinY2, -sinX2 * sinY2);
            m = new RTQuaternion(0, mag.X, mag.Y, mag.Z);

            m = q * m * q.Conjugate();
            result.Z = -Math.Atan2(m.Y, m.X);
            return result;
        }