spoift指令

main.m-主函数文件(脚本文件用到的各个变量及响应赋值,和公式)

clear;

sample_csi_traceTmp =load('sample_csi_trace');//加载了名为 sample_csi_trace.mat 的文件,并将其存储在名为 sample_csi_traceTmp 的结构体变量(将.mat文件打开,送给结构体)

sample_csi_trace = sample_csi_traceTmp.sample_csi_trace;//文件中存储的变量名为 sample_csi_trace,所以通过 sample_csi_traceTmp.sample_csi_trace 来访问这个变量,并将其赋值给 sample_csi_trace 变量。(将文件中存储的东西通过结构体拿出来,赋值给一个变量,本质就是文件的内容无法直接送出,要经过结构体的打开)

fc = 5.63e9;//中心频率

M = 3;//rx天线个数

fs = 40e6;//通道频宽

c = 3e8;//光速

d = 2.6e-2;//线性天线阵列中相邻天线之间的距离

SubCarrInd =[-58,-54,-50,-46,-42,-38,-34,-30,-26,-22,-18,-14,-10,-6,-2,2,6,10,14,18,22,26,30,34,38,42,46,50,54,58];//CSI可用的WiFi子载波指数

N = length(SubCarrInd);//子载波数

fgap = 312.5e3;//WiFi中连续子载波之间以Hz为单位的频率差距

lambda = c/fc;//波长

T = 1;//发射机天线数

// MUSIC算法需要估计网格中的MUSIC频谱。paramRange捕获该网格的参数

//对于下面的示例,MUSIC频谱计算101ToF(飞行时间)值,间隔在- 25ns和25ns之间。MUSIC频谱是为101 AoA(到达角)值在-90度和90度之间计算的。

paramRange = struct; 

paramRange.GridPts = [101 101 1];//格式格点数[ToF(飞行时间)格点数,到达角(AoA)格点数,1]

paramRange.delayRange = [-50 50]*1e-9;//考虑ToF网格的最低和最高值。

paramRange.angleRange = 90*[-1 1];//最低和值考虑的AoA网格。

do_second_iter = 0;//是否进行二次迭代。

paramRange.K = floor(M/2)+1;//平滑相关参数。

paramRange.L = floor(N/2);//平滑相关参数。

paramRange.T = 1; 

paramRange.deltaRange = [0 0];

maxRapIters = Inf; 

useNoise = 0; 

paramRange.generateAtot = 2;

// ToF净化代码(SpotFi论文中算法1)

csi_plot = reshape(sample_csi_trace, N, M);//将sample_csi_trace重构成N*M的矩阵

[PhsSlope, PhsCons]=removePhsSlope(csi_plot,M,SubCarrInd,N);//调用removePhsSlope函数(消除斜率影响文件)

ToMult = exp(1i*(-PhsSlope*repmat(SubCarrInd(:),1,M) - PhsCons*ones(N,M)));//对CSI信道进行去斜率处理,ToMult表示对应子载波上的相位修正值

csi_plot = csi_plot.*ToMult;//信号CSI通过信道,ToF与AOA会对信号相位产生影响。

relChannel_noSlope = reshape(csi_plot, N, M, T);//reshape用于改变矩阵/向量形状;将csi_plot矩阵N*M变换成relChannel_noSlope矩阵N*M*T

sample_csi_trace_sanitized = relChannel_noSlope(:);//将矩阵relChannel_noSlope 重构成一个列向量,并赋值给变量 sample_csi_trace_sanitized;即将3D矩阵N*M*T变成一个一维向量。

//估计到达角的MUSIC算法

//aoaEstimateMatrix是(nComps x 5)矩阵,其中nComps是环境中的路径数量。第一列是ToF (ns),第二列是AoA(度),如SpotFi论文中定义的那样

aoaEstimateMatrix = backscatterEstimationMusic(sample_csi_trace_sanitized, M, N, c, fc, T, fgap, SubCarrInd, d, paramRange, maxRapIters, useNoise, do_second_iter, ones(2))//调用backscatterEstimationMusic函数, 根据 backscatterEstimationMusic 函数的定义,返回值应该是 [Parameters, varargout],其中 Parameters 是一个包含估计的参数的向量,varargout 是一个可选的输出变量。因此,aoaEstimateMatrix 可以是 Parameters 或者 varargout{1},取决于调用函数时是否传递了额外的输出参数。如果调用时没有传递额外的参数,则 aoaEstimateMatrix 是 Parameters,否则就是 varargout{1}。

tofEstimate=aoaEstimateMatrix(:,1);//从aoaEstimateMatrix中取出所有行的第一个元素,然后赋值给tofEstimate

aoaEstomate = aoaEstimateMatrix(:,2);//从 aoaEstimateMatrix 矩阵中取出第二列,即所有行的第二个元素,存储到 aoaEstomate 向量中

removePhsSlope.m-消除相位斜率的影响文件

function[PhsSlope,PhsCons,vna_response_corrected]=removePhsSlope(vna_response,M,SubCarrInd,N)

useCvxgen = 0;//使用非凸优化库Cvxgen来计算相位斜率和常数。如果不使用Cvxgen,则使用矩阵计算来计算相位斜率和常数。(本函数使用矩阵计算相位斜率和常数)

if ~useCvxgen //useCvxgen =0,所以下面的if语句执行

    PhsRelFirstPac = unwrap(angle(vna_response));//angle函数为复数数组 z 的每个元素返回区[-π,π]中的相位角,unwrap函数:相位展开以确保相邻相位变化在[-pi, pi]的范围内,一列。(将vna_response矩阵的每个元素的相位展开,并将结果存储在PhsRelFirstPac矩阵中)

//下面的代码用于使用相位相对时

//第一个包

    for antIdForPhs = 1:M //PhsRelFirstPac(1,antIdForPhs)表示第antIdForPhs个天线的第一个数据点的相位角度,而PhsRelFirstPac(1,1)则表示第一个天线的第一个数据点的相位角度。因此,PhsRelFirstPac(1,antIdForPhs) - PhsRelFirstPac(1,1)就是第antIdForPhs个天线的第一个数据点的相位角度与第一个天线的第一个数据点的相位角度之差。

        if PhsRelFirstPac(1,antIdForPhs) - PhsRelFirstPac(1,1) > pi 

            PhsRelFirstPac(:,antIdForPhs) = PhsRelFirstPac(:,antIdForPhs) - 2*pi; 

        elseif PhsRelFirstPac(1,antIdForPhs) - PhsRelFirstPac(1,1) < -pi 

            PhsRelFirstPac(:,antIdForPhs) = PhsRelFirstPac(:,antIdForPhs) + 2*pi; 

    end

end 

A = [repmat(SubCarrInd(:), M, 1) ones(N*M, 1)]; //由所选的子载波编号和全1向量组成,repmat重复数组副本(将SubCarrlnd(:)矩阵复制成M*1矩阵模样),ones(N*M,1)生产一个N*M的全是1的矩阵。

x = A\PhsRelFirstPac(:);//x向量是A矩阵的伪逆与PhsRelFirstPac矩阵展开后的向量的乘积

PhsSlope = x(1);//x(1)是相位斜率

PhsCons = x(2);//x(2)是相位常数

end

backscatterEstimationMusic.m-MUSIC算法的回波功率谱密度估计(MUSIC用于从数据中估计信号频率和空间分量的算法,回波功率谱密度估计是分析信号的回波信号,即从接收到的信号中提取有用的信息)

function [Parameters, varargout] = backscatterEstimationMusic(csi_trace, M, N, c, fc, Ttot, fgap, SubCarrInd, d, paramRange, maxRapIters, useNoise, do_second_iter, varargin)

nComps = [];//初始化这个变量,将其设置为空值

corrThr = 0.4;//相关性阈值决定有多少组件后,我们决定切断MUSIC进程(决定在多少个成分后截断的相关阈值)

//以前使用的值为0.83。这个值应该是截止角的cosd与投影平面的平方

if ~isempty(varargin) //isempty判断矩阵是否为空,为空则返回逻辑1,否则0

    parametersTrue = varargin{1};//将其赋值为varargin的第一个元素,{}表示cell数组,返回的是矩阵本身,即ones(2)

    nComps = size(parametersTrue,1);//返回ones维度1的大小为2

    if   nComps==0, nComps = []; end;

end

//音乐参数

//K =地板(M/2)+1;% K是选择用于平滑音乐的天线子集的数量。默认值为(M/2)+1

//L =地板(N/2);% L是为平滑音乐而选择的子载波子集的数目。默认值为floor(N/2)

//对于移动定位

if ~isfield(paramRange,'K')//判断K是否是结构体数组paramRange的一个字段的名称,是则返回1,不是则为0。

    K = floor(M/2)+1;//y因为返回的是1,所以下面三行不执行

    L = floor(N/2); 

    T = floor(Ttot/2)+1;

else 

    K = paramRange.K; 

    L = paramRange.L; 

    T = paramRange.T; 

end

//do_second_iter=0;//做两次迭代

if ~isfield(paramRange,'delayRange')//判断delayRange是否是结构体数组paramRange的一个字段的名称,是则返回1,不是则为0。

    delayRange = [-25 25]*1e-9;%[-25 70]//isfield因为返回的是1,所以下面三行不执行

    deltaRange = [-c/2/fc c/2/fc]; 

    angleRange = [-90 90]; 

    GridPts = [100 100 100];  

else 

    delayRange = paramRange.delayRange; 

    deltaRange = paramRange.deltaRange; 

    angleRange = paramRange.angleRange; 

    GridPts = paramRange.GridPts; 

end 

MaxAngle = angleRange(2);//AOA相位角的最大值为90

MinAngle = angleRange(1);//AoA相位角的最小值为-90

if isempty(maxRapIters)//判断maxRaplter是否为空,maxRaplters为Inf,则返回1.

     maxRapIters = Inf;

end 

if do_second_iter//是否进行两次迭代,因为否,所以直接执行else

    if~isfield(paramRange,'seconditerGridPts') 

        GridPts = [70 70 35];

        MaxAngle = MaxAngle*(GridPts(2)-1)/(GridPts(2)+1); 

        MinAngle = -MaxAngle; 

        seconditerGridPts = [15 25 2]; %[15 25 5]; 

    else 

        seconditerGridPts = paramRange.seconditerGridPts; 

    end 

else 

    seconditerGridPts = [];//seconditerGridPts是一个空矩阵

 end 

if ~isfield(paramRange,'circularTx')//判断circularTx是否是结构体数组paramRange的一个字段的名称,是则返回1,不是则为0。这是0。

    paramRange.circularTx = 0; 

end 

if paramRange.circularTx == 1//此行不执行,因为paramRange.circularTx=0

    if ~isfield(paramRange, 'deltaRange') 

        deltaRange = 0:359; 

    else 

        deltaRange = paramRange.deltaRange; 

    end 

    dTx = paramRange.dTx; 

end 

[aTot,GridStart,GridSpacing, delayGridValue, u_sGridValue, deltaGridValue] = gridVecBackscatter(deltaRange, M, T, d, fc, c, do_second_iter, delayRange, SubCarrInd, N, fgap, GridPts, MaxAngle, MinAngle, paramRange.generateAtot);//调用gridVecBackscatter函数

EigDiffCutoff = 4; 

if ~isfield(paramRange,'X')

     X = formatCSI(csi_trace, N, M, Ttot, K, L, T);//调用formatCSI函数

else 

    X = paramRange.X; 

end 

[Pn,Ps,Qn,Qs,EigenInfo]=GetQnBackscatter(X,EigDiffCutoff, nComps);//获取信号中反向散射信号的贡献,输出的结果包括噪声主子空间Pn,信号主子空间Ps,噪声子空间对应的投影矩阵Qn,信号子空间对应的投影矩阵 Qs,以及一些特征信息EigenInfo。

delayFromMusic =[]; 

angleFromMusic =[]; 

deltaFromMusic =[];

 if ~useNoise 

    nIters = min(maxRapIters,size(Qs,2)); 

else 

    nIters = 1; 

end 

maxCorr = zeros(nIters,1); 

doBreak = 1;//是否应用break语句

 if paramRange.circularTx == 0 

    for k=1:nIters 

        [delayFromMusicTmp,angleFromMusicTmp, deltaFromMusicTmp, maxCorr(k),music_spectrum] =RAPMusicGridMaxBackscatter(aTot,GridStart,GridSpacing,GridPts,Qn,Qs,fc,fgap,d,K,L,delayFromMusic,angleFromMusic, deltaFromMusic,SubCarrInd, deltaGridValue, u_sGridValue, delayGridValue, T, c, do_second_iter, seconditerGridPts, useNoise);

        if k==1

            varargout{1} = music_spectrum;//varargout表示第一个输参数

        end 

        if ~doBreak 

            delayFromMusic=[delayFromMusic; delayFromMusicTmp]; 

            angleFromMusic=[angleFromMusic; angleFromMusicTmp]; 

            deltaFromMusic=[deltaFromMusic; deltaFromMusicTmp]; 

        else 

            if k==1 

                delayFromMusic = [delayFromMusic; delayFromMusicTmp]; 

                angleFromMusic = [angleFromMusic; angleFromMusicTmp]; 

                deltaFromMusic = [deltaFromMusic; deltaFromMusicTmp]; 

            else 

                if maxCorr(k)>corrThr*max(maxCorr) 

                    delayFromMusic = [delayFromMusic; delayFromMusicTmp]; 

                    angleFromMusic = [angleFromMusic; angleFromMusicTmp]; 

                    deltaFromMusic = [deltaFromMusic; deltaFromMusicTmp]; 

                else 

                    break 

                end 

            end 

        end 

    end 

    if ~doBreak 

        allParameters = [delayFromMusic*1e9 angleFromMusic deltaFromMusic*1e3]; 

        varargout{1} = allParameters; 

        cutoffEntry = find(maxCorr<corrThr*maxCorr(1),1)-1; 

        if isempty(cutoffEntry) 

        cutoffEntry = length(maxCorr); 

        end 

        delayFromMusic = delayFromMusic(1:cutoffEntry); 

        angleFromMusic = angleFromMusic(1:cutoffEntry); 

        deltaFromMusic = deltaFromMusic(1:cutoffEntry);

    end 

end 

alphaFromMusic = zeros(length(delayFromMusic),1);//创建一个length(delayFromMusic)*1的全零矩阵

if paramRange.circularTx == 1

    if ~isfield(paramRange, 'X') 

        Ahat = []; 

        for compNo = 1:length(delayFromMusic) 

        u_s = (d*fc/c)*sind(angleFromMusic(compNo)); 

        Ahat(:,compNo) = gridSampleBackscatter(fc, Ttot, deltaFromMusic(compNo), M, u_s, c, SubCarrInd(1:N), fgap, delayFromMusic(compNo) );

         end 

        alphaFromMusic = Ahat\csi_trace; 

        residualEstimationError = norm(csi_trace - Ahat*alphaFromMusic)/norm(csi_trace); 

        varargout{1}.residualEstimationError = residualEstimationError; 

    end 

end 

Parameters = [delayFromMusic*1e9 angleFromMusic deltaFromMusic*1e3 abs(alphaFromMusic) angle(alphaFromMusic)];//将delayFromMusic *1e9 、angleFromMusic、deltaFromMusic*1e3 、abs(alphaFromMusic)、angle(alphaFromMusic)这五个变量沿着列方向拼接成一个矩阵,然后将这个矩阵作为Parameters变量的值

上文中包含了几个基础的函数:gridVecBackscatter用于计算回波信号在网格点处的分量值;formatCSI:对输入CSI数据进行格式化处理;GetQnBackscatter:获取Qn和Qs矩阵以进行MUSIC算法处理; gridSampleBackscatter:对估计结果进行后处理。

gridVecBackscatter-提供回波的模拟数据

function [aTot,GridStart,GridSpacing, delayGridValue, u_sGridValue, deltaGridValue] = gridVecBackscatter(deltaRange, M, T, d, fc, c, do_second_iter, delayRange, SubCarrInd, N, fgap, GridPts, MaxAngle, MinAngle, generateAtot)

GridStart = [delayRange(1) MinAngle deltaRange(1)];//输入的值是[0,-90,0]

GridStop = [delayRange(2) MaxAngle deltaRange(2)];//输入的值是[0,90,0]

GridSpacing = (GridStop-GridStart)./max(1, GridPts-ones(size(GridPts)));//size函数返回矩阵行列大小;ones返回矩阵1*3的全是1的矩阵;max将1与后面矩阵每一项对比,选最大的一个,返回1*3的矩阵;进行点除,返回最后的值[0,1.8,0]。

angleStart = GridStart(2);//-90

delayStart = GridStart(1);//0

deltaStart = GridStart(3);//0

angleDiff = GridSpacing(2);//1.8

delayDiff = GridSpacing(1);//0

deltaDiff = GridSpacing(3);//0

numGridPoints = prod(GridPts);//prod返回向量元素乘积101*101*1

[delayIndices,angleIndices,deltaIndices] = ind2sub(GridPts,1:numGridPoints);//将线性索引换成下标,本质就是将GridPts矩阵101*101*1矩阵排数,从上往下,再从左往右排数,再将从中选出1-numGridPoints,将其中第一位数送给delayIndices,第二位数送给angleIndices,第三位数送给deltaIndices。

delayGridValue = delayStart + (delayIndices-1)*delayDiff;//0

angleGridValue = (angleStart + (angleIndices-1)*angleDiff)*pi/180;

u_sGridValue = (d*fc/c)*sin(angleGridValue); 

deltaGridValue = deltaStart + (deltaIndices-1)*deltaDiff;//0

aTot = [];//将其设置为空矩阵

if ~generateAtot

    load('aTotSaveSpotfi');

else

    aTot = zeros(N*M*T,numGridPoints);//组件一个90*(101*101)的全0数组。

    for gridEntry = 1:numGridPoints

        aTot(:,gridEntry) =gridSampleBackscatter(fc,T,deltaGridValue(gridEntry), M, u_sGridValue(gridEntry), c,SubCarrInd,fgap, delayGridValue(gridEntry));//调用gridSampleBackscatter函数

    end

    if generateAtot == 2

        save('aTotSaveSpotfi','aTot')//将名为 aTot 的变量保存到名为 aTotSaveSpotfi 的 MATLAB 数据文件中;保存的文件格式通常为.mat。

    end

end

gridSampleBackscatter-对接收到的信号进行波束形成,以便在目标检测和成像等应用中提取目标信息。(波束形成:通过对接收信号的加权和相位调节,从而实现指向性的信号辐射或接收)

function steeringVec = gridSampleBackscatter(fc, T, deltak, M, u_s, c, SubCarrInd, fgap, delay)    

//fc:中心频率

//T:等位移的时间瞬间数

//delta:沿发射机tak方向的位移

aoaSteering = exp(-1i*2*pi*u_s*(-(M-1)/2:(M-1)/2)');//这行代码定义了一个名为 aoaSteering 的向量,该向量用于在入射角处生成一个指向性相应。

aoaSteeringInv = exp(-1i*2*pi*fc*(0:(T-1))'*deltak/c);//这行代码定义了一个名为 aoaSteeringInv 的向量,用于在信号采样的时间/频率上生成一个指向性响应。

delaySteering = exp(-1i*2*pi*(SubCarrInd(:))*fgap*delay);//这行代码定义了一个名为delaySteering 的向量,对应于在给定子载波下的延迟。

steeringVecDelayAoATmp = delaySteering*aoaSteering.';//这行代码定义了一个名为 steeringVecDelayAoATmp 的矩阵。

steeringVecDelayAoA = steeringVecDelayAoATmp(:);//这行代码将矩阵 steeringVecDelayAoATmp 压缩成一个列向量。

steeringVecTmp = steeringVecDelayAoA*aoaSteeringInv.';//这行代码定义了一个名为 steeringVecTmp 的矩阵,它是将 steeringVecDelayAoA 与 aoaSteeringInv的共轭转置相乘 

steeringVec = steeringVecTmp(:);//将 steeringVecTmp 矩阵展平为列向量 steeringVec

formatCSI-对CSI数据进行格式化处理(将输入的CSI矩阵按时间,天线和子载波进行分块,并将这些分块转换成一个用于3D MUSIC算法输入的矩阵X)

function X = formatCSI(csi_trace, N, M, Ttot, K, L, T)

//X是我们输入到MUSIC的矩阵

X = [];

X3D = [];//初始化两个变量 X 和 X3D

csiTracePerPkt = reshape(csi_trace, N, M, Ttot);//并将输入的 CSI 矩阵按照(N, M, Ttot)的形状重新排列成 csiTracePerPkt

for iT = 1:Ttot

    ysenarr = csiTracePerPkt(:,:,iT);//选择第iT个时间步对应的所有元素组成的二维矩阵,即ysenarr成为一个N*M的二维矩阵。

    [N,M] = size(ysenarr);

    D = [];

    for m=1:M 

        D{m} = hankel(ysenarr(1:L,m),ysenarr(L:N,m));//用指定的列和行向量创建一个非对称 Hankel矩阵,生成一个大小为 L x (N-L+1)的 Hankel 矩阵,对于 m=1:M 中的每个 m,D{m} 都存储了一个 Hankel 矩阵。

    end

    De = zeros(K*L, (M - K +1)*(N - L+1));//设置一个全零矩阵

    for start_idx = 1:K

        tmp =cat(2,D{start_idx:start_idx+M-K});//串联矩阵,选择垂直串联矩阵。

        De((start_idx-1)*L+(1:L),:) = tmp;//将temp放在De对应位置

    end

    X = [X; De];//将所有的 De 拼接成一个大的矩阵 X

    X3D{iT} = De;//将 De 存储在 X3D 的第 iT 个元素中

end

//如果需要执行 3D MUSIC 算法,则将所有的 De 拼接成一个三维矩阵 X3D,并将 X3D 中的子矩阵按照时间顺序拼接成一个大的矩阵 X

X = zeros(K*L*T, (M - K + 1)*(N - L + 1)*(Ttot - T + 1));//将X设置为一个全0矩阵

subarraySizeAntSubcarr = L*K;

for start_idx = 1:T

    tmp =  cat(2,X3D{start_idx:start_idx+Ttot-T});

    X((start_idx-1)*subarraySizeAntSubcarr + (1:subarraySizeAntSubcarr),:) = tmp;

end//最终输出的矩阵 X 用于 MUSIC 算法的输入。

GetQnBackscatter-实现了获取输入矩阵的后向散射(Qn)、信号空间投影矩阵(Ps)、噪声空间投影矩阵(Pn)、正向散射(Qs)、EigenInfo特征信息(包括U矩阵,信号空间的多路径数量,奇异值)。

function [Pn,Ps,Qn,Qs,EigenInfo] = GetQnBackscatter(X,EigDiffCutoff, nComps)

[Utmp,D] = eig(X*X');//计算矩阵XX'的特征分解,其中Utmp是XX'的特征向量矩阵,D是XX'的特征值矩阵

D = abs(D);//将矩阵D中的元素全部取绝对值,取绝对值是为了确保所有的特征值都是非负的。

[Dtmp,I] = sort(diag(D), 'descend');//将对角线元素从大到小排序,并且返回排序后的结果和排序后每个元素的原始下标。diag(D)提取矩阵D的对角线元素,形成一个列向量,descend表示降序。Dtmp保存排好序的对角线元素值,I保存排序前每个元素的下标。

D = diag(Dtmp);//diag 函数可以将一个向量转换成对角矩阵。

U = Utmp(:,I);//这行代码将矩阵 Utmp 的列按从大到小的顺序排列,并将结果存储在矩阵 U 中

//设置常数

minMP = 2;

useMDL = 0;

useDiffMaxVal = 0;

MDL = [];

lambdaTot = diag(D);//diag(D)提取矩阵D的对角线元素,形成一个列向量。

subarraySize = size(X,1);//返回X第一维度的大小。

nSegments = size(X,2);//返回X第二维度的大小。

maxMultipath = length(lambdaTot);//返回lanbdaTot的长度,即矩阵D对角线元素的长度。

for k = 1:maxMultipath

    MDL(k) =-nSegments*(subarraySize-(k-1))*log(geo_mean(lambdaTot(k:end))/mean(lambdaTot(k:end))) + 0.5*(k-1)*(2*subarraySize-k+1)*log(nSegments);//log函数返回参数的对数值,mean返回向量的均值。nSegments和subarraySize分别是输入数据X的段数和子阵列大小。lambdaTot是信号子空间和噪声子空间的特征值向量。geo_mean(lambdaTot(k:end))/mean(lambdaTot(k:end))计算了特征值的几何平均值除以算术平均值。

end

[~, SignalEndIdxTmp] = min(MDL);//找到MDL向量最小值的索引,~表示忽略第一个输出参数,即最小值,SignalEndIdxTmp赋值为MDL的最小值的索引。

if useMDL

    SignalEndIdx = max(SignalEndIdxTmp-1, 1);

else

    VecForSignalEnd = wkeep(diag(D),5,'l');//对角线元素向量 diag(D) 的长度限制为5,wkeep 函数的第二个参数表示保留的长度,第三个参数表示从左边开始保留元素。

    diag(D(1:floor(length(D)/2)));//这行代码的作用是取矩阵D的前一半对角线元素,并将它们放在一个对角矩阵中。floor意思向下取整。

    Criterion1 = diff(db(VecForSignalEnd))<=max(-EigDiffCutoff,min(diff(db(VecForSignalEnd))));//db是用于计算分贝 (dB) 的函数,其计算方式为:db(x)=20log10(x);diff函数可以对向量进行差分操作,即对相邻元素之间的差值进行计算,输出一个长度比原向量小1的向量;表示满足一定条件的子空间信号成分的终止点的位置,

    Criterion3 = (VecForSignalEnd(1:end-1)/VecForSignalEnd(1)>0.03);//元素的值是VecForSignalEnd中的每个元素除以VecForSignalEnd的第一个元素是否大于0.03,即对于VecForSignalEnd的每个元素,如果它除以VecForSignalEnd的第一个元素大于0.03,则相应的Criterion3元素为1,否则为0。

    SignalEndIdx = find(Criterion1 & Criterion3,1,'last');//通过使用find函数,查找同时满足Criterion1和Criterion3条件的最后一个位置,并将该位置赋值给变量SignalEndIdx。通过同时满足这两个条件,可以找到信号的结束位置。

    if isempty(SignalEndIdx)

        SignalEndIdx = find(Criterion3,1,'last');

    end

end

SignalEndIdx = max(SignalEndIdx, minMP);//minMP=2,找出SignalEndldx和minMP的最大值。

if ~isempty(nComps)//nComps=2,不是空

    SignalEndIdx = nComps;

end

//各种输出的结果公式。

Qn = U(:,SignalEndIdx+1:end);//将变换矩阵U的第SignaEndldx+1到最后一列的所有列向量提取出来,组成矩阵Qn。

Pn = (Qn*Qn');//Qn与Qn的共轭转置或转置相乘

Qs = U(:,1:SignalEndIdx);//将变换矩阵U的第1到第SignalEndldx的所有列向量提取出来,组成矩阵Qs

Ps = (Qs*Qs');//Qs与Qs的共轭转置或转置相乘

EigenInfo = struct;//定义为结构体

EigenInfo.Umatrix = U;//结构体变量定义为U

EigenInfo.nMPs = SignalEndIdx;//结构体变量定义为SignalEndldx

EigenInfo.singularValuesdB = db(diag(D));//结构体变量定义为D的对角矩阵的分贝计算函数

RAPMusicGridMaxBackscatter-执行ICFD算法并计算所需的输出,如延迟,角度,多普勒偏移量,最大相关系数和MUSIC谱(ICFD是一种基于MUSIC算法的信号处理技术,包含两个步骤:第一步是对雷达回波信号进行波束形成,以提取信号的方向信息和延迟信息。第二步是对所得到的方向和延迟信息进行迭代估计和校正,以减少多径效应的影响。 ICFD技术的主要优点是,它可以提高目标信号的信噪比,并减少多径效应对目标信号的影响)

function [delayFromMusic, angleFromMusic, deltaFromMusic, maxCorr, music_spectrum_plot] = RAPMusicGridMaxBackscatter(aTot,GridStart,GridSpacing,GridPts,Qn,Qs,fc,fgap,d,K,L,delayFromMusicPrev,angleFromMusicPrev, deltaFromMusicPrev, SubCarrInd, deltaGridValue, u_sGridValue, delayGridValue, T, c, do_second_iter, seconditerGridPts, useNoise)//delayFromMusic:计算出的延迟向量;angleFromMusic:计算出的角度向量;deltaFromMusic:计算出的多普勒偏移量向量;maxCorr:最大相关系数;music_spectrum_plot:MUSIC谱。

maxCorr = [];//将其设置为空矩阵

if ~useNoise

    if ~isempty(delayFromMusicPrev)

        Ahat = [];

        for compNo = 1:length(delayFromMusicPrev)

            u_s = (d*fc/c)*sind(angleFromMusicPrev(compNo));

            Ahat(:,compNo) = gridSampleBackscatter(fc, T, deltaFromMusicPrev(compNo), K, u_s, c, SubCarrInd(1:L), fgap, delayFromMusicPrev(compNo) );

        end

        PerpAhat = eye(size(Ahat,1)) - Ahat*pinv(Ahat'*Ahat)*Ahat';

    else

        PerpAhat = eye(size(Qs,1),'like',2+1i);//创建一个方阵,大小为Qs的行数,列数与行数相同,like 参数指定了创建的矩阵的数据类型和储存方式,它使用了一个复数类型的2+1i 作为参考类型。(eye函数创建一个对角线上全是1,其他元素全是0的矩阵,然后乘以2+1i),最终得到的矩阵 PerpAhat 对角线上全是2+1i,其他元素全是0。

    end

    Qs = PerpAhat*Qs;

    Ps = (Qs*Qs');

    numGridPts = prod(GridPts);//返回向量元素乘积,即[101,101,1]乘积

    delayConsider = GridStart(1) + (0:GridPts(1)-1)*GridSpacing(1);

    u_sConsider = (d*fc/c)*sind( GridStart(2) + (0:GridPts(2)-1)*GridSpacing(2) );//sind返回元素的正弦

    deltaConsider = GridStart(3) + (0:GridPts(3)-1)*GridSpacing(3);

    delaySteeringMat = exp(-1i*2*pi*(SubCarrInd(1:L).')*fgap*delayConsider);

    aoaSteeringMat = exp(-1i*2*pi*((-(K-1)/2:(K-1)/2)')*u_sConsider);

    aoaSteeringInvMat = exp(-1i*2*pi*(fc/c)*((0:(T-1))')*deltaConsider);

    thetaTauMat = kron(aoaSteeringMat, delaySteeringMat);//返回矩阵aoaSteeringMat  和 delaySteeringMat 的 Kronecker 张量积

    thetaTauDeltaMat = kron(aoaSteeringInvMat, thetaTauMat);

    PerpAhat_a = PerpAhat*thetaTauDeltaMat;

    PsA = Ps*PerpAhat_a;

    music_spec_num = sum((PerpAhat_a').*(PsA.'),2);//返回PerpAhat_a共轭转置矩阵与PsA转置矩阵的乘积的 每一行总和的列向量。

    music_spec_den = sum((PerpAhat_a').*(PerpAhat_a.'),2);

    music_spectrum = abs(music_spec_num./music_spec_den);//返回数组每个元素的绝对值

else

    delayConsider = GridStart(1) + (0:GridPts(1)-1)*GridSpacing(1);

    u_sConsider = (d*fc/c)*sind( GridStart(2) + (0:GridPts(2)-1)*GridSpacing(2) );

    deltaConsider = GridStart(3) + (0:GridPts(3)-1)*GridSpacing(3);

    delaySteeringMat = exp(-1i*2*pi*(SubCarrInd(1:L).')*fgap*delayConsider);

    aoaSteeringMat = exp(-1i*2*pi*((-(K-1)/2:(K-1)/2)')*u_sConsider);

    aoaSteeringInvMat = exp(-1i*2*pi*(fc/c)*((0:(T-1))')*deltaConsider);

    thetaTauMat = kron(aoaSteeringMat, delaySteeringMat);

    thetaTauDeltaMat = kron(aoaSteeringInvMat, thetaTauMat);

    PnA = (Qn*Qn')*thetaTauDeltaMat;

    thetaTauDeltaMatTrans = thetaTauDeltaMat';

    music_spectrum = sum(thetaTauDeltaMatTrans.*(PnA.'),2);

    music_spectrum = 1./abs(music_spectrum);

end

if ~useNoise

    [maxCorr,loopVarMax] = max(music_spectrum);//maxCorr是music_spectrum中的最大值, loopVarMax是maxCorr在music_spectrum中的索引位置,也就是maxCorr所在的频率下标

    [delay_idx,angle_idx, delta_idx] = ind2sub(GridPts,loopVarMax);//delay_idx 表示最大元素在第一维上的位置,angle_idx 表示最大元素在第二维上的位置,delta_idx 表示最大元素在第三维上的位置

    delayFromMusic = GridStart(1) + (delay_idx-1)*GridSpacing(1);

    angleFromMusic = GridStart(2) + (angle_idx-1)*GridSpacing(2);

    deltaFromMusic = GridStart(3) + (delta_idx-1)*GridSpacing(3);

else

    music_spectrum = reshape(music_spectrum,GridPts(1),GridPts(2),GridPts(3));

    BW = imregionalmax(music_spectrum);

    [delay_idx, angle_idx, delta_idx] = ind2sub(size(BW), find(BW));

    topPeakIndices = topk(music_spectrum(BW), min(size(Qs,2), length(find(BW(:)))));

    delayFromMusic = GridStart(1) + (delay_idx(topPeakIndices)-1)*GridSpacing(1);

    angleFromMusic = GridStart(2) + (angle_idx(topPeakIndices)-1)*GridSpacing(2);

    deltaFromMusic = GridStart(3) + (delta_idx(topPeakIndices)-1)*GridSpacing(3);

    maxCorr = max(music_spectrum);

end

music_spectrum = reshape(music_spectrum,GridPts(1),GridPts(2),GridPts(3));//重构 music_spectrum矩阵

music_spectrum_plot = music_spectrum;

if do_second_iter 

    delayFirstIter = delayFromMusic;

    angleFirstIter = angleFromMusic;

    deltaFirstIter = deltaFromMusic;

    for iComp = 1:length(delayFirstIter)

        GridPts = seconditerGridPts;

        delayRange = [delayFirstIter(iComp)-GridSpacing(1) delayFirstIter(iComp)+GridSpacing(1)];

        angleRange = [angleFirstIter(iComp)-GridSpacing(2) angleFirstIter(iComp)+GridSpacing(2)];

        deltaRange = [deltaFirstIter(iComp)-GridSpacing(3) deltaFirstIter(iComp)+GridSpacing(3)];

        [GridStart, GridSpacing, delayGridValue, u_sGridValue, deltaGridValue] = gridParamsBackscatter(GridPts, angleRange, deltaRange, d, fc, c, delayRange);

        if ~useNoise

            numGridPts = prod(GridPts);

            delayConsider = GridStart(1) + (0:GridPts(1)-1)*GridSpacing(1);

            u_sConsider = (d*fc/c)*sind( GridStart(2) + (0:GridPts(2)-1)*GridSpacing(2) );

            deltaConsider = GridStart(3) + (0:GridPts(3)-1)*GridSpacing(3);

            delaySteeringMat = exp(-1i*2*pi*(SubCarrInd(1:L).')*fgap*delayConsider);

            aoaSteeringMat = exp(-1i*2*pi*((-(K-1)/2:(K-1)/2)')*u_sConsider);

            aoaSteeringInvMat = exp(-1i*2*pi*(fc/c)*((0:(T-1))')*deltaConsider);

            thetaTauMat = kron(aoaSteeringMat, delaySteeringMat);

            thetaTauDeltaMat = kron(aoaSteeringInvMat, thetaTauMat);

            PerpAhat_a = PerpAhat*thetaTauDeltaMat; 

            PsA = Ps*PerpAhat_a;

            music_spec_num = sum((PerpAhat_a').*(PsA.'),2);            

            music_spec_den = sum((PerpAhat_a').*(PerpAhat_a.'),2);

            music_spectrum = abs(music_spec_num./music_spec_den);

       else

            delayConsider = GridStart(1) + (0:GridPts(1)-1)*GridSpacing(1);

            u_sConsider = (d*fc/c)*sind( GridStart(2) + (0:GridPts(2)-1)*GridSpacing(2) );

            deltaConsider = GridStart(3) + (0:GridPts(3)-1)*GridSpacing(3);

            delaySteeringMat = exp(-1i*2*pi*(SubCarrInd(1:L).')*fgap*delayConsider);

            aoaSteeringMat = exp(-1i*2*pi*((-(K-1)/2:(K-1)/2)')*u_sConsider);

            aoaSteeringInvMat = exp(-1i*2*pi*(fc/c)*((0:(T-1))')*deltaConsider);

            thetaTauMat = kron(aoaSteeringMat, delaySteeringMat);

            thetaTauDeltaMat = kron(aoaSteeringInvMat, thetaTauMat);

            PnA = (Qn*Qn')*thetaTauDeltaMat;

            thetaTauDeltaMatTrans = thetaTauDeltaMat';

            music_spectrum = sum(thetaTauDeltaMatTrans.*(PnA.'),2);

            music_spectrum = 1./abs(music_spectrum);

        end

        if ~useNoise

            [maxCorrTmp,loopVarMaxTmp] = max(music_spectrum);

            maxCorr = maxCorrTmp(1);

            loopVarMax = loopVarMaxTmp(1);

            [delay_idx,angle_idx, delta_idx] = ind2sub(GridPts,loopVarMax);

            delayFromMusic = GridStart(1) + (delay_idx-1)*GridSpacing(1);

            angleFromMusic = GridStart(2) + (angle_idx-1)*GridSpacing(2);

            deltaFromMusic = GridStart(3) + (delta_idx-1)*GridSpacing(3);

        else

            maxCorr = max(music_spectrum);

            music_spectrum = reshape(music_spectrum,GridPts(1),GridPts(2),GridPts(3));

            BW = imregionalmax(music_spectrum);

            [delay_idx, angle_idx, delta_idx] = ind2sub(size(BW), find(BW));

            topPeakIndices = topk(music_spectrum(BW), 1);

            delayFromMusic(iComp) = GridStart(1) + (delay_idx(topPeakIndices)-1)*GridSpacing(1);

            angleFromMusic(iComp) = GridStart(2) + (angle_idx(topPeakIndices)-1)*GridSpacing(2);

            deltaFromMusic(iComp) = GridStart(3) + (delta_idx(topPeakIndices)-1)*GridSpacing(3);

        end

    end

end


本文章仅个人学习使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容