237 lines
7.0 KiB
C#
237 lines
7.0 KiB
C#
namespace RobotNet10.RobotApp.Motion;
|
|
|
|
/// <summary>
|
|
/// Helper class for matrix operations used in Extended Kalman Filter
|
|
/// Implements basic operations for small matrices (up to 6x6)
|
|
/// </summary>
|
|
public static class MatrixHelper
|
|
{
|
|
/// <summary>
|
|
/// Create identity matrix of size n x n
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create zero matrix of size rows x cols
|
|
/// </summary>
|
|
public static double[,] CreateZeros(int rows, int cols)
|
|
{
|
|
return new double[rows, cols];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create diagonal matrix from array of diagonal values
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Matrix multiplication: C = A * B
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Matrix addition: C = A + B
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Matrix subtraction: C = A - B
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Matrix transpose: B = A^T
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Matrix scalar multiplication: B = scalar * A
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Matrix inverse using Gauss-Jordan elimination (for small matrices)
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy matrix
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Print matrix (for debugging)
|
|
/// </summary>
|
|
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();
|
|
}
|
|
}
|