Use callback groups to allow an Action to trigger a service of the same Node

asked 2021-03-08 09:31:39 -0500

CraigH92 gravatar image

I have a Node that hosts an Action and a Service Client:

    callback_group=ReentrantCallbackGroup()
    self.__driver = GrappleCraneDriverClient(self, callback_group)

    self.move_joint_absolute_action_server = ActionServer(self,
        action_type=MoveJointAbsolute,
        action_name='move_joint_absolute',
        execute_callback=move_joint_absolute_execute_callback,
        goal_callback=move_joint_absolute_goal_callback,
        cancel_callback=move_joint_absolute_cancel_callback,
        callback_group=callback_group
    )

The service client adds clients to the Node:

class GrappleCraneDriverClient:

    def __init__(self, node: Node, callback_group=None):

        self.__node = node

        # Service clients

        self.__move_x_abs=node.create_client(
            srv_type=MoveOneAxis,
            srv_name='accs/grapple_crane/service/move_x_abs',
            callback_group=callback_group
        )

    def move_x_abs(self, target_position: float) -> MoveOneAxis_Response:
        self.__node.get_logger().info(
            f'[GrappleCraneDriverClient]: calling service {self.__move_x_abs.srv_name}')

       future_trigger_result = self.__move_x_abs.call_async(
           MoveOneAxis_Request(target_position=target_position))
        try: 
            return asyncio.run(asyncio.wait_for(future_trigger_result, timeout=5))
        except asyncio.TimeoutError as e:
            self.__node.get_logger().error(f'TimeoutError: {e}')
            return MoveOneAxis_Response(success=False, message=f'TimeoutError: {e}')

The Node hosting the services is running in a different process.

If I test the GrappleCraneDriverClient by constructing it with a new Node, and then launching it in the same process as the Node that hosts the services, then it works fine.

However when I use the GrappleCraneDriverClient to compose part of my Node that hosts the actions, then I get a timeout error because the service never gets called.

Why would this be?

A key difference between the test code (which works), and the action server code is that in the action server a callback is already running (the move_joint_absolute_execute_callback) when the service is called. However, I am using a ReentrantCallbackGroup(), so this should allow the callbacks to run at the same time, should it not?

I am also using a MultiThreadedExecutor.

If I give the GrappleCraneDriverClient a new Node and run that Node alongside the Node hosting the action (but still in the same process), it also works.

How do I correctly get the service to be called while the action is running, and have the client and action server elonging to the same Node?

Thanks.

edit retag flag offensive close merge delete