pi_trees_ros.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import rospy
00004 import actionlib
00005 from actionlib_msgs.msg import GoalStatus
00006 from pi_trees_lib.pi_trees_lib import *
00007 import sys
00008 
00009 class MonitorTask(Task):
00010     """
00011         Turn a ROS subscriber into a Task.
00012     """
00013     def __init__(self, name, topic, msg_type, msg_cb, wait_for_message=True, timeout=5):
00014         super(MonitorTask, self).__init__(name)
00015         
00016         self.topic = topic
00017         self.msg_type = msg_type
00018         self.timeout = timeout
00019         self.msg_cb = msg_cb
00020                 
00021         rospy.loginfo("Subscribing to topic " + topic)
00022         
00023         if wait_for_message:
00024             try:
00025                 rospy.wait_for_message(topic, msg_type, timeout=self.timeout)
00026                 rospy.loginfo("Connected.")
00027             except:
00028                 rospy.loginfo("Timed out waiting for " + topic)
00029                 
00030         # Subscribe to the given topic with the given callback function executed via run() 
00031         rospy.Subscriber(self.topic, self.msg_type, self._msg_cb)
00032         
00033     def _msg_cb(self, msg):
00034         self.set_status(self.msg_cb(msg))
00035         
00036     def run(self):
00037         return self.status
00038     
00039 class ServiceTask(Task):
00040     """
00041         Turn a ROS service into a Task.
00042     """
00043     def __init__(self, name, service, service_type, request, result_cb=None, wait_for_service=True, timeout=5):
00044         super(ServiceTask, self).__init__(name)
00045         
00046         self.result = None
00047         self.request = request
00048         self.timeout = timeout
00049         self.result_cb = result_cb
00050                 
00051         rospy.loginfo("Connecting to service " + service)
00052         
00053         if wait_for_service:
00054             rospy.loginfo("Waiting for service")
00055             rospy.wait_for_service(service, timeout=self.timeout)
00056             rospy.loginfo("Connected.")
00057         
00058         # Create a service proxy
00059         self.service_proxy = rospy.ServiceProxy(service, service_type)
00060         
00061     def run(self):
00062         try:
00063             result = self.service_proxy(self.request)
00064             if self.result_cb is not None:
00065                 self.result_cb(result)
00066             return TaskStatus.SUCCESS
00067         except:
00068             rospy.logerr(sys.exc_info())
00069             return TaskStatus.FAILURE
00070         
00071     def reset(self):
00072         self.status = None
00073         
00074 class SimpleActionTask(Task):
00075     """
00076         Turn a ROS action into a Task.
00077     """
00078     def __init__(self, name, action, action_type, goal, rate=5, connect_timeout=10, result_timeout=30, reset_after=False, active_cb=None, done_cb=None, feedback_cb=None):
00079         super(SimpleActionTask, self).__init__(name)
00080         
00081         self.action = action
00082         self.goal = goal
00083         self.tick = 1.0 / rate
00084         self.rate = rospy.Rate(rate)
00085 
00086         self.result = None
00087         self.connect_timeout = connect_timeout
00088         self.result_timeout = result_timeout
00089         self.reset_after = reset_after
00090         
00091         self.final_status = None
00092         
00093         if done_cb:
00094             self.user_done_cb = done_cb
00095         else:
00096             self.user_done_cb = None
00097         
00098         self.done_cb = self.default_done_cb
00099         
00100         if active_cb == None:
00101             active_cb = self.default_active_cb
00102         self.active_cb = active_cb
00103         
00104         if feedback_cb == None:
00105             feedback_cb = self.default_feedback_cb
00106         self.feedback_cb = feedback_cb
00107                 
00108         self.action_started = False
00109         self.action_finished = False
00110         self.goal_status_reported = False
00111         self.time_so_far = 0.0
00112         
00113         # Goal state return values
00114         self.goal_states = ['PENDING', 'ACTIVE', 'PREEMPTED', 
00115                             'SUCCEEDED', 'ABORTED', 'REJECTED',
00116                             'PREEMPTING', 'RECALLING', 'RECALLED',
00117                             'LOST']
00118         
00119         self.retry_goal_states = [GoalStatus.PREEMPTED]
00120             
00121         rospy.loginfo("Connecting to action " + action)
00122 
00123         # Subscribe to the base action server
00124         self.action_client = actionlib.SimpleActionClient(action, action_type)
00125 
00126         rospy.loginfo("Waiting for action server...")
00127         
00128         # Wait up to timeout seconds for the action server to become available
00129         try:
00130             self.action_client.wait_for_server(rospy.Duration(self.connect_timeout))
00131         except:
00132             rospy.loginfo("Timed out connecting to the action server " + action)
00133     
00134         rospy.loginfo("Connected to action server")
00135 
00136     def run(self):
00137         # Send the goal
00138         if not self.action_started:
00139             rospy.loginfo("Sending " + str(self.name) + " goal to action server...")
00140             self.action_client.send_goal(self.goal, done_cb=self.done_cb, active_cb=self.active_cb, feedback_cb=self.feedback_cb)
00141             self.action_started = True
00142             self.activate_time = rospy.Time.now()
00143         
00144         ''' We cannot use the wait_for_result() method here as it will block the entire
00145             tree so we break it down in time slices of duration 1 / rate.
00146         '''
00147         if not self.action_finished:
00148             self.time_so_far += self.tick
00149             self.rate.sleep()
00150             if self.time_so_far > self.result_timeout:
00151                 self.action_client.cancel_goal()
00152                 rospy.loginfo("Timed out achieving goal")
00153                 self.action_finished = True
00154                 return TaskStatus.FAILURE
00155             else:
00156                 return TaskStatus.RUNNING
00157         else:
00158             # Check the final goal status returned by default_done_cb
00159             if self.goal_status == GoalStatus.SUCCEEDED:
00160                 self.status = TaskStatus.SUCCESS
00161             
00162             # This case handles PREEMPTED
00163             elif self.goal_status in self.retry_goal_states:
00164                 self.status = TaskStatus.RUNNING
00165                 self.action_started = False
00166                 self.action_finished = False
00167                 self.time_so_far = 0
00168             
00169             # Otherwise, consider the task to have failed
00170             else:
00171                 self.status = TaskStatus.FAILURE
00172             
00173             # Store the final status before we reset
00174             self.final_status = self.status
00175 
00176             # Reset the task if the reset_after flag is True
00177             if self.reset_after:
00178                 self.reset()
00179         
00180         self.action_client.wait_for_result(rospy.Duration(10))
00181         return self.final_status
00182                             
00183     def default_done_cb(self, result_state, result):
00184         """Goal Done Callback
00185         This callback resets the active flags and reports the duration of the action.
00186         Also, if the user has defined a result_cb, it is called here before the
00187         method returns.
00188         """
00189         self.goal_status = result_state
00190         self.action_finished = True
00191         
00192         if not self.goal_status_reported:
00193             self._duration = rospy.Time.now() - self.activate_time
00194             
00195             rospy.loginfo("Action " + self.name + " terminated after "\
00196                     + str(self._duration.to_sec()) + " seconds with result "\
00197                     + self.goal_states[self.action_client.get_state()] + ".")
00198             
00199             self.goal_status_reported = True
00200             
00201         if self.user_done_cb:
00202             self.user_done_cb(result_state, result)
00203     
00204     def default_active_cb(self):
00205         pass
00206         
00207     def default_feedback_cb(self, msg):
00208         pass
00209     
00210     def reset(self):
00211         rospy.logdebug("RESETTING " + str(self.name))
00212         self.action_started = False
00213         self.action_finished = False
00214         self.goal_status_reported = False
00215         self.status = self.final_status
00216         self.time_so_far = 0.0
00217         super(SimpleActionTask, self).reset()


pi_trees_ros
Author(s): Patrick Goebel
autogenerated on Thu Jun 6 2019 17:33:34