Why does async client call block timer callback
I have an issue where my async client call seems to block the timer callback.
I have created a simple example by modifying the service tutorial code to have a timer function that makes a service call. When I run it using the call_async(...)
method, the client completes, but the timer function never gets called again. The resulting output is
[INFO] [1663166937.600692028] [minimal_client_async]: send_request: enter
[INFO] [1663166937.602566992] [minimal_client_async]: send_request: exit
[INFO] [1663166937.602842863] [minimal_client_async]: Result of add_two_ints: for 4 + 2 = 6
If I instead make a call to the call(...)
method then the output repeats indefinitely.
[INFO] [1663168270.133728816] [minimal_client_async]: send_request: enter
[INFO] [1663168270.134015634] [minimal_client_async]: send_request: exit
[INFO] [1663168270.136338613] [minimal_client_async]: Result of add_two_ints: for 4 + 2 = 6
[INFO] [1663168271.125882562] [minimal_client_async]: send_request: enter
[INFO] [1663168271.126730859] [minimal_client_async]: send_request: exit
[INFO] [1663168271.132774293] [minimal_client_async]: Result of add_two_ints: for 4 + 2 = 6
[INFO] [1663168272.124292254] [minimal_client_async]: send_request: enter
[INFO] [1663168272.124570905] [minimal_client_async]: send_request: exit
[INFO] [1663168272.126700274] [minimal_client_async]: Result of add_two_ints: for 4 + 2 = 6
Why does the async call stop the timer callback?
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
from rclpy.executors import MultiThreadedExecutor, SingleThreadedExecutor
from rclpy.callback_groups import MutuallyExclusiveCallbackGroup
from rclpy.callback_groups import ReentrantCallbackGroup
class MinimalClientAsync(Node):
def __init__(self):
super().__init__('minimal_client_async')
self.client_cb = MutuallyExclusiveCallbackGroup()
self.timer_cb = MutuallyExclusiveCallbackGroup() # ReentrantCallbackGroup()
self.cli = self.create_client(AddTwoInts, 'add_two_ints', callback_group=self.client_cb)
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
self.req = AddTwoInts.Request()
# Create a timer for the main loop execution
self.timer = self.create_timer(1.0, self.main_loop, callback_group=self.timer_cb)
def send_request(self, a, b):
self.get_logger().info("send_request: enter")
self.req.a = a
self.req.b = b
# Uncomment for async call - Note that this blocks
future = self.cli.call_async(self.req)
rclpy.spin_until_future_complete(self, future)
self.get_logger().info("send_request: exit")
return future.result()
# # Uncomment for syncronous call - Note that this does not block
# self.get_logger().info("send_request: exit")
# return self.cli.call(self.req)
def main_loop(self) -> None:
response = self.send_request(4, 2)
self.get_logger().info(
'Result of add_two_ints: for %d + %d = %d' %
(4, 2, response.sum))
def main(args=None):
rclpy.init(args=args)
minimal_client = MinimalClientAsync()
executor = MultiThreadedExecutor()
executor.add_node(minimal_client)
executor.spin()
rclpy.shutdown()
if __name__ == '__main__':
main()
Asked by gdroge on 2022-09-14 10:12:34 UTC
Comments
It was suggested that I try to specify the number of threads in the MultiThreadedExecutor. I changed the initialization of the executor to
executor = MultiThreadedExecutor(num_threads=4)
, but got the same result. I tried to specify the number of threads from 1 to 10 and nothing changed.Asked by gdroge on 2022-09-15 08:00:03 UTC