将gnuradio源码中的模块添加制作成自己的OOT模块

2024-01-20 23:50

本文主要是介绍将gnuradio源码中的模块添加制作成自己的OOT模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

将gnuradio源码中的模块添加制作成自己的OOT模块(安装了release版本无法进入源码中编译,但是又不想卸载后安装源码版本)

    • 1、写这篇文章的原因
    • 2、Gnuradio流图和相关参数如下:
    • 3、Bug复现
    • 4、通过OOT定义外部用户模块来实现修改源码的曲线救国方案
      • i. 命令行输入命令查看Gnuradio版本
      • ii. guihub上下载Gnuradio源码文件,并且指定为与自己版本相同
      • iii. 创建OOT模块
      • iv. 根据源文件对创建OOT文件进行修改
        • 1、cc文件的修改
        • 2、impl.h文件的修改
        • 3、h文件的修改
        • 4、yml文件的修改
      • v. 编译安装测试
        • 1、编译整体过程
        • 2、编译安装
      • vi. 修改内部函数并测试结果
    • 5、总结:
    • 6、参考资料:

1、写这篇文章的原因

  1. 笔者也是刚刚从2023年暑假接触Gnuradio和SDR,其根本原因是在对比FPGA和Gnuradio之后,想要实现通信原理中的调制解调,并且想通过电磁波发送出去,验证理论与实际。同时想与深度学习结合,验证传统算法和DL的高下。Gnuradio感觉集成度更高一点,软件定义无线电,通过写代码模拟嵌入式系统。当然更大一部分的原因是其宜人的价格。

  2. 奈何资料是真的少,大部分的时间都在寻找资料的路上。不过遇到的良师亦有不少,但是由于个人设备的原因,产生了如下的问题:

    a. 环境已经安装好,gnudaio是直接sudo apt install gnuradio的,也就是release版本,无法找到源码的文件,并且也已经安装好全部的硬件的依赖环境,一切都能正常运行,在不想重新配置环境(配不通)的情况下,想要更改源码内容实现功能的改进。

    b. 在bilibili上跟着 张老师学习SDR,在学习到OFDM图传的那一课时,张老师在里面说到了一个Gnuradio中的 Header/Payload Demux 模块的底层bug问题。(超过10帧的数据会出现丢帧的现象,所以在发送图片的时候基本是理想的信道,也会出现问题)
    1、 西电研究生探究问题所在,并且解决问题(点击跳转)
    2、张老师的这个视频从1:17:28开始讲OFDM图传,并且介绍bug,视频前面也有OOT模块的创建的教程(点击跳转)

2、Gnuradio流图和相关参数如下:

理想的图传流图,OFDM图传报告,详细描述每个块的作用和参数,想学习可以参考一下(点击跳转);
整体的流图如下图:
这是接收端的
这是发送端

3、Bug复现

就上面流图而言,是理想的信道,只有一点点的噪声,根据算法应该可以恢复得很漂亮才对,但是在传输图片的时候却出现了如下的不合理的情况:
发送端
接收端
理想信道下居然有如此严重的失真,显然是不合理的,是模块内部算法有问题。具体原因就是前面链接中文章的介绍。解决方法如果是源码安装的Gnuradio根据前面视频中张老师的方法就可以解决。
下面是介绍没有源码安装又想解决这个问题的情况。
其根本的原因是:Header/Payload Demux 模块的底层bug问题

4、通过OOT定义外部用户模块来实现修改源码的曲线救国方案

  1. 先学习如何OOT:自己定义OOT模块(点击跳转学习)
  2. 学习如何创建OOT后,我们并不需要编写源码,因为源码的文件我们是可以通过网上找到的,这里我用我自己认为是正确方法进行源码的查找:

i. 命令行输入命令查看Gnuradio版本

gnuradio-config-info -v

在这里插入图片描述

ii. guihub上下载Gnuradio源码文件,并且指定为与自己版本相同

(个人感觉直接用源码可能也可以,有道友尝试过可以回复我一下)

git clone https://github.com/gnuradio/gnuradio.git
cd gnuradio
git checkout maint-3.8

通过这两步之后,我们就得到了源码,而我们的Header/Payload Demux中的cch文件地址就在:

gnuradio/gr-digital/lib			#下的cc和h文件
gnuradio/grc						#下的ymal文件
gnuradio/include/gnuradio/digital      #x下的h文件

搜索到找到这四个文件复制保存备用
在这里插入图片描述

iii. 创建OOT模块

根据教程在命令行输入:

在这里插入图片描述
创建了Myoot的文件夹,并且添加了自己的模块名为:my_heade,使用的是cpp语言,不需要验证(这里看个人情况而定)
经过上面的操作之后,文件路径下会有一个gr-Myoot的文件,并且里面的内容如下:

在这里插入图片描述
在lib文件下就是我们要修改的cc和h文件,在grc文件夹就是我们需要修改的yml文件,在include/Myoot是其头文件,这四个都是需要修改的文件。

iv. 根据源文件对创建OOT文件进行修改

1、cc文件的修改

查看cc文件,OOT模块和源文件的区别可以看到,头文件文件名是不一样的,为了修改文件的正确,选择最笨的方法进行修改,方法如下:(左边是自定义的cc文件,右边是源码文件)
在这里插入图片描述
修改后的如图
在这里插入图片描述
并且看到我们要找的函数正好对齐了在最下方。
这时我们继续根据源文件的内容,往创建的OOT文件中填入参数。比如make()中填入参数后如图所示:
在这里插入图片描述
同样填入参数和根据源文件修改函数内容后如图:
修改参数和函数
往后看到这两个函数

    my_heade_impl::~my_heade_impl(){}void my_heade_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required){/* <+forecast+> e.g. ninput_items_required[0] = noutput_items */}

my_heade_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
中用同样的方法修改后如图:

在这里插入图片描述
然后是函数在函数int my_heade_impl::general_work前后有自定义的函数,在如之前那样完成my_heade_impl::general_work函数的修改后,再进行自定义函数的修改。my_heade_impl::general_work函数是这个blk的启动函数,相当于是main()函数,很长内容很多,所以不贴图了。
注意一些自定义函数贴过来的时候要注意名字,要改成与自己文件名相同的名字。
general_work前有一个check_buffers_ready函数,修改名字后到我们的文件后如图:

在这里插入图片描述
将general_work函数同样的方法修改后,我们的文件后面就没有函数了,但是源文件上还有很多,这些都是一些自定义的函数,通过观察,发现都是header_payload_demux_impl类的函数,我们直接复制过来然后使用ctrl+f快捷键一键修改成我们设置的类my_heade_impl函数的名字即可:
替换后续函数
至此保存,cc文件修改完成。

2、impl.h文件的修改

注意有两个h文件,有impl的是和cc文件同一个文件夹的
同样的方式我们源文件和我们创建的h文件,同样修改文件,观察后发现需要修改的地方如下:
在这里插入图片描述
根据源文件填入后:
在这里插入图片描述

3、h文件的修改

通过观察,只有static sptr函数需要在static sptr make();填入参数即可:

      static sptr make(const int header_len,const int items_per_symbol = 1,const int guard_interval = 0,const std::string &length_tag_key = "frame_len",const std::string &trigger_tag_key = "",const bool output_symbols = false,const size_t itemsize = sizeof(gr_complex),const std::string &timing_tag_key = "",const double samp_rate = 1.0,const std::vector<std::string> &special_tags = std::vector<std::string>(),const size_t header_padding = 0);};
4、yml文件的修改

通过观察这两个文件,找到这个同样的东西:
在这里插入图片描述
将源码中parameter的东西,除了头,都复制过来,然后再修改上面图片中make: Myoot.my_heade()中的参数,都贴过来,然后删除多余的东西,file_format:1就是代码的最后一行了,后面我们需要继续修改里面的一些参数。
在这里插入图片描述
到这一步,需要修改cpp_templates的一些参数,网上找不到相关的资料,这里笔者也是瞎猫乱来的,在这里希望有高手兄可以指点一下我。先后找了很多资料,后来实在不知道如何,问了问AI:

这看起来是一个YAMLYAML Ain't Markup Language)配置文件的一部分,
用于定义和配置一个名为 `cpp_templates` 的组件,可能用于某种软件工程项目。
让我为您解释其中的各个部分:1. `cpp_templates`(组件名称): 
这是配置文件中的一个部分或部件,用于定义一些属性和操作。2. `includes`(包含语句): 这是一个包含了一个或多个C++头文件的列表。
在这种情况下,它包括了 `<gnuradio/digital/header_payload_demux.h>` 头文件,
表示在编译时需要包含这个头文件以使用其中的功能。3. `declarations`(声明): 这是一个C++代码片段,用于声明一个变量。
在这里,它声明了一个名为 `${id}` 的变量,其类型是 `digital::header_payload_demux::sptr``${id}` 看起来像是一个占位符,可能在稍后的配置文件中有具体的值。4. `make`(初始化): 这是一个C++代码块,用于初始化先前声明的变量 `${id}`。
它使用了一些参数,如 `${header_len}``${items_per_symbol}` 等等,这些参数可能也是占位符,
其具体值可能在其他地方定义或提供。5. `link`(链接库): 这是一个列表,指定了与该组件相关联的库。在这里,
它包括了 `'gnuradio-digital'`,
表示需要链接到 `gnuradio-digital` 这个库。6. `translations`(翻译): 这是一个键-值对的映射,用于定义将布尔值 `'True'``'False'` 
转化为相应的C++ 布尔值 `'true'``'false'`。这可能是因为不同的编程语言或库使用不同的布尔表示方式。这个配置片段的具体用途可能需要结合更多的上下文来理解。
通常情况下,这种配置文件用于配置和生成代码或定义特定的组件,以便在软件工程项目中使用。

最终修改成一下的样子

cpp_templates:includes: ['#include <gr-Myoot/my_heade.h']declarations: 'gr::Myoot::my_heade::sptr ${id};'make: |-this->${id} = gr::Myoot::my_heade::make(${header_len},${items_per_symbol},${guard_interval},${length_tag_key},${trigger_tag_key},${output_symbols},${type.cpp_itemsize},${timing_tag_key},${samp_rate},${special_tags},${header_padding});link: ['gnuradio-Myoot']translations:'True': 'true''False': 'false'

这个我也尝试了其它的名字,感觉都可以,不知道什么原因。保存,至此我们完成全部文件的修改,将修改好的文件替换没有修改的文件,接着我们开始在命令行编译。

v. 编译安装测试

1、编译整体过程

打开命令行,进入我们前面生成的文件夹中,我们这里是==(gr-Myoot文件夹)==
因为笔者已经安装过了,我再此修改一下yml中的文件的第二个参数,这个参数是模块的名字,我将其更改为:my_head/半盏生
主要步骤如下,前面的链接中的教程,也有详细的过程:

cd gr-Myoot
mkdir build
cd build
cmake ../
make
sudo make install
sudo ldconfig
2、编译安装

编译的过程如下,1、cmake
在这里插入图片描述
2、make
在这里插入图片描述
3、sudo make install
4、sudo ldconfig
在这里插入图片描述
打开Gnuradio,刷新之后,可以查找到我们添加的blk
在这里插入图片描述
将它替换原本的模块,完美的运行了,当然生成的也是失真的图片,因为到目前为止我们并没有进行header块内部函数的修改。根据前面张老师的方法,我们只需要修改一个参数。下面我们修改这个参数,以便解决这个问题。

vi. 修改内部函数并测试结果

打开cc文件,查找const int items_padding,然后修改方法如下:

 //const int items_padding = std::max(d_header_padding_total_items, 1);  //源文件的代码const int items_padding = std::max(d_header_padding_total_items, 3);//修改后的代码(将1改成3)

将后面的1改成3,当然张老师的视频有详细的讲解原理。大家有兴趣可以详细观看,肯定有所收获。

修改的代码块如下:

case STATE_PAYLOAD:// Assumptions:// - Input buffer is in the right spot to just start copyingif (check_buffers_ready(d_curr_payload_len,0,noutput_items,d_curr_payload_len * (d_items_per_symbol + d_gi),ninput_items,n_items_read)){// Write payloadcopy_n_symbols(in,out_payload,PORT_PAYLOAD,n_items_read_base + n_items_read,d_curr_payload_len);// Consume payload// We can't consume the full payload, because we need to hold off// at least the padding value. We'll use a minimum padding of 1// item here.//const int items_padding = std::max(d_header_padding_total_items, 1);  //源文件的代码const int items_padding = std::max(d_header_padding_total_items, 3);//修改后的代码(将1改成3)const int items_to_consume =d_curr_payload_len * (d_items_per_symbol + d_gi) - items_padding;CONSUME_ITEMS(items_to_consume);set_min_noutput_items(d_output_symbols ? 1 : (d_items_per_symbol + d_gi));d_state = STATE_FIND_TRIGGER;}break;

完成修改后,我们重复之前 v 中的步骤,步骤如下:

1、cd gr-Myoot/build
2、make
3、sudo make install
4、sudo ldconfig

之后连接流图如图,可以看到传输的图片是很漂亮的:

在这里插入图片描述
再传输了之前传输失败的一些图片,如此图:
在这里插入图片描述
用原来文件的header是传输不过来的,但是修改之后,却可以完成传输的过程,过程我,这里好像放不了视频,我给放哔哩哔哩了,可以点击查看传输的过程。https://www.bilibili.com/video/BV14841167QV/?spm_id_from=333.999.0.0

5、总结:

笔者仍在学习,后面打算搭建一个完整的通讯过程,加入深度学习的内容,奈何要学习的东西实在太多,很多东西都找不到突破口,希望能得到大家的指点,共同学习。

6、参考资料:

参考资料
[1]: https://blog.csdn.net/Flag_ing/article/details/121272591
[2]: https://blog.csdn.net/Flag_ing/article/details/120468143
[3]: https://blog.csdn.net/Flag_ing/article/details/118568932
[4]: https://www.bilibili.com/video/BV1yj41197ym/?vd_source=cc2ad6f27704707aaa7e22b40e6d8b75#reply189349046432
[5]:https://www.docin.com/p-4015404154.html
[6]:https://www.bilibili.com/video/BV14841167QV/?spm_id_from=333.999.0.0,本实验最终过程

这篇关于将gnuradio源码中的模块添加制作成自己的OOT模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/627748

相关文章

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

使用Python制作一个PDF批量加密工具

《使用Python制作一个PDF批量加密工具》PDF批量加密‌是一种保护PDF文件安全性的方法,通过为多个PDF文件设置相同的密码,防止未经授权的用户访问这些文件,下面我们来看看如何使用Python制... 目录1.简介2.运行效果3.相关源码1.简介一个python写的PDF批量加密工具。PDF批量加密

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

Python模块导入的几种方法实现

《Python模块导入的几种方法实现》本文主要介绍了Python模块导入的几种方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录一、什么是模块?二、模块导入的基本方法1. 使用import整个模块2.使用from ... i

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于