Datenserialisierungs-Toolchain für Computer und eingebettete Systeme mit C++- oder MATLAB-Unterstützung
microbuf
verwenden?Sie können es verwenden, wenn Sie vorhaben, eine Schnittstelle zwischen Geräten zu erstellen, auf denen eine C++-Anwendung ausgeführt wird (ein Computer oder ein eingebettetes System) und/oder Geräten, auf denen (möglicherweise kompilierter) MATLAB-Code ausgeführt wird (Simulink auf PC oder eingebetteten Systemen). Ein möglicher Anwendungsfall wäre „Steuerdaten vom Computer über UDP an eingebettetes System senden“. Die derzeit unterstützten Sprachen sind C++ und MATLAB, sowohl für die Serialisierung als auch für die Deserialisierung (Tx+Rx). Dies ermöglicht es beispielsweise, Daten von einem ROS-Knoten an eine dSPACE MicroAutoBox, von einem Arduino an eine Simulink-Simulation auf einem PC zu senden oder Daten zwischen mehreren Arduinos auszutauschen – ohne den Schnittstellencode Byte für Byte zu schreiben oder sich um Dinge wie diese zu kümmern Endianness. Die Unterstützung weiterer Sprachen kann mit vertretbarem Aufwand hinzugefügt werden.
protobuf
/ JSON
/ matlab-msgpack
/... verwenden? Die Verwendung eines anderen Frameworks mit mehr Funktionen wie Protobuf kann in vielen Fällen tatsächlich sinnvoll sein. microbuf
ist für Anwendungsfälle mit starken Einschränkungen gedacht, z. B. eingebettete Systeme oder ähnliche Umgebungen mit einer eingeschränkten Toolchain. microbuf
ist nicht auf externe Bibliotheken (oder sogar auf Funktionen im C++ std
-Namespace) angewiesen und eine Kompilierung nur mit Standard-Sprachtools ist möglich.
matlab-msgpack von bastibe kann mit dem Simulink/MATLAB-Codierer nicht in C-Code kompiliert werden.
Die folgenden Datentypen werden derzeit unterstützt:
bool
uint8
, uint16
, uint32
und uint64
float32
, float64
Sprache | Serialisierung | Deserialisierung | CRC-Unterstützung | Beispiele | Notizen |
---|---|---|---|---|---|
C++ | ✔ | ✔ | ✔ | ROS-Knoten; C++-Anwendung; Arduino-Skizze | |
MATLAB | ✔ | ✔ | ✔ | dSPACE MicroAutoBox; Simulink-Simulation | Verwendbar in Simulink; kompiliert mit Simulink/MATLAB Coder |
... | ✘ | ✘ | ✘ | Bitte öffnen Sie eine Funktionsanfrage oder PR für neue Zielsprachen |
microbuf
verwendet Nachrichtenbeschreibungsdateien mit der Endung .mmsg
, um die Struktur von Nachrichten zu beschreiben, ähnlich wie ROS. mmsg
Dateien müssen einer bestimmten Struktur folgen und gültiges YAML
sein. Das folgende Beispiel kann als SensorData.mmsg
gespeichert und dann als microbuf
-Nachricht verwendet werden:
version : 1
append_checksum : yes
content :
distance : float32[10]
angle : float32[10]
robot_id : uint8
Weitere Beispiele finden Sie unter test/messages/.
Wenn Sie nun ./microbuf.py SensorData.mmsg
ausführen, werden automatisch Serialisierer und Deserialisierer für die unterstützten Sprachen generiert. Mit den Serialisierern können Sie Daten in Bytes umwandeln, an Ihren Empfänger senden (z. B. über UDP oder I2C) und dort mit den Deserialisierern dekodieren.
Die Serialisierung von microbuf
basiert auf der MessagePack-Spezifikation. Alle Datenelemente werden in ein flaches Array gepackt und optional wird eine CRC16-Prüfsumme angehängt.
git clone https://github.com/nspo/microbuf.git
cd microbuf
pyyaml
) installiert sind:sudo apt install python3-yaml
pip
: pip3 install -r requirements.txt
microbuf
mit der Beispielnachricht aus: ./microbuf.py SensorData.mmsg
git submodule update --init --recursive
Angenommen, Sie möchten die oben erwähnte Nachricht SensorData.mmsg
von einem Computer (unter Verwendung von C++) an eine Simulink-Simulation senden. microbuf
generiert eine Header-Datei SensorData.h
, die Sie in Ihren C++-Code einbinden können. Diese Nachrichten-Header-Datei benötigt Zugriff auf die Header-Datei microbuf.h
. Kopieren Sie also einfach beide Dateien in denselben Ordner, in dem Ihr Compiler sie findet, oder passen Sie Ihre CMakeLists.txt
an. Anschließend können Sie die Struktur SensorData_struct_t
in C++ verwenden, um Ihre Daten einzugeben und in einen Byte-Vektor umzuwandeln, z. B. so:
SensorData_struct_t sensor_data {};
// fill example data into SensorData msg
for ( size_t i= 0 ; i< 10 ; ++i)
{
sensor_data. distance [i] = 2.5 * static_cast < float >(i);
sensor_data. angle [i] = 4.2 * static_cast < float >(i);
}
sensor_data.robot_id = 42U ;
const auto bytes = sensor_data.as_bytes(); // convert to bytes
bytes
müssen nun irgendwie an das Empfängersystem gesendet werden, z. B. über UDP. Der examples
enthält ein Beispiel, wie man es machen könnte.
Die Simulink-Simulation kann für den Empfang der serialisierten Bytes konfiguriert werden. Dies kann beispielsweise mit dem UDP-Receive-Block aus der DSP System Toolbox erreicht werden. Durch Hinzufügen der Datei deserialize_SensorData.m
, die microbuf
generiert hat, zum Simulink-Modell können Sie die empfangenen Daten dann einfach deserialisieren:
Beachten Sie, dass sich zum Simulieren oder Kompilieren eines solchen Modells der matlab
Ordner von microbuf
in Ihrem MATLAB-Pfad befinden muss, da er die erforderliche Funktionalität enthält, die nicht in deserialize_SensorData.m
enthalten ist. Sie können den enthaltenen +microbuf
-Ordner natürlich auch einfach an eine Stelle in Ihrem Projekt kopieren, die ohnehin auf Ihrem MATLAB-Pfad liegt.
Der examples
enthält auch das vollständige Simulink-Modell. In derselben Datei finden Sie auch ein auskommentiertes Beispiel für die Verwendung von MATLAB zur Serialisierung von Daten.
Für dieses Beispiel müssen im Großen und Ganzen die gleichen Dinge getan werden wie für das vorherige. Der Code kann größtenteils wiederverwendet werden. Sie müssen den notwendigen C++-Code in Ihren ROS-Knoten einbinden und darüber nachdenken, wann Sie eine Nachricht an die MicroAutoBox senden möchten (z. B. mit welcher Rate).
Auf der MicroAutoBox-Seite können Sie nicht denselben UDP-Empfangsblock verwenden, da Sie einen hardwarespezifischen Block benötigen. Ein ähnlicher UDP-Empfangsblock ist jedoch im RTI Ethernet (UDP) Blockset enthalten, sodass Sie diesen stattdessen verwenden können. Beachten Sie, dass die maximale Nutzlast von UDP-Paketen für dieses Blockset laut Dokumentation 1472 Byte beträgt. Die Deserialisierungsfunktion kann wie im vorherigen Beispiel eingebunden werden und wird automatisch in C-Code kompiliert.
Die von microbuf
generierten Header können problemlos in eine Arduino-Skizze eingefügt werden. Der Code wird kompiliert, da er keine Funktionalität aus dem std
-Namespace erfordert. Möglicherweise hängt es von Ihrer spezifischen Arduino-Hardware ab. float64
Daten können auf dem Arduino wahrscheinlich nicht serialisiert werden, da double
-S möglicherweise nur 32 Bit haben. Bei Verwendung der Wire (I2C)-Bibliothek können nur 32 Bytes in einem Schritt übertragen werden.
Ein Beispiel für das Senden von Daten von einem Arduino zu einem anderen über I2C finden Sie hier.
microbuf
kennt die erforderliche Anzahl an Bytes, siehe zB die Konstante data_size
der generierten C++-Struktur. Bekannte Grenzen: