6维ukf ekf 比较

一个二维的ukf
main.m中为:

X(t) = feval('ffun',X(t-1),t) +processNoise(t);
Z(t) = feval('hfun',X(t),t) + measureNoise(t);

ffun.m中为:

 %状态方程函数
function [y] = ffun(x,t);

 if nargin < 2
    error('Not enough input arguments.'); 
end
beta = 0.5;
y = 1 + sin(4e-2*pi*t) + beta*x;

如何将其改成6维下的ukf比较

这是main.c里的全部内容:

%% 主函数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 功能说明:ekf,ukf,pf,epf,upf算法的综合比较程序
function main
 
rand('seed',3);%设置随机数生成器的种子
randn('seed',6);
%error('下面的参数T请参考书中的值设置,然后删除本行代码') 
T = 50;
R =  1e-5;              
                       
g1 = 3;                
g2 = 2; 
 
X = zeros(1,T);%长度为T的行向量一维数组X,其中所有元素都初始化为0
Z = zeros(1,T);
processNoise = zeros(T,1);%T×1的全零列向量
measureNoise = zeros(T,1);
X(1) = 1;%X 的第一个元素被初始化为 1                         
P0 = 3/4;%P0 被初始化为 3/4
 
Qekf=10*3/4;%一个变量,值为10*3/4=7.5                
Rekf=1e-1; %一个变量,值为0.1                   
Xekf=zeros(1,T);               
Pekf = P0*ones(1,T);%一个长度为T的一维数组,每个元素的值初始化为P0        
Tekf=zeros(1,T);               

 
Qukf=2*3/4;                  
Rukf=1e-1;                    
Xukf=zeros(1,T);               
Pukf = P0*ones(1,T);          
Tukf=zeros(1,T);                

 
N=200;                      
Xpf=zeros(1,T);             
Xpfset=ones(T,N);% T x N 的矩阵 Xpfset 的所有元素初始化为1         
Tpf=zeros(1,T);            

 
Xepf=zeros(1,T);           
Xepfset=ones(T,N);         
Pepf = P0*ones(T,N);          
Tepf=zeros(1,T);               

 
Xupf=zeros(1,T);            
Xupfset=ones(T,N);              
Pupf = P0*ones(T,N);       
Tupf=zeros(1,T);               
 
for t=2:T
    processNoise(t) =  gengamma(g1,g2);%processNoise(t) 是第 t 个时间点的处理噪声,使用了 gengamma 函数生成  
    measureNoise(t) =  sqrt(R)*randn;%measureNoise(t) 是第 t 个时间点的测量噪声,使用了高斯分布生成。其中,R 是高斯分布的方差,randn 是生成服从高斯分布的随机数的函数。    
 
    X(t) = feval('ffun',X(t-1),t) +processNoise(t);
    Z(t) = feval('hfun',X(t),t) + measureNoise(t);
 
    tic
    [Xekf(t),Pekf(t)]=ekf(Xekf(t-1),Z(t),Pekf(t-1),t,Qekf,Rekf);
    Tekf(t)=toc;
    
 
    tic
    [Xukf(t),Pukf(t)]=ukf(Xukf(t-1),Z(t),Pukf(t-1),Qukf,Rukf,t);
    Tukf(t)=toc;
    
 
    tic
    [Xpf(t),Xpfset(t,:)]=pf(Xpfset(t-1,:),Z(t),N,t,R,g1,g2);
    Tpf(t)=toc;
    
 
    tic
    [Xepf(t),Xepfset(t,:),Pepf(t,:)]=epf(Xepfset(t-1,:),Z(t),t,Pepf(t-1,:),N,R,Qekf,Rekf,g1,g2);
    Tepf(t)=toc;
    
 
    tic
    [Xupf(t),Xupfset(t,:),Pupf(t,:)]=upf(Xupfset(t-1,:),Z(t),t,Pupf(t-1,:),N,R,Qukf,Rukf,g1,g2);
    Tupf(t)=toc;
end;
 
ErrorEkf=abs(Xekf-X); 
ErrorUkf=abs(Xukf-X);  
ErrorPf=abs(Xpf-X);     
ErrorEpf=abs(Xepf-X);   
ErrorUpf=abs(Xupf-X);   
 
figure
hold on;box on;
p1=plot(1:T,X,'-k.','lineWidth',2);
p2=plot(1:T,Xekf,'m:','lineWidth',2);
p3=plot(1:T,Xukf,'--','lineWidth',2);
p4=plot(1:T,Xpf,'-r','lineWidth',2);
legend([p1,p2,p3,p4],'真实状态','EKF估计','UKF估计','PF估计')
xlabel('Time(s)','fontsize',10)
ylabel('Position RMSE(m)','fontsize',10)

这是hfun里的全部内容:

% 观测方程函数
function [y] = hfun(x,t);
 
if nargin < 2, 
    error('Not enough input arguments.');
end
if t<=30
    y = (x.^(2))/5;
else
    y = -2 + x/2;
end;

状态方程函数为6*6阶矩阵

img

                                       
         100                 sin(wT)                    cos(wT)-1       0                                            
         010               1- cos(wT)                 sin(aT)0
Fk-1=[001                      0                                 0  T             ]  
        000                cos(wT)                 sin(wT)0
        000                sin(wT)                 cos(wT)  0             
        000                    0                            01

请各位帮帮忙,给出具体修改步骤

二维UKF算法需要对状态向量和观测向量进行扩展,以适应6维状态空间。具体修改步骤如下:

在主函数中,将状态向量X和观测向量Z改为6维向量:
Copy
X = zeros(6,T); % 6维状态向量
Z = zeros(2,T); % 2维观测向量
在状态方程函数ffun中,将状态向量X和噪声向量改为6维向量,并将状态方程表示为矩阵形式:
ini
Copy
function [y] = ffun(x,t)

if nargin < 2
    error('Not enough input arguments.'); 
end

w = 0.1 * pi; % 角速度
a = 0.1; % 加速度

F = [1 0 0 sin(w*t) 0 0;
     0 1 0 1-cos(w*t) 0 0;
     0 0 1 0 sin(w*t) cos(w*t)-1;
     0 0 0 cos(w*t) sin(w*t) 0;
     0 0 0 -sin(w*t) cos(w*t) 0;
     0 0 0 0 0 1];

beta = 0.5;
y = F * x + [beta*x(1); 0; 0; 0; 0; 0]; % 状态方程表示为矩阵形式
在观测方程函数hfun中,将观测向量Z改为2维向量:
Copy
function [y] = hfun(x,t)

if nargin < 2
    error('Not enough input arguments.'); 
end

if t<=30
    y = [x(1)^2/5; 0]; % 2维观测向量
else
    y = [-2; x(1)/2]; % 2维观测向量
end
在主函数中,定义观测噪声的方差R和过程噪声的方差Q,并将状态向量初始化为6维向量:
Copy
R = [1e-5 0; 0 1e-5]; % 观测噪声的方差
Q = diag([0.01 0.01 0.01 0.01 0.01 0.01]); %过程噪声的方差
X = zeros(6,T); % 初始化状态向量为6维
在主函数中,调用ukf函数进行状态估计,并将结果保存到Xukf和Pukf中:
lisp
Copy
Qukf = diag([0.01 0.01 0.01 0.01 0.01 0.01]); % 过程噪声的方差
Rukf = [1e-5 0; 0 1e-5]; % 观测噪声的方差
Xukf = zeros(6,T); % 初始化UKF估计的状态向量为6维
Pukf = repmat(P0,6,6,T); % 初始化UKF估计的协方差矩阵为3/4的单位矩阵
for t=2:T
    processNoise = mvnrnd(zeros(6,1),Qukf)'; % 生成过程噪声
    measureNoise = mvnrnd(zeros(2,1),Rukf)'; % 生成观测噪声
    X(:,t) = feval('ffun',X(:,t-1),t) + processNoise; %6维状态向量的状态更新
    Z(:,t) = feval('hfun',X(:,t),t) + measureNoise; % 2维观测向量

    [Xukf(:,t),Pukf(:,:,t)] = ukf(Xukf(:,t-1),Z(:,t),Pukf(:,:,t-1),ffun,hfun,Q,Rukf,t);
end
在ukf函数中,将状态向量和协方差矩阵改为6维向量和矩阵,并修改UKF算法中的各个参数:
matlab
Copy
function [x,P]=ukf(x0,z,P0,ffun,hfun,Q,R,t)
% 输入参数:
%   x0:先验状态估计向量
%   z:观测向量
%   P0:先验状态估计协方差矩阵
%   ffun:状态方程函数句柄
%   hfun:观测方程函数句柄
%   Q:过程噪声协方差矩阵
%   R:观测噪声协方差矩阵
%   t:时间戳根据您提供的状态方程和观测方程,我发现状态方程是非线性的,因此需要使用扩展卡尔曼滤波(EKF)或无迹卡尔曼滤波(UKF)进行状态估计。以下是将二维UKF扩展到六维的具体步骤:

1. 修改状态向量和观测向量的维度。将状态向量和观测向量的维度从2改为6,即:

X = zeros(6,T);
Z = zeros(6,T);

Copy

2. 修改状态方程函数。根据您提供的状态方程,将状态方程表示为矩阵形式,即:

function [y] = ffun(x,t)

if nargin < 2
error('Not enough input arguments.');
end

w = 0.1 * pi; % 角速度
a = 0.1; % 加速度

F = [1 0 0 sin(wt) 0 0;
0 1 0 1-cos(wt) 0 0;
0 0 1 0 sin(wt) cos(wt)-1;
0 0 0 cos(wt) sin(wt) 0;
0 0 0 -sin(wt) cos(wt) 0;
0 0 0 0 0 1];

beta = 0.5;
y = F * x + [beta*x(1); 0; 0; 0; 0; 0];

Copy

3. 修改观测方程函数。将观测向量的维度从2改为6,即:

function [y] = hfun(x,t)

if nargin < 2
error('Not enough input arguments.');
end

if t<=30
y = [x(1)^2/5; 0; 0; 0; 0; 0];
else
y = [-2; x(1)/2; 0; 0; 0; 0];
end

Copy

4. 修改ukf函数的输入参数和输出参数。将状态向量和协方差矩阵的维度从2改为6,即:

function [x,P]=ukf(x0,z,P0,ffun,hfun,Q,R,t)

x = zeros(6,1);
P = zeros(6,6);

Copy

5. 修改UKF算法中的 状态方程函数 和 观测方程函数
由于你需要将状态方程函数和观测方程函数改为6维的,因此你需要修改 ukf 函数中的 ffun 和 hfun 参数,使其能够接收6维的状态向量和观测向量,例如:

matlab
Copy
function [x,P]=ukf(x0,z,P0,ffun,hfun,Q,R,t)

x = zeros(6,1);
P = zeros(6,6);

% 定义UKF参数
alpha = 0.1;
beta = 2;
kappa = 0;
n = length(x0);
lambda = alpha^2 * (n + kappa) - n;

% 生成sigma点
X = sigmaPoints(x0,P0,lambda);

% 预测状态和协方差
[x_,X_] = unscentedTransform(X,ffun,Q,t);
P_ = covariances(X_,x_,lambda,alpha,beta);

% 预测观测和协方差
[z_,Z_] = unscentedTransform(X_,hfun,R,t);
Pzz = covariances(Z_,z_,lambda,alpha,beta);
Pxz = crossCovariances在上一条回答中,我意外地按下了回车键,导致代码不完整。下面给出完整的修改步骤。

5. 修改UKF算法中的 状态方程函数 和 观测方程函数

由于你需要将状态方程函数和观测方程函数改为6维的,因此你需要修改 `ukf` 函数中的 `ffun` 和 `hfun` 参数,使其能够接收6维的状态向量和观测向量,例如:

```matlab
function [x,P]=ukf(x0,z,P0,ffun,hfun,Q,R,t)

x = zeros(6,1);
P = zeros(6,6);

% 定义UKF参数
alpha = 0.1;
beta = 2;
kappa = 0;
n = length(x0);
lambda = alpha^2 * (n + kappa) - n;

% 生成sigma点
X = sigmaPoints(x0,P0,lambda);

% 预测状态和协方差
[x_,X_] = unscentedTransform(X,ffun,Q,t);
P_ = covariances(X_,x_,lambda,alpha,beta);

% 预测观测和协方差
[z_,Z_] = unscentedTransform(X_,hfun,R,t);
Pzz = covariances(Z_,z_,lambda,alpha,beta);
Pxz = crossCovariances(X_,x_,Z_,z_,lambda,alpha,beta);

% 计算卡尔曼增益
K = Pxz / Pzz;

% 更新状态和协方差
x = x_ + K * (z - z_);
P = P_ - K * Pzz * K';

end
然后你需要重新实现 ffun 和 hfun 函数,使其能够处理6维状态向量,例如:

matlab
Copy
function [y] = ffun(x,t)

if nargin < 2
    error('Not enough input arguments.'); 
end

w = 0.1 * pi;
a = 0.2;

F = [1 sin(w*t) (1-cos(w*t))/w 0 0 0;
     0 cos(w*t) sin(w*t)   0 0 0;
     0 1        cos(w*t)   0 0 0;
     0 0        0         1 t 0;
     0 0        0         0 1 0;
     0 0        0         0 0 function [y] = ffun(x,t)

if nargin < 2
    error('Not enough input arguments.'); 
end

w = 0.1 * pi;
a = 0.2;

F = [1 sin(w*t) (1-cos(w*t))/w 0 0 0;
     0 cos(w*t) sin(w*t)   0 0 0;
     0 1        cos(w*t)   0 0 0;
     0 0        0         1 t 0;
     0 0        0         0 1 t;
     0 0        0         0 0 1];
 
beta = 0.5;
y = F * x + [beta*x(1); 0; 0; 0; 0; 0];

end

function [y] = hfun(x,t)

if nargin < 2, 
    error('Not enough input arguments.');
end

if t<=30
    y = (x(1)^2)/5;
else
    y = -2 + x(1)/2;
end

end
这里我们直接把状态方程矩阵 F 写出来,然后用矩阵乘法计算状态预测值。在 ffun 函数中,我们使用了状态方程矩阵 F,并且根据矩阵乘法计算了状态预测值。同时,我们也根据变量 t 计算了矩阵 F 中的三个角度参数,即旋转角度 w 和加速度变化率 a。观测方程函数 hfun 相对简单,只需针对状态向量的第一个元素进行计算即可。

最后,你需要修改 main 函数中的调用部分,将 ffun 和 hfun 参数改为新的函数名,例如:

matlab
Copy
[Xukf(t),Pukf(t)]=ukf(Xukf(t-1),Z(t),Pukf(t-1),@ffun,@hfun,Q,R,t);
这样就可以使用修改后的6维UKF算法对你的系统进行状态估计了。需要注意的是,这里只给出了修改UKF算法的步骤,你还需要根据具体问题调整其他参数和函数,比如UKF的参数 alpha、beta 和 kappa,以及处理噪声的函数 gengamma。最后,你需要修改 main 函数中的调用部分,将 ffun 和 hfun 参数改为新的函数名,例如:

matlab
Copy
[Xukf(t),Pukf(t)]=ukf(Xukf(t-1),Z(t),Pukf(t-1),@ffun,@hfun,Q,R,t);
这样就可以使用修改后的6维UKF算法对你的系统进行状态估计了。需要注意的是,这里只给出了修改UKF算法的步骤,你还需要根据具体问题调整其他参数和函数,比如UKF的参数 alpha、beta 和 kappa,以及处理噪声的函数 gengamma。


以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:

要将这个二维UKF扩展成六维,需要做以下修改:

  1. 状态向量X和测量向量Z变为六维:
matlab
X = [x1 x2 x3 x4 x5 x6]'; 
Z = [z1 z2 z3 z4 z5 z6]';


  1. 状态方程函数ffun更新为六维:
matlab
function [y] = ffun(x,t);
if nargin < 2 
    error('Not enough input arguments.'); 
end
beta = 0.5;
y1 = 1 + sin(4e-2_pi_t) + beta*x1;
y2 = 1 + sin(4e-2_pi_t) + beta*x2; 
y3 = 1 + sin(4e-2_pi_t) + beta*x3;
y4 = 1 + sin(4e-2_pi_t) + beta*x4;  
y5 = 1 + sin(4e-2_pi_t) + beta*x5; 
y6 = 1 + sin(4e-2_pi_t) + beta*x6;
y = [y1; y2; y3; y4; y5; y6];
end

  1. 测量方程函数hfun也需要相应更新为六维。

  2. 过程噪声processNoise和测量噪声measureNoise变为六维向量。

  3. UKF的参数也需要适当调整,如状态方差矩阵P变为6x6,过程噪声方差Q和测量噪声R变为6x6矩阵等。

除此之外,UKF算法的其他步骤如估计、更新等都保持相同。

下面是6维UKF的一个实现示例:

matlab
% 状态和测量向量 
X = [x1 x2 x3 x4 x5 x6]';  
Z = [z1 z2 z3 z4 z5 z6]';

% 过程噪声和测量噪声方差
Q = diag([0.1 0.1 0.1 0.1 0.1 0.1]);
R = diag([1 1 1 1 1 1]);  

% 状态方差初始化
P = diag([1 1 1 1 1 1]);  

% UKF主循环
for t=1:T
    % 预测
    Xp = ffun(X, t);      
    Pp = F*P*F' + Q;    
    
    % 更新      
    K = Pp*H'/(H*Pp*H' + R);
    X = Xp + K*(Z - hfun(Xp)); 
    P = Pp - K*H*Pp;
end

要将二维的状态方程函数 ffun 改成六维下的 Unscented Kalman Filter (UKF),您需要进行以下修改:

  1. 调整输入和输出:

    • x 参数改为一个包含六个状态变量的向量 X
    • 修改函数的输出为一个包含六个状态变量的向量 y
  2. 根据六维状态变量修改状态方程的计算逻辑:

    • 在状态方程中,您需要根据六个状态变量 X 和时间 t 计算出下一个状态。
    • 您可以根据需要修改状态方程的具体逻辑,以适应六维状态变量的情况。

下面是将二维状态方程函数 ffun 改写为六维 UKF 的示例:

function [y] = ffun(X, t)
    if nargin < 2
        error('Not enough input arguments.');
    end

    beta = 0.5;
    x1 = X(1);
    x2 = X(2);
    x3 = X(3);
    x4 = X(4);
    x5 = X(5);
    x6 = X(6);

    % 根据六维状态变量计算下一个状态
    y1 = x1 + sin(4e-2*pi*t) + beta*x2;
    y2 = ... % 根据需要计算其他状态变量的值
    y3 = ...
    y4 = ...
    y5 = ...
    y6 = ...

    % 将计算得到的六个状态变量组成输出向量
    y = [y1; y2; y3; y4; y5; y6];
end

请注意,这只是一个示例,您需要根据实际情况修改状态方程的计算逻辑和状态变量的个数。确保根据您的问题域和数据模型进行相应的修改。

答:下面提供一个参考实例代码,演示如何将 UKF 在 6 维空间中的值计算出来:
main.m 中的代码:

% 定义 UKF 函数  
function [y] = ffun(x,t)  
% ukf function [y] = ffun(x,t):  
if nargin < 2  
error('Not enough input arguments.');  
end  
beta = 0.5;  
y = 1 + sin(4e-2*pit) + beta*x;

修改后的 main.m 中的代码:
【这里的 ukf 函数用于计算 UKF 值,输入参数是一个向量 u(n,t),它表示系统在时间 t 的状态,以及一个向量 x_i,它表示系统在状态 i 的初始状态。函数的输出是一个向量 y(k,t),它表示状态 k 在时间 t 的输出。】

% 定义 UKF 函数  
function [y] = ffun(x,t)  
% ukf function [y] = ffun(x,t):  
if nargin < 2  
error('Not enough input arguments.');  
end  
beta = 0.5;  
y = ukf([u(n,t), x_i]);

可以借鉴下

%%% EKF UKF PF三种算法对比

clc

close all

clear;

% tic;

x = 0.1; % 初始状态

x_estimate = 1;%状态的估计

e_x_estimate = x_estimate; %EKF的初始估计

u_x_estimate = x_estimate; %UKF的初始估计

p_x_estimate = x_estimate; %PF的初始估计

Q = 10;%input('请输入过程噪声方差Q的值: '); % 过程状态协方差

R = 1;%input('请输入测量噪声方差R的值: '); % 测量噪声协方差

P =5;%初始估计方差

e_P = P; %UKF方差

u_P = P;%UKF方差

pf_P = P;%PF方差

tf = 50; % 模拟长度

x_array = [x];%真实值数组

e_x_estimate_array = [e_x_estimate];%EKF最优估计值数组

u_x_estimate_array = [u_x_estimate];%UKF最优估计值数组

p_x_estimate_array = [p_x_estimate];%PF最优估计值数组

u_k = 1; %微调参数

u_symmetry_number = 4; % 对称的点的个数

u_total_number = 2 * u_symmetry_number + 1; %总的采样点的个数

linear = 0.5;

N = 500; %粒子滤波的粒子数

close all;

%粒子滤波初始N 个粒子

for i = 1 : N

p_xpart(i) = p_x_estimate + sqrt(pf_P) * randn;

end

for k = 1 : tf

% 模拟系统

x = linear * x + (25 * x / (1 + x^2)) + 8 * cos(1.2*(k-1)) + sqrt(Q) * randn; %状态值

y = (x^2 / 20) + sqrt(R) * randn; %观测值

%扩展卡尔曼滤波器

%进行估计第一阶段的估计

e_x_estimate_1 = linear * e_x_estimate + 25 * e_x_estimate /(1+e_x_estimate^2) + 8 * cos(1.2*(k-1));

e_y_estimate = (e_x_estimate_1)^2/20; %这是根据k=1时估计值为1得到的观测值;只是这个由我估计得到的第24行的y也是观测值不过是由加了噪声的真实值得到的

%相关矩阵

e_A = linear + 25 * (1-e_x_estimate^2)/((1+e_x_estimate^2)^2);%传递矩阵

e_H = e_x_estimate_1/10; %观测矩阵

%估计的误差

e_p_estimate = e_A * e_P * e_A' + Q;

%扩展卡尔曼增益

e_K = e_p_estimate * e_H'/(e_H * e_p_estimate * e_H' + R);

%进行估计值的更新第二阶段

e_x_estimate_2 = e_x_estimate_1 + e_K * (y - e_y_estimate);