通用型二阶卡尔曼滤波算法
由于c语言不支持矩阵运算,而卡尔曼滤波算法又涉及到矩阵的运算,因此我写了个通用性比较强的矩阵运算“库”,有了这个,就行轻松完成矩阵叉乘、点乘、求转置、二阶矩阵求逆等操作了。
函数列表:
void Matrix_Init(float *pr , int hang , int lie );
void Matrix_Init_One (float *matrix , int hang , int lie );
void Matrix_Init_eye (float *matrix , int hang , int lie );
void Matrix_Mul_Cross(float *pre ,int hang_pre , int lie_pre , float *later,int hang_lat , int lie_lat ,float *res );
void Matrix_Mul_dot(float *matrix , float mul ,int hang , int lie ,float *res );
void Matrix_T(float *matrix ,int hang , int lie ,float *res );
void Matrix_NI(float *matrix_a ,int scale,float *res );
void Matrix_Add(float *matrix_a ,float *matrix_b ,int hang , int lie ,float *res );
void Matrix_deduct(float *matrix_a ,float *matrix_b ,int hang , int lie ,float *res );
基于我自己写的矩阵运算库的二阶卡尔曼滤波源码:
公式如下:
/速度位置二阶系统
void Horizon_klm_estimate(float Pos , float Vel ,Second_order_sys * sys,float delta_T)
{
sys->A_matrix[0][1] = delta_T;
sys->y_oberve[0][0] = Pos ;
sys->y_oberve[1][0] = Vel ;
sys->x_state[0][0]= sys->x_state[0][0] + delta_T * sys->x_state[1][0] ;/step1 predict x
///step2 predict P
float P_temp[2][2] ,P_temp2[2][2];
float A_T_Matrix[2][2] ;
Matrix_Mul_Cross((float *)(&sys->A_matrix) , 2,2 , (float *)&(sys->p_variance) , 2 , 2 ,(float *)&P_temp) ;
Matrix_T((float *)&(sys->A_matrix),2,2,(float *)&A_T_Matrix);
Matrix_Mul_Cross((float *)&P_temp , 2,2 , (float *)&A_T_Matrix , 2 , 2 ,(float *)&P_temp2) ;
Matrix_Add((float *)&P_temp2 , (float *)&(sys->Q_variance) ,2,2, (float *)&(sys->p_variance)) ;
///step3 calculate K
float matrix3_NI[2][2] ;
float K_temp[2][2];
Matrix_Add((float *)&(sys->p_variance) , (float *)&(sys->R_variance) ,2,2, (float *)&K_temp) ;
Matrix_NI((float *)&K_temp,2,(float *)&matrix3_NI) ;
Matrix_Mul_Cross((float *)&(sys->p_variance),2,2,(float *)&matrix3_NI ,2,2,(float *)&(sys->K_gain));
///step4 correct x
float Z_delta[2][1] ;
float statue_correct[2][1] ;
Z_delta[0][0] = sys->x_state[0][0] - sys->y_oberve[0][0];
Z_delta[1][0] = sys->x_state[1][0] - sys->y_oberve[1][0];
Matrix_Mul_Cross((float *)&(sys->K_gain),2,2,(float *)&Z_delta ,2,1,(float *)&statue_correct);
sys->x_state[0][0] = sys->x_state[0][0] - statue_correct[0][0];
sys->x_state[1][0] = sys->x_state[1][0] - statue_correct[1][0];
/// step5 update P
float P_update[2][2] ;
Matrix_Init_eye((float *)&P_temp ,2,2);
Matrix_deduct((float *)&P_temp, (float *)&(sys->K_gain) ,2,2,(float *)&P_temp);
Matrix_Mul_Cross((float *)&P_temp,2,2,(float *)&(sys->p_variance) ,2,2,(float *)&P_update);
Matrix_Mul_dot((float *)&P_update,1,2,2,(float *)&(sys->p_variance));
}
卡尔曼滤波结构体:
typedef struct
{
float x_state[2][1]; //状态
float y_oberve[2][1]; //观测
float A_matrix[2][2]; //驱动
float p_variance[2][2]; //协方差
float K_gain[2][2]; //卡尔曼增益
float R_variance[2][2]; //观测误差方差
float Q_variance[2][2]; //过程误差方差
}Second_order_sys;;
这里用二维数组当做矩阵,左边是行数,右边是列数,[2][1]就是两行一列的矩阵。
函数调用:
int Horizon_counter =0;
void Horizon_POS_estimate()
{
Horizon_PV.E_Vel = Hubu_filter(0.75,LC306_flow.flow_x,UAV_GPS_Home.E_speed);
Horizon_PV.N_Vel = Hubu_filter(0.75,LC306_flow.flow_y,UAV_GPS_Home.N_speed);
Horizon_PV.E_pos = UAV_GPS_Home.E_deviation;
Horizon_PV.N_pos = UAV_GPS_Home.N_deviation;
Horizon_counter++;
if(Horizon_counter>100)
{
Horizon_counter=0;
}
if(Horizon_counter % 5 ==0)
{
Horizon_klm_estimate(UAV_GPS_Home.E_deviation , Horizon_PV.E_Vel ,&Horizon_E_klm ,0.04);
Horizon_klm_estimate(UAV_GPS_Home.N_deviation , Horizon_PV.N_Vel ,&Horizon_N_klm ,0.04);
}
}
代码量少,易懂,我自己觉得挺好用的。
如果想改成其他形式的系统,就只要改A矩阵以及H矩阵。
如果想用我这个矩阵运算库的,请看我上传的资源。