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)并进行速度映射。
- 通过调用
get_doppler_spectrum
函数生成多普勒频谱,并存储在doppler_spectrum
变量中。 - 对多普勒频谱进行速度映射处理,将多普勒频谱映射到速度空间。
- 对不同的频率段进行处理,将多普勒频谱映射到速度谱,并进行优化处理。
- 在循环中,对每个频率段进行优化处理,并将处理后的速度谱保存到文件中。
[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
这段代码主要实现了以下功能:
- 定义了一系列参数和常量,如每个文件中的段数(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)等。
- 根据频率分bin对多普勒谱进行循环移位,使得频率分bin中的最大值位于数组的开头。
- 对每一个 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);
这段代码的主要作用是对每个段进行速度映射处理,具体解释如下:
- 计算多普勒谱中的最大值,并将其用 repmat 函数复制为大小为 M*M 的矩阵 U_bound。
- 根据选择的位置(pos_sel)、发射机位置(Tx_pos)、接收机位置(Rx_pos)、接收机数量(rx_cnt),通过函数 get_A_matrix 计算得到矩阵 A。
- 使用函数 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
这段代码实现了对多普勒谱进行处理和速度映射的过程,具体步骤如下:
- 对输入的多普勒谱进行处理,计算频率分bin和生成多普勒谱。
- 设置一系列参数和常量,如段长度、波长、速度范围、分辨率等。
- 根据频率分bin对多普勒谱进行循环处理。
- 使用 mesh 函数绘制多普勒谱的三维图形。
- 对每个段进行速度映射处理,使用 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));
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