namespace RobotNet10.RobotApp.Motion; /// /// Helper class for matrix operations used in Extended Kalman Filter /// Implements basic operations for small matrices (up to 6x6) /// public static class MatrixHelper { /// /// Create identity matrix of size n x n /// public static double[,] CreateIdentity(int n) { var result = new double[n, n]; for (int i = 0; i < n; i++) result[i, i] = 1.0; return result; } /// /// Create zero matrix of size rows x cols /// public static double[,] CreateZeros(int rows, int cols) { return new double[rows, cols]; } /// /// Create diagonal matrix from array of diagonal values /// public static double[,] CreateDiagonal(double[] diagonal) { int n = diagonal.Length; var result = new double[n, n]; for (int i = 0; i < n; i++) result[i, i] = diagonal[i]; return result; } /// /// Matrix multiplication: C = A * B /// public static double[,] Multiply(double[,] a, double[,] b) { int aRows = a.GetLength(0); int aCols = a.GetLength(1); int bRows = b.GetLength(0); int bCols = b.GetLength(1); if (aCols != bRows) throw new ArgumentException($"Matrix dimensions incompatible for multiplication: ({aRows}x{aCols}) * ({bRows}x{bCols})"); var result = new double[aRows, bCols]; for (int i = 0; i < aRows; i++) { for (int j = 0; j < bCols; j++) { double sum = 0.0; for (int k = 0; k < aCols; k++) sum += a[i, k] * b[k, j]; result[i, j] = sum; } } return result; } /// /// Matrix addition: C = A + B /// public static double[,] Add(double[,] a, double[,] b) { int rows = a.GetLength(0); int cols = a.GetLength(1); if (rows != b.GetLength(0) || cols != b.GetLength(1)) throw new ArgumentException("Matrix dimensions must match for addition"); var result = new double[rows, cols]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[i, j] = a[i, j] + b[i, j]; return result; } /// /// Matrix subtraction: C = A - B /// public static double[,] Subtract(double[,] a, double[,] b) { int rows = a.GetLength(0); int cols = a.GetLength(1); if (rows != b.GetLength(0) || cols != b.GetLength(1)) throw new ArgumentException("Matrix dimensions must match for subtraction"); var result = new double[rows, cols]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[i, j] = a[i, j] - b[i, j]; return result; } /// /// Matrix transpose: B = A^T /// public static double[,] Transpose(double[,] a) { int rows = a.GetLength(0); int cols = a.GetLength(1); var result = new double[cols, rows]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[j, i] = a[i, j]; return result; } /// /// Matrix scalar multiplication: B = scalar * A /// public static double[,] ScalarMultiply(double scalar, double[,] a) { int rows = a.GetLength(0); int cols = a.GetLength(1); var result = new double[rows, cols]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[i, j] = scalar * a[i, j]; return result; } /// /// Matrix inverse using Gauss-Jordan elimination (for small matrices) /// public static double[,] Inverse(double[,] a) { int n = a.GetLength(0); if (n != a.GetLength(1)) throw new ArgumentException("Matrix must be square for inversion"); // Create augmented matrix [A | I] var augmented = new double[n, 2 * n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) augmented[i, j] = a[i, j]; augmented[i, n + i] = 1.0; } // Gauss-Jordan elimination for (int i = 0; i < n; i++) { // Find pivot int maxRow = i; for (int k = i + 1; k < n; k++) { if (Math.Abs(augmented[k, i]) > Math.Abs(augmented[maxRow, i])) maxRow = k; } // Swap rows if (maxRow != i) { for (int k = 0; k < 2 * n; k++) (augmented[i, k], augmented[maxRow, k]) = (augmented[maxRow, k], augmented[i, k]); } // Check for singular matrix if (Math.Abs(augmented[i, i]) < 1e-10) throw new InvalidOperationException("Matrix is singular and cannot be inverted"); // Scale pivot row double pivot = augmented[i, i]; for (int j = 0; j < 2 * n; j++) augmented[i, j] /= pivot; // Eliminate column for (int k = 0; k < n; k++) { if (k != i) { double factor = augmented[k, i]; for (int j = 0; j < 2 * n; j++) augmented[k, j] -= factor * augmented[i, j]; } } } // Extract inverse from augmented matrix var result = new double[n, n]; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) result[i, j] = augmented[i, n + j]; return result; } /// /// Copy matrix /// public static double[,] Copy(double[,] a) { int rows = a.GetLength(0); int cols = a.GetLength(1); var result = new double[rows, cols]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[i, j] = a[i, j]; return result; } /// /// Print matrix (for debugging) /// public static string ToString(double[,] a, string format = "F4") { int rows = a.GetLength(0); int cols = a.GetLength(1); var sb = new System.Text.StringBuilder(); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { sb.Append(a[i, j].ToString(format)); if (j < cols - 1) sb.Append(" "); } if (i < rows - 1) sb.AppendLine(); } return sb.ToString(); } }