非线性滤波——基于EKF的INS/GPS松组合算法的研究(间接法|EKF|欧拉角)

2023-10-12 06:59

本文主要是介绍非线性滤波——基于EKF的INS/GPS松组合算法的研究(间接法|EKF|欧拉角),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在之前的博文《非线性滤波——基于EKF的INS/GPS松组合算法的研究(直接法|EKF|欧拉角)》中,我们记录了直接形式的EKF实现INS/GPS松组合算法,并在《卡尔曼滤波——直接法VS间接法》中对比说明了直接法与间接法的优劣。本文,我们记录使用间接反馈校正形式的EKF算法实现INS/GPS松组合算法。

建立模型

本文的INS/GPS组合模型主要参考文献:
Barton, Jeffrey. (2012). Fundamentals of Small Unmanned Aircraft Flight. Johns Hopkins Apl Technical Digest. 31. 132-149.
实验数据来源于之前的博客:非线性滤波——INS/GPS组合导航仿真数据的生成

INS/GPS的松组合模型可以用状态方程和测量方程描述与《非线性滤波——基于EKF的INS/GPS松组合算法的研究(直接法|EKF|欧拉角)》中一致,此处将其简记为
x ˙ = f ( x ) + w ( t ) , w ( t ) ∼ N ( 0 , Q ) \dot{\bold{x}}=f(\bold{x})+\bold{w}(t), \mathbf{w}(t) \sim N(0, \mathbf{Q}) x˙=f(x)+w(t),w(t)N(0,Q)

z ˉ = h ( x ) + v ( t ) , v ( t ) ∼ N ( 0 , R ) \bar{\bold{z}}=h(\bold{x})+\bold{v}(t), \mathbf{v}(t) \sim N(0, \mathbf{R}) zˉ=h(x)+v(t),v(t)N(0,R)

假设在时刻 t t t的状态 x ( t ) \bold{x}(t) x(t)是未知的,但我们知道其大致范围,则可以选定一个值 x ∗ ( t ) \bold{x}^*(t) x(t),只要得到了 δ x ( t ) = x ( t ) − x ∗ ( t ) \bold{\delta x}(t)=\bold{x}(t)-\bold{x}^{*}(t) δx(t)=x(t)x(t)的估计,就可以修正 x ∗ ( t ) \bold{x}^*(t) x(t),从而得到对 x ( t ) \bold{x}(t) x(t)更准确的估计。
在选取 x ∗ ( t ) \bold{x}^*(t) x(t)时需要满足以下关系
x ∗ ( t ) = f ( x ∗ ( t ) ) \bold{x}^*(t) = f(\bold{x}^*(t)) x(t)=f(x(t))

z ∗ ( t ) = h ( x ∗ ( t ) ) \bold{z}^*(t)=h(\bold{x}^*(t)) z(t)=h(x(t))
将上面两个方程与模型本身相减,并用泰勒级数展开,略去高阶项,得到
δ x ˙ ( t ) = F ( t ) δ x ( t ) + w ( t ) \delta \dot {\bold{{x}}}(t)=\boldsymbol{F}(t) \delta \bold{x}(t)+\bold{w}(t) δx˙(t)=F(t)δx(t)+w(t)

δ z = H ( t ) δ x ( t ) + v ( t ) \delta{\bold{z}}=\boldsymbol{H}(t) \delta \bold{x}(t)+\bold{v}(t) δz=H(t)δx(t)+v(t)
其中
F ( t ) = ∂ f ∂ x ∣ x ∗ , H ( t ) = ∂ h ∂ x ∣ x ∗ \boldsymbol{F}(t)=\left.\frac{\partial f}{\partial x}\right|_{x^{*}}, \boldsymbol{H}(t)=\left.\frac{\partial \boldsymbol{h}}{\partial \boldsymbol{x}}\right|_{x^{*}} F(t)=xfx,H(t)=xhx
其余步骤与之前的博文《非线性滤波——基于EKF的INS/GPS松组合算法的研究(直接法|EKF|欧拉角)》相同。
特别注意: 在程序中对误差状态量进行一步预测时,与直接法不同,需要将误差状态的一步预测值置零。因为在最后一步状态修正中
x ^ k + 1 ∣ k + 1 = x ^ k + 1 ∣ k + δ x ^ k + 1 ∣ k + 1 \hat{\bold{x}}_{k+1 | k+1}=\hat{\bold{x}}_{k+1 | k}+\delta \hat{\bold{x}}_{k+1 | k+1} x^k+1k+1=x^k+1k+δx^k+1k+1
经过修正后有
x ^ k + 1 ∣ k + 1 = E { x ( t k + 1 ) } \widehat{\bold{x}}_{k+1 | k+1}=E\left\{\bold{x}\left(t_{k+1}\right)\right\} x k+1k+1=E{x(tk+1)}
所以 δ x ^ k + 1 ∣ k + 1 = 0 \delta \hat{\bold{x}}_{k+1 | k+1}=0 δx^k+1k+1=0,也就 δ x ^ k ∣ k = 0 \delta \hat{\bold{x}}_{k | k}=0 δx^kk=0

仿真实现

本文代码在github及gitee(国内镜像)中不定时维护,代码内容可能与本文有所出入,地址:
https://github.com/tsuibeyond/BasicEKF
https://gitee.com/tsuibeyond/BasicEKF

clc
clear % 生成仿真数据
generate_uav_sensors_structure;% 重力加速度常量,m/s^2
g_mps2 = 9.81;  % 定义directEKF算法相关变量
ekf = [];
% 磁强计和GPS测量噪声估计,用于构造 R 矩阵
ekf.sigmas.mag2D_meas_rad        = sqrt(uavSensors.sigmas.mag2D_yaw_noise_rad^2);
ekf.sigmas.pos_meas_m            = sqrt(uavSensors.sigmas.GPSpos_noise_m^2);
ekf.sigmas.vel_meas_mps          = sqrt(uavSensors.sigmas.GPSvel_noise_mps^2);
ekf.R_gps = diag([...[1 1 1]*ekf.sigmas.pos_meas_m ...            % North-East-Alt position measurement noise, m[1 1 1]*ekf.sigmas.vel_meas_mps ...          % NED velocity measurement noise, m/s].^2);
ekf.R_gps = max(ekf.R_gps,(1e-3)^2*eye(size(ekf.R_gps)));    
ekf.R_mag2d = ekf.sigmas.mag2D_meas_rad;
ekf.R_mag2d = max(ekf.R_mag2d,(1e-3)^2*eye(size(ekf.R_mag2d)));   % 陀螺仪和加速度计初始估计的不确定度,用于构造P矩阵(协方差矩阵)
ekf.sigmas.gyro_bias_rps         = uavSensors.sigmas.gyro_bias_rps;
ekf.sigmas.accel_bias_mps2       = uavSensors.sigmas.accel_bias_mps2;% EKF过程噪声估计,用于构造 Q 矩阵
% Q 矩阵需要根据经验调节。Q 值代表了我们对状态模型的置信程度
ekf.sigmas.attitude_process_noise_rad = 0.002;%0.002;% Euler angle process noise, rad
ekf.sigmas.pos_process_noise_m = 0.005;%0;           % Position process noise, m
ekf.sigmas.vel_process_noise_mps = 0.001;%2;         % Velocity process noise, m/s
ekf.sigmas.gyroBias_process_noise_rps = 1e-5;%1e-6; % Gyro bias process noise, rad/s
ekf.sigmas.accelBias_process_noise_mps2=1e-5;%1e-6; % Accel bias process noise, m/s^2
ekf.Q = diag([...[1 1 1]*ekf.sigmas.attitude_process_noise_rad ...   % Euler angle process noise, rad[1 1 1]*ekf.sigmas.pos_process_noise_m ...          % North-East-Alt position process noise, m[1 1 1]*ekf.sigmas.vel_process_noise_mps ...        % NED velocity process noise, m/s[1 1 1]*ekf.sigmas.gyroBias_process_noise_rps ...   % XYZ gyro bias process noise, rad/s[1 1 1]*ekf.sigmas.accelBias_process_noise_mps2 ... % XYZ accel bias process noise, m/s^2].^2);
ekf.Q = max(ekf.Q,(1e-3)^2*eye(size(ekf.Q)));    % 设定EKF状态误差向量初始值
err_euler_init = [ 0 0 0 ];   % 欧拉角误差初始值, rad
err_pos_init = [ 0 0 0 ];
err_vel_init = [ 0 0 0 ];
ekf.xhat_err = [ ...err_euler_init ...                              %   1-3:Euler angle (Roll, Pitch, Yaw) 状态进行初始化,raderr_pos_init ...                                %   4-6: 对 North-East-Alt 位置状态进行初始化, merr_vel_init ...                                %   7-9: 对 NED 速度状态初始化, m/s[0 0 0] ...                                 % 10-12: 对 XYZ 三轴陀螺仪的常值偏差进行初始化, rad/s[0 0 0] ...                                 % 13-15: 对 XYZ 三轴加速度计的长治偏差进行初始化, m/s^2]';
clear err_euler_init err_pos_init err_vel_init% 设定EKF状态向量初始值
phi = 0;                                   % 横滚角初始值,rad
theta=0;                                   % 俯仰角初始值,rad
psi = uavSensors.mag2D_yaw_deg(1)*pi/180;  % 偏航角初始值, rad
euler_init = [ phi theta psi ];   
pos_init = [ uavSensors.GPS_north_m(1) uavSensors.GPS_east_m(1) uavSensors.GPS_h_msl_m(1) ];
vel_init = uavSensors.GPS_v_ned_mps(1,:);
ekf.xhat_ins = [ ...euler_init ...                              %   1-3:Euler angle (Roll, Pitch, Yaw) 状态进行初始化,radpos_init ...                                %   4-6: 对 North-East-Alt 位置状态进行初始化, mvel_init ...                                %   7-9: 对 NED 速度状态初始化, m/s[0 0 0] ...                                 % 10-12: 对 XYZ 三轴陀螺仪的常值偏差进行初始化, rad/s[0 0 0] ...                                 % 13-15: 对 XYZ 三轴加速度计的长治偏差进行初始化, m/s^2]';
clear psi theta phi euler_init pos_init vel_init% 对初始的协方差矩阵(P矩阵)设定较大值,以便EKF算法在初始的几次滤波步骤中更多的相信测量方程
large_angle_uncertainty_rad = 30*pi/180;
large_pos_uncertainty_m = 100;
large_vel_uncertainty_mps = 10;
ekf.P = diag([...[1 1 1]*large_angle_uncertainty_rad ...     % init Euler angle (NED-to-body) uncertainties, rad[1 1 1]*large_pos_uncertainty_m ...         % init North-East-Alt position uncertainties, m[1 1 1]*large_vel_uncertainty_mps ...       % init NED velocity uncertainties, m/s[1 1 1]*ekf.sigmas.gyro_bias_rps ...        % init XYZ gyro bias uncertainties, rad/s[1 1 1]*ekf.sigmas.accel_bias_mps2 ...      % init XYZ accel bias uncertainties, m/s^2].^2);
ekf.P = max(ekf.P,(1e-3)^2*eye(size(ekf.P)));    % 为了避免gyro_bias_rps和accel_bias_mps2设定为0
clear large_angle_uncertainty_rad large_pos_uncertainty_m large_vel_uncertainty_mps% 定义uavEst结构体并分配内存空间,用于存储估计的中间结果
uavEst.xhat = zeros(length(uavTruth.time_s),length(ekf.xhat_ins));
uavEst.P = zeros(length(uavTruth.time_s),length(ekf.xhat_ins));for kTime = 1 : length(uavSensors.time_s)% 计算两次滤波的时间间隔time_s                  = uavSensors.time_s(kTime);if kTime == 1dt_s = uavSensors.time_s(2) - uavSensors.time_s(1);elsedt_s = time_s - uavSensors.time_s(kTime-1);end% 获取滤波器所估计的状态量phi=ekf.xhat_ins(1);    theta=ekf.xhat_ins(2);  psi=ekf.xhat_ins(3);	% Roll, Pitch, Yaw Euler angles, radPn=ekf.xhat_ins(4); Pe=ekf.xhat_ins(5); Alt=ekf.xhat_ins(6);            % Position, North/East/Altitude, metersVn=ekf.xhat_ins(7); Ve=ekf.xhat_ins(8); Vd=ekf.xhat_ins(9);             % Velocity, North/East/Down, m/sbwx=ekf.xhat_ins(10);   bwy=ekf.xhat_ins(11);   bwz=ekf.xhat_ins(12);	% Gyro biases, rad/sbax=ekf.xhat_ins(13);   bay=ekf.xhat_ins(14);   baz=ekf.xhat_ins(15);	% Accelerometer biases, m/s^2% IMU 更新gyro_wb_rps             = uavSensors.gyro_wb_rps(kTime,:)';                     % 3x1 vectoraccel_fb_mps2           = uavSensors.accel_fb_mps2(kTime,:)';                   % 3x1 vectorwx = gyro_wb_rps(1);    wy = gyro_wb_rps(2);    wz = gyro_wb_rps(3);            % rad/sfx = accel_fb_mps2(1);    fy = accel_fb_mps2(2);    fz = accel_fb_mps2(3);      % m/s^2% 计算 xdotC_bodyrate2eulerdot  = [1      sin(phi)*tan(theta)    cos(phi)*tan(theta); ...0           cos(phi)                -sin(phi)    ; ...0      sin(phi)*sec(theta)    cos(phi)*sec(theta)];C_ned2b  = [cos(theta)*cos(psi)                               cos(theta)*sin(psi)                             -sin(theta); ...sin(phi)*sin(theta)*cos(psi)-cos(phi)*sin(psi)    sin(phi)*sin(theta)*sin(psi)+cos(phi)*cos(psi)   sin(phi)*cos(theta); ...cos(phi)*sin(theta)*cos(psi)+sin(phi)*sin(psi)    cos(phi)*sin(theta)*sin(psi)-sin(phi)*cos(psi)   cos(phi)*cos(theta)];C_b2ned=transpose(C_ned2b);xdot = [ ...C_bodyrate2eulerdot*([wx;wy;wz]-[bwx;bwy;bwz]); ...  % Derivative of [roll; pitch; yaw][Vn; Ve; -Vd]; ...                                   % Derivative of [Pn; Pe; Alt]C_b2ned*([fx;fy;fz]-[bax;bay;baz])+[0;0;g_mps2]; ... % Derivative of [Vn; Ve; Vd][0;0;0]; ...                                         % Derivative of [bwx; bwy; bwz][0;0;0]; ...                                         % Derivative of [bax; bay; baz]];% 计算 F 矩阵F = [ ...[                                                                 sin(phi)*tan(theta)*(bwz - wz) - cos(phi)*tan(theta)*(bwy - wy),                                  - cos(phi)*(bwz - wz)*(tan(theta)^2 + 1) - sin(phi)*(bwy - wy)*(tan(theta)^2 + 1),                                                                                                                                                              0, 0, 0, 0, 0, 0,  0, -1, -sin(phi)*tan(theta), -cos(phi)*tan(theta),                    0,                                                  0,                                                  0][                                                                                       cos(phi)*(bwz - wz) + sin(phi)*(bwy - wy),                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,            -cos(phi),             sin(phi),                    0,                                                  0,                                                  0][                                                             (sin(phi)*(bwz - wz))/cos(theta) - (cos(phi)*(bwy - wy))/cos(theta),                    - (cos(phi)*sin(theta)*(bwz - wz))/cos(theta)^2 - (sin(phi)*sin(theta)*(bwy - wy))/cos(theta)^2,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0, -sin(phi)/cos(theta), -cos(phi)/cos(theta),                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 1, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 1,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0, -1,  0,                    0,                    0,                    0,                                                  0,                                                  0][ - (sin(phi)*sin(psi) + cos(phi)*cos(psi)*sin(theta))*(bay - fy) - (cos(phi)*sin(psi) - cos(psi)*sin(phi)*sin(theta))*(baz - fz), cos(psi)*sin(theta)*(bax - fx) - cos(phi)*cos(psi)*cos(theta)*(baz - fz) - cos(psi)*cos(theta)*sin(phi)*(bay - fy), (cos(phi)*cos(psi) + sin(phi)*sin(psi)*sin(theta))*(bay - fy) - (cos(psi)*sin(phi) - cos(phi)*sin(psi)*sin(theta))*(baz - fz) + cos(theta)*sin(psi)*(bax - fx), 0, 0, 0, 0, 0,  0,  0,                    0,                    0, -cos(psi)*cos(theta),   cos(phi)*sin(psi) - cos(psi)*sin(phi)*sin(theta), - sin(phi)*sin(psi) - cos(phi)*cos(psi)*sin(theta)][   (cos(psi)*sin(phi) - cos(phi)*sin(psi)*sin(theta))*(bay - fy) + (cos(phi)*cos(psi) + sin(phi)*sin(psi)*sin(theta))*(baz - fz), sin(psi)*sin(theta)*(bax - fx) - cos(phi)*cos(theta)*sin(psi)*(baz - fz) - cos(theta)*sin(phi)*sin(psi)*(bay - fy), (cos(phi)*sin(psi) - cos(psi)*sin(phi)*sin(theta))*(bay - fy) - (sin(phi)*sin(psi) + cos(phi)*cos(psi)*sin(theta))*(baz - fz) - cos(psi)*cos(theta)*(bax - fx), 0, 0, 0, 0, 0,  0,  0,                    0,                    0, -cos(theta)*sin(psi), - cos(phi)*cos(psi) - sin(phi)*sin(psi)*sin(theta),   cos(psi)*sin(phi) - cos(phi)*sin(psi)*sin(theta)][                                                                 cos(theta)*sin(phi)*(baz - fz) - cos(phi)*cos(theta)*(bay - fy),                            cos(theta)*(bax - fx) + cos(phi)*sin(theta)*(baz - fz) + sin(phi)*sin(theta)*(bay - fy),                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,           sin(theta),                               -cos(theta)*sin(phi),                               -cos(phi)*cos(theta)][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0][                                                                                                                               0,                                                                                                                  0,                                                                                                                                                              0, 0, 0, 0, 0, 0,  0,  0,                    0,                    0,                    0,                                                  0,                                                  0]];    % 计算 PHI_k & Q_k 矩阵(一步预测矩阵 和 离散形式的过程噪声矩阵)nStates = length(ekf.xhat_ins);AA = [-F ekf.Q; zeros(nStates,nStates) F']*dt_s;BB = expm(AA); % <- Matrix exponential!PHI_k = BB(nStates+1:2*nStates,nStates+1:2*nStates)';Q_k = PHI_k*BB(1:nStates,nStates+1:2*nStates);% 一步预测 & 更新协方差ekf.xhat_ins = ekf.xhat_ins + xdot*dt_s;ekf.xhat_err = 0*ekf.xhat_err;ekf.P = PHI_k*ekf.P*PHI_k' + Q_k;% 磁强计测量融合(更新频率与IMU一致)mag2D_yaw_rad           = uavSensors.mag2D_yaw_deg(kTime)*pi/180;ekf.H_mag2d = [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];ekf.K_mag2d = (ekf.P*ekf.H_mag2d')/(ekf.H_mag2d*ekf.P*ekf.H_mag2d'+ekf.R_mag2d);% 消除yaw角的范围约束while mag2D_yaw_rad>ekf.xhat_ins(3)+pi, mag2D_yaw_rad=mag2D_yaw_rad-2*pi; endwhile mag2D_yaw_rad<ekf.xhat_ins(3)-pi, mag2D_yaw_rad=mag2D_yaw_rad+2*pi; end
%     ekf.Z_mag2d = mag2D_yaw_rad;ekf.Z_mag2d_err = mag2D_yaw_rad - ekf.H_mag2d*ekf.xhat_ins;ekf.xhat_err = ekf.xhat_err + ekf.K_mag2d*(ekf.Z_mag2d_err - ekf.H_mag2d*ekf.xhat_err);ekf.P = (eye(length(ekf.xhat_ins))-ekf.K_mag2d*ekf.H_mag2d)*ekf.P;ekf.xhat_ins = ekf.xhat_ins + ekf.xhat_err;% GPS 测量更新 (更新频率较低)GPS_east_m              = uavSensors.GPS_east_m(kTime);GPS_north_m             = uavSensors.GPS_north_m(kTime);GPS_h_msl_m             = uavSensors.GPS_h_msl_m(kTime);GPS_v_ned_mps           = uavSensors.GPS_v_ned_mps(kTime,:)';            % 3x1 vectorGPS_valid               = uavSensors.GPS_valid(kTime);if GPS_validekf.H_gps = [ ...[ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0][ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0][ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0][ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]];ekf.K_gps = (ekf.P*ekf.H_gps')/(ekf.H_gps*ekf.P*ekf.H_gps'+ekf.R_gps);ekf.Z_gps = [ ...[GPS_north_m; GPS_east_m; GPS_h_msl_m];GPS_v_ned_mps];ekf.Z_gps_err = ekf.Z_gps - ekf.H_gps*ekf.xhat_ins;ekf.xhat_err = ekf.xhat_err + ekf.K_gps*(ekf.Z_gps_err - ekf.H_gps*ekf.xhat_err);ekf.P = (eye(length(ekf.xhat_ins))-ekf.K_gps*ekf.H_gps)*ekf.P;ekf.xhat_ins = ekf.xhat_ins + ekf.xhat_err;end% uavEst.xhat(kTime,:) = ekf.xhat_ins';
enduavEst.time_s = uavSensors.time_s;
uavEst.north_m = uavEst.xhat(:,4);
uavEst.east_m = uavEst.xhat(:,5);
uavEst.h_msl_m = uavEst.xhat(:,6);
uavEst.v_ned_mps = uavEst.xhat(:,7:9);
uavEst.roll_deg = rad2deg(uavEst.xhat(:,1));
uavEst.pitch_deg = rad2deg(uavEst.xhat(:,2));
uavEst.yaw_deg = rad2deg(uavEst.xhat(:,3));% 估计结果可视化
figure(1)
clf;
% 绘图的线型和点型设置
truthLineType    = 'b-';
sensedLineType   = 'gd';
estimateLineType = 'r.';
markerSize       = 6;
linewidth        = 2;%-东方向的位置估计结果
subplot(4,2,[1 3])
plot(uavSensors.GPS_east_m, uavSensors.GPS_north_m, sensedLineType, ...uavEst.east_m,         uavEst.north_m,         estimateLineType, ...uavTruth.east_m,       uavTruth.north_m,       truthLineType, ...'markersize',markerSize, 'linewidth', linewidth);
hold on
plot(uavTruth.east_m(1),uavTruth.north_m(1),'co', ...'markersize',1.5*markerSize, 'linewidth', 2*linewidth);
hold off
axis equal
grid on
xlabel('East, m'); ylabel('North, m')
title('UAV Position')
legend('GPS Meas.','Est. Pos.','True Pos.','Start','location','best')% 海拔高度估计结果
subplot(4,2,5)
plot(uavSensors.time_s, uavSensors.GPS_h_msl_m, sensedLineType, ...uavEst.time_s,     uavEst.h_msl_m,         estimateLineType, ...uavTruth.time_s,   uavTruth.h_msl_m,       truthLineType, ...'markersize',markerSize, 'linewidth', linewidth);
grid on
xlabel('Time, s'); ylabel('Altitude, above MeanSeaLevel, m')
legend('GPS Meas.','Est. Alt','True Alt','location','best')%--地 速度估计结果
subplot(4,2,7)
mag = @(v)(sqrt(sum(v.^2,2))); % magnitude of each row
plot(uavSensors.time_s, mag(uavSensors.GPS_v_ned_mps), sensedLineType, ...uavEst.time_s,     mag(uavEst.v_ned_mps),         estimateLineType, ...uavTruth.time_s,   mag(uavTruth.v_ned_mps),       truthLineType, ...'markersize',markerSize, 'linewidth', linewidth);
grid on
xlabel('Time, s'); ylabel('Inertial Speed, m/s')
legend('GPS Meas.','Est. Speed','True Speed','location','best')% 横滚角估计结果
subplot(3,2,2); 
plot(uavEst.time_s,     uavEst.roll_deg,    estimateLineType, ...uavTruth.time_s,   uavTruth.roll_deg,  truthLineType, ...    'markersize',markerSize, 'linewidth', linewidth);
grid on
xlabel('Time, s'); ylabel('Roll Angle, deg')
title('UAV Attitude: Roll')
legend('Est. Roll','True Roll','location','best')% 俯仰角估计结果
subplot(3,2,4); 
plot(uavEst.time_s,     uavEst.pitch_deg,    estimateLineType, ...uavTruth.time_s,   uavTruth.pitch_deg,  truthLineType, ...     'markersize',markerSize, 'linewidth', linewidth);
grid on
xlabel('Time, s'); ylabel('Pitch Angle, deg')
title('UAV Attitude: Pitch')
legend('Est. Pitch','True Pitch','location','best')% 偏航角估计结果(-180,180subplot(3,2,6);
wrap = @(angleDeg)(mod(angleDeg+180,360)-180); % Wrap from -180deg to 180deg.
plot(uavSensors.time_s, wrap(uavSensors.mag2D_yaw_deg), sensedLineType, ...uavEst.time_s,     wrap(uavEst.yaw_deg),           estimateLineType, ...uavTruth.time_s,   wrap(uavTruth.yaw_deg),         truthLineType, ...     'markersize',markerSize, 'linewidth', linewidth);
grid on
xlabel('Time, s'); ylabel('Yaw Angle, deg')
title('UAV Attitude: Yaw')
legend('Magnetometer','Est. Yaw','True Yaw','location','best')

仿真结果

在这里插入图片描述

这篇关于非线性滤波——基于EKF的INS/GPS松组合算法的研究(间接法|EKF|欧拉角)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/194138

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

Open3D 基于法线的双边滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 输入参数: 输出参数: 参数影响: 2.2完整代码 三、实现效果 3.1原始点云 3.2滤波后点云 Open3D点云算法汇总及实战案例汇总的目录地址: Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客 一、概述         基于法线的双边

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int