gnss 并行码捕获-matlab

代码和测试数据: gitee link

1 GPS捕获原理

首先是正交混频,剥离载波,CA码不做介绍(参考谢钢那本GPS原理和接收机设计)。将CA码重采样,对于GPS L1CA,考虑计算量,采用2倍采样率,即2.046MHz。利用matlab的xcorr做1ms并行相关,N次相干积分,M次非相干积分,寻找大于阈值的非相干结果的峰值,即可实现捕获。

2 Matlab代码

gnss_main.m

%%
clear
close all

%% gps L1 bds B1I prn and doppler
% 4 7 8 9 16 21 26 27
% -2272 3143 777 -385 -1963 3126 -2332 -1556
% 1 2 3 4 5 6 7 9 10 16 27 30
% 10 -4 24 25 4 -1021 -138 -446 -60 -1019 -1255 1757

%% datapath and read data
ifdata_path     = 'IFData\\';
codepath        = 'OutCACodeResult\\';
pathname        = 'ifdata_2bit_20ms.txt';
dataformat      = 2; %% 1: txt IQ, with header, 2: txt no header
system_type     = 1; %% 0: GPS L1CA 1: BDS: B1I

%% read raw ifdata
switch dataformat
    case 1
        filename        = [ifdata_path,pathname];
        readdata        = importdata(filename);
        gnss_ifdata     = readdata.data;
    case 2
        filename        = [ifdata_path,pathname];
        readdata        = importdata(filename);
        gnss_ifdata     = readdata;
end

%% read code data
switch system_type
        case 0
            filename1   = 'GPSCACode.txt';
            f1          = [codepath,filename1];
            gnss_code   = importdata(f1); 
        case 1
            filename1   = 'BDSCACode.txt';
            f1          = [codepath,filename1];
            gnss_code   = importdata(f1); 
        case 2
            disp("error system!!!")
        case 3
            disp("error system!!!")
        otherwise
            disp("error system!!!")
end
%% gnss config init
gnss_config     = set_gnss_config(system_type);
%% acq
tic
acq_result      = gnss_acq(gnss_config.acq_config, gnss_ifdata, gnss_code);
toc

if acq_result.acq_status == 1
    %% show result
    dop_list            = gnss_config.acq_config.acq_fre_min : gnss_config.acq_config.acq_fre_step : gnss_config.acq_config.acq_fre_max;
    code_phase_step     = gnss_config.acq_config.code_phase_step;
    system_name         = gnss_config.acq_config.system_name;
    x                   = acq_result.acq_check_list{1,1}.x * code_phase_step;
    acq_noncoh_result   = acq_result.acq_check_list{1,1}.temp_noncoh_result;
    PRN                 = acq_result.acq_check_list{1,1}.prn;
    
    %% 2D plot
    figure(1)
    plot(x, acq_noncoh_result(:, acq_result.acq_check_list{1, 1}.acq_check_result.dop_cnt))
    xlabel('Codephase/chip')
    ylabel('Amplitude')
    titlename = [system_name, ' PRN-', num2str(PRN),' ','Result'];
    title(titlename)
    grid on
    
    % 3D plot, note: gnss_acq not save result, please config
    if 1
        h = figure(2);
        mesh(dop_list, x, acq_noncoh_result)
        titlename = [system_name, ' PRN-', num2str(PRN),' ','Result'];
        title(titlename)
        xlabel('Doppler/Hz')
        ylabel('Codephase/chip')
        zlabel('Amplitude')
        % savefig(h, titlename);
        % close(h)
    end

end

set_gnss_config.m

%% function: set_gnss_config
%% system_type: 0: L1CA, 1: B1I, 2: E1 3: F1
function gnss_config = set_gnss_config(system_type)

switch system_type
    case 0
        acq_config.system_type          = 0;
        acq_config.system_name          = 'GPS L1CA';
        acq_config.ifdata_center_fre    =  1567.236E6; %Hz
        acq_config.samplerate           = 30.69E6;
        acq_config.system_fre           = 1575.42E6;
        acq_config.acq_samplerate       = 2.046E6;
        acq_config.code_rate            = 1.023E6;
        acq_config.code_len             = 1023;
        acq_config.isdownsample         = 1;
        acq_config.coh_num              = 1;
        acq_config.noncoh_num           = 20;
        acq_config.acq_snr_thd          = 3; % 12: 10mscoh 3: 1mscoh
        acq_config.acq_prn_list         = [4 7 8 9 16 21 26 27];
        acq_config.is_set_acq_prn       = 1;
        acq_config.acq_fre_step         = 1000/acq_config.coh_num/2;
        acq_config.acq_fre_max          = 4000;
        acq_config.acq_fre_min          = -4000;
        acq_config.code_phase_step      = 0.5;
    case 1
        acq_config.system_type          = 1;
        acq_config.system_name          = 'BDS B1I';
        acq_config.ifdata_center_fre    = 1567.236E6; %Hz
        acq_config.samplerate           = 30.69E6;
        acq_config.system_fre           = 1561.098E6;
        acq_config.acq_samplerate       = 4.092E6;
        acq_config.code_rate            = 2.046E6;
        acq_config.code_len             = 2046;
        acq_config.isdownsample         = 1;
        acq_config.coh_num              = 1;
        acq_config.noncoh_num           = 20;
        acq_config.acq_snr_thd          = 3;
        acq_config.acq_prn_list         = [1 2 3 4 5 6 7 9 10 16 27 30];
        acq_config.is_set_acq_prn       = 1;
        acq_config.acq_fre_step         = 1000/acq_config.coh_num/2;
        acq_config.acq_fre_max          = 4000;
        acq_config.acq_fre_min          = -4000;
        acq_config.code_phase_step      = 0.5;
    case 2
        disp("no support system!!!")
    case 3
        disp("no support system!!!")
    otherwise
        disp("error system!!!")
end
gnss_config.acq_config = acq_config;
end

gnss_acq.m

%%
%% function: fft_acq for GPS L1CA, BDS B1I
%% input: gnss_config.acq_config gnss_ifdata gnss_code
%% system_type: 0: L1CA, 1: B1I, 2: E1 3: F1
%% gnss_ifdata: (real, imag) Nx2
%% gnss_code: CA_Code
%% output: acq result of all/set satellites

function acq_result = gnss_acq(acq_config, gnss_ifdata, gnss_code)

%% get config
system_type         = acq_config.system_type;
ifdata_center_fre   = acq_config.ifdata_center_fre;
samplerate          = acq_config.samplerate;
system_fre          = acq_config.system_fre;
acq_samplerate      = acq_config.acq_samplerate;
code_rate           = acq_config.code_rate;
code_len            = acq_config.code_len;
isdownsample        = acq_config.isdownsample;
%%acq parameter
coh_num             = acq_config.coh_num;
acq_prn_list        = acq_config.acq_prn_list;
noncoh_num          = acq_config.noncoh_num;
acq_snr_thd         = acq_config.acq_snr_thd;
is_set_acq_prn      = acq_config.is_set_acq_prn;
acq_fre_step        = acq_config.acq_fre_step;
acq_fre_max         = acq_config.acq_fre_max;
acq_fre_min         = acq_config.acq_fre_min;
code_phase_step     = acq_config.code_phase_step;
acq_ms              = coh_num*noncoh_num;

%% start deal
acq_result.acq_status = 0;
ifdata_ms = length(gnss_ifdata(:,1));
if acq_ms > ifdata_ms
    acq_result.acq_status = 0;
else
    ifdata_len  = acq_ms/1000*samplerate;
    acq_ifdata      = gnss_ifdata(1:ifdata_len,:);
    switch system_type
        case 0
            disp("ACQ GPS L1CA!!!")
            %%
            if is_set_acq_prn == 0
               acq_prn_list = 1:32;
            end
        case 1
            disp("ACQ BDS B1I!!!")
             if is_set_acq_prn == 0
               acq_prn_list = 1:37;
            end
        case 2
            disp("no support system!!!")
        case 3
            disp("no support system!!!")
        otherwise
            disp("error system!!!")
    end
    
    % isdownsample check 
    if isdownsample == 1
        downfre_config.fc       = system_fre - ifdata_center_fre;
        downfre_config.fc_down  = system_fre - system_fre;
        downfre_config.fs_down  = acq_samplerate;
        downfre_config.fs       = samplerate;
        % down convert fre
        conv_acq_data           = downconvertsample(acq_ifdata, downfre_config);
        down_fre                = 0;
        acq_ifdata_ms_len       = acq_samplerate/1000;
        acq_ifdata_len          = acq_ms/1000*acq_samplerate;
    else
        acq_samplerate          = samplerate;
        acq_ifdata_ms_len       = acq_samplerate/1000;
        conv_acq_data           = acq_ifdata;
        down_fre                = system_fre - ifdata_center_fre;    
        acq_ifdata_len          = acq_ms/1000*acq_samplerate;
    end

    %% acq process
    acq_check_cnt = 1;
    for prn = acq_prn_list
            ca_code             = gnss_code(:,prn);
            codeValueIndex      = ceil(code_rate*(1:code_len*acq_samplerate/code_rate)/acq_samplerate);
            ca_code_resample    = ca_code(codeValueIndex); % resample C/A code
            ca_code_complex     = complex(ca_code_resample,0);
            dop_cnt             = 1;
            isacq_cnt           = 0;
        for dop = acq_fre_min : acq_fre_step: acq_fre_max

            %% set search parameter
            temp_noncoh = zeros(acq_ifdata_ms_len*2-1,1);
            temp_coh    = zeros(acq_ifdata_ms_len*2-1,1);
            %%NCO
            fncos       = dop + down_fre;
            dt          = 1/acq_samplerate;
            t           = (0:acq_ifdata_len-1)*dt;
            sin_x       = sin(2*pi*fncos*t);
            cos_x       = cos(2*pi*fncos*t);
            x_drc       = complex(cos_x', sin_x') .* conv_acq_data;

            for i = 1 : noncoh_num
                
                for j = 1 : coh_num
                    ms_cnt                  = (i - 1)*coh_num + j;
                    temp_index              = 1 + (ms_cnt-1)*acq_ifdata_ms_len : acq_ifdata_ms_len*ms_cnt;
                    xdr_ms_ij               = x_drc(temp_index);  
                    %Normalized results, parallel code correlator     
                    [fft_code_result, x]    = xcorr(xdr_ms_ij, ca_code_complex, 'coeff');       
                    %coherent
                    temp_coh                = temp_coh + fft_code_result;
                end
                    %%捕获
                    temp_noncoh             = temp_noncoh + abs(temp_coh);
                    temp_coh                = zeros(acq_ifdata_ms_len*2-1, 1);
            end       

            %% acq check
            temp_noncoh_result(:,dop_cnt)   = temp_noncoh;
            acq_check_result                = acq_check(dop, temp_noncoh, acq_snr_thd, code_phase_step);
            acq_check_result.dop_cnt        = dop_cnt;
            if acq_check_result.isacq == 1
                disp(['system_type:', num2str(system_type), ' acq prn:', num2str(prn), ' acq_snr:', num2str(acq_check_result.acq_snr), ' codephase: ', num2str(acq_check_result.codephase), ' doppler: ', num2str(acq_check_result.dop)]);
                %% save acq_check_list
                acq_check_result.system_type                        = system_type;
                acq_check_list{acq_check_cnt, 1}.acq_check_result   = acq_check_result;
                acq_check_list{acq_check_cnt, 1}.x                  = x;
                acq_check_list{acq_check_cnt, 1}.prn                = prn;
                %% 
                isacq_cnt                                           = isacq_cnt + 1;
                acq_check_cnt                                       = acq_check_cnt + 1;
                acq_result.acq_status                               = 1;
            end
            dop_cnt                         = dop_cnt + 1;
        end
        %% save noncoh result
        if isacq_cnt > 0
            for check_cnt = acq_check_cnt - isacq_cnt : acq_check_cnt - 1
                acq_check_list{check_cnt, 1}.temp_noncoh_result = temp_noncoh_result;
            end
        end

    end
    if acq_result.acq_status == 1
        acq_result.acq_check_list  = acq_check_list;
    end

end

end


%% acq check
function acq_check_result = acq_check(dop, temp_noncoh, acq_snr_thd, code_phase_step)

 [~,index_max]  = max(temp_noncoh, [], 1);  %%按列
 index_len      = floor(1/code_phase_step/2);
 sum1           = sum(temp_noncoh);
 sum2           = sum(temp_noncoh(index_max - index_len : index_max + index_len)); %% code step = 0.5
 len            = length(temp_noncoh(:, 1));
 acq_snr        = temp_noncoh(index_max)*(len - index_len*2-1)/(sum1 - sum2);
 %% acq check
 if acq_snr > acq_snr_thd
    acq_check_result.isacq  = 1;
 else
    acq_check_result.isacq  = 0;
 end
 acq_check_result.index_max = index_max;
 acq_check_result.codephase = code_phase_step*(index_max - floor(index_max/2));
 acq_check_result.acq_snr   = acq_snr;
 acq_check_result.dop       = dop;
 
end


%% resample data
function conv_data = downconvertsample(data, downfre_config)

    %% f_result = fc - lco_f
    lco_f       = downfre_config.fc - downfre_config.fc_down;
    ratio_f     = downfre_config.fs/downfre_config.fs_down;
    
    %% genertate local signal for convert
    len         = length(data);
    t           = 0:1/downfre_config.fs: len*1/downfre_config.fs - 1/downfre_config.fs;
    t           = t';
    real        = cos(2*pi*t*lco_f)*32;
    imag        = sin(2*pi*t*lco_f)*32;
        
    loc         = complex(real, imag);
    ifdata      = complex(data(:,1), data(:, 2));
    
    %% fre down convert
    temp_data   = loc.*ifdata;

    %% down sample rate
    temp_ifdata = resample(temp_data, 4, ratio_f*4); %% for 8.184E6 
    
    conv_data   = temp_ifdata;

end

3 测试结果

3.1 GPS L1CA测试结果

GPS L1CA参数设置:

  • 数据采样率2.046 MHz
  • 1 ms相干积分,1次相干积分,20次非相干积分
  • 捕获步进500Hz
    测试结果 2-D图:
    在这里插入图片描述
    测试结果3-D图
    在这里插入图片描述

3.2 BDS B1I测试结果

BDS B1I参数设置:

  • 数据采样率4.092MHz
  • 1 ms相干积分,1次相干积分,20次非相干积分
  • 捕获步进500Hz

注意:由于BDS 非GEO卫星调制了NH码,无法直接进行大于1ms的相干积分。
测试结果 2-D图:
在这里插入图片描述
测试结果3-D图:
在这里插入图片描述

4 数据及代码链接

代码和测试数据: gitee link

  • 32
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 46
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值