示例#1
0
        /// Fits a polynomial of the given degree to the data points.
        public PolynomialFit solve(int degree)
        {
            if (degree > x.Count)
            {
                // Not enough data to fit a curve.
                return(null);
            }

            PolynomialFit result = new PolynomialFit(degree);

            // Shorthands for the purpose of notation equivalence to original C++ code.
            int m = x.Count;
            int n = degree + 1;

            // Expand the X vector to a matrix A, pre-multiplied by the weights.
            _Matrix a = new _Matrix(n, m);

            for (int h = 0; h < m; h += 1)
            {
                a[0, h] = w[h];
                for (int i = 1; i < n; i += 1)
                {
                    a[i, h] = a[i - 1, h] * x[h];
                }
            }

            // Apply the Gram-Schmidt process to A to obtain its QR decomposition.

            // Orthonormal basis, column-major ordVectorer.
            _Matrix q = new _Matrix(n, m);
            // Upper triangular matrix, row-major order.
            _Matrix r = new _Matrix(n, n);

            for (int j = 0; j < n; j += 1)
            {
                for (int h = 0; h < m; h += 1)
                {
                    q[j, h] = a[j, h];
                }

                for (int i = 0; i < j; i += 1)
                {
                    float dot = q.getRow(j) * q.getRow(i);
                    for (int h = 0; h < m; h += 1)
                    {
                        q[j, h] = q[j, h] - dot * q[i, h];
                    }
                }

                float norm = q.getRow(j).norm();
                if (norm < 0.000001f)
                {
                    // Vectors are linearly dependent or zero so no solution.
                    return(null);
                }

                float inverseNorm = 1.0f / norm;
                for (int h = 0; h < m; h += 1)
                {
                    q[j, h] = q[j, h] * inverseNorm;
                }

                for (int i = 0; i < n; i += 1)
                {
                    r[j, i] = i < j ? 0.0f : q.getRow(j) * a.getRow(i);
                }
            }

            // Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
            // We just work from bottom-right to top-left calculating B's coefficients.
            _Vector wy = new _Vector(m);

            for (int h = 0; h < m; h += 1)
            {
                wy[h] = y[h] * w[h];
            }

            for (int i = n - 1; i >= 0; i -= 1)
            {
                result.coefficients[i] = q.getRow(i) * wy;
                for (int j = n - 1; j > i; j -= 1)
                {
                    result.coefficients[i] -= r[i, j] * result.coefficients[j];
                }

                result.coefficients[i] /= r[i, i];
            }

            // Calculate the coefficient of determination (confidence) as:
            //   1 - (sumSquaredError / sumSquaredTotal)
            // ...where sumSquaredError is the residual sum of squares (variance of the
            // error), and sumSquaredTotal is the total sum of squares (variance of the
            // data) where each has been weighted.
            float yMean = 0.0f;

            for (int h = 0; h < m; h += 1)
            {
                yMean += y[h];
            }

            yMean /= m;

            float sumSquaredError = 0.0f;
            float sumSquaredTotal = 0.0f;

            for (int h = 0; h < m; h += 1)
            {
                float term = 1.0f;
                float err  = y[h] - result.coefficients[0];
                for (int i = 1; i < n; i += 1)
                {
                    term *= x[h];
                    err  -= term * result.coefficients[i];
                }

                sumSquaredError += w[h] * w[h] * err * err;
                float v = y[h] - yMean;
                sumSquaredTotal += w[h] * w[h] * v * v;
            }

            result.confidence = sumSquaredTotal <= 0.000001f ? 1.0f : 1.0f - (sumSquaredError / sumSquaredTotal);
            return(result);
        }
示例#2
0
        public VelocityEstimate getVelocityEstimate()
        {
            List <float> x           = new List <float>();
            List <float> y           = new List <float>();
            List <float> w           = new List <float>();
            List <float> time        = new List <float>();
            int          sampleCount = 0;
            int          index       = _index;

            _PointAtTime newestSample = _samples[index];

            if (newestSample == null)
            {
                return(null);
            }

            _PointAtTime previousSample = newestSample;
            _PointAtTime oldestSample   = newestSample;

            do
            {
                _PointAtTime sample = _samples[index];
                if (sample == null)
                {
                    break;
                }

                float age   = (float)(newestSample.time - sample.time).TotalMilliseconds;
                float delta = Mathf.Abs((float)(sample.time - previousSample.time).TotalMilliseconds);
                previousSample = sample;
                if (age > _horizonMilliseconds ||
                    delta > _assumePointerMoveStoppedMilliseconds)
                {
                    break;
                }

                oldestSample = sample;
                Offset position = sample.point;
                x.Add(position.dx);
                y.Add(position.dy);
                w.Add(1.0f);
                time.Add(-age);
                index = (index == 0 ? _historySize : index) - 1;

                sampleCount += 1;
            } while (sampleCount < _historySize);

            if (sampleCount >= _minSampleSize)
            {
                LeastSquaresSolver xSolver = new LeastSquaresSolver(time, x, w);
                PolynomialFit      xFit    = xSolver.solve(2);
                if (xFit != null)
                {
                    LeastSquaresSolver ySolver = new LeastSquaresSolver(time, y, w);
                    PolynomialFit      yFit    = ySolver.solve(2);
                    if (yFit != null)
                    {
                        return(new VelocityEstimate(
                                   pixelsPerSecond: new Offset(xFit.coefficients[1] * 1000, yFit.coefficients[1] * 1000),
                                   confidence: xFit.confidence *yFit.confidence,
                                   duration: newestSample.time - oldestSample.time,
                                   offset: newestSample.point - oldestSample.point
                                   ));
                    }
                }
            }

            return(new VelocityEstimate(
                       pixelsPerSecond: Offset.zero,
                       confidence: 1.0f,
                       duration: newestSample.time - oldestSample.time,
                       offset: newestSample.point - oldestSample.point
                       ));
        }