初级教程(3)创建和修改 Python 块4-Python 块标签
4.Python 块标签
本教程演示了如何创建两个嵌入式 Python 块,用于检测输入信号何时超过阈值并为其写入标签,然后在单独的块中读取标签并使用自上次检测以来的时间更新输出。
上一教程Python Block Message Passing演示了如何使用Embedded Python Block发送和接收消息。下一个教程低通滤波器示例演示了如何在 GNU Radio 中使用过滤块。
内容
标签概述
标签是一种以时间同步方式与数字化 RF 样本一起传递信息的方式。当下游块需要知道接收器调谐到新频率的样本时,或者在特定样本中包含时间戳时,标签特别有用。
在消息以异步方式传送信息且没有基于时钟的时间保证的情况下,标签是与特定 RF 样本相关联的信息。标签与数据流和矢量中的数字化 RF 样本并存,包括Complex Float 32、Float 32、Byte和所有其他格式。
使用以下行添加标签:
self.add_item_tag(outputPortNumber, absoluteIndex, key, value)
outputPortNumber确定将标签添加到哪个输出流。absoluteIndex是添加标签的样本索引。流程图对每个样本进行计数,生成的第一个样本位于绝对样本索引0 处。键是包含要存储的变量名称的 PMT 类型,值是包含要存储的信息的另一种 PMT 类型。

读取标签可以使用以下功能完成:
tagTuple = self.get_tags_in_window(inputPortNumber, relativeIndexStart, relativeIndexStop))
在窗口中读取标签会根据当前input_items向量中的相对索引读取它们。获取与当前input_items样本对应的所有标签的最简单方法是使用函数调用:
tagTuple = self.get_tags_in_window(inputPortNumber, 0, len(input_items[inputPortNumber])))

可以在此处找到有关标签的更多信息:流标签
创建测试信号
需要一个测试信号。拖入输入信号的块:
- GLFSR 来源
- 重复
- 乘以常量
- 添加常量
- 单极 IIR 滤波器
- 风门
- QT GUI 时间接收器
更改以下参数:
- GLFSR 来源,学位:32
- 重复,插值:128
- 乘以 Const,常数:0.5
- 添加 Const,常量:0.5
- 单极 IIR 滤波器,Alpha:0.05
- QT GUI 时间接收器
- 点数:2048
- 自动缩放:是
- samp_rate变量,值:3200
将所有块更改为Float输入和输出。根据以下流程图将它们全部连接起来:

运行流程图。生成 过滤后的0和1的伪随机序列:

阈值检测器:定义块
拖入一个Python Block并双击它以编辑源代码。回想一下,嵌入式 Python 块使用 4 个空格的倍数缩进。
更改example_param变量名称并添加新参数report_period:
def __init__(self, threshold=1.0, report_period=128):
更新块名称:
name='阈值检测器',
将输入和输出类型更改为Float:
in_sig=[np.float32], out_sig=[np.float32]
从self.example_param更改变量名称:
self.threshold = 阈值 self.report_period = report_period
删除self.example_param的乘法:
output_items[0][:] = input_items[0]
代码如下所示:

保存代码 (CTRL + S) 并返回 GRC。该块如下所示:

如果块没有正确更新,则可能是 Python 语法有问题。双击嵌入式 Python 块以查看任何潜在的语法错误。下图给出了 synax 错误所在位置的示例:

将虚拟接收器和虚拟源块添加到流程图。更改以下块属性:
- 阈值检测器
- 阈值:0.75
- 报告期:128
- Virtual Sink , Stream ID: signal
- 虚拟源,流 ID:信号
- QT GUI 时间接收器,名称:“阈值检测器”
根据流程图连接块:

阈值检测器:写标签
需要编写阈值检测器的内部结构。回想一下,嵌入式 Python 块使用 4 个空格的倍数缩进。
导入pmt库:
导入PMT
在__init__()函数下新增两个变量self.timer和self.readyForTag:
自拍定时器 = 0 self.readyForTag = True

work ()函数需要修改。创建一个 for 循环以遍历所有输入样本:
对于范围内的索引(len(input_items [0])):
需要写三段代码。一旦达到或超过阈值,第一个块将振幅级别写入名为detect的标签。仅当self.readyForTag状态变量为 True时才写入标签。写入标签后,状态变量self.readyForTag将设置为 False。
# 写标签 如果(input_items[0][index] >= self.threshold 和 self.readyForTag == True): # 将键定义为“检测” key = pmt.intern('检测') # 获取检测值 value = pmt.from_float(np.round(float(input_items[0][index]),2)) # 要写入的标签索引 writeIndex = self.nitems_written(0) + 索引 # 添加标签对象(键值对) self.add_item_tag(0, writeIndex, 键, 值) # 标签已经写入,设置状态 self.readyForTag = 假
下一个代码块用于运行计时器。只要self.readyForTag为 False,定时器就会为每个输入样本增加 1:
# 将计时器增加 1 如果(self.readyForTag == False): 自拍定时器 = 自拍定时器 + 1
第三个代码块控制状态变量self.readyForTag。一旦self.timer达到最大值,计时器就会重置,状态变量self.readyForTag将设置为 True:
# 设置要写的标志 如果(self.timer >= self.report_period): # 重置定时器 自拍定时器 = 0 # 一旦定时器达到最大值就重置状态 self.readyForTag = True

运行流程图。标签显示在QT GUI Time Sink中:

检测计数器:定义块
创建一个新的嵌入式 Python 块来读取标签,计算自上一个标签以来的样本数,并将该数字作为输出。
将一个新的 Python 块拖放到 GRC 工作区中。不要复制和粘贴现有的 python 块,它只会创建Threshold Detector的第二个副本。
双击Embedded Python Block并编辑代码。
删除self.example_param参数:
def __init__(自我):
更改名称:
name='检测计数器',
使输入和输出端口浮动:
in_sig=[np.float32], out_sig=[np.float32]
删除行self.example_param = example_param和乘以self.example_param:
output_items[0][:] = input_items[0]

保存代码 (CTRL + S)。添加另一个QT GUI Time Sink并更改属性:
- QT GUI 时间接收器
- 名称:《检测计数器》
- 点数:2048
- 自动缩放:是
在阈值检测之后 连接检测计数器块。

检测计数器:读取标签
需要修改 检测计数器块以读取标签。
导入pmt库:
导入PMT
在__init__()下添加一个新变量:
self.samplesSinceDetection = 0

修改work()函数以读取标签:
# 获取与 input_items[0] 关联的所有标签 tagTuple = self.get_tags_in_window(0, 0, len(input_items[0]))
遍历所有标签,计算键等于检测的标签的相对偏移量,并将其存储在列表中:
# 声明一个列表 relativeOffsetList = [] # 遍历所有“检测”标签并存储它们的相对偏移量 对于 tagTuple 中的标签: 如果(pmt.to_python(tag.key)=='检测'): relativeOffsetList.append( tag.offset - self.nitems_read(0) )
将偏移量从最低到最高排序:
# 排序相对偏移列表 relativeOffsetList.sort()
遍历所有输出样本:
# 遍历所有输出样本 对于范围内的索引(len(output_items [0])):
使用自上次检测标签以来的当前样本数生成输出样本:
# 输出现在是自检测计数器以来的样本 output_items[0][index] = self.samplesSinceDetection
如果当前输出样本索引大于或等于当前检测标签的索引,则从列表中删除偏移值并重置样本计数器self.samplesSinceDetection。否则,将样本计数器加 1。
# 确保列表不为空,如果当前输入样本 #大于或等于下一个 如果 (len(relativeOffsetList) > 0 和索引 >= relativeOffsetList[0]): # 清除偏移量 relativeOffsetList.pop(0) # 重置输出计数器 self.samplesSinceDetection = 0 别的: # 没有看到检测标签,所以继续增加 # 输出计数器 self.samplesSinceDetection = self.samplesSinceDetection + 1
删除输出分配:
output_items[0][:] = input_items[0]
工作函数如下所示:

保存代码 (CTRL + S)。运行流程图。输出如下所示:

请注意,来自检测计数器 输入的所有标签都自动传送到其输出。
标签传播
默认情况下,所有输入标签都会传播到所有输出标签。从某些流中减少或完全删除标签可能很有用。Tag Gate块正是这样做的。在检测计数器块之后连接标签门:

运行流程图。这些标签已从QT GUI Time Sink中删除:

下一个教程低通滤波器示例演示了如何在 GNU Radio 中使用过滤块。