GNU Radio中的流标签(Stream Tags)

目录

0、GR 中常用术语的官方解释

1、定义概述

2、在数据流中添加标签

3、添加标签的demo举例

4、从数据流中的获取标签

5、提取标签的demo举例


0、GR 中常用术语的官方解释

直接吧官方的解释抄过来,直接看英文更容易理解:

BlockA functional processing unit with inputs and outputs
PortA single input or output of a block
SourceA producer of data
SinkA consumer of data
ConnectionA flow of data from output port to input port
Flow graphA collection of blocks and connections
ItemA unit of data. Ex: baseband sample, fft vector, matrix...
StreamA continuous flow of consecutive items
IO signatureA description of a blocks input and output ports

1、定义概述

流标签(Stream Tags)顾名思义就是为数据流中的特定 item (即数据项,数据项可以理解为一个数据单元,这个单元可以是一个向量、数组、一般的数据类型如 float、int、char 等类型的数据,一下简称数据)打上标签,用以标记我们认为的一些特殊的数据(比如幅值低于某个阈值的无效数据等),便于后续数据的处理。标签的形式是一个键值对(key:value pair),定义在块(block)的 work 函数中。其中键(key)指明了值(value)所代表的含义,值包含了这个标签里要传输的数据内容。键和值都是PMTs类型的数据,键是一个pmt symbol类型的数据,而值可以是任何数据类型的的pmt。另外,标签中还有一个额外的部分SrcID,也是pmt symbol类型的数据,指明了创建这个标签的块,一般是块的别名。

2、在数据流中添加标签

一个标签中需要包含四个部分

1、偏置(offset):数据流中的标签需要使用绝对引用值。当某个数据流传输到某个block的work函数时,都会分配一个索引为0~N-1的缓冲区,该索引为数据流的相对索引。绝对索引值在数据流在流图开始运行时就开始计数了。可以通过以下两个c++ API来获取

unsigned long int nitems_read(unsigned int which_input);
unsigned long int nitems_written(unsigned int which_output);

nitems_read用于输入数据流,nitems_written用于输出数据流。如果使用i代表输出数据的迭代索引,则将在输出端口的第nitems_written(0)+i个位置写入流标签。0代表第0个输出端口(the 0th output port)。 

2、键(key):表明标签数据类型的pmt symbol

3、值(value):标签所含的数据,pmt类型

4、源ID(srcid):可选参数。指明了创建标签的block,pmt symbol类型

C++中有两种添加标签的函数;

// 第一种,直接传入定义好的标签结构体 
void add_item_tag(unsigned int which_output, const tag_t &tag);
// 第二种,显式调用
 void add_item_tag(unsigned int which_output,
                   uint64_t abs_offset,
                   const pmt::pmt_t &key,
                   const pmt::pmt_t &value,
                   const pmt::pmt_t &srcid=pmt::PMT_F);

第一种方式中是传入定义好的gr::tag_t结构体,第二种则是直接显式传入参数。

在Python中,可以调用如下方式添加标签(使用时注意参数数据类型):

add_item_tag(which_output, abs_offset, key, value)
add_item_tag(which_output, abs_offset, key, value, srcid)

3、添加标签的demo举例

我们使用GNU Radio自带的嵌入Python块(embedded Python block)来举例说明添加标签的方式,加深理解。

该demo的作用是将输入向量(1, 2, 3, 4, 5, 6, 7)中值小于4的数据打上标签。嵌入Python块的命名为“add stream tag”,标签的key为"smaller than thr",value为小于阈值threshold的数。流图如下:

其中嵌入Python块的代码如下:

import numpy as np
from gnuradio import gr
import pmt

class blk(gr.sync_block):  # other base classes are basic_block, decim_block, interp_block
    """Embedded Python Block example - a simple multiply const"""

    def __init__(self, threshold = 4.0):  # only default arguments here
        """arguments to this function show up as parameters in GRC"""
        gr.sync_block.__init__(
            self,
            name='add stream tag', 
            in_sig=[np.float32],
            out_sig=[np.float32] )
        # 设置阈值
        self.threshold = threshold

    def work(self, input_items, output_items):
        for index, sample in enumerate(input_items[0]):
            # print(sample)
            if sample < self.threshold:
                key = pmt.intern("smaller than thr")
                value = pmt.to_pmt(float(sample))
                # 为模值小于添加标签
                self.add_item_tag(0,    # 将标签写到第0个输出端口
                            self.nitems_written(0) + index,   # 绝对索引值
                            key,     # 键
                            value)   # 值
        output_items[0][:] = input_items[0]
        return len(output_items[0])

运行流图,结果如下。可以看到,在向量中,小于4的元素1、2、3都被打上了标签。 

4、从数据流中的获取标签

在C++中在指定的数据流中的获取标签油两种API可以调用,起作用范围已在注释中标明:

 // 1、获取数据在一个绝对索引值范围内的所有标签
 void get_tags_in_range(。。。);
 // 2、获取数据在一个绝对索引值范围内的所有标签(范围限制在一个work函数内)
 void get_tags_in_window(。。。);

每一种API都有两种调用方式,以get_tags_in_range为例说明:

 // 1、返回所给范围内的所有标签
 void get_tags_in_range(std::vector<tag_t> &v,
                        unsigned int which_input,
                        uint64_t abs_start,
                        uint64_t abs_end);
 // 2、返回所给范围内的指定键值的标签
 void get_tags_in_range(std::vector<tag_t> &v,
                        unsigned int which_input,
                        uint64_t abs_start,
                        uint64_t abs_end,
                        const pmt::pmt_t &key);

注意第二种相比第一种多了个键值参数。

Python中的调用方式与C++略有不同,在Python中是返回一个符合条件的标签列表,如下:

tags = self.get_tags_in_window(which_input, rel_start, rel_end)

5、提取标签的demo举例

同上一个demo一样,这里仍用一个嵌入Python块来举例,加标签部分还使用3中的代码。

流图如下,流图中添加了一个用来读取标签的嵌入Python块,并命名为“read tags”。

该提取标签的block的代码如下:

import numpy as np
from gnuradio import gr
import pmt

class blk(gr.sync_block):  # other base classes are basic_block, decim_block, interp_block
    """Embedded Python Block example - a simple multiply const"""

    def __init__(self):  
        """arguments to this function show up as parameters in GRC"""
        gr.sync_block.__init__(
            self,
            name='read tags',   # 模块命名
            in_sig=[np.float32],  # 输入数据类型
            out_sig=None)

    def work(self, input_items, output_items):
        tags = self.get_tags_in_window(0,   # 第0个输入端口
                                       0,   # 相对索引值下限
                       len(input_items[0])) # 相对索引值上限
        for tag in tags:
            key = pmt.to_python(tag.key)    # 将键由pmt转换为string
            value = pmt.to_python(tag.value)# 将键值由pmt转换为float
            print("(key: {} ; value: {})".format(key, value)) # 打印出键值对
        return len(output_items[0])

结果显示如下,可以看出,打印出的tags完全符合3中的tag数据。

(参考:Stream Tags - GNU Radio

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

地球被支点撬走啦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值