0
$\begingroup$

Rosanswers logo

Hi! I'm looking for a good way to ensure that different actions do not run at the same time.

Let's say we have a robot that can do different actions, such as moving and making a measurement. It seems natural to implement each of these actions as different actionlib servers as they would require different types of variables as a goal. But we want to avoid multiple actions running at once, such as the robot starting to move while it is making a measurement.

What would be a good way to design such a system? Such that it is simple to add on more actions when needed with minimal re-writing. While ensuring that the actions cannot run at the same time.

Looking forward to your answers :)


Originally posted by sverre on ROS Answers with karma: 45 on 2020-04-16

Post score: 2

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

The only way I see to accomplish this is to have a central "broker" that manages the set of actions. You need one place in the code that can check if one of all the mutual exclusive actions is already running to be able to reject (or abort, depending on your design) incoming goals. You can implement that for example by having some type of lock that needs to be acquired to execute an action and if that lock cannot be acquired within some timeout, the goal gets aborted.

There are many possible ways of implementing this and it depends on your requirements. For example, if you have one process that holds all action servers, a simple mutex that you try to lock at the beginning of your execute callbacks could work. If the action servers are distributed over multiple processes, you could add some central lock mechanism using ROS services (best encapsulated in some class or even in a specialization of ActionServer).


Originally posted by Stephan with karma: 1924 on 2020-04-16

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by sverre on 2020-04-17:
Ah, so you are thinking a separate mutex node where all other action nodes will run a service asking for the lock. If the service returns with false the action has to terminate, if true the action can continue. One service callback will be run at the mutex node at the time so race conditions should not be a problem. How about freeing the lock again? The simplest would for every node to use a free serivce. This requires that every node remembers to free the lock after every setAbort/setPreempt/setSucceed. Which is not really a problem, but I imagine this can lead to some bugs where you forget to free the lock and the lock gets lost in a dead action. Is there some elegant way to ensure that the keys get released when an action ends, even if it forgets to releas the lock? (if not then remembering to free the lock is also acceptable)

Comment by Stephan on 2020-04-18:
I would implement a specialization of the ActionServer (or of SimpleActionServer) that tries to acquire the lock when a goal is received and releases the lock when going into a terminal state (and on destruction). Every action that should be mutual exclusive should then use that special action server. You can even make it fancy and create groups of mutual exclusive actions, i.e. spawn several lock managers and configure each action server to connect to a selected one. See here for a detailed description of ActionServer states and transitions.

Comment by sverre on 2020-04-19:
Using an action server then new calls to the lock would preempt old calls, or is there a way to make the action server prevent new goals before the previous one finished? Were you then thinking that the old instances must check that they still have the lock and if not preempt/abort themselves? Thanks for the good answers! :)

Comment by Stephan on 2020-05-11:
What happens when a new goal comes in while the same action server is already executing one depends on your application. You can make it abort the new goal or preempt the running one and let the new one take over. You can tailor your implementation to not release the lock in that case. If that is what you want.

$\endgroup$

Your Answer

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