WIFI信号状态信息 CSI 数据处理篇之插值(四)

本篇是数据处理篇的最后一个补充环节,这个环节不是必须的步骤,视情况作补充。需要插值的原因参考鲁勇的《基于WiFi信号的人体行为感知技术研究综述》:

本人在做实验的时候也确实遇到了这个问题,特别是在采样频率设置的高的时候,信号传输很容易碰到堵塞缺漏的情况,这一点可以观察在数据包的timestamp_low,代码具体细节参考上篇教程:
WIFI信号状态信息 CSI 数据处理篇之读取数据与数据解析(二)_csi相位解卷绕-CSDN博客

csi_trace里面是实验收到的所有数据包,维度是N*1,也就是意味着这条数据存储了N个数据包。csi_trace{1}和csi_trace{N}的timestamp_low这一项则是系统赋予数据包的时间戳,这个时间戳的数值虽然不是现实世界的时间,但它是相对准确的。举例,假如采样频率是1000Hz,根据之前教程所讲的,两个相邻数据包时间的时间戳间隔应该是1000(左右),那么csi_trace{1}和csi_trace{N}之间的则timestamp_low应该相差1000*1000=10^6,但是如果相差太多,就可以判断发生了数据包的错漏,如果这个错漏如果严重,是会影响系统与现实的时间对照严谨性的。

例如,下面是本人一条数据的首位数据包信息,row=65333,理论啥csi_trace{row}.timestamp_low - csi_trace{1}.timestamp_low=65332*10^3
但是实际情况是时间戳相差68303.148*10^3,相当于差了3s的数据,需要补近3000个点的数据。

       

当数据包丢失比较严重的时候,就要对其进行补充,缺多少补多少。补什么也不能乱补,可以和前/后一个数据包的值一样,也可以用线性插值等插值算法,这里我们采用较为简单的线性插值。

插值是一个很耗时间的步骤,一种方案是从头到尾过一遍所有数据包的时间戳,把需要插值的地方记下来,然后再插值。这里为了节约时间,就边读值边插值,插值的逻辑也比较简单粗暴,直接四舍五入,如果当前时间戳与上一个时间戳差距大于1500(理论上应该是1000),就补数据。代码如下:

close all
clear
clc

%% 读取原始数据
str = 'XXX.dat'; % 输入文件名字
csi_trace = read_bf_file(str);
row = size(csi_trace,1);
result_matrix = zeros(row,181,'single'); % 使用 single 类型存储数据,减小内存占用

% 读取原始数据并同时检测和补足数据包漏失
prev_timestamp = 0;
new_row_index = 0; % 定义新数据包的索引变量
for i = 1:row
    % 读取第i条数据
    csi_entry = csi_trace{i}; % 结构体形式

    % 读取并存储第i条数据的时间戳
    current_timestamp = csi_trace{i}.timestamp_low;
    result_matrix(i, 181) = current_timestamp;

    % 检测时间戳间隔
    if i > 1 % 添加这个条件来避免第一次循环时的错误
        timestamp_interval = current_timestamp - prev_timestamp;

        % 计算需要补足的数据包数量
        num_missing_packets = round(timestamp_interval / 1000) - 1;

        % 使用矩阵运算进行线性插值
        if num_missing_packets > 0
            prev_amplitude = result_matrix(i-1, 1:90);
            prev_phase = result_matrix(i-1, 91:180);
            current_amplitude = result_matrix(i, 1:90);
            current_phase = result_matrix(i, 91:180);

            % 计算振幅和相位的差值
            amplitude_diff = current_amplitude - prev_amplitude;
            phase_diff = current_phase - prev_phase;

            % 计算插值的倍数
            interpolation_factors = (1:num_missing_packets) / (num_missing_packets + 1);

            % 广播插值的倍数,并计算插值后的振幅和相位
            interpolated_amplitude = prev_amplitude + amplitude_diff .* interpolation_factors';
            interpolated_phase = prev_phase + phase_diff .* interpolation_factors';

            % 插入补足的数据包
            new_row_index_range = new_row_index + (1:num_missing_packets);
            result_matrix(new_row_index_range, 1:90) = interpolated_amplitude;
            result_matrix(new_row_index_range, 91:180) = interpolated_phase;
            result_matrix(new_row_index_range, 181) = prev_timestamp + (1:num_missing_packets) * 1000; % 更新时间戳

            % 更新新数据包的索引
            new_row_index = new_row_index + num_missing_packets;
        end
    end

    % 更新前一个时间戳
    prev_timestamp = current_timestamp;

    % 读取第i条数据的CSI值
    csi = get_scaled_csi(csi_entry); % 复数矩阵,1*3*30
    csi1 = squeeze(csi); % 去掉全为1的数组以降维,复数矩阵,3*30

    % 提取当前时刻的信号数据包
    current_packet = csi1; % 复数矩阵,3*30

    % 计算振幅信息
    amplitude = abs(current_packet);

    % 计算相位信息
    phase = angle(current_packet);

    % 将振幅和相位信息存储到result_matrix中
    result_matrix(i, 1:90) = reshape(amplitude, 1, []);
    result_matrix(i, 91:180) = reshape(phase, 1, []);

    % 更新新数据包的索引
    new_row_index = new_row_index + 1;
end

运行完还是得到的result_matrix矩阵,相比之前读取数据的代码,就是多加了插值的操作。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值