executor.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # executor.py
00003 """ Provides an execution queue for the roboframenet interface.
00004 
00005 Manages incoming callback requests (in the form of filled semantic frames), and calls them in order of request.
00006 """
00007 
00008 import roslib; roslib.load_manifest('executor')
00009 import rospy
00010 import actionlib
00011 import actionlib_msgs.msg
00012 import threading
00013 from collections import deque
00014 from roboframenet_msgs.msg import FilledSemanticFrameAction, FilledSemanticFrameGoal, Procedure
00015 
00016 MAX_WAIT_TIME = 3.0 # seconds
00017 
00018 client = False
00019 sm_is_running = False
00020 need_to_preempt = False
00021 
00022 def cb_procedure(msg):
00023     global client, sm_is_running
00024     # Preempt currently-running
00025     need_to_preempt = True
00026     if client:
00027         rospy.loginfo("Requesting goal cancellation.")
00028         client.cancel_all_goals()
00029     # Wait for servers to stop running
00030     r = rospy.Rate(10) #hz
00031     while sm_is_running:
00032         r.sleep()
00033     # Start our new server.
00034     need_to_preempt = False
00035     t = threading.Thread(target=lambda: execute_sm_wrapper(msg.frame_lists))
00036     t.start()
00037     return
00038 
00039 
00040 def execute_sm_wrapper(frame_lists):
00041     global sm_is_running
00042     sm_is_running = True
00043     r = execute_sm(frame_lists)
00044     sm_is_running = False
00045 
00046 def execute_sm(frame_lists):
00047     # call one-by-one until one succeeds
00048     # frame_lists is listof(listof(FilledSemanticFrame)), where
00049     #   listof(FilledSemanticFrame) is a sequence of actions which
00050     #   need to execute, in order of appearance.  To successfully
00051     #   complete execution of the sequence, all elements
00052     #   therein must successfully execute.  If they do not,
00053     #   the next list will start executing.  (In other words,
00054     #   inner lists are "and"ed, and outer lists are "or"ed.)
00055     global need_to_preempt
00056     rospy.loginfo("Executing frame_lists:\n" + str(frame_lists))
00057     success_overall = False # We completed our action
00058     for frame_list in frame_lists:
00059         rospy.loginfo("  Executing frame sequence: " +
00060                       ', '.join(map(lambda frame: frame.name, frame_list.frames)))
00061         success_frame_list = False # We completed our frame list
00062         for frame in frame_list.frames:
00063             rospy.loginfo("    Executing frame: " + frame.name)
00064             success_frame = False
00065             for topic in frame.action_server_topics:
00066                 # Check that we don't have new goals
00067                 if need_to_preempt:
00068                     rospy.loginfo("    Preempted!.")
00069                     return False
00070                 rospy.loginfo("      Calling topic: " + topic)
00071                 result = call_server(frame, topic)
00072                 rospy.loginfo("        Server terminated with status " +
00073                               str(result) + " (" +
00074                               ("PENDING"    if result == 0 else
00075                                "ACTIVE"     if result == 1 else
00076                                "PREEMPTED"  if result == 2 else
00077                                "SUCCEEDED"  if result == 3 else
00078                                "ABORTED"    if result == 4 else
00079                                "REJECTED"   if result == 5 else
00080                                "PREEMPTING" if result == 6 else
00081                                "RECALLING"  if result == 7 else
00082                                "RECALLED"   if result == 8 else
00083                                "LOST"       if result == 9 else
00084                                "unknown status id") +
00085                               ").")
00086                 if result == actionlib_msgs.msg.GoalStatus.SUCCEEDED:
00087                     rospy.loginfo("      ...Success with called topic!")
00088                     success_frame = True
00089                     break
00090                 elif result in [actionlib_msgs.msg.GoalStatus.ABORTED,
00091                                 actionlib_msgs.msg.GoalStatus.REJECTED,
00092                                 actionlib_msgs.msg.GoalStatus.RECALLED]:
00093                     rospy.logwarn("      ...Failure with called topic.")
00094                     break
00095                 elif result == actionlib_msgs.msg.GoalStatus.PREEMPTED:
00096                     rospy.loginfo("      ...Preempted!.")
00097                     return False
00098                 else:
00099                     rospy.logerr("Unknown actionlib state!: " + str(result) +
00100                                  " -- Aborting.")
00101                     return False
00102             # end "for topic"
00103             if not success_frame:
00104                 rospy.logwarn("    ...Failure with frame.")
00105                 break
00106             rospy.loginfo("    ...Success with frame!")
00107         # end "for frame"
00108         if not success_frame:
00109             success_frame_list = False # Failed frame -> failed sequence
00110             rospy.logwarn("  ...Failure with frame sequence.")
00111         else:
00112             success_frame_list = True
00113             success_overall = True
00114             rospy.loginfo("  ...Success with frame sequence!")
00115             break
00116     # end "for frame_list"
00117     if not success_overall:
00118         rospy.logerr("...Failure overall.")
00119     else:
00120         rospy.loginfo("...Success overall!")
00121     is_running = False
00122     return success_overall
00123 
00124 
00125 # We will be in a terminal state upon exit.
00126 def call_server(semantic_frame, action_topic):
00127     # rospy.loginfo("Calling topic '" + action_topic +
00128     #              "'.  Frame: " + str(semantic_frame.name))
00129     global client
00130     client = actionlib.SimpleActionClient(action_topic, FilledSemanticFrameAction)
00131     if not client.wait_for_server(rospy.Duration.from_sec(MAX_WAIT_TIME)):
00132         rospy.logerr("call_server: Server with topic " + action_topic +
00133                      " has not responded.  Aborting.")
00134         return actionlib_msgs.msg.GoalStatus.ABORTED
00135 
00136     goal = FilledSemanticFrameGoal()
00137     goal.frame = semantic_frame
00138     client.send_goal(goal)
00139     r = rospy.Rate(10) #hz
00140     s = client.get_state()
00141     while s in [actionlib_msgs.msg.GoalStatus.PENDING,
00142                 actionlib_msgs.msg.GoalStatus.ACTIVE,
00143                 actionlib_msgs.msg.GoalStatus.PREEMPTING,
00144                 actionlib_msgs.msg.GoalStatus.RECALLING,
00145                 actionlib_msgs.msg.GoalStatus.LOST]:
00146         # result should not be actionlib_msgs.msg.GoalStatus.LOST,
00147         #   as only client should send this to server.
00148         # Wait for status to become terminal.
00149         r.sleep()
00150         s = client.get_state()
00151     return s
00152 
00153 
00154 def main():
00155     rospy.init_node('executor')
00156     rospy.Subscriber('procedure', Procedure, cb_procedure)
00157     rospy.spin()
00158 
00159 
00160 
00161 if __name__ == '__main__':
00162     main()
00163 
00164 
00165 


executor
Author(s): Brian Thomas
autogenerated on Fri Dec 6 2013 20:42:03