// finds an estimate on the robots position gradient based on the sonar readings public static double[] getGradient(LMMobileRobot thecart, int curOrientation, int prevOrientation) { double[] gradient = new double[] { 0, 0 }; double D1x, D2x, D3x, D4x, D5x, D6x; double D1y, D2y, D3y, D4y, D5y, D6y; double[] Snew = new double[8]; double[] Sprev = new double[8]; int i; // storing sensor index permutations for both new and previous orientations int[] prevPerm = getSensorPermutation(prevOrientation); int[] newPerm = getSensorPermutation(curOrientation); for (i = 0; i < 8; i++) { Snew[i] = (double)thecart.SonarArray[newPerm[i]]; Sprev[i] = (double)thecart.PrevSonarArray[prevPerm[i]]; } // initially applying a Kalman Filter to the measurements // a zero-input vector for the process double[] U = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }; double[] B = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }; double[] W0 = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }; double[] V0 = new double[] { 2, 2, 2, 2, 2, 2, 2, 2 }; double[][] A = new double[][] { new double[] { 1, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 1, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 1, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 1, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 1, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 1, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 1, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 1 } }; double[][] H = new double[][] { new double[] { 1, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 1, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 1, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 1, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 1, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 1, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 1, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 1 } }; double[][] Q = new double[][] { new double[] { 5, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 5, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 5, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 5, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 5, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 5, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 5, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 5 } }; double[][] R = new double[][] { new double[] { 2, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 2, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 2, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 2, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 2, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 2, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 2, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 2 } }; KalmanFilter filter = new KalmanFilter(8, A, B, W0, H, V0, Q, R, Sprev); // retrieving the measurement noise-free estimate by the Kalman filter, // in order to use it to calculate the gradient double[] Snest = filter.getNewEstimate(Snew, U); // computing Gx D1x = Sprev[1] * Math.Cos(Math.PI / 4) - Snest[1] * Math.Cos(Math.PI / 4); //if (Math.Abs(D1x) > sup) D1x = 0; D2x = Sprev[2] - Snest[2]; //if (Math.Abs(D2x) > sup) D2x = 0; D3x = Sprev[3] * Math.Cos(Math.PI / 4) - Snest[3] * Math.Cos(Math.PI / 4); //if (Math.Abs(D3x) > sup) D3x = 0; D4x = -(Sprev[5] * Math.Cos(Math.PI / 4) - Snest[5] * Math.Cos(Math.PI / 4)); //if (Math.Abs(D4x) > sup) D4x = 0; D5x = -(Sprev[6] - Snest[6]); //if (Math.Abs(D5x) > sup) D5x = 0; D6x = -(Sprev[7] * Math.Cos(Math.PI / 4) - Snest[7] * Math.Cos(Math.PI / 4)); //if (Math.Abs(D6x) > sup) D6x = 0; gradient[0] = (D1x + D2x + D3x + D4x + D5x + D6x) / 6; // computing Gy D1y = Sprev[0] - Snest[0]; //if (Math.Abs(D1y) > sup) D1y = 0; D2y = Sprev[1] * Math.Cos(Math.PI / 4) - Snest[1] * Math.Cos(Math.PI / 4); //if (Math.Abs(D2y) > sup) D2y = 0; D3y = -(Sprev[3] * Math.Cos(Math.PI / 4) - Snest[3] * Math.Cos(Math.PI / 4)); //if (Math.Abs(D3y) > sup) D3y = 0; D4y = -(Sprev[4] - Snest[4]); //if (Math.Abs(D4y) > sup) D4y = 0; D5y = -(Sprev[5] * Math.Cos(Math.PI / 4) - Snest[5] * Math.Cos(Math.PI / 4)); //if (Math.Abs(D5y) > sup) D5y = 0; D6y = Sprev[7] * Math.Cos(Math.PI / 4) - Snest[7] * Math.Cos(Math.PI / 4); //if (Math.Abs(D6y) > sup) D6y = 0; gradient[1] = (D1y + D2y + D3y + D4y + D5y + D6y) / 6; return gradient; }
private void button135_Click(object sender, EventArgs e) { double[][] A = new double[][] {new double[] {1, 0}, new double[] {0, 1} }; double[] B = new double[] { 0, 0}; double[] V0 = new double[] { 2, 2}; double[] W0 = new double[] { 0, 0}; double[][] H = new double[][] {new double[] {1, 0}, new double[] {0, 1} }; double[][] Q = new double[][] { new double[] {5, 0}, new double[] {0, 5} }; double[][] R = new double[][] { new double[] {2, 0}, new double[] {0, 2} }; double[] Z = new double[] {5, 5}; double[] Z1 = new double[] {6, 6}; double[] U = new double[] {0, 0}; KalmanFilter kalman = new KalmanFilter(2, A, B, W0, H, V0, Q, R, Z); double[] est = kalman.getNewEstimate(Z1, U); double[] Z2 = new double[] { 5, 5 }; kalman.getNewEstimate(Z2, U); double[][] matrix = new double[][] { new double[] {1, 0, 0}, new double[] {2, 1, 0}, new double[] {1, 0, 1}}; double d = KalmanFilter.getDeterminant(matrix, 3); double[][] inv = KalmanFilter.inverseMatrix(matrix, 3); double[] Gxy = MappingFSM.getGradient(cart, MappingFSM.orEAST, MappingFSM.orNORTH); double acos = MappingFSM.getAngleOffset(cart, MappingFSM.orEAST, MappingFSM.orNORTH); double angle = 180*Math.Acos(acos)/Math.PI; int test = 1; }
// finds an estimate of the angular offset of the robot (unsigned) // after a 90 turn public static double getAngleOffset(LMMobileRobot thecart, int curOrientation, int prevOrientation) { double[] Snew = new double[8]; double[] Sprev = new double[8]; int i; // storing sensor index permutations for both new and previous orientations int[] prevPerm = getSensorPermutation(prevOrientation); int[] newPerm = getSensorPermutation(curOrientation); for (i = 0; i < 8; i++) { Snew[i] = (double)thecart.SonarArray[newPerm[i]]; Sprev[i] = (double)thecart.PrevSonarArray[prevPerm[i]]; } // initially applying a Kalman Filter to the measurements // a zero-input vector for the process double[] U = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }; double[] B = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }; double[] W0 = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }; double[] V0 = new double[] { 2, 2, 2, 2, 2, 2, 2, 2 }; double[][] A = new double[][] { new double[] { 1, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 1, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 1, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 1, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 1, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 1, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 1, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 1 } }; double[][] H = new double[][] { new double[] { 1, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 1, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 1, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 1, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 1, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 1, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 1, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 1 } }; double[][] Q = new double[][] { new double[] { 5, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 5, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 5, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 5, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 5, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 5, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 5, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 5 } }; double[][] R = new double[][] { new double[] { 2, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 2, 0, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 2, 0, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 2, 0, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 2, 0, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 2, 0, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 2, 0 }, new double[] { 0, 0, 0, 0, 0, 0, 0, 2 } }; KalmanFilter filter = new KalmanFilter(8, A, B, W0, H, V0, Q, R, Sprev); // retrieving the measurement noise-free estimate by the Kalman filter, // in order to use it to calculate the gradient double[] Snest = filter.getNewEstimate(Snew, U); // now computing the average cosine of the triangles double anglesum = 0; int count = 0; for (i=0; i<8; i++) if (Snest[i] < Snew[i]) { count++; anglesum += 180*Math.Acos((Snest[i]+11) / (Snew[i]+11))/Math.PI; } double average = (count == 0) ? 1 : anglesum / count; return average; }