protected virtual Vector2[] ToLocal(Vector2[] points, Pose2D target)
        {
            TMatrix2D rotmx = target.ToGlobalMatrix();

            Vector2[] local = new Vector2[(points.Length - 1) + 1];
            int       len   = points.Length - 1;

            for (int i = 0; i <= len; i++)
            {
                local[i] = (Vector2)(rotmx * points[i]);
            }
            return(local);
        }
        protected virtual Vector2[] ToLocal(Vector2[] points, Pose2D target)
        {
            int i2;

            TMatrix2D rotmx = target.ToGlobalMatrix();

            Vector2[] local = new Vector2[checked (checked (checked ((int)points.Length) - 1) + 1)];
            int       i1    = checked (checked ((int)points.Length) - 1);
            int       i     = 0;

            while (i <= i2)
            {
                local[i] = rotmx * points[i];
                i        = checked (i + 1);
                i2       = i1;
            }
            return(local);
        }
        // Methods
        protected internal override MatchResult MatchPoints(Vector2[] points1, Vector2[] points2, Pose2D seed, double dangle, bool[] filter1, bool[] filter2)
        {
            int startTime = Environment.TickCount;

            Pose2D rawdpose = seed;
            Pose2D curdpose = rawdpose;

            Vector2[] curpoints2             = null;
            Correlation <Vector2>[] curpairs = null;
            Queue <double>          results  = new Queue <double>();
            int     nconverged = 0;
            Vector2 uavg       = new Vector2();
            double  sumerror   = 0.0;
            double  sumangcov  = 0.0;

            int n = 1;

            while (n <= base.MAX_ITERATIONS)
            {
                curpoints2 = this.ToLocal(points2, curdpose);

                curpairs = this.CorrelatePointsDM(points1, curpoints2, filter1, filter2);


                if (curpairs.Length > 0)
                {
                    Vector2 sumpoint1 = new Vector2();
                    Vector2 sumpoint2 = new Vector2();
                    foreach (Correlation <Vector2> pair in curpairs)
                    {
                        sumpoint1 += pair.Point1;
                        sumpoint2 += pair.Point2;
                    }
                    Vector2 u1 = sumpoint1 / curpairs.GetLength(0);
                    Vector2 u2 = sumpoint2 / curpairs.GetLength(0);
                    uavg      = (u1 + u2) / 2;
                    sumpoint1 = new Vector2();
                    sumpoint2 = new Vector2();
                    sumerror  = 0.0;
                    sumangcov = 0.0;
                    foreach (Correlation <Vector2> pair in curpairs)
                    {
                        Vector2 point1 = pair.Point1;
                        Vector2 point2 = pair.Point2;
                        sumpoint1 += new Vector2((point1[0] - u1[0]) * (point2[0] - u2[0]), (point1[1] - u1[1]) * (point2[1] - u2[1]));
                        sumpoint2 += new Vector2((point1[0] - u1[0]) * (point2[1] - u2[0]), (point1[1] - u1[1]) * (point2[0] - u2[1]));
                        Vector2 dpoint = point1 - point2;
                        Vector2 mpoint = (point1 + point2) / 2;
                        sumerror  += dpoint * dpoint;
                        sumangcov += mpoint * mpoint;
                    }
                    double    rotest   = System.Math.Atan2(sumpoint2[0] - sumpoint2[1], sumpoint1[0] + sumpoint1[1]);
                    TMatrix2D rotmx    = new TMatrix2D(rotest);
                    Vector2   transest = u2 - (rotmx * u1);
                    curdpose = new Pose2D(curdpose.Position - transest, curdpose.Rotation - rotest);
                    rotmx    = new TMatrix2D(-rotest);
                    curdpose = (Pose2D)(rotmx * curdpose);

                    bool converged = false;
                    foreach (double result in results)
                    {
                        if (sumerror == 0.0)
                        {
                            converged = converged || (result < base.RESULTS_MAXERROR);
                        }
                        else
                        {
                            converged = converged || (System.Math.Abs((double)((result / sumerror) - 1.0)) < base.RESULTS_MAXERROR);
                        }
                    }
                    results.Enqueue(sumerror);
                    while (results.Count > base.RESULTS_CONSIDERED)
                    {
                        results.Dequeue();
                    }
                    if (converged)
                    {
                        nconverged++;
                    }
                }
                if (nconverged >= base.RESULTS_CONVERGED)
                {
                    break;
                }
                n++;
            }

            Matrix3 mcov = new Matrix3();

            bool   inverseError = false;
            double mdist        = 0.0;
            int    num          = 0;

            if (curpairs.Length > 0)
            {
                foreach (Correlation <Vector2> pair in curpairs)
                {
                    Vector2 dpoint = pair.Point2 - pair.Point1;
                    mdist += System.Math.Pow(dpoint.X, 2.0) + System.Math.Pow(dpoint.Y, 2.0);
                }
                mdist = System.Math.Pow(mdist, 0.5);
                num   = curpairs.GetLength(0);

                MathNet.Numerics.LinearAlgebra.Matrix cov = new MathNet.Numerics.LinearAlgebra.Matrix(3, 3);
                cov[0, 0] = num;
                cov[0, 1] = 0.0;
                cov[0, 2] = -num * uavg[1];
                cov[1, 0] = 0.0;
                cov[1, 1] = num;
                cov[1, 2] = num * uavg[0];
                cov[2, 0] = -num * uavg[1];
                cov[2, 1] = num * uavg[0];
                cov[2, 2] = sumangcov;

                try
                {
                    cov = (sumerror / (2 * num - 3)) * cov.Inverse();
                }
                catch
                {
                    inverseError = true;
                }

                mcov[0, 0] = (float)cov[0, 0];
                mcov[0, 1] = (float)cov[0, 1];
                mcov[0, 2] = (float)cov[0, 2];
                mcov[1, 0] = (float)cov[1, 0];
                mcov[1, 1] = (float)cov[1, 1];
                mcov[1, 2] = (float)cov[1, 2];
                mcov[2, 0] = (float)cov[2, 0];
                mcov[2, 1] = (float)cov[2, 1];
                mcov[2, 2] = (float)cov[2, 2];
            }

            double duration = (Environment.TickCount - startTime) / 1000.0;

            return(new MatchResult(rawdpose, curdpose, n, duration, this.HasConverged(points1.Length, num, n) && !inverseError));
        }
Exemple #4
0
        protected internal override MatchResult MatchPoints(Vector2[] points1, Vector2[] points2, Pose2D seed, double dangle, bool[] filter1, bool[] filter2)
        {
            //Debug.DrawPoints(points1, 0);

            //Vector2[] pt2Local = this.ToLocal(points2, seed);
            //Debug.DrawPoints(pt2Local, 1);

            int startTime = Environment.TickCount;

            Matrix2 J  = new Matrix2(0, -1, 1, 0);
            Matrix2 Jt = J.Transpose();

            double[] iangles1 = this.ComputeIncidenceAngles(points1);
            double[] iangles2 = this.ComputeIncidenceAngles(points2);

            //covariance matrixes
            Matrix2[] ecovs1 = new Matrix2[points1.Length];
            Matrix2[] ecovs2 = new Matrix2[points2.Length];

            for (int i = 0; i < ecovs1.Length; i++)
            {
                ecovs1[i] = this.ComputeErrorCovariance(points1[i], iangles1[i], dangle);
            }

            Pose2D rawdpose = seed;
            Pose2D curdpose = rawdpose;

            Vector2[] curpoints2             = null;
            Correlation <Vector2>[] curpairs = null;

            //indexers, for fast access to covariance matrices
            int index = 0;

            int[] index1 = null;
            int[] index2 = null;

            Queue <double> results    = new Queue <double>();
            int            nconverged = 0;

            Matrix2 suminvsumcov = new Matrix2();
            Vector2 midpoint     = new Vector2();
            Matrix2 sumsumcov    = new Matrix2();
            Vector2 transest     = new Vector2();
            double  rotest       = 0;

            int n = 0;

            for (n = 1; n <= MAX_ITERATIONS; n++)
            {
                //recompute relative coords for range-scan 2 given the new dpose estimate
                curpoints2 = this.ToLocal(points2, curdpose);
                //Debug.DrawPoints(curpoints2, 2);

                //recompute covariances for curpoints2 (= covs2)
                for (int i = 0; i < ecovs2.Length; i++)
                {
                    ecovs2[i] = this.ComputeErrorCovariance(curpoints2[i], iangles2[i], dangle);
                }

                //find all correlated point-pairs
                Heap assoc = this.CorrelatePointsQT(points1, curpoints2, filter1, filter2);
                curpairs = getFilteredCorrespondances(assoc);
                //Debug.DrawPointRelations(curpairs);

                if (curpairs.Length > 0)
                {
                    //recompute indexes only once per iteration
                    index1 = new int[curpairs.Length];
                    index2 = new int[curpairs.Length];
                    index  = 0;

                    foreach (Correlation <Vector2> pair in curpairs)
                    {
                        index1[index] = Array.IndexOf(points1, pair.Point1);
                        index2[index] = Array.IndexOf(curpoints2, pair.Point2);
                        index++;
                    }

                    //these vars will hold summaries for a single iteration
                    Vector2 sumipoint1 = new Vector2();
                    Vector2 sumipoint2 = new Vector2();
                    Matrix2 sumirotmid = new Matrix2();
                    Vector2 sumrotmid  = new Vector2();
                    double  sumerror   = 0;
                    suminvsumcov = new Matrix2();

                    index = 0;
                    foreach (Correlation <Vector2> pair in curpairs)
                    {
                        //get corresponding points and error covariances ...
                        Vector2 point1 = pair.Point1;
                        Vector2 point2 = pair.Point2;
                        Matrix2 cov1   = ecovs1[index1[index]];
                        Matrix2 cov2   = ecovs2[index2[index]];

                        //translation estimate ...
                        Matrix2 sumcov    = cov1 + cov2;
                        Matrix2 invsumcov = sumcov.Invert();

                        suminvsumcov = suminvsumcov + invsumcov;
                        sumipoint1   = sumipoint1 + invsumcov * point1;
                        sumipoint2   = sumipoint2 + invsumcov * point2;

                        //error metric ...
                        Vector2 dpoint = point1 - point2;
                        sumerror = sumerror + (dpoint * invsumcov * dpoint);

                        //rotation estimate ...
                        Matrix2 irotmid = Jt * invsumcov * J;
                        sumirotmid = sumirotmid + 2 * irotmid;
                        sumrotmid  = sumrotmid + irotmid * point1 + irotmid * point2;

                        index++;
                    }

                    //get rotational midpoint and translation estimate
                    midpoint  = sumirotmid.Invert() * sumrotmid;
                    sumsumcov = suminvsumcov.Invert();
                    transest  = sumsumcov * (sumipoint2 - sumipoint1);



                    double sumnval = 0;
                    double sumdval = 0;

                    index = 0;
                    foreach (Correlation <Vector2> pair in curpairs)
                    {
                        //get corresponding points and error covariances ...
                        Vector2 point1 = pair.Point1;
                        Vector2 point2 = pair.Point2;
                        Matrix2 cov1   = ecovs1[index1[index]];
                        Matrix2 cov2   = ecovs2[index2[index]];

                        //apply estimated midpoint and translation
                        point1 = point1 - midpoint;
                        point2 = point2 - transest - midpoint;

                        Matrix2 sumcov    = cov1 + cov2;
                        Matrix2 invsumcov = sumcov.Invert();

                        //update numerator and denominator summaries
                        Vector2 dpoint = point2 - point1;
                        double  nval   = dpoint * invsumcov * J * point2;
                        double  dval   = dpoint * invsumcov * point2 + point2 * J * invsumcov * J * point2;

                        sumnval = sumnval + nval;
                        sumdval = sumdval + dval;

                        index++;
                    }

                    //get rotational estimate
                    rotest = -sumnval / sumdval;

                    //update odometry estimate
                    Vector2   vdpose = curdpose.Position - transest - midpoint;
                    TMatrix2D rotmx  = new TMatrix2D(-rotest);
                    vdpose   = rotmx * vdpose;
                    vdpose   = vdpose + midpoint;
                    curdpose = new Pose2D(vdpose, curdpose.Rotation - rotest);

                    //check for convergence
                    bool converged = false;
                    foreach (double result in results)
                    {
                        if (sumerror == 0)
                        {
                            converged = converged || (result < RESULTS_MAXERROR);
                        }
                        else
                        {
                            converged = converged || (System.Math.Abs(result / sumerror - 1) < RESULTS_MAXERROR);
                        }
                    }

                    results.Enqueue(sumerror);
                    while (results.Count > RESULTS_CONSIDERED)
                    {
                        results.Dequeue();
                    }

                    if (converged)
                    {
                        nconverged++;
                    }
                }

                if (nconverged >= RESULTS_CONVERGED)
                {
                    break;
                }
            }

            int    untilTime = Environment.TickCount;
            double duration  = (untilTime - startTime) / 1000.0;

            int num = (curpairs != null ? curpairs.Length : -1);

            return(new MatchResult(rawdpose, curdpose, n, duration, this.HasConverged(points1.Length, num, n)));
        }