适用于支持 C++ 或 MATLAB 的计算机和嵌入式系统的数据序列化工具链
microbuf
?如果您计划在运行 C++ 应用程序(计算机或嵌入式系统)的设备和/或运行(可能编译的)MATLAB 代码(PC 或嵌入式系统上的 Simulink)的设备之间创建接口,您可能需要使用它。一种可能的用例是“通过 UDP 将控制数据从计算机发送到嵌入式系统”。当前支持的语言是 C++ 和 MATLAB,用于序列化和反序列化 (Tx+Rx)。这样就可以将数据从 ROS 节点发送到 dSPACE MicroAutoBox,从 Arduino 发送到 PC 上的 Simulink 仿真,或者在多个 Arduino 之间交换数据 - 无需逐字节编写接口代码或担心诸如此类的事情字节序。通过合理的努力可以添加对更多语言的支持。
protobuf
/ JSON
/ matlab-msgpack
/...?在许多情况下,使用另一个具有更多功能(例如 protobuf)的框架确实是有意义的。 microbuf
适用于具有严格限制的用例,例如嵌入式系统或具有受限工具链的类似环境。 microbuf
不依赖于外部库(甚至 C++ std
命名空间中的功能),并且可以仅使用标准语言工具进行编译。
bastibe 的 matlab-msgpack 无法使用 Simulink/MATLAB 编码器编译为 C 代码。
目前支持以下数据类型:
bool
uint8
、 uint16
、 uint32
和uint64
float32
、 float64
语言 | 序列化 | 反序列化 | CRC 支持 | 示例 | 笔记 |
---|---|---|---|---|---|
C++ | ✔ | ✔ | ✔ | ROS节点; C++应用程序; Arduino草图 | |
MATLAB | ✔ | ✔ | ✔ | dSPACE MicroAutoBox; Simulink 仿真 | 可在 Simulink 中使用;使用 Simulink/MATLAB Coder 进行编译 |
... | ✘ | ✘ | ✘ | 请针对新的目标语言提出功能请求或 PR |
microbuf
使用以.mmsg
结尾的消息描述文件来描述消息的结构,与 ROS 不同。 mmsg
文件需要遵循特定的结构并且必须是有效的YAML
。以下示例可以保存为SensorData.mmsg
,然后用作microbuf
消息:
version : 1
append_checksum : yes
content :
distance : float32[10]
angle : float32[10]
robot_id : uint8
更多示例可以在 test/messages/ 下找到。
当您现在执行./microbuf.py SensorData.mmsg
时,将自动生成支持语言的序列化器和反序列化器。您可以使用串行器将数据转换为字节,将它们发送到接收器(例如通过UDP 或I2C),然后使用解串器对其进行解码。
microbuf
的序列化基于 MessagePack 规范。所有数据元素都打包到平面数组中,并附加可选的 CRC16 校验和。
git clone https://github.com/nspo/microbuf.git
cd microbuf
pyyaml
):sudo apt install python3-yaml
pip
: pip3 install -r requirements.txt
microbuf
示例消息: ./microbuf.py SensorData.mmsg
git submodule update --init --recursive
假设您要将上述消息SensorData.mmsg
从计算机(使用 C++)发送到 Simulink 仿真。 microbuf
将生成一个头文件SensorData.h
,您可以将其包含在 C++ 代码中。此消息头文件需要访问microbuf.h
头文件,因此只需将这两个文件复制到编译器将找到它们或调整CMakeLists.txt
的同一文件夹即可。然后,您可以使用 C++ 中的 struct SensorData_struct_t
填充数据并将其转换为字节向量,例如:
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
发送到接收系统,例如通过UDP。 examples
文件夹包含一个如何做到这一点的示例。
Simulink 仿真可以配置为接收序列化字节。这可以通过 DSP System Toolbox 中的 UDP 接收模块来实现。通过将microbuf
生成的文件deserialize_SensorData.m
添加到 Simulink 模型中,您可以轻松地反序列化接收到的数据:
请注意,为了模拟或编译此类模型, microbuf
的matlab
文件夹需要位于 MATLAB 路径上,因为它包含deserialize_SensorData.m
中未包含的必要功能。当然,您也可以将包含的+microbuf
文件夹复制到项目中位于 MATLAB 路径上的位置。
examples
文件夹还包含完整的 Simulink 模型。在同一文件中,您还会发现一个使用 MATLAB 序列化数据的注释掉示例。
此示例需要执行的操作与前一个示例基本相同。代码大部分可以重用。您需要在 ROS 节点中包含必要的 C++ 代码,并考虑何时要向 MicroAutoBox 发送消息(例如以何种速率)。
在 MicroAutoBox 一侧,您不能使用相同的 UDP 接收块,因为您需要一个特定于硬件的接收块。不过,RTI 以太网 (UDP) 模块集中包含类似的 UDP 接收模块,因此您可以改用该模块。请注意,根据文档,此块集的 UDP 数据包的最大有效负载为 1472 字节。反序列化函数可以像前面的示例一样包含在内,并将自动编译为 C 代码。
microbuf
生成的标头可以轻松包含在 Arduino 草图中。该代码可以编译,因为它不需要std
命名空间中的功能。可能取决于您特定的 Arduino 硬件, float64
数据可能无法在 Arduino 上序列化,因为double
可能只有 32 位。使用Wire(I2C)库时,一步只能传输32个字节。
可以在此处找到通过 I2C 从一个 Arduino 向另一个 Arduino 发送数据的示例。
microbuf
知道所需的字节数,请参见生成的 C++ 结构体的常量data_size
。已知限制: