Dynamically fetch type descriptions for ROS 2 topics at runtime
Thanks in part to Foxglove’s contributions, the ROS 2 Iron Irwini release allows you to programmatically fetch type descriptions from remote nodes at runtime. Every type description now includes an associated hash, ensuring that you have the correct type descriptions to decode your ROS messages.
ROS 1 already provided md5sum
hashes for type checking, and this contribution closes the gap for ROS 2.
In ROS, publisher nodes advertise a topic by providing a topic name (e.g. /imu
) and type name (e.g. sensor_msgs/msg/Imu
). If a subscriber node wants to listen to a published topic and start receiving its messages, it first checks that the message type name matches before connecting.
There were two problems with this model. For one, ROS message type definitions can evolve over time. Nodes with an outdated version of a type description could still receive messages of that type, but would fail to correctly deserialize the packets. Secondly, a system that didn't have the necessary type descriptions installed would not be able to parse ROS 2 data files using those message types.
With Foxglove’s latest contribution, ROS 2 makes progress towards tackling these issues by making it possible to identify when type descriptions have evolved and to dynamically fetch the required types at runtime.
Each message type now has a unique compact hash baked into it at build time. Subscribers now receive this hash when requesting topic information from publishers and compare it with their own local understanding of the type description. In this way, they can detect a possible mismatch – even if the type name itself hasn’t changed – before ever connecting to the publisher.
This pre-validation leads to more accurate type tracking and more robust systems. Instead of having to wonder why users can’t parse or playback a particular ROS data file, app developers can now detect if a type has changed and surface this root cause to users.
This new hash lives in the updated topic_endpoint_info
, in the new rosidl_type_hash_t
field. The ros2 topic info --verbose
command will now print the discovered type hash (starts with “RIHS01”, for ROS Interface Hashing Standard, version 01):
$ ros2 topic info /chatter --verbose
Type: std_msgs/msg/String
Publisher count: 1
Node name: talker
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: PUBLISHER
GID: 01.0f.70.b7.38.00.06.74.00.00.00.00.00.00.14.03
QoS profile:
Reliability: RELIABLE
History (Depth): UNKNOWN
Durability: VOLATILE
Lifespan: Infinite
Deadline: Infinite
Liveliness: AUTOMATIC
Liveliness lease duration: Infinite
Subscription count: 0
language-bash
Nodes now provide a GetTypeDescription
service (~/get_type_description
) – similar to the services exposed to manage ROS parameters. Given a request, a publisher node will return the full programmatic type description via a new set of type description messages. It may optionally also send the text contents of the original source used to define the type.
To dynamically fetch the types required to parse a given topic, run a simple publisher node in one Terminal window:
$ ros2 run demo_nodes_cpp talker
language-bash
List all services in another:
$ ros2 service list
/talker/describe_parameters
/talker/get_parameter_types
/talker/get_parameters
/talker/get_type_description
/talker/list_parameters
/talker/set_parameters
/talker/set_parameters_atomically
language-bash
Call the /talker/get_type_description
service to dynamically fetch the appropriate type descriptions (in this case, std_msgs/msg/String
):
$ ros2 service call \
/talker/get_type_description \
type_description_interfaces/srv/GetTypeDescription \
"{type_name: std_msgs/msg/String, type_hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
, include_type_sources: true}"
requester: making request: type_description_interfaces.srv.GetTypeDescription_Request(type_name='std_msgs/msg/String', type_hash='RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18', include_type_sources=True)
response:
type_description_interfaces.srv.GetTypeDescription_Response(
successful=True, failure_reason='',
type_description=type_description_interfaces.msg.TypeDescription(
type_description=type_description_interfaces.msg.IndividualTypeDescription(
type_name='std_msgs/msg/String',
fields=[
type_description_interfaces.msg.Field(
name='data',
type=type_description_interfaces.msg.FieldType(type_id=17, capacity=0, string_capacity=0, nested_type_name=''), default_value='')
]),
referenced_type_descriptions=[]),
type_sources=[
type_description_interfaces.msg.TypeSource(
type_name='std_msgs/msg/String',
encoding='msg',
raw_file_contents='# This was originally provided as an example message.\n# It is deprecated as of Foxy\n# It is recommended to create your own semantically meaningful message.\n# However if you would like to continue using this please use the equivalent in example_msgs.\n\nstring data')
],
extra_information=[])
language-bash
Now that you can dynamically fetch the types you need, you can inspect remote systems – even those that are not known on the local computer – and dynamically fetch the types needed to parse their topics.
This added support paves the way for future improvements – like allowing dynamic subscriptions to any publisher using just a type name at runtime. Even without prior knowledge of a custom type description, subscribers would always have automatic access to the “source of truth” during data playback – regardless of when and where the original type descriptions were first defined.
This is particularly useful for third party applications and developer tools like Foxglove, as they can now dynamically inspect whatever is coming over the network.
Dynamic subscriptions and publishers also open the door to “evolving types”. Messages change over time as a regular part of ROS development, but ROS 2 currently does not adapt well to these type description iterations.
In the future, applications could handle these type changes more gracefully, by dynamically converting them for forwards- and backwards-compatibility. This would afford developers much more flexibility, as types evolve alongside previously recorded data.
We’re excited that this new feature is making ROS 2 more robust for production use and enabling easy message inspection in off-host visualization tools like Foxglove and RViz.
This type description feature set was a prerequisite for the features of ROS Enhancement Proposal (REP) 2011 “Evolving Types”, which is a larger project designed to make ROS applications more robust to migrations over time. Check out the new REP 2016 “Type Descriptions” for a full description of this feature set, or the type_description_interfaces
package for more information.