传递对准MATLAB仿真程序

传递对准(Transfer Alignment)MATLAB仿真程序,包含卡尔曼滤波模型建立、运动轨迹生成和性能分析。

传递对准完整仿真程序

1. 主程序框架

matlab 复制代码
%% 传递对准仿真主程序 - 基于速度+姿态匹配的卡尔曼滤波
clear; close all; clc;
fprintf('========== 传递对准仿真程序 ==========\n');

%% 1. 仿真参数设置
dt = 0.01;                   % 采样时间 (s)
T_total = 60;                % 总仿真时间 (s)
t = 0:dt:T_total;            % 时间序列
N = length(t);               % 数据点数

% 主惯导(Master INS) - 高精度
master.pos = zeros(3, N);    % 位置 (m)
master.vel = zeros(3, N);    % 速度 (m/s)
master.att = zeros(3, N);    % 姿态: 滚转/俯仰/航向 (rad)

% 子惯导(Slave INS) - 低成本
slave.pos = zeros(3, N);
slave.vel = zeros(3, N);
slave.att = zeros(3, N);

%% 2. 生成运动轨迹(载体机动)
fprintf('生成载体运动轨迹...\n');
[motion_profile, maneuver_type] = generate_maneuver_trajectory(t, dt);

%% 3. 传递对准卡尔曼滤波器初始化
fprintf('初始化传递对准卡尔曼滤波器...\n');
[kf_params, state_names] = init_transfer_alignment_kf(dt);

%% 4. 主循环:仿真传递对准过程
fprintf('开始传递对准仿真...\n');
estimation_history = struct();
true_errors = struct();

for k = 1:N
    % 更新主惯导状态(含真实轨迹)
    [master, slave, true_err] = update_ins_states(master, slave, motion_profile, k, dt);
    true_errors = save_true_errors(true_errors, true_err, k);
    
    % 生成量测信息(速度/姿态匹配)
    measurements = generate_measurements(master, slave, k, kf_params);
    
    % 卡尔曼滤波:预测 + 更新
    if k > 1
        [kf_params, est] = kf_transfer_alignment(kf_params, measurements, k);
        estimation_history = save_estimation(estimation_history, est, k);
    end
    
    % 反馈校正(可选:开环或闭环)
    if mod(k, 100) == 0 && k > 10  % 每1秒反馈一次
        slave = apply_correction(slave, kf_params, k);
    end
    
    % 显示进度
    if mod(k, round(N/10)) == 0
        fprintf('进度: %.0f%%\n', k/N*100);
    end
end

%% 5. 结果分析与可视化
fprintf('\n========== 仿真结果分析 ==========\n');
analyze_and_plot_results(t, master, slave, true_errors, estimation_history, ...
                         kf_params, state_names, maneuver_type);

fprintf('传递对准仿真完成!\n');

2. 卡尔曼滤波模型核心实现

matlab 复制代码
function [kf_params, state_names] = init_transfer_alignment_kf(dt)
% 初始化传递对准卡尔曼滤波器参数
% 状态向量: [姿态误差(3), 速度误差(3), 位置误差(3), 陀螺零偏(3), 加表零偏(3), 杆臂误差(3), 安装失准角(3)]
% 共21个状态量

    n_states = 21;
    n_meas = 6;  % 速度差(3) + 姿态差(3)
    
    % 状态名称(用于绘图)
    state_names = {
        '滚转误差 (rad)', '俯仰误差 (rad)', '航向误差 (rad)', ...
        '东向速度误差 (m/s)', '北向速度误差 (m/s)', '天向速度误差 (m/s)', ...
        '纬度误差 (rad)', '经度误差 (rad)', '高度误差 (m)', ...
        '陀螺X零偏 (rad/s)', '陀螺Y零偏 (rad/s)', '陀螺Z零偏 (rad/s)', ...
        '加表X零偏 (m/s²)', '加表Y零偏 (m/s²)', '加表Z零偏 (m/s²)', ...
        '杆臂X (m)', '杆臂Y (m)', '杆臂Z (m)', ...
        '安装X角 (rad)', '安装Y角 (rad)', '安装Z角 (rad)'
    };
    
    % 初始状态估计
    kf_params.x_est = zeros(n_states, 1);
    kf_params.x_est(19:21) = deg2rad([0.5; 0.5; 1.0]);  % 安装失准角初值
    
    % 初始协方差矩阵
    kf_params.P = diag([
        deg2rad([0.5, 0.5, 1.0]).^2,    % 姿态误差 (rad^2)
        [0.1, 0.1, 0.1].^2,             % 速度误差 (m^2/s^2)
        deg2rad([0.0001, 0.0001]).^2, 0.1^2,  % 位置误差
        deg2rad([0.1, 0.1, 0.1]/3600).^2,     % 陀螺零偏 (rad^2/s^2)
        [1e-4, 1e-4, 1e-4].^2,          % 加表零偏 (m^2/s^4)
        [0.1, 0.1, 0.1].^2,             % 杆臂误差 (m^2)
        deg2rad([0.5, 0.5, 1.0]).^2     % 安装失准角 (rad^2)
    ]);
    
    % 过程噪声协方差矩阵 Q
    gyro_noise = deg2rad(0.1/3600);     % 陀螺角随机游走
    accel_noise = 1e-5;                 % 加表速度随机游走
    kf_params.Q = diag([
        zeros(1, 9),                    % 误差状态
        gyro_noise^2 * [1, 1, 1],       % 陀螺零偏驱动噪声
        accel_noise^2 * [1, 1, 1],      % 加表零偏驱动噪声
        zeros(1, 6)                     % 杆臂和安装角(假设常数)
    ]) * dt;
    
    % 量测噪声协方差矩阵 R
    vel_meas_noise = 0.01;              % 速度量测噪声 (m/s)
    att_meas_noise = deg2rad(0.1);      % 姿态量测噪声 (rad)
    kf_params.R = diag([vel_meas_noise^2 * [1, 1, 1], ...
                        att_meas_noise^2 * [1, 1, 1]]);
    
    % 系统矩阵 F (连续时间)
    kf_params.F_cont = zeros(n_states);
    % 姿态误差方程:φ_dot = -ω×φ + δω
    kf_params.F_cont(1:3, 1:3) = -skew_symmetric([0; 0; 7.292115e-5]); % 地球自转
    kf_params.F_cont(1:3, 10:12) = eye(3);  % 陀螺零偏
    
    % 速度误差方程:δv_dot = -f×φ + C_b^n δf + ...
    kf_params.F_cont(4:6, 1:3) = -skew_symmetric([0; 0; 9.8]);  % 重力/比力
    kf_params.F_cont(4:6, 13:15) = eye(3);  % 加表零偏
    
    % 位置误差方程
    kf_params.F_cont(7:9, 4:6) = eye(3);
    
    % 转换为离散时间系统矩阵
    kf_params.F = eye(n_states) + kf_params.F_cont * dt;
    
    % 控制输入矩阵(杆臂效应)
    kf_params.B = zeros(n_states, 3);
    kf_params.B(4:6, 1:3) = eye(3);  % 杆臂加速度到速度误差
    
    % 量测矩阵 H
    kf_params.H = zeros(n_meas, n_states);
    kf_params.H(1:3, 4:6) = eye(3);   % 速度误差观测
    kf_params.H(4:6, 1:3) = eye(3);   % 姿态误差观测
    kf_params.H(4:6, 19:21) = eye(3); % 安装失准角观测
    
    % 存储历史记录
    kf_params.history.state = zeros(n_states, N);
    kf_params.history.cov = zeros(n_states, N);
end

function [kf, est] = kf_transfer_alignment(kf, z, k)
% 传递对准卡尔曼滤波主函数(预测 + 更新)
    
    % ---------- 预测步骤 ----------
    % 状态预测
    kf.x_pred = kf.F * kf.x_est;
    
    % 协方差预测
    kf.P_pred = kf.F * kf.P * kf.F' + kf.Q;
    
    % ---------- 更新步骤 ----------
    % 计算卡尔曼增益
    S = kf.H * kf.P_pred * kf.H' + kf.R;
    K = kf.P_pred * kf.H' / S;
    
    % 计算新息(量测残差)
    innovation = z - kf.H * kf.x_pred;
    
    % 状态更新
    kf.x_est = kf.x_pred + K * innovation;
    
    % 协方差更新 (Joseph形式,数值更稳定)
    I = eye(size(kf.P));
    kf.P = (I - K * kf.H) * kf.P_pred * (I - K * kf.H)' + K * kf.R * K';
    
    % 存储结果
    kf.history.state(:, k) = kf.x_est;
    kf.history.cov(:, k) = diag(kf.P);
    
    % 返回估计值
    est.x_est = kf.x_est;
    est.innovation = innovation;
    est.K = K;
end

3. 运动轨迹生成函数

matlab 复制代码
function [profile, maneuver_type] = generate_maneuver_trajectory(t, dt)
% 生成载体机动轨迹(用于激励传递对准可观性)
    
    N = length(t);
    profile = struct();
    
    % 选择机动类型
    maneuver_list = {'摇摆', 'S形转弯', '加速度机动', '复合机动'};
    maneuver_type = maneuver_list{3};  % 可修改选择
    
    fprintf('机动类型: %s\n', maneuver_type);
    
    % 初始化运动参数
    profile.accel = zeros(3, N);  % 加速度 (m/s^2)
    profile.omega = zeros(3, N);  % 角速度 (rad/s)
    profile.pos = zeros(3, N);    % 位置 (m)
    profile.vel = zeros(3, N);    % 速度 (m/s)
    profile.att = zeros(3, N);    % 姿态 (rad)
    
    % 基础运动(匀速直线)
    vel_const = 20;  % 20 m/s
    profile.vel(1, :) = vel_const;
    
    switch maneuver_type
        case '摇摆'
            % 正弦摇摆运动(激励俯仰和滚转)
            amplitude = deg2rad(15);  % 15度幅度
            frequency = 0.5;          % 0.5 Hz
            
            profile.omega(2, :) = amplitude * 2*pi*frequency * ...
                                  cos(2*pi*frequency*t);  % 俯仰角速度
            profile.att(2, :) = amplitude * sin(2*pi*frequency*t);
            
            % 添加滚转激励
            profile.omega(1, :) = amplitude * 0.7 * 2*pi*frequency * ...
                                  sin(2*pi*frequency*t + pi/4);
            profile.att(1, :) = amplitude * 0.7 * -cos(2*pi*frequency*t + pi/4);
            
        case 'S形转弯'
            % S形转弯(激励航向)
            turn_rate = deg2rad(15);  % 15度/秒转弯率
            turn_duration = 10;       % 每次转弯10秒
            
            for k = 1:N
                phase = floor(t(k)/turn_duration);
                if mod(phase, 2) == 0
                    profile.omega(3, k) = turn_rate;  % 右转
                else
                    profile.omega(3, k) = -turn_rate; % 左转
                end
                profile.att(3, k) = profile.att(3, max(1,k-1)) + ...
                                    profile.omega(3, k) * dt;
            end
            
        case '加速度机动'
            % 加速度变化(激励杆臂效应)
            accel_profile = zeros(1, N);
            segments = floor(N/4);
            
            % 分段加速度
            accel_profile(1:segments) = 2.0;          % 加速
            accel_profile(segments+1:2*segments) = 0; % 匀速
            accel_profile(2*segments+1:3*segments) = -1.5; % 减速
            accel_profile(3*segments+1:end) = 0.5;    % 小加速
            
            profile.accel(1, :) = accel_profile;
            
            % 计算速度和位置
            for k = 2:N
                profile.vel(1, k) = profile.vel(1, k-1) + ...
                                   profile.accel(1, k) * dt;
                profile.pos(1, k) = profile.pos(1, k-1) + ...
                                   profile.vel(1, k) * dt;
            end
            
            % 添加角运动
            profile.omega(2, :) = deg2rad(5) * sin(2*pi*0.2*t);
            profile.att(2, :) = deg2rad(5)/ (2*pi*0.2) * (1 - cos(2*pi*0.2*t));
            
        case '复合机动'
            % 组合多种机动
            % 加速度变化
            profile.accel(1, :) = 1.0 * sin(2*pi*0.1*t);
            
            % 角运动
            profile.omega(1, :) = deg2rad(10) * sin(2*pi*0.3*t);  % 滚转
            profile.omega(2, :) = deg2rad(8) * cos(2*pi*0.25*t);  % 俯仰
            profile.omega(3, :) = deg2rad(12) * sin(2*pi*0.15*t); % 航向
            
            % 积分得到速度和姿态
            for k = 2:N
                profile.vel(:, k) = profile.vel(:, k-1) + ...
                                   profile.accel(:, k) * dt;
                profile.pos(:, k) = profile.pos(:, k-1) + ...
                                   profile.vel(:, k) * dt;
                profile.att(:, k) = profile.att(:, k-1) + ...
                                   profile.omega(:, k) * dt;
            end
    end
    
    % 添加噪声(真实环境)
    process_noise_level = 0.01;
    profile.accel = profile.accel + process_noise_level * randn(3, N);
    profile.omega = profile.omega + deg2rad(0.1) * randn(3, N);
end

4. 惯性导航更新函数

matlab 复制代码
function [master, slave, true_err] = update_ins_states(master, slave, motion, k, dt)
% 更新主/子惯导状态(包含真实误差)
    
    if k == 1
        % 初始状态
        master.att(:, 1) = deg2rad([0; 0; 45]);  % 初始航向45度
        slave.att(:, 1) = master.att(:, 1) + deg2rad([0.5; 0.3; 1.0]);  % 初始误差
        
        % 杆臂效应参数(真实值)
        true_err.lever_arm = [0.5; -0.3; 0.2];  % 主惯导到子惯导的杆臂 (m)
        true_err.misalignment = deg2rad([0.5; 0.5; 1.0]);  % 安装失准角 (rad)
        true_err.gyro_bias = deg2rad([0.1; -0.05; 0.08]/3600);  % 陀螺零偏 (rad/s)
        true_err.accel_bias = [1e-3; -5e-4; 2e-3];  % 加表零偏 (m/s^2)
        
        % 子惯导初始位置 = 主惯导位置 + 杆臂
        slave.pos(:, 1) = master.pos(:, 1) + true_err.lever_arm;
        
        return;
    end
    
    % ---------- 主惯导更新(假设完美) ----------
    % 获取当前运动参数
    omega = motion.omega(:, min(k, size(motion.omega, 2)));
    accel = motion.accel(:, min(k, size(motion.accel, 2)));
    
    % 姿态更新(四元数法)
    C_nb_prev = euler2dcm(master.att(:, k-1));
    delta_theta = omega * dt;
    C_nb_curr = C_nb_prev * (eye(3) + skew_symmetric(delta_theta));
    master.att(:, k) = dcm2euler(C_nb_curr);
    
    % 速度更新
    gravity = [0; 0; 9.7803267714];  % 重力向量
    master.vel(:, k) = master.vel(:, k-1) + ...
                      (C_nb_curr * accel + gravity) * dt;
    
    % 位置更新
    master.pos(:, k) = master.pos(:, k-1) + master.vel(:, k) * dt;
    
    % ---------- 子惯导更新(包含误差) ----------
    % 安装误差影响
    C_misalignment = euler2dcm(true_err.misalignment);
    
    % 子惯导处的比力(考虑杆臂效应)
    omega_dot = (omega - motion.omega(:, max(1,k-1))) / dt;
    lever_accel = skew_symmetric(omega_dot) * true_err.lever_arm + ...
                  skew_symmetric(omega) * skew_symmetric(omega) * true_err.lever_arm;
    
    accel_slave = accel + lever_accel;
    
    % 添加传感器误差
    gyro_slave = omega + true_err.gyro_bias + deg2rad(0.1/3600) * randn(3,1);
    accel_slave = accel_slave + true_err.accel_bias + 1e-4 * randn(3,1);
    
    % 子惯导姿态更新
    C_slave_prev = euler2dcm(slave.att(:, k-1));
    delta_theta_slave = gyro_slave * dt;
    C_slave_curr = C_slave_prev * (eye(3) + skew_symmetric(delta_theta_slave));
    slave.att(:, k) = dcm2euler(C_slave_curr);
    
    % 子惯导速度更新
    slave.vel(:, k) = slave.vel(:, k-1) + ...
                     (C_slave_curr * accel_slave + gravity) * dt;
    
    % 子惯导位置更新
    slave.pos(:, k) = slave.pos(:, k-1) + slave.vel(:, k) * dt;
    
    % 保存真实误差(用于验证)
    true_err.att_error = slave.att(:, k) - master.att(:, k);
    true_err.vel_error = slave.vel(:, k) - master.vel(:, k);
    true_err.pos_error = slave.pos(:, k) - master.pos(:, k);
end

5. 辅助工具函数

matlab 复制代码
function C = euler2dcm(euler)
% 欧拉角转换为方向余弦矩阵 (Z-Y-X顺序)
    phi = euler(1); theta = euler(2); psi = euler(3);
    
    Cx = [1, 0, 0; 0, cos(phi), sin(phi); 0, -sin(phi), cos(phi)];
    Cy = [cos(theta), 0, -sin(theta); 0, 1, 0; sin(theta), 0, cos(theta)];
    Cz = [cos(psi), sin(psi), 0; -sin(psi), cos(psi), 0; 0, 0, 1];
    
    C = Cz * Cy * Cx;  % 注意顺序:航向-俯仰-滚转
end

function euler = dcm2euler(C)
% 方向余弦矩阵转换为欧拉角
    phi = atan2(C(3,2), C(3,3));  % 滚转
    theta = -asin(C(3,1));        % 俯仰
    psi = atan2(C(2,1), C(1,1));  % 航向
    euler = [phi; theta; psi];
end

function S = skew_symmetric(v)
% 生成反对称矩阵
    S = [0, -v(3), v(2); 
         v(3), 0, -v(1); 
         -v(2), v(1), 0];
end

function measurements = generate_measurements(master, slave, k, kf_params)
% 生成量测信息(速度差 + 姿态差)
    
    % 速度差量测
    vel_diff = slave.vel(:, k) - master.vel(:, k);
    
    % 姿态差量测(通过方向余弦矩阵计算)
    C_master = euler2dcm(master.att(:, k));
    C_slave = euler2dcm(slave.att(:, k));
    C_diff = C_slave * C_master';
    
    % 将旋转矩阵转换为旋转向量(姿态误差)
    theta = acos((trace(C_diff) - 1)/2);
    if abs(theta) < 1e-10
        att_diff = zeros(3,1);
    else
        axis = [C_diff(3,2)-C_diff(2,3); 
                C_diff(1,3)-C_diff(3,1); 
                C_diff(2,1)-C_diff(1,2)] / (2*sin(theta));
        att_diff = theta * axis;
    end
    
    % 添加量测噪声
    vel_noise = sqrt(kf_params.R(1,1)) * randn(3,1);
    att_noise = sqrt(kf_params.R(4,4)) * randn(3,1);
    
    measurements = [vel_diff + vel_noise; att_diff + att_noise];
end

6. 结果分析与可视化

matlab 复制代码
function analyze_and_plot_results(t, master, slave, true_errors, ...
                                 estimation_history, kf_params, ...
                                 state_names, maneuver_type)
    
    fprintf('\n========== 对准性能分析 ==========\n');
    
    % 提取估计结果
    est_states = estimation_history.state;
    n_states = size(est_states, 1);
    
    % 计算对准误差
    final_att_error = rad2deg(slave.att(:, end) - master.att(:, end));
    final_vel_error = slave.vel(:, end) - master.vel(:, end);
    final_pos_error = slave.pos(:, end) - master.pos(:, end);
    
    fprintf('最终姿态误差: 滚转=%.4f°, 俯仰=%.4f°, 航向=%.4f°\n', ...
            final_att_error(1), final_att_error(2), final_att_error(3));
    fprintf('最终速度误差: [%.4f, %.4f, %.4f] m/s\n', ...
            final_vel_error(1), final_vel_error(2), final_vel_error(3));
    fprintf('最终位置误差: [%.4f, %.4f, %.4f] m\n', ...
            final_pos_error(1), final_pos_error(2), final_pos_error(3));
    
    % 1. 误差状态估计对比图
    figure('Position', [100, 100, 1400, 800]);
    
    % 姿态误差估计
    subplot(3, 4, 1:2);
    true_att_err = rad2deg(reshape([true_errors.att_error], 3, []));
    plot(t, true_att_err', '--', 'LineWidth', 1.5); hold on;
    plot(t, rad2deg(est_states(1:3, 1:length(t))'), '-', 'LineWidth', 1);
    xlabel('时间 (s)'); ylabel('姿态误差 (°)');
    title('姿态误差估计对比');
    legend('真实滚转', '真实俯仰', '真实航向', ...
           '估计滚转', '估计俯仰', '估计航向', 'Location', 'best');
    grid on;
    
    % 速度误差估计
    subplot(3, 4, 3:4);
    true_vel_err = reshape([true_errors.vel_error], 3, []);
    plot(t, true_vel_err', '--', 'LineWidth', 1.5); hold on;
    plot(t, est_states(4:6, 1:length(t))', '-', 'LineWidth', 1);
    xlabel('时间 (s)'); ylabel('速度误差 (m/s)');
    title('速度误差估计对比');
    legend('真实东向', '真实北向', '真实天向', ...
           '估计东向', '估计北向', '估计天向', 'Location', 'best');
    grid on;
    
    % 传感器零偏估计
    subplot(3, 4, 5:6);
    gyro_bias_est = rad2deg(est_states(10:12, :)) * 3600;  % 转换为°/h
    plot(t, gyro_bias_est', 'LineWidth', 1.5);
    xlabel('时间 (s)'); ylabel('陀螺零偏 (°/h)');
    title('陀螺零偏估计');
    legend('X轴', 'Y轴', 'Z轴', 'Location', 'best');
    grid on;
    
    subplot(3, 4, 7:8);
    accel_bias_est = est_states(13:15, :) * 1e3;  % 转换为mg
    plot(t, accel_bias_est', 'LineWidth', 1.5);
    xlabel('时间 (s)'); ylabel('加表零偏 (mg)');
    title('加表零偏估计');
    legend('X轴', 'Y轴', 'Z轴', 'Location', 'best');
    grid on;
    
    % 安装误差和杆臂估计
    subplot(3, 4, 9:10);
    misalignment_est = rad2deg(est_states(19:21, :));
    plot(t, misalignment_est', 'LineWidth', 1.5);
    xlabel('时间 (s)'); ylabel('安装失准角 (°)');
    title('安装失准角估计');
    legend('X轴', 'Y轴', 'Z轴', 'Location', 'best');
    grid on;
    
    subplot(3, 4, 11:12);
    lever_est = est_states(16:18, :);
    plot(t, lever_est', 'LineWidth', 1.5);
    xlabel('时间 (s)'); ylabel('杆臂 (m)');
    title('杆臂估计');
    legend('X轴', 'Y轴', 'Z轴', 'Location', 'best');
    grid on;
    
    sgtitle(sprintf('传递对准状态估计结果 - 机动类型: %s', maneuver_type));
    
    % 2. 收敛特性分析
    figure('Position', [100, 100, 1200, 400]);
    
    % 协方差收敛(3σ边界)
    subplot(1, 2, 1);
    sigma_att = 3 * sqrt(estimation_history.cov(1:3, :));
    plot(t, rad2deg(sigma_att'), 'LineWidth', 1.5);
    xlabel('时间 (s)'); ylabel('3σ边界 (°)');
    title('姿态误差协方差收敛');
    legend('滚转', '俯仰', '航向', 'Location', 'best');
    grid on;
    
    % 新息序列(检验滤波器一致性)
    subplot(1, 2, 2);
    innovations = estimation_history.innovation(1:3, :);
    plot(t, innovations', 'LineWidth', 1);
    hold on;
    innov_std = sqrt(kf_params.R(1,1));
    plot(t, 3*innov_std*ones(size(t)), 'r--', 'LineWidth', 1.5);
    plot(t, -3*innov_std*ones(size(t)), 'r--', 'LineWidth', 1.5);
    xlabel('时间 (s)'); ylabel('速度新息 (m/s)');
    title('新息序列及3σ边界');
    legend('东向', '北向', '天向', '±3σ', 'Location', 'best');
    grid on;
    
    % 3. 对准精度统计
    figure('Position', [100, 100, 800, 600]);
    
    % 计算稳态误差(最后10秒)
    steady_start = find(t >= t(end)-10, 1);
    steady_idx = steady_start:length(t);
    
    att_steady = rad2deg(est_states(1:3, steady_idx));
    vel_steady = est_states(4:6, steady_idx);
    
    att_std = std(att_steady, 0, 2);
    vel_std = std(vel_steady, 0, 2);
    
    subplot(2, 2, 1);
    bar([att_std'; vel_std']);
    set(gca, 'XTickLabel', {'姿态(°)', '速度(m/s)'});
    ylabel('稳态标准差');
    title('对准精度统计');
    legend('滚转/X轴', '俯仰/Y轴', '航向/Z轴', 'Location', 'best');
    grid on;
    
    % 收敛时间分析(达到95%最终值的时间)
    subplot(2, 2, 2);
    conv_time = zeros(3, 1);
    for i = 1:3
        final_val = abs(est_states(i, end));
        idx_95 = find(abs(est_states(i, :)) >= 0.95*final_val, 1);
        if ~isempty(idx_95)
            conv_time(i) = t(idx_95);
        end
    end
    bar(conv_time);
    ylabel('收敛时间 (s)');
    set(gca, 'XTickLabel', {'滚转', '俯仰', '航向'});
    title('主要状态收敛时间');
    grid on;
    
    % 机动效果分析
    subplot(2, 2, 3);
    % 计算不同机动阶段的估计精度
    if strcmp(maneuver_type, 'S形转弯')
        turn_period = 10;  % 转弯周期
        n_turns = floor(t(end)/turn_period);
        turn_accuracy = zeros(n_turns, 3);
        
        for turn = 1:n_turns
            turn_idx = find(t >= (turn-1)*turn_period & t < turn*turn_period);
            if ~isempty(turn_idx)
                turn_accuracy(turn, :) = std(rad2deg(est_states(1:3, turn_idx)), 0, 2)';
            end
        end
        
        plot(1:n_turns, turn_accuracy, 'o-', 'LineWidth', 1.5);
        xlabel('转弯序号'); ylabel('姿态误差标准差 (°)');
        title('不同转弯阶段对准精度');
        legend('滚转', '俯仰', '航向', 'Location', 'best');
        grid on;
    end
    
    % 杆臂效应估计精度
    subplot(2, 2, 4);
    lever_true = true_errors.lever_arm;
    lever_est_final = est_states(16:18, end);
    lever_error = abs(lever_est_final - lever_true);
    
    bar(lever_error);
    ylabel('杆臂估计绝对误差 (m)');
    set(gca, 'XTickLabel', {'X轴', 'Y轴', 'Z轴'});
    title('杆臂估计最终精度');
    grid on;
    
    fprintf('\n========== 对准性能总结 ==========\n');
    fprintf('机动类型: %s\n', maneuver_type);
    fprintf('姿态对准精度 (3σ): 滚转=%.4f°, 俯仰=%.4f°, 航向=%.4f°\n', ...
            3*att_std(1), 3*att_std(2), 3*att_std(3));
    fprintf('速度对准精度 (3σ): [%.4f, %.4f, %.4f] m/s\n', ...
            3*vel_std(1), 3*vel_std(2), 3*vel_std(3));
    fprintf('航向收敛时间: %.2f s\n', conv_time(3));
end

7. 程序使用说明

  1. 运行方式

    • 将以上所有函数保存为独立的.m文件或放在一个文件中运行
    • 从主程序开始执行
  2. 关键参数调整

    matlab 复制代码
    % 在init_transfer_alignment_kf函数中调整:
    - 初始协方差P:影响收敛速度
    - 过程噪声Q:模型不确定性
    - 量测噪声R:传感器精度
    
    % 在generate_maneuver_trajectory函数中调整:
    - 机动类型:选择不同激励运动
    - 机动幅度:影响可观性
  3. 仿真场景定制

    • 修改true_err结构体中的误差参数模拟不同设备
    • 添加新的机动类型以测试不同环境下的对准性能
    • 修改量测方案(如增加位置匹配)

参考代码 关于传递对准的MATLAB仿真源代码 www.3dddown.com/csa/97398.html

8. 扩展功能建议

  1. 多算法比较

    matlab 复制代码
    % 实现UKF、EKF等不同滤波器的比较
    algorithms = {'EKF', 'UKF', 'PF'};
    results = cell(length(algorithms), 1);
    for i = 1:length(algorithms)
        results{i} = run_transfer_alignment(algorithm);
    end
  2. 硬件在环测试接口

    matlab 复制代码
    % 添加串口/UDP接口接收真实IMU数据
    function real_data = read_imu_from_port(port)
        % 从硬件读取数据
    end
相关推荐
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨7 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区8 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大9 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai9 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜9 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa10 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio