Ask Your Question

Revision history [back]

Nothing prevents to do a service call within a callback managed by the executor (e.g. Timer or subscription callbacks), but a little More care is required for doing it.

The problems with doing a service call within an executor callback are the following: - if the service server is located in the same executor as the callback from where you are doing the service request, then the code for the service call must be non blocking. This is because, unless you have multithreaded executor, the service server will not be able to start until the aforementioned callback returns, which is in turn waiting for the service to be completed, causing a deadlock. - if the service server is located In another executor, there is no risk of deadlocks, but still you should try to avoid blocking the callback as that will prevent other entities associated with the executor to do their work.

Note that ROS will not detect these problems for you.

As the error says, your problem however is that you are adding your node to two executors. I assume that your node is already added to an executor since it is executing the timer. This means that in the timer callback you can't add it to another. Without looking at the code in tour timer callback i can't really say what you are doing wrong, but chaces are that you are using a synchronous service call or using a ros API that under the hoods adds the node to an executor, such as spin_until_future_complete.

My suggestion is to look into asynchronous service calls. Those will not cause the problem and will also be better for your system.

For details read the tutorial page that describes both the deadlock problem as well as asynchronous services https://docs.ros.org/en/foxy/Guides/Sync-Vs-Async.html#asynchronous-calls

Nothing prevents to do a service call within a callback managed by the executor (e.g. Timer or subscription callbacks), but a little More care is required for doing it.

The problems with doing a service call within an executor callback are the following: - following:

  • if the service server is located in the same executor as the callback from where you are doing the service request, then the code for the service call must be non blocking. This is because, unless you have multithreaded executor, the service server will not be able to start until the aforementioned callback returns, which is in turn waiting for the service to be completed, causing a deadlock. - deadlock.

  • if the service server is located In another executor, there is no risk of deadlocks, but still you should try to avoid blocking the callback as that will prevent other entities associated with the executor to do their work.

Note that ROS will not detect these problems for you.

As the error says, your problem however is that you are adding your node to two executors. I assume that your node is already added to an executor since it is executing the timer. This means that in the timer callback you can't add it to another. Without looking at the code in tour your timer callback i can't really say what you are doing wrong, but chaces chances are that you are using a synchronous service call or using a ros API that under the hoods adds the node to an executor, such as spin_until_future_complete.

My suggestion is to look into asynchronous service calls. calls. Those will not cause the problem and will also be better for your system.

For details read the tutorial page that describes both the deadlock problem as well as asynchronous services https://docs.ros.org/en/foxy/Guides/Sync-Vs-Async.html#asynchronous-calls