UWBIns/Code/Matlab/UWBInsFusion/eskf_uwb_imu.m

356 lines
15 KiB
Mathematica
Raw Normal View History

2025-04-16 20:15:33 +08:00
clc
clear
close all
addpath './lib';
addpath './lib/gnss';
addpath './lib/calbiration';
addpath './lib/plot';
addpath './lib/rotation';
addpath './lib/geo';
savepath
%%
% UWB IMU 15
% PR(TOF) UWB
% IMU: (3) 3(3) 6,,
% noimal_state: : : (3) (3) (4) 10
% err_state: KF: (3) (3) (3) (3) (3) 15
% du: : (3) (3) 6
% :
% ,: m/s^(2)
% , (): rad/s
% rad
% : m/s
%%
load datas2
dataset = datas;
% dataset
% dataset
% imu
% | acc
% | gyr
% | time
% uwb
% | time 1*17200
% | anchor xyz
% | tof 4*172004
% | cnt
% pos
N = length(dataset.imu.time); %
dt = mean(diff(dataset.imu.time)); % dtIMUdiffdt
%
% dataset.uwb.anchor(:,1) = [];
% dataset.uwb.tof(1,:) = [];
% EKF使22D
%dataset.uwb.cnt = size(dataset.uwb.anchor, 2);
m_div_cntr = 0; % IMU m_div UWB
m_div = 1; % m_divEKF(UWB),
% UWBIMUIMU 100HzUWB 10Hz
UWB_LS_MODE = 3; % 2 UWB2D 3UWB3D
UWB_EKF_UPDATE_MODE = 3; % EKF 2D 3: EKF3D
%%
out_data.uwb = []; %
out_data.uwb.time = dataset.uwb.time; % UWB
out_data.imu.time = dataset.imu.time; % IMU
out_data.uwb.anchor = dataset.uwb.anchor; %
% pr = 0;
% last_pr = 0;
%%
settings = uwb_imu_example_settings(); % 使uwb_imu_example_settings()
% settings
R = diag(ones(dataset.uwb.cnt, 1)*settings.sigma_uwb^(2)); %
noimal_state = init_navigation_state(settings) ; % 10x,y,z;vx,vy,vz;姿q0,q1,q2,q3
%
err_state = zeros(15, 1); % ,1533姿333
%
%使
pr = dataset.uwb.tof(:, 1); % UWB
%
% =++
%
% UWB线
% noimal_state:使
noimal_state(1:3) = multilateration(dataset.uwb.anchor, [ 1 1 0.99]', pr', UWB_LS_MODE);
du = zeros(6, 1); %
[P, Q1, Q2, ~, ~] = init_filter(settings); % 使~
%
fprintf("共%d帧数据, IMU采样频率:%d Hz 共运行时间 %d s\n", N, 1 / dt, N * dt);
fprintf("UWB基站个数:%d\n", dataset.uwb.cnt);
fprintf("UWB量测更新频率为:%d Hz\n", (1 / dt) / m_div);
fprintf("UWB EKF量测更新模式: %dD模式\n", UWB_EKF_UPDATE_MODE);
fprintf("纯UWB最小二乘解算: %dD模式\n", UWB_LS_MODE);
fprintf("EKF 滤波参数:\n");
settings
fprintf("开始滤波...\n");
for k=1:N
acc = dataset.imu.acc(:,k);
gyr = dataset.imu.gyr(:,k);
% bias, bias
% = + +
acc = acc - du(1:3); % du1346
gyr = gyr - du(4:6); %
%
p = noimal_state(1:3); % [x; y; z]
v = noimal_state(4:6); % [vx; vy; vz]m/s
q = noimal_state(7:10); % 姿 [q0; q1; q2; q3]
% IMU姿
% pvqaccgyrdt
[p, v, q] = nav_equ_local_tan(p, v, q, acc, gyr, dt, [0, 0, -9.8]'); % -9.8
% NZ00
v(3) = 0;
%
noimal_state(1:3) = p;
noimal_state(4:6) = v;
noimal_state(7:10) = q;
out_data.eul(k,:) = q2eul(q); %
% F G
% acc dt F G
[F, G] = state_space_model(noimal_state, acc, dt);
% P
P = F*P*F' + G*blkdiag(Q1, Q2)*G';
% log
out_data.x(k,:) = noimal_state;
out_data.delta_u(k,:) = du'; %
out_data.diag_P(k,:) = trace(P); % 姿
%% EKF UWB
m_div_cntr = m_div_cntr+1; %
% m_divEKF(UWB)m_div1
if m_div_cntr == m_div
m_div_cntr = 0;
pr = dataset.uwb.tof(1:dataset.uwb.cnt, k); % prkUWBTOF
%PR PRGNSS
% arr = find(abs(pr - last_pr) < 0.05);
% last_pr = pr;
% out_data.good_anchor_cnt(k,:) = length(arr); %
%
% if(isempty(arr))
% continue;
% end
%
% % R
% pr = pr(arr);
% anch = dataset.uwb.anchor(:, arr);
% R1 = R(arr, arr);
%
anch = dataset.uwb.anchor;
R1 = R; %
%
% Y noimal_state
% H
[Y, H] = uwb_hx(noimal_state, anch, UWB_EKF_UPDATE_MODE);
% K
S = H*P*H'+R1; % system uncertainty
residual = pr - Y; % residual
%% R Self-Calibrating Multi-Sensor Fusion with Probabilistic
%Measurement Validation for Seamless Sensor Switching on a UAV,
% LMahalanobis L
L = (residual'*S^(-1)*residual);
out_data.L(k,:) = L;
% if(L > 20 ) %
% S = H*P*H'+R1*5;
% end
K = (P*H')/(S); % K
err_state = [zeros(9,1); du] + K*(residual); %
%
noimal_state(1:6) = noimal_state(1:6) + err_state(1:6);
% 姿
q = noimal_state(7:10); % 姿
q = qmul(rv2q(err_state(7:9)), q);
noimal_state(7:10) = q; % 姿使
%
du = err_state(10:15);
% P
P = (eye(15)-K*H)*P;
end
%% Z B Z0().. Z https://kth.instructure.com/files/677996/download?download_frd=1 https://academic.csuohio.edu/simond/pubs/IETKalman.pdf
%% BZ
R2 = eye(1)*0.5;
Cn2b = q2m(qconj(noimal_state(7:10))); % ;
H = [zeros(1,3), [0 0 1]* Cn2b, zeros(1,9)]; % H
K = (P*H')/(H*P*H'+R2);
z = Cn2b*noimal_state(4:6); % BZ
err_state = [zeros(9,1); du] + K*(0-z(3:3)); % 0BZz(3)
%
noimal_state(1:6) = noimal_state(1:6) + err_state(1:6);
% 姿
q = noimal_state(7:10);
q = qmul(ch_rv2q(err_state(7:9)), q); %
noimal_state(7:10) = q;
%
% du = err_state(10:15);
% P
P = (eye(15)-K*H)*P;
end
fprintf("开始纯UWB最小二乘位置解算...\n");
%% UWB
j = 1;
uwb_pos = [1 1 1]';
N = length(dataset.uwb.time);
for i=1:N
pr = dataset.uwb.tof(:, i);
% NaN
%if all(~isnan(pr)) == true
uwb_pos = multilateration(dataset.uwb.anchor, uwb_pos, pr', UWB_LS_MODE);
out_data.uwb.pos(:,j) = uwb_pos;
j = j+1;
%end
end
fprintf("计算完成...\n");
%% plot
out_data.uwb.tof = dataset.uwb.tof;
out_data.uwb.fusion_pos = out_data.x(:,1:3)';
demo_plot(dataset, out_data);
%% nomial state
function x = init_navigation_state(~)
% 0 10x,y,z;vx,vy,vz;姿q0,q1,q2,q3
q = eul2q(deg2rad([0 0 0])); % eul2q
x = [zeros(6,1); q]; % 6
end
%%
function [P, Q1, Q2, R, H] = init_filter(settings)
% Kalman filter state matrix
P = zeros(15);
P(1:3,1:3) = settings.factp(1)^2*eye(3);
P(4:6,4:6) = settings.factp(2)^2*eye(3);
P(7:9,7:9) = diag(settings.factp(3:5)).^2;
P(10:12,10:12) = settings.factp(6)^2*eye(3);
P(13:15,13:15) = settings.factp(7)^2*eye(3);
% Process noise covariance
Q1 = zeros(6);
Q1(1:3,1:3) = diag(settings.sigma_acc).^2*eye(3);
Q1(4:6,4:6) = diag(settings.sigma_gyro).^2*eye(3);
Q2 = zeros(6);
Q2(1:3,1:3) = settings.sigma_acc_bias^2*eye(3);
Q2(4:6,4:6) = settings.sigma_gyro_bias^2*eye(3);
R =0;
H = 0;
end
%% FG
% x acc dt F G
function [F,G] = state_space_model(x, acc, dt)
Cb2n = q2m(x(7:10)); % bodynav
sk = askew(Cb2n * acc); % v线
O = zeros(3);
I = eye(3);
% P V theta
F = [
O I O O O;
O O -sk -Cb2n O;
O O O O -Cb2n;
O O O O O;
O O O O O];
% Approximation of the discret time state transition matrix
%
F = eye(15) + dt*F;
% Noise gain matrix
G=dt*[
O O O O;
Cb2n O O O;
O -Cb2n O O;
O O I O;
O O O I];
end
%% UWB
% Y UWB
% H
% anchor: M x N: M:3() N:
% dim: 2: 3
function [Y, H] = uwb_hx(x, anchor, dim)
N = size(anchor,2); %
% xyzxy
position = x(1:3);
if(dim)== 2
position = position(1:2);
anchor = anchor(1:2, 1:N);
% uwb.anchor
end
Y = []; % Y
H = []; %
% s
perd_pr = repmat(position,1,N) - anchor(:,1:N);
for i=1:N
if(dim)== 2
H = [H ;perd_pr(:,i)'/norm(perd_pr(:,i)),zeros(1,13)];
else
H = [H ;perd_pr(:,i)'/norm(perd_pr(:,i)),zeros(1,12)];
end
Y = [Y ;norm(perd_pr(:,i))];
end
end