예제 #1
0
 ComputeDiagonalSingularValues()
 {
     return(Matrix.Diagonal(_singular));
 }
        private void UpdateTimeVaryingMatrices(TimeSpan timeDelta)
        {
            double dt = timeDelta.TotalSeconds;

            double posByV = dt;            // p=vt
            double posByA = 0.5 * dt * dt; // p=0.5at^2
            double velByA = dt;            // v=at

            // World state transition matrix.
            // Update position and velocity from previous state.
            // Previous state acceleration is neglected since current acceleration only depends on current input.
            A = Matrix.Create(new double[n, n]
            {
                // Px Py Pz Vx Vy Vz Qx Qy Qz Qw
                { 1, 0, 0, posByV, 0, 0, 0, 0, 0, 0 },                // Px
                { 0, 1, 0, 0, posByV, 0, 0, 0, 0, 0 },                // Py
                { 0, 0, 1, 0, 0, posByV, 0, 0, 0, 0 },                // Pz
                { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },                     // Vx
                { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },                     // Vy
                { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },                     // Vz

                // We don't handle transition of quaternions here due to difficulties. Using B instead.
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },                     // Quaternion X
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },                     // Quaternion Y
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },                     // Quaternion Z
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },                     // Quaternion W
            });
            AT = Matrix.Transpose(A);


            // Input gain matrix.
            // Acceleration forward/right/down
            // Angular Rate Roll/Pitch/Heading
            B = Matrix.Create(new double[n, p]
            {
                // Ax Ay Az Qx Qy Qz Qw
                { posByA, 0, 0, 0, 0, 0, 0 },                     // Px
                { 0, posByA, 0, 0, 0, 0, 0 },                     // Py
                { 0, 0, posByA, 0, 0, 0, 0 },                     // Pz
                { velByA, 0, 0, 0, 0, 0, 0 },                     // Vx
                { 0, velByA, 0, 0, 0, 0, 0 },                     // Vy
                { 0, 0, velByA, 0, 0, 0, 0 },                     // Vz

                // Simply set new orientation directly by quaternion input
                { 0, 0, 0, 1, 0, 0, 0 },                     // Quaternion X
                { 0, 0, 0, 0, 1, 0, 0 },                     // Quaternion Y
                { 0, 0, 0, 0, 0, 1, 0 },                     // Quaternion Z
                { 0, 0, 0, 0, 0, 0, 1 },                     // Quaternion W
            });


            // TODO For simplicity we assume all acceleromter axes have identical standard deviations (although they don't)
            float accelStdDev    = _sensorSpecifications.AccelerometerStdDev.Forward;
            float velocityStdDev = ((float)velByA) * accelStdDev;
            float positionStdDev = ((float)posByA) * accelStdDev;

            // Diagonal matrix with noise std dev
            Q = Matrix.Diagonal(new Vector(new double[n]
            {
                positionStdDev, positionStdDev, positionStdDev,
                velocityStdDev, velocityStdDev, velocityStdDev,
                0, 0, 0, 0                                      // TODO Orientation has no noise, should be added later
            }));

            R  = Matrix.Diagonal(_stdDevV); // Diagonal matrix with noise std dev
            Q *= Matrix.Transpose(Q);       // Convert standard deviations to variances
            R *= Matrix.Transpose(R);       // Convert standard deviations to variances

            w = GetNoiseMatrix(_stdDevW, n);
            v = GetNoiseMatrix(_stdDevV, m);
        }