AWR2243cascade radar MIMO后处理梳理

1. MIMO模式工作原理

2.mmwavestudio数据采集

3. matlab后处理代码分析

3.1数据加载

3.1.1 配置数据文件夹

%% get the input path and testList
pro_path = getenv('CASCADE_SIGNAL_PROCESSING_CHAIN_MIMO');
input_path = strcat(pro_path,'\main\cascade\input\');
testList = strcat(input_path,'testList.txt');
  • pro_path:工程文件夹路径(C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example)
  • intput_path:工程输入文件夹路径,包括了ADC数据文件路径、校准数据.mat文件(C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example\main\cascade\input)
  • testList:包括了ADC数据文件夹、校准矩阵、处理代码文件
D:\Desktop\radar\2243\2022-10-12 测试数据\电车 35码左右行驶   70帧  采集时间35s\Cascade_Capture_22xx\
C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example\main\cascade\input\calibrateResults_dummy.mat
C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example\main\cascade\paramGen\module_param.m

3.1.2 获取具体的数据文件名

根据上一把得到的一个路径数组,分别获取各种数据的具体文件或者文件夹。

%% get each test vectors within the test list
% test data file name
dataFolder_test = fgetl(fidList);     %获取数据目录路径
%calibration file name
dataFolder_calib = fgetl(fidList);    %获取校准矩阵,TI提供原始校准矩阵
%module_param_file defines parameters to init each signal processing
%module
module_param_file = fgetl(fidList);    
%parameter file name for the test
pathGenParaFile = [input_path,'test',num2str(testID), '_param.m'];
%important to clear the same.m file, since Matlab does not clear cache
%automatically
clear(pathGenParaFile);

3.1.3 生成完整的参数文件

%调用该函数,在信号处理前使用Jason文件生成一个完整的参数文件,包括chirp参数和模块参数。
%input:
% test_name: 测试数据文件名,包含chirp配置
%文件为Jason文件格式
% dataFolder_calib: 校准数据文件路径,包含预先校准的.mat文件。这个.mat文件包括校准矩阵,用于adc数据校准模块。
% module_param_file: 包含初始化每个信号处理模块的参数。
% pathGenParaFile: 要生成的完整参数文件名
% dataPlatform:数据采集平台的标志
parameter_file_gen_json(dataFolder_test, dataFolder_calib, module_param_file, pathGenParaFile, dataPlatform);

:::info
parameter_file_gen_json函数的作用就是将数据文件夹的配置文件、校准文件统一的写进test1_param.m文件中,test1_param.m文件是用以下的代码定义
:::

%parameter file name for the test
pathGenParaFile = [input_path,'test',num2str(testID), '_param.m'];
%important to clear the same.m file, since Matlab does not clear cache
%automatically
clear(pathGenParaFile);

3.1.4 读取各类参数文件赋值给结构体

将上一步重新写好的test1_param.m文件赋值给各个结构体

simTopObj           = simTopCascade('pfile', pathGenParaFile);
calibrationObj      = calibrationCascade('pfile', pathGenParaFile, 'calibrationfilePath', dataFolder_calib);
rangeFFTObj         = rangeProcCascade('pfile', pathGenParaFile);
DopplerFFTObj       = DopplerProcClutterRemove('pfile', pathGenParaFile);
detectionObj        = CFAR_CASO('pfile', pathGenParaFile);
DOAObj              = DOACascade('pfile', pathGenParaFile);
    
结构体名 描述
simTopObj SimTopObj用于顶层参数解析和数据加载保存
calibrationObj 数据校准结构体,包括校准矩阵的路径、话有一些校准参数,用校准来校准ADC数据
rangeFFTObj 进行距离维FFT处理时的参数,包括采样点数、窗口系数等
DopplerFFTObj 进行多普勒维FFT处理时的参数,包括天线数、多普勒点数、窗口系数等
detectionObj CFAR目标检测算法结构体,包括算法参数、算法实现
DOAObj 定义角度检测算法结构体,基于FFT的波束成形方法估计方位角和仰角(如果启用),在方位角方向检测到多个峰值,在仰角方向只检测到最大峰值。

3.2 数据预处理

3.2.1 获取有效帧数

% Get Valid Number of Frames 
[numValidFrames dataFileSize] = getValidNumFrames(fullfile(dataFolder_test, fileNameStruct.masterIdxFile));

通过读取master_0000_idx.bin文件,获得有效帧数信息。
:::info
fullfile(dataFolder_test, fileNameStruct.masterIdxFile)可以理解为文件文件路径和路径下的文件进行拼接,得到完整的文件位置。
:::

3.2.2 datapath函数说明

在后处理的matlab代码中,所有模块都有datapath函数,在调用时都是调用同名函数,根据传入的结构体来区分,在调用时将相应的结构体传递给相同名字的函数即可。

3.2.3 数据读取和数据校准

(1)bin数据读取

:::success
每次数据采集后,都会保存一个二进制数据文件和相应的啁啾配置参数。这两个文件是ADC数据读取和校准模块的输入。二进制数据文件根据基于数据格式、每个啁啾的样本、每帧啁啾、TXRX通道的数量的啁啾参数进行读取/解析。然后,数据被重新格式化为4D矩阵,其维度为每个啁啾点的样本、每帧啁啾点、RX通道的数量和TX通道的数量。每个TX/RX通道根据预先计算好的校准矩阵进行校准,该矩阵可以通过第3节中描述的程序获得。
:::
数据文件夹如下图所示:
AWR2243cascade radar MIMO后处理梳理_第1张图片
读取bin数据代码:

switch obj.dataPlatform
    case 'TDA2'
        numChirpPerLoop = obj.numChirpsPerFrame/obj.nchirp_loops; 
        numLoops = obj.nchirp_loops;             
        numRXPerDevice = 4; % Fixed number      
        [radar_data_Rxchain] = read_ADC_bin_TDA2_separateFiles(fileName,frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, 1);
    otherwise
        error('Not supported data capture platform!');       
end

具体的函数解释:

function [radar_data_Rxchain] = read_ADC_bin_TDA2_separateFiles(fileNameCascade,frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices)
  dataFolder =fileNameCascade.dataFolderName;
  fileFullPath_master = fullfile(dataFolder,fileNameCascade.master);
  fileFullPath_slave1 = fullfile(dataFolder,fileNameCascade.slave1);
  fileFullPath_slave2 = fullfile(dataFolder,fileNameCascade.slave2);
  fileFullPath_slave3 = fullfile(dataFolder,fileNameCascade.slave3);
 [radar_data_Rxchain_master] = readBinFile(fileFullPath_master, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
 [radar_data_Rxchain_slave1] = readBinFile(fileFullPath_slave1, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
 [radar_data_Rxchain_slave2] = readBinFile(fileFullPath_slave2, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
 [radar_data_Rxchain_slave3] = readBinFile(fileFullPath_slave3, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
% Arranged based on Master RxChannels, Slave1 RxChannels, slave2 RxChannels, slave3 RxChannels 
% The RX channels are re-ordered according to "TI_Cascade_RX_ID" defined in
% "module_params.m"
 radar_data_Rxchain(:,:,1:4,:) = radar_data_Rxchain_master;
 radar_data_Rxchain(:,:,5:8,:) = radar_data_Rxchain_slave1;
 radar_data_Rxchain(:,:,9:12,:) = radar_data_Rxchain_slave2;
 radar_data_Rxchain(:,:,13:16,:) = radar_data_Rxchain_slave3;
end

function [adcData1Complex] = readBinFile(fileFullPath, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices)
Expected_Num_SamplesPerFrame = numSamplePerChirp*numChirpPerLoop*numLoops*numRXPerDevice*2;
fp = fopen(fileFullPath, 'r');
fseek(fp,(frameIdx-1)*Expected_Num_SamplesPerFrame*2, 'bof');
adcData1 = fread(fp,Expected_Num_SamplesPerFrame,'uint16');
neg             = logical(bitget(adcData1, 16));
adcData1(neg)    = adcData1(neg) - 2^16;
%% 
adcData1 = adcData1(1:2:end) + sqrt(-1)*adcData1(2:2:end);
adcData1Complex = reshape(adcData1, numRXPerDevice, numSamplePerChirp, numChirpPerLoop, numLoops);
adcData1Complex = permute(adcData1Complex, [2 4 1 3]);
fclose(fp);
end

readBinFile函数代码解释如下:

  • 根据提供的文件名 fileFullPath、帧号 frameIdx 和其他参数,计算出该帧中的总样数,计算方式为每个chirp采样点数每次循环的chirp数循环次数每个雷达芯片的RX数据2 (*2是因为复数)
  • 打开该二进制数据文件。并使用 fseek() 函数定位到第 frameIdx 个帧的起始位置。
  • 使用 fread() 函数读取 frameIdx 个帧对应的数据,保存到 adcData1 中。数据类型为 uint16,表示 16 位无符号整数。
  • 对 adcData1 的最高位进行检验,得到 neg 表示哪些数据存在负溢出的标志位。对发生负溢出的采样值减去 2^16,保证其在有符号 16 位整数范围内。
  • adcData1(1:2:end) + i*adcData1(2:2:end) 用来构建每个组合的复数,实部取自后一组采样点,虚部取自前一组采样点。将 16 位实数采样点转换为 32 位复数,以便后续的信号处理能够对采样点进行复数运算。实际上,ADC 采集到的信号本身就是复数信号,这里通过复数转换重建了信号的复数形式。
  • adcData1Complex 的四个维度分别是numRXPerDevice(4)、numSamplePerChirp(230 )、numChirpPerLoop(12)和numLoops(64)。使用 permute() 重新排列维度,以便后续处理。这里的数据只是一个雷达芯片的数据,这样的数据有四个,后续需要将这四个数据合并为一个数据。有四个雷达。每个雷达有四个接收天线,也就是numRXPerDevice x 4 = 16

最终得到的矩阵是:230 64 16 12

radar_data_Rxchain(:,:,1:4,:) = radar_data_Rxchain_master;
radar_data_Rxchain(:,:,5:8,:) = radar_data_Rxchain_slave1;
radar_data_Rxchain(:,:,9:12,:) = radar_data_Rxchain_slave2;
radar_data_Rxchain(:,:,13:16,:) = radar_data_Rxchain_slave3;

(2)数据校准

  • 消除不同通道之间的误差,减小通道间差异,以产生更为一致的显示结果。 在同一场景下不同通道采集到的信号将出现一定的频率、相位差异,如果不进行校准,在显示上会出现明显的 “波纹” 现象,影响观测结果。
  • 提高信号电场重叠度、相位保真性,改善信号对比度和广度,提高目标检测性能。 通过消除通道差异,使得不同通道信号在显示或后续处理中能够完全重叠,相互弥合,产生更宽、更清晰的信号特征,从而更容易区分目标回波。
  • 确保不同通道提取到的特征参数(如距离、 Doppler 频率等)更加一致和准确。 仅通过确认通道差异后再查找特征是不够的,频率和相位校准能够在根本上改进信号量化和特征提取的准确性。

毫米波雷达数据的频率校准和相位校准主要有几种常用方法:

  • 基于参考通道的比较校准:选择一组启用通道作为参考通道,与其他通道逐一比较,计算频率和相位差异,构建相关校准矩阵予以修正。
  • 差异建模校准:根据通道间在某一区域(如 Range 或 Doppler 频率空间)出现的差异特点,构建数学模型(如一元二次曲线)进行差异描述和修正。这种方法更灵活而抽象。
  • 自学习校准:每个通道根据其自身历史数据,通过一定算法(如低通滤波)学习出其特征差异,并进行相应修正。这种方法无需参考通道,但需要大量假设和调优。
  • 互动校准:同时应用前两种方法,使用参考通道构建基础校准框架,并在框架内通过差异建模不断优化和学习。这种方法结合了前两种方法的优势,表现较佳。
  • 物理参量校准:根据每个通道相关物理参量(如天线角度、中心频率等),建立错误建模关系再进行修正。这种方法更为确定实际,少有假设,但需要对系统有较深入的了解。

TI的校准方式是对TX频率和相位进行校准。
AWR2243cascade radar MIMO后处理梳理_第2张图片

  1. 频率校准
    指定一个TX通道进行校准,与其它通道进行比较。频率校准向量的计算公式如下 F ⃗ = 2 π × Δ P × f s c a l i b f s c h i r p × f chirp  f calib  / ( N × I interp  ) × n ⃗ \vec{F}=2 \pi \times \Delta P \times \frac{f_s^{c a l i b}}{f_s^{c h i r p}} \times \frac{f_{\text {chirp }}}{f_{\text {calib }}} /\left(N \times I_{\text {interp }}\right) \times \vec{n} F =2π×ΔP×fschirpfscalib×fcalib fchirp /(N×Iinterp )×n
    其中参数解释如下表:
    | Δ P \Delta P ΔP | 虚拟通道的FFT峰值索引差 |
    | — | — |
    | f c h i r p f_{c h i r p} fchirp | FMCW的chirp频率斜率 |
    | f c a l i b f_{calib} fcalib | 用于校准的FMCW chirp频率斜率 |
    | I interp  I_{\text {interp }} Iinterp  | 插值 |
    | f   s c a i l i b    f_{\ s}^{c a i l i b}\; f scailib | 用于校准的FMCW chirp采样率 |
    | f   s c h i r p    f_{\ s}^{chirp}\; f schirp | FMCW chirp采样率(实际配置的) |
    | N | 每个chirp的样本数 |
    | n ⃗ \vec{n} n | [0 N-1] 是ADC采样点的索引 |
freq_calib = (RangeMat(TXind,:)-RangeMat(TX_ref,1))*fs_calib/Sampling_Rate_sps *chirpSlope/Slope_calib;       
freq_calib = 2*pi*(freq_calib)/(numSamplePerChirp * calibrationInterp);
correction_vec = (exp(1i*((0:numSamplePerChirp-1)'*freq_calib))');


freq_correction_mat = repmat(correction_vec, 1, 1, nchirp_loops);
freq_correction_mat = permute(freq_correction_mat, [2 3 1]);
outData1TX = radar_data_Rxchain(:,:,:,iTX).*freq_correction_mat;

校准矩阵可以参考AWRx_TX_Channel_Calibration_Script_User_Guide.pdf

  1. 相位校准

相位校准和频率校准类似,都是选第一个通道作为参考值,公式为:
C p h − a m = C r e f / C t x   i / r   x j C p h_{-}a m=C_{r e f}/C t x\,i/r\,x j Cpham=Cref/Ctxi/rxj
Crer是参考通道的复数值,Ctxi,是 其他通道的复数值; Cph_am 是计算的相位和振幅校准值。Cph_am对参考
通道为1,对其他各通道不同。Cph am与频率校准的输出相乘,结果是最终校准的ADC数据。
AWR2243cascade radar MIMO后处理梳理_第3张图片

%construct the phase compensation matrix
phase_calib = PeakValMat(TX_ref,1)./PeakValMat(TXind,:);
phase_correction_mat = repmat(phase_calib.', 1,numSamplePerChirp, nchirp_loops);
phase_correction_mat = permute(phase_correction_mat, [2 3 1]);
outData(:,:,:,iTX) = outData1TX.*phase_correction_mat;

3.2.4 数据处理

(1)虚拟通道

:::info
MIMO模式的虚拟通道:在毫米波雷达的MIMO模式下,虚拟通道数等于发射天线数乘以接收天线数的原因是多个发射天线和多个接收天线之间可以组成多个独立的通道,每个通道可以看作是一个虚拟通道。
在MIMO雷达中,通过使用多个发射天线和多个接收天线可以获得多个接收信号,每个接收信号对应一个虚拟通道。对于每个虚拟通道,都可以通过信号处理算法获得相应的距离、角度和速度信息。因此,在MIMO雷达中,虚拟通道数等于发射天线数乘以接收天线数。
举例来说,如果一个MIMO雷达有12个发射天线和16个接收天线,那么可以组成192个虚拟通道。每个虚拟通道可以得到自己的距离、角度和速度信息,可以提高雷达测量的精度和鲁棒性。
:::
:::success
TXBF模式的虚拟通道:在TXBF(Transmit Beamforming)模式下,虚拟通道数等于每个雷达的接收天线数乘以扫描角度数的原因是,每个接收天线可以接收到来自不同方向的信号,并且每个方向都可以看作是一个独立的通道,每个通道可以看作是一个虚拟通道。
在TXBF模式下,雷达发送的信号经过波束成形后,只会在某个方向上产生较大的功率,而在其他方向上的功率较小。因此,每个接收天线可以接收来自不同方向的信号,每个方向都相当于一个独立的通道,可以看作是一个虚拟通道。而每个接收天线可以接收多个方向的信号,因此每个接收天线可以产生多个虚拟通道。
此外,由于TXBF模式下雷达需要扫描不同的方向来获得目标的位置信息,因此每个方向都需要进行一次扫描,每次扫描可以获得一个虚拟通道的信息。因此,虚拟通道数等于每个雷达的接收天线数乘以扫描角度数。
举例来说,如果一个雷达有4个接收天线,扫描角度数为90度,那么可以产生360个虚拟通道。其中,每个接收天线可以产生90个虚拟通道,每个扫描角度可以产生4个虚拟通道。每个虚拟通道都可以得到自己的距离、角度和速度信息,可以提高雷达测量的精度和鲁棒性。
:::

(2)数据处理流程图

AWR2243cascade radar MIMO后处理梳理_第4张图片

(3)距离、多普勒FFT

对每个虚拟通道进行距离FFT和多普勒FFT,12T16R的配置总共有12x16=192个虚拟通道,在代码中并不是直接循环192次,而是先循环发射天线数(12),再循环接收天线数(16),代码如下:

%perform 2D FFT
rangeFFTOut = [];
DopplerFFTOut = [];
%size(adcData) = 230    64    16    12
for i_tx = 1: size(adcData,4)  %12
    % range FFT
    rangeFFTOut(:,:,:,i_tx)     = datapath(rangeFFTObj, adcData(:,:,:,i_tx));
    % Doppler FFT
    DopplerFFTOut(:,:,:,i_tx)   = datapath(DopplerFFTObj, rangeFFTOut(:,:,:,i_tx));
end

其中两个datapath是不同模块的同名函数,根据传入的Obj来区分调用,下面依次解释这两个datapath。

%% datapath function
% input: adc data, assuming size(input) = [numSamplePerChirp, numChirpsPerFrame numAntenna]
function [out] = datapath(obj, input)
  numLines  = size(input,2);
  numAnt    = size(input,3);
  % dopplerWinLen  = length(obj.dopplerWindowCoeff);
  if obj.enable           
      % initialize
      out = zeros(obj.rangeFFTSize, numLines, numAnt);
      for i_an = 1:numAnt  
          % vectorized version
          inputMat    = squeeze(input(:,:,i_an));          
          % DC offset compensation
          %用于在不使用循环的情况下,对矩阵进行操作,这里用于减去输入矩阵的平均值,即DC偏移补偿。
          inputMat    = bsxfun(@minus, inputMat, mean(inputMat));          
          % apply range-domain windowing
          inputMat    = bsxfun(@times, inputMat, obj.rangeWindowCoeffVec);         
          % Range FFT
          fftOutput   = fft(inputMat, obj.rangeFFTSize);        
          % apply Doppler windowing and scaling to the output. Doppler windowing moved to DopplerProc.m (5/24)
          % fftOutput   = bsxfun(@times, fftOutput, obj.scaleFactorRange*obj.dopplerWindowCoeffVec.');
          if  obj.FFTOutScaleOn == 1
              fftOutput   = fftOutput * obj.scaleFactorRange;
          end        
          % populate in the data cube
          out(:,:,i_an) = fftOutput;
      end            
  else
      out     = input;
  end
end

:::success
代码解释:

  • 循环在变量i_an从1到numAnt之间迭代,也就是第二次循环,接收天线循环。
  • squeeze函数用于删除单维度条目,因为输入矩阵可能包含不必要的单维度条目。
  • bsxfun函数用于在不使用循环的情况下,对矩阵进行操作,这里用于减去输入矩阵的平均值,即DC偏移补偿。
  • 进行距离域窗口化处理,将输入矩阵乘以obj.rangeWindowCoeffVec。
  • 对输入矩阵进行Range FFT处理,得到频域信号fftOutput。
  • 注:在距离FFT的时候,fftOutput = fft(inputMat, obj.rangeFFTSize);表示对第一维度的数据进行FFT,也就是采样点个数,并且FFT的点数根据采样点数最接近2的n次方决定(例如:采样点数为230,那么距离FFT的点数就是256).
    :::
% datapath function
% input: adc data, assuming size(input) = [numSamplePerChipr numChirpsPerFrame numAntenna]
function [out] = datapath(obj, input)
    numLines  = size(input,1);
    numAnt    = size(input,3);
    if obj.enable                  
        % initialize
        out = zeros(numLines, obj.dopplerFFTSize, numAnt);    
        for i_an = 1:numAnt                           
            %% vectorized version
            inputMat    = squeeze(input(:,:,i_an));
            inputMat    = bsxfun(@times, inputMat, obj.dopplerWindowCoeffVec.');
            if obj.clutterRemove ==1
                inputMat = inputMat - (repmat(mean(inputMat'),size(inputMat,2),1))';
            end
            fftOutput   = fft(inputMat, obj.dopplerFFTSize, 2);                                  
            if obj.FFTOutScaleOn ==1
                fftOutput   = fftshift(fftOutput, 2) * obj.scaleFactorDoppler;
            else
                fftOutput   = fftshift(fftOutput, 2);
            end
            % populate in the data cube
            out(:,:,i_an) = fftOutput;       
        end
    else
        out     = input;
    end
end

代码解释:

  • (a) 从输入数据中提取第i_an个天线的数据,squeez函数是将第三维去掉,剩下前面两维数据。(因为第三维是循环维度,每次都是1)
  • 将输入矩阵inputMat中的每个元素与Doppler窗函数系数向量中对应位置的元素进行乘法运算,得到一个同样大小的结果矩阵inputMat。
  • 如果开启了杂波消除功能(obj.clutterRemove==1),则从输入数据中减去每个脉冲的平均值,以消除杂波的影响。
  • 对第i_an个天线的数据进行Doppler FFT变换,变换大小为obj.dopplerFFTSize。如果开启了FFT输出缩放功能(obj.FFTOutScaleOn==1),则将FFT输出乘以一个缩放因子obj.scaleFactorDoppler。
  • fftshift函数对fftOutput矩阵进行移动,以将频域数据的零频率分量移到中心位置。
  • 将Doppler FFT输出存储到输出矩阵out中的第i_an个通道。
  • **需要注意的是,多普勒FFT的输入数据是距离FFT的结果,下面这行代码是表示对距离FFT结果的第二维(numloops dopplerBins)进行FFT运算:fftOutput = fft(inputMat, obj.dopplerFFTSize, 2); **

经过距离、多普勒FFT之后,需要将接收天线和发射天线维度合并为虚拟通道维度

DopplerFFTOut = reshape(DopplerFFTOut,size(DopplerFFTOut,1), size(DopplerFFTOut,2), size(DopplerFFTOut,3)*size(DopplerFFTOut,4));

经过上述操作得到了多普勒FFT数据,维度为:numSamplePerChirp256 x nchirp_loops 64 x 虚拟通道数 192

(4)非相干累加

:::success
在多普勒FFT之后,得到的是各个通道的多普勒频移信息。为了提高目标检测的信噪比,通常需要将多个通道的数据进行非相干累加。相比于单个通道的数据,非相干累加可以减少随机噪声的影响,从而提高目标信号的强度和可靠性。
:::

% CFAR done along only TX and RX used in MIMO array
DopplerFFTOut = reshape(DopplerFFTOut,size(DopplerFFTOut,1), size(DopplerFFTOut,2), size(DopplerFFTOut,3)*size(DopplerFFTOut,4));
%detection
sig_integrate = 10*log10(sum((abs(DopplerFFTOut)).^2,3) + 1);

这行代码是在对一组多普勒测量数据进行快速傅里叶变换(FFT)后计算信号功率的分贝(dB)值。
具体来说:

  • DopplerFFTOut是一个包含192个虚拟通道的多普勒FFT数据,每个通道的数据都是一个二维数组。
  • abs(DopplerFFTOut)对每个测量数据向量中的元素取绝对值,得到一个新的数组
  • sum((abs(DopplerFFTOut)).^2, 3)计算每个通道数据矩阵的平方和,并将所有通道数据的平方和相加。这里的3表示对第三个维度进行求和。
    • 1对上一步计算得到的结果加1,以避免在取对数时出现负数或零。
  • 10*log10()将上一步的结果转换为分贝值。这是将功率转换为分贝的标准公式。

经过上面的非相干累加,将sig_integrate绘图分析:
AWR2243cascade radar MIMO后处理梳理_第5张图片
AWR2243cascade radar MIMO后处理梳理_第6张图片
第一个图表示的是距离-强度图,图中最高的一条曲线表示零多普勒维度。第二个图是距离-多普勒-强度图,图中突出的一排表示的是零多普勒,用于CFAR检测的数据就是距离-多普勒-强度图的数据,实现目标识别。

(5)CFAR目标检测

算法文件路径:C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example\modules\detection@CFAR_CASO\datapath.m

这个模块实现了CA-CFAR算法,但是噪声被估计为较小的平均噪声水平由左右两个噪音分档估计。检测分两步完成。

  • 范围/多普勒FFT的输出被发送到检测模块。第一步是对所有虚拟通道进行非相干积分。
  • 进行距离CFAR检测(CFAR_CASO_Range.m),循环多普勒维度。
  • 然后在检测到的范围分组进行多普勒CFAR检测(CFAR_CASO_Doppler_overlap.m),循环距离维度。
  • 对于每个交叉检测的范围多普勒点, 应用最大速度扩展算法来纠正TDM

(a)CFAR_CASO_Range.m

该算法的基本思想是,对于每一个采样点,以其为中心,选择一定数量的左右邻域采样点,计算邻域内的平均值作为噪声水平,然后将该点的信号值与噪声水平比较,若超过一定阈值,则判断为目标。其中,K0值用于调节检测的灵敏度和虚警率。

function [N_obj, Ind_obj, noise_obj, CFAR_SNR] = CFAR_CASO_Range(obj, sig)

cellNum = obj.refWinSize;  %单元窗口
gapNum = obj.guardWinSize; %保护窗口
cellNum = cellNum(1);
gapNum = gapNum(1);
K0 = obj.K0(1);

M_samp=size(sig, 1);
N_pul=size(sig, 2);
%% input:  assuming size(input) = [numSamplePerChipr numChirpsPerFrame numAntenna]
%for each point under test, gapNum samples on the two sides are excluded
%from averaging. Left cellNum/2 and right cellNum/2 samples are used for
%averaging
gaptot=gapNum + cellNum;
N_obj=0;
Ind_obj=[];
noise_obj = [];
CFAR_SNR = [];

discardCellLeft = obj.discardCellLeft;
discardCellRight = obj.discardCellRight;
%for the first gaptot samples only use the right sample
for k=1:N_pul
    sigv=(sig(:,k))';
    vec = sigv(discardCellLeft+1:M_samp-discardCellRight);
    vecLeft = vec(1:(gaptot));
    vecRight = vec(end-(gaptot)+1:end);
    vec = [vecLeft vec vecRight];
    for j=1:(M_samp-discardCellLeft-discardCellRight)
        cellInd=[j-gaptot: j-gapNum-1 j+gapNum+1:j+gaptot];
        cellInd=cellInd + gaptot;
        cellInda=[j-gaptot: j-gapNum-1];
        cellInda=cellInda + gaptot;
        cellIndb=[ j+gapNum+1:j+gaptot];
        cellIndb=cellIndb + gaptot;
        
        cellave1a =sum(vec(cellInda))/(cellNum);
        cellave1b =sum(vec(cellIndb))/(cellNum);
        cellave1 = min(cellave1a,cellave1b);
        
        %if((j > discardCellLeft) && (j < (M_samp-discardCellRight)))
        if obj.maxEnable==1 %check if it is local maximum peak
            maxInCell = max(vec([cellInd(1):cellInd(end)]));
            if (vec(j+gaptot)>K0*cellave1 && ( vec(j+gaptot)>=maxInCell))
                N_obj=N_obj+1;
                Ind_obj(N_obj,:)=[j+discardCellLeft, k];
                noise_obj(N_obj) = cellave1; %save the noise level
                CFAR_SNR(N_obj) = vec(j+gaptot)/cellave1;
            end
        else
            if vec(j+gaptot)>K0*cellave1
                N_obj=N_obj+1;
                Ind_obj(N_obj,:)=[j+discardCellLeft, k];
                noise_obj(N_obj) = cellave1; %save the noise level
                CFAR_SNR(N_obj) = vec(j+gaptot)/cellave1;
            end
        end        
    end
end

%get the noise variance for each antenna
for i_obj = 1:N_obj
    ind_range = Ind_obj(i_obj,1);
    ind_Dop = Ind_obj(i_obj,2);
    if ind_range<= gaptot
        %on the left boundary, use the right side samples twice
        cellInd=[ind_range+gapNum+1:ind_range+gaptot ind_range+gapNum+1:ind_range+gaptot];
    elseif ind_range>=M_samp-gaptot+1
        %on the right boundary, use the left side samples twice
        cellInd=[ind_range-gaptot: ind_range-gapNum-1 ind_range-gaptot: ind_range-gapNum-1];
    else
        cellInd=[ind_range-gaptot: ind_range-gapNum-1 ind_range+gapNum+1:ind_range+gaptot];
    end    
end

N_obj表示检测到的目标数量,Ind_obj是一个二维矩阵,每行表示一个目标所在的行列索引,noise_obj表示检测到的目标处的噪声水平,CFAR_SNR表示检测到的目标处的信噪比。
CFAR-CASO算法流程图如下:
image.png
AWR2243cascade radar MIMO后处理梳理_第7张图片
:::success

  • 保护单元:保护单元是指在检测目标信号时,需要保护不被噪声干扰的区域。保护单元通常被定义为一个窗口,窗口的中心为当前正在检测的目标信号。
    :::
  • 参考单元:参考单元的作用是用于计算背景噪声的统计信息,通常使用参考单元中的噪声水平来作为阈值,以便将噪声和目标信号区分开来。CFAR-CASO算法流程图中用于计算平均值的部分

代码流程如下:

  1. sigv=(sig(:,k))';获取第一个多普勒维度的 256个采样点

  2. vecLeft = vec(1:(gaptot));
    vecRight = vec(end-(gaptot)+1:end);
    vec = [vecLeft vec vecRight];

    得到一个包含参考窗口、保护窗口和左右两侧扩展的邻域点的向量,为了解决CFAR算法中参考窗口和保护窗口边缘处数据不足的问题

  3. cellInd=[j-gaptot: j-gapNum-1 j+gapNum+1:j+gaptot];
    对于当前采样点j,以其为中心,左右各排除gapNum个邻域点,得到保护窗口;然后以保护窗口为基础,向左右各扩展gaptot-gapNum个邻域点,得到单元窗口。

  4. cellInd=cellInd + gaptot;
    cellInda=[j-gaptot: j-gapNum-1];

    cellInda=cellInda + gaptot; %[1,2,3,4,5,6,7,8]
    cellIndb=[ j+gapNum+1:j+gaptot];
    cellIndb=cellIndb + gaptot; %[26,27,28,29,30,31,32,33]
    cellave1a =sum(vec(cellInda))/(cellNum);
    cellave1b =sum(vec(cellIndb))/(cellNum);
    cellave1 = min(cellave1a,cellave1b);
    获取两边保护单元的数据索引,保护单元大小为8,并计算对应的平均值,最后取较小的平均值。

  5. 判决过程

if vec(j+gaptot)>K0*cellave1
    N_obj=N_obj+1;
    Ind_obj(N_obj,:)=[j+discardCellLeft, k];
    noise_obj(N_obj) = cellave1; %save the noise level
    CFAR_SNR(N_obj) = vec(j+gaptot)/cellave1;
end

这里使用了vec(j+gaptot)表示第一个距离门的采样数据是因为在前面两边各加了16个数据,防止边界检测的时候数据不足的情况。当这个数据大于阈值x保护单元的最小平均值时判定为目标,则保存数据索引、噪声、信噪比。

参考资料

AWRx_TX_Channel_Calibration_Script_User_Guide.pdf
signal_processing_4chip_cascade.pdf
signal_processing_4chip_cascade zh.pdf

你可能感兴趣的:(毫米波雷达,matlab,开发语言)