OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 16504|回复: 26

讨论一个卡尔曼滤波入门问题

[复制链接]

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
发表于 2015-5-6 06:25:54 | 显示全部楼层 |阅读模式
5金钱
前几天在网上看到了一个卡尔曼的介绍,自己虽然有数字信号处理的基础,但是毕竟底子比较薄弱,还没有完全弄明白详细的机理,但是大概的过程是明白了。
基本就是用上一次的最优估计值作为真实值进行数据迭代,然后不断地把数据误差缩小。
这里贴上代码,和百度文库的很像,我只是修改了迭代次数。
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
double frand() 
{      return 2*((rand()/(double)RAND_MAX) - 0.5);  //随机噪声
}  
void main()
{ float x_last=0;   
float p_last=0.02;
float Q=0.018;
float R=0.542;
float kg;
float x_mid;
float x_now;
float p_mid;
float p_now;
float z_real=0.56;//0.56
float z_measure;
float sumerror_kalman=0;
float sumerror_measure=0;
int i;
x_last=z_real+frand()*0.03;
x_mid=x_last;
for(i=0;i<400;i++)
{ x_mid=x_last;    //x_last=x(k-1|k-1),x_mid=x(k|k-1)
p_mid=p_last+Q;  //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
kg=p_mid/(p_mid+R); //kg为kalman filter,R为噪声
z_measure=z_real+frand()*0.03;//测量值
x_now=x_mid+kg*(z_measure-x_mid);//估计出的最优值
p_now=(1-kg)*p_mid;//最优值对应的covariance
printf("Real     position: %6.3f \n",z_real);  //显示真值
        printf("Mesaured position: %6.3f [diff:%.3f]\n",z_measure,fabs(z_real-z_measure));  //显示测量值以及真值与测量值之间的误差
        printf("Kalman   position: %6.3f [diff:%.3f]\n",x_now,fabs(z_real - x_now));  //显示kalman估计值以及真值和卡尔曼估计值的误差
        sumerror_kalman += fabs(z_real - x_now);  //kalman估计值的累积误差
        sumerror_measure += fabs(z_real-z_measure);  //真值与测量值的累积误差
        p_last = p_now;  //更新covariance值
        x_last = x_now;  //更新系统状态值
}
printf("总体测量误差     : %f\n",sumerror_measure);  //输出测量累积误差
    printf("总体卡尔曼滤波误差: %f\n",sumerror_kalman);   //输出kalman累积误差
    printf("卡尔曼误差所占比例: %d%% \n",100-(int)((sumerror_kalman/sumerror_measure)*100)); 
}
运行出来的结果是,比20次的迭代数据误差波动要小一些,但并不是小很多。这是400次的迭代结果。rand是伪随机函数,过两天我把用STM32随机数发生器做的测试代码发上来,顺便测试一下效率。不过PC机跑了一下,感觉不怎么好。
现在一个问题是,真实值我是不知道的,那么刚开始的输入我应该怎么写呢?是0还是随便的一个数据,希望能和大家一起讨论一下!谢谢!

Delta-sigma数据转换器
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-5-6 23:14:42 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-5-8 22:40:51 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子哥,问题已经找到。
卡尔曼滤波是一种最优滤波方案,只是在均方误差最小的准则下,加入了一个方差最小的准则。
实测的波动还是有的不过在±1度左右,做飞行器的话问题应该不是很大。
估计还是估计,毕竟永远无法测得真实值。这种随机迭代,基本上要达到3000多次以上好像才会收敛。贴上代码:

void Kalman_yaw()
{
static float x_last=0;//????????????????????
static float p_last=0.02;
static float Q=0.018;
static float R=0.542;
static float Kg;//Kalman Gain;
static float x_mid;
static float x_now;
static float p_mid;
static float p_now;
 //float z_real=Copter.roll;
static float z_measure;
// float sumerror_kalman=0;
//float sumerror_measure=0;
//int i=0;
// x_last=z_real;
//x_mid=x_last;

x_mid=x_last;
p_mid=p_last+Q;
Kg=p_mid/(p_mid+R);
z_measure=Copter.yaw;
x_now=x_mid+Kg*(z_measure-x_mid);
p_now=(1-Kg)*p_mid;
p_last=p_now;
x_last=x_now;//??????????????×÷??×????
Copter.yaw=x_now;//?ü?? ·????÷?ó??????????×÷?????????ù??
}
这里的Copter.yaw是利用6050读出来的yaw.数据波动还行,在0.01度这样
Delta-sigma数据转换器
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-5-8 22:41:42 | 显示全部楼层
希望能做一个自适应的东西,不知道论坛里的人有没有新的想法
Delta-sigma数据转换器
回复

使用道具 举报

5

主题

68

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
114
金钱
114
注册时间
2014-12-25
在线时间
2 小时
发表于 2015-5-13 11:26:06 | 显示全部楼层
我们可以深入交流一下卡尔曼滤波的含义及其实现,一般的处理在要求比较高的飞行器上还欠缺。
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-5-25 19:05:25 | 显示全部楼层
回复【5楼】惯性坐标系:
---------------------------------
实验我已经做完了,感觉加入的效果并没有6050本身的DMP好。
因为是一个估计,卡尔曼就是用上次的估计值作为准确值反复迭代最后毕竟真实值的
这个好处是在毕竟的同时相比较于维纳滤波器多一个方差最小的有点,不过还是有波动的。波动比较小,最后在一个收敛区间里面反复波动了。
目前了解的就是这些。在自动控制这块倒是着实很头疼。不知道该用什么方法了。
Delta-sigma数据转换器
回复

使用道具 举报

53

主题

608

帖子

0

精华

高级会员

Rank: 4

积分
890
金钱
890
注册时间
2013-3-29
在线时间
18 小时
发表于 2015-5-25 22:46:49 | 显示全部楼层
回复【6楼】玉面飞龙:
---------------------------------
以前想搞卡尔曼,发现完全搞不懂。。。。。。。
学电子,学音乐!!
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-5-26 17:06:45 | 显示全部楼层
回复【7楼】XINSI:
---------------------------------
原理仔细想想还是能够明白的,
就是把上一次的估计值当做真实的值反复迭代,最终能够逼近。
但是传感器自己出了有噪声,还有一些量化误差的东西,这些会导致最后的数据是在一个区间里面波动。
至于为什么能够这样做,那就有相应的理论推导,证明我们这样做是可以的。
优点是不仅能达到和维纳滤波器一样的效果,同时数据波动的方差还是最小的。
缺点是需要迭代一定的周期,这个对于快速系统和慢的传感器是不合适的。
Delta-sigma数据转换器
回复

使用道具 举报

70

主题

231

帖子

0

精华

高级会员

Rank: 4

积分
976
金钱
976
注册时间
2013-8-14
在线时间
103 小时
发表于 2015-6-1 08:52:11 | 显示全部楼层
你这不是卡尔曼吧,你这是互补滤波吧
谢谢!
回复

使用道具 举报

17

主题

69

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
259
金钱
259
注册时间
2015-3-9
在线时间
67 小时
发表于 2015-6-9 23:23:23 | 显示全部楼层
楼主有没有开动过电机测试dmp抗干扰效果怎么样,我移植的,1/2油门就开始大幅度波动了有3. 4度,不知楼主是否遇到过类似问题
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-6-22 13:13:10 | 显示全部楼层
回复【9楼】今天天气不好:
---------------------------------
和互补滤波不一样的,上面有更新的。
Delta-sigma数据转换器
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-6-22 13:13:57 | 显示全部楼层
回复【10楼】979653421@qq.com:
---------------------------------
 没,电机还没测试,不过如果是抗干扰效果不好,是不是EMI问题?硬件设计,可能要多注意下把。
Delta-sigma数据转换器
回复

使用道具 举报

17

主题

69

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
259
金钱
259
注册时间
2015-3-9
在线时间
67 小时
发表于 2015-6-22 13:41:54 | 显示全部楼层
回复【12楼】玉面飞龙:
---------------------------------
你说的emi是指滤波吗
回复

使用道具 举报

14

主题

225

帖子

3

精华

高级会员

Rank: 4

积分
623
金钱
623
注册时间
2014-7-8
在线时间
26 小时
发表于 2015-6-26 23:05:52 | 显示全部楼层
回复【9楼】今天天气不好:
---------------------------------
他这个最后效果跟互补没有区别呢~~~~~~~最后叠来叠去参数就固定了。。。。。跟互补就一样了。。。。
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-7-9 21:01:37 | 显示全部楼层
回复【14楼】2013的弹子球:
---------------------------------
可能和阶数有关吧,我感觉这个东西还是在处理随机问题上,效果要好些。
6050那个传感器也不怎么样,做怎么样效果也不会好到哪里去。
Delta-sigma数据转换器
回复

使用道具 举报

21

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2014-11-13
在线时间
20 小时
 楼主| 发表于 2015-7-9 21:03:03 | 显示全部楼层
回复【13楼】979653421@qq.com:
---------------------------------
也有可能是震动问题了。
Delta-sigma数据转换器
回复

使用道具 举报

9

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2015-4-22
在线时间
0 小时
发表于 2015-8-10 11:43:22 | 显示全部楼层
回复【3楼】玉面飞龙:
---------------------------------
// /*卡尔曼滤波参数*/
 static float angle, angle_dot;  //外部需要引用的变量
static float Q_angle=0.001, Q_gyro=0.003, R_angle=0.5, dt=0.01;   //注意:dt的取值为kalman滤波器采样时间;, dt=0.01
static float [2][2] = {{ 1, 0 },{ 0, 1 }};
static float dot[4] ={0,0,0,0};
static char C_0 = 1;
static float q_bias, angle_err, Ct_0, Ct_1, E, K_0, K_1, t_0, t_1;

void Kalman_Filter(float angle_m,float gyro_m)
{
angle+=(gyro_m-q_bias) * dt;//先验估计

Pdot[0]=Q_angle - [0][1] - [1][0];// k-' 先验估计误差协方差的微分
Pdot[1]=-P[1][1];
Pdot[2]=-P[1][1];
Pdot[3]=Q_gyro;

P[0][0] += dot[0] * dt;// k- 先验估计误差协方差微分的积分 = 先验估计误差协方差
P[0][1] += dot[1] * dt;
P[1][0] += Pdot[2] * dt;
P[1][1] += Pdot[3] * dt;

angle_err = angle_m - angle;//zk-先验估计

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;//Kk
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;//后验估计
q_bias += K_1 * angle_err;//后验估计
angle_dot = gyro_m-q_bias;//输出值(后验估计)的微分 = 角速度
//return angle;
//return angle_dot;
}

师父,我的卡尔曼滤波的波形过冲,怎么处理啊?
回复

使用道具 举报

9

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2015-4-22
在线时间
0 小时
发表于 2015-8-10 11:44:43 | 显示全部楼层
// /*卡尔曼滤波参数*/
 static float angle, angle_dot; //外部需要引用的变量
static float Q_angle=0.001, Q_gyro=0.003, R_angle=0.5, dt=0.01;   //注意:dt的取值为kalman滤波器采样时间;, dt=0.01
static float P[2][2] = {{ 1, 0 },{ 0, 1 }};
static float Pdot[4] ={0,0,0,0};
static char C_0 = 1;
static float q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;

void Kalman_Filter(float angle_m,float gyro_m)
{
angle+=(gyro_m-q_bias) * dt;//先验估计

Pdot[0]=Q_angle - P[0][1] - P[1][0];// Pk-' 先验估计误差协方差的微分
Pdot[1]=-P[1][1];
Pdot[2]=-P[1][1];
Pdot[3]=Q_gyro;

P[0][0] += Pdot[0] * dt;// Pk- 先验估计误差协方差微分的积分 = 先验估计误差协方差
P[0][1] += Pdot[1] * dt;
P[1][0] += Pdot[2] * dt;
P[1][1] += Pdot[3] * dt;

angle_err = angle_m - angle;//zk-先验估计

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;//Kk
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;//后验估计
q_bias += K_1 * angle_err;//后验估计
angle_dot = gyro_m-q_bias;//输出值(后验估计)的微分 = 角速度
//return angle;
//return angle_dot;
}


回复

使用道具 举报

9

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
337
金钱
337
注册时间
2016-4-15
在线时间
126 小时
发表于 2016-8-10 11:06:00 | 显示全部楼层
各位大神,要怎么验证精度啊?
回复

使用道具 举报

0

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2016-11-24
在线时间
8 小时
发表于 2017-4-6 09:44:58 | 显示全部楼层
卡尔曼滤波跟迭代没什么关系,他是通过观测误差最优化估计线性系统误差的方法。你这个如果是卡尔曼滤波的话,我想问问你的状态方程是什么?量测方程呢?
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
发表于 2017-5-8 16:58:48 | 显示全部楼层
小白110 发表于 2015-8-10 11:44
// /*卡尔曼滤波参数*/
&nbsp;static float angle, angle_dot;                 //外部需要引用的变量
static float Q_a ...

请教一下这段程序中间,Pdot矩阵和P矩阵那部分运算是什么意思啊
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

27

主题

132

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
327
金钱
327
注册时间
2018-7-20
在线时间
117 小时
发表于 2018-8-24 21:21:44 | 显示全部楼层
帮顶
回复

使用道具 举报

16

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2018-4-9
在线时间
111 小时
发表于 2018-8-27 21:40:00 | 显示全部楼层
小白110 发表于 2015-8-10 11:44
// /*卡尔曼滤波参数*/
&nbsp;static float angle, angle_dot;                 //外部需要引用的变量
static float Q_a ...

请问这是什么软件,是不是也能观察PID的优化程度
回复

使用道具 举报

0

主题

8

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2017-10-16
在线时间
10 小时
发表于 2018-11-11 17:22:29 | 显示全部楼层
惯性坐标系 发表于 2015-5-13 11:26
我们可以深入交流一下卡尔曼滤波的含义及其实现,一般的处理在要求比较高的飞行器上还欠缺。

你好,能交流一下使用卡尔曼滤波的一些心得吗,就是在四轴上用的
企鹅1375127228
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2019-11-13
在线时间
2 小时
发表于 2020-5-25 11:17:35 | 显示全部楼层
小白110 发表于 2015-8-10 11:43
回复【3楼】玉面飞龙:
---------------------------------
//&nbsp;/*卡尔曼滤波参数*/
&nbsp;static&nbsp; ...

滤波时间没调好
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2019-11-13
在线时间
2 小时
发表于 2020-5-25 13:50:00 | 显示全部楼层
小白110 发表于 2015-8-10 11:44
// /*卡尔曼滤波参数*/
&nbsp;static float angle, angle_dot;                 //外部需要引用的变量
static float Q_a ...

这个能将角速度滤到什么程度?能达到0.01精度吗?
回复

使用道具 举报

10

主题

48

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
298
金钱
298
注册时间
2016-4-9
在线时间
97 小时
发表于 2020-6-11 13:56:33 | 显示全部楼层
Wanhh 发表于 2020-5-25 11:17
滤波时间没调好

滤波时间是常数,和这段代码运行周期对应,不需要调
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 17:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表