ROS Resources: Documentation | Support | Discussion Forum | Service Status | Q&A answers.ros.org

ROS 2 type support introspection and conversion of C/C++ messages to/from YAML

This post is a follow-up to this previous post/comment about message introspection and conversion into a YAML representation using this repo: GitHub - osrf/dynamic_message_introspection

I’ve added support for C++ messages to go along support for C messages, made the message<–>YAML conversion symmetrical, and did a bunch of refactoring. The code for this is on a branch on my fork: GitHub - christophebedard/dynamic_message_introspection at add-cpp-support-and-refactor

In short, it allows you to convert a C or C++ message, like this std_msgs/Header message:

std_msgs::msg::Header msg;
msg.frame_id = "my_frame";
builtin_interfaces::msg::Time stamp;
stamp.sec = 4;
stamp.nanosec = 20U;
msg.stamp = stamp;

into a YAML representation, which can be converted to string:

stamp:
  sec: 4
  nanosec: 20
frame_id: my_frame

That string can be parsed as a YAML object and then converted back to a std_msgs/Header message that will be equivalent to the original one!

Note that you could do the first part using std_msgs::msg::to_yaml(const Header & msg). However, that doesn’t use type support introspection, and again it only does the conversion to YAML and not the other way. rosidl_runtime_py can do the conversion from YAML (e.g., for ros2 topic pub), but it’s in Python.

Even starting from the implementation for C messages, writing the introspection code for C++ messages was a nice challenge. I’m sure some things could be improved, and I might have done some things wrong (although it works :tm:). It could nonetheless serve as another example of how to do type support introspection! :robot:

6 Likes

Cool!

Is that a typo (hopefully), should be std_msgs::to_yaml()?

1 Like

Oops yes it’s a typo! It should be std_msgs::msg::to_yaml(); I fixed it, thank you!

thanks for the awesome information.

This is great!

I just started using asyncapi to document ROS2, and then the converted messages for MQTT also.

Would you be interested in letting me contribute to convert from your yaml representation into asyncapi yaml?

My interest is to make a way to, given a ROS2 .msg, generate the asyncapi yaml specification for the messages.

Asyncapi supports code generation for many other languages, so if this is accomplished, this could allow people to re-use the ROS2 message definitions in many other languages.

Feel free to fork my fork and give it a try!

As for AsyncAPI, unless I misunderstand your goal, I don’t think this project is what you want. This turns a message instance (with values) into YAML at runtime. However, you want to turn the message definition/structure (.idl/.msg file) into an AsyncAPI YAML spec, correct? You might want to look into parsing .idl files directly or trying to rely on some of the existing tools, like rosidl_parser (and the other rosidl* packages).

Got it. Seems to not be the right tool for the job. We are using asyncAPI to generate source code to convert between the messages from ROS2 representations into JSON for MQTT, but supports all our custom messages too.

I’ll check out the rosidl_parser.

The biggest issue I have right now is the conversion that ROS2 does to go from msg files into idl loses all the documentation because documentation is just comments in msg with no official guidelines. I don’t think there is any way to fix that other than flipping the way ROS2 genenerates their messages, by starting from IDL and the IDL is the source of truth; it at least supports @annotations.

Theoretically, we could pass along the comments from the .msg files into the .idl as annotations. There are some design decisions to be made there, but I don’t think the problem is insurmountable.