Hey @sgvandijk, before I explain more: I am fine with asynchronous only services if I can design my system around it from the beginning. In this particular example of mine, the issue is with the transition from a system (ROS1) that only worked synchronously. I would be fine with waiting for the std::future as suggested in my examples, however, this seems to not work when calling service from a callback (currently due to malfunctioning parallelism of timer callbacks).
One such example of the use of synchronous services can be our high level takeoff service callback for a multirotor helicopter. When approached from the high-level point of view, this service (potentially called by a user) has to trigger the following sub-services in a fast and consecutive fashion:
- Activate a particular feedback controller for takeoff (service call)
- Activate a particular reference generator for takeoff (service call)
- Trigger a reference generation for the takeoff (service call)
Each service call can fail which will trigger an abort of the takeoff by calling more services to either restore the previous state or to call emergency landing routine. You could say that this should be implemented as a full-fledged “state machine” where every awaited service call result should be checked by its own state asynchronously. For some situations yes, however, here a few if-then-else statements are fine, especially, in the case of a linear state machine. Moreover, all this happens in a service callback so a user can get a memo back whether the takeoff was successful or not. Some mechanism for blocking the callback until all the asynchronous mess is settled would have to be implemented. Someone could say that this should be handled by an action server. Mind that this whole event takes a millisecond and action server just seems as a too large cannon for this job.
It is not pretty but you asked for it :-). There is a ton of similar situation where the logical flow of our programs just expects that the “one-liner” of a service call will just get you the result… And building asynchronous state machines for all of them seems to me just too much.