• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

移动机器人技术(7) — 卡尔曼滤波原理与仿真

人工智能 Techblog of HaoWANG 1385次浏览 0个评论

基本概念:

1、状态方程:

    某一时刻的状态用Xt表示,它是一个列向量,表征了当前位置Pt和当前速度Vt;上一时刻位置Pt-1和上一时刻速度Vt-1,由于卡尔曼滤波器是时域下的线性滤波器,故可以对状态矢量Xt进行改写:

  • 状态预测公式:

,x^ 表示预测值或推测值,非实际值

  • 状态转移矩阵Ft, 表示如何从上一时刻的状态来推测当前时刻的状态:

          

  • 控制矩阵B,表示控制量U如何作用与当前状态:

            

    有了状态预测公式我们就可以推测当前时刻的状态,但是我们知道所有的推测都是包含噪声的,噪声越大,则不确定性就越大,准确度越低;如何衡量这种不确定性的大小呢,协方差矩阵可以完成这项表征任务。

2.协方差矩阵 :

    对于一维包含噪声的数据,它的分布可以近似地用高斯分布来表示:

    期望值即为预测的输出值,而其他离散的点就是噪声点,不难发现,噪声点的离散程度会影响样本的均值与方差,这也就导致了状态预测出现了偏差。

    二维包含噪声数据,它在x,y轴均满足高斯分布,则:

    (1) x,y独立同分布          (2) x,y正相关             (3) x,y负相关

 

    因此,二维问题不能简单的用两个维度的高斯分布来表征,还需要考虑两个维度之间的相关性,即协方差。

协方差矩阵可以表示为:

    在卡尔曼滤波器中,所有关于噪声或不确定性的表征,都要用到协方差矩阵。在小汽车的例子中,每一个时刻的状态不确定性都是由协方差矩阵P来表示,那么,如何让这种不确定性在每一个时刻进行传递呢?方法就是让协方差矩阵乘以一个状态转换矩阵。

     

    值得注意的是,我们的预测模型也不是绝对准确的,它也存在一些不确定性或者误差,因此,需要将模型引入的不确定性考虑在内。

上式描述了,不确定性在不同时刻的传递特性。

 

    假设在小车的一端,有一个观测器用来观测小车的每一个时间点的位置,这个观测值记为标量Zt,状态向量Xt为列向量

    则Zt可以用Xt表示为:

                      

 由于观测值Z存在观测误差,引入了不确定性,用v来表示这种不确定性。

3.多传感器融合策略:

 

 假设观测器不止一个或一种,例如:激光测距仪+IMU+红外等等,因此,观测值Z就成了一个多维的列向量,它包含了多个观测器的观测值。而每一个测量值,都只是真实状态的不完全表征,我们可以从几种不完全的表征中推断出真实的状态,而卡尔曼滤波器的数据融合功能,正是在测量矩阵中体现出来的。我们已经有了观测量Z和它的协方差矩阵R,那么如何将他们整合至系统状态估计呢?上述,已经得到了带偏差的状态估计值:假设观测器不止一个或一种,例如:激光测距仪+IMU+红外等等,因此,观测值Z就成了一个多维的列向量,它包含了多个观测器的观测值。而每一个测量值,都只是真实状态的不完全表征,我们可以从几种不完全的表征中推断出真实的状态,而卡尔曼滤波器的数据融合功能,正是在测量矩阵中体现出来的。

         … (1)

  那么,在带偏差估计值得基础上,加上一个修正值便可以得到最佳估计值:

其中,表示观测值Z与估计值之间的残差,Kt是卡尔曼系数,实际上它也是一个矩阵。

    

卡尔曼系数作用:

  1. 权衡 预测状态协方差矩阵P与观察量的协方差R的大小,来决定预测模型和观测模型的置信区间。若相信预测模型大于观测模型,残差的权重就会小一点;若相信观测模型大于预测模型,则残差权重就会大一点。

  2. 把残差的表现形式从观察域转换到状态域。

 

噪声协方差矩阵的更新:

    更新最佳估计值得噪声分布,这个值用于下一时刻迭代。在这一步里,状态的不确定性经过滤波而减小,而下一时刻,由于噪声的引入,状态预测的不确定性又会增加,实际上,卡尔曼滤波正是在这种波动迭代过程中找到一个权衡。

4.总结:

 

 

预测:通过上一时刻预测得到了当前时刻的状态预测值,但这并不是最佳的估计值,需要从当前时刻的观测值获得信息,校正预测值;

 

更新:将观测值引入到状态估计中,在预测值更新后,便得到了最佳的状态预测值。

 

5.MATLAB卡尔曼滤波器的实现

 

Z —匀速运动的观测值,每秒1m的速度前进;

Noise – -高斯噪声

X — 初始状态

P  — 状态协方差阵

F — 状态转移矩阵

Q — 状态转移矩阵的协方差阵,Q的方差较小,因为状态转移矩阵不易出现偏差。

H — 观测矩阵

R — 观测噪声方差

 

迭代次数100次的结果:

#include 
#include 
 
MPU6050 mpu;     //实例化一个 MPU6050 对象,对象名称为 mpu
int16_t ax, ay, az, gx, gy, gz;
 
//********************global_angle data*********************//
float Gyro_y; //Y轴陀螺仪数据暂存
float Gyro_x; //X轴陀螺仪数据暂存
float Gyro_z; //Z轴陀螺仪数据暂存
float angleAx;  
float angle6; 
float K1 = 0.05; // 对加速度计取值的权重
float Angle;   //一阶互补滤波计算出的小车最终倾斜角度
float accelz = 0;  
 
//********************angle data*********************//
 
//***************Kalman_Filter Initialiation*********************//
float P[2][2] = {
  { 1, 0 },
  { 0, 1 }
};
float Pdot[4] = { 0, 0, 0, 0};
float Q_angle = 0.001, Q_gyro = 0.005; //角度数据置信度,角速度数据置信度
float R_angle = 0.5 , C_0 = 1;
float q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;
float timeChange = 5; //滤波法采样时间间隔,单位毫秒ms
float dt = timeChange * 0.001; //注意:dt的取值为滤波器采样时间,单位秒s
//***************Kalman_Filter*********************//
 
void AngleFilter()
{
  //平衡参数
  Angle = atan2(ay , az) * 57.3;           //角度计算公式
  Gyro_x = (gx - 128.1) / 131;              //角度转换
  Kalman_Filter(Angle, Gyro_x);            //卡曼滤波
  //旋转角度Z轴参数
  if (gz > 32768) gz -= 65536;              //强制转换2g  1g
  Gyro_z = -gz / 131;                      //Z轴参数转换
  accelz = az / 16.4;
 
  angleAx = atan2(ax, az) * 180 / PI; //计算与x轴夹角
  Gyro_y = -gy / 131.00; //计算角速度
  //一阶互补滤波
  angle6 = K1 * angleAx + (1 - K1) * (angle6 + Gyro_y * dt);
}
 
kalman filter/
float angle, angle_dot;                                //平衡角度值angle,平衡角速度值angle_dot
void Kalman_Filter(double angle_m, double gyro_m)
{
  angle += (gyro_m - q_bias) * dt;
  angle_err = angle_m - angle;
  Pdot[0] = Q_angle - P[0][1] - P[1][0];
  Pdot[1] = - P[1][1];
  Pdot[2] = - P[1][1];
  Pdot[3] = Q_gyro;
  P[0][0] += Pdot[0] * dt;
  P[0][1] += Pdot[1] * dt;
  P[1][0] += Pdot[2] * dt;
  P[1][1] += Pdot[3] * dt;
  PCt_0 = C_0 * P[0][0];
  PCt_1 = C_0 * P[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 * P[0][1];
  P[0][0] -= K_0 * t_0;
  P[0][1] -= K_0 * t_1;
  P[1][0] -= K_1 * t_0;
  P[1][1] -= K_1 * t_1;
  angle += K_0 * angle_err; //角度, angle
  q_bias += K_1 * angle_err;
  angle_dot = gyro_m - q_bias;  //角速度 angle_dot
}  // kalman filter END //
 
 
void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();
    
    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(9600);
    // initialize device
    Serial.println("Initializing I2C devices...");
    mpu.initialize();
    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(mpu.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
} // setup END
 
void loop() {
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);     //IIC获取MPU6050六轴数据 ax ay az gx gy gz  
 
  AngleFilter();                                      //获取angle 角度和卡曼滤波
 
  Serial.print(ax);Serial.print(",");
  Serial.print(ay);Serial.print(",");
  Serial.print(az);Serial.print("---");
  Serial.print(angle);Serial.print(",");
  Serial.print(angle_dot);Serial.print(",");
  Serial.println(angle6);
  
  delay(5);
} // Loop END


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明移动机器人技术(7) — 卡尔曼滤波原理与仿真
喜欢 (0)

您必须 登录 才能发表评论!

加载中……