1、角度和弧度之间的转换公式? 
设角度为 angle,弧度为 radian 
radian = angle * pi / 180; 
angle = radian * 180 / pi; 
所以在matlab中经常设置一个参数,用于角度与弧度之间的转换:deg_rad=0.01745329252e0;

2、注意下面角度Angint的表示方法: 
Angint=[0,10,0]*deg_rad; 
则:Angint(0) = 0;Angint(1) = 0.0175;Angint(2) = 0; 
这种表示方法可以在四元数中应用: 
例如: 
q=[cos(Angint(3)/2)*sin(Angint(2)/2)*cos(Angint(1)/2)+sin(Angint(3)/2)*cos(Angint(2)/2)*sin(Angint(1)/2) 
cos(Angint(3)/2)*cos(Angint(2)/2)*sin(Angint(1)/2)-sin(Angint(3)/2)*sin(Angint(2)/2)*cos(Angint(1)/2) 
-sin(Angint(3)/2)*cos(Angint(2)/2)*cos(Angint(1)/2)+cos(Angint(3)/2)*sin(Angint(2)/2)*sin(Angint(1)/2) 
cos(Angint(3)/2)*cos(Angint(2)/2)*cos(Angint(1)/2)+sin(Angint(3)/2)*sin(Angint(2)/2)*sin(Angint(1)/2)]; 
可以用q(0)、q(1)、q(2)、q(3)来代入公式计算三轴姿态角。

3、在滤波的过程中,要明确滤波时间和采样频率;

4、IMU数据仿真分析: 
(1)先模拟加速度计和陀螺仪的真实输出: 
[ Angle,Wibb,Fb ] = imu_true_out( tt,ynong,T );%tt=tt+TT;TT=1/f为时间间隔 
注意:加速度计的输出要进行坐标转换: ao=Cnb*([0,0,g]’, 
其中:Cnb

如果你要在加速度计的输出上添加一个随机干扰(可模拟非重力加速度干扰),可以使用函数awgn();  %Add white Gaussian noise to a signal. 
ao=Cnb*([0,0,g]’+[0,awgn(0,ynong),0]’);   %如果在指点的时间内添加这种干扰,可以加一个if函数 
(2)模拟加速度计和陀螺仪的误差: 
[Gyro_b,Gyro_r,Gyro_wg,Acc_r]=imu_err_random(tt,TT,Gyro_b,Gyro_r,Gyro_wg,Acc_r);

function [Gyro_b,Gyro_r,Gyro_wg,Acc_r]=imu_err_random(t,T,Gyro_b,Gyro_r,Gyro_wg,Acc_r)

g=9.7803698;         %重力加速度    (单位:米/秒/秒)
Wie=7.292115147e-5; %地球自转角速度(单位:弧度/秒)
deg_rad=0.01745329252e0;% Transfer from angle degree to rad Da_bias=[0.001; 0.001; 0.001]*g; %加速度零偏(应与非随机性误差中的加速度零偏保持一致) Ta=1800.0; %加速度一阶马尔可夫过程相关时间
Tg=3600.0; %陀螺一阶马尔可夫过程相关时间 %%%%%%%%%%%%%%%%%%随机性误差%%%%%%%%%%%%%%%
if( t== )
Acc_r=Da_bias.*randn(,); %加速度一阶马尔可夫过程1.0e-4g Gyro_b=0.01*deg_rad/3600.0*randn(,); %随机常数0.(deg/h)
Gyro_r=0.01*deg_rad/3600.0*randn(,); %陀螺一阶马尔可夫过程0.(deg/h)
Gyro_wg=0.01*deg_rad/3600.0*randn(,);%陀螺白噪声0.(deg/h)
else
Acc_wa=sqrt(*T/Ta)*Da_bias.*randn(,);%加速度一阶马尔可夫过程白噪声
Acc_r=exp(-1.0*T/Ta)*Acc_r; %加速度一阶马尔可夫过程 Gyro_wr=0.01*sqrt(*T/Tg)*deg_rad/3600.0*randn(,);%陀螺一阶马尔可夫过程白噪声0.(deg/h)
Gyro_r=exp(-1.0*T/Tg)*Gyro_r+Gyro_wr;%陀螺一阶马尔可夫过程0.(deg/h)
Gyro_wg=0.01*deg_rad/3600.0*randn(,);%陀螺白噪声0.(deg/h)
end

然后再在while(1)中将真实值+误差值按时间序列存储在数组中以备用,如下:

while tt<=T;
[ Angle,Wibb,Fb ] = imu_true_out( tt,ynong,T );
[Gyro_b,Gyro_r,Gyro_wg,Acc_r]=imu_err_random(tt,TT,Gyro_b,Gyro_r,Gyro_wg,Acc_r);
Ture_Angle(:,kk)=Angle/deg_rad;%模拟输出的三轴姿态角
gyro(:,kk)=Wibb+Gyro_b+Gyro_r+Gyro_wg;%模拟输出的陀螺仪输出
acc(:,kk)=Fb+Acc_r;%模拟输出的加速度计输出
tt=tt+TT;
kk=kk+;%这里TT=/f=/100为采样时间间隔,f为采样频率,T为采样时间,文中设置为30s
end

5、函数randn的意思: 
R = randn(3,1);%产生3行1列的随机R矩阵,R矩阵满足方差为1,均值为0;注意这里不是说这三个数的方差为1,均值为0,而是每次运行randn时,当运行的量足够大时,所有的R(0)的方差为1,均值为0,R(1)、R(2)同理。 
例如1. randn(1) ;%生成一个随机数,要想满足方差为1,均值为0,也必须运行足够多的次数 
例如2. x = .6 + sqrt(0.1) * randn(1);%产生均值为0.6,方差为0.1的一个5*5的随机数;sqrt(0.1)对0.1进行开方,直接写0.1那这里就是表示标准差了

randi([m,n],a,b)    %[m,n] 的  a*b 随机数

6、axis()函数的用法:
axis([xmin xmax ymin ymax]);%定义x轴和y轴之间的间距

7、set()函数的用法:
plot(t,acc(,:),'linewidth',1.3);
set(gcf,'Position',[ ]); %这里的100是指生成的图片距离左下角的距离,400和300分别表示长和宽
axis([ T -4.9 2.0]);
set(gca, 'YTick', [-4.9 -2.4 -0.1 2.0])
set(gca,'fontname','宋体','fontsize',); %用于改变坐标轴坐标大小,10代表坐标大小;
xlabel('时间/s','fontname','宋体','fontsize',);%用于改变x轴标注的文字和大小;
ylabel('加速度计数据/(g)','fontname','宋体','fontsize',);%用于改变y轴标注的文字和大小;
legend('accy');%标注


8、EKF的matlab实现:

kalman的前提条件:

1)线性系统 
2)系统噪声和测量噪声服从高斯分布

卡尔曼最初提出的滤波理论只适用于线性系统,Bucy,Sunahara等人提出并研究了扩展卡尔曼滤波(Extended Kalman Filter,简称EKF),将卡尔曼滤波理论进一步应用到非线性领域。EKF的基本思想是将非线性系统线性化,然后进行卡尔曼滤波,因此EKF是一种次优滤波。其后,多种二阶广义卡尔曼滤波方法的提出及应用进一步提高了卡尔曼滤波对非线性系统的估计性能。二阶滤波方法考虑了Taylor级数展开的二次项,因此减少了由于 线性化所引起的 估计误差,但大大增加了运算量,因此在实际中反而没有一阶EKF应用广泛。 
在状态方程或测量方程为非线性时,通常采用扩展卡尔曼滤波(EKF)。EKF对非线性函数的Taylor展开式进行一阶线性化截断,忽略其余高阶项,从而将非线性问题转化为线性,可以将卡尔曼线性滤波算法应用于非线性系统中。这样一来,解决了非线性问题。EKF虽然应用于非线性状态估计系统中已经得到了学术界认可并为人广泛使用,然而该种方法也带来了两个缺点,其一是当强非线性时EKF违背局部线性假设,Taylor展开式中被忽略的高阶项带来大的 误差时,EKF算法可能会使滤波发散;另外,由于EKF在线性化处理时需要用雅克比(Jacobian)矩阵,其繁琐的计算过程导致该方法实现相对困难。所以,在满足 线性系统、高斯白噪声、所有随机变量服从高斯(Gaussian)分布这3个假设条件时,EKF是最小方差准则下的次优滤波器,其性能依赖于局部非线性度。

%---------------------------EKF算法实现------------------------------------
for k=:kk-
%---------------不考虑噪声时,根据状态方程预测当前值--------------------------
Ag=AntiMatrix(gyro(:,k-));%计算陀螺仪输出的反对称矩阵
Ag=[-Ag, gyro(:,k-)
-gyro(:,k-)', 0];
Ag=expm(Ag//f); %系统一步转移矩阵 Tg=AntiMatrix(q(:,k-));
Tg=[Tg+eye()*q(,k-)
-(q(:,k-))'];
Tg=-0.5*Tg/f; %计算系统噪声矩阵 q(:,k)=Ag*q(:,k-);%计算姿态四元数的状态估计值 %------------------------计算此时的方差-------------------------------------
p=Ag*p*Ag'+Tg*Q*Tg';
%------------------------计算卡尔曼增益-------------------------------------
r=[,,g]';
qv=q(:,k); %状态方程四元数矢量部分
qs=q(,k); %状态方程四元数标量部分 %计算量测向量
Hg=*[qv'*r*eye(3)+qv*r'-r*qv'+qs*AntiMatrix(r),qs*r+AntiMatrix(r)*qv]; Kg=p*Hg'*(Hg*p*Hg'+R)^-;%计算卡尔曼增益 %------------------根据当前量测值,对预测更新--------------------------------
Cnb=(qs^-qv'*qv)*eye(3)+2*qv*qv'-*qs*AntiMatrix(qv);
h=Cnb*r;
q(:,k)=q(:,k)+Kg*(acc(:,k)-h); %-----------------------更新估计值方差--------------------------------------
p=(eye()-Kg*Hg)*p; %---------------------------归一化-----------------------------------------
h(k)=sqrt(q(,k)^+q(,k)^+q(,k)^+q(,k)^);
q(:,k)=q(:,k)/h(k); %----------------------------姿态角计算-------------------------------------
%补偿后(-,)180会出现奇点,-180度正常,但是不影响,实际上-180和180是重合的 T33=(q(,k))^-(q(,k))^-(q(,k))^+(q(,k))^;
T13=*(q(,k)*q(,k)-q(,k)*q(,k));
T23=*(q(,k)*q(,k)+q(,k)*q(,k));
if T33> %根据物理意义不可能出现0
ANGLE0(,k)=-/pi*atan(T13/T33);
else
ANGLE0(,k)=/pi*(-pi*sign(T13)-atan(T13/T33));
end ANGLE0(,k)=/pi*asin(T23); %俯仰角,绕X轴转动 end
注意此程序的特点,需关注以下问题:

1)如何根据陀螺仪输出计算系统一步转移矩阵:

 


2)如何根据四元数计算系统的噪声矩阵:;

四元数卡尔曼滤波算法的状态方程(由陀螺仪输出计算得到): ;

四元数卡尔曼滤波的时间输出过程如下:

3)如何根据四元数计算系统的量测向量; 
Hg=2*[qv’*r*eye(3)+qv*r’-r*qv’+qs*AntiMatrix(r),qs*r+AntiMatrix(r)*qv];

4)如何根据四元数计算系统的转态转移矩阵; 
Cnb=(qs^2-qv’*qv)*eye(3)+2*qv*qv’-2*qs*AntiMatrix(qv); 
注意对预测值(即四元数)的更新过程: 
q(:,k)=q(:,k)+Kg*(acc(:,k)-h); 
因为是由加速度计构建系统的量测方程的,acc(:,k)表示加速度计的量测值,h=Cnb*r为先验估计(不考虑误差,r=[0,0,g]’;),这里是将地理坐标系转化为导航坐标系。 
实际上,kalman的5个公式一部分是从状态方程和量测方程上获取的。

5)如何根据四元数计算系统的姿态角:

6)反对称矩阵用函数表示AntiMatrix():     
function [A] = AntiMatrix(B)
A=[,-B(,),B(,)
B(,),,-B(,)
-B(,),B(,),];
end

----------------------------------------------------------------------分割线----------------------------------------------------------------------------

Z=(:); %观测值
noise=randn(,); %方差为1的高斯噪声
Z=Z+noise; X=[; ]; %状态
Sigma = [ ; ]; %状态协方差矩阵
F=[ ; ]; %状态转移矩阵
Q=[0.0001, ; 0.0001]; %状态转移协方差矩阵
H=[ ]; %观测矩阵
R=; %观测噪声方差 figure;
hold on; for i=: X_ = F*X;
Sigma_ = F*Sigma*F'+Q;
K = Sigma_*H'/(H*Sigma_*H'+R);
X = X_+K*(Z(i)-H*X_);
Sigma = (eye()-K*H)*Sigma_; plot(X(), X(), '.','MarkerSize',); %画点,横轴表示位置,纵轴表示速度
end plot([,],[,],'r-');

----------------------------------------------------------------------分割线----------------------------------------------------------------------------

一.离散时间线性动态系统的状态方程

  线性系统采用状态方程、观测方程及其初始条件来描述。线性离散时间系统的一般状态方程可描述为

  其中,X(k) 是 k 时刻目标的状态向量,V(k)是过程噪声,它是具有均值为零、方差矩阵为 Q(k) 的高斯噪声向量,即 
 

  Q(k)是状态转移矩阵, G(k)是过程噪声增益矩阵。

二.传感器的测量(观测)方程

  传感器的通用观测方程为

 
  
  这里, Z(k+1)是传感器在 k+1 时刻的观测向量,观测噪声 W(k+1) 是具有零均值和正定协方差矩阵 R(k+1) 的高斯分布测量噪声向量,即

三.初始状态的描述

  初始状态 X(0) 是高斯的,具有均值 X(0|0) 和协方差 ,即

四.Kalman滤波算法

  状态估计的一步预测方程为

  一步预测的协方差为

  预测的观测向量为

  观测向量的预测误差协方差为

  新息或量测残差为

  滤波器增益为

  Kalman滤波算法的状态更新方程为

  滤波误差协方差的更新方程为

% Kalman滤波技术

A=;                                        % 状态转移矩阵 Φ(k)
H=0.2; % 观测矩阵 H(k)
X()=; % 目标的状态向量 X(k)
% V()=; % 过程噪声 V(k)
Y()=; % 一步预测x(k)的更新 X(k+|k+)
P()=; % 一步预测的协方差 P(k)
N=;
V=randn(,N); % 模拟产生过程噪声(高斯分布的随机噪声)
w=randn(,N); % 模拟产生测量噪声 for k=:N X(k) = A * X(k-)+V(k-); % 状态方程:X(k+)=Φ(k)X(k)+G(k)V(k),其中G(k)= end Q=std(V)^; % W(k)的协方差,std()函数用于计算标准偏差
R=std(w)^; % V(k)的协方差 covariance Z=H*X+w; % 观测方程:Z(k+)=H(k+)X(k+)+W(k+),Z(k+)是k+1时刻的观测值 for t=:N P(t) = A * P(t-)+Q; % 一步预测的协方差 P(k+|k) S(t) = H.^ * P(t)+R; % 观测向量的预测误差协方差 S(k+) K(t) = H * P(t)/S(t); % 卡尔曼滤波器增益 K(k+) v(t) = Z(t) - ( A * H * Y(t-) ); % 新息/量测残差 v(k+) Y(t)=A * Y(t-) + K(t) * v(t); % 状态更新方程 X(k+|k+)=X(k+|k)+K(k+)*v(k+) P(t)=(-H * K(t)) * P(t); % 误差协方差的更新方程: P(k+|k+)=(I-K(k+)*H(k+))*P(k+|k)
end t=:N;
plot(t,Y,'r',t,Z,'g',t,X,'b'); % 红色线最优化估算结果滤波后的值,%绿色线观测值,蓝色线预测值
legend('Kalman滤波结果','观测值','预测值');

----------------------------------------------------------------------分割线----------------------------------------------------------------------------

但在实际工作中,我们的系统几乎都是非线性的,所以如何解决非线性系统 的滤波问题呢,这就是我们要讲的EKF(扩展卡尔曼滤波),它的原理很简单,就是在估计状态的地方进行线性化,线性化的方法也很简单,只需要进行泰勒的一 阶展开就行。当然我们也要说一下缺点,因为我们选择的线性化方法,所以只能达到二阶的精度(UKF可以达到四阶的精度),所以要求我们的系统是弱线性化 的。其实UKF也是对非线性系统的卡尔曼滤波,主要本人对其线性化方法(UT变换)不是很理解,等考完试再说。
  首先,系统的状态方程和观测方程如下:


我们知道,在更新误差协方差矩阵的时候,不能直接用f和h的,所以我们要进行泰勒展开,也就是要求雅克比矩阵。再利用线性情况下的卡尔曼滤波进行计算更新。
预测:


利用雅克比矩阵进行更新模型:



更新:





下面我会展示一个目标追踪的EKF例子:

%扩展Kalman滤波在目标跟踪中的应用

%function EKF_For_TargetTracking

clc;clear;

T=;%雷达扫描周期

N=/T;%总的采样次数

X=zeros(,N);%目标真实位置、速度

X(:,)=[-,,,];%目标初始位置、速度

Z=zeros(,N);%传感器对位置的观测

delta_w=1e-;%如果增大这个参数,目标的真实轨迹就是曲线了

Q=delta_w*diag([0.5,]);%过程噪声方差

G=[T^/,;T,;,T^/;,T];%过程噪声驱动矩阵

R=;%观测噪声方差

F=[,T,,;,,,;,,,T;,,,];%状态转移矩阵

x0=;%观测站的位置

y0=;

Xstation=[x0,y0];

for t=:N

    X(:,t)=F*X(:,t-)+G*sqrtm(Q)*randn(,);%目标真实轨迹

end

for t=:N

    Z(t)=Dist(X(:,t),Xstation)+sqrtm(R)*randn;%观测值

end

%EKF

Xekf=zeros(,N);

Xekf(:,)=X(:,);%Kalman滤波的状态初始化

P0=eye();%误差协方差矩阵的初始化

for i=:N

    Xn=F*Xekf(:,i-);%一步预测

    P1=F*P0*F'+G*Q*G';%预测误差协方差

    dd=Dist(Xn,Xstation);%观测预测

    %求解雅克比矩阵H

    H=[(Xn(,)-x0)/dd,,(Xn(,)-y0)/dd,];%泰勒展开的一阶近似

    K=P1*H'*inv(H*P1*H'+R);%卡尔曼最优增益

    Xekf(:,i)=Xn+K*(Z(:,i)-dd);%状态更新

    P0=(eye()-K*H)*P1;%滤波误差协方差更新

end

%误差分析

for i=:N

    Err_KalmanFilter(i)=Dist(X(:,i),Xekf(:,i));%

end

%画图

figure

hold on;box on;

plot(X(,:),X(,:),'-k');%真实轨迹

plot(Xekf(,:),Xekf(,:),'-r');%扩展Kalman滤波轨迹

legend(' real trajectory','EKF trajectory');

xlabel('X-axis  X/m');

ylabel('Y-axis Y/m');

figure

hold on ;box on;

plot(Err_KalmanFilter,'-ks','MarkerFace','r')

xlabel('Time /s');

ylabel('Position estimation bias   /m');

%子函数 求欧氏距离

function d=Dist(X1,X2);

if length(X2)<=

    d=sqrt((X1()-X2())^+(X1()-X2())^);

else

    d=sqrt((X1()-X2())^+(X1()-X2())^);

end

%子函数 求欧氏距离

function d=Dist(X1,X2);

if length(X2)<=

    d=sqrt((X1()-X2())^+(X1()-X2())^);

else

    d=sqrt((X1()-X2())^+(X1()-X2())^);

end

MATLAB-卡尔曼滤波简单运用示例的更多相关文章

  1. 【java开发系列】—— spring简单入门示例

    1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控制反转 ...

  2. Springmvc整合tiles框架简单入门示例(maven)

    Springmvc整合tiles框架简单入门示例(maven) 本教程基于Springmvc,spring mvc和maven怎么弄就不具体说了,这边就只简单说tiles框架的整合. 先贴上源码(免积 ...

  3. hadoop环境安装及简单Map-Reduce示例

    说明:这篇博客来自我的csdn博客,http://blog.csdn.net/lxxgreat/article/details/7753511 一.参考书:<hadoop权威指南--第二版(中文 ...

  4. EasyHook远注简单监控示例 z

    http://www.csdn 123.com/html/itweb/20130827/83559_83558_83544.htm 免费开源库EasyHook(inline hook),下面是下载地址 ...

  5. Web Service简单入门示例

    Web Service简单入门示例     我们一般实现Web Service的方法有非常多种.当中我主要使用了CXF Apache插件和Axis 2两种. Web Service是应用服务商为了解决 ...

  6. Ext简单demo示例

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  7. GDAL中MEM格式的简单使用示例

    GDAL库中提供了一种内存文件格式--MEM.如何使用MEM文件格式,主要有两种,一种是通过别的文件使用CreateCopy方法来创建一个MEM:另外一种是图像数据都已经存储在内存中了,然后使用内存数 ...

  8. html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例

    这篇文章主要介绍了html5本地存储的localstorage .本地数据库.sessionStorage简单使用示例,需要的朋友可以参考下 html5的一个非常cool的功能,就是web stora ...

  9. hydra简单使用示例

    本内容为网上收集整理,仅作为备忘!! hydra简单使用示例: 破解https: # hydra -m /index.php -l muts -P pass.txt 10.36.16.18 https ...

  10. nodejs nodejs模块使用及简单的示例

    nodejs模块使用及简单的示例 参考菜鸟教程网:http://www.runoob.com/ 一.fs模块的使用: 1.文件操作: 读文件: //读文件 var fs=require('fs'); ...

随机推荐

  1. .net MVC +EF+VUE做回合制游戏(二)

    Emmm,游戏中的属性购买页面 话不多说先上代码 <form id="vue" action="/ltgdGame.Web/Main/Index" met ...

  2. java爬虫系列第二讲-爬取最新动作电影《海王》迅雷下载地址

    1. 目标 使用webmagic爬取动作电影列表信息 爬取电影<海王>详细信息[电影名称.电影迅雷下载地址列表] 2. 爬取最新动作片列表 获取电影列表页面数据来源地址 访问http:// ...

  3. Java学习点滴——对象实例化

    基于<Java编程思想>第四版 构造与析构 在C++中通过构造函数和析构函数来保证:对象在使用前被正确初始化,在使用后被正确回收.Java中同样存在构造函数,但是没有析构函数.之所以没有析 ...

  4. Where Can I Download Full Installers for WebLogic Server

    Where can I download full installers for the different versions of WebLogic Server (WLS)? Full insta ...

  5. 荣耀7.0系统手机最简单激活Xposed框架的步骤

    对于喜欢玩手机的小伙伴来说,很多时候会使用到Xposed框架及各类功能彪悍的模块,对于5.0以下的系统版本,只要手机能获得Root权限,安装和激活Xposed框架是比较简便的,但随着系统版本的不断更新 ...

  6. Android 视频通信,低延时解决方案

    背景: 由于,项目需要,需要进行视频通信,把a的画面,转给b. 运维部署: APP1:编码摄像头采集的数据,并且发送数据到服务端 APP2:从服务端,拉取数据,并且进行解码显示 服务端:接收APP1提 ...

  7. java:合并两个排序的链表(递归+非递归)

    //采用不带头结点的链表 非递归实现 public static ListNode merge(ListNode list1,ListNode list2){ if(list1==null) retu ...

  8. .net core 命令行(仅作记录)

    命令大全:dotnet 命令 创建NuGet包:如何使用 .NET Core 命令行接口 (CLI) 工具创建 NuGet 包

  9. Swift中 删除Array的元素对象

    Swift中Array的删除对象 在Swift中数组Array没有removeObject的方法 1.找到下标 let model_index = selectedArray.index(where: ...

  10. oracle有三种类型的异常错误: 预定义 ( Predefined )错误里面的常见错误

    oracle有三种类型的异常错误: 预定义 ( Predefined )错误, 非预定义 ( Predefined )错误, 用户定义(User_define) 错误 预定义 ( Predefined ...