Robotics StackExchange | Archived questions

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

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 movejointabsoluteexecutecallback) 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.

Asked by CraigH92 on 2021-03-08 10:31:39 UTC

Comments

I tried to think of the root cause but it was way beyond me. Just a small clarification: Can we assume GrappleCraneDriverClient.move_x_abs gets called from the callback move_joint_absolute_goal_callback?

Asked by 130s on 2023-05-07 10:30:12 UTC

In the example above, it calls the service from the execute_callback.

In the latest version, it gets called from the handle_accepted_callback.

I have used the goal_callback to determine if it should be accepted or rejected, the handle_accepted_callback then writes to the hardware and polls the system until the motion has started, and then the execute_callback polls the system to see if it has succeeded, failed, or been canceled.

It now works, although I am not sure if this is due to this change, or if it is because I am now using humle.

Asked by CraigH92 on 2023-05-09 03:37:37 UTC

Answers