Chaîne d'outils de sérialisation de données pour ordinateurs et systèmes embarqués avec prise en charge C++ ou MATLAB
microbuf
?Vous souhaiterez peut-être l'utiliser si vous envisagez de créer une interface entre des appareils exécutant une application C++ (un ordinateur ou un système embarqué) et/ou des appareils exécutant (éventuellement compilé) du code MATLAB (Simulink sur PC ou systèmes embarqués). Un cas d'utilisation possible serait "Envoyer les données de contrôle de l'ordinateur via UDP au système embarqué". Les langages actuellement pris en charge sont C++ et MATLAB, pour la sérialisation et la désérialisation (Tx+Rx). Cela permet par exemple d'envoyer des données d'un nœud ROS à une MicroAutoBox dSPACE, d'un Arduino à une simulation Simulink sur un PC, ou d'échanger des données entre plusieurs Arduinos - sans écrire le code d'interface octet par octet ni se soucier de choses comme endianité. La prise en charge de plusieurs langues peut être ajoutée avec un effort raisonnable.
protobuf
/ JSON
/ matlab-msgpack
/... ? Utiliser un autre framework avec plus de fonctionnalités comme protobuf peut en effet avoir du sens dans de nombreux cas. microbuf
est destiné à des cas d'utilisation avec de fortes limitations, par exemple des systèmes embarqués ou des environnements similaires avec une chaîne d'outils contrainte. microbuf
ne dépend pas de bibliothèques externes (ni même de fonctionnalités de l'espace de noms std
C++) et une compilation utilisant uniquement des outils de langage standard est possible.
matlab-msgpack de bastibe ne peut pas être compilé en code C avec le codeur Simulink/MATLAB.
Les types de données suivants sont actuellement pris en charge :
bool
uint8
, uint16
, uint32
et uint64
float32
, float64
Langue | Sérialisation | Désérialisation | Prise en charge du CRC | Exemples | Remarques |
---|---|---|---|---|---|
C++ | ✔ | ✔ | ✔ | Nœud ROS ; Applications C++ ; Croquis Arduino | |
MATLAB | ✔ | ✔ | ✔ | dSPACE MicroAutoBox ; Simulation Simulink | Utilisable dans Simulink ; compile avec Simulink/MATLAB Coder |
... | ✘ | ✘ | ✘ | Veuillez ouvrir une demande de fonctionnalité ou un PR pour de nouvelles langues cibles |
microbuf
utilise des fichiers de description de message se terminant par .mmsg
pour décrire la structure des messages, un peu comme ROS. Les fichiers mmsg
doivent suivre une structure spécifique et doivent être YAML
valides. L'exemple suivant peut être enregistré sous SensorData.mmsg
puis être utilisé comme message microbuf
:
version : 1
append_checksum : yes
content :
distance : float32[10]
angle : float32[10]
robot_id : uint8
D'autres exemples peuvent être trouvés sous test/messages/.
Lorsque vous exécutez maintenant ./microbuf.py SensorData.mmsg
, les sérialiseurs et désérialiseurs pour les langues prises en charge seront automatiquement générés. Vous pouvez utiliser les sérialiseurs pour convertir les données en octets, les envoyer à votre récepteur (par exemple via UDP ou I2C) et les décoder là-bas avec les désérialiseurs.
La sérialisation de microbuf
est basée sur la spécification MessagePack. Tous les éléments de données sont regroupés dans un tableau plat et une somme de contrôle CRC16 facultative est ajoutée.
git clone https://github.com/nspo/microbuf.git
cd microbuf
pyyaml
au moment de la rédaction) est installée :sudo apt install python3-yaml
pip
: pip3 install -r requirements.txt
microbuf
avec l'exemple de message : ./microbuf.py SensorData.mmsg
git submodule update --init --recursive
Supposons que vous souhaitiez envoyer le message SensorData.mmsg
mentionné ci-dessus depuis un ordinateur (en utilisant C++) vers une simulation Simulink. microbuf
générera un fichier d'en-tête SensorData.h
que vous pourrez inclure dans votre code C++. Ce fichier d'en-tête de message doit accéder au fichier d'en-tête microbuf.h
, copiez donc simplement les deux fichiers dans le même dossier où votre compilateur les trouvera ou adaptez votre CMakeLists.txt
. Vous pouvez ensuite utiliser la struct SensorData_struct_t
en C++ pour remplir vos données et les convertir en vecteur d'octets, par exemple comme ceci :
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
doivent maintenant être envoyés au système récepteur d'une manière ou d'une autre, par exemple via UDP. Le dossier examples
contient un exemple de la manière dont on pourrait procéder.
La simulation Simulink peut être configurée pour recevoir les octets sérialisés. Ceci peut être réalisé par exemple avec le bloc de réception UDP de la boîte à outils système DSP. En ajoutant le fichier deserialize_SensorData.m
généré par microbuf
au modèle Simulink, vous pouvez alors facilement désérialiser les données reçues :
Notez que pour simuler ou compiler un tel modèle, le dossier matlab
de microbuf
doit se trouver sur votre chemin MATLAB car il contient les fonctionnalités nécessaires qui ne sont pas incluses dans deserialize_SensorData.m
. Vous pouvez bien sûr également simplement copier le dossier +microbuf
contenu à un endroit de votre projet qui se trouve de toute façon sur votre chemin MATLAB.
Le dossier examples
contient également le modèle Simulink complet. Dans le même fichier, vous trouverez également un exemple commenté utilisant MATLAB pour sérialiser des données.
Il faut faire en grande partie les mêmes choses pour cet exemple que pour le précédent. Le code peut en grande partie être réutilisé. Vous devez inclure le code C++ nécessaire dans votre nœud ROS et réfléchir au moment où vous souhaitez envoyer un message à la MicroAutoBox (par exemple à quel débit).
Du côté de MicroAutoBox, vous ne pouvez pas utiliser le même bloc de réception UDP car vous en avez besoin d'un spécifique au matériel. Un bloc de réception UDP similaire est cependant inclus dans le Blockset RTI Ethernet (UDP), vous pouvez donc l'utiliser à la place. Notez que la charge utile maximale des paquets UDP pour cet ensemble de blocs est de 1 472 octets, selon la documentation. La fonction de désérialisation peut être incluse comme dans l'exemple précédent et sera automatiquement compilée en code C.
Les en-têtes générés microbuf
peuvent facilement être inclus dans un croquis Arduino. Le code se compile car il ne nécessite pas de fonctionnalités de l'espace de noms std
. Cela dépend peut-être de votre matériel Arduino spécifique, les données float64
ne peuvent probablement pas être sérialisées sur l'Arduino car double
ne peuvent avoir que 32 bits. Lors de l'utilisation de la bibliothèque Wire (I2C), seuls 32 octets peuvent être transmis en une seule étape.
Un exemple d'envoi de données d'un Arduino à un autre via I2C peut être trouvé ici.
microbuf
connaît le nombre d'octets requis, voir par exemple la constante data_size
de la structure C++ générée. Limites connues :