GNU Radio Companion
Stream Tags
Metadaten, die synchron an einzelne Samples eines Datenstroms geheftet werden — Aufbau, PMTs und Beispielcode.
In GNU Radio fließen Daten normalerweise als ununterbrochener Strom von Samples. Ein Stream Tag ist ein Mechanismus, um Metadaten (in Form von Schlüssel-Wert-Paaren) direkt an ein spezifisches Sample innerhalb dieses Datenstroms zu heften.
Im Gegensatz zu „Message Passing" (das asynchron und ohne Zeitstempel erfolgt) sind Tags synchron: Ein Tag bleibt an "seinem" Sample, während es den Flowgraph durchläuft. Bei ratenverändernden Blöcken (Dezimatoren, Interpolatoren) bedeutet das nicht denselben Offset-Wert, sondern eine proportionale Umrechnung — ein Tag bei Offset 1000 landet nach einer Dezimation um Faktor 10 bei Offset 100, bleibt also an der relativen Position im Signal, nicht am identischen Sample-Index.
Ein Tag besteht technisch aus vier Komponenten:
- Offset: Die absolute Position im Datenstrom (Sample-Index).
- Key: Ein PMT-Symbol (z.B.
pmt::mp("rx_freq")). - Value: Ein PMT-Wert (kann fast alles sein: Zahlen, Strings, Vektoren).
- Source ID: Ein PMT-Symbol, das den Block identifiziert, der den Tag erstellt hat.
PMT (Polymorphic Types)
Ein PMT ist ein Container-Typ, der jeden beliebigen Datentyp aufnehmen kann. Er verhält sich ähnlich wie ein Variant-Typ in anderen Sprachen oder ein Object in Java/Python. Das ermöglicht es GNU Radio, Nachrichten und Tags zu versenden, ohne dass der Empfänger-Block vorher genau wissen muss, welche Struktur die Daten haben.
Die meisten PMTs sind immutable. Um einen Wert zu ändern, muss daher technisch gesehen ein neues PMT-Objekt erzeugt werden. Das macht sie sicher für den Einsatz in Multi-Threaded-Umgebungen, da keine Locks benötigt werden, wenn ein Tag von mehreren Blöcken gleichzeitig gelesen wird. Ein in Python erstelltes PMT-Element kann auch direkt in einem C++-Block gelesen werden. Das ermöglicht eine nahtlose Datenübergabe.
Python verfügt über ein PMT-Modul, mit dessen Hilfe die PMT-Variablen erzeugt werden können.
Bsp.: pmt.from_long(42)
Bsp.: pmt.from_long(42)
Tags einfügen
In Verbindung mit den Stream Tags können Tags sowohl als Keys als auch als Values angelegt werden.
self.key_preamble = pmt.intern("preamble_start") wäre z.B. ein Key, um den Start einer Preamble zu markieren.
Ein Tag wird mit der Methode self.add_item_tag() in einen Datenstrom eingespeist.
self.add_item_tag(stream_id, offset, key, value)
Bsp.: self.add_item_tag(0, self.nitems_written(0) + index, self.key_preamble, pmt.PMT_T)
self.add_item_tag(stream_id, offset, key, value)
Bsp.: self.add_item_tag(0, self.nitems_written(0) + index, self.key_preamble, pmt.PMT_T)
Tags auslesen
Das Gegenstück zum Einfügen ist das Auslesen: Ein nachfolgender Block fragt mit self.get_tags_in_window() alle Tags ab, die innerhalb des aktuell verarbeiteten Samples-Fensters liegen. Ohne diesen Schritt bleiben eingefügte Tags im Datenstrom, aber kein Block reagiert auf sie.
def work(self, input_items, output_items):
n_input = len(input_items[0])
# Alle Tags im aktuellen Verarbeitungsfenster abrufen
tags = self.get_tags_in_window(0, 0, n_input, self.key_preamble)
for tag in tags:
offset_in_window = tag.offset - self.nitems_read(0)
# z.B. Symbol-Sync zurücksetzen, sobald die Preamble erkannt wird
print(f"Preamble-Tag gefunden bei relativer Position {offset_in_window}")
output_items[0][:] = input_items[0]
return n_input
def work(self, input_items, output_items):
n_input = len(input_items[0])
# Alle Tags im aktuellen Verarbeitungsfenster abrufen
tags = self.get_tags_in_window(0, 0, n_input, self.key_preamble)
for tag in tags:
offset_in_window = tag.offset - self.nitems_read(0)
# z.B. Symbol-Sync zurücksetzen, sobald die Preamble erkannt wird
print(f"Preamble-Tag gefunden bei relativer Position {offset_in_window}")
output_items[0][:] = input_items[0]
return n_input
tag.offset ist dabei immer die absolute Position im gesamten Stream — self.nitems_read(0) liefert die absolute Position des ersten Samples im aktuellen Fenster, die Differenz ergibt die Position relativ zum gerade verarbeiteten Puffer.