GNU Radio Stream Tags

Stream Tags

Introduction

GNURadio原本是一个流媒体系统,没有其他的机制在块之间传递数据。数据流是一个可以很好地处理采样值、比特等的模型,但是缺乏控制手段和元数据。

其中的一部分是通过消息传递接口来解决的,它允许块认同flowgraph中任何其他块发布的消息。消息传递系统的主要缺点是异步工作,这意味着当消息相对于数据流到达时,没有保证。

流标签是与主数据流并行运行的等同步数据流。流标签是由一个块的工作函数生成的,并且从那里流向下游的一个特定的采样值,直到它到达一个接收器,或者被迫停止另一个块的传播。

流标签是为数据流中的特定项目定义的,并以键:值(key:vaule)对组成。键识别值是什么,而值保存标签所包含的数据。键和值都是PMTs(多态类型),其中键是PMT符号,而值是任何类型的PMT,因此可以处理我们希望传递的任何数据。标签的第四个部分是srcid,它是PMT符号,用于识别创建标记的块(通常是block的别名())。

API Extensions to the gr::block

要启用流标签,我们已经拓展了gr::block的API来理解absolute条目数字。在数据流模型中,每个块的工作函数在从0到N-1的数据流中都有一个缓冲区。这是数据流的相对偏移量。绝对引用从流程图的开始开始,并继续与任何条目一起计数。每个输入流都与“读取的条目数量”的概念相关联,并且每个输出流都有一个“被写入的条目数量”。这些都是通过两个API调用来实现的:

unsigned long int nitems_read(unsigned int which_input);

unsigned long int nitems_written(unsigned int which_output);

每个标记都与这个绝对时间范围内的某个条目相关联,这些项是使用这些函数计算的。

和其他数据流一样,在调用工作函数时,读/写的条目数只更新一次。因此,在一个工作函数中,读/写的条目数将在工作函数开始时引用数据流的状态。因此,我们必须在数据流中增加当前相对偏移量。因此,如果我们对所有的输出项迭代i次,我们将把流标签写在nitems_written(0)+i的输出端口上,为第0个输出端口。

Stream Tags API

流标签API由4个函数组成,2个用来添加,2个用来获取流标签。这些函数只在调用通用工作/工作函数时被访问。虽然可以通过一个块在其他地方调用它们,但是由于没有对缓冲区中条目计数的确切了解,工作函数之外的行为没有定义。

Adding a Tag to a Stream

这里定义了两个函数调用来添加item标签。我们将一个标记添加到块的特定输出流中。如果需要的话,我们可以将它们输出到多个输出流中,但是要这样做,就意味着每个端口都调用一个函数。

同样,标签被定义为:

offset: 在绝对项目时间内,数据流中的标记的偏移量。

key: ***:***PMT符号,标识标签的类型。

value: PMT类型数据,保存标签的数据。.

srcid: (可选的)PMT符号,标识创建标签的块。

我们可以建立一个gr::tagt结构来保存所有的标签信息,这可能是最简单的方法。gr:tagt struct被定义为拥有与上面列表相同的成员。要向流添加gr::tagt标签,请使用该函数:

void add_item_tag(unsigned int which_output, consttag_t &tag);

二级API允许我们通过显式列出函数调用中的所有标记信息来创建标记:

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);

Getting tags from a Stream

为了从一个特定的输入流中获得标记,我们有两个可以使用的函数。这两个都传回了gr::tagt向量。第二个函数允许我们指定一个特殊的键(作为PMT符号),它会滤除我们感兴趣的键以外的所有键,这减少了工作函数中获取正确标签数据的工作量。

第一个调用只返回给定范围项之间的任何标记:

void get_tags_in_range(std::vector &v,

unsigned int which_input,

uint64_t abs_start,

uint64_t abs_end);

向这个函数添加第五个参数允许我们对键key进行过滤。

void get_tags_in_range(std::vector &v,

unsigned int which_input,

uint64_t abs_start,

uint64_t abs_end,

const pmt::pmt_t &key);

Tag Propagation

标签像正常的数据流一样,从一个块传播到另一个块。如何实际移动块取决于具体的传播策略。我们定义了三种类型的政策:

All-to-All: 来自任何输入端口的所有标签都被复制到所有输出端口

One-to-One: 输入端口i的标签只被复制到输出端口i(依赖于num inputs = num outputs)。

Dont: 不传播标记。标签要么在这里停止,要么工作函数传播它们本身。

块的默认行为是“All-to-All”的传播方法。

要设置不同的传播策略,请使用该函数:

void set_tag_propagation_policy(tag_propagation_policy_tp);

请参阅gr::block::tag_propagation_policy_t文档,以了解该枚举类型的详细信息。

Tag Propagation through Rate Changes

当一个标记通过一个具有速率变化的块传播时,数据流中的条目的偏移量将发生变化。调度器使用block的gr::block::relative_rate来执行标签的偏移值的更新。块的相对变化率决定了输入速率和输出速率之间的关系。下抽数值为D的下抽器的相对变化率是1/D。

同步块(gr::syncblock)、下抽器(gr::sync_decimator)和插值器(gr::sync_interpolator)都具有预定义的和易于理解的相对速率。一个标准的gr::block的默认相对速率是1.0,但是如果它不这样工作,那么它必须被设置。通常,我们使用一个gr::block,因为我们没有预先设想的输出项的输入数量。如果重要的是通过这些块传递标签来考虑项目值的变化,那么我们就必须使用TPP_DONT标记传播策略并在内部处理传播。

在任何情况下,标签的值都是通过块传播的。当使用TaggedStream Blocks.时,这就变得相关了。

Notes on How to Use Tags

标签对应用程序非常有用,而且它们的应用也在扩展。如果有任何变化,USRP源会生成关于时间、采样率和频率的标签信息。我们有一个元数据文件source/sink,它使用标记来存储关于数据流的信息。但是,当在块中使用标记时,有一些事情需要考虑。

首先,当没有使用标记时,调度程序几乎没有任何影响。但是,当我们使用标记时,我们通过从数据流中获取和提取标记来增加开销。我们还使用开销来传播标记。对于每一个标签,每个块必须将一个标记向量从一个块的输出端口(s)复制到下一个块(s)的输入端口(s)。这些复制操作可以加起来。

关键是要尽量减少标签的使用。在必要时使用它们,并尝试提供一些控制,以控制如何生成标签来控制它们的频率。一个很好的例子是USRP source,,它生成一个时间标记。如果每个采样值都生成一个标记,那么每秒钟就会有数千个标记,这将增加大量的开销。相反,如果我们以t0开始,采样率为sr,那么在N个样本之后,我们知道我们现在是在t0+N/sr。因此不断产生新标签不会增加信息。

在上述情况下,我们需要处理的主要问题是,从USRP收到的数据包中出现了不连续点。由于我们无法在流程图中知道有多少样本可能丢失,我们已经失去了对计时信息的跟踪。USRP驱动程序识别数据包何时被丢弃,并使用它来排队等候另一个标签,这允许我们重新同步。同样地,每当采样率或频率发生变化时,都会发出一个新的标记。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值