コード例 #1
0
        private void magObservationFunctionForNumericalJacobian(Matrix3x3d so3SensorFromWorldPred, Vector3d result)
        {
            Matrix3x3d.mult(so3SensorFromWorldPred, north, mh);
            So3Util.sO3FromTwoVec(mh, mz, magObservationFunctionForNumericalJacobianTempM);

            So3Util.muFromSO3(magObservationFunctionForNumericalJacobianTempM, result);
        }
コード例 #2
0
ファイル: So3Util.cs プロジェクト: secile/CardboardXamarin
        public static void sO3FromMu(Vector3d w, Matrix3x3d result)
        {
            double thetaSq = Vector3d.dot(w, w);
            double theta = Math.Sqrt(thetaSq);
            double kA, kB;

            if (thetaSq < 1.0E-08D)
            {
                kA = 1.0D - 0.16666667163372D * thetaSq;
                kB = 0.5D;
            }
            else
            {
                if (thetaSq < 1.0E-06D)
                {
                    kB = 0.5D - 0.0416666679084301D * thetaSq;
                    kA = 1.0D - thetaSq * 0.16666667163372D * (1.0D - 0.16666667163372D * thetaSq);
                }
                else
                {
                    double invTheta = 1.0D / theta;
                    kA = Math.Sin(theta) * invTheta;
                    kB = (1.0D - Math.Cos(theta)) * (invTheta * invTheta);
                }
            }
            rodriguesSo3Exp(w, kA, kB, result);
        }
コード例 #3
0
ファイル: So3Util.cs プロジェクト: secile/CardboardXamarin
        private static void rodriguesSo3Exp(Vector3d w, double kA, double kB, Matrix3x3d result)
        {
            double wx2 = w.x * w.x;
            double wy2 = w.y * w.y;
            double wz2 = w.z * w.z;

            result.set(0, 0, 1.0D - kB * (wy2 + wz2));
            result.set(1, 1, 1.0D - kB * (wx2 + wz2));
            result.set(2, 2, 1.0D - kB * (wx2 + wy2));

            double a, b;

            a = kA * w.z;
            b = kB * (w.x * w.y);
            result.set(0, 1, b - a);
            result.set(1, 0, b + a);

            a = kA * w.y;
            b = kB * (w.x * w.z);
            result.set(0, 2, b + a);
            result.set(2, 0, b - a);

            a = kA * w.x;
            b = kB * (w.y * w.z);
            result.set(1, 2, b - a);
            result.set(2, 1, b + a);
        }
コード例 #4
0
        public /*synchronized*/ void processGyro(float[] gyro, long sensorTimeStamp)
        {
            float kTimeThreshold = 0.04F;
            float kdTdefault     = 0.01F;

            if (sensorTimeStampGyro != 0L)
            {
                float dT = (float)(sensorTimeStamp - sensorTimeStampGyro) * 1.0E-09F;
                if (dT > kTimeThreshold)
                {
                    dT = gyroFilterValid ? filteredGyroTimestep : kdTdefault;
                }
                else
                {
                    filterGyroTimestep(dT);
                }

                mu.set(gyro[0] * -dT, gyro[1] * -dT, gyro[2] * -dT);
                So3Util.sO3FromMu(mu, so3LastMotion);

                processGyroTempM1.set(so3SensorFromWorld);
                Matrix3x3d.mult(so3LastMotion, so3SensorFromWorld, processGyroTempM1);
                so3SensorFromWorld.set(processGyroTempM1);

                updateCovariancesAfterMotion();

                processGyroTempM2.set(mQ);
                processGyroTempM2.scale(dT * dT);
                mP.plusEquals(processGyroTempM2);
            }
            sensorTimeStampGyro = sensorTimeStamp;
            lastGyro[0]         = gyro[0];
            lastGyro[1]         = gyro[1];
            lastGyro[2]         = gyro[2];
        }
コード例 #5
0
 public static void arrayAssign(double[][] data, Matrix3x3d m)
 {
     //assert(3 == data.length);
     //assert(3 == data[0].length);
     //assert(3 == data[1].length);
     //assert(3 == data[2].length);
     m.set(data[0][0], data[0][1], data[0][2], data[1][0], data[1][1], data[1][2], data[2][0], data[2][1], data[2][2]);
 }
コード例 #6
0
        private void updateCovariancesAfterMotion()
        {
            so3LastMotion.transpose(updateCovariancesAfterMotionTempM1);
            Matrix3x3d.mult(mP, updateCovariancesAfterMotionTempM1, updateCovariancesAfterMotionTempM2);

            Matrix3x3d.mult(so3LastMotion, updateCovariancesAfterMotionTempM2, mP);
            so3LastMotion.setIdentity();
        }
コード例 #7
0
        public /*synchronized*/ void processAcc(float[] acc, long sensorTimeStamp)
        {
            mz.set(acc[0], acc[1], acc[2]);

            if (sensorTimeStampAcc != 0L)
            {
                accObservationFunctionForNumericalJacobian(so3SensorFromWorld, mNu);

                double eps = 1.0E-07D;
                for (int dof = 0; dof < 3; dof++)
                {
                    Vector3d delta = processAccVDelta;
                    delta.setZero();
                    delta.setComponent(dof, eps);

                    So3Util.sO3FromMu(delta, processAccTempM1);
                    Matrix3x3d.mult(processAccTempM1, so3SensorFromWorld, processAccTempM2);

                    accObservationFunctionForNumericalJacobian(processAccTempM2, processAccTempV1);

                    Vector3d withDelta = processAccTempV1;

                    Vector3d.sub(mNu, withDelta, processAccTempV2);
                    processAccTempV2.scale(1.0D / eps);
                    mH.setColumn(dof, processAccTempV2);
                }

                mH.transpose(processAccTempM3);
                Matrix3x3d.mult(mP, processAccTempM3, processAccTempM4);
                Matrix3x3d.mult(mH, processAccTempM4, processAccTempM5);
                Matrix3x3d.add(processAccTempM5, mRaccel, mS);

                mS.invert(processAccTempM3);
                mH.transpose(processAccTempM4);
                Matrix3x3d.mult(processAccTempM4, processAccTempM3, processAccTempM5);
                Matrix3x3d.mult(mP, processAccTempM5, mK);

                Matrix3x3d.mult(mK, mNu, mx);

                Matrix3x3d.mult(mK, mH, processAccTempM3);
                processAccTempM4.setIdentity();
                processAccTempM4.minusEquals(processAccTempM3);
                Matrix3x3d.mult(processAccTempM4, mP, processAccTempM3);
                mP.set(processAccTempM3);

                So3Util.sO3FromMu(mx, so3LastMotion);

                Matrix3x3d.mult(so3LastMotion, so3SensorFromWorld, so3SensorFromWorld);

                updateCovariancesAfterMotion();
            }
            else
            {
                So3Util.sO3FromTwoVec(down, mz, so3SensorFromWorld);
            }
            sensorTimeStampAcc = sensorTimeStamp;
        }
コード例 #8
0
ファイル: So3Util.cs プロジェクト: secile/CardboardXamarin
        private static void rotationPiAboutAxis(Vector3d v, Matrix3x3d result)
        {
            rotationPiAboutAxisTemp.set(v);
            rotationPiAboutAxisTemp.scale(3.141592653589793D / rotationPiAboutAxisTemp.length());
            double invTheta = 0.3183098861837907D;

            double kA = 0.0D;

            double kB = 0.2026423672846756D;

            rodriguesSo3Exp(rotationPiAboutAxisTemp, kA, kB, result);
        }
コード例 #9
0
        public /*synchronized*/ void setHeadingDegrees(double heading)
        {
            double currentHeading = getHeadingDegrees();
            double deltaHeading   = heading - currentHeading;
            double s = Math.Sin(deltaHeading / 180.0D * 3.141592653589793D);
            double c = Math.Cos(deltaHeading / 180.0D * 3.141592653589793D);

            double[][] deltaHeadingRotationVals = new double[][] { new[] { c, -s, 0.0D }, new[] { s, c, 0.0D }, new[] { 0.0D, 0.0D, 1.0D } };

            arrayAssign(deltaHeadingRotationVals, setHeadingDegreesTempM1);
            Matrix3x3d.mult(so3SensorFromWorld, setHeadingDegreesTempM1, so3SensorFromWorld);
        }
コード例 #10
0
ファイル: So3Util.cs プロジェクト: secile/CardboardXamarin
        public static void muFromSO3(Matrix3x3d so3, Vector3d result)
        {
            double cosAngle = (so3.get(0, 0) + so3.get(1, 1) + so3.get(2, 2) - 1.0D) * 0.5D;

            result.set((so3.get(2, 1) - so3.get(1, 2)) / 2.0D, (so3.get(0, 2) - so3.get(2, 0)) / 2.0D, (so3.get(1, 0) - so3.get(0, 1)) / 2.0D);

            double sinAngleAbs = result.length();

            if (cosAngle > M_SQRT1_2)
            {
                if (sinAngleAbs > 0.0D)
                {
                    result.scale(Math.Asin(sinAngleAbs) / sinAngleAbs);
                }
            }
            else if (cosAngle > -M_SQRT1_2)
            {
                double angle = Math.Acos(cosAngle);
                result.scale(angle / sinAngleAbs);
            }
            else
            {
                double angle = 3.141592653589793D - Math.Asin(sinAngleAbs);
                double d0    = so3.get(0, 0) - cosAngle;
                double d1    = so3.get(1, 1) - cosAngle;
                double d2    = so3.get(2, 2) - cosAngle;

                Vector3d r2 = muFromSO3R2;
                if ((d0 * d0 > d1 * d1) && (d0 * d0 > d2 * d2))
                {
                    r2.set(d0, (so3.get(1, 0) + so3.get(0, 1)) / 2.0D, (so3.get(0, 2) + so3.get(2, 0)) / 2.0D);
                }
                else if (d1 * d1 > d2 * d2)
                {
                    r2.set((so3.get(1, 0) + so3.get(0, 1)) / 2.0D, d1, (so3.get(2, 1) + so3.get(1, 2)) / 2.0D);
                }
                else
                {
                    r2.set((so3.get(0, 2) + so3.get(2, 0)) / 2.0D, (so3.get(2, 1) + so3.get(1, 2)) / 2.0D, d2);
                }

                if (Vector3d.dot(r2, result) < 0.0D)
                {
                    r2.scale(-1.0D);
                }
                r2.normalize();
                r2.scale(angle);
                result.set(r2);
            }
        }
コード例 #11
0
        private double[] glMatrixFromSo3(Matrix3x3d so3)
        {
            for (int r = 0; r < 3; r++)
            {
                for (int c = 0; c < 3; c++)
                {
                    rotationMatrix[(4 * c + r)] = so3.get(r, c);
                }
            }
            double tmp62_61 = (rotationMatrix[11] = 0.0D); rotationMatrix[7] = tmp62_61; rotationMatrix[3] = tmp62_61;
            double tmp86_85 = (rotationMatrix[14] = 0.0D); rotationMatrix[13] = tmp86_85; rotationMatrix[12] = tmp86_85;

            rotationMatrix[15] = 1.0D;

            return(rotationMatrix);
        }
コード例 #12
0
        public double[] getPredictedGLMatrix(double secondsAfterLastGyroEvent)
        {
            double   dT  = secondsAfterLastGyroEvent;
            Vector3d pmu = getPredictedGLMatrixTempV1;

            pmu.set(lastGyro[0] * -dT, lastGyro[1] * -dT, lastGyro[2] * -dT);
            Matrix3x3d so3PredictedMotion = getPredictedGLMatrixTempM1;

            So3Util.sO3FromMu(pmu, so3PredictedMotion);

            Matrix3x3d so3PredictedState = getPredictedGLMatrixTempM2;

            Matrix3x3d.mult(so3PredictedMotion, so3SensorFromWorld, so3PredictedState);

            return(glMatrixFromSo3(so3PredictedState));
        }
コード例 #13
0
ファイル: So3Util.cs プロジェクト: secile/CardboardXamarin
        public static void sO3FromTwoVec(Vector3d a, Vector3d b, Matrix3x3d result)
        {
            Vector3d.cross(a, b, sO3FromTwoVecN);
            if (sO3FromTwoVecN.length() == 0.0D)
            {
                double dot = Vector3d.dot(a, b);
                if (dot >= 0.0D)
                {
                    result.setIdentity();
                }
                else
                {
                    Vector3d.ortho(a, sO3FromTwoVecRotationAxis);
                    rotationPiAboutAxis(sO3FromTwoVecRotationAxis, result);
                }
                return;
            }

            sO3FromTwoVecA.set(a);
            sO3FromTwoVecB.set(b);

            sO3FromTwoVecN.normalize();
            sO3FromTwoVecA.normalize();
            sO3FromTwoVecB.normalize();

            Matrix3x3d r1 = sO3FromTwoVec33R1;

            r1.setColumn(0, sO3FromTwoVecA);
            r1.setColumn(1, sO3FromTwoVecN);
            Vector3d.cross(sO3FromTwoVecN, sO3FromTwoVecA, temp31);
            r1.setColumn(2, temp31);

            Matrix3x3d r2 = sO3FromTwoVec33R2;

            r2.setColumn(0, sO3FromTwoVecB);
            r2.setColumn(1, sO3FromTwoVecN);
            Vector3d.cross(sO3FromTwoVecN, sO3FromTwoVecB, temp31);
            r2.setColumn(2, temp31);

            r1.transpose();
            Matrix3x3d.mult(r2, r1, result);
        }
コード例 #14
0
ファイル: So3Util.cs プロジェクト: secile/CardboardXamarin
 public static void generatorField(int i, Matrix3x3d pos, Matrix3x3d result)
 {
     result.set(i, 0, 0.0D);
     result.set((i + 1) % 3, 0, -pos.get((i + 2) % 3, 0));
     result.set((i + 2) % 3, 0, pos.get((i + 1) % 3, 0));
 }
コード例 #15
0
        public void processMag(float[] mag, long sensorTimeStamp)
        {
            mz.set(mag[0], mag[1], mag[2]);
            mz.normalize();

            Vector3d downInSensorFrame = new Vector3d();

            so3SensorFromWorld.getColumn(2, downInSensorFrame);

            Vector3d.cross(mz, downInSensorFrame, processMagTempV1);
            Vector3d perpToDownAndMag = processMagTempV1;

            perpToDownAndMag.normalize();

            Vector3d.cross(downInSensorFrame, perpToDownAndMag, processMagTempV2);
            Vector3d magHorizontal = processMagTempV2;

            magHorizontal.normalize();
            mz.set(magHorizontal);

            if (sensorTimeStampMag != 0L)
            {
                magObservationFunctionForNumericalJacobian(so3SensorFromWorld, mNu);

                double eps = 1.0E-07D;
                for (int dof = 0; dof < 3; dof++)
                {
                    Vector3d delta = processMagTempV3;
                    delta.setZero();
                    delta.setComponent(dof, eps);

                    So3Util.sO3FromMu(delta, processMagTempM1);
                    Matrix3x3d.mult(processMagTempM1, so3SensorFromWorld, processMagTempM2);

                    magObservationFunctionForNumericalJacobian(processMagTempM2, processMagTempV4);

                    Vector3d withDelta = processMagTempV4;

                    Vector3d.sub(mNu, withDelta, processMagTempV5);
                    processMagTempV5.scale(1.0D / eps);

                    mH.setColumn(dof, processMagTempV5);
                }

                mH.transpose(processMagTempM4);
                Matrix3x3d.mult(mP, processMagTempM4, processMagTempM5);
                Matrix3x3d.mult(mH, processMagTempM5, processMagTempM6);
                Matrix3x3d.add(processMagTempM6, mR, mS);

                mS.invert(processMagTempM4);
                mH.transpose(processMagTempM5);
                Matrix3x3d.mult(processMagTempM5, processMagTempM4, processMagTempM6);
                Matrix3x3d.mult(mP, processMagTempM6, mK);

                Matrix3x3d.mult(mK, mNu, mx);

                Matrix3x3d.mult(mK, mH, processMagTempM4);
                processMagTempM5.setIdentity();
                processMagTempM5.minusEquals(processMagTempM4);
                Matrix3x3d.mult(processMagTempM5, mP, processMagTempM4);
                mP.set(processMagTempM4);

                So3Util.sO3FromMu(mx, so3LastMotion);

                Matrix3x3d.mult(so3LastMotion, so3SensorFromWorld, processMagTempM4);
                so3SensorFromWorld.set(processMagTempM4);

                updateCovariancesAfterMotion();
            }
            else
            {
                magObservationFunctionForNumericalJacobian(so3SensorFromWorld, mNu);
                So3Util.sO3FromMu(mx, so3LastMotion);

                Matrix3x3d.mult(so3LastMotion, so3SensorFromWorld, processMagTempM4);
                so3SensorFromWorld.set(processMagTempM4);

                updateCovariancesAfterMotion();
            }
            sensorTimeStampMag = sensorTimeStamp;
        }