예제 #1
0
        //---------------------------------------------------------

        /* Matlab version
         * %% forward substitution
         * %  use to find Z for L*Z = C, given L and C
         * function Z = ForwardSub(L,C)
         * Z = zeros(size(C));
         * for c=1:size(C,2)
         *  Z(1,c) = C(1,c)/L(1,1);
         *  for r=2:size(C,1)
         *     sum = 0;
         *     for j=1:(r-1)
         *         sum = sum + L(r,j)*Z(j,c);
         *     end
         *     Z(r,c) = (C(r,c)-sum)/L(r,r);
         *  end
         * end
         * end
         */
        /// <summary> added by Rahul Rastogi
        /// Forward Substitution function to find Z for L*Z = C, given L and C
        /// </summary>
        /// <param name="L">Lower Triangular Matrix, must be square</param>
        /// <param name="C">Matrix to divide into, must have same number of rows as L</param>
        public static UMatrix ForwardSub(UMatrix L, UMatrix C)
        {
            if (L.numCols != L.numRows || L.numRows != C.numRows)
            {
                throw new ArgumentException("Matrix dimensions are not valid.");
            }
            int rows = L.numCols;
            int cols = C.numCols;

            UMatrix Z = new UMatrix(rows, cols);

            fixed(double *ptrZ = Z.data, ptrL = L.data, ptrC = C.data)
            {
                for (int c = 0; c < C.numCols; c++)
                {
                    (*(ptrZ + c)) = (*(ptrC + c)) / (*(ptrL));
                    for (int r = 1; r < C.numRows; r++)
                    {
                        double sum = 0;
                        for (int j = 0; j <= (r - 1); j++)
                        {
                            sum += (*(ptrL + j + (L.numCols * r))) * (*(ptrZ + c + (Z.numCols * j)));
                        }
                        (*(ptrZ + c + (Z.numCols * r))) = (*(ptrC + c + (C.numCols * r)) - sum) / (*(ptrL + r + (L.numCols * r)));
                    }
                }
                return(Z);
            }
        }
예제 #2
0
        //-----------------------------------------------------------------

        /* Matlab version
         * %% backward substitution
         * % use to find X for U*X = Z, given U and Z
         * function X = BackSub(U,Z)
         * N = size(U,1);
         * X = zeros(N);
         * for c=1:size(Z,2)
         * X(N,c) = Z(N,c)/U(N,N);
         * for r=(N-1):-1:1
         *      sum = 0;
         *     for j=(r+1):N
         *        sum = sum + U(r,j)*X(j,c);
         *    end
         *    X(r,c) = (Z(r,c)-sum)/U(r,r);
         *  end
         * end
         * end
         */

        /// <summary> added by Rahul Rastogi
        /// Backward Substitution function to find X for U*X = Z, given U and Z
        /// </summary>
        /// <param name="U">Upper Triangular Matrix, must be square</param>
        /// <param name="Z">Matrix to divide into, must have same number of rows as U</param>
        public static UMatrix BackwardSub(UMatrix U, UMatrix Z)
        {
            if (U.numCols != U.numRows || U.numRows != Z.numRows)
            {
                throw new ArgumentException("Matrix dimensions are not valid.");
            }

            int     rows = U.numCols;
            int     cols = Z.numCols;
            int     n    = (U.numRows - 1);
            UMatrix X    = new UMatrix(rows, cols);

            fixed(double *ptrX = X.data, ptrU = U.data, ptrZ = Z.data)
            {
                for (int c = 0; c < Z.numCols; c++)
                {
                    (*(ptrX + c + (X.numCols * n))) = (*(ptrZ + c + (Z.numCols * n))) / (*(ptrU + n + (U.numCols * n)));
                    for (int r = (n - 1); r >= 0; r--)
                    {
                        double sum = 0;
                        for (int j = (r + 1); j <= n; j++)
                        {
                            sum += (*(ptrU + j + (U.numCols * r))) * (*(ptrX + c + (X.numCols * j)));
                        }
                        (*(ptrX + c + (X.numCols * r))) = (*(ptrZ + c + (Z.numCols * r)) - sum) / (*(ptrU + r + (U.numCols * r)));
                    }
                }
                return(X);
            }
        }
예제 #3
0
        /// <summary>Matrix-matrix multiplication.</summary>
        public static UMatrix Multiply(UMatrix left, UMatrix right)
        {
            if (right.numRows != left.numCols)
            {
                throw new ArgumentException("Matrix dimensions are not valid.");
            }

            int     rows    = left.numRows;
            int     columns = right.numCols;
            int     size    = left.numCols;
            UMatrix X       = new UMatrix(rows, columns);

            fixed(double *ptrX = X.data, ptrL = left.data, ptrR = right.data)
            {
                for (int rl = 0; rl < left.numRows; rl++)
                {
                    for (int cr = 0; cr < right.numCols; cr++)
                    {
                        double sum = 0;

                        for (int rr = 0; rr < right.numRows; rr++)
                        {
                            sum += (*(ptrL + rr + (left.numCols * rl))) * (*(ptrR + cr + (right.numCols * rr)));
                            //sum += left.data[rr + (left.numCols * rl)] * right.data[cr + (right.numCols * rr)];
                        }
                        //X.data[cr + (X.numCols * rl)] = sum;
                        (*(ptrX + cr + (X.numCols * rl))) = sum;
                    }
                }
            }

            //-----------------------------------------------------

            return(X);
        }
예제 #4
0
        /// <summary>Matrix subtraction.</summary>
        public static UMatrix Subtract(UMatrix left, UMatrix right)
        {
            int rows    = left.numRows;
            int columns = left.numCols;

            if ((rows != right.numRows) || (columns != right.numCols))
            {
                throw new ArgumentException("Matrix dimension do not match.");
            }

            UMatrix X = new UMatrix(rows, columns);

            fixed(double *ptrX = X.data, ptrL = left.data, ptrR = right.data)
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        //X.data[j + (columns * i)] = left.data[j + (columns * i)] - right.data[j + (columns * i)];
                        (*(ptrX + j + (columns * i))) = (*(ptrL + j + (columns * i))) - (*(ptrR + j + (columns * i)));
                    }
                }
            }

            return(X);
        }
예제 #5
0
        /// <summary>Unary minus.</summary>
        public static UMatrix Negate(UMatrix value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            int     rows    = value.numRows;
            int     columns = value.numCols;
            UMatrix X       = new UMatrix(rows, columns);

            fixed(double *ptrX = X.data, ptrThis = value.data)
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        //X.data[j + (columns * i)] = -value.data[j + (columns * i)];
                        (*(ptrX + j + (columns * i))) = -(*(ptrThis + j + (columns * i)));
                    }
                }
            }

            return(X);
        }
예제 #6
0
        public UMatrix Inverse()
        {
            UMatrix upper, lower, c, z;

            LuDecomposition(out lower, out upper);
            c = new UMatrix(numRows, numCols, 1);
            z = UMatrix.ForwardSub(lower, c);

            return(UMatrix.BackwardSub(upper, z));
        }
예제 #7
0
 public UMatrix(UMatrix m)
 {
     this.numRows = m.numRows;
     this.numCols = m.numCols;
     this.data    = new double[numRows * numCols];
     for (int i = 0; i < numRows; i++)
     {
         for (int j = 0; j < numCols; j++)
         {
             this[i, j] = m[i, j];
         }
     }
 }
예제 #8
0
 public UMatrix(UMatrix m)
 {
     this.numRows = m.numRows;
     this.numCols = m.numCols;
     this.data = new double[numRows * numCols];
     for (int i = 0; i < numRows; i++)
     {
         for (int j = 0; j < numCols; j++)
         {
             this[i, j] = m[i, j];
         }
     }
 }
예제 #9
0
        /// <summary>Returns the transposed matrix.</summary>
        public UMatrix Transpose()
        {
            UMatrix X = new UMatrix(numCols, numRows);

            fixed(double *ptrX = X.data, ptrThis = data)
            {
                for (int i = 0; i < numRows; i++)
                {
                    for (int j = 0; j < numCols; j++)
                    {
                        //X.data[i + (numRows * j)] = data[j + (numCols * i)];
                        (*(ptrX + i + (numRows * j))) = (*(ptrThis + j + (numCols * i)));
                    }
                }
            }

            return(X);
        }
예제 #10
0
        /// <summary>Matrix-scalar multiplication.</summary>
        public static UMatrix Multiply(UMatrix left, double right)
        {
            int rows    = left.numRows;
            int columns = left.numCols;

            UMatrix X = new UMatrix(rows, columns);

            fixed(double *ptrX = X.data, ptrL = left.data)
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        //X.data[j + (columns * i)] = left.data[j + (columns * i)] * right;
                        (*(ptrX + j + (columns * i))) = ((*(ptrL + j + (columns * i))) * right);
                    }
                }
            }

            return(X);
        }
예제 #11
0
        /// <summary>Returns a sub matrix extracted from the current matrix.</summary>
        /// <param name="startRow">Start row index</param>
        /// <param name="endRow">End row index</param>
        /// <param name="startColumn">Start column index</param>
        /// <param name="endColumn">End column index</param>
        public UMatrix Submatrix(int startRow, int endRow, int startColumn, int endColumn)
        {
            if ((startRow > endRow) || (startColumn > endColumn) || (startRow < 0) || (startRow >= this.numRows) || (endRow < 0) || (endRow >= this.numRows) || (startColumn < 0) || (startColumn >= this.numCols) || (endColumn < 0) || (endColumn >= this.numCols))
            {
                throw new ArgumentException("Argument out of range.");
            }

            UMatrix X = new UMatrix(endRow - startRow + 1, endColumn - startColumn + 1);

            fixed(double *ptrX = X.data, ptrThis = data)
            {
                for (int i = startRow; i <= endRow; i++)
                {
                    for (int j = startColumn; j <= endColumn; j++)
                    {
                        //X.data[j + (X.numCols * i)] = data[j + (numCols * i)];
                        (*(ptrX + j + (X.numCols * i))) = (*(ptrThis + j + (numCols * i)));
                    }
                }
            }

            return(X);
        }
예제 #12
0
        /// <summary>Matrix-matrix multiplication.</summary>
        public static UMatrix Multiply(UMatrix left, UMatrix right)
        {
            if (right.numRows != left.numCols)
            {
                throw new ArgumentException("Matrix dimensions are not valid.");
            }

            int rows = left.numRows;
            int columns = right.numCols;
            int size = left.numCols;
            UMatrix X = new UMatrix(rows, columns);

            fixed (double* ptrX = X.data, ptrL = left.data, ptrR = right.data)
            {
                for (int rl = 0; rl < left.numRows; rl++)
                {
                    for (int cr = 0; cr < right.numCols; cr++)
                    {
                        double sum = 0;

                        for (int rr = 0; rr < right.numRows; rr++)
                        {
                            sum += (*(ptrL + rr + (left.numCols * rl))) * (*(ptrR + cr + (right.numCols * rr)));
                            //sum += left.data[rr + (left.numCols * rl)] * right.data[cr + (right.numCols * rr)];
                        }
                        //X.data[cr + (X.numCols * rl)] = sum;
                        (*(ptrX + cr + (X.numCols * rl))) = sum;
                    }
                }
            }

            //-----------------------------------------------------

            return X;
        }
예제 #13
0
        UMatrix ComputeJacobianQ(double q1, double q2, double q3, double q4)
        {
            UMatrix toReturn = new UMatrix(16, 7);
            toReturn.Zero();

            toReturn[12, 0] = 1;
            toReturn[13, 1] = 1;
            toReturn[14, 2] = 1;

            toReturn[0, 3] = 2 * q1;
            toReturn[1, 3] = 2 * q2;
            toReturn[2, 3] = 2 * q3;
            toReturn[4, 3] = 2 * q2;
            toReturn[5, 3] = -2 * q1;
            toReturn[6, 3] = 2 * q4;
            toReturn[8, 3] = 2 * q3;
            toReturn[9, 3] = -2 * q4;
            toReturn[10, 3] = -2 * q1;

            toReturn[0, 4] = -2 * q2;
            toReturn[1, 4] = 2 * q1;
            toReturn[2, 4] = -2 * q4;
            toReturn[4, 4] = 2 * q1;
            toReturn[5, 4] = 2 * q2;
            toReturn[6, 4] = 2 * q3;
            toReturn[8, 4] = 2 * q4;
            toReturn[9, 4] = 2 * q3;
            toReturn[10, 4] = -2 * q2;

            toReturn[0, 5] = -2 * q3;
            toReturn[1, 5] = 2 * q4;
            toReturn[2, 5] = 2 * q1;
            toReturn[4, 5] = -2 * q4;
            toReturn[5, 5] = -2 * q3;
            toReturn[6, 5] = 2 * q2;
            toReturn[8, 5] = 2 * q1;
            toReturn[9, 5] = 2 * q2;
            toReturn[10, 5] = 2 * q3;

            toReturn[0, 6] = 2 * q4;
            toReturn[1, 6] = 2 * q3;
            toReturn[2, 6] = -2 * q2;
            toReturn[4, 6] = -2 * q3;
            toReturn[5, 6] = 2 * q4;
            toReturn[6, 6] = 2 * q1;
            toReturn[8, 6] = 2 * q2;
            toReturn[9, 6] = -2 * q1;
            toReturn[10, 6] = 2 * q4;

            return toReturn;
        }
예제 #14
0
        //---------------------------------------------------------
        /* Matlab version
        %% forward substitution
        %  use to find Z for L*Z = C, given L and C
        function Z = ForwardSub(L,C)
        Z = zeros(size(C));
        for c=1:size(C,2)
            Z(1,c) = C(1,c)/L(1,1);
            for r=2:size(C,1)
               sum = 0;
               for j=1:(r-1)
                   sum = sum + L(r,j)*Z(j,c);
               end
               Z(r,c) = (C(r,c)-sum)/L(r,r);
            end
        end
        end
        */
        /// <summary> added by Rahul Rastogi
        /// Forward Substitution function to find Z for L*Z = C, given L and C
        /// </summary>
        /// <param name="L">Lower Triangular Matrix, must be square</param>
        /// <param name="C">Matrix to divide into, must have same number of rows as L</param>
        public static UMatrix ForwardSub(UMatrix L, UMatrix C)
        {
            if (L.numCols != L.numRows || L.numRows != C.numRows)
            {
                throw new ArgumentException("Matrix dimensions are not valid.");
            }
            int rows = L.numCols;
            int cols = C.numCols;

            UMatrix Z = new UMatrix(rows, cols);
            fixed (double* ptrZ = Z.data, ptrL = L.data, ptrC = C.data)
            {
                for (int c = 0; c < C.numCols; c++)
                {
                    (*(ptrZ + c)) = (*(ptrC + c)) / (*(ptrL));
                    for (int r = 1; r < C.numRows; r++)
                    {
                        double sum = 0;
                        for (int j = 0; j <= (r - 1); j++)
                        {
                            sum += (*(ptrL + j + (L.numCols * r))) * (*(ptrZ + c + (Z.numCols * j)));
                        }
                        (*(ptrZ + c + (Z.numCols * r))) = (*(ptrC + c + (C.numCols * r)) - sum) / (*(ptrL + r + (L.numCols * r)));
                    }
                }
                return Z;
            }
        }
예제 #15
0
        /// <summary>Matrix-scalar multiplication.</summary>
        public static UMatrix Multiply(UMatrix left, double right)
        {
            int rows = left.numRows;
            int columns = left.numCols;

            UMatrix X = new UMatrix(rows, columns);
            fixed (double* ptrX = X.data, ptrL = left.data)
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        //X.data[j + (columns * i)] = left.data[j + (columns * i)] * right;
                        (*(ptrX + j + (columns * i))) = ((*(ptrL + j + (columns * i))) * right);
                    }
                }
            }
            return X;
        }
예제 #16
0
        public RobotTwoWheelCommand GetCommand()
        {
            double g = 3;
            double zeta = .7; //parameters for STC
            double dt = .4; // adjust to change speed
            double deltadist = .10; //incremental distance for looking ahead
            // deltadist/dt = nominal speed along path

            //get trajectory // this step is performed outside of this function by BehavioralDirector
            //discretize trajectory into [xr, yr]

            //generate reference velocities at each trajectory point [vr, wr, thetar] if new path
            if (!pathsame)
            {
                this.GenrefVWHuniformdt(pathCurrentlyTracked, deltadist, dt);
            }
            //use current timestamp to find corresponding index in reference vectors
            //double currenttime = TimeSync.CurrentTime;
            double currenttime = (DateTime.Now.Ticks - 621355968000000000) / 10000000.0;
            int indextotrack = (int) (Math.Ceiling((currenttime - timestamps[0]) / dt));
            if (indextotrack >= timestamps.Length)
                indextotrack = timestamps.Length - 1;
            Console.WriteLine("indextotrack = {0}", indextotrack);
            Console.WriteLine("time = {0}", currenttime);

            //unwrap thetar against thetarold, ignore if null (1337)
            if (!endpointsame) { thetarold = 1337; }
            if (thetarold != 1337)
            {
                while (hr[indextotrack] - thetarold >= Math.PI)
                {
                    hr[indextotrack] -= 2 * Math.PI; ;
                }
                while (hr[indextotrack] - thetarold <= -Math.PI)
                {
                    hr[indextotrack] += 2 * Math.PI;
                }
            }
            //set thetarold to thetar
            thetarold = hr[indextotrack];

            double[] qrefdata = { xr[indextotrack], yr[indextotrack], hr[indextotrack] };
            UMatrix qref = new UMatrix(3, 1, qrefdata);
            //print to qref to screen // use only for debugging
            //string qrefstring = qref.ToString();
            //Console.WriteLine("QREF\n {0}", qrefstring);

            //establish pose vector q = [x, y, theta];
            double x, y, theta;
            x = this.currentPoint.x;
            y = this.currentPoint.y;
            theta = this.currentPoint.yaw; // in radians
            double[] qdata = { x, y, theta };
            UMatrix q = new UMatrix(3, 1, qdata);

            //unwrap pose against qref
            while (q[2, 0] - qref[2, 0] >= Math.PI)
            {
                q[2, 0] -= 2 * Math.PI; ;
            }
            while (q[2, 0] - qref[2, 0] <= -Math.PI)
            {
                q[2, 0] += 2 * Math.PI;
            }

            //establish kinematic state error
            UMatrix delq = new UMatrix(3, 1);
            delq = qref - q;

            //if (!endpointsame) { delqthetarold = 1337; }
            //if (delqthetarold != 1337)
            //{
            //    while (delq[2,0] - delqthetarold >= Math.PI)
            //    {
            //        delq[2,0] -= 2 * Math.PI; ;
            //    }
            //    while (delq[2,0] - delqthetarold <= -Math.PI)
            //    {
            //        delq[2,0] += 2 * Math.PI;
            //    }
            //}
            ////set thetarold to thetar
            //delqthetarold = delq[2,0];

            //print delq to screen // use only for debugging
            string delqstring = delq.ToString();
            //Console.WriteLine("ERROR\n {0}", delqstring);
            //Console.ReadLine();

            //create rotation matrix
            double[] Rotdata = { Math.Cos(theta), Math.Sin(theta), 0, -Math.Sin(theta), Math.Cos(theta), 0, 0, 0, 1 };
            UMatrix Rot = new UMatrix(3, 3, Rotdata);

            //convert to robot frame
            UMatrix e = new UMatrix(3, 1);
            e = Rot * delq; //error in the robot reference frame: first element is along track error, second element is cross track error, last element is angle error
            string estring = e.ToString();
            Console.WriteLine("ERROR\n {0}", estring);

            // calculate Uf = [vf, wf]
            double vf = vr[indextotrack] * Math.Cos(e[2, 0]); // in meters/sec
            double wf = wr[indextotrack] * 180 / Math.PI; // in degrees/sec
            Console.WriteLine("vf = {0}, wf = {1}",vf,wf);

            //calculate wn = sqrt(wr^2 + g*vr^2)
            double wn = Math.Sqrt(Math.Pow(wr[indextotrack], 2) + g * (Math.Pow(vr[indextotrack], 2)));

            //calculte STC gain matrix
            double k1, k2, k3;
            k1 = 2 * zeta * wn;
            k3 = k1;
            k2 = g * vr[indextotrack];
            double[] Kdata = { k1, 0, 0, 0, k2, k3 };
            UMatrix K = new UMatrix(2, 3, Kdata);

            //find control values Ub = K*e
            UMatrix Ub = new UMatrix(2, 1);
            Ub = K * e;
            Console.WriteLine("vb = {0}, wb = {1}", Ub[0, 0], Ub[1, 0]);

            //find total control u = Uf + Ub
            double vcommand = (Ub[0, 0] + vf) * 3.6509; // multiply by 3.6509 to get "segway units"
            double wcommand = (Ub[1, 0] * 180 / Math.PI + wf) * 3.9; // convert to deg/sec and multiply by 3.9 for "segway units" (counts/deg/sec)

            RobotTwoWheelCommand command = new RobotTwoWheelCommand(vcommand * 2.23693629, wcommand);
            if (Math.Abs(wcommand) >= 600)
                Console.WriteLine("W saturation");

            //create text file of information
            if (indextotrack < timestamps.Length && counter < 15)
            {
                if (indextotrack == timestamps.Length - 1) { counter = counter + 1; }
                tw2.WriteLine("{0}  {1}  {2}  {3}  {4}  {5}  {6}  {7}  {8}  {9}  {10}  {11} ", indextotrack, timestamps[indextotrack], x, y, e[0, 0], e[1, 0], e[2, 0], vf, wf, Ub[0, 0], Ub[1, 0]);
            }
            else { tw2.Close(); }

            return command;
        }
예제 #17
0
        //-----------------------------------------------------------------
        /* Matlab version
        %% backward substitution
        % use to find X for U*X = Z, given U and Z
        function X = BackSub(U,Z)
        N = size(U,1);
        X = zeros(N);
        for c=1:size(Z,2)
           X(N,c) = Z(N,c)/U(N,N);
           for r=(N-1):-1:1
                sum = 0;
               for j=(r+1):N
                  sum = sum + U(r,j)*X(j,c);
              end
              X(r,c) = (Z(r,c)-sum)/U(r,r);
            end
        end
        end
        */
        /// <summary> added by Rahul Rastogi
        /// Backward Substitution function to find X for U*X = Z, given U and Z
        /// </summary>
        /// <param name="U">Upper Triangular Matrix, must be square</param>
        /// <param name="Z">Matrix to divide into, must have same number of rows as U</param>
        public static UMatrix BackwardSub(UMatrix U, UMatrix Z)
        {
            if (U.numCols != U.numRows || U.numRows != Z.numRows)
            {
                throw new ArgumentException("Matrix dimensions are not valid.");
            }

            int rows = U.numCols;
            int cols = Z.numCols;
            int n = (U.numRows-1);
            UMatrix X = new UMatrix(rows, cols);
            fixed (double* ptrX = X.data, ptrU = U.data, ptrZ = Z.data)
            {
                for (int c = 0; c < Z.numCols; c++)
                {
                    (*(ptrX + c + (X.numCols * n))) = (*(ptrZ + c + (Z.numCols * n))) / (*(ptrU + n + (U.numCols * n)));
                    for (int r = (n-1); r >= 0; r--)
                    {
                        double sum = 0;
                        for (int j = (r+1); j <= n; j++)
                        {
                            sum += (*(ptrU + j + (U.numCols * r))) * (*(ptrX + c + (X.numCols * j)));
                        }
                        (*(ptrX + c + (X.numCols * r))) = (*(ptrZ + c + (Z.numCols * r)) - sum) / (*(ptrU + r + (U.numCols * r)));
                    }
                }
                return X;
            }
        }
예제 #18
0
        private UMatrix ComputeJacobianZYX(double yaw, double pitch, double roll)
        {
            UMatrix m = new UMatrix(16, 6);
            m.Zero();

            m[12, 0] = 1;

            m[13, 1] = 1;

            m[14, 2] = 1;

            m[1, 3] = Math.Cos(roll) * Math.Sin(pitch) * Math.Cos(yaw) + Math.Sin(roll) * Math.Sin(yaw);
            m[2, 3] = -Math.Sin(roll) * Math.Sin(pitch) * Math.Cos(yaw) + Math.Cos(roll) * Math.Sin(yaw);
            m[5, 3] = Math.Cos(roll) * Math.Sin(pitch) * Math.Sin(yaw) - Math.Sin(roll) * Math.Cos(yaw);
            m[6, 3] = -Math.Sin(roll) * Math.Sin(pitch) * Math.Sin(yaw) - Math.Cos(roll) * Math.Cos(yaw);
            m[9, 3] = Math.Cos(roll) * Math.Cos(pitch);
            m[10, 3] = -Math.Sin(roll) * Math.Cos(pitch);

            m[0, 4] = -Math.Sin(pitch) * Math.Cos(yaw);
            m[1, 4] = Math.Sin(roll) * Math.Cos(pitch) * Math.Cos(yaw);
            m[2, 4] = Math.Cos(roll) * Math.Cos(pitch) * Math.Cos(yaw);
            m[4, 4] = -Math.Sin(pitch) * Math.Sin(yaw);
            m[5, 4] = Math.Sin(roll) * Math.Cos(pitch) * Math.Sin(yaw);
            m[6, 4] = Math.Cos(roll) * Math.Cos(pitch) * Math.Sin(yaw);
            m[8, 4] = -Math.Cos(pitch);
            m[9, 4] = -Math.Sin(roll) * Math.Sin(pitch);
            m[10, 4] = -Math.Cos(roll) * Math.Sin(pitch);

            m[0, 5] = -Math.Cos(pitch) * Math.Sin(yaw);
            m[1, 5] = -Math.Sin(roll) * Math.Sin(pitch) * Math.Sin(yaw) - Math.Cos(roll) * Math.Cos(yaw);
            m[2, 5] = -Math.Cos(roll) * Math.Sin(pitch) * Math.Sin(yaw) + Math.Sin(roll) * Math.Cos(yaw);
            m[4, 5] = Math.Cos(pitch) * Math.Cos(yaw);
            m[5, 5] = Math.Sin(roll) * Math.Sin(pitch) * Math.Cos(yaw) - Math.Cos(roll) * Math.Sin(yaw);
            m[6, 5] = Math.Cos(roll) * Math.Sin(pitch) * Math.Cos(yaw) + Math.Sin(roll) * Math.Sin(yaw);

            return m;
        }
예제 #19
0
        private void UpdateCovariance(Matrix robotCov)
        {
            lock (locker)
            {
                UMatrix abc = new UMatrix(6, 6);
                for (int i = 0; i < 6; i++)
                {
                    for (int j = 0; j < 6; j++)
                    {
                        abc[i, j] = robotCov[i, j]; // this is a heck !!!!!
                    }

                    if (abc[i, i] < 0)
                        abc[i, i] = Math.Abs(abc[i, i]);
                }
                if (abc[2, 2] == 0) abc[2, 2] = 0.01;
                if (abc[4, 4] == 0) abc[4, 4] = 0.01;
                if (abc[5, 5] == 0) abc[5, 5] = 0.01;
                covRobotPose = abc;
            }
        }
예제 #20
0
        //----------------------------------------------------------------------------

        public UMatrix LuDecomposition(out UMatrix l, out UMatrix u)
        {
            double[] lu = new double[data.Length];
            Array.Copy(data, lu, data.Length);

            //double[] luRowI;
            double *luRowIPtr;

            double[] luColJ = new double[numRows];
            double[] lData  = new double[numRows * numRows];
            double[] uData  = new double[numRows * numRows];

            fixed(double *luPtr = lu, luColJPtr = luColJ, lDataPtr = lData, uDataPtr = uData)
            {
                int pivotSign = 1;

                int[] pivotVector = new int[numRows];
                for (int i = 0; i < numRows; i++)
                {
                    pivotVector[i] = i;
                }

                // Outer loop.
                for (int j = 0; j < numCols; j++)
                {
                    // Make a copy of the j-th column to localize references.
                    for (int i = 0; i < numRows; i++)
                    {
                        *(luColJPtr + i) = *(luPtr + j + i * numCols);
                    }

                    // Apply previous transformations.
                    for (int i = 0; i < numRows; i++)
                    {
                        luRowIPtr = luPtr + i * numCols;

                        // Most of the time is spent in the following dot product.
                        //int kmax = (i > j) ? j : i;
                        int    kmax = Math.Min(i, j);
                        double s    = 0.0;
                        for (int k = 0; k < kmax; k++)
                        {
                            s += *(luRowIPtr + k) * *(luColJPtr + k);
                        }
                        *(luRowIPtr + j) = *(luColJPtr + i) -= s;
                    }

                    // Find pivot and exchange if necessary.
                    int p = j;
                    for (int i = j + 1; i < numRows; i++)
                    {
                        if (Math.Abs(*(luColJPtr + i)) > Math.Abs(*(luColJPtr + p)))
                        {
                            p = i;
                        }
                    }

                    if (p != j)
                    {
                        for (int k = 0; k < numCols; k++)
                        {
                            double t = *(luPtr + k + p * numCols);
                            *(luPtr + k + p * numCols) = *(luPtr + k + j * numCols);
                            *(luPtr + k + j * numCols) = t;
                        }

                        int v = pivotVector[p];
                        pivotVector[p] = pivotVector[j];
                        pivotVector[j] = v;

                        pivotSign = -pivotSign;
                    }

                    // Compute multipliers.
                    if (j < numRows & *(luPtr + j + j * numCols) != 0.0)
                    {
                        for (int i = j + 1; i < numRows; i++)
                        {
                            *(luPtr + j + i * numCols) /= *(luPtr + j + j * numCols);
                        }
                    }
                }



                for (int i = 0; i < numRows; i++)
                {
                    for (int j = 0; j < numCols; j++)
                    {
                        *(lDataPtr + j + i * numCols) = (j == i) ? 1 : (i < j) ? 0 : *(luPtr + j + i * numCols);
                        *(uDataPtr + j + i * numCols) = (i > j) ? 0 : *(luPtr + j + i * numCols);
                    }
                }

                l = new UMatrix(numRows, numCols, lData);
                u = new UMatrix(numRows, numCols, uData);
            }

            return(new UMatrix(numRows, numCols, lu));
        }
예제 #21
0
        /// <summary>
        /// Update OccupancyGrid based on lidarScan and robotPose received
        /// </summary>
        /// <param name="lidarScan"></param>
        /// <param name="currentRobotPose"></param>
        public void UpdateOccupancyGrid(ILidarScan<ILidar2DPoint> lidarScan, int robotID, RobotPose currentRobotPose, SensorPose lidarPose, List<Polygon> dynamicObstacles)
        {
            if (lidarPose == null)
            {
                lidarPose = new SensorPose(0, 0, 0.5, 0, 0 * Math.PI / 180.0, 0, 0);
            }
            if (laser2RobotTransMatrixDictionary.ContainsKey(robotID))
            {
                JTpl = jacobianLaserPoseDictionary[robotID];
                laserToRobotDCM = laser2RobotTransMatrixDictionary[robotID];
            }
            else
            {
                Matrix4 laser2RobotDCM = Matrix4.FromPose(lidarPose);
                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        laserToRobotDCM[i, j] = laser2RobotDCM[i, j];
                    }
                }
                laser2RobotTransMatrixDictionary.Add(robotID, laserToRobotDCM);
                jacobianLaserPoseDictionary.Add(robotID, ComputeJacobian(lidarPose.yaw, lidarPose.pitch, lidarPose.roll));
                JTpl = jacobianLaserPoseDictionary[robotID];
            }

            // calculate robot2global transformation matrix
            Matrix4 robot2GlocalDCM = Matrix4.FromPose(currentRobotPose);
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    robotToGlocalDCM[i, j] = robot2GlocalDCM[i, j];
                }
            }

            if (lidarScan == null) return;
            Stopwatch sw1 = new Stopwatch();
            Stopwatch sw2 = new Stopwatch();
            Stopwatch sw3 = new Stopwatch();
            Stopwatch sw4 = new Stopwatch();
            Stopwatch sw5 = new Stopwatch();
            Stopwatch sw6 = new Stopwatch();

            UMatrix JTpr = ComputeJacobian(currentRobotPose.yaw, currentRobotPose.pitch, currentRobotPose.roll);
            List<UMatrix> JfPrCubixLaserToRobotDCM = new List<UMatrix>(6);
            List<UMatrix> RobotToGlocalDCMJfPlCubix = new List<UMatrix>(6);
            for (int i = 0; i < 6; i++)
            {
                //derivative of the robot transform matrtix w.r.t. some element of the robot psoe
                UMatrix j = new UMatrix(4, 4);
                j[0, 0] = JTpr[0, i]; j[1, 0] = JTpr[1, i]; j[2, 0] = JTpr[2, i]; j[3, 0] = JTpr[3, i];
                j[0, 1] = JTpr[4, i]; j[1, 1] = JTpr[5, i]; j[2, 1] = JTpr[6, i]; j[3, 1] = JTpr[7, i];
                j[0, 2] = JTpr[8, i]; j[1, 2] = JTpr[9, i]; j[2, 2] = JTpr[10, i]; j[3, 2] = JTpr[11, i];
                j[0, 3] = JTpr[12, i]; j[1, 3] = JTpr[13, i]; j[2, 3] = JTpr[14, i]; j[3, 3] = JTpr[15, i];
                JfPrCubixLaserToRobotDCM.Add(j * laserToRobotDCM);

                UMatrix tempJacobianPl = new UMatrix(4, 4);
                tempJacobianPl[0, 0] = JTpl[0, i]; tempJacobianPl[1, 0] = JTpl[1, i]; tempJacobianPl[2, 0] = JTpl[2, i]; tempJacobianPl[3, 0] = JTpl[3, i];
                tempJacobianPl[0, 1] = JTpl[4, i]; tempJacobianPl[1, 1] = JTpl[5, i]; tempJacobianPl[2, 1] = JTpl[6, i]; tempJacobianPl[3, 1] = JTpl[7, i];
                tempJacobianPl[0, 2] = JTpl[8, i]; tempJacobianPl[1, 2] = JTpl[9, i]; tempJacobianPl[2, 2] = JTpl[10, i]; tempJacobianPl[3, 2] = JTpl[11, i];
                tempJacobianPl[0, 3] = JTpl[12, i]; tempJacobianPl[1, 3] = JTpl[13, i]; tempJacobianPl[2, 3] = JTpl[14, i]; tempJacobianPl[3, 3] = JTpl[15, i];
                RobotToGlocalDCMJfPlCubix.Add(robotToGlocalDCM * tempJacobianPl);
            }
            UMatrix laserToENU = robotToGlocalDCM * laserToRobotDCM;
            UMatrix pijCell = new UMatrix(rangeToApply * 2 + 1, rangeToApply * 2 + 1);
            // update covariance
            UpdateCovariance(currentRobotPose.covariance);

            //SickPoint p = new SickPoint(new RThetaCoordinate(1.0f, 0.0f));
            for (int laserIndex = 0; laserIndex < lidarScan.Points.Count; laserIndex++)
            {
                lock (locker)
                {

                    ILidar2DPoint p = lidarScan.Points[laserIndex];
                    if (p.RThetaPoint.R >= MAXRANGE) continue;

                    bool hitDynamicObstacles = false;
                    // figure out if this lidar point is hitting other robot

                    // find laser points in 3D space
                    // first define 2D point on the laser plane
                    UMatrix laserPoint = new UMatrix(4, 1);

                    double deg = (p.RThetaPoint.theta * 180.0 / Math.PI);
                    int thetaDegIndex = (int)Math.Round((deg + 90.0) * 2.0) % 360;
                    double cosTheta = cosLookup[thetaDegIndex];
                    double sinTheta = sinLookup[thetaDegIndex];

                    laserPoint[0, 0] = p.RThetaPoint.R * cosTheta;
                    laserPoint[1, 0] = p.RThetaPoint.R * sinTheta;
                    laserPoint[2, 0] = 0;
                    laserPoint[3, 0] = 1;

                    //calculate r_hat_ENU
                    UMatrix r_hat_ENU = laserToENU * laserPoint;

                    foreach (Polygon dp in dynamicObstacles)
                    {
                        if (dp.IsInside(new Vector2(r_hat_ENU[0, 0], r_hat_ENU[1, 0])))
                        {
                            hitDynamicObstacles = true;
                            break;
                        }
                    }
                    if (hitDynamicObstacles) continue;

                    //-------------------------------//
                    // COVARIANCE UMatrix CALCULATION //
                    //-------------------------------//
                    UMatrix JRr = new UMatrix(4, 2);
                    JRr.Zero();
                    JRr[0, 0] = cosTheta;
                    JRr[0, 1] = -p.RThetaPoint.R * sinTheta;
                    JRr[1, 0] = sinTheta;
                    JRr[1, 1] = p.RThetaPoint.R * cosTheta;

                    UMatrix Jfr = new UMatrix(3, 2); // 3x2
                    Jfr = (laserToENU * JRr).Submatrix(0, 2, 0, 1);	 // 4x4 * 4x4 * 4x2

                    UMatrix Jfpr = new UMatrix(3, 6);
                    UMatrix Jfpl = new UMatrix(3, 6);
                    sw1.Reset();
                    sw1.Start();

                    for (int i = 0; i < 6; i++) //for each state var (i.e. x,y,z,y,p,r)
                    {
                        UMatrix JfprTemp = (JfPrCubixLaserToRobotDCM[i]) * laserPoint; // 4 by 1 UMatrix
                        Jfpr[0, i] = JfprTemp[0, 0];
                        Jfpr[1, i] = JfprTemp[1, 0];
                        Jfpr[2, i] = JfprTemp[2, 0];

                        //UMatrix JfplTemp = (RobotToGlocalDCMJfPlCubix[i]) * laserPoint; // 4 by 1 UMatrix
                        //Jfpl[0, i] = JfplTemp[0, 0];
                        //Jfpl[1, i] = JfplTemp[1, 0];
                        //Jfpl[2, i] = JfplTemp[2, 0];
                    }
                    sw1.Stop();
                    sw2.Reset();
                    sw2.Start();
                    UMatrix JfprQprJfprT = new UMatrix(3, 3);
                    UMatrix JfplQplJfplT = new UMatrix(3, 3);
                    UMatrix JfrQrJfrT = new UMatrix(3, 3);
                    JfprQprJfprT = (Jfpr * covRobotPose) * Jfpr.Transpose();
                    //JfplQplJfplT = (Jfpl * covLaserPose) * Jfpl.Transpose();
                    JfrQrJfrT = (Jfr * covLaserScan) * Jfr.Transpose();

                    // add above variables together and get the covariance
                    UMatrix covRHatENU = JfprQprJfprT + /*JfplQplJfplT +*/ JfrQrJfrT; // 3x3 UMatrix
                    sw2.Stop();
                    sw3.Reset();
                    sw3.Start();
                    //-----------------------------//
                    // FIND WHICH CELLS TO COMPUTE //
                    //-----------------------------//

                    // find out cells around this laser point
                    int laserPointIndexX = 0;
                    int laserPointIndexY = 0;
                    //this is used just to do the transformation from reaal to grid and visa versa
                    psig_u_hat_square.GetIndicies(r_hat_ENU[0, 0], r_hat_ENU[1, 0], out laserPointIndexX, out laserPointIndexY); // get cell (r_hat_ENU_X, r_hat_ENU_y)
                    sw3.Stop();
                    sw4.Reset();
                    sw4.Start();
                    //-----------------------------------------//
                    // COMPUTE THE DISTRIBUTION OF UNCERTAINTY //
                    //-----------------------------------------//

                    double sigX = Math.Sqrt(covRHatENU[0, 0]);
                    double sigY = Math.Sqrt(covRHatENU[1, 1]);
                    double rho = covRHatENU[1, 0] / (sigX * sigY);
                    double logTerm = Math.Log(2 * Math.PI * sigX * sigY * Math.Sqrt(1 - (rho * rho)));
                    double xTermDenom = (1 - (rho * rho));
                    for (int i = -rangeToApply; i <= rangeToApply; i++) // column
                    {
                        for (int j = -rangeToApply; j <= rangeToApply; j++) // row
                        {
                            // estimate using Bivariate Normal Distribution
                            double posX = 0; double posY = 0;
                            psig_u_hat_square.GetReals(laserPointIndexX + i, laserPointIndexY + j, out posX, out posY);
                            posX += psig_u_hat_square.ResolutionX / 2;
                            posY += psig_u_hat_square.ResolutionY / 2;
                            double x = posX - r_hat_ENU[0, 0];
                            double y = posY - r_hat_ENU[1, 0];
                            double z = (x * x) / (sigX * sigX) -
                                                (2 * rho * x * y / (sigX * sigY)) +
                                                 (y * y) / (sigY * sigY);
                            double xTerm = -0.5 * z / xTermDenom;
                            // chi2 test
                            //if ((2 * (1 - (rho * rho))) * ((x * x) / (sigX * sigX) + (y * y) / (sigY * sigY) - (2 * rho * x * y) / (sigX * sigY)) > 15.2)
                            //  continue;
                            pijCell[j + rangeToApply, i + rangeToApply] = Math.Exp(xTerm - logTerm) * psig_u_hat_square.ResolutionX * psig_u_hat_square.ResolutionY;
                            laserHit.SetCellByIdx(laserPointIndexX + i, laserPointIndexY + j, laserHit.GetCellByIdx(laserPointIndexX + i, laserPointIndexY + j) + 1);
                        }
                    }
                    sw4.Stop();
                    sw5.Reset();
                    sw5.Start();

                    //---------------------------//
                    // COMPUTE HEIGHT ESTIMATION //
                    //---------------------------//
                    //				Matrix2 PEN = new Matrix2(covRHatENU[0, 0], covRHatENU[0, 1], covRHatENU[1, 0], covRHatENU[1, 1]);

                    UMatrix PEN = covRHatENU.Submatrix(0, 1, 0, 1);

                    UMatrix PENInv = PEN.Inverse2x2;

                    UMatrix PuEN = new UMatrix(1, 2);
                    UMatrix PENu = new UMatrix(2, 1);
                    UMatrix PuENPENInv = PuEN * PENInv;
                    UMatrix uHatMatrix = new UMatrix(rangeToApply * 2 + 1, rangeToApply * 2 + 1);
                    UMatrix sigUHatMatrix = new UMatrix(rangeToApply * 2 + 1, rangeToApply * 2 + 1);

                    PuEN[0, 0] = covRHatENU[2, 0];
                    PuEN[0, 1] = covRHatENU[2, 1];

                    PENu[0, 0] = covRHatENU[0, 2];
                    PENu[1, 0] = covRHatENU[1, 2];

                    double sig_u_hat_product = (PuENPENInv * PENu)[0, 0]; // output = 1x1 UMatrix

                    for (int i = -rangeToApply; i <= rangeToApply; i++) // column
                    {
                        for (int j = -rangeToApply; j <= rangeToApply; j++) // row
                        {
                            UMatrix ENmr_EN = new UMatrix(2, 1);
                            double posX = 0; double posY = 0;
                            psig_u_hat_square.GetReals(laserPointIndexX + i, laserPointIndexY + j, out posX, out posY);
                            ENmr_EN[0, 0] = posX - r_hat_ENU[0, 0];
                            ENmr_EN[1, 0] = posY - r_hat_ENU[1, 0];
                            double u_hat_product = (PuENPENInv * (ENmr_EN))[0, 0]; // output = 1x1 UMatrix
                            uHatMatrix[j + rangeToApply, i + rangeToApply] = r_hat_ENU[2, 0] + u_hat_product;
                            sigUHatMatrix[j + rangeToApply, i + rangeToApply] = covRHatENU[2, 2] - sig_u_hat_product;
                        }
                    }
                    sw5.Stop();
                    sw6.Reset();
                    sw6.Start();

                    //-------------------------------------------//
                    // ASSIGN FINAL VALUES TO THE OCCUPANCY GRID //
                    //-------------------------------------------//
                    for (int i = -rangeToApply; i <= rangeToApply; i++)
                    {
                        for (int j = -rangeToApply; j <= rangeToApply; j++)
                        {
                            int indexXToUpdate = laserPointIndexX + i;
                            int indexYToUpdate = laserPointIndexY + j;
                            // if the cell to update is out of range, continue
                            if (!psig_u_hat_square.CheckValidIdx(indexXToUpdate, indexYToUpdate))
                            {
                                //Console.WriteLine("Laser points out of the occupancy grid map");
                                continue;
                            }

                            pij_sum.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApply, i + rangeToApply] + pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            pu_hat.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApply, i + rangeToApply] * uHatMatrix[j + rangeToApply, i + rangeToApply] + pu_hat.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            pu_hat_square.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApply, i + rangeToApply] * uHatMatrix[j + rangeToApply, i + rangeToApply] * uHatMatrix[j + rangeToApply, i + rangeToApply] + pu_hat_square.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            psig_u_hat_square.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApply, i + rangeToApply] * sigUHatMatrix[j + rangeToApply, i + rangeToApply] + psig_u_hat_square.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            uhatGM.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                                            (pu_hat.GetCellByIdx(indexXToUpdate, indexYToUpdate) / pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate)));
                            normalisedPijSum.SetCellByIdx(indexXToUpdate, indexYToUpdate, pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate) / laserHit.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            double largeU = (pu_hat.GetCellByIdx(indexXToUpdate, indexYToUpdate) / pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            double largeSig = (psig_u_hat_square.GetCellByIdx(indexXToUpdate, indexYToUpdate) + pu_hat_square.GetCellByIdx(indexXToUpdate, indexYToUpdate)) / pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate) - largeU * largeU;

                            uhatGM.SetCellByIdx(indexXToUpdate, indexYToUpdate, largeU);
                            sigSqrGM.SetCellByIdx(indexXToUpdate, indexYToUpdate, largeSig);

                            Index index = new Index(indexXToUpdate, indexYToUpdate);
                            if (!indicesDictionary.ContainsKey(index))
                                indicesDictionary.Add(index, indicesDictionary.Count);
                            /*
                            if (indicesDictionary.ContainsKey(index))
                            {
                                int indexOfIndices = indicesDictionary[index];
                                heightList[indexOfIndices] = (float)largeU;
                                covList[indexOfIndices] = (float)largeSig;
                                pijSumList[indexOfIndices] = (float)pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate);
                            }
                            else
                            {
                                indicesDictionary.Add(index, indicesDictionary.Count);
                                indicesList.Add(new Index(indexXToUpdate, indexYToUpdate));
                                heightList.Add((float)largeU);
                                covList.Add((float)largeSig);
                                pijSumList.Add((float)pij_sum.GetCellByIdx(indexXToUpdate, indexYToUpdate));
                            }
                             */
                        }
                    }
                    sw6.Stop();

                } // end foreach

                //Console.WriteLine("1: " + sw1.ElapsedMilliseconds +
                //                                    " 2: " + sw2.ElapsedMilliseconds +
                //                                    " 3: " + sw3.ElapsedMilliseconds +
                //                                    " 4: " + sw4.ElapsedMilliseconds +
                //                                    " 5: " + sw5.ElapsedMilliseconds +
                //                                    " 6: " + sw6.ElapsedMilliseconds +
                //                                    " TOTAL: " + (sw1.ElapsedMilliseconds + sw2.ElapsedMilliseconds + sw3.ElapsedMilliseconds + sw4.ElapsedMilliseconds + sw5.ElapsedMilliseconds + sw6.ElapsedMilliseconds).ToString());
            } // end function
        }
예제 #22
0
        /// <summary>Returns a sub matrix extracted from the current matrix.</summary>
        /// <param name="startRow">Start row index</param>
        /// <param name="endRow">End row index</param>
        /// <param name="startColumn">Start column index</param>
        /// <param name="endColumn">End column index</param>
        public UMatrix Submatrix(int startRow, int endRow, int startColumn, int endColumn)
        {
            if ((startRow > endRow) || (startColumn > endColumn) || (startRow < 0) || (startRow >= this.numRows) || (endRow < 0) || (endRow >= this.numRows) || (startColumn < 0) || (startColumn >= this.numCols) || (endColumn < 0) || (endColumn >= this.numCols))
            {
                throw new ArgumentException("Argument out of range.");
            }

            UMatrix X = new UMatrix(endRow - startRow + 1, endColumn - startColumn + 1);
            fixed (double* ptrX = X.data, ptrThis = data)
            {
                for (int i = startRow; i <= endRow; i++)
                {
                    for (int j = startColumn; j <= endColumn; j++)
                    {
                        //X.data[j + (X.numCols * i)] = data[j + (numCols * i)];
                        (*(ptrX + j + (X.numCols * i))) = (*(ptrThis + j + (numCols * i)));
                    }
                }
            }

            return X;
        }
예제 #23
0
        public UMatrix Inverse()
        {
            UMatrix upper, lower, c, z;

            LuDecomposition(out lower, out upper);
            c = new UMatrix(numRows, numCols, 1);
            z = UMatrix.ForwardSub(lower, c);

            return UMatrix.BackwardSub(upper, z);
        }
예제 #24
0
        /// <summary>Unary minus.</summary>
        public static UMatrix Negate(UMatrix value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            int rows = value.numRows;
            int columns = value.numCols;
            UMatrix X = new UMatrix(rows, columns);
            fixed (double* ptrX = X.data, ptrThis = value.data)
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        //X.data[j + (columns * i)] = -value.data[j + (columns * i)];
                        (*(ptrX + j + (columns * i))) = -(*(ptrThis + j + (columns * i)));
                    }
                }
            }

            return X;
        }
예제 #25
0
        public GaussianMixMappingQ(IOccupancyGrid2D ocToUpdate, SensorPose laserRelativePositionToRover, int cellToUpdate)
        {
            //currentLaserPoseToRobot = laserRelativePositionToRover;
            this.rangeToApply = cellToUpdate;
            Matrix4 laser2RobotDCM = Matrix4.FromPose(laserRelativePositionToRover);
            laserToRobotDCM = new UMatrix(4, 4);
            robotToGlocalDCM = new UMatrix(4, 4);
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    laserToRobotDCM[i, j] = laser2RobotDCM[i, j];
                }
            }
            covRobotPose = new UMatrix(6, 6);
            covLaserPose = new UMatrix(6, 6);
            covLaserScan = new UMatrix(2, 2);

            pij_sum = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            pu_hat = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            pu_hat_square = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            psig_u_hat_square = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            uhatGM = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            sigSqrGM = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            laserHit = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            thresholdedHeightMap = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            resetCountMap = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            indexMap = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            this.numCellX = ocToUpdate.NumCellX;
            this.numCellY = ocToUpdate.NumCellY;
            #region Initial setup

            double[] Qp_robot = new double[36]{0.1, 0, 0, 0, 0, 0,
                                               0, 0.1, 0, 0, 0, 0,
                                               0, 0, 0.1, 0, 0, 0,
                                               0, 0, 0, 0.01, 0, 0,
                                               0, 0, 0, 0, 0.01, 0,
                                               0, 0, 0, 0, 0, 0.01};

            double[] Qp_laser = new double[36]{0.001, 0, 0, 0, 0, 0,
                                               0, 0.001, 0, 0, 0, 0,
                                               0, 0, 0.001, 0, 0, 0,
                                               0, 0, 0, 0.0001, 0, 0,
                                               0, 0, 0, 0, 0.0001, 0,
                                               0, 0, 0, 0, 0, 0.0001};

            double[] Qr = new double[4] { .01 * .01, 0, 0, (0.1 * Math.PI / 180.0) * (0.1 * Math.PI / 180.0) };

            // assign to our UMatrix
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    covRobotPose[j, i] = Qp_robot[j * 6 + i];// *1e-6;
                    covLaserPose[j, i] = Qp_laser[j * 6 + i];// *1e-6;
                }
            }
            covLaserScan[0, 0] = Qr[0];
            covLaserScan[0, 1] = 0;
            covLaserScan[1, 0] = 0;
            covLaserScan[1, 1] = Qr[3];
            #endregion

            int k = 0;

            sinLookupHokuyo = new double[682];
            cosLookupHokuyo = new double[682];
            for (double i = -120; i <= 120; i += 0.35190615835777126099706744868035)
            {
                sinLookupHokuyo[k] = (Math.Sin(i * Math.PI / 180.0));
                cosLookupHokuyo[k] = (Math.Cos(i * Math.PI / 180.0));
                k++;
            }
            laserHalfAngleHokuyo = 120;
            MAXRANGEHokuyo = 5.0;
            MINRANGEHokuyo = 0.5;

            k = 0;
            sinLookupSick = new double[361];
            cosLookupSick = new double[361];
            for (double i = -90; i <= 90; i += .5)
            {
                sinLookupSick[k] = (Math.Sin(i * Math.PI / 180.0));
                cosLookupSick[k] = (Math.Cos(i * Math.PI / 180.0));
                k++;
            }
            laserHalfAngleSick = 90;
            MAXRANGESick = 30.0;
            MINRANGESick = 0.5;

            hokuyoStartIdx = 100;
            hokuyoEndIdx = 500;

            indicesList = new List<Index>();
            heightList = new List<float>();
            covList = new List<float>();
            pijSumList = new List<float>();

            laser2RobotTransMatrixDictionary = new Dictionary<int, Dictionary<int, UMatrix>>();
            jacobianLaserPoseDictionary = new Dictionary<int, Dictionary<int, UMatrix>>();

            indicesDictionary = new Dictionary<Index, int>();
        }
예제 #26
0
        /// <summary>
        /// Update OccupancyGrid based on lidarScan and robotPose received
        /// </summary>
        /// <param name="lidarScan"></param>
        /// <param name="currentRobotPose"></param>
        public void UpdateOccupancyGrid(ILidarScan<ILidar2DPoint> lidarScan, int robotID, int scannerID, PoseFilterState currentRobotPose, SensorPose lidarPose, List<Polygon> dynamicObstacles)
        {
            if (robotID == 1)
            {
                MAXRANGESick = 7.0;
            }
            else if (robotID == 3)
            {
                MAXRANGESick = 30.0;
            }

            if (lidarPose == null)
            {
                lidarPose = new SensorPose(0, 0, 0.5, 0, 0 * Math.PI / 180.0, 0, 0);
            }
            if (laser2RobotTransMatrixDictionary.ContainsKey(robotID))
            {
                if (laser2RobotTransMatrixDictionary[robotID].ContainsKey(scannerID))
                {
                    JTpl = jacobianLaserPoseDictionary[robotID][scannerID];
                    laserToRobotDCM = laser2RobotTransMatrixDictionary[robotID][scannerID];
                }
                else
                {
                    Matrix4 laser2RobotDCM = Matrix4.FromPose(lidarPose);
                    for (int i = 0; i < 4; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            laserToRobotDCM[i, j] = laser2RobotDCM[i, j];
                        }
                    }
                    laser2RobotTransMatrixDictionary[robotID].Add(scannerID, laserToRobotDCM);
                    jacobianLaserPoseDictionary[robotID].Add(scannerID, ComputeJacobian(lidarPose.yaw, lidarPose.pitch, lidarPose.roll));
                    JTpl = jacobianLaserPoseDictionary[robotID][scannerID];
                }
            }
            else
            {
                laser2RobotTransMatrixDictionary.Add(robotID, new Dictionary<int, UMatrix>());
                jacobianLaserPoseDictionary.Add(robotID, new Dictionary<int, UMatrix>());
                Matrix4 laser2RobotDCM = Matrix4.FromPose(lidarPose);
                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        laserToRobotDCM[i, j] = laser2RobotDCM[i, j];
                    }
                }
                laser2RobotTransMatrixDictionary[robotID].Add(scannerID, new UMatrix(laserToRobotDCM));
                jacobianLaserPoseDictionary[robotID].Add(scannerID, ComputeJacobian(lidarPose.yaw, lidarPose.pitch, lidarPose.roll));
                JTpl = jacobianLaserPoseDictionary[robotID][scannerID];
            }

            // calculate robot2global transformation matrix
            if (currentRobotPose == null) return;
            Matrix4 robot2GlocalDCM = Matrix4.FromPose(currentRobotPose);
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    robotToGlocalDCM[i, j] = robot2GlocalDCM[i, j];
                }
            }

            if (lidarScan == null) return;

            UMatrix JTpr = ComputeJacobianQ(currentRobotPose.q1, currentRobotPose.q2, currentRobotPose.q3, currentRobotPose.q4);
            List<UMatrix> JfPrCubixLaserToRobotDCM = new List<UMatrix>(6);
            List<UMatrix> RobotToGlocalDCMJfPlCubix = new List<UMatrix>(7);
            for (int i = 0; i < 7; i++)
            {
                //derivative of the robot transform matrtix w.r.t. some element of the robot psoe
                UMatrix j = new UMatrix(4, 4);
                j[0, 0] = JTpr[0, i]; j[1, 0] = JTpr[1, i]; j[2, 0] = JTpr[2, i]; j[3, 0] = JTpr[3, i];
                j[0, 1] = JTpr[4, i]; j[1, 1] = JTpr[5, i]; j[2, 1] = JTpr[6, i]; j[3, 1] = JTpr[7, i];
                j[0, 2] = JTpr[8, i]; j[1, 2] = JTpr[9, i]; j[2, 2] = JTpr[10, i]; j[3, 2] = JTpr[11, i];
                j[0, 3] = JTpr[12, i]; j[1, 3] = JTpr[13, i]; j[2, 3] = JTpr[14, i]; j[3, 3] = JTpr[15, i];
                JfPrCubixLaserToRobotDCM.Add(j * laserToRobotDCM);

                if (i == 7) continue; // same as break
                UMatrix tempJacobianPl = new UMatrix(4, 4);
                tempJacobianPl[0, 0] = JTpl[0, i]; tempJacobianPl[1, 0] = JTpl[1, i]; tempJacobianPl[2, 0] = JTpl[2, i]; tempJacobianPl[3, 0] = JTpl[3, i];
                tempJacobianPl[0, 1] = JTpl[4, i]; tempJacobianPl[1, 1] = JTpl[5, i]; tempJacobianPl[2, 1] = JTpl[6, i]; tempJacobianPl[3, 1] = JTpl[7, i];
                tempJacobianPl[0, 2] = JTpl[8, i]; tempJacobianPl[1, 2] = JTpl[9, i]; tempJacobianPl[2, 2] = JTpl[10, i]; tempJacobianPl[3, 2] = JTpl[11, i];
                tempJacobianPl[0, 3] = JTpl[12, i]; tempJacobianPl[1, 3] = JTpl[13, i]; tempJacobianPl[2, 3] = JTpl[14, i]; tempJacobianPl[3, 3] = JTpl[15, i];
                RobotToGlocalDCMJfPlCubix.Add(robotToGlocalDCM * tempJacobianPl);
            }
            UMatrix laserToENU = robotToGlocalDCM * laserToRobotDCM;
            //UMatrix pijCell = new UMatrix(rangeToApply * 2 + 1, rangeToApply * 2 + 1);
            // update covariance
            UpdateCovarianceQ(currentRobotPose.Covariance);

            //SickPoint p = new SickPoint(new RThetaCoordinate(1.0f, 0.0f));
            for (int laserIndex = 0; laserIndex < lidarScan.Points.Count; laserIndex++)
            {
                lock (locker)
                {
                    ILidar2DPoint p = lidarScan.Points[laserIndex];
                    if (scannerID == 1)
                    {
                        if (p.RThetaPoint.R >= MAXRANGESick || p.RThetaPoint.R <= MINRANGESick)
                            continue;
                    }
                    else if (scannerID == 2)
                    {
                        if (p.RThetaPoint.R >= MAXRANGEHokuyo || p.RThetaPoint.R <= MINRANGEHokuyo || laserIndex < hokuyoStartIdx || laserIndex > hokuyoEndIdx)
                            continue;
                    }
                    bool hitDynamicObstacles = false;
                    // figure out if this lidar point is hitting other robot

                    // find laser points in 3D space
                    // first define 2D point on the laser plane
                    UMatrix laserPoint = new UMatrix(4, 1);

                    double deg = (p.RThetaPoint.theta * 180.0 / Math.PI);
                    int thetaDegIndex = 0;
                    if (scannerID == 2) // hokuyo
                        thetaDegIndex = (int)Math.Round((deg + laserHalfAngleHokuyo) * 2.84);// % 360;
                    else if (scannerID == 1) // sick
                        thetaDegIndex = (int)Math.Round((deg + laserHalfAngleSick) * 2) % 360;

                    double cosTheta = 0, sinTheta = 0;

                    if (scannerID == 1)
                    {
                        cosTheta = cosLookupSick[thetaDegIndex];
                        sinTheta = sinLookupSick[thetaDegIndex];
                    }
                    else if (scannerID == 2)
                    {
                        cosTheta = cosLookupHokuyo[thetaDegIndex];
                        sinTheta = sinLookupHokuyo[thetaDegIndex];
                    }

                    // initial laser points
                    laserPoint[0, 0] = p.RThetaPoint.R * cosTheta;
                    laserPoint[1, 0] = p.RThetaPoint.R * sinTheta;
                    laserPoint[2, 0] = 0;
                    laserPoint[3, 0] = 1;

                    //calculate r_hat_ENU
                    UMatrix r_hat_ENU = laserToENU * laserPoint;

                    foreach (Polygon dp in dynamicObstacles)
                    {
                        if (dp.IsInside(new Vector2(r_hat_ENU[0, 0], r_hat_ENU[1, 0])))
                        {
                            hitDynamicObstacles = true;
                            break;
                        }
                    }
                    if (hitDynamicObstacles) continue;

                    //-------------------------------//
                    // COVARIANCE UMatrix CALCULATION //
                    //-------------------------------//
                    UMatrix JRr = new UMatrix(4, 2);
                    JRr.Zero();
                    JRr[0, 0] = cosTheta;
                    JRr[0, 1] = -p.RThetaPoint.R * sinTheta;
                    JRr[1, 0] = sinTheta;
                    JRr[1, 1] = p.RThetaPoint.R * cosTheta;

                    UMatrix Jfr = new UMatrix(3, 2); // 3x2
                    Jfr = (laserToENU * JRr).Submatrix(0, 2, 0, 1);	 // 4x4 * 4x4 * 4x2

                    UMatrix Jfpr = new UMatrix(3, 7);
                    UMatrix Jfpl = new UMatrix(3, 6);

                    for (int i = 0; i < 7; i++) //for each state var (i.e. x,y,z,y,p,r)
                    {
                        UMatrix JfprTemp = (JfPrCubixLaserToRobotDCM[i]) * laserPoint; // 4 by 1 UMatrix
                        Jfpr[0, i] = JfprTemp[0, 0];
                        Jfpr[1, i] = JfprTemp[1, 0];
                        Jfpr[2, i] = JfprTemp[2, 0];

                        //UMatrix JfplTemp = (RobotToGlocalDCMJfPlCubix[i]) * laserPoint; // 4 by 1 UMatrix
                        //Jfpl[0, i] = JfplTemp[0, 0];
                        //Jfpl[1, i] = JfplTemp[1, 0];
                        //Jfpl[2, i] = JfplTemp[2, 0];
                    }
                    UMatrix JfprQprJfprT = new UMatrix(3, 3);
                    UMatrix JfplQplJfplT = new UMatrix(3, 3);
                    UMatrix JfrQrJfrT = new UMatrix(3, 3);
                    JfprQprJfprT = (Jfpr * covRobotPoseQ) * Jfpr.Transpose();
                    //JfplQplJfplT = (Jfpl * covLaserPose) * Jfpl.Transpose(); // not doing because covariance of laser point is so small
                    JfrQrJfrT = (Jfr * covLaserScan) * Jfr.Transpose();

                    // add above variables together and get the covariance
                    UMatrix covRHatENU = JfprQprJfprT + /*JfplQplJfplT +*/ JfrQrJfrT; // 3x3 UMatrix
                    //-----------------------------//
                    // FIND WHICH CELLS TO COMPUTE //
                    //-----------------------------//

                    // find out cells around this laser point
                    int laserPointIndexX = 0;
                    int laserPointIndexY = 0;
                    //this is used just to do the transformation from reaal to grid and visa versa
                    psig_u_hat_square.GetIndicies(r_hat_ENU[0, 0], r_hat_ENU[1, 0], out laserPointIndexX, out laserPointIndexY); // get cell (r_hat_ENU_X, r_hat_ENU_y)
                    if ((laserPointIndexX < 0 || laserPointIndexX >= numCellX) || (laserPointIndexY < 0 || laserPointIndexY >= numCellY))
                        continue;

                    int rangeToApplyX = (int)Math.Round(Math.Sqrt(covRHatENU[0, 0]) / (pij_sum.ResolutionX * 2)) * 2;
                    int rangeToApplyY = (int)Math.Round(Math.Sqrt(covRHatENU[1, 1]) / (pij_sum.ResolutionY * 2)) * 2;
                    //-----------------------------------------//
                    // COMPUTE THE DISTRIBUTION OF UNCERTAINTY //
                    //-----------------------------------------//
                    UMatrix pijCell = new UMatrix(rangeToApplyY * 2 + 1, rangeToApplyX * 2 + 1);

                    double sigX = Math.Sqrt(covRHatENU[0, 0]);
                    double sigY = Math.Sqrt(covRHatENU[1, 1]);
                    double rho = covRHatENU[1, 0] / (sigX * sigY);
                    double logTerm = Math.Log(2 * Math.PI * sigX * sigY * Math.Sqrt(1 - (rho * rho)));
                    double xTermDenom = (1 - (rho * rho));
                    //for (int i = -rangeToApply; i <= rangeToApply; i++) // row
                    for (int i = -rangeToApplyX; i <= rangeToApplyX; i++) // row
                    {
                        //for (int j = -rangeToApplyX; j <= rangeToApplyX; j++) // column
                        for (int j = -rangeToApplyY; j <= rangeToApplyY; j++) // column
                        {
                            if (laserPointIndexX + i < 0 || laserPointIndexX + i >= numCellX || laserPointIndexY + j < 0 || laserPointIndexY + j >= numCellY) continue;
                            // estimate using Bivariate Normal Distribution
                            double posX = 0; double posY = 0;
                            psig_u_hat_square.GetReals(laserPointIndexX + i, laserPointIndexY + j, out posX, out posY);
                            posX += psig_u_hat_square.ResolutionX / 2;
                            posY += psig_u_hat_square.ResolutionY / 2;
                            double x = posX - r_hat_ENU[0, 0];
                            double y = posY - r_hat_ENU[1, 0];
                            double z = (x * x) / (sigX * sigX) -
                                                (2 * rho * x * y / (sigX * sigY)) +
                                                 (y * y) / (sigY * sigY);
                            double xTerm = -0.5 * z / xTermDenom;
                            // chi2 test
                            //if ((2 * (1 - (rho * rho))) * ((x * x) / (sigX * sigX) + (y * y) / (sigY * sigY) - (2 * rho * x * y) / (sigX * sigY)) > 15.2)
                            //  continue;
                            pijCell[j + rangeToApplyY, i + rangeToApplyX] = Math.Exp(xTerm - logTerm) * psig_u_hat_square.ResolutionX * psig_u_hat_square.ResolutionY;
                            laserHit.SetCellByIdx(laserPointIndexX + i, laserPointIndexY + j, laserHit.GetCellByIdxUnsafe(laserPointIndexX + i, laserPointIndexY + j) + 1);
                        }
                    }

                    //---------------------------//
                    // COMPUTE HEIGHT ESTIMATION //
                    //---------------------------//
                    UMatrix PEN = covRHatENU.Submatrix(0, 1, 0, 1);

                    UMatrix PENInv = PEN.Inverse2x2;

                    UMatrix PuEN = new UMatrix(1, 2);
                    UMatrix PENu = new UMatrix(2, 1);
                    UMatrix PuENPENInv = PuEN * PENInv;
                    UMatrix uHatMatrix = new UMatrix(rangeToApplyY * 2 + 1, rangeToApplyX * 2 + 1);
                    UMatrix sigUHatMatrix = new UMatrix(rangeToApplyY * 2 + 1, rangeToApplyX * 2 + 1);

                    PuEN[0, 0] = covRHatENU[2, 0];
                    PuEN[0, 1] = covRHatENU[2, 1];

                    PENu[0, 0] = covRHatENU[0, 2];
                    PENu[1, 0] = covRHatENU[1, 2];

                    double sig_u_hat_product = (PuENPENInv * PENu)[0, 0]; // output = 1x1 UMatrix

                    for (int i = -rangeToApplyX; i <= rangeToApplyX; i++) // row
                    {
                        for (int j = -rangeToApplyY; j <= rangeToApplyY; j++) // column
                        {
                            UMatrix ENmr_EN = new UMatrix(2, 1);
                            double posX = 0; double posY = 0;
                            psig_u_hat_square.GetReals(laserPointIndexX + i, laserPointIndexY + j, out posX, out posY);
                            ENmr_EN[0, 0] = posX - r_hat_ENU[0, 0];
                            ENmr_EN[1, 0] = posY - r_hat_ENU[1, 0];
                            double u_hat_product = (PuENPENInv * (ENmr_EN))[0, 0]; // output = 1x1 UMatrix
                            uHatMatrix[j + rangeToApplyY, i + rangeToApplyX] = r_hat_ENU[2, 0] + u_hat_product;
                            sigUHatMatrix[j + rangeToApplyY, i + rangeToApplyX] = covRHatENU[2, 2] - sig_u_hat_product;
                        }
                    }

                    //-------------------------------------------//
                    // ASSIGN FINAL VALUES TO THE OCCUPANCY GRID //
                    //-------------------------------------------//
                    for (int i = -rangeToApplyX; i <= rangeToApplyX; i++)
                    {
                        for (int j = -rangeToApplyY; j <= rangeToApplyY; j++)
                        {
                            int indexXToUpdate = laserPointIndexX + i;
                            int indexYToUpdate = laserPointIndexY + j;
                            // if the cell to update is out of range, continue
                            if (!psig_u_hat_square.CheckValidIdx(indexXToUpdate, indexYToUpdate))
                                continue;

                            pij_sum.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApplyY, i + rangeToApplyX] + pij_sum.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate));
                            pu_hat.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApplyY, i + rangeToApplyX] * uHatMatrix[j + rangeToApplyY, i + rangeToApplyX] + pu_hat.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate));
                            pu_hat_square.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApplyY, i + rangeToApplyX] * uHatMatrix[j + rangeToApplyY, i + rangeToApplyX] * uHatMatrix[j + rangeToApply, i + rangeToApply] + pu_hat_square.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate));
                            psig_u_hat_square.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                            pijCell[j + rangeToApplyY, i + rangeToApplyX] * sigUHatMatrix[j + rangeToApplyY, i + rangeToApplyX] + psig_u_hat_square.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate));
                            uhatGM.SetCellByIdx(indexXToUpdate, indexYToUpdate,
                                                            (pu_hat.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) / pij_sum.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate)));

                            double largeU = (pu_hat.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) / pij_sum.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate));
                            double largeSig = (psig_u_hat_square.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) + pu_hat_square.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate)) / pij_sum.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) - largeU * largeU;
                            if (pij_sum.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) > 1)
                                thresholdedHeightMap.SetCellByIdx(indexXToUpdate, indexYToUpdate, largeU);//pij_sum.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) / laserHit.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate));

                            uhatGM.SetCellByIdx(indexXToUpdate, indexYToUpdate, largeU);
                            //sigSqrGM.SetCellByIdx(indexXToUpdate, indexYToUpdate, largeU + 2 * Math.Sqrt(largeSig));

                            if (indexMap.GetCellByIdxUnsafe(indexXToUpdate, indexYToUpdate) != 1.0)
                            {
                                Index index = new Index(indexXToUpdate, indexYToUpdate);
                                indicesDictionary.Add(index, indicesDictionary.Count);
                                indexMap.SetCellByIdx(indexXToUpdate, indexYToUpdate, 1.0);
                            }
                        }
                    }

                } // end foreach

                //Console.WriteLine("1: " + sw1.ElapsedMilliseconds +
                //                                    " 2: " + sw2.ElapsedMilliseconds +
                //                                    " 3: " + sw3.ElapsedMilliseconds +
                //                                    " 4: " + sw4.ElapsedMilliseconds +
                //                                    " 5: " + sw5.ElapsedMilliseconds +
                //                                    " 6: " + sw6.ElapsedMilliseconds +
                //                                    " TOTAL: " + (sw1.ElapsedMilliseconds + sw2.ElapsedMilliseconds + sw3.ElapsedMilliseconds + sw4.ElapsedMilliseconds + sw5.ElapsedMilliseconds + sw6.ElapsedMilliseconds).ToString());
            } // end function
        }
예제 #27
0
        /// <summary>Matrix subtraction.</summary>
        public static UMatrix Subtract(UMatrix left, UMatrix right)
        {
            int rows = left.numRows;
            int columns = left.numCols;

            if ((rows != right.numRows) || (columns != right.numCols))
            {
                throw new ArgumentException("Matrix dimension do not match.");
            }

            UMatrix X = new UMatrix(rows, columns);
            fixed (double* ptrX = X.data, ptrL = left.data, ptrR = right.data)
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        //X.data[j + (columns * i)] = left.data[j + (columns * i)] - right.data[j + (columns * i)];
                        (*(ptrX + j + (columns * i))) = (*(ptrL + j + (columns * i))) - (*(ptrR + j + (columns * i)));
                    }
                }
            }
            return X;
        }
예제 #28
0
 private void UpdateCovarianceQ(Matrix state)
 {
     UMatrix abc = new UMatrix(7, 7);
     for (int i = 0; i < 7; i++)
     {
         for (int j = 0; j < 7; j++)
             abc[i, j] = state[i, j];
     }
     covRobotPoseQ = abc;
 }
예제 #29
0
        //----------------------------------------------------------------------------
        public UMatrix LuDecomposition(out UMatrix l, out UMatrix u)
        {
            double[] lu = new double[data.Length];
            Array.Copy(data, lu, data.Length);

            //double[] luRowI;
            double* luRowIPtr;
            double[] luColJ = new double[numRows];
            double[] lData = new double[numRows * numRows];
            double[] uData = new double[numRows * numRows];

            fixed (double* luPtr = lu, luColJPtr = luColJ, lDataPtr = lData, uDataPtr = uData)
            {
                int pivotSign = 1;
                int[] pivotVector = new int[numRows];
                for (int i = 0; i < numRows; i++)
                {
                    pivotVector[i] = i;
                }

                // Outer loop.
                for (int j = 0; j < numCols; j++)
                {
                    // Make a copy of the j-th column to localize references.
                    for (int i = 0; i < numRows; i++)
                    {
                        *(luColJPtr + i) = *(luPtr + j + i * numCols);
                    }

                    // Apply previous transformations.
                    for (int i = 0; i < numRows; i++)
                    {
                        luRowIPtr = luPtr + i * numCols;

                        // Most of the time is spent in the following dot product.
                        //int kmax = (i > j) ? j : i;
                        int kmax = Math.Min(i, j);
                        double s = 0.0;
                        for (int k = 0; k < kmax; k++)
                        {
                            s += *(luRowIPtr + k) * *(luColJPtr + k);
                        }
                        *(luRowIPtr + j) = *(luColJPtr + i) -= s;
                    }

                    // Find pivot and exchange if necessary.
                    int p = j;
                    for (int i = j + 1; i < numRows; i++)
                    {
                        if (Math.Abs(*(luColJPtr + i)) > Math.Abs(*(luColJPtr + p)))
                        {
                            p = i;
                        }
                    }

                    if (p != j)
                    {
                        for (int k = 0; k < numCols; k++)
                        {
                            double t = *(luPtr + k + p * numCols);
                            *(luPtr + k + p * numCols) = *(luPtr + k + j * numCols);
                            *(luPtr + k + j * numCols) = t;
                        }

                        int v = pivotVector[p];
                        pivotVector[p] = pivotVector[j];
                        pivotVector[j] = v;

                        pivotSign = -pivotSign;
                    }

                    // Compute multipliers.
                    if (j < numRows & *(luPtr + j + j * numCols) != 0.0)
                    {
                        for (int i = j + 1; i < numRows; i++)
                        {
                            *(luPtr + j + i * numCols) /= *(luPtr + j + j * numCols);
                        }
                    }
                }

                for (int i = 0; i < numRows; i++)
                {
                    for (int j = 0; j < numCols; j++)
                    {
                        *(lDataPtr + j + i * numCols) = (j == i) ? 1 : (i < j) ? 0 : *(luPtr + j + i * numCols);
                        *(uDataPtr + j + i * numCols) = (i > j) ? 0 : *(luPtr + j + i * numCols);
                    }
                }

                l = new UMatrix(numRows, numCols, lData);
                u = new UMatrix(numRows, numCols, uData);
            }

            return new UMatrix(numRows, numCols, lu);
        }
예제 #30
0
        public GaussianMixMapping(IOccupancyGrid2D ocToUpdate, SensorPose laserRelativePositionToRover)
        {
            //currentLaserPoseToRobot = laserRelativePositionToRover;
            Matrix4 laser2RobotDCM = Matrix4.FromPose(laserRelativePositionToRover);
            laserToRobotDCM = new UMatrix(4, 4);
            robotToGlocalDCM = new UMatrix(4, 4);
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    laserToRobotDCM[i, j] = laser2RobotDCM[i, j];
                }
            }
            covRobotPose = new UMatrix(6, 6);
            covLaserPose = new UMatrix(6, 6);
            covLaserScan = new UMatrix(2, 2);

            pij_sum = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            pu_hat = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            pu_hat_square = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            psig_u_hat_square = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            uhatGM = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            sigSqrGM = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            laserHit = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            normalisedPijSum = new OccupancyGrid2D((OccupancyGrid2D)ocToUpdate);
            #region Initial setup
            // initial setup
            // these matrices were obtained from Jon using Vicon with Pioneer and HOKUYO laser
            // these matrices need to be redefined
            // these matrices are in row-wise

            //double[] Qp_robot = new double[36]{0.0026,    0.0011,   -0.0008,   -0.0019,    0.0125,   -0.0047,
            //                      0.0011,    0.0082,   -0.0054,    0.0098,    0.0116,   -0.0330,
            //                     -0.0008,   -0.0054,    0.0132,   -0.0173,   -0.0154,    0.0115,
            //                     -0.0019,    0.0098,   -0.0173,    0.0542,    0.0076,   -0.0319,
            //                      0.0125,    0.0116,   -0.0154,    0.0076,    0.0812,   -0.0397,
            //                     -0.0047,   -0.0330,    0.0115,   -0.0319,   -0.0397,    0.1875};

            //double[] Qp_laser = new double[36]{0.0077, -0.0009, -0.0016, -0.0127, -0.0415, -0.0011,
            //                       -0.0009, 0.0051, -0.0013, -0.0035, 0.0045, 0.0197,
            //                       -0.0016, -0.0013, 0.0101, -0.0167, 0.0189, 0.0322,
            //                       -0.0127, -0.0035, -0.0167, 0.2669, -0.0548, -0.2940,
            //                       -0.0415, 0.0045, 0.0189, -0.0548, 0.8129, 0.3627,
            //                       -0.0011, 0.0197, 0.0322, -0.2940, 0.3627, 0.7474};

            double[] Qp_robot = new double[36]{0.1, 0, 0, 0, 0, 0,
                                                                                 0, 0.1, 0, 0, 0, 0,
                                                                                 0, 0, 0.1, 0, 0, 0,
                                                                                 0, 0, 0, 0.01, 0, 0,
                                                                                 0, 0, 0, 0, 0.01, 0,
                                                                                 0, 0, 0, 0, 0, 0.01};

            double[] Qp_laser = new double[36]{0.001, 0, 0, 0, 0, 0,
                                                                                 0, 0.001, 0, 0, 0, 0,
                                                                                 0, 0, 0.001, 0, 0, 0,
                                                                                 0, 0, 0, 0.0001, 0, 0,
                                                                                 0, 0, 0, 0, 0.0001, 0,
                                                                                 0, 0, 0, 0, 0, 0.0001};

            double[] Qr = new double[4] { .01 * .01, 0, 0, (0.1 * Math.PI / 180.0) * (0.1 * Math.PI / 180.0) };

            // assign to our UMatrix
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    covRobotPose[j, i] = Qp_robot[j * 6 + i];// *1e-6;
                    covLaserPose[j, i] = Qp_laser[j * 6 + i];// *1e-6;
                }
            }
            covLaserScan[0, 0] = Qr[0];
            covLaserScan[0, 1] = 0;
            covLaserScan[1, 0] = 0;
            covLaserScan[1, 1] = Qr[3];
            #endregion

            //JTpl = ComputeJacobian(currentLaserPoseToRobot.yaw, currentLaserPoseToRobot.pitch, currentLaserPoseToRobot.roll);

            //	int thetaDegIndex = (int)((p.RThetaPoint.theta * 180.0/Math.PI) * 2) + 180;
            int k = 0;
            for (double i = -90; i <= 90; i += .5)
            {
                sinLookup[k] = (Math.Sin(i * Math.PI / 180.0));
                cosLookup[k] = (Math.Cos(i * Math.PI / 180.0));
                k++;
            }

            // initialize arrays
            //pijToSend = new float[361 * rangeLong * rangeLong];
            //largeUToSend = new float[361 * rangeLong * rangeLong];
            //largeSigToSend = new float[361 * rangeLong * rangeLong];
            //colIdxChange = new int[361 * rangeLong * rangeLong];
            //rowIdxChange = new int[361 * rangeLong * rangeLong];

            indicesList = new List<Index>();
            heightList = new List<float>();
            covList = new List<float>();
            pijSumList = new List<float>();

            laser2RobotTransMatrixDictionary = new Dictionary<int, UMatrix>();
            jacobianLaserPoseDictionary = new Dictionary<int, UMatrix>();

            indicesDictionary = new Dictionary<Index, int>();
        }
예제 #31
0
        /// <summary>Returns the transposed matrix.</summary>
        public UMatrix Transpose()
        {
            UMatrix X = new UMatrix(numCols, numRows);
            fixed (double* ptrX = X.data, ptrThis = data)
            {
                for (int i = 0; i < numRows; i++)
                {
                    for (int j = 0; j < numCols; j++)
                    {
                        //X.data[i + (numRows * j)] = data[j + (numCols * i)];
                        (*(ptrX + i + (numRows * j))) = (*(ptrThis + j + (numCols * i)));
                    }
                }
            }

            return X;
        }
예제 #32
0
        public UMatrix ComputeJacobian(double yaw, double pitch, double roll)
        {
            UMatrix m = new UMatrix(16, 6);
            m.Zero();

            double cp = Math.Cos(pitch);
            double sp = Math.Sin(pitch);
            double cy = Math.Cos(yaw);
            double sy = Math.Sin(yaw);
            double cr = Math.Cos(roll);
            double sr = Math.Sin(roll);

            m[0, 3] = -cp * sy;
            m[0, 4] = -sp * cy;
            m[1, 3] = -sp * sr * sy - cy * cr;
            m[1, 4] = cp * sr * cy;
            m[1, 5] = sp * cr * cy + sy * sr;

            m[2, 3] = -sp * cr * sy + cy * sr;
            m[2, 4] = cp * cr * cy;
            m[2, 5] = -sp * sr * cy + sy * cr;

            m[4, 3] = cp * cy;
            m[4, 4] = -sp * sy;
            m[5, 3] = sp * sr * cy - sy * cr;
            m[5, 4] = cp * sr * sy;
            m[5, 5] = sp * cr * sy - cy * sr;
            m[6, 3] = sp * cr * cy + sy * sr;
            m[6, 4] = cp * cr * sy;
            m[6, 5] = -sp * sr * sy - cy * cr;

            m[8, 4] = -cp;
            m[9, 4] = -sp * sr;
            m[9, 5] = cp * cr;
            m[10, 4] = -sp * cr;
            m[10, 5] = -cp * sr;

            m[12, 0] = 1;
            m[13, 1] = 1;
            m[14, 2] = 1;

            return m;
        }