C++ AnySubscriber and AnyPublisher ROS Babel Fish now available

Technically that is not true. In RTI the message hierarchy is retained by the intermediate representation FlatMessage.

Anyway, I am not interested to publish the type erased messages, only to parse those I receive, therefore I will not implement that feature in the future.

Summarizing, RTI and RBF have a 80% overlap in functionalities and user should just choose the one that better adapt to his/her needs.

Cheers :slight_smile:

Hi!

I am not familiar with neither RTI nor RBF. But do you think it could be used in a proxy like rosserial_server? Currently it uses a service that calls a Python node to deal with messages type at runtime.

EDITED:

I am not familiar with rosserial, but reading the WIKI, I think that it does not provide the message definition, that RTI needs.

Therefore, from my side, the answer is “no”.

I think that both rosserial_server and RBF use Python to compensate for that (@StefanFabian, can you confirm from your side?) .

If you point me to some instances in the code where that is done I could give you a definite answer but I suspect yes.
RBF can send (almost) any messages that python can.

RBF does not use Python. There’s an implementation of a description provider (this is the interface that looks up the message definition, md5 sum etc.) that calls the genmsg python package methods using Python 2.7 in C++. However, I’ve since implemented a native C++ version of the message lookup which is the default. The python version can be enabled as an option in the CMakeLists.txt but it’s disabled by default.

EDIT:
I’ve found the code I assume you were referring to. Yes, the description provider in RBF could be used to get the information. BUT it looks up the message definition on the local machine. The service server for rosserial_server may run on a different computer and that computer may have messages that don’t exist on the computer running the rosserial_server. So, the actual answer is NO, the behavior can not be replicated without a service server. RBF would allow implementing that service server in C++ but I don’t see anything to gain from that.

Thank you for your answer @facontidavide.

I am not sure to understand this.

The rosserial client provides a rosserial_msgs/TopicInfo message containing:

  • name of topic
  • type of message
  • md5sum

I see that the message definition is missing. But then, how RTI and Plotjuggler manage to get this information? Because they can run on system with custom messages without re-building them.

A small example on how to use RTI like the one RBF has in its README would be nice :slight_smile:

Thank you for your answer @StefanFabian.

As you have found, the code is here.

A publisher is created from a topic_tools::ShapeShifter this is created from the name and the message type from the rosserial client and the message definition returned by the Python service.

I have never though of that use case before, Python service on another computer with more message definition. I am not sure this feature is really leveraged in real use cases.

You may find the examples of RTI here.

The main use case of RTI is:

  • Subscribe to topic_tools::ShapeShifter messages, which is a type erased format in ROS1
  • Read messages from rosbags.

Both contain the message definition I need.
If we could add the Definition to rosserial_msgs/TopicInfo , that would awesome :wink:

Thank you, I did not look for a separate repository for the tests and examples :wink:

I ask these questions because I am thinking of writing something close to rosserial but for another user case so I will think about adding the definition. Thanks.

What you could do is first look up the message definition on the local machine using the integrated description provider and if that fails, you could fall back to a service call. The description provider will also cache message definitions which in the case of dependencies significantly improves performance if you look up multiple messages. Hence, you should reuse the instance of the description provider.

For your information, I just released ros_type_introspection 2.0, which does not depend on abseil_cpp anymore.

I’ve just released some changes including some significant optimizations.
The updated benchmark can be found here.
@facontidavide you should take a look at the benchmark code and whether you still have some changes because I got significantly higher timings for the image and pointcloud messages. I have built ros_type_introspection from source in the latest version available on GitHub so there might be some issue with the benchmark code.

Here are the updated results (RTI=ros_type_introspection, RBF=ros_babel_fish):

--------------------------------------------------------------------------------------------
Benchmark                                                     Time           CPU Iterations
--------------------------------------------------------------------------------------------
RTI_ParseMessageDefinition<geometry_msgs::Pose>              76 us         76 us       9124
RBF_ParseMessageDefinition<geometry_msgs::Pose>              46 us         46 us      15431

RTI_ParseMessageDefinition<sensor_msgs::JointState>         172 us        172 us       4087
RBF_ParseMessageDefinition<sensor_msgs::JointState>         104 us        104 us       6800

RTI_ParseMessageDefinition<nav_msgs::Odometry>              324 us        324 us       2188
RBF_ParseMessageDefinition<nav_msgs::Odometry>              261 us        261 us       2716

RTI_ParseMessageDefinition<tf::tfMessage>                   217 us        217 us       3113
RBF_ParseMessageDefinition<tf::tfMessage>                   170 us        170 us       4137

RTI_ParseMessageDefinition<sensor_msgs::PointCloud2>        294 us        294 us       2434
RBF_ParseMessageDefinition<sensor_msgs::PointCloud2>        148 us        148 us       4709

RTI_ParseMessageDefinition<sensor_msgs::Image>              185 us        185 us       3714
RBF_ParseMessageDefinition<sensor_msgs::Image>              131 us        131 us       5335

---

RTI_ParseMessage<geometry_msgs::Pose>                       334 ns        334 ns    2078223
RBF_ParseMessage<geometry_msgs::Pose>                       349 ns        349 ns    2044464

RTI_ParseMessage<sensor_msgs::JointState>                   581 ns        581 ns    1215252
RBF_ParseMessage<sensor_msgs::JointState>                   335 ns        335 ns    2009207

RTI_ParseMessage<nav_msgs::Odometry>                       1159 ns       1159 ns     614297
RBF_ParseMessage<nav_msgs::Odometry>                       1009 ns       1009 ns     695203

RTI_ParseMessage<tf::tfMessage>                            1946 ns       1946 ns     353818
RBF_ParseMessage<tf::tfMessage>                            1889 ns       1889 ns     377316

RTI_ParseMessage<sensor_msgs::PointCloud2>                 8827 ns       8826 ns      79320
RBF_ParseMessage<sensor_msgs::PointCloud2>                  586 ns        586 ns    1219825

RTI_ParseMessage<sensor_msgs::Image>                      62604 ns      62604 ns      11197
RBF_ParseMessage<sensor_msgs::Image>                        354 ns        354 ns    2012739

This is definitively a huge improvement!

With version 2.0 of RTI, the large difference in Image and PointCloud2 will disappear.

Just add this line:

   parser.setBlobPolicy(RosIntrospection::Parser::STORE_BLOB_AS_REFERENCE);

And modify this one to avoid extra work that is not really needed:

   parser.applyNameTransform(datatype, flat_container, &renamed_value, true);

EDITED after the last commit to RTI

 RTI_ParseMessage<geometry_msgs::Pose>             492 ns
 RBF_ParseMessage<geometry_msgs::Pose>             546 ns
 RTI_ParseMessage<sensor_msgs::JointState>         750 ns 
 RBF_ParseMessage<sensor_msgs::JointState>         481 ns
 RTI_ParseMessage<nav_msgs::Odometry>             1631 ns 
 RBF_ParseMessage<nav_msgs::Odometry>             1463 ns
 RTI_ParseMessage<tf::tfMessage>                  2224 ns
 RBF_ParseMessage<tf::tfMessage>                  2509 ns
 RTI_ParseMessage<sensor_msgs::PointCloud2>        709 ns
 RBF_ParseMessage<sensor_msgs::PointCloud2>        923 ns
 RTI_ParseMessage<sensor_msgs::Image>              440 ns
 RBF_ParseMessage<sensor_msgs::Image>              549 ns

By the way, our results may differ because we are using different computers but also different compilers, I guess (I am using Ubuntu 16.04)

Said that…

image

2 Likes

Looking back from the start, the speed gains in both of these libraries are fantastic. Keep up the good work guys!

1 Like