ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Ensuring mutual exclusion between different actions

asked 2020-04-16 10:01:57 -0500

sverre gravatar image

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 :)

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2020-04-16 11:15:49 -0500

Stephan gravatar image

updated 2020-04-16 11:20:22 -0500

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

edit flag offensive delete link more


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 ...(more)

sverre gravatar image sverre  ( 2020-04-17 09:42:47 -0500 )edit

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.

Stephan gravatar image Stephan  ( 2020-04-18 14:23:06 -0500 )edit

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! :)

sverre gravatar image sverre  ( 2020-04-19 04:01:54 -0500 )edit

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.

Stephan gravatar image Stephan  ( 2020-05-11 02:01:46 -0500 )edit

Question Tools



Asked: 2020-04-16 10:01:57 -0500

Seen: 337 times

Last updated: Apr 16 '20