Describe ScottHassan/TestPage here.
Writing a Simple Server
The Code
First, create your_package/src/fibonacci_action.cpp in your favorite editor, and place the following inside it:
1 #include <ros/ros.h>
2 #include <actionlib/server/simple_action_server.h>
3 #include <actionlib_tutorials/FibonacciAction.h>
4
5 class FibonacciAction
6 {
7 public:
8
9 FibonacciAction(std::string name) :
10 as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1)),
11 action_name_(name)
12 {
13 }
14
15 ~FibonacciAction(void)
16 {
17 }
18
19 void executeCB(const actionlib_tutorials::FibonacciGoalConstPtr &goal)
20 {
21 // helper variables
22 ros::Rate r(1);
23 bool success = true;
24
25 // push_back the seeds for the fibonacci sequence
26 feedback_.sequence.clear();
27 feedback_.sequence.push_back(0);
28 feedback_.sequence.push_back(1);
29
30 // publish info to the console for the user
31 ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i", action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]);
32
33 // start executing the action
34 for(int i=1; i<=goal->order; i++)
35 {
36 // check that preempt has not been requested by the client
37 if (as_.isPreemptRequested())
38 {
39 ROS_INFO("%s: Preempted", action_name_.c_str());
40 // set the action state to preempted
41 as_.setPreempted();
The Code Explained
Now, let's break down the code piece by piece.
actionlib/server/simple_action_server.h is the action library used from implementing simple actions.
This includes action message generated from the Fibonacci.action file show above. This is a header generated automatically from the FibonacciAction.msg file. For more information on message definitions, see the msg page.
In the action constructor, an action server is created. The action server takes arguments of a node handle, name of the action, and optionally an executeCB. In this example the action server is created with the arguments for the executeCB.
Now the executeCB function referenced in the constructor is created. The callback function is passed a pointer to the goal message.
20 {
21 // helper variables
22 ros::Rate r(1);
23 bool success = true;
24
25 // push_back the seeds for the fibonacci sequence
26 feedback_.sequence.clear();
27 feedback_.sequence.push_back(0);
28 feedback_.sequence.push_back(1);
29
30 // publish some info to the console for the user
31 ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i",action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]);
32
33 // start executing the action
34 for(int i=1; i<=goal->order; i++)
35 {
Here the internals of the action are created. In this example ROS_INFO is being published to let the user know that the action is executing.
In the process of a running action it is important check that the action client has not requested the current goal to be canceled. If the action has been requested to preempt the action should respond with setting preempted after any necessary clean up is completed.
Here the Fibonacci sequence is put into the feedback variable and then published on the feedback channel provided by the action server. Then the action continues on looping and publishing feedback.
Once the action has finished computing the Fibonacci sequence the action notifies the action client that the action is complete by setting succeeded.
61 protected:
62
63 ros::NodeHandle nh_;
64 actionlib::SingleGoalActionServer<actionlib_tutorials::FibonacciAction> as_;
65 std::string action_name_;
66 // create messages that are used to published feedback/result
67 actionlib_tutorials::FibonacciFeedback feedback_;
68 actionlib_tutorials::FibonacciResult result_;
69 };
These are the protected variables of the action class. The node handle is constructed and passed into the action server during construction of the action. The action server is constructed in the constructor of the action and has been discussed above. The feedback and result messages are created for publishing in the action.
Finally the main function, creates the action and spins the node. This puts the action in a pending state when the action is started.
Compiling and Running the Action
Add the following line to your CMakeLists.txt file:
rospack_add_executable(fibonacci_action fibonacci_action.cpp)
After you have made the executable, start a roscore in a new terminal
$ roscore
And then run the action server:
$ rosrun your_package fibonacci_action
You will see something similar to:
[ INFO] 1250790662.410962000: Started node [/fibonacci], pid [29267], bound on [aqy], xmlrpc port [39746], tcpros port [49573], logging to [~/ros/ros/log/fibonacci_29267.log], using [real] time
To check that your action is running properly list topics being published:
$ rostopic list -v
You will see something similar to:
Published topics: * /fibonacci/feedback [actionlib_tutorials/FibonacciActionFeedback] 1 publisher * /fibonacci/status [actionlib/GoalStatusArray] 1 publisher * /fibonacci/result [actionlib_tutorials/FibonacciActionResult] 1 publisher * /rosout [roslib/Log] 1 publisher * /rosout_agg [roslib/Log] 1 publisher Subscribed topics: * /time [unknown type] 2 subscribers * /rosout [roslib/Log] 1 subscriber * /fibonacci/goal [unknown type] 1 subscriber * /fibonacci/cancel [unknown type] 1 subscriber
Alternatively you can look at the nodes:
$ rxgraph
This shows that your action server is publishing the feedback, status, and result channels as expected and subscribed to the goal and cancel channels as expected. The action server is up and running properly.
Sending a Goal to the Action Server
For the next step in using your action, you need to write a simple action client.