Widar3.0:Matlab代码学习笔记

CSI_TOOL_BOX部分

csi_get_all.m

function [cfr_array, timestamp] = csi_get_all(filename)
	csi_trace = read_bf_file(filename);
	...
	csi_all = squeeze(get_scaled_csi(csi_entry)).';
	...
	csi = [csi_all(:,1); csi_all(:,2); csi_all(:, 3)].';
	...
	cfr_array(k,:) = csi;
end
  • 读取文件中的CSI数据,并将结果存储在csi_trace变量中。

  • 调用get_scaled_csi函数,将csi_entry作为参数传递,并将返回的标准化CSI数据存储在csi_all中。

  • 从csi_all中选择一个天线对应的CSI数据,并将其展开成一个行向量csi

  • 将csi存储在cfr_array的第k行中,用于构建频率响应矩阵。

read_bf_file.m文件

输出

输出

  • 输出结果和初次csi matlab复现时结果相同

  • 1 * 3 * 30 的数据

  • (:,perm(1:Nrx),:) 表示对 CSI 数据进行切片操作

  • ret{count}.csi(:,1:Nrx,:) 表示以原始天线顺序为基准的 CSI 数据。
ret{count}.csi(:,perm(1:Nrx),:) = ret{count}.csi(:,1:Nrx,:);

read_bfee.c

在 MATLAB 中,可以通过 MEX 文件来调用使用 C 语言编写的函数。MEX 文件是一种特殊的 MATLAB 可执行文件,允许 MATLAB 与底层的 C 或 C++ 代码进行交互。通过 MEX 文件,您可以将 C 语言代码编译成 MATLAB 可识别的二进制文件,从而在 MATLAB 环境中调用 C 函数。

使用 MATLAB 提供的 MEX 工具(mex 命令)将 C 函数编译成 MEX 文件。 这将生成一个 MATLAB 可执行文件,用于在 MATLAB 中调用 C 函数。

disp

  • 控制台输出

BVP部分

generate_vs.m

调用DVM_main.m

DVM_main.m

用于生成多普勒频谱(Doppler Spectrum)并进行速度映射。

  1. 通过调用 get_doppler_spectrum 函数生成多普勒频谱,并存储在 doppler_spectrum 变量中。
  2. 对多普勒频谱进行速度映射处理,将多普勒频谱映射到速度空间。
  3. 对不同的频率段进行处理,将多普勒频谱映射到速度谱,并进行优化处理。
  4. 在循环中,对每个频率段进行优化处理,并将处理后的速度谱保存到文件中。
[doppler_spectrum, freq_bin] = get_doppler_spectrum([dpth_ges, spfx_ges],... rx_cnt, rx_acnt, 'stft');
                

spfx_ges 作为文件名参数,传递到DVM_main

38-53

for kk = 1:6
    figure;
    
    colormap(jet);
    % 使用 mesh 函数绘制三维图形,横轴为 1 到多普勒谱的第三维度大小,纵轴为 -60 到 60,数据为第 kk 个维度的多普勒谱挤压结果
    mesh(1:size(doppler_spectrum,3),-60:60,squeeze(doppler_spectrum(kk,:,:)));view([0,90]);
    xlim([0,size(doppler_spectrum,3)]);ylim([-60,60]);
    set(gcf,'WindowStyle','normal','Position', [300,300,400,250]); % window size
    set (gca,'color','none', 'fontsize', 12); % fontsize
    set(gca,'yTick',-60:20:60);
    xlabel('Time (ms)'); % x label
    ylabel('Frequency (Hz)'); % y label

    colorbar; %Use colorbar only if necessary
    caxis([min(doppler_spectrum(:)),max(doppler_spectrum(:))]);
end

这段代码主要实现了以下功能:

  1. 定义了一系列参数和常量,如每个文件中的段数(ges_per_file)、归一化参数(norm)、惩罚参数(lambda)、人体部位位置(torso_pos)、人体部位方向(torso_ori)、发射机位置(Tx_pos)、接收机位置(Rx_pos)、段长度(seg_length)、波长(wave_length)、速度范围的最大值(V_max)、速度范围的最小值(V_min)、速度分bin数(V_bins)、速度分bin的分辨率(V_resolution)、速度分bin数组(velocity_bin)、最大函数评估次数(MaxFunctionEvaluations)等。
  2. 根据频率分bin对多普勒谱进行循环移位,使得频率分bin中的最大值位于数组的开头。
  3. 对每一个 kk 值(从1到6)进行循环,绘制多普勒谱的三维图形。使用 mesh 函数绘制,横轴为多普勒谱的第三维度大小,纵轴为 -60 到 60,数据为第 kk 个维度的多普勒谱挤压结果。同时设置图形的窗口大小、字体大小、坐标轴刻度、标签等,并根据数据范围设置 colorbar。

55-61

% For Each Segment Do Mapping 对每个段进行映射
doppler_spectrum_max = max(max(max(doppler_spectrum,[],2),[],3));
U_bound = repmat(doppler_spectrum_max, M, M);
A = get_A_matrix(torso_pos(pos_sel,:), Tx_pos, Rx_pos, rx_cnt);
VDM = permute(get_velocity2doppler_mapping_matrix(A, wave_length,...
    velocity_bin, freq_bin, rx_cnt), [2,3,1,4]);    % 20*20*rx_cnt*121
% CastM = get_CastM_matrix(A, wave_length, velocity_bin, freq_bin);

这段代码的主要作用是对每个段进行速度映射处理,具体解释如下:

  1. 计算多普勒谱中的最大值,并将其用 repmat 函数复制为大小为 M*M 的矩阵 U_bound。
  2. 根据选择的位置(pos_sel)、发射机位置(Tx_pos)、接收机位置(Rx_pos)、接收机数量(rx_cnt),通过函数 get_A_matrix 计算得到矩阵 A。
  3. 使用函数 get_velocity2doppler_mapping_matrix 计算速度到多普勒映射矩阵 VDM,其中包含了波长、速度分bin数组、频率分bin数组以及接收机数量的信息。最终得到的 VDM 是一个 2020rx_cnt*121 的矩阵。

get_A_matrix:用于计算矩阵 A ,其中每一行代表了人体部位与发射机、接收机之间的关系。

get_CastM_matrix:用于生成用于非线性不等式约束的 Cast 矩阵 (未使用), 用于在非线性优化过程中约束速度谱的范围

get_velocity2doppler_mapping_matrix:用于生成速度到多普勒映射矩阵,返回速度到多普勒映射矩阵 VDM,其中每个元素代表了速度到多普勒的映射关系。

63-104

for ges_number = 1:ges_per_file
    seg_number = floor(size(doppler_spectrum, 3)/seg_length);
    doppler_spectrum_ges = doppler_spectrum;
    velocity_spectrum = zeros(M, M, seg_number);
    parfor ii = 1:seg_number
        % 设置 fmincon 输入
        doppler_spectrum_seg = doppler_spectrum_ges(:,:,...
            (ii - 1)*seg_length+1 : ii*seg_length);
        doppler_spectrum_seg_tgt = mean(doppler_spectrum_seg, 3);
        
        % 接收器之间的归一化(补偿路径损耗)
        for jj = 2:size(doppler_spectrum_seg_tgt,1)
            if any(doppler_spectrum_seg_tgt(jj,:))
                doppler_spectrum_seg_tgt(jj,:) = doppler_spectrum_seg_tgt(jj,:)...
                    * sum(doppler_spectrum_seg_tgt(1,:))/sum(doppler_spectrum_seg_tgt(jj,:));
            end
        end

        % 应用 fmincon 求解器
        [P,fval,exitFlag,output] = fmincon(...
            @(P)DVM_target_func(P, VDM, lambda, doppler_spectrum_seg_tgt, size(doppler_spectrum_seg_tgt,1), norm),...
            zeros(M,M),...  % 初始值
            [],[],...       % 线性不等式约束
            [],[],...       % 线性等式约束
            zeros(M,M),...  % 下界
            U_bound,...     % 上界
            [],... % @(P)DVM_nonlinear_func(P, CastM),...    % 非线性约束
            optimoptions('fmincon','Algorithm','sqp',...
            'MaxFunctionEvaluations', MaxFunctionEvaluations));	% 选项
        velocity_spectrum(:,:,ii) = P;
        exitFlag
    end
    
    % 根据方向旋转速度谱
    velocity_spectrum_ro = get_rotated_spectrum(velocity_spectrum, torso_ori(ori_sel));
    
    % 保存速度谱
    save([dpth_vs, dpth_people, '-', spfx_ges, '-', num2str(ges_number),...
        '-', num2str(lambda), '-', num2str(seg_length),...
        '-', num2str(V_bins), '-', num2str(MaxFunctionEvaluations),...
        '-L', num2str(norm), '.mat'], 'velocity_spectrum_ro');
end

这段代码实现了对多普勒谱进行处理和速度映射的过程,具体步骤如下:

  1. 对输入的多普勒谱进行处理,计算频率分bin和生成多普勒谱。
  2. 设置一系列参数和常量,如段长度、波长、速度范围、分辨率等。
  3. 根据频率分bin对多普勒谱进行循环处理。
  4. 使用 mesh 函数绘制多普勒谱的三维图形。
  5. 对每个段进行速度映射处理,使用 fmincon 函数进行非线性规划求解速度谱。
  6. 根据方向旋转速度谱,并保存处理后的速度谱数据。
 [P,fval,exitFlag,output] = fmincon(...
            @(P)DVM_target_func(P, VDM, lambda, doppler_spectrum_seg_tgt, size(doppler_spectrum_seg_tgt,1), norm),...
            zeros(M,M),...  % 初始值
            [],[],...       % 线性不等式约束
            [],[],...       % 线性等式约束
            zeros(M,M),...  % 下界
            U_bound,...     % 上界
            [],... % @(P)DVM_nonlinear_func(P, CastM),...    % 非线性约束
            optimoptions('fmincon','Algorithm','sqp',...
            'MaxFunctionEvaluations', MaxFunctionEvaluations));

DVM_target_func: 这段代码的作用是通过 fmincon 函数对目标函数进行优化,得到最优的速度谱 P。

DVM_nonlinear_func: 用于计算非线性约束条件, 非线性不等式约束条件 fc 和非线性等式约束条件 fceq。在优化过程中,可以使用这些约束条件来限制优化变量 P 的取值范围

% 根据方向旋转速度谱
    velocity_spectrum_ro = get_rotated_spectrum(velocity_spectrum, torso_ori(ori_sel));

运行DVM_main.m到这句时,报错:需要安装Image Processing Toolbox

运行完毕,BVP储存

get_doppler_spectrum.m

function [doppler_spectrum, freq_bin] = get_doppler_spectrum(spfx_ges, rx_cnt, rx_acnt,... method)
	...
	[csi_data, ~] = csi_get_all([spfx_ges, '-r', num2str(1), '.dat']);
	doppler_spectrum = zeros(rx_cnt, 1 + freq_lpf_positive_max  +               							freq_lpf_negative_min,...floor(size(csi_data, 1)));
	...
end
  • csi_get_all 读取数据

  • csi_data 为dat文件中所有的csi数据

    • 在这里插入图片描述
  • 创建一个全零矩阵 doppler_spectrum

  • 设置参数和滤波器:定义采样率、滤波器参数等。

  • 处理多普勒频谱:循环处理每个天线的 CSI 数据,进行信号处理和分析。

  • 信号预处理:对 CSI 数据进行均值、方差计算,选择参考信号,进行振幅调整等操作。

  • 信号处理:对信号进行共轭乘积、滤波、主成分分析(PCA)等操作。

  • 时频分析:根据选择的方法(‘cwt’ 或 ‘stft’),进行连续小波变换或短时傅里叶变换。

  • 频率处理:选择关注的频率范围,对频谱进行归一化处理。

  • 频率分析:定义频率分布范围,并存储频率谱数据。

  • 返回结果:将处理后的频率谱数据存储在 doppler_spectrum 中,并返回频率分布范围 freq_bin

信号预处理、信号处理、时频分析是关键!

调整振幅

原理:这种振幅调整的原理是通过找到信号中的最小幅度 alpha,然后对信号进行缩放和平移,使得最小幅度变为零,同时乘以一个比例因子 beta。这种调整可以帮助信号更好地适应某些处理或分析的需求,例如在信号处理中去除噪声或增强信号特征。

共轭乘积

conj_mult = csi_data_adj .* conj(csi_data_ref_adj);
% 计算 csi_data_adj 和 csi_data_ref_adj 的共轭乘积
% .*:逐元素相乘
% conj():求共轭
% conj_mult:存储共轭乘积结果的矩阵

conj_mult = [conj_mult(:, 1:30*(idx - 1)), conj_mult(:, 30*idx+1:90)];
% 保留了与 idx 相关的列,删除了其他列
% [:, 1:30*(idx - 1)]:保留 idx 之前的列
% [:, 30*idx+1:90]:保留 idx 之后的列
% conj_mult:更新后的矩阵

主成分分析

PCA 是一种常用的数据降维技术,通过发现数据中的主要特征(主成分),可以减少数据的维度并保留数据中最重要的信息。在这段代码中,PCA 用于降维处理,以便在更低维度的空间中进行后续分析或处理。

pca_coef = pca(conj_mult);
% 使用 PCA 对 conj_mult 矩阵进行主成分分析
% pca() 函数会返回 PCA 的系数,表示数据在主成分方向上的投影

conj_mult_pca = conj_mult * pca_coef(:, 1);
% 将 conj_mult 矩阵乘以第一个主成分的系数,得到降维后的结果 conj_mult_pca
% 这样做相当于将数据投影到第一个主成分上,实现了降维处理

首先使用 PCA 对 conj_mult 矩阵进行主成分分析,得到了主成分分析的系数 pca_coef。然后,将原始数据矩阵 conj_mult 乘以第一个主成分的系数(pca_coef(:, 1)),得到了降维后的数据 conj_mult_pca

时频分析

if strcmp(method, 'cwt')
    % 如果选择的方法是连续小波变换(cwt)
    % 使用 scaled_cwt 函数进行连续小波变换
    % frq2scal() 用于生成小波尺度
    freq_time_prof_allfreq = scaled_cwt(conj_mult_pca, frq2scal([1:samp_rate/2 -1*samp_rate/2:-1], 'cmor4-1', 1/samp_rate), 'cmor4-1');
else
    if strcmp(method, 'stft')
        % 如果选择的方法是短时傅里叶变换(stft)
        % 设置时间实例和窗口大小
        time_instance = 1:length(conj_mult_pca);
        window_size = round(samp_rate/4+1);
        if(~mod(window_size,2))
            window_size = window_size + 1;
        end
        % 使用 tfrsp 函数进行短时傅里叶变换
        % tftb_window() 生成窗口函数
        freq_time_prof_allfreq = tfrsp(conj_mult_pca, time_instance, samp_rate, tftb_window(window_size, 'gauss'));
    end
end
  • 21
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隼尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值