Code for autonomous ground vehicle, Data Bus, 3rd place winner in 2012 Sparkfun AVC.
Dependencies: Watchdog mbed Schedule SimpleFilter LSM303DLM PinDetect DebounceIn Servo
Estimation/Matrix/Matrix.cpp
- Committer:
- shimniok
- Date:
- 2012-06-20
- Revision:
- 0:826c6171fc1b
File content as of revision 0:826c6171fc1b:
#include <stdio.h> #include "Matrix.h" unsigned int matrix_error = 0; void Vector_Cross_Product(float C[3], float A[3], float B[3]) { C[0] = (A[1] * B[2]) - (A[2] * B[1]); C[1] = (A[2] * B[0]) - (A[0] * B[2]); C[2] = (A[0] * B[1]) - (A[1] * B[0]); return; } void Vector_Scale(float C[3], float A[3], float b) { for (int m = 0; m < 3; m++) C[m] = A[m] * b; return; } float Vector_Dot_Product(float A[3], float B[3]) { float result = 0.0; for (int i = 0; i < 3; i++) { result += A[i] * B[i]; } return result; } void Vector_Add(float C[3], float A[3], float B[3]) { for (int m = 0; m < 3; m++) C[m] = A[m] + B[m]; return; } void Vector_Add(float C[3][3], float A[3][3], float B[3][3]) { for (int m = 0; m < 3; m++) for (int n = 0; n < 3; n++) C[m][n] = A[m][n] + B[m][n]; } void Matrix_Add(float C[3][3], float A[3][3], float B[3][3]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { C[i][j] = A[i][j] + B[i][j]; } } } void Matrix_Add(int n, int m, float *C, float *A, float *B) { for (int i = 0; i < n*m; i++) { C[i] = A[i] + B[i]; } } void Matrix_Subtract(int n, int m, float *C, float *A, float *B) { for (int i = 0; i < n*m; i++) { C[i] = A[i] - B[i]; } } // grabbed from MatrixMath library for Arduino // http://arduino.cc/playground/Code/MatrixMath // E.g., the equivalent Octave script: // A=[x; y; z]; // B=[xx xy xz; yx yy yz; zx xy zz]; // C=A*B; // Would be called like this: // Matrix_Mulitply(1, 3, 3, C, A, B); // void Matrix_Multiply(int m, int p, int n, float *C, float *A, float *B) { // A = input matrix (m x p) // B = input matrix (p x n) // m = number of rows in A // p = number of columns in A = number of rows in B // n = number of columns in B // C = output matrix = A*B (m x n) for (int i=0; i < m; i++) { for(int j=0; j < n; j++) { C[n*i+j] = 0; for (int k=0; k < p; k++) { C[i*n+j] += A[i*p+k] * B[k*n+j]; } } } return; } void Matrix_Multiply(float C[3][3], float A[3][3], float B[3][3]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { C[i][j] = 0; for (int k = 0; k < 3; k++) { C[i][j] += A[i][k] * B[k][j]; } } } } void Matrix_Transpose(int n, int m, float *C, float *A) { for (int i=0; i < n; i++) { for (int j=0; j < m; j++) { C[j*n+i] = A[i*m+j]; } } } #define fabs(x) (((x) < 0) ? -x : x) // grabbed from MatrixMath library for Arduino // http://arduino.cc/playground/Code/MatrixMath //Matrix Inversion Routine // * This function inverts a matrix based on the Gauss Jordan method. // * Specifically, it uses partial pivoting to improve numeric stability. // * The algorithm is drawn from those presented in // NUMERICAL RECIPES: The Art of Scientific Computing. // * NOTE: The argument is ALSO the result matrix, meaning the input matrix is REPLACED void Matrix_Inverse(int n, float *A) { // A = input matrix AND result matrix // n = number of rows = number of columns in A (n x n) int pivrow=0; // keeps track of current pivot row int k,i,j; // k: overall index along diagonal; i: row index; j: col index int pivrows[n]; // keeps track of rows swaps to undo at end float tmp; // used for finding max value and making column swaps for (k = 0; k < n; k++) { // find pivot row, the row with biggest entry in current column tmp = 0; for (i = k; i < n; i++) { if (fabs(A[i*n+k]) >= tmp) { // 'Avoid using other functions inside abs()?' tmp = fabs(A[i*n+k]); pivrow = i; } } // check for singular matrix if (A[pivrow*n+k] == 0.0f) { matrix_error |= SINGULAR_MATRIX; //fprintf(stdout, "Inversion failed due to singular matrix"); return; } // Execute pivot (row swap) if needed if (pivrow != k) { // swap row k with pivrow for (j = 0; j < n; j++) { tmp = A[k*n+j]; A[k*n+j] = A[pivrow*n+j]; A[pivrow*n+j] = tmp; } } pivrows[k] = pivrow; // record row swap (even if no swap happened) tmp = 1.0f/A[k*n+k]; // invert pivot element A[k*n+k] = 1.0f; // This element of input matrix becomes result matrix // Perform row reduction (divide every element by pivot) for (j = 0; j < n; j++) { A[k*n+j] = A[k*n+j]*tmp; } // Now eliminate all other entries in this column for (i = 0; i < n; i++) { if (i != k) { tmp = A[i*n+k]; A[i*n+k] = 0.0f; // The other place where in matrix becomes result mat for (j = 0; j < n; j++) { A[i*n+j] = A[i*n+j] - A[k*n+j]*tmp; } } } } // Done, now need to undo pivot row swaps by doing column swaps in reverse order for (k = n-1; k >= 0; k--) { if (pivrows[k] != k) { for (i = 0; i < n; i++) { tmp = A[i*n+k]; A[i*n+k] = A[i*n+pivrows[k]]; A[i*n+pivrows[k]] = tmp; } } } return; } void Matrix_Copy(int n, int m, float *C, float *A) { for (int i=0; i < n*m; i++) C[i] = A[i]; } void Matrix_print(int n, int m, float *A, const char *name) { fprintf(stdout, "%s=[", name); for (int i=0; i < n; i++) { for (int j=0; j < m; j++) { fprintf(stdout, "%5.5f", A[i*m+j]); if (j < m-1) fprintf(stdout, ", "); } if (i < n-1) fprintf(stdout, "; "); } fprintf(stdout, "]\n"); } void Vector_Print(float A[3], const char *name) { fprintf(stdout, "%s=[ ", name); for (int i=0; i < 3; i++) fprintf(stdout, "%5.5f ", A[i]); fprintf(stdout, "]\n"); return; }