CMSIS Matrix Functions 矩陣運算
之前寫的基於 C 語言矩陣運算實際在微控制器上做 kalman 有些問題,不知道是因為 malloc 用太多或是反矩陣求解問題,目前打算先用 CMSIS 提供的矩陣運算替代,之後在繼續找問題,如果 CMSIS DSP 庫效能好的話,或許就直接繼續使用了。
目前 CMSIS MatrixFunctions 只有提供下面幾種運算 ( 複數矩陣因為用不到所以沒有放入 )
arm_mat_init_f32 /* 初始化 */
arm_mat_add_f32 /* 加法 */
arm_mat_sub_f32 /* 減法 */
arm_mat_trans_f32 /* 轉置 */
arm_mat_scale_f32 /* 乘常數 */
arm_mat_mult_f32 /* 乘法 */
arm_mat_inverse_f32 /* 反矩陣(flaot) */
arm_mat_inverse_f64 /* 反矩陣(double) */
上面函數除了加減法和乘常數可以存回自己外,其他都無法存回自己,像是
status = arm_mat_init_f32(matrixA1, matrixA2, matrixA1); /* matrixA1 = matrixA1 + matrixA2 ... OK */
status = arm_mat_inverse_f32(matrixI, matrixI); /* matrixI = inv(matrixI) ... ERROR */
以及為了加入之前多寫的一些功能,diag、取部分矩陣等功能,所以就把原本 CMSIS 做擴增,並且實現乘法、反矩陣等函數可以存回原矩陣的功能。新的矩陣函數庫重新定義原本的矩陣型態
...
typedef arm_matrix_instance_f32 matrix_t;
typedef arm_matrix_instance_f64 matrix64_t;
...
並為了實現存回原本矩陣的功能,加入的預先分配的空間,空間大小以 float64 為主,並定義為最大可以運算的反矩陣維度兩倍,預設是最大可以運算 12x12 的反矩陣,所以如果是計算 flaot32 反矩陣,則可以最大實現 24x24 的反矩陣運算,依微控制器的狀況作調整。
#ifdef USE_MATRIX_BUFFER
#define MATRIX_MAX_DIMENSION ((uint32_t)12)
#define MATRIX_MAX_SIZE ((uint32_t)144) /* MATRIX_MAX_DIMENSION ^ 2 */
#define MATRIX_BUF_SIZE ((uint32_t)MATRIX_MAX_SIZE << 1)
static float64_t matrixBuf[MATRIX_BUF_SIZE] = {0};
#endif
目前實現了下面這些功能
void Matrix_Clear( matrix_t *pMatrix );
void Matrix_Init( matrix_t *pMatrix, float32_t *pArray, uint16_t rows, uint16_t cols );
arm_status Matrix_Copy( matrix_t *pMatrix, const matrix_t *pMatrixC );
arm_status Matrix_SetData( matrix_t *pMatrix, uint16_t rows, uint16_t cols, float32_t data );
arm_status Matrix_GetData( const matrix_t *pMatrix, uint16_t rows, uint16_t cols, float32_t *data );
arm_status Matrix_SetDiag( matrix_t *pMatrix, float32_t data );
arm_status Matrix_GetDiag( matrix_t *pMatrix, matrix_t *pMatrixD );
arm_status Matrix_SetMatrix( matrix_t *pMatrix, matrix_t *pMatrixS, uint16_t rows_pos, uint16_t cols_pos );
arm_status Matrix_GetMatrix( matrix_t *pMatrixG, matrix_t *pMatrix, uint16_t rows_pos, uint16_t cols_pos );
arm_status Matrix_Add( matrix_t *pMatrix, const matrix_t *pMatrixA1, const matrix_t *pMatrixA2 );
arm_status Matrix_Sub( matrix_t *pMatrix, const matrix_t *pMatrixS1, const matrix_t *pMatrixS2 );
arm_status Matrix_Mult( matrix_t *pMatrix, const matrix_t *pMatrixM1, const matrix_t *pMatrixM2 );
arm_status Matrix_MultScale( matrix_t *pMatrix, const matrix_t *pMatrixM, float32_t scale );
arm_status Matrix_Trans( matrix_t *pMatrix, const matrix_t *pMatrixT );
arm_status Matrix_Inv( matrix_t *pMatrix, const matrix_t *pMatrixI );
arm_status Matrix_Inv64( matrix_t *pMatrix, const matrix_t *pMatrixI );
void Matrix_Print( matrix_t *pMatrix );
void Matrix_Print64( matrix64_t *pMatrix );
void Matrix_PrintInfo( matrix_t *pMatrix );
之後有空再補上行列式以及完善乘法
詳細的程式可以參考下面,使用 CMSIS 做擴增,在其他不同型號或廠家的微控制器上應該都可以很容易做移植,且不失效能。
https://github.com/KitSprout/KDWM1000/tree/master/Software/KDWM_ApplicationSTD_matrixOperation/Program