将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

相关文章

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

springboot项目打jar制作成镜像并指定配置文件位置方式

《springboot项目打jar制作成镜像并指定配置文件位置方式》:本文主要介绍springboot项目打jar制作成镜像并指定配置文件位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录一、上传jar到服务器二、编写dockerfile三、新建对应配置文件所存放的数据卷目录四、将配置文

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

Python datetime 模块概述及应用场景

《Pythondatetime模块概述及应用场景》Python的datetime模块是标准库中用于处理日期和时间的核心模块,本文给大家介绍Pythondatetime模块概述及应用场景,感兴趣的朋... 目录一、python datetime 模块概述二、datetime 模块核心类解析三、日期时间格式化与

Python如何调用指定路径的模块

《Python如何调用指定路径的模块》要在Python中调用指定路径的模块,可以使用sys.path.append,importlib.util.spec_from_file_location和exe... 目录一、sys.path.append() 方法1. 方法简介2. 使用示例3. 注意事项二、imp

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel