I'm controlling a mobile robot and I'd like to set up an action (call it back_and_forth) that commands the robot to move forward 1 meter, then move backwards one meter. The interface that I'm using (iRobot create3 ROS 2 API) uses actions to handle movement commands, so I need to call one action (move forward 1m), wait for it to complete, and call another action (move backwards 1m) inside the callback of my own action back_and_forth.

I have found reference to a few approaches for doing this, but none of them seem to work:

  1. Use ActionClient.send_goal() to send the move forwards and backwards actions. If I do this, the node gets stuck on that line and never continues to the move backwards action.
  2. Use ActionClient.send_goal_async(), followed by rclpy.spin_until_future_complete(). But as the documentation says, the future resolves "when the goal request has been accepted or rejected", not when the action completes. So it doesn't wait for the forward action to complete before moving onto the next one.

Something like this answer may work, but seems extremely convoluted and hacky for what should be a simple functionality.

This whole thing begs a broader question: if we can't wait for things (i.e. rclpy.spin) inside a callback, how are we supposed to write a meaningful action server that calls other services, actions, etc. to get things done, and only returns success once they are done?


1 Answer 1


As I understand, for each user call to your back_and_forth action server it should in turn make two calls to iRobot API action server. This again is not very straight forward but you can try

  • In your back_and_forth server's handle_accepted callback you may create a new thread and give it an execute function and detach the thread.
  • Inside this function you can create & send a goal for api action server and also wait for its completion in a loop.
  • Once that's done you can create a new goal for backward motion and send it again.
  • You'll also need to pass along goal_handle to the execute function so that you may set the states of user action call from inside the execute function.

Another advise would be to keep your server side callbacks and client side callbacks in independent callback groups or they might end up blocking each other.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.