无味卡尔曼滤波——非线性UKF-Matlab

%UKF无味卡尔曼滤波在自动驾驶车辆定位中的应用
%参考文献:
%        The High-Degree Cubature Kalman Filter (Bin Jia, Ming Xin, and Yang Cheng)
%        Unscented Kalman Filter Tutorial (Gabriel A. Terejanu )
%        基于正交变换的五阶容积卡尔曼滤波导航算法 (何康辉,董朝阳 )
%        EKF、UKF和CKF的滤波性能对比研究 (常宇健,赵辰)
%        组合导航原理与应用 (西北工业大学出版社)
%        卡尔曼滤波与Matlab仿真 (北京航空航天大学出版社)
% 本例子使用线性状态模型,因此加速度变成了干扰项
% Lidar传感器测量模型为线性模型,Radar传感器测模型为非线性模型
% 在Radar传感器中使用滤波算然为 UKF,在Lidar传感器中使用滤波算然为 KF
clear;
clc;
tic;      %计时
dt = 0.1; %步长

%分配空间
Radar_measurement = [];
Radar_measurement_p = [];
Lidar_measurement = [];
UKF_estimation = [];
ukf = [];  % 结构体

%读取Radar_Lidar_Data2.csv文件保存到矩阵Data
Data = csvread('Radar_Lidar_Data1.csv',1,1);%起点为第2行第2612组数据
%将Data矩阵数据保存到data.csv文件中
csvwrite('Data.csv',Data);

%初始化状态,x是4维向量
if (Data(1,1) == 1)  
    x = [Data(1,2); Data(1,3); 0; 0];          %如果是lidar测量数据,文件 Dada2.csv,保存这个
else
    x = [   
            Data(1,2)*cos(Data(1,3)); 
            Data(1,2)*sin(Data(1,3)); 
            Data(1,4)*cos(Data(1,3)); 
            Data(1,4)*sin(Data(1,3))
         ];  %如果是Radar测量数据,文件 Dada1.csv,保存这个
end

%初始化状态协方差矩阵
P = diag([1,1,1000,1000]);
 
%状态转移矩阵,线性
F = [[1, 0, dt, 0];
     [0, 1, 0, dt];
     [0, 0, 1, 0];
     [0, 0, 0, 1]];

 %系统误差协方差矩阵
Q = [[(dt^2)/4,0,(dt^3)/2,0];
     [0,(dt^2)/4,0,(dt^3)/2];
     [(dt^3/2),0,(dt^2),0];
     [0,(dt^3)/2,0,(dt^2)]];
 
%Lidar传感器观测矩阵,线性
H_L = [[1, 0, 0, 0];
       [0, 1, 0, 0]];

%雷达传感器测量误差协方差矩阵
R_r = diag([0.09,0.005,0.09]);

%激光雷达传感器测量误差协方差矩阵
R_L = diag([0.0025, 0.0025]);

%4阶单位矩阵
I = eye(4);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% UKF参数设置 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
L = numel(x);                                 %numer of states    
alpha = 0.001;                                %对于高斯分布来说,取值为 (0,1) 
ki = -1;                                      %对于高斯分布来说,取值为 3-n
beita = 2;                                    %对于高斯分布来说,取值为2    
lambda = alpha^2*(L+ki)-L;                    %表示sigma点与均值的距离
Wm = [lambda/(L+lambda),1/(2*(L+lambda)) * ones(1,2*L)];                         %sigma点对期望权重 
Wc = [(lambda/(L+lambda) + 1 - alpha^2 + beita),1/(2*(L+lambda)) * ones(1,2*L)]; %sigma点对方差权重
gama = sqrt(L+lambda); 
% alpha 越大,第一个sigma 点(平均值处)的权重越大,其他点权重越小

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 开始迭代 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for n = 1:length(Data) 
    
    %Radar传感器
    %非线性
    if (Data(n,1) == 2)
        
        %Radar测量数据
        z = transpose(Data(n,2:4));
        z_p = [ z(1) * cos(z(2));z(1) * sin(z(2));z(3) * cos(z(2));z(3) * sin(z(2))];
        
        %UKF 算法核心部分
        %======================================================================%        
        %1.采样:由x0,P0产生sigma点
        A1 = gama * chol(P);        
        Y1 = x(:,ones(1,numel(x)));                                                      
        X1_sigma = [x,Y1 + A1,Y1 - A1];    
        
        %2.UT变换:sigma点经过线性映射
        cols = size(X1_sigma,2);              % 返回矩阵列数
        x1_mean = zeros(L,1);                 % 加权均值:经过线性映射后均值
        X1_ut = zeros(L,cols);                % UT变换:sigma点经过线性映射
        for k = 1 : cols  
            X1_ut(:,k) = F * X1_sigma(:,k);            % UT变换:sigma点经过线性映射
            x1_mean = x1_mean + Wm(k) * X1_ut(:,k);   % 加权均值:经过线性映射后均值 2n+1
        end  
        error1 = X1_ut - x1_mean(:,ones(1,cols));         % 经过线性映射后偏差
        P1_cov = error1 * diag(Wc) * transpose(error1) + Q;   % 加权方差:经过线性映射后方差
        
        %3.采样:计算增广sigma点
        A2 = gama * chol(P1_cov);        
        Y2 = x1_mean(:,ones(1,numel(x1_mean)));                                                      
        X2_sigma = [x1_mean,Y2 + A2,Y2 - A2];
        
        %4.非线性测量方程 
        h = @(x)[sqrt(x(1)^2 + x(2)^2);
                 atan(x(2)/x(1));
                (x(1)*x(3) + x(2)*x(4)) / sqrt(x(1)^2 + x(2)^2)];
        
        %5.UT变换:sigma点经过非线性映射
        x2_mean = zeros(L-1,1);                % 加权均值:经过非线性映射后均值 3x1
        X2_ut = zeros(L-1,cols);               % UT变换:sigma点经过非线性映射 3x9
        for k = 1 : cols  
            X2_ut(:,k) = h(X2_sigma(:,k));              % UT变换:sigma点经过非线性映射 3x9
            x2_mean= x2_mean + Wm(k) * X2_ut(:,k);      % 加权均值:经过非线性映射后均值 3x1
        end  
        error2 = X2_ut - x2_mean(:,ones(1,cols));                % 经过非线性映射后偏差 3x3
        P2_cov = error2 * diag(Wc) * transpose(error2) + R_r;    % 加权方差:经过非线性映射后方差 3x3
        
        %6.量测更新
        P3_cov = error1 * diag(Wc) * transpose(error2);  % 方差cross 4x3
        K = P3_cov / P2_cov;                             % 卡尔曼增益 4x3
        x = x1_mean + K * (z - x2_mean);                 % 状态均值更新
        P = P1_cov - K * P2_cov * transpose(K);          % 状态方差更新
        
        %7.保存数据
        UKF_estimation = [UKF_estimation;transpose(x)];
        Radar_measurement = [Radar_measurement; transpose(z)];
        Radar_measurement_p = [Radar_measurement_p;transpose(z_p)];
    %======================================================================%
    
    %Lidar传感器
    %线性
    else
        %KF 算法核心部分
        %======================================================================% 
        %1.预测更新状态、状态协方差阵
        x = F * x;
        P = F * P * transpose(F) + Q;

        %2.Lidar测量数据
        z = transpose(Data(n,2:3));
        
        %3.测量更新
        %更新卡尔曼增益矩阵
        y = z - (H_L * x);
        S = H_L * P * transpose(H_L) + R_L;
        K = P * transpose(H_L) / S;
        x = x + (K * y);          % 更新状态
        P = (I - (K * H_L)) * P;  % 更新状态协方差阵
        
        %4.保存状态值
        UKF_estimation = [UKF_estimation;transpose(x)];
        Lidar_measurement = [Lidar_measurement; transpose(z)];
        %======================================================================% 
    end     
    
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 数据可视化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1);
hold on;
plot(Data(:,5),Data(:,6),'k');                                                %真实状态
scatter(UKF_estimation(:,1),UKF_estimation(:,2),5,'filled','r');                          %估计状态
scatter(Lidar_measurement(:,1),Lidar_measurement(:,2),5,'filled','blue');     %Lidar传感器测量
scatter(Radar_measurement_p(:,1),Radar_measurement_p(:,2),5,'filled','g');    %Radar传感器测量
legend('truth','UKF Path result','Lidar Measurement','Radar Measurement');    %标注
title('位置估计');
axis square;
grid on;
hold off;

%位置x误差
figure(2);
hold on;
UKF_x_error = Data(1:2:1223,5) - UKF_estimation(1:2:1223,1);  %位置x误差
plot(1:612,UKF_x_error);
plot(1:612,Data(1:2:1223,5) - Radar_measurement_p(:,1));
legend('UKFerror','Radarerror');       
title('位置x误差');
grid on;
hold off;

%位置y误差
figure(3);
hold on;
UKF_y_error = Data(1:2:1223,6) - UKF_estimation(1:2:1223,2);  %位置y误差
plot(1:612,UKF_y_error);
plot(1:612,Data(1:2:1223,6) - Radar_measurement_p(:,2));
legend('UKFerror','Radarerror');       
title('位置y误差');
grid on
hold off;

%速度x误差
figure(4);
hold on;
UKF_vx_error = Data(1:2:1223,7) - UKF_estimation(1:2:1223,3);  %速度x误差
plot(1:612,UKF_vx_error);
plot(1:612,Data(1:2:1223,7) - Radar_measurement_p(:,3));
legend('UKFerror','Radarerror');       
title('速度x误差');
grid on
hold off;

%速度y误差
figure(5);
hold on;
UKF_vy_error = Data(1:2:1223,8) - UKF_estimation(1:2:1223,4);  %速度y误差
plot(1:612,UKF_vy_error);
plot(1:612,Data(1:2:1223,8) - Radar_measurement_p(:,4));
legend('UKFerror','Radarerror');       
title('速度y误差');
grid on
hold off;

%将数据保存到 UKF_error.csv 文件中,用于软法比较
UKF_error = [UKF_x_error,UKF_y_error,UKF_vx_error,UKF_vy_error];
csvwrite('UKF_error.csv',UKF_error);
%保存到结构体
ukf.estimation = UKF_estimation;
ukf.error      = UKF_error;
ukf.measurement_R = Radar_measurement_p;
ukf.measurement_L = Lidar_measurement;
%结束计时
toc;

结果分析:
无味卡尔曼滤波——非线性UKF-Matlab_第1张图片
无味卡尔曼滤波——非线性UKF-Matlab_第2张图片
无味卡尔曼滤波——非线性UKF-Matlab_第3张图片

你可能感兴趣的:(组合导航,卡尔曼滤波相关)