@foxglove/rosmsg: ROS1 and ROS2 message definition parsing TypeScript library

https://github.com/foxglove/rosmsg

@foxglove/rosmsg is a library written in TypeScript and published to npm (so it can be used in any TypeScript or JavaScript project) that parses ROS1 and ROS2 message definitions into a structured representation and can convert this representation back into a canonical message definition. This library evolved out of the native ROS support in Foxglove and has graduated to a standalone library. The primary use case is pairing with other libraries that handle serialization and deserialization for ROS1/ROS2 data formats, but it could be useful on its own to create validation tools for .msg files or as a reference for formal grammars describing the two message definition languages.

The published library is a single self-contained JavaScript file that can run in a browser or Node.js environments.

4 Likes

Hi John, this is great. Thanks for sharing. Have you had a chance to compare it to the two message parsing approaches included in rosnodejs, gennodejs and “on-the-fly”? I’d be curious to see how it compares in terms of serializing/deserializing large messages such as video or point cloud messages. Have you run any such tests? Or is this literally only for parsing the message definition without actually generating JS classes that can do the (de)serialization?

Thanks @chfritz! To answer your question, this library is the latter. It does not do any code generation or (de)serialization, but it can be used as a building block to create that type of functionality. For Foxglove specifically, we are focused on “on-the-fly” serde and message parsing since our visualization tool connects to whatever data source or live robot you throw at it and we don’t know your topic datatypes ahead of time. But by building each component as a standalone library like this I hope we can support lots of different use cases under the robotwebtools umbrella.

2 Likes

Would it make sense to try and unify those code bases, the two in rosnodejs and yours? Chris, formerly at Rethink Robotics, now at Ready Robotics, has already done a great job merging parts of the two parsing + serialization approaches in rosnodejs. It might be more bang for the buck for open-source if we tried to all use the same code/package.

If we want to go that route then the logical next question is: which one should we start with and standardize on? Was there a reason you decided to write your own rather than trying to extract the relevant classes from rosnodejs – was there something missing? I’m not trying to imply any criticism of that decision here, just trying to find ways to compare these options. One thing that, I think, the rosnodejs code has going for it is that it has been “battle tested” by companies having used it in production for a few years by now.

@chfritz it’s a good question, I will make a note to add a section in the README addressing how this differs from rosnodejs. Here are the highlights:

  • @foxglove/rosmsg supports both ROS1 and ROS2 message definition parsing while sharing a common type system for both. This makes it possible to use libraries like https://github.com/foxglove/studio/tree/main/packages/rosmsg-msgs-common in both ROS1 and ROS2 environments. rosnodejs is only targeting ROS1 support. For ROS2, developers are directed to rclnodejs which is a node.js wrapper around native code, it won’t run in a browser environment.
  • @foxglove/rosmsg serves one purpose without adding additional dependencies or specific workflows. rosnodejs message definition parsing is embedded in code that is intended for code generation. It could be extracted out into a class or library that only handles message definitions without the code generation, which narrows the question down to whether you use a refactored version of the existing parsing code or start fresh.
  • @foxglove/rosmsg uses a parser grammar for both IDLs, and is written in TypeScript.

While it’s feasible to parse ROS1 without writing a grammar (see rosnodejs/MessageSpec.js at kinetic-devel · RethinkRobotics-opensource/rosnodejs · GitHub), the difficulty goes up quite a bit for ROS2 message definitions which support default values. And using TypeScript I hope will make it possible for more people to co-author a single codebase. The lack of type information in JavaScript means you need to study each part of a codebase fairly exhaustively before you can understand the flow of data types. Take the Field class at https://github.com/RethinkRobotics-opensource/rosnodejs/blob/kinetic-devel/src/utils/messageGeneration/MessageSpec.js#L80 for example. It looks like it only has four fields, but if you trace the code execution you can find three more nullable fields that are assigned to it elsewhere. There’s always going to be a barrier to entry contributing to a new codebase, but using TypeScript and separating functionally independent components out into standalone libraries can help lower the barrier.

2 Likes

Excellent points, John. Thanks for the thorough analysis!