之前的卡尔曼滤波程序出了问题,就在网上找了另外一个,代码是这样的
#define PI 3.14159
//角度参数
float Angle, Angle_dot; //小车最终倾斜角度、角速度
float Angle_aYZ; //由Y轴Z轴上的加速度传感器测得的数值,计算出倾斜角度
float Angle_gX; //由X轴的陀螺仪传感器测得的数值,计算出角速度
//卡尔曼参数
float Q_angle=0.01;
float Q_gyro=0.01;
float R_angle=0.003;
float dt=0.005; //dt为kalman滤波器采样时间;
char C_0 = 1;
float Q_bias, Angle_err;
float PCt_0, PCt_1, E;
float K_0, K_1, t_0, t_1;
float Pdot[4] ={0,0,0,0};
float PP[2][2] = { { 1, 0 },{ 0, 1 } };
// 卡尔曼滤波
void Kalman_Filter(float Accel,float Gyro)
{
Angle+=(Gyro - Q_bias) * dt; //先验估计
Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分
Pdot[1]=- PP[1][1];
Pdot[2]=- PP[1][1];
Pdot[3]=Q_gyro;
PP[0][0] += Pdot[0] * dt; // Pk-先验估计误差协方差微分的积分
PP[0][1] += Pdot[1] * dt; // =先验估计误差协方差
PP[1][0] += Pdot[2] * dt;
PP[1][1] += Pdot[3] * dt;
Angle_err = Accel - Angle; //zk-先验估计
PCt_0 = C_0 * PP[0][0];
PCt_1 = C_0 * PP[1][0];
E = R_angle + C_0 * PCt_0;
K_0 = PCt_0 / E;
K_1 = PCt_1 / E;
t_0 = PCt_0;
t_1 = C_0 * PP[0][1];
PP[0][0] -= K_0 * t_0; //后验估计误差协方差
PP[0][1] -= K_0 * t_1;
PP[1][0] -= K_1 * t_0;
PP[1][1] -= K_1 * t_1;
Angle += K_0 * Angle_err; //后验估计
Q_bias += K_1 * Angle_err; //后验估计
Angle_dot = Gyro - Q_bias; //输出值(后验估计)的微分=角速度
}
//倾角计算(卡尔曼融合)
void Angle_Calcu(void)
{
//------根据加速度分量测得角速度--------------------------
//不自测,加速度传感器范围设置 0 ±2g 16384 LSB/g
Angle_aYZ = atan2((Out_Data(ACCEL_YOUT_H) - 300), (Out_Data(ACCEL_ZOUT_H)-(16384-16450))) *180/PI ; //去除零点偏移,计算得到角度(弧度)
//弧度转换为度,
//-------角速度-------------------------
//不自测,陀螺仪测量范围设置 0 ±250°/s 131LSB/(°/s) 0.00763358 (°/s)/LSB
Angle_gX = (Out_Data(GYRO_XOUT_H)-0) *0.00763358 ;//0为补偿量,在静止是测得的角速度为0LSB;
//-------卡尔曼滤波融合-----------------------
Kalman_Filter(Angle_aYZ - 0, Angle_gX - 0); //卡尔曼滤波计算倾角,减去零点偏移,
}
应该来说就是可以很好的检测出我的小车的倾斜角度,但是我实际拿车倾斜一个30度左右的时候,输出的角度几乎没什么变化没得,都是0度,但是如果我放一个大一些的好比80度角度就可以检测到,不知道是什么原因,大家帮忙看看吧,几乎被这个问题缠绕7,8个小时了,我看了6050的检测数据还是非常灵敏的。理应不会出现检测断层的。
我要赚赏金
