Conjunto de ferramentas de serialização de dados para computadores e sistemas embarcados com suporte C++ ou MATLAB
microbuf
?Você pode querer usá-lo se planeja criar uma interface entre dispositivos que executam um aplicativo C++ (um computador ou sistema embarcado) e/ou dispositivos que executam código MATLAB (possivelmente compilado) (Simulink em PC ou sistemas embarcados). Um possível caso de uso seria "Enviar dados de controle do computador por UDP para o sistema embarcado". As linguagens atualmente suportadas são C++ e MATLAB, tanto para serialização quanto para desserialização (Tx+Rx). Isso torna possível, por exemplo, enviar dados de um nó ROS para um dSPACE MicroAutoBox, de um Arduino para uma simulação Simulink em um PC ou trocar dados entre vários Arduinos - sem escrever o código da interface byte por byte ou se preocupar com coisas como endianismo. O suporte para mais idiomas pode ser adicionado com esforço razoável.
protobuf
/ JSON
/ matlab-msgpack
/...? Usar outra estrutura com mais recursos como o protobuf pode realmente fazer sentido em muitos casos. microbuf
destina-se a casos de uso com fortes limitações, por exemplo, sistemas embarcados ou ambientes semelhantes com um conjunto de ferramentas restrito. microbuf
não depende de bibliotecas externas (ou mesmo de funcionalidade no namespace C++ std
) e é possível uma compilação usando apenas ferramentas de linguagem padrão.
matlab-msgpack por bastibe não pode ser compilado para código C com o codificador Simulink/MATLAB.
Os seguintes tipos de dados são atualmente suportados:
bool
uint8
, uint16
, uint32
e uint64
float32
, float64
Linguagem | Serialização | Desserialização | Suporte CRC | Exemplos | Notas |
---|---|---|---|---|---|
C++ | ✔ | ✔ | ✔ | Nó ROS; Aplicação C++; Esboço do Arduino | |
MATLAB | ✔ | ✔ | ✔ | dSPACE MicroAutoBox; Simulação Simulink | Utilizável em Simulink; compila com codificador Simulink/MATLAB |
... | ✘ | ✘ | ✘ | Abra uma solicitação de recurso ou PR para novos idiomas de destino |
microbuf
usa arquivos de descrição de mensagens que terminam em .mmsg
para descrever a estrutura das mensagens, não muito diferente do ROS. Os arquivos mmsg
precisam seguir uma estrutura específica e devem ser YAML
válidos. O exemplo a seguir pode ser salvo como SensorData.mmsg
e depois usado como uma mensagem microbuf
:
version : 1
append_checksum : yes
content :
distance : float32[10]
angle : float32[10]
robot_id : uint8
Mais exemplos podem ser encontrados em test/messages/.
Quando você executar agora ./microbuf.py SensorData.mmsg
, serializadores e desserializadores para os idiomas suportados serão gerados automaticamente. Você pode usar os serializadores para converter dados em bytes, enviá-los para o seu receptor (por exemplo, via UDP ou I2C) e decodificá-los lá com os desserializadores.
A serialização de microbuf
é baseada na especificação MessagePack. Todos os elementos de dados são compactados em uma matriz simples e uma soma de verificação CRC16 opcional é anexada.
git clone https://github.com/nspo/microbuf.git
cd microbuf
pyyaml
no momento da escrita) estejam instalados:sudo apt install python3-yaml
pip
: pip3 install -r requirements.txt
microbuf
com a mensagem de exemplo: ./microbuf.py SensorData.mmsg
git submodule update --init --recursive
Suponha que você queira enviar a mensagem SensorData.mmsg
mencionada acima de um computador (usando C++) para uma simulação Simulink. microbuf
irá gerar um arquivo de cabeçalho SensorData.h
que você pode incluir em seu código C++. Este arquivo de cabeçalho de mensagem precisa de acesso ao arquivo de cabeçalho microbuf.h
, então basta copiar os dois arquivos para a mesma pasta onde seu compilador irá encontrá-los ou adaptar seu CMakeLists.txt
. Você pode então usar a estrutura SensorData_struct_t
em C++ para preencher seus dados e convertê-los em um vetor de bytes, por exemplo, assim:
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
agora precisam ser enviados ao sistema receptor de alguma forma, por exemplo, via UDP. A pasta examples
contém um exemplo de como fazer isso.
A simulação Simulink pode ser configurada para receber os bytes serializados. Isto pode ser conseguido, por exemplo, com o bloco UDP Receive da caixa de ferramentas do sistema DSP. Ao adicionar o arquivo deserialize_SensorData.m
que microbuf
gerou ao modelo Simulink, você pode desserializar facilmente os dados recebidos:
Observe que para simular ou compilar tal modelo, a pasta matlab
do microbuf
precisa estar no caminho do MATLAB porque contém a funcionalidade necessária que não está incluída em deserialize_SensorData.m
. É claro que você também pode simplesmente copiar a pasta +microbuf
contida para um local do seu projeto que esteja no caminho do MATLAB de qualquer maneira.
A pasta examples
também contém o modelo Simulink completo. No mesmo arquivo você também encontrará um exemplo comentado usando MATLAB para serializar dados.
Em grande parte, as mesmas coisas precisam ser feitas neste exemplo e no anterior. O código pode ser reutilizado principalmente. Você precisa incluir o código C++ necessário em seu nó ROS e pensar em quando deseja enviar uma mensagem para o MicroAutoBox (por exemplo, com que taxa).
No lado do MicroAutoBox, você não pode usar o mesmo bloco de recebimento UDP porque precisa de um bloco específico de hardware. Um bloco de recebimento UDP semelhante está incluído no conjunto de blocos RTI Ethernet (UDP), portanto, você pode usá-lo. Observe que a carga máxima de pacotes UDP para este conjunto de blocos é de 1.472 bytes, de acordo com a documentação. A função de desserialização pode ser incluída como no exemplo anterior e será compilada para código C automaticamente.
Os cabeçalhos gerados microbuf
podem ser facilmente incluídos em um esboço do Arduino. O código é compilado porque não requer funcionalidade do namespace std
. Possivelmente dependendo do hardware específico do seu Arduino, os dados float64
provavelmente não podem ser serializados no Arduino, pois double
s podem ter apenas 32 bits. Ao usar a biblioteca Wire (I2C), apenas 32 bytes podem ser transmitidos em uma etapa.
Um exemplo de envio de dados de um Arduino para outro via I2C pode ser encontrado aqui.
microbuf
conhece o número necessário de bytes, veja, por exemplo, a constante data_size
da estrutura C++ gerada. Limites conhecidos: