Greetings, fellow robotics enthusiasts!
I’ve spent the past months at work writing multiple microcontroller programs that have to exchange status and configuration data with ROS 2 nodes on the host system.
After writing custom serialization code for the first one – a reverse-engineered motor controller running on a Teensy 4.0 for the Unitree A1 motors powering our tracked robot, I thought there must be a better way.
But I couldn’t find one - although there probably is one that neither Perplexity nor I could find - that fit my needs (simple, no extra tooling, quick to change)…
So I made my own and released it on GitHub ![]()
Crosstalk is a MIT-licensed header-only C++17 library based on the refl-cpp (also MIT-licensed) library.
What does it do?
Using crosstalk, you can register your data structures once with refl-cpp and a custom ID property that has to be unique.
Example:
struct MyData {
std::string name;
float measurement;
uint32_t timestamp; // Make sure to use types with fixed size! Avoid: int, long, etc.
};
// The id needs to be unique for each type you want to serialize.
REFL_AUTO(type(MyData, crosstalk::id(1)),
field(name), field(measurement), field(timestamp))
Afterwards, you can just send the data structs from and to the microcontroller using e.g. USB serial, and crosstalk will handle the serialization and error checking.
You can even keep your serial logging, as crosstalk will automatically identify the parts of the serial stream that are crosstalk exchanged objects. (Full Example in README)
No need for any libraries or custom-generated code. Just one header for crosstalk and one for the serial abstraction (provided are abstractions for Teensy, STM32, and ESP32 using PlatformIO).
As always, I hope this is useful to you, and feel free to shoot me a message if you do something cool with it ![]()
If not, here’s a picture of our future supreme robot overlord to make up for your lost time:
PS: I know there’s micro ros2, but it’s complicated to set up, and I want middleware agnostic communication so the ROS 2 host node can just do the communication (and the middleware can be changed without breaking the microcontroller interface).
