[Documentation] [TitleIndex] [WordIndex

DEPRECATED

The robot_actions package has been deprecated in favor of the actionlib package. Please see the documentation for the actionlib package instead for information about using actions with ROS.


Package Summary

The robot_actions package provides a construct for goal achieving, modular behavior primitives that are non-blocking for the client, and preemptable. This is in contrast to a service which is not preemptable and blocks the client. The proposed package will define core components to enforce action semantics. Such actions will be primitives available for aggregation into higher level tasks. Specific action implementations will not be part of this package. However, I propose that the message based interface common for invocation and monitoring of actions will be included in the package, much as robot_srvs are done now. Abstract base class actions will be provided to support common action patterns. The genesis of this idea is the work done in developing the highlevel_controllers, and this is effectively a factoring of that work.

A strawman indicating the relationships between a supervisory executive, actions, and low-level controllers (real time controllers operating very fast, with very limited lookahead) is shown below.

actions.png

ROS Message Interface

The states for an action are:

The states and their transitions are shown below.

action.std.png

Implementation Requirements

Whenever an actions is in an inactive state (i.e. UNDEFINED, SUCCESS, PREEMPTED, ABORTED) it should be operating in a low-duty cycle. An implementation of an action must also support:

Implementation Support

A small C++ framework has been put in place to allow easy implementation of an action by sub-classing robot_actions::Action. The example below is from a test action in test_robot_actions. It illustrates the primary function an action implementer must provide - execute. This function will block until the action has become deactivated. Note the use of the function to test for preemption. if developers do not have such tests then in practice their action will not be pre-emptable since preemption must be signaled by the action implementer.

   1 class MyAction: public robot_actions::Action<Float32, Float32> {
   2 public:
   3 
   4   MyAction(): robot_actions::Action<Float32, Float32>("my_action") {}
   5 
   6   const static int FAIL_IF = 30;
   7 
   8 private:
   9 
  10   // This method will run for the number of ms given by the goal.
  11   virtual ResultStatus execute(const Float32& goal, Float32& feedback) {
  12 
  13     // Variable for accumulated running time
  14     double count = 0.0;
  15     ros::Duration d; d.fromSec(0.001);
  16 
  17     while (!isPreemptRequested() && count <= goal.data) {
  18       count += 1.0;
  19       feedback.data = count;
  20       update(feedback);
  21       d.sleep();
  22     }
  23 
  24     if (isPreemptRequested()) {
  25       return PREEMPTED;
  26     } else if(goal.data >= FAIL_IF){
  27       return ABORTED;
  28     }
  29     else {
  30       return SUCCESS;
  31     }
  32   }
  33 };

We also provide a function to waitForDeactivation so that action implementations based on callbacks can signal the execute method to complete.

Finally, an ActionRunner class is provided to implement the ROS message bindings, making the action callable over ROS.

   1   MyAction action;
   2 
   3   // Now run it.
   4   robot_actions::ActionRunner runner(10.0);
   5   runner.connect<Float32, TestState, Float32>(action);
   6   runner.run();

Test Support

An ActionClient has been provided to allow a test program in C++ to call actions remotely, exercising the ROS message integration model. Simple test executives can thus be built.

Here is a simple test executive.

   1   // Use a client to test the action
   2   robot_actions::ActionClient<Float32, TestState, Float32> client("my_action");
   3   ros::Duration duration(5);
   4   duration.sleep();
   5 
   6   // Start the action; it must finish in 1 second
   7   Float32 g, f;
   8   g.data = 5;
   9   robot_actions::ResultStatus result = client.execute(g, f, ros::Duration(1));
  10   ASSERT_EQ(result, robot_actions::SUCCESS);
  11 
  12   // Start the action; it must finish in 0.0001 second
  13   result = client.execute(g, f, ros::Duration().fromSec(0.0001));
  14   ASSERT_EQ(result, robot_actions::PREEMPTED);

Tutorials

Links to relevant tutorials


Troubleshooting

Review Process


2024-04-13 12:57