0
点赞
收藏
分享

微信扫一扫

估计IMU和车辆之间的安装角度

这里写自定义目录标题

前言

在SINS/NHC组合导航中,需要得到IMU和车辆之间的安装角,以及IMU和车轮(非转向轮)之间的杆臂。论文《Estimation of IMU Mounting Angles for Land Vehicular GNSS/INS Integrated System》给出了一种基于EKF的估计安装角的方法,有相应的论文和代码,代码链接如下:
Estimation of IMU Mounting Angles for Land Vehicular GNSS/INS Integrated System
其主要思路是把里程计速度(或里程增量)先从车辆坐标系转换到IMU坐标系,再从IMU坐标系转换到导航坐标系,构成一个DR系统,通过DR输出的位置和SINS/GNSS构成的后处理系统输出的位置相减,构成观测变量。对于没有里程计的车辆来说,代码中的思路是通过SINS/GNSS系统的PPK位置结果(导航系),通过转换矩阵转换到IMU坐标系,再转到车辆坐标系(初始IMU到车辆坐标系为单位矩阵)构成一个虚拟的里程计数据源。

论文公式推导

代码解读

1.main函数

function main()

close all;
% -------------------------------------------------------------------------
% This open-source program implementing the IMU mounting angle estimation
% KF may help the readers in understanding the algorithm designed in the 
% manuscript - 
%  Qijin Chen, Xiaoji Niu, Jingnan Liu, "Estimation of 
%  IMU Mounting Angles for Land Vehicular GNSS/INS Integrated System"
% 
%  Please read the user manual for the definitions of the raw data format. 
% -------------------------------------------------------------------------
% Author:
% Qijin Chen, GNSS Research Center, Wuhan University, China.;
% chenqijin@whu.edu.cn;
% Nov. 2019;
% -------------------------------------------------------------------------
% close all; clear; clc
% step 1: set configuration 
cfg.fins = '.\data\ains_imu2.bin';   % raw GNSS/INS smoothing result; change to process different IMU data.
cfg.imutype = 'imu2';       % IMU type; 'imu1', 'imu2', 'imu3' for the three simulated IMUs
cfg.session = [800; 1200];  % time segment of the trajectory used as input to the KF estimator

% preprocess the GNSS/INS smoothing solution :1) derive traveled distance
% from GNSS/INS position; 2) resample GNSS/INS smoothing solution in
% distance domain. 
% 0.1米
cfg.fds = 0.1; % distance interval for resample the raw GNSS/INS smoothing solution
data_ains = dataPreproc(cfg);

% Kalman filter tuning, P0, Q, R matrice.
cfg = paraTuning(cfg);

% step 2: KF estimator
nav = mas_ekf(data_ains, cfg);

% step 3: show results
cfg.plot_ma = 1;
cfg.plot_att_err = 1;
cfg.plot_odosf = 1;
plotResult(nav, cfg);


end

function cfg = paraTuning(cfg)
%% P0 matrix
% Uncertainty of the initial mounting angles(zeros). 
cfg.ini_ma_std = [1; 2] *pi/180.0;       % 1 deg for pitch-, 2 deg for heading-mounting angle, respectively.

% Uncertainty of the scale factor error of the distance measurement derived
% from GNSS/INS smoothing position. 
% 标度因子
cfg.ini_odosf_std = 100 *1.0e-6;         % 100 ppm

% Scale to enlarge the initial attitude uncertainty. 
cfg.attstd_scale = 1.0; % 欧拉角不确定度的倍数

%% Q matrix
% ARW: angular random walk, i.e., white noise. of the gyro outputs
% 角度随机游走
switch cfg.imutype
    case 'imu1'
        cfg.q_arw = 0.0022 *pi/180.0/60; % deg/sqrt(h) -> rad/sqrt(s)       
    case 'imu2'
        cfg.q_arw = 0.15 *pi/180.0/60;
    case 'imu3'
        cfg.q_arw = 0.1 *pi/180.0/60;
    otherwise
        cfg.q_arw = 0.1 *pi/180.0/60;
end
% covariance of the noise in modeling the pitch- and heading-mounting angles
cfg.q_ma_p = 0.001 *pi/180.0/60;    % for pitch-mounting angle
cfg.q_ma_y = 0.001 *pi/180.0/60;    % for heading-mounting angle
cfg.q_odosf = 1.0 *1.0e-6;          % for scale factor error of the distance measurement
cfg.q_dt = 0.1;                     % average time interval between two DR epoch. 

%% R matrix
cfg.kf.up_interval = 0.2;   % the distance interval to use GNSS/INS position update.
% 位置置信度的倍数
cfg.kf.sf_R_pos = 3;      % scale to enlarge the uncertainty of GNSS/INS position
end

2.dataPreproc函数

function data_ains = dataPreproc(cfg)
% -------------------------------------------------------------------------
%DATAPREPROC Preprocess the GNSS/INS smoothing solution: 1) calculate the 
%            traveled distance from GNSS/INS smoothing position; 2) resample 
%            GNSS/INS smoothing solution along distance. Prepare data for
%            DR and mounting angle KF estimator.     
%	data_ains = dataPreproc(cfg)
%
%INPUTS:
%	cfg = the configuration
%OUTPUTS:
%   imu_ains = the data used as input to DR and mounting angle
%              estimator. refer to table 2 for the format definition
% -------------------------------------------------------------------------
% Author:
% Qijin Chen, GNSS Research Center, Wuhan University, China.;
% chenqijin@whu.edu.cn;
% Nov. 2019;
% -------------------------------------------------------------------------


% read the GNSS/INS smoothing solution; refer to table 1 for the format 
fid = fopen(cfg.fins, 'rb');
if fid == -1
    disp('Cannot open the file!');
    data_ains = [];
    return;
end
% GNSS/INS data
data = fread(fid, [21,inf], 'double')';
fclose(fid); clear fid;

% the segment of trajectory used to estimate the mounting angles
n1 = find(data(:,1)>cfg.session(1), 1);
n2 = find(data(:,1)>cfg.session(2), 1);
data = data(n1:n2, :);

% calculate velocity in v-frame to help computing the distance increment
% data(idx,7:9):北东地速度(后处理结果)
v_v = zeros(size(data,1), 3);
for idx = 1:size(v_v,1)
    cbn = eul2dcm(data(idx,10)*pi/180.0, data(idx,11)*pi/180.0, data(idx,12)*pi/180.0);
    v_v(idx, :) = (cbn' * data(idx,7:9)')'; % 转到imu坐标系
end
dt = diff(data(:,1));
% 前,右,下(载体坐标系)
ds = v_v(1:end-1,1).*dt; %前进方向
vdist = [0; cumsum(ds(:))]; %里程累积值
ts_vel = [data(:,1), vdist];

[~, m, ~] = unique(ts_vel(:,2)); % 静止段去掉
ts_vel = ts_vel(m, :);
data = data(m,:);

% compute traveled distance from GNSS/INS smoothing position 
%按照里程分割时间
s1 = min(ts_vel(:,2)):cfg.fds:max(ts_vel(:,2));
t1 = interp1(ts_vel(:,2), ts_vel(:,1), s1); % 插值
t1 = t1(:);

%ppk位置
pos = interp1(data(:,1), [data(:,5:6) data(:,4)], t1);
dpos = diff(pos);
ds = zeros(size(pos,1), 1);
for idx = 1:size(dpos,1)
    ds(idx+1,1) = sqrt(dpos(idx,1)*dpos(idx,1)+dpos(idx,2)*dpos(idx,2)+dpos(idx,3)*dpos(idx,3));
end
ts_pos = [t1, cumsum(ds)]; % GPS里程累积


figure;
plot(data(:,3),data(:,2),'b-*');

% resample the GNSS/INS smoothing solution according to the distance
data(:,12) = yawSmooth(data(:,12));
data = interp1(data(:,1),data, ts_pos(:,1));
data(:,12) = data(:,12)-floor(data(:,12)/360)*360;%??

n = isnan(data(:,1));
data(n, :) = [];

% Unit conversion
data(:,2:3) = data(:,2:3)*pi/180; % rad
data(:,10:12) = data(:,10:12)*pi/180; % rad 
data(:,19:21) = data(:,19:21)*pi/180; % rad 

data_ains = [data, ts_pos(:,2)];  % GPS里程累积
end

function Az = yawSmooth(Az)

N = length(Az);
A_threshold = 180;
for i = 2:N
    if Az(i) - Az(i-1) > A_threshold
        Az(i:N) = Az(i:N) - 360;
    elseif Az(i) - Az(i-1) < -A_threshold
        Az(i:N) = Az(i:N) + 360;
    end
end
end

3.mas_ekf函数

滤波主体函数

function nav = mas_ekf(data_ains, cfg)
% -------------------------------------------------------------------------
%MASEKF implementation of the mounting angle estimation Kalman filtering 
%	dcm = eul2dcm(roll, pitch, heading)
%INPUTS:
%   1. imu_ains = the data used as input to DR and mounting angle
%              estimator. refer to table 2 for the format definition
%   2. cfg = the configuration
%OUTPUTS:
%	1. nav = Nx21 matrix, each column is defined as
%       nav(i,1) = time in seconds
%       nav(i,2) = distance in meters
%       nav(i,3:5) = latitude(in radians),longitude(in radians), height
%                   (in meters); 
%       nav(i,6:7) = pitch-mounting angle(in radians),heading-mounting angle
%                   (in radians);
%       nav(i,8:10) = estimated attitude errors in GNSS/INS smoothing roll, 
%                     pitch and heading angle (in radians); 
%       nav(i,11) = scale factor error of the distance measurement. 
% -------------------------------------------------------------------------
% Author:
% Qijin Chen, GNSS Research Center, Wuhan University, China.;
% chenqijin@whu.edu.cn;
% Nov. 2019;
% -------------------------------------------------------------------------

ds = [0; diff(data_ains(:,22))];  % distance increment between two epochs. 

% initialize the dead reckoning positioning. 
[nav, P, x, Q, G, Phi, datum] = initDR(data_ains, cfg);
cbv = eye(3);   % initialize the mounting angles as zeros

% progress bar
num = size(data_ains,1);
if num > 100
    fric = floor(num/100);
    handle = waitbar(0, 'DR aided by GNSS/INS position!', 'Name', 'IMU Mounting Angle Estimator');
    WaitTitle = 'Filtering...';
end

% DR/AINS position filtering
s_prev = data_ains(1,22);
for idx = 2:size(data_ains,1)
    
    % show current progress
    if num > 100
        if mod(idx, fric) == 0
            waitbar(idx/num, handle, WaitTitle);
        end
    end
    meas = data_ains(idx,:);
    cbn = eul2dcm(meas(10), meas(11), meas(12));

    % feedback the estimated mounting angles to compensate the GNSS/INS attitude
    % 车辆坐标系到导航系
    cvn = cbn*cbv'; 
    
    % distance increment resolved in navigation frame 
    % 导航系的里程增量
    ds_n = cvn*[ds(idx); 0; 0]; 
    
    % the radii of curvature along lines of constant longitude and
    % latitude.
    Rm = datum.a*(1-datum.e2)/((1-datum.e2 * sin(data_ains(idx,2))^2)^(3/2));  
    Rn = datum.a/sqrt(1-datum.e2 * sin(data_ains(idx,2))^2);
    
    % DR position update
    nav(idx, 3) = nav(idx-1,3) + ds_n(1)/(Rm + data_ains(idx,4));
    nav(idx, 4) = nav(idx-1,4) + ds_n(2)/(Rn + data_ains(idx,4))/cos(data_ains(idx,2));
    nav(idx, 5) = nav(idx-1,5) - ds_n(3);

    % Set the state transition matrix PHI
    M = [0 0; 0 -abs(ds(idx)); abs(ds(idx)) 0];
    % 4-5:安装角
    % 6-8:欧拉角
    % 9:标度因子
    % 公式推导
    Phi(1:3,4:5) = -cvn*M;
    Phi(1:3,6:8) = cp_form(ds_n);
    Phi(1:3,9) = ds_n(:);

    % Kalman filter prediction, time update of the state and P matrix
    [x, P] = Kalman_predict(x, P, Phi, G, Q);
    
    % Kalman filter measurement update
    % The aided INS positioning solution is used as measurement update for
    % the DR system
    % up_interval:the distance interval to use GNSS/INS position update
    if abs(data_ains(idx,22)-s_prev) > cfg.kf.up_interval  
        r_gps_e = blh2xyz(datum.e2, Rn, data_ains(idx,2:4)');
        % nav(idx,3:5):DR推算位置
        r_ins_e = blh2xyz(datum.e2, Rn, nav(idx,3:5)');
        la_r = zeros(3,1);
        C_en = cne(data_ains(idx,2), data_ains(idx,3))';
        % 观测数据
        z = C_en * (r_ins_e - r_gps_e) + la_r;
        % Measurement equations
        % Hm:观测转测矩阵
        Hm = zeros(3,9);
        Hm(1:3,1:3) = eye(3);      
        % 新息:inno
        inno = z - Hm * x;    % innovation 
        R = diag((cfg.kf.sf_R_pos*data_ains(idx,13:15)).^2);
        [x, P, pdf] = Kalman_update(x, P, inno, Hm, R);
        if pdf ~= 0
            return
        end
             
        % position feedback
        % 反馈了位置
        d_lat = x(1)/(Rm + nav(idx,5));
        d_lon = x(2)/(Rn + nav(idx,5))/cos(nav(idx,3));
        d_theta = [d_lon * cos(nav(idx,3)); -d_lat; -d_lon * sin(nav(idx,3))];   
        % rv2quat:旋转变量转四元数
        qn = rv2quat(-d_theta);
        q_ne = qne(nav(idx,3), nav(idx,4));
        q_ne = quatprod(q_ne, qn);
        [nav(idx,3), nav(idx,4)] = qne2bl(q_ne);
        nav(idx,5) = nav(idx,5) + x(3); % 高程直接反馈
        
        % Update the mounting angle estimates
        % 反馈了安装角
        cvv = eul2dcm(0, x(4), x(5));
        cbv = cvv*cbv; % 更新车辆坐标系到导航系
        
        % set the state components as zeros after feedback
        % 状态变量置0
        x(1:5,1) = zeros(1,5);
    end
    [~, nav(idx,6), nav(idx,7)] = dcm2eul(cbv);
    nav(idx,8:10) = x(6:8);
    nav(idx,11) = x(9);  
end

% close progress bar
if num > 100
    close(handle);
end
end

% Navigation initialization
function [nav, P, x, Q, G, Phi, datum] = initDR(imu, cfg)

datum = earthModel();

% initialize the DR position with adied INS positioning solutions
nav = zeros(length(imu), 11);	
nav(:,1:2) = [imu(:,1), imu(:,22)];    % time and distance index.
nav(1,3:5) = imu(1,2:4);    % initialize the DR position from GNSS/INS smoothing position

% Initialize the state error covariance matrix, P0
% 9维:
% 1-3:位置
% 4-5:安装角
% 6-8:欧拉角
% 9:标度因子
P = zeros(9,9);
% 位置不确定度使用PPK的位置不确定度
P(1:3,1:3) = diag(1.0*(imu(1,13:15)).^2);       % position !!!! 1.0 位置的不确定度
P(4:5,4:5) = diag(cfg.ini_ma_std.^2);           % mounting angles 安装角度
P(6:8,6:8) = diag((cfg.attstd_scale*imu(1,19:21)).^2);  % attitude uncertainty 欧拉角不确定度
P(9,9) = cfg.ini_odosf_std^2;	% incremental distance scale factor error 标度因子

% state vector initialization
x = zeros(9,1);	

% set system noise covariance matrix, Q, time-invariant
Q = diag([cfg.q_ma_p; % for pitch-mounting angle
    cfg.q_ma_y; % for heading-mounting angle
    cfg.q_arw; % 角度随机游走
    cfg.q_arw;
    cfg.q_arw;
    cfg.q_odosf].^2)*cfg.q_dt; % for scale factor error of the distance measurement

% discrete-time system noise distribution matrix
% 噪声转换矩阵
% 安装角:4-5
% 欧拉角:6-8
% 标度因子:9
G = zeros(9,6);
G(4:9, 1:6) = eye(6);

% initilization of the discrete-time transition matrix
% 状态转移矩阵
Phi = eye(9);
end

% Kalman Filter prediction
function [x_pred, P_pred] = Kalman_predict(x, P, PHI, Gamma, Qw)
x_pred = PHI * x;
P_pred = PHI * P * PHI' + Gamma * Qw * Gamma';
end

% Kalman filter measurement update
function [x_up, P_up, pdf] = Kalman_update(x, P, inno, H, R)
PHt = P * H'; 
HPHt = H * PHt;
RHPHt = R + HPHt;
% chol??
[U, pdf] = chol(RHPHt);

if pdf == 0 % positive definite
    U = inv(U);
    U = U * U';
    K = PHt * U;
    dx = K * inno;
    x_up = x + dx; % 状态变量更新
    IKH = eye(length(x)) - K * H;
    P_up = IKH * P * IKH' + K * R * K'; % P矩阵更新
else
    x_up = 0;
    P_up = zeros(5);
end

end

4.plotResult函数

function plotResult(nav, cfg)
% -------------------------------------------------------------------------
%PLOTRESULT plot the results
% -------------------------------------------------------------------------
% Author:
% Qijin Chen, GNSS Research Center, Wuhan University, China.;
% chenqijin@whu.edu.cn;
% Nov. 2019;
% -------------------------------------------------------------------------

t0 = floor(nav(1,1)/100)*100;

%%  Figure1, plot the mounting angle estimate
if cfg.plot_ma
    figure,plot(nav(:,1)-t0, nav(:,6:7)*180/pi, 'linewidth', 2.0);
    set(gca, 'fontsize', 12);
    xlabel(['Time -' num2str(t0) ' / s'], 'fontsize', 12);
    ylabel('deg', 'fontsize', 12);
    legend({'\delta\theta', '\delta\psi'}, 'orientation', 'horizontal', 'Box', 'off', 'fontsize', 13);
    title('Mounting Angle Estimate', 'fontsize', 12, 'color', 'k');
    ylim([0 4]);
end

%% figure2, plot the estimated errors in the GNSS/INS smoothing attitude 
if cfg.plot_att_err
    figure,
    f1 = subplot(311); plot(nav(:,1)-t0, nav(:,8)*180/pi, 'color', [0.3 0.3 0.3]);
    set(gca, 'fontsize', 12);
    ylabel('\phi / deg', 'fontsize', 12, 'color', 'r');
    title('Attitude Error Estimate', 'fontsize', 12, 'color', 'k');
    f2 = subplot(312); plot(nav(:,1)-t0, nav(:,9)*180/pi, 'color', [0.3 0.3 0.3]);
    set(gca, 'fontsize', 12);
    ylabel('\theta / deg', 'fontsize', 12, 'color', 'r');
    f3 = subplot(313); plot(nav(:,1)-t0, nav(:,10)*180/pi, 'color', [0.3 0.3 0.3]);
    set(gca, 'fontsize', 12);
    ylabel('\psi / deg', 'fontsize', 12, 'color', 'r');
    xlabel(['Time -' num2str(t0) ' / s'], 'fontsize', 12);
    linkaxes([f1 f2 f3], 'x');
end

%% figure3, plot the estimated scale factor of the distance measurements.
if cfg.plot_odosf
    figure,plot(nav(:,1)-t0, nav(:,11)*1.0e6, 'color', [0.3 0.3 0.3]);
    set(gca, 'fontsize', 12);
    xlabel(['Time -' num2str(t0) ' / s'], 'fontsize', 12);
    ylabel('PPM', 'fontsize', 12);
    title('Odometer Scale Factor Error Estimate', 'fontsize', 12, 'color', 'k');
end
end

参考文献

1.Estimation of IMU Mounting Angles for Land Vehicular GNSS/INS Integrated System

举报

相关推荐

0 条评论