【实践】多径效应CIR估计

2023-05-16

这周最紧要任务,写多径效应的CIR估计,故将思路历程收集于一个 blog 中,以供今后参考

文章目录

  • 1 题目解读
  • 2 信道估计初探
  • Reference

1 题目解读

首先这个任务题目就看不懂,啥叫 CIR估计?
问了学姐,是信道脉冲响应,突然联想到之前一直听说的信道估计,百度百科对于信道估计的解释是:

所谓信道估计,就是从接收数据中将假定的某个信道模型的模型参数估计出来的过程。如果信道是线性的话,那么信道估计就是对系统冲激响应进行估计。需强调的是信道估计是信道对输入信号影响的一种数学表示,而“好”的信道估计则是使得某种估计误差最小化的估计算法。


2021-9-2更新
什么是CIR估计?
在这里插入图片描述
CIR包括两个纬度
CIR就是每个延时点上信号的强度
两个纬度:(1)每路信号的延时时间;(2)每路信号的强度

之前老师让看的两篇文章与CIR估计有什么关系?
【文献精读】【通信】Symphony: Localizing Multiple Acoustic Sources with a Single Microphone Array
【文献笔记】【通信】MAVL: Multiresolution Analysis of Voice Localization

DoA/AoA 的估计就是按信号时延来算的,而且用的也是互相关的的方法,因此在算角度的过程中已经把CIR算出来了

如果是多径信道,令 rx 与 tx 信号作互相关,肯定会在多个延时处有不同信号(这里的延时指tx相对rx的延时,不同路径信号延时不同)

不仅如此,对于多径信道来说,作自相关也能算出CIR,比如之前看的同一个source 的 LOS 和 ECHO两个信道,令 tx 作自相关,就能得到 LOS 和 ECHO 之间的时延


那么也就是说,我的任务可以转述为,对有多径效应的信道作信道估计

这其中有两个问题需要搞清楚:
(1)有多径效应的信道该如何用代码表示?
(2)信道估计算法怎么写?

首先,在开始调研之前,我对信道的理解如下:

一个通信系统有编码、调制、信道传输、解调、解码这几个过程
把要传送的数据编码,为的是增加复杂度,减小出错率
调制,是为了能够将数据嵌入一个carrier中,从而能够实现传输
而通信模型中的信道发挥存在感的就是加入噪声干扰,使解调和解码出现错误

由我当前对通信系统以及信道的理解,可以对题目引出如下几点疑问:
(1)信道脉冲响应的意义是什么?
(2)多径效应的信道和其他效应的信道相比有什么区别?或者说,不同的信道在哪些方面会有差别?


问题(1)隔天再看已经可以解答
学信号与系统的时候就知道,在线性时不变系统中,所有输入对应的输出都可以看成是一堆脉冲响应的线性组合,所以只要知道了这个系统的冲激响应,那么任意给一个输入就能算出输出


第二个问题有点深,在探究这个问题之前,我觉得可以先实现一个普通的信道估计算法来感受一下


8-30更新
通过阅读两篇声源定位的论文,可以初步下一个定义,所谓信道估计,就是得到信道传递函数 H 的过程,这个H就是一个关于衰减与延迟的函数


2 信道估计初探


根据 2 中的描述,为什么要作信道估计?
是为了在接收端进行信道补偿,从而提高整个的系统性能。


《MIMO-OFDM无线通信技术及MATLAB实现》有专门的一章来讲信道估计
在这里插入图片描述
信道估计一般使用前导 preamble 或者导频 pilot

导频结构有三种:
(1)块状类型:适用于频率选择性信道
(2)梳状类型:适用于快衰弱信道
(3)格状类型

基于训练符号的信道估计

训练符号估计需要发送前导或者导频信号,会产生额外负荷降低传输效率。
使用训练符号时,一般采用 最小二乘(LS)或者 最小均方误差(MMSE)技术来进行信道估计

LS方法,每个子载波上的LS信道估计可以表示为
在这里插入图片描述
其中,Y为输出,X为输入

LS方法会增强噪声,但是因为简单而被广泛使用

接下来的一堆公式推导看不懂

根据与导师的交流,对于多径信道来说 LS 和 MMSE根本不够用,并推荐我看了如下两篇论文:
【文献精读】【通信】Symphony: Localizing Multiple Acoustic Sources with a Single Microphone Array

这两篇论文看完后还是懵逼,因为这两篇paper的主题是声源定位,所以只是简要介绍了多径信道的模型,并没有讲信道估计算法

这篇帖子详细贴了 OFDM系统的信道估计代码
OFDM中信道估计技术分析与实现

我亲手打了一遍这个帖子的代码,有一两个小bug,但是过程非常清晰,亲手 coding 之后感觉酣畅淋漓,我自己写的详细注释版如下:

close all;
clear;
clc;

% 单纯打印在命令行窗口
fprintf('OFDM信道估计仿真\n');

%% 参数设置 

carrier_count = 64;  % 单个OFDM符号中的载波数目
num_symbol = 50;     % OFDM符号数量,不包括导频
guard = 8;           % 循环前缀 CP, 即每个OFDM的最后8个子载波作为CP加在开头
pilot_inter = 8;     % 导频间隔,即每隔几个OFDM符号插入一个导频
modulation_mode = 16;% 调制方式, QAM调制的order
SNR = 0:2:20;        % 信噪比取值
num_loop = 15;       % 循环次数

% 每种信噪比做15次实验
num_bit_err = zeros(length(SNR), num_loop);
num_bit_err_dft = zeros(length(SNR), num_loop);
num_bit_err_ls = zeros(length(SNR), num_loop);
MSE = zeros(length(SNR), num_loop);
MSE_dft = zeros(length(SNR), num_loop);
MSE_ls = zeros(length(SNR), num_loop);

%% 主程序

for c1 = 1:length(SNR)
    fprintf('\n\n\n仿真信噪比为%f\n\n', SNR(c1));
    for num1 = 1:num_loop
        %---------------产生发送的随机序列-----------------------
        
        bits_len = carrier_count * num_symbol;
        bits_tx = randi([0 1], 1, bits_len); % 1行bits_len列矩阵
        
        %---------------符号调制-----------------------
        
        modulated_sequence = qammod(bits_tx, modulation_mode);
        
        %---------------导频格式-----------------------
        
        pilot_len = carrier_count; % 导频与OFDM符号同级别
        % rand 默认区间(01% round 四舍五入
        % 结束后 pilot_symbols只有01,是一个1行pilot_len列矩阵
        pilot_symbols = round(rand(1, pilot_len));
        
        % 将导频信号中的0变为-1,所以目前导频有两种,-11
        for i = 1:pilot_len
            if pilot_symbols(1, i) == 0
                pilot_symbols(1, i) = pilot_symbols(1, i) - 1;
            else
                pilot_symbols(1, i) = pilot_symbols(1, i);
            end
        end
         
        % 行向量变列向量
        pilot_symbols = pilot_symbols';
        
        %---------------计算导频和数据数目-----------------------
        
        % ceil 向上取整
        num_pilot = ceil(num_symbol / pilot_inter);
        % rem 取余,返回 num_symbol除以pilot_inter后的余数 
        % 每组符号开头一个导频,结尾还要再加一个导频
        if rem(num_symbol, pilot_inter)==0
            num_pilot = num_pilot + 1;
        end
        
        num_data = num_symbol + num_pilot;
        
        %---------------导频位置计算-----------------------
        
        pilot_index = zeros(1, num_pilot);
        % +1 是算上了导频的位置,此时data_index容量大于 num_symbol
        data_index = zeros(1, num_pilot * (pilot_inter + 1));
        for i = 1:num_pilot-1
            pilot_index(1, i) = (i-1) * (pilot_inter + 1) + 1;
        end
        % 最后一个导频的位置从开头数起要看具体情况
        % 但反正是在最后一个
        pilot_index(1, num_pilot) = num_data;
        
        % 为了插入导频,第一个、最后一个以及每隔8个位的索引都空了出来
        % 缺少的索引值在 pilot_index
        for j = 0:num_pilot
            data_index(1, (1 + j * pilot_inter) : (j + 1) * pilot_inter) = (2 + j * (pilot_inter + 1)) : ((j + 1) * (pilot_inter + 1));
        end
        
        % 将多余的容量去掉
        data_index = data_index(1, 1:num_symbol);
        
        %---------------导频插入-----------------------
        
        % 和之前不一样,每一列为一个OFDM调制符号
        piloted_ofdm_syms = zeros(carrier_count, num_data);
       
        % piloted_ofdm_syms 与 modulated_sequence的列数不一样
        % piloted_ofdm_syms 的列数增加了 导频数
        % 而modulated_sequence的列数只有 OFDM符号数
        
        % 先将 modulated_sequence 中应该是 OFDM符号 的列数依次插入 modulated_sequence 的列
        % data_index 和 modulated_sequence 的列数都是 num_symbol
        piloted_ofdm_syms(:, data_index) = reshape(modulated_sequence, carrier_count, num_symbol);
        % 再将 pilot 插入其索引位
        % pilot_symbols 只是一个列向量,横向扩充 num_pilot 倍成为一个数组
        piloted_ofdm_syms(:, pilot_index) = repmat(pilot_symbols, 1, num_pilot);
        
        %---------------IFFT变换-----------------------
        
        % OFDM调制后默认是频域信号
        % 为什么要乘以 sqrt(carrier_count)
        time_signal = sqrt(carrier_count) * ifft(piloted_ofdm_syms);
        
        %---------------加循环前缀-----------------------
        
        % CP 与子载波同级别
        add_cyclic_signal = [time_signal((carrier_count - guard + 1 : carrier_count), :); time_signal];
        % 将矩阵变为一个行向量再传输
        tx_data_trans = reshape(add_cyclic_signal, 1, (carrier_count + guard) * num_data);
        
        %---------------信道处理-----------------------
        
        % AWGN 信道
        
        % 计算信号功率
        tx_signal_power = sum(abs(tx_data_trans(:)) .^ 2) / length(tx_data_trans(:));
        % 为啥这么算?
        noise_var = tx_signal_power / (10 ^ (SNR(c1) / 10));
        rx_data = awgn(tx_data_trans, SNR(c1), 'measured');
        
        %---------------信号接收、去循环前缀、FFT变换-----------------------
        
        % 信号接收
        rx_signal = reshape(rx_data, (carrier_count + guard), num_data);
        % 去除CP
        rx_signal_matrix = zeros(carrier_count, num_data);
        rx_signal_matrix = rx_signal(guard + 1:end, :);
        % FFT变换
        % 因为接下来要提取导频,导频自然得回到频域才能提取
        rx_carriers = fft(rx_signal_matrix) / sqrt(carrier_count);
        
        %---------------导频和数据提取-----------------------
        
        % 提取导频
        rx_pilot = rx_carriers(:, pilot_index);
        % 提取数据(频域)
        rx_fre_data = rx_carriers(:, data_index);
        
        %---------------导频位置信道响应LS估计-----------------------
        
        % pilot_patt 就是发送端插入的 pilot
        pilot_patt = repmat(pilot_symbols, 1, num_pilot);
        % LS算法的 y/x
        pilot_esti = rx_pilot ./ pilot_patt;
        
        %---------------LS估计的线性插值-----------------------
        
        % 使用信道估计,其实就已经默认了rx的data是不可信的
        % 所以需要使用导频来恢复 data
        
        int_len = pilot_index;
        len = 1:num_data;
        channel_H_ls = zeros(carrier_count, num_data);
        
        % 每个符号/导频的子载波数量是固定的
        % 现在是要通过 num_pilot 个 导频来估算 num_data 个导频+data
        % 因此子载波一个一个来
        for ii = 1:carrier_count
            % 在 int_len(pilot_index)这些点(点的数量为 num_pilot)
            % 函数取值分别为 pilot_esti(ii, 1:(num_pilot))
            % 那么同样的函数,将点扩充为 len(num_data)个,各点的估计值是多少?
            channel_H_ls(ii, :) = interp1(int_len, pilot_esti(ii, 1:(num_pilot)), len, 'linear');
        end
        
        channel_H_data_ls = channel_H_ls(:, data_index);
        
        %---------------LS估计中发送数据的估计值-----------------------
        
        % 这个公式从何而来还不懂
        tx_data_estimate_ls = rx_fre_data .* conj(channel_H_data_ls) ./ (abs(channel_H_data_ls) .^ 2);
        
        %---------------DFT估计------------
        
        % DFT估计是为了再ls基础上消除时域噪声
        % 但是以下代码没看懂为什么能达到消除时域噪声的效果
        % 或许是在时域作超过子载波长度点数的FFT能够消除噪声?
        
        % 先将 pilot_esti 换为时域
        % 补充子载波padding后(symbol纬度不变)
        % 再换回频域
        % 加padding 其实就是做了 carrier_count+1024 点 FFT 变换
        tx_pilot_estimate_ifft = ifft(pilot_esti);
        padding_zero = zeros(1024, num_pilot);
        tx_pilot_estimate_ifft_padding_zero = [tx_pilot_estimate_ifft; padding_zero];
        % 对于矩阵来说,fft分别对各列作fft
        tx_pilot_estimate_dft = fft(tx_pilot_estimate_ifft_padding_zero);
        
        %---------------DFT估计的线性插值------------
        
        % 插值操作与 ls 一样
        
        int_len = pilot_index;
        len = 1:num_data;
        channel_H_dft = zeros(carrier_count, num_data);

        for ii = 1:carrier_count
            channel_H_dft(ii, :) = interp1(int_len, tx_pilot_estimate_dft(ii, 1:(num_pilot)), len, 'linear');
        end
        
        channel_H_data_dft = channel_H_dft(:, data_index);
        
        %---------------DFT估计中发送数据的估计值------------
        
        tx_data_estimate_dft = rx_fre_data .* conj(channel_H_data_dft) ./ (abs(channel_H_data_dft) .^ 2);
        
        %---------------DFT符号解调------------
        
        % 原矩阵每一列向量变为行向量
        % 并且按顺序铺成 sequence
        demod_in_dft = tx_data_estimate_dft(:).';
        demod_out_dft = qamdemod(demod_in_dft, modulation_mode);
        
        %---------------LS符号解调------------
        
        demod_in_ls = tx_data_estimate_ls(:).';
        demod_out_ls = qamdemod(demod_in_ls, modulation_mode);
        
        %---------------误码率计算------------
        
        for i = 1:length(bits_tx)
            if demod_out_dft(i) ~= bits_tx(i)
                num_bit_err_dft(c1, num1) = num_bit_err_dft(c1, num1) + 1;
            end
            if demod_out_ls(i) ~= bits_tx(i)
                 num_bit_err_ls(c1, num1) = num_bit_err_ls(c1, num1) + 1;
        
            end
        end
    end
end

% num_bit_err_dft.'表示原来的行变列
% 原先是每行代表一个 SNR 的所有 loop 结果
% 现在变成每列
% 与num_bit_err_dft(:).'展开不同,num_bit_err_dft.'仍是矩阵
% 因为 mean 是按列来算平均值的
BER_dft = mean(num_bit_err_dft.') / length(bits_tx);
BER_ls = mean(num_bit_err_ls.') / length(bits_tx);

%% 绘图
figure
semilogy(SNR, BER_dft, '-mp', SNR, BER_ls, '-k+');
title('OFDM系统的LS和DFT信道估计');
xlabel('SNR');
ylabel('BER');
legend('DFT信道估计','LS信道估计');

通过这次coding 主要明白了以下的几个重要知识点:
(1)pilot, CP 的真面目
导频 pilot 与 符号 symbol 同级别 ,每隔几个 symbol 插入一个 pilot


更新,pilot也可以与子载波同级别,导频有很多种插入法


循环前缀 CP 与 子载波 同级别,每个symbol的最后n个子载波复制了然后插入到开头作为CP
比如一个 symbol [1, 2, 3, 4, 5], 假设 CP 为2,那么加入CP后变为 [4, 5, 1, 2, 3, 4, 5]

(2)明白了pilot的真正用途
使用信道估计,其实就已经默认了rx的data是不可信的,所以需要使用不易被干扰的导频来获取信道对信号的影响,即得到H,然后再通过 rx与 H 的运算来获得可信 data

(3)DFT估计,就是在LS基础上将导频ifft换回时域然后再作N点fft换回频域(N大于载波数量)

并且,通过此次coding 明确了我搞不懂的问题到底在哪里


要做XXX信道估计,要解决两个问题
(1)建立这个信道的模型
加多少噪音、衰弱、延时?以什么方式加?
(2)选择合适的估计算法
如果 y = hx + n,那就 ls, mmse, dft

卡壳点:
(1)微信论文中有给出多径信道模型,代码如何实现?
看起来还是 y = hx + n的形式,为什么 ls 不行了?
(2)不知道该上哪找合适的估计算法


Reference

[1] 移动无线信道脉冲响应的计算机模拟

[2] Matlab关于信道估计的一个描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【实践】多径效应CIR估计 的相关文章

  • UCOS-III

    一 UCOSIII 简介 UCOSIII 是一个可裁剪 可固化 可剥夺 的多任务系统 xff0c 没有任务数目的限制 xff0c 是 UCOS 的第三代内核 xff0c UCOSIII 有以下几个重要的特性 xff1a 可剥夺多任务管理 x
  • 【Python】词频统计(written in python and Mapreduce)

    一 利用Python进行词频统计 xff08 一 xff09 计算机等级考试中常用的方法 首先是一个比较标准的考试中使用的方法 xff0c 针对英文文本 xff1a span class token keyword def span spa
  • 数据处理技巧(5):MATLAB 读取txt中的数据

    全是数字的类型 txt 的数据是有数字的 xff0c 如下图 xff1a 读取结点坐标 xff0c 保存在 NodeCoor 数组当中 xff0c 共1331行3列 filename span class token operator 61
  • 基于51单片机的模拟自动感应门 系统protues仿真

    硬件设计 xff08 末尾附文件 xff09 代码设计 include lt reg51 h gt 调用头文件 define uchar unsigned char 宏定义 define uint unsigned int 宏定义 端口定义
  • linux测试程序

    stresslinux super pi prime mprime nbench cpuburn gamut mersenne prime stress cpu burn in memtester memtest86 memtest86 4
  • mysql 删除多余0的问题

    0 43 CAST 字段 AS CHAR 别名 可加可不加
  • 三维点沿指定向量方向到平面的距离计算方法及C++代码实现

    设平面外一点为P p1 p2 p3 xff0c 指定的方向向量为d 61 d1 d2 d3 xff0c 平面Q方程为Ax 43 By 43 Cz 61 D xff0c 设系数ABC已经归一化 xff0c 则其法向量为n 61 A B C 则
  • ubuntu使用proxychains给终端设置代理

    有时 xff0c 我们需要下载一些国外网站上的东西 xff0c 如果用国内网络直接下载的话 xff0c 往往是连接不上的 或者有时下载一个东西速度很慢 xff0c 这都是因为国内网络限制的问题 xff0c 大大影响了我们的工作效率 解决方法
  • int为什么占4个字节?一个字节为什么是8位?

    不知道大家有没有思考过这样的问题 xff0c 一个字节为什么是8位呀 xff0c 也许还有小伙伴不知道我说的这些是什么 xff0c 没关系往下看 第一个解释 xff08 历史 xff09 是IBM为System 360设计了一套8位EBCD
  • K8S之kubectl命令详解及示例

    目录 1 查看类命令 2 操作类命令 3 进阶命令操作 4 kubectl replace 重启pod的四种方法 5 kubectl语法 1 查看类命令 获取节点和服务版本信息 kubectl get nodes 获取节点和服务版本信息 x
  • ROS运动规划学习五---global_planner

    文章目录 前言一 global planner功能包结构二 planner core1 执行过程2 calculatePotentials 3 getPlanFromPotential 总结 前言 本节将学习ROS中的全局规划期global
  • ROS自定义消息---发布数组和整型数据

    ROS自定义消息 数组和整型数据 前言一 ROS中的消息数据格式二 自定义话题消息1 新建msg文件2 编写发布者和接收者程序 总结 前言 ROS自带的消息格式已经包含一维数组 xff0c 有时候我们需要定义多维数组 xff0c 以及混合数
  • Markdown中的公式、字母表示汇总

    Markdown中的公式 字母表示汇总 1 常用希腊字母表2 数学公式 最近几个月打了很多Markdown公式 xff0c 隔一段时间就会忘一些表示方式 xff0c 还不如在这里慢慢汇总记录 xff0c 以后要用的时候来查就行了 xff01
  • CMake项目中神器:CMakeLists.txt

    首次接触 CMake xff0c 见识了 CMakeLists txt 的强大后 xff0c 赶紧整理出来分享一下 参考资料 xff1a Cmake 3 6 W3Cschool参考手册 本文讲述了一个 CMake 项目 xff0c 在从单文
  • TCP详解之拥塞控制

    概述 TCP模块还有一个重要任务 xff0c 就是提高网络利用率 xff0c 降低丢包率 xff0c 并保证网络资源对每条数据流的公平性 xff0c 这就是所谓的拥塞控制 拥塞控制的四个部分 xff1a 慢启动 拥塞避免 快速重传 快速恢复
  • frps搭建自己的内网穿透服务器

    frps搭建自己的内网穿透服务器 开发过程中 xff0c 很多时候我们需要用到内网穿透 xff0c 将自己的服务器映射到外网 xff0c 下面说一下怎么用frps搭建自己的内网穿透服务器 frps Github地址 里面有中文文档 xff0
  • 更换backbone心得

    1 对于目标检测 xff0c backbone相当于连接中间环节 xff0c 连接着图片输入和后面的检测头 xff0c 所以在更换网络时候只要注意输入backbone的数据形式以及后面一个环节要求输入的形式 xff0c 把backbone的
  • from torch._C import *ImportError: DLL load failed while importing _C: 找不到指定的模块。

    更新torch的版本 xff0c 原先是1 4 0出现这个问题 xff0c 更新到1 11 0后解决 pip install torch 61 61 1 11 0 43 cpu torchvision 61 61 0 12 0 43 cpu
  • 模型衡量标准recall precision accuracy f1score(hmean)

    问题背景 xff1a 在处理分类问题时 xff0c 会遇到一种情况 xff1a 假设一个二元分类问题 xff1a 假设我们的预测算法是 xff1a xff0c 这个算法忽略特征值 xff0c 不管任何情况下都是预测等于0 毫无疑问这是一个糟
  • layoutlmV3使用步骤

    1 layoutlm系列的预训练权重全都是放在huggingface上面 xff0c 安装官方教程如果下载失败 xff0c 可以在linux系统下载 xff0c 然后将下载的缓存文件保存 或者在官网上下载并保存 需要下载的文件如下图 2 将

随机推荐