---
title: "Zugriff auf Ergebnisdaten mit FlatBuffers"
product: "LumiScan AI Object Matching"
component: "lumiscan-ai-object-matching-de"
version: "2.1.0"
display_version: "2.1.0.9"
latest_version: true
language: "de"
url: "https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/accessing-flatbuffers-data.html"
---

# Zugriff auf Ergebnisdaten mit FlatBuffers – LumiScan AI Object Matching

Diese Seite gilt für ctrlX OS (ctrlX CORE oder ctrlX IPC): Sie beschreibt, wie ein ctrlX-SPS-Programm das Ergebnis liest.

LumiScan AI Object Matching veröffentlicht das Ergebnis jeder Inferenz auf dem ctrlX Data Layer als binäre FlatBuffers-Nachricht. Ein SPS-Programm kann diese Nachricht nur mit dem Schema interpretieren, das ihren Aufbau beschreibt. Die Anwendung stellt deshalb die Schemadatei `object_detection.fbs` bereit.

Dieses Kapitel beschreibt, wie Sie das Schema beziehen, wie Sie es in ctrlX PLC Engineering importieren und wie Sie das Ergebnis lesen, einschließlich Position und Score eines erkannten Objekts.

## Ergebnisknoten

**Tabelle 1. Eigenschaften des Ergebnisknotens**

| Eigenschaft | Wert |
| --- | --- |
| Knotenadresse | `hdvisionsystems/lumiscan-ai-object-matching/<network name>/output/result` |
| Zugriff | Schreibgeschützt |
| Datentyp | FlatBuffers |
| Adresse des registrierten Typs | `types/hdvisionsystems/lumiscan-ai-object-matching/object_detection` |
| Schemadatei | `object_detection.fbs` |
| Schema-Namespace | `hdv.object_detection2d` |
| Root-Typ | `Result` |

Der Knoten enthält das Ergebnis der letzten Inferenz. Lesen Sie ihn erst, nachdem die Inferenz abgeschlossen und erfolgreich war: Beim Handshake ist `output/package-identifier` um eins gestiegen (`status/code` ist am Ende jeder über den Handshake angeforderten Inferenz `3`); bei `control/inference/execute` ist `status/code` `0`. Siehe [Ausgang einer Inferenz](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/general-concept-of-handshake.html#outcome-of-an-inference) und [Statuscode-Werte](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/initializing-the-inference.html#status-code-values).

## Voraussetzungen

- ctrlX PLC Engineering 2.6 oder neuer.
- Die Bibliotheken `CXA_Datalayer` und `CXA_Flatbuffers` sind im **Library Manager** des SPS-Projekts referenziert. `CXA_Datalayer` liest Knoten vom Data Layer. `CXA_Flatbuffers` stellt die Basis-Funktionsbausteine der FlatBuffers-Funktionsbausteine bereit, die der Import erzeugt. Prüfen Sie nach dem Import den Library Manager. Fehlt eine Bibliothek, fügen Sie sie dort hinzu (siehe auch [Die ctrlX-Data-Layer-Bibliothek installieren](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/accessing-flatbuffers-data.html#lumiscan-install-datalayer-library)).
- LumiScan AI Object Matching ist installiert und wurde mindestens einmal mit einer gültigen Lizenz gestartet (siehe [Voraussetzungen](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/requirements.html)).

## Schritt 1: Schemadatei beziehen

Die Anwendung kopiert das Schema bei jedem Start in ihren Anwendungsdatenordner auf der ctrlX CORE. So laden Sie es herunter:

1. Melden Sie sich an der Weboberfläche von ctrlX OS an und öffnen Sie **Manage app data** (siehe [Ordnerstruktur von LumiScan AI Object Matching](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/folder-structure.html)).
2. Öffnen Sie den Ordner `lumiscan-ai-object-matching/schemas/flatbuffers`.
3. Klicken Sie in der Spalte **Actions** von `object_detection.fbs` auf das Download-Symbol und speichern Sie die Datei auf dem Engineering-PC.

Alternativ laden Sie die Datei über WebDAV herunter (siehe [Daten hochladen](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/uploading-data.html)).

> [!NOTE]
> Der Ordner `schemas` wird beim Start der Anwendung angelegt, nach der Lizenzprüfung. Existiert der Ordner nicht, ist die Anwendung nicht erfolgreich gestartet. Prüfen Sie, ob eine gültige Lizenz installiert ist, und lesen Sie das Systemprotokoll. Siehe [Der Ordner schemas existiert nicht](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/troubleshooting.html#faq-schemas-folder-missing).
>
> Die Anwendung löscht den Ordner `schemas` bei jedem Start und legt ihn neu an. Bearbeiten Sie keine Dateien in diesem Ordner; Änderungen gehen verloren. Das Schema passt immer zur installierten Version der Anwendung.

## Schritt 2: Schema in das SPS-Projekt importieren

1. Öffnen Sie in ctrlX PLC Engineering das SPS-Projekt.
2. Klicken Sie im Gerätebaum mit der rechten Maustaste auf **Application**.
3. Wählen Sie **Import from FlatBuffers file…**.
4. Wählen Sie die heruntergeladene Datei `object_detection.fbs`.

![Gerätebaum von ctrlX PLC Engineering mit dem geöffneten Kontextmenü von Application auf Import from FlatBuffers file](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/_images/plc-import-flatbuffers.png)

*Abbildung 1. Import from FlatBuffers file*

PLC Engineering fügt der Anwendung die folgenden Funktionsbausteine hinzu. Ihre Namen bestehen aus dem Schema-Namespace und dem Typnamen.

**Tabelle 2. Vom Import erzeugte Funktionsbausteine**

| Funktionsbaustein | Zweck |
| --- | --- |
| `hdv_object_detection2d_Result` | Wurzel der Nachricht. Liefert den besten Score und die beste Klasse sowie den Zugriff auf das Array der Instanzen. |
| `hdv_object_detection2d_Instance` | Ein erkanntes Objekt: Klassenindex, Score und Bounding Box. |
| `hdv_object_detection2d_OrientedBoundingBox` | Mittelpunkt, Größe und Winkel der Bounding Box einer Instanz. |
| `hdv_object_detection2d_InstanceTVec` | Zum Lesen der Ergebnisse nicht erforderlich (siehe [Bekannte Meldung: Identifier 'VectorT' not defined](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/accessing-flatbuffers-data.html#lumiscan-known-message-vectort)). |

### Bekannte Meldung: Identifier 'VectorT' not defined {#lumiscan-known-message-vectort}

Je nach Version von ctrlX PLC Engineering zeigt der Editor des Funktionsbausteins `hdv_object_detection2d_InstanceTVec` die Meldung `Identifier 'VectorT' not defined`. Die Meldung beeinträchtigt das Lesen der Ergebnisse nicht. Ursachen und Schritte sind unter [Fehlerbehebung](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/troubleshooting.html) beschrieben:

- [Nach dem Import erscheint die Meldung "Identifier 'VectorT' not defined"](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/troubleshooting.html#faq-vectort-not-defined)

### Die ctrlX-Data-Layer-Bibliothek installieren {#lumiscan-install-datalayer-library}

Ist **Import from FlatBuffers file…** im Kontextmenü nicht verfügbar, fehlt die ctrlX-Data-Layer-Bibliothek. Installieren Sie sie wie folgt und wiederholen Sie dann Schritt 2:

1. Wählen Sie in der Menüleiste von PLC Engineering **Tools** > **Library Repository…**.

![Menü Tools von ctrlX PLC Engineering mit hervorgehobenem Befehl Library Repository](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/_images/plc-install-datalayer-1.png)

*Abbildung 2. Befehl Library Repository*

2. Suchen Sie nach `CXA_Datalayer`, wählen Sie die Bibliothek aus und klicken Sie auf **Open**.

![Dialog Find Library mit dem Suchbegriff CXA_Datalayer und der ausgewählten Bibliothek CXA_Datalayer](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/_images/plc-install-datalayer-2.png)

*Abbildung 3. Suche nach der Bibliothek CXA_Datalayer*

## Schritt 3: Ergebnis im SPS-Programm lesen

1. Führen Sie eine Inferenz mit dem Handshake aus, der in [Inferenz starten](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/initializing-the-inference.html) beschrieben ist.
2. Warten Sie, bis die Inferenz abgeschlossen ist, und prüfen Sie, ob sie erfolgreich war: `inference/ready` ist wieder **True** und `output/package-identifier` ist um eins gestiegen. Bei `control/inference/execute` prüfen Sie stattdessen, ob `status/code` 0 ist.
3. Lesen Sie den Knoten `hdvisionsystems/lumiscan-ai-object-matching/<network name>/output/result` mit dem Funktionsbaustein `DL_ReadNodeValue` der Bibliothek `CXA_Datalayer`. Der Funktionsbaustein liefert den Wert in einem `DL_NodeValue`.
4. Übergeben Sie Adresse und Größe des Puffers (`GetData` und `GetSize` des `DL_NodeValue`) an `getRootAsResult` von `hdv_object_detection2d_Result`.
5. Lesen Sie die Felder des Ergebnisses mit den `get`-Methoden der erzeugten Funktionsbausteine.

> [!NOTE]
> Die erzeugten Funktionsbausteine lesen den empfangenen Puffer an Ort und Stelle; sie kopieren ihn nicht. Verwenden oder kopieren Sie die Werte, bevor der Knoten erneut gelesen wird.

## Beispiel: Position und Score einer Instanz lesen {#lumiscan-example-instance}

Das Array `instances` des Ergebnisses ist nach Score absteigend sortiert. Instanz 0 ist daher die Instanz mit dem höchsten Score. Das Beispiel liest die Position (x, y), den Score und den Klassenindex dieser Instanz.

Deklaration:

```text
PROGRAM PRG_ReadObjectMatchingResult
VAR
    // Data Layer access (CXA_Datalayer)
    fbReadResult : DL_ReadNodeValue;
    nvResult     : DL_NodeValue;    // receives the FlatBuffers buffer
    bRead        : BOOL;            // set to TRUE to read the node once
    sNode        : STRING(255) := 'hdvisionsystems/lumiscan-ai-object-matching/<network name>/output/result';

    // FlatBuffers readers, generated by "Import from FlatBuffers file..."
    fbResult     : hdv_object_detection2d_Result;
    fbInstance   : hdv_object_detection2d_Instance;
    pBox         : POINTER TO hdv_object_detection2d_OrientedBoundingBox;

    // Values of the instance with the highest score
    bFound       : BOOL;
    rX           : REAL;            // x of the bounding box center [pixel]
    rY           : REAL;            // y of the bounding box center [pixel]
    rScore       : REAL;            // score [0.0 - 1.0]
    uClassIndex  : ULINT;           // index into class-names
END_VAR
```

Implementierung:

```text
// 1. Read the node. A rising edge on bRead starts one read.
fbReadResult(Execute := bRead, NodeName := sNode, NodeValue := nvResult);

IF fbReadResult.Done THEN
    bFound := FALSE;

    IF nvResult.GetSize() > 0 THEN
        // 2. Point the generated reader at the received buffer.
        fbResult.getRootAsResult(data := nvResult.GetData(), size := nvResult.GetSize());

        // 3. The instances are sorted by score, so instance 0 has the highest score.
        IF fbResult.getInstancesLength() > 0 THEN
            IF fbResult.getInstances(j := 0, result := ADR(fbInstance)) THEN
                rScore      := fbInstance.GetScore();
                uClassIndex := fbInstance.GetClassIndex();

                // 4. The position is part of the bounding box.
                pBox := fbInstance.getOrientedBoundingBox();
                IF pBox <> 0 THEN
                    rX     := pBox^.GetCenterX();
                    rY     := pBox^.GetCenterY();
                    bFound := TRUE;
                END_IF
            END_IF
        END_IF
    END_IF
END_IF

// 5. End the access.
IF fbReadResult.Done OR fbReadResult.Error THEN
    bRead := FALSE;
    fbReadResult(Execute := bRead, NodeName := sNode, NodeValue := nvResult);
END_IF
```

Ersetzen Sie `<network name>` in `sNode` durch den Namen des Netzes. Setzen Sie `bRead` erst auf TRUE, nachdem die Inferenz abgeschlossen und erfolgreich war (siehe Schritt 3). Ist `fbReadResult.Error` TRUE, werten Sie `fbReadResult.ErrorID` und `fbReadResult.ErrorIdent` aus.

**Tabelle 3. Im Beispiel verwendete Methoden**

| Wert | Methode | Typ | Einheit oder Bereich |
| --- | --- | --- | --- |
| Anzahl der Instanzen | `fbResult.getInstancesLength()` | `UDINT` |   |
| Instanz nach Index | `fbResult.getInstances(j, result)` | `BOOL` | `TRUE`, wenn die Instanz existiert |
| Score | `fbInstance.GetScore()` | `REAL` | 0.0 bis 1.0 |
| Klassenindex | `fbInstance.GetClassIndex()` | `ULINT` | Index in `class-names` |
| Bounding Box | `fbInstance.getOrientedBoundingBox()` | `POINTER TO hdv_object_detection2d_OrientedBoundingBox` |   |
| x des Mittelpunkts | `pBox^.GetCenterX()` | `REAL` | Pixel |
| y des Mittelpunkts | `pBox^.GetCenterY()` | `REAL` | Pixel |

> [!NOTE]
> Die Sortierung nach Score ist das Verhalten der aktuellen Version. Das Schema erlaubt, dass die Sortierreihenfolge in einer künftigen Version konfigurierbar wird. `getBestIndex()` von `hdv_object_detection2d_Result` liefert immer den Index der Instanz mit dem höchsten Score; er ist 0, solange die Instanzen nach Score sortiert sind. Verwenden Sie ihn statt des festen Index 0, wenn das Programm unabhängig von der Sortierreihenfolge bleiben soll.

### Alle Instanzen lesen

Um alle Instanzen auszuwerten, durchlaufen Sie das Array in einer Schleife. Da die Instanzen nach Score sortiert sind, kann die Schleife bei der ersten Instanz unter einem Mindest-Score abbrechen. Das folgende Fragment ersetzt Schritt 3 der Implementierung. Es benötigt die zusätzlichen Deklarationen `i : UDINT;` und `rMinScore : REAL := 0.5;`.

```text
i := 0;
WHILE i < fbResult.getInstancesLength() DO
    IF fbResult.getInstances(j := i, result := ADR(fbInstance)) THEN
        rScore := fbInstance.GetScore();

        IF rScore < rMinScore THEN
            EXIT;   // sorted by score: no instance with a higher score follows
        END_IF

        pBox := fbInstance.getOrientedBoundingBox();
        IF pBox <> 0 THEN
            rX := pBox^.GetCenterX();
            rY := pBox^.GetCenterY();
            // Use or store the values of instance i here.
        END_IF
    END_IF
    i := i + 1;
END_WHILE
```

Verwenden Sie keine `FOR`-Schleife mit der vorzeichenlosen Anzahl (`FOR i := 0 TO count - 1`): Ist die Anzahl 0, läuft die Obergrenze auf den größten `UDINT`-Wert über.

## Aufbau des Ergebnisses

Die folgenden Tabellen beschreiben den Inhalt von `object_detection.fbs`. Die Schemadatei ist die maßgebliche Definition.

**Tabelle 4. Result (table, Root-Typ)**

| Feld | Typ | Beschreibung |
| --- | --- | --- |
| `instances` | `[Instance]` | Erkannte Objekte, nach Score absteigend sortiert (höchster Score zuerst). Das Array kann Objekte verschiedener Klassen enthalten; das SPS-Programm muss die benötigte Klasse auswählen (siehe [Klassennamen und Klassenfilter](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/accessing-flatbuffers-data.html#lumiscan-class-names-and-filters)). |
| `best_index` | `ulong` | Index der Instanz mit dem höchsten Score in `instances`. Immer 0, solange die Instanzen nach Score sortiert sind. |
| `best_score` | `float` | Score der besten Instanz, im Bereich 0.0 bis 1.0. |
| `best_class_index` | `ulong` | Klassenindex der besten Instanz. |
| `image_id` | `ulong` | Package Identifier des Eingabebilds, zu dem das Ergebnis gehört. In Versionen vor Oktober 2026 war es ein 16-Bit-`short`. |
| `image_name` | `string` | Nicht verwendet. |
| `requested_timestamp` | `ulong` | Zeitpunkt, zu dem die Anwendung den Inferenz-Request angenommen hat, den die SPS auf **True** gesetzt hatte. |
| `timestamp` | `ulong` | Zeitstempel des Eingabebilds. Typ und Auflösung hängen von der Zeitstempelquelle der Anwendung `lumiscan-cam-driver` ab, die das Bild geliefert hat. |
| `status` | `ulong` | Nicht verwendet. Prüfen Sie den Ausgang mit `status/code` (siehe [Statuscode-Werte](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/initializing-the-inference.html#status-code-values)). |

**Tabelle 5. Instance (struct)**

| Feld | Typ | Beschreibung |
| --- | --- | --- |
| `oriented_bounding_box` | `OrientedBoundingBox` | Position, Größe und Orientierung des erkannten Objekts im Bild. |
| `class_index` | `ulong` | Index der erkannten Klasse (siehe [Klassennamen und Klassenfilter](https://docs.hdvisionsystems.com/de/lumiscan-ai-object-matching-de/2.1.0/lumiscan-ai-object-matching/accessing-flatbuffers-data.html#lumiscan-class-names-and-filters)). |
| `score` | `float` | Score der Erkennung, im Bereich 0.0 bis 1.0. |

**Tabelle 6. OrientedBoundingBox (struct)**

| Feld | Typ | Einheit | Beschreibung |
| --- | --- | --- | --- |
| `center_x` | `float` | Pixel | Horizontale Position des Box-Mittelpunkts. |
| `center_y` | `float` | Pixel | Vertikale Position des Box-Mittelpunkts. |
| `width` | `float` | Pixel | Breite der Box. |
| `height` | `float` | Pixel | Höhe der Box. |
| `angle` | `float` | Grad | Orientierung der Box. Die aktuelle Implementierung kann negative Winkel liefern; gehen Sie nicht davon aus, dass der Wert auf den Bereich 0.0 bis 360.0 normiert ist. |

## Klassennamen und Klassenfilter {#lumiscan-class-names-and-filters}

Mit der Standard-Klassenzuordnung bezeichnet `class_index` eine Klasse über ihre Position im Array der Klassennamen, das für das Netz konfiguriert ist. Verwenden Sie die folgenden Knoten, um Klassen aufzulösen und einzuschränken:

> [!NOTE]
> Ist eine eigene Neuzuordnung der Klassenindizes konfiguriert, folgt der veröffentlichte Klassenindex dieser Zuordnung und kann von der Position in `setting/class-names` abweichen. Interpretieren Sie das Ergebnis anhand der konfigurierten Zuordnung.

**Tabelle 7. Knoten zu den Klassen**

| Adresse | Zugriff | Beschreibung |
| --- | --- | --- |
| `hdvisionsystems/lumiscan-ai-object-matching/<network name>/setting/class-names` | Schreibgeschützt | Klassennamen des Netzes. Mit der Standardzuordnung ist die Position eines Namens im Array sein Klassenindex. |
| `hdvisionsystems/lumiscan-ai-object-matching/<network name>/input/class-filters` | Beschreibbar | Klassennamen, die in das Ergebnis aufgenommen werden. Lassen Sie das Array leer, um die Filterung zu deaktivieren. |

## Anwendung aktualisieren

Laden Sie nach einem Update der Anwendung das Schema erneut herunter und importieren Sie es erneut in das SPS-Projekt, damit das SPS-Programm das Schema der installierten Version verwendet.
