====== Lab 08 ======
During this lab, you should learn how to work with action servers and clients.
===== ROS action server and client =====
The ROS action servers/clients provide the ability to execute and interface preemptable tasks that can take a long time to execute.
It also allows you to get a regular feedback from tasks that are currently being executed.
Examples of such a task can be moving a robot to a target location or following a given path with a robot.
You can check out the official python tutorial [[http://wiki.ros.org/actionlib_tutorials/Tutorials/Writing%20a%20Simple%20Action%20Server%20using%20the%20Execute%20Callback%20%28Python%29 | action server]] and [[http://wiki.ros.org/actionlib_tutorials/Tutorials/Writing%20a%20Simple%20Action%20Client%20%28Python%29 | action client]].
==== Action specification ====
The action specification have three parts, the goal (similar to services' request), the results (similar to services' response), and the feedback messages to enable reporting on the action run.
The action server and action clients can be created using ''actionlib'' library in python.
The definition of an example action ''GoToPosition.action'' can look as follows:
#goal definition
geometry_msgs/Point position
---
#result definition
bool success
string message
---
#feedback
float32 position_error
float32 orientation_error
string message
==== Action server ====
The action server part listens for a goal message and once the goal is received, it starts executing procedures to fulfill the given goal.
While working on finishing the goal, the action server can periodically report the current state of goal processing through a feedback message, but also has to check if it was not stopped through preemption request.
Upon finishing or failing to fulfill the goal, the action server sends its result to the client.
The action server code could look like this:
def execute_cb(goal):
success = True # just to save global success status somewhere
rate = rospy.Rate(10) # run the action while loop with 10Hz frequency
while not rospy.is_shutdown(): #while the node is running
if action_server.is_preempt_requested(): #the action was canceled from outside
action_server.set_preempted()
success = False
break # break the action loop
.... # do something now, compute position and orientation error
feedback = GoToPositionFeedback() # create a feedback message
feedback.message = "still working on it" # fill the feedback message
feedback.position_error = ...
feedback.orientation_error = ...
action_server.publish_feedback(feedback) # send the feedback
# check finish/fail conditions
if #finished or #failed:
success = True/False #based on finished or failed
break # break the action loop
rate.sleep() # sleep for rest of rate's period
result = GoToPositionResult() # create result message when action finishes
result.success = success
if success:
result.message = "finished successfully"
action_server.set_succeeded(result) # send the result
else:
result.message = "failed miserably"
action_server.set_aborted(result) # send the result
# create action server "robocop_goto_as" with GoToPositionAction type
action_server = actionlib.SimpleActionServer("goto_position", GoToPositionAction, execute_cb=execute_cb,
auto_start=False)
action_server.start()
==== Action client ====
The action client can be used to interface the action server efficiently.
A simple client can look like this:
# create "robocop_goto_as" client with GoToPositionAction action type
client = actionlib.SimpleActionClient('goto_position', GoToPositionAction)
client.wait_for_server() # wait for the server to be alive
goal = GoToPositionGoal() # create the goal message
goal.position = ... # fill the position
# send the goal message and assign callbacks for feedback and for transition to "Done"
client.send_goal(goal, feedback_cb=action_feedback_cb, done_cb=action_done_cb)
client.wait_for_result() # wait for the server to finish