GNU Radio3.8创建OOT的详细过程(进阶/C++)

GNU Radio 学习使用 OOT 系列教程:

GNU Radio3.8创建OOT的详细过程(基础/C++)

GNU Radio3.8创建OOT的详细过程(进阶/C++)

GNU Radio3.8创建OOT的详细过程(python)

GNU Radio自定义模块:Embedded Python Block的使用

GNU Radio3.8:编辑yaml文件的方法

GNU Radio3.8:创建自定义的QPSK块(C++)

----------------------------------------------------------------------------------------

目录

一、sync block 的创建

二、一些其他类型的块

1、Sources 和 Sinks

2、Hierarchical blocks

3、Decimation Block

4、Interpolation Block


在上篇文章《GNU 3.8创建OOT的详细过程(基础/C++) 》我们创建了一个 general 类型的 block ,文章的结尾我们提到,对于输入输出数据比固定为 1:1 的情况下,我们可以对 “general” 类型的 block 的代码进行进行简化,这样就引出了本文要讲的 sync 类型的 block 。

对于输入输出数据比固定为 1:1 时还有一种特殊情况:即我们需要用到 N 个数据来生成一个输出,但是这 N 个数据中前 N-1 个数据为历史记录的数据,只有第 N 个数据为当前的新数据(类似滑动窗口中每滑动一步就会记载一个新的数据并丢掉一个最旧的数据,注意其与插值 1:N 数据比以及抽取操作 N:1 数据比的区别)。对于前 N-1 个数据来说,这在 GR 中是一种叫做 “history” 的概念,这时就需要在构造函数中或在需求发生变化时调用 set_history()。例如,对于非抽取、非插值的 FIR 滤波器来说,需要检查它产生的每个输出样本的 N 个输入样本,其中 N 是滤波器中的抽头数。但是,它每次只消耗1个输入样本来产生1个输出。

官方对 generalsync 的解释为:

GeneralThis block a generic version of all blocks
SyncThe sync block allows users to write blocks that consume and produce an equal number of items per port. From the user perspective, the GNU Radio scheduler synchronizes the input and output items, it has nothing to with synchronization algorithms

一、sync block 的创建

sync block 的创建过程与 general block 的创建方法类似。我们还在 之前创建的 mymod 模块 的基础上 添加一个名为 square2_ff 的 sync block,作用与之前的 square1_ff 一样。命令为:gr_modtool add -t sync -l cpp square2_ff

wsx@wsx:~/temp/gr-mymod$ gr_modtool add -t sync -l cpp square2_ff
GNU Radio module name identified: mymod
Language: C++
Block/code identifier: square2_ff
Please specify the copyright holder: 
Enter valid argument list, including default arguments: 
Add Python QA code? [Y/n] y
Add C++ QA code? [y/N] n
Adding file 'lib/square2_ff_impl.h'...
Adding file 'lib/square2_ff_impl.cc'...
Adding file 'include/mymod/square2_ff.h'...
Editing swig/mymod_swig.i...
Adding file 'python/qa_square2_ff.py'...
Editing python/CMakeLists.txt...
Adding file 'grc/mymod_square2_ff.block.yml'...
Editing grc/CMakeLists.txt...

同样的,仍然使用 python 测试文件,命令参数及最终生成的文件等内容在 上一篇文章 中已详细介绍,这里就不在赘述啦~

下面是测试代码 python/qa_square2_ff.py 的编写:

# python/qa_square2_ff.py
from gnuradio import gr, gr_unittest
from gnuradio import blocks
import mymod_swig as mymod

class qa_square2_ff(gr_unittest.TestCase):

    def setUp(self):
        self.tb = gr.top_block()

    def tearDown(self):
        self.tb = None

    def test_001_square2_ff(self):
        src_data = (-3, 4, -5.5, 2, 3)
        expected_result = (9, 16, 30.25, 4, 9)
        src = blocks.vector_source_f(src_data)
        sqr = mymod.square2_ff()
        dst = blocks.vector_sink_f()
        self.tb.connect(src, sqr, dst)
        self.tb.run()
        result_data = dst.data()
        self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6)
        # check data

if __name__ == '__main__':
    gr_unittest.run(qa_square2_ff)

然后是 lib/square2_ff_impl.cc 代码的填写:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "square2_ff_impl.h"

namespace gr {
  namespace mymod {

    square2_ff::sptr
    square2_ff::make()
    {
      return gnuradio::get_initial_sptr
        (new square2_ff_impl());
    }

    /* 构造函数 */
    square2_ff_impl::square2_ff_impl()
      : gr::sync_block("square2_ff",
                  gr::io_signature::make(1, 1, sizeof (float)), // input signature
                  gr::io_signature::make(1, 1, sizeof (float))) // output signature
    {}

    /* 析构函数 */
    square2_ff_impl::~square2_ff_impl()
    { }

    // work()是执行实际信号处理任务的函数
    int
    square2_ff_impl::work(int noutput_items,
        gr_vector_const_void_star &input_items,
        gr_vector_void_star &output_items)
    {
      const float *in = (const float *) input_items[0];
      float *out = (float *) output_items[0];

      for(int i = 0; i < noutput_items; i++) {
        out[i] = in[i] * in[i];
      }

      // Tell runtime system how many output items we produced.
      return noutput_items;
    }

  } /* namespace mymod */
} /* namespace gr */

上述代码中,测试文件的编写没啥区别,区别主要是在 square2_ff_impl.cc 代码中。可以发现,新的代码中的代码量少了不少,信号处理主函数由 work() 取代了 general_work() ,并且省略了 ninput_items 参数,同时 consume_each() 以及 forecast() 函数也不见了。如果 block 需要大于 1 个 history,则需要在构造函数中或在需求发生变化时调用 set_history()。

这里 forecast 函数虽然没显式调用,但在代码中会隐式实现,系统会默认为1:1的关系。consume_each 函数也是如此。

之后对 square2_ff 进行编译安装。由于之前添加 square2_ff 时 gr_modtool 已自动修改 CMakeList 文件,这里在 build/ 文件夹中可以直接 make,系统会自动重新 cmake 然后再make:

wsx@wsx:~/temp/gr-mymod/build$ make -j10
-- Build type not specified: defaulting to release.
-- Using GMP.
-- User set python executable /usr/bin/python3
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython3.8.so (found suitable exact version "3.8.10") 
-- Using install prefix: /usr/local
-- Building for version: v1.0-compat-xxx-xunknown / 1.0.0git
-- No C++ unit tests... skipping
-- 
-- Checking for module SWIG
-- Found SWIG version 4.0.1.
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython3.8.so (found version "3.8.10") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/wsx/temp/gr-mymod/build
[ 20%] Built target pygen_apps_9a6dd
[ 33%] Built target doxygen_target
[ 33%] Built target _mymod_swig_doc_tag
[ 33%] Built target pygen_python_6451a
Scanning dependencies of target gnuradio-mymod
[ 46%] Built target mymod_swig_swig_doc
Scanning dependencies of target mymod_swig_swig_compilation
[ 60%] Building CXX object lib/CMakeFiles/gnuradio-mymod.dir/square2_ff_impl.cc.o
[ 60%] Swig source mymod_swig.i
[ 60%] Built target mymod_swig_swig_compilation
[ 66%] Linking CXX shared library libgnuradio-mymod.so
[ 73%] Built target gnuradio-mymod
Scanning dependencies of target mymod_swig
[ 80%] Building CXX object swig/CMakeFiles/mymod_swig.dir/CMakeFiles/mymod_swig.dir/mymod_swigPYTHON_wrap.cxx.o
[ 86%] Linking CXX shared module _mymod_swig.so
[ 86%] Built target mymod_swig
[100%] Generating mymod_swig.pyo
[100%] Generating mymod_swig.pyc
[100%] Built target pygen_swig_1e481

之后又是 make test 。。。emmmmm,你可以先 make test 一下试试,如果能通过,当我下面的 BUG 部分啥也没说哈——如果没通过,而且运行 ctest -V -R square 报错的话,那就继续看下面这部分:

============================== BUG ===============================

报错大概是这样的:ImportError: ×××: undefined symbol ×××

ImportError: /path/to/build/swig/_mymod_swig.so: undefined symbol: _ZN2gr5mymod10square2_ff4makeEv

这就遇到一个很神奇的现象,但是并不影响最终的使用,情况是这样的:

情况1:在本例中,我们是继续 这篇文章 的步骤,在 mymod 模块中添加了第二个 block:square2_ff,这时的情况就是之前那个 block:square1_ff 已经编译过一次,我们是在这样一个基础上再对又添加一个 block 后的两个 block 进行编译。这种情况下,在我进行编译测试的过程中,如果 make 之后紧接着就是 make test 的话,就会出现上面提到的这个问题,这时我找遍了 google 的资源,找到了几个遇到过相似问题的解决方法:

python - gnuradio `ImportError undefined symbol` - Stack Overflow

FAQ - GNU Radio

但是,这种解决方式大致的意思就是说cmakelist文件中没有加入跟 square2_ff 有关的库并需要我们手动加入,emmmmm我照做了,但是没啥用(好吧,我承认是我没太看懂这上面大佬的解决方法说的是个啥。。。),但是直觉告诉我 test 没通过可能也不影响后面的使用,之后我就没管这个这个 test 的问题直接进行 gr_modtool makeyaml square2_ff,然后 sudo make install,然后!我发现 test 没通过确实对结果没影响,square1_ff 和 square2_ff 都能在GRC中使用了!后来在回到 build 文件中运行 make test ,它通过了。。。OK,完成,总结就是:

最好在 sudo make install 之后在运行 make test 。

 情况2:在情况1的基础上,我猜测可能是先对 square1_ff 进行编译 的结果影响了后面再加入 的 square2_ff ,因此就尝试删了之前安装好的 block 及 mymod 工程,重新建一个一模一样的,依次完成加入square1_ff / square2_ff 和 相应的 python test 文件等步骤,然后一起一次性完成编译,这时我在 make 命令之后紧接着运行 make test 指令,他真的通过了!

wsx@wsx:~/temp/gr-mymod/build$ make -j10
Scanning dependencies of target pygen_python_6451a
Scanning dependencies of target pygen_apps_9a6dd
Scanning dependencies of target doxygen_target
Scanning dependencies of target _mymod_swig_doc_tag
Scanning dependencies of target gnuradio-mymod
[ 13%] Built target pygen_apps_9a6dd
[ 20%] Generating documentation with doxygen
[ 20%] Generating __init__.pyc
[ 20%] Generating __init__.pyo
[ 26%] Building CXX object swig/CMakeFiles/_mymod_swig_doc_tag.dir/_mymod_swig_doc_tag.cpp.o
[ 33%] Building CXX object lib/CMakeFiles/gnuradio-mymod.dir/square2_ff_impl.cc.o
[ 40%] Building CXX object lib/CMakeFiles/gnuradio-mymod.dir/square1_ff_impl.cc.o
warning: Tag 'PERL_PATH' at line 1686 of file '/home/wsx/temp/gr-mymod/build/docs/doxygen/Doxyfile' has become obsolete.
         To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u"
warning: Tag 'MSCGEN_PATH' at line 1707 of file '/home/wsx/temp/gr-mymod/build/docs/doxygen/Doxyfile' has become obsolete.
         To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u"
[ 40%] Built target pygen_python_6451a
[ 40%] Built target doxygen_target
[ 46%] Linking CXX executable _mymod_swig_doc_tag
[ 46%] Built target _mymod_swig_doc_tag
Scanning dependencies of target mymod_swig_swig_doc
[ 53%] Generating doxygen xml for mymod_swig_doc docs
warning: Tag 'PERL_PATH' at line 1654 of file '/home/wsx/temp/gr-mymod/build/swig/mymod_swig_doc_swig_docs/Doxyfile' has become obsolete.
         To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u"
warning: Tag 'MSCGEN_PATH' at line 1675 of file '/home/wsx/temp/gr-mymod/build/swig/mymod_swig_doc_swig_docs/Doxyfile' has become obsolete.
         To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u"
[ 60%] Generating python docstrings for mymod_swig_doc
[ 60%] Built target mymod_swig_swig_doc
Scanning dependencies of target mymod_swig_swig_compilation
[ 66%] Swig source mymod_swig.i
[ 66%] Built target mymod_swig_swig_compilation
[ 73%] Linking CXX shared library libgnuradio-mymod.so
[ 73%] Built target gnuradio-mymod
Scanning dependencies of target mymod_swig
[ 80%] Building CXX object swig/CMakeFiles/mymod_swig.dir/CMakeFiles/mymod_swig.dir/mymod_swigPYTHON_wrap.cxx.o
[ 86%] Linking CXX shared module _mymod_swig.so
[ 86%] Built target mymod_swig
Scanning dependencies of target pygen_swig_1e481
[100%] Generating mymod_swig.pyo
[100%] Generating mymod_swig.pyc
[100%] Built target pygen_swig_1e481
wsx@wsx:~/temp/gr-mymod/build$ make test
Running tests...
Test project /home/wsx/temp/gr-mymod/build
    Start 1: qa_square1_ff
1/2 Test #1: qa_square1_ff ....................   Passed   17.04 sec
    Start 2: qa_square2_ff
2/2 Test #2: qa_square2_ff ....................   Passed    0.73 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) =  18.10 sec

情况就是这么个情况,玄乎。。好了,问题解决了,我们继续讲后面的

============================== END ===============================

下面是安装完成之后的效果:

 运行的结果如下:

二、一些其他类型的块

1、Sources 和 Sinks

Sources 和 Sinks 都是 gr:sync_block 的派生类。唯一不同的是 sources 没有输入端口。sinks没有输出端口,这些由 gr::io_signature::make 控制。可以在源码文件中查看一些例子:

gr-blocks / lib / file_source_impl.cc、file_source.{h,cc}、file_sink_impl.{h,cc} 

2、Hierarchical blocks

Hierarchical(分层) blocks 是由其他 blocks 组成的一种 block,它可以实例化其他 blocks 或者 hierarchical blocks 并将他们连接起来,为了达到这个目的,hierarchical block 内部有一个“connect” 函数可供调用。hierarchical block 可以像普通 block 一样定义输入输出流。

把一个输入 i 连接到一个 hierarchical block 的python 代码:

self.connect((self, <i>), <block>)

类似地,要将信号从输出流 o 上的块发送出去的代码:

self.connect(<block>, (self, <o>))

与创建 sync 及 general 的方法一样,使用 gr_modtool 创建 hierarchical block 的命令如下:

gr_modtool.py add -t hier -l cpp hierblockcpp_ff

3、Decimation Block

decimation(抽取) block 是另一种类型的固定速率块(N : 1),其中输入项的数量是输出项数量的固定倍数。一个  decimation block 的 C++ 例子如下:

#include <gr_sync_decimator.h>

class my_decim_block : public gr_sync_decimator
{
public:
  my_decim_block(...):
    gr_sync_decimator("my decim block", 
                      in_sig,
                      out_sig,
                      decimation)
  {
    //constructor stuff
  }

  //work function here...
};

gr_sync_decimator 构造函数的第四个参数 decimation 为抽取因子。另外,不难理解,输入项目的数量 = noutput_items * decimation

4、Interpolation Block

与decimation block 作用相反,interpolation(插值) block 是另一种固定速率块(1 : N),其中输出项的数量是输入项数量的固定倍数。C++例子如下。

#include <gr_sync_interpolator.h>

class my_interp_block : public gr_sync_interpolator
{
public:
  my_interp_block(...):
    gr_sync_interpolator("my interp block", 
                         in_sig,
                         out_sig,
                         interpolation)
  {
    //constructor stuff
  }

  //work function here...
};

参考网站:

OutOfTreeModules - GNU Radio

BlocksCodingGuide - GNU Radio

GNU Radio Manual and C++ API Reference: gr::block Class Reference

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

地球被支点撬走啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值