ROS2 C++ Generic Action / Service Client

Hello, I’m trying to make a generic C++ application for controlling ROS robots. The idea is to allow design of GUIs in a higher-level language (QML) without requiring modifying the C++ when integrating new ROS systems.

So far I’ve been using the generic subscription from rosbag2_transport along with introspection via ros2_introspection, which has worked great for topic data.

However, now I’d like to do the same for calling services and actions. From looking at the code, it looks like a writing a “GenericClient” for services would mean creating a new subclass of rclcpp::ClientBase and instantiating it with the relevant typesupport handle. Similarly for actions with rclcpp_action::ClientBase. Or perhaps I am misreading it, and using the ClientBase classes directly would suffice.

Is developing this functionality on any current roadmap, or has anybody attempted this before?

Thanks for your question. However we ask that you please ask questions on following our support guidelines:

ROS Discourse is for news and general interest discussions. ROS Answers provides a Q&A site which can be filtered by tags to make sure the relevant people can find and/or answer the question, and not overload everyone with hundreds of posts.

I think this doesn’t count as a Q&A, as there is an answer to this yet.
I think there is a lot possible design concepts that could be discussed.

No one is planning to do this as far as I know. It sounds like what you proposed might work, but without digging into it, I’d have a hard time saying one way or the other.

This (interacting with unknown types at runtime) is an area that we need to improve on still in the core API, in my opinion. But it is not on any immediate road map that I’m aware of.

1 Like

I managed to cobble together a generic service client, following in the footsteps of the rosbag2 generic subscription and ros2_introspection.

The principles are the same, just using the service type support instead of the message type support. One oddity I did find is that I had to use an rmw-specific typesupport library (rosidl_typesupport_fastrtps_cpp) to get the service typesupport for a given type, which wasn’t necessary for messages.

Agreed - being a bit of a ROS2 novice I was disappointed to find that I needed to duplicate the(de)serialization method used in the specific rmw implementation I was using in order to get usable data out of a SerializedMessage. It feels like something that should be possible without coupling my application to a specific rmw implementation.

It occurs to me that there is another approach to solve the problem of writing generic C++ applications that work with message / service types not known until runtime. That is to follow the path of SOSS and use generated code which is compiled to plugins that are loaded at runtime. As far as I can tell the key advantage of that route is you don’t have to mess around with the sort of serialisation routines I mentioned above, and should be fully insulated from the rmw. But I don’t know if using using SOSS as a library for an existing application one of its intended uses, rather than as a standalone gateway.