1 Star 0 Fork 0

云海/Mat_Learn

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
kalman.m 4.85 KB
一键复制 编辑 原始数据 按行查看 历史
云海 提交于 2024-09-19 09:41 . 。。。
% kalman filter
% X(K)=F*X(K-1)+Q
% Y(K)=H*(K)+R
% 第一个问题,生成一段随机信号,并滤波
% 生成一段时间 t
t = 0.1:0.01:1; % 从 0.1 秒开始 间隔 0.01秒,到 1 秒结束
L=length(t);
% 生成真实信号 x,以及观测 y
% 首先初始化
x = zeros(1, L); % 一行 L 列的数组,每个值都是 0
y = x;
y_2 = x;
% 生成信号,设 x = t^2
for i = 1:L
x(i) = t(i)^2;
y(i) = x(i) + normrnd(0, 1); % 正态分布生成函数,参数为期望和标准差
y_2(i) = x(i) + normrnd(0, 1); % 正态分布生成函数,参数为期望和标准差
end
%%%%%%%%%%%%%信号生成完毕%%%%%%%%%%%%%
% plot(t, x, t, y, 'LineWidth', 2);
%%%%%%%%%%%%%滤波算法%%%%%%%%%%%%%
%%%%%%预测方程观测方程怎么写?%%%%%%
% 观测方程好写 Y(K) = X(K) + R R~N(0, 1)
% 预测方程不好写
% 在这里,可以猜一猜线性表现是怎样的
% 大多数实际问题中,信号是杂乱无章的,怎么办?
%%%%模型一,最粗糙的建模
% X(K) = X(K-1) + Q;
% Y(K) = X(K) + R;
% Q ~ N(0, 1);
F_1 = 1;
H_1 = 1;
Q_1 = 1; % 预测噪声方差,这里给的小意味着对初值比较自信
R_1 = 1; % 观测噪声方差,这里给的大意味着对观测值比较自信
% 初始化 X(K)+
X_plus_1 = zeros(1, L); % plus: + ; minus: - ;
% 我们会经常用到 X_plus, X_minus, P_plus, P_minus;
% 设置一个初值,设置 X_plus_1(1) ~ N(0.01, 0.01^2); 这里方差给的小意味着对初值比较自信
% X_plus_1(1) = 0.01;
X_plus_1(1) = 1;
P_plus_1 = 0.01^2;
% 卡尔曼滤波算法
% X(K)_minus = F*X(K-1)_plus;
% P(K)_minus = F*P(K-1)_plus*F' + Q;
% K = P(K)_minus*H' * inv(H*P(K)_minus*H' + R);
% X(K)_plus = X(K)_minus + K*(y(K) - H*X(K)_minus);
% P(K)_plus = P(K)_minus - K*H*P(K)_minus;
% 卡尔曼滤波算法
for i = 2:L
% 预测
X_minus_1 = F_1 * X_plus_1(i-1);
P_minus_1 = F_1 * P_plus_1(i-1) * F_1' + Q_1;
% 增益
K_1 = (H_1 * P_minus_1 * H_1' + R_1) \ (P_minus_1 * H_1');
% 更新
X_plus_1(i) = X_minus_1 + K_1 * (y(i) - H_1 * X_minus_1);
P_plus_1(i) = P_minus_1 - K_1 * H_1 * P_minus_1;
end
%%%%模型二
% X(K) = X(K-1) + X'(K-1)*dt + X"(K-1)*dt^2*(1/2!) + Q_2;
% Y(K) = X(K) + R; R~N(0, 1);
% 此时状态变量 X(K) = [X(K) X'(K) X"(K)]T(列向量)
% Y(K) = H*X(K) + R; H~N(0, 1); H = [1 0 0](行向量);
%
% 预测方程
%
% X(K) = X(K-1) + X'(K-1)*dt + X"(K-1)*dt^2*(1/2!) + Q_2;
% X'(K) = 0 * X(K-1) + X'(K-1) + X"(K-1)*dt + Q_3;
% X"(K) = 0 * X(K-1) + 0 * X'(K-1) + X"(K-1)*dt + Q_3;
%
% 多项式信号多求几阶导数,总会比较平缓,
% X"(K) = X"(K-1)*dt + Q_3; 正是描述平缓的随机过程,这种建模相对来说更精细一些,适用范围也比较广
%
% F = 1 dt 0.5*dt^2
% 0 1 dt
% 0 0 1
%
% H = 1 0 0;
%
% Q = Q_2 0 0
% 0 Q_3 0
% 0 0 Q_3
%
dt = t(2) - t(1);
F_2 = [1 dt 0.5*dt^2; 0 1 dt; 0 0 1]; % 此处要注意矩阵是否病态,若 dt 特别小,精度会丢失
H_2 = [1 0 0];
Q_2 = [1, 0, 0;
0, 0.1, 0;
0, 0, 0.01];
R2 = 20;
% 设置初值
X_plus_2 = zeros(3, L);
X_plus_2(:, 1) = [0.01; 0.01; 0.01]; % 初值
P_plus_2 = eye(3); % eye(3) 是 3*3 的单位矩阵
% 开始滤波
for i = 2:L
% 预测
X_minus_2 = F_2 * X_plus_2(:, i-1);
P_minus_2 = F_2 * P_plus_2 * F_2' + Q_2;
% 增益
K_2 = (H_2 * P_minus_2 * H_2' + R2) \ (P_minus_2 * H_2');
% 更新
X_plus_2(:, i) = X_minus_2 + K_2 * (y(i) - H_2 * X_minus_2);
P_plus_2 = (eye(3) - K_2 * H_2) * P_minus_2;
end
%%% 优点,可以在线进行滤波,可以在线进行参数调整 %%%
%%% 缺点,需要对信号进行建模,模型不好,滤波效果不好 %%%
% 问题2,两个传感器,进行滤波
% Y_K(1) = X(K) + R_1;
% Y_K(2) = X(K) + R_2;
% 假设是模型 1
% H = [1 1]T (列向量) X = X(K)
% 假设是模型 2
% H = 1 0 0 X = X(K) X'(K) X"(K)
% 1 0 0
% R = [R_1 0; 0 R_2];
% Q 和 R 一定是方阵,
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 绘图
figure(1);
% 绘制观测值
scatter(t, y, 30, 'r', 'filled', 'DisplayName', '带噪声观测值');
hold on;
plot(t, y, 'r-', 'LineWidth', 1, 'DisplayName', '带噪声观测值(连续)');
% 绘制真实信号
plot(t, x, 'g--', 'LineWidth', 2, 'DisplayName', '真实信号');
% 绘制卡尔曼滤波估计
plot(t, X_plus_1, 'b-', 'LineWidth', 2, 'DisplayName', '卡尔曼滤波估计_1');
plot(t, X_plus_2(1,:), 'p-', 'LineWidth', 2, 'DisplayName', '卡尔曼滤波估计_2');
xlabel('时间');
ylabel('值');
title('卡尔曼滤波结果');
legend('Location', 'best');
grid on;
% 计算均方根误差(RMSE)
rmse_original = sqrt(mean((y - x).^2));
rmse_filtered = sqrt(mean((X_plus_1 - x).^2));
fprintf('原始观测的RMSE: %.4f\n', rmse_original);
fprintf('卡尔曼滤波后的RMSE: %.4f\n', rmse_filtered);
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/LuIrara/Mat_Learn.git
git@gitee.com:LuIrara/Mat_Learn.git
LuIrara
Mat_Learn
Mat_Learn
main

搜索帮助