6 import mongodb_store.util
as dc_util
8 from actionlib_msgs.msg
import GoalStatus
9 from geometry_msgs.msg
import Pose, Point, Quaternion
10 from mongodb_store.message_store
import MessageStoreProxy
11 from topological_navigation.msg
import GotoNodeAction, GotoNodeGoal
13 from std_srvs.srv
import Empty, EmptyResponse
14 from std_msgs.msg
import String
16 from smach_ros
import SimpleActionState, IntrospectionServer
22 super(ExecutorState , self ).
__init__(outcomes=outcomes, input_keys=[
'task'])
26 def __init__(self, duration, pause_secs=1, can_finish=None):
27 super(TimerState , self ).
__init__(outcomes=[
'succeeded',
'preempted',
'aborted'])
29 self.
pause = rospy.Duration(pause_secs)
30 if can_finish
is None:
36 now = rospy.get_rostime()
38 while now < target
and not self.preempt_requested()
and not rospy.is_shutdown():
39 rospy.sleep(self.
pause)
40 now = rospy.get_rostime()
43 while not self.
can_finish()
and not self.preempt_requested()
and not rospy.is_shutdown():
44 rospy.sleep(self.
pause)
45 rospy.loginfo(
'Waiting for signal that I can finish after timeout')
47 if rospy.is_shutdown():
49 elif self.preempt_requested():
59 ExecutorState.__init__(self, task_executor, outcomes=[
'aborted'])
62 rospy.logwarn(
'Task failed')
63 completed = userdata.task
64 self.executor.active_task =
None
65 self.executor.log_task_event(userdata.task, TaskEvent.TASK_FAILED, rospy.get_rostime())
66 self.executor.task_failed(completed)
67 rospy.loginfo(
'Execution of task %s failed' % userdata.task.task_id)
72 ExecutorState.__init__(self, task_executor, outcomes=[
'succeeded'])
75 now = rospy.get_rostime()
77 completed = userdata.task
78 self.executor.active_task =
None
79 self.executor.log_task_event(userdata.task, TaskEvent.TASK_SUCCEEDED, rospy.get_rostime())
81 self.executor.task_succeeded(completed)
82 rospy.loginfo(
'Execution of task %s succeeded' % userdata.task.task_id)
88 ExecutorState.__init__(self, task_executor, outcomes=[
'preempted'])
91 rospy.loginfo(
'Execution of task %s was cancelled' % userdata.task.task_id)
92 self.executor.log_task_event(userdata.task, TaskEvent.TASK_PREEMPTED, rospy.get_rostime())
94 if self.executor.active_task
is not None and self.executor.active_task.task_id == userdata.task.task_id:
95 completed = userdata.task
96 self.executor.active_task =
None
97 self.executor.task_failed(completed)
103 ExecutorState.__init__(self, task_executor, outcomes=[
'succeeded'])
107 self.executor.log_task_event(userdata.task, TaskEvent.TASK_STARTED, rospy.get_rostime())
108 self.executor.prepare_task(userdata.task)
112 """ Provides a base executor using Smach """
117 super( AbstractTaskExecutor, self ).
__init__()
127 if self.
sis is not None:
133 rospy.logerr(
'SMACH thread has not shut down properly. Continuing with execution regardless')
142 rospy.loginfo(
'Nav started to %s for task %s, action %s' % (task.start_node_id, task.task_id, task.action))
143 self.
log_task_event(task, TaskEvent.NAVIGATION_STARTED, rospy.get_rostime())
153 rospy.loginfo(
'Nav terminated with outcome %s' % container_outcome)
154 if container_outcome ==
'succeeded':
155 self.
log_task_event(userdata.task, TaskEvent.NAVIGATION_SUCCEEDED, rospy.get_rostime())
156 elif container_outcome ==
'preempted':
157 self.
log_task_event(userdata.task, TaskEvent.NAVIGATION_PREEMPTED, rospy.get_rostime())
159 self.
log_task_event(userdata.task, TaskEvent.NAVIGATION_FAILED, rospy.get_rostime())
163 rospy.loginfo(
'Action %s started for task %s' % (task.action, task.task_id))
164 self.
log_task_event(task, TaskEvent.EXECUTION_STARTED, rospy.get_rostime())
167 if outcome_map[
'MONITORED'] ==
'succeeded':
169 if outcome_map[
"MONITORED"] ==
"aborted" or outcome_map[
"MONITORING"] ==
"aborted":
171 if outcome_map[
"MONITORING"] ==
"succeeded":
173 if outcome_map[
"MONITORED"] ==
"preempted" or outcome_map[
"MONITORING"] ==
"preempted":
192 rospy.loginfo(
'Action terminated with outcome %s' % container_outcome)
193 if container_outcome ==
'succeeded':
194 self.
log_task_event(userdata.task, TaskEvent.EXECUTION_SUCCEEDED, rospy.get_rostime())
195 elif container_outcome ==
'preempted':
196 self.
log_task_event(userdata.task, TaskEvent.EXECUTION_PREEMPTED, rospy.get_rostime())
198 self.
log_task_event(userdata.task, TaskEvent.EXECUTION_FAILED, rospy.get_rostime())
201 """ Called to trigger execution of given task. """
206 rospy.loginfo(
'Execution of task %s was requested' % task.task_id)
209 self.
task_sm = smach.StateMachine([
'succeeded',
'aborted',
'preempted'])
210 self.task_sm.userdata.task = task
216 if task.start_node_id !=
'':
217 init_transition = {
'succeeded':
'TASK_NAVIGATION'}
219 init_transition = {
'succeeded':
'TASK_EXECUTION'}
221 smach.StateMachine.add(
'TASK_INITIALISATION',
TaskInitialisation(self), transitions=init_transition)
224 smach.StateMachine.add(
'TASK_SUCCEEDED',
TaskSucceeded(self), transitions={
'succeeded':
'succeeded'})
225 smach.StateMachine.add(
'TASK_CANCELLED',
TaskCancelled(self), transitions={
'preempted':
'preempted'})
226 smach.StateMachine.add(
'TASK_FAILED',
TaskFailed(self), transitions={
'aborted':
'aborted'})
231 concurrence_child_term_cb =
lambda so:
True
235 if task.start_node_id !=
'':
237 nav_transitions = {
'preempted':
'TASK_CANCELLED',
'aborted':
'TASK_FAILED'}
240 if task.action ==
'':
241 nav_transitions[
'succeeded'] =
'TASK_SUCCEEDED'
244 nav_transitions[
'succeeded'] =
'TASK_EXECUTION'
248 nav_concurrence = smach.Concurrence(outcomes=[
'succeeded',
'preempted',
'aborted'],
249 default_outcome=
'aborted',
251 child_termination_cb=concurrence_child_term_cb)
255 nav_concurrence.userdata.task = task
257 with nav_concurrence:
260 nav_goal = GotoNodeGoal(target = task.start_node_id)
264 smach.Concurrence.add(
'MONITORED',
267 SimpleActionState(
'topological_navigation',
270 smach.Concurrence.add(
'MONITORING',
TimerState(duration=monitor_duration))
272 smach.StateMachine.add(
'TASK_NAVIGATION', nav_concurrence, transitions=nav_transitions)
275 if task.action !=
'':
278 action_clz = dc_util.load_class(dc_util.type_to_class_string(action_string))
279 goal_clz = dc_util.load_class(dc_util.type_to_class_string(goal_string))
282 goal = goal_clz(*argument_list)
285 action_concurrence = smach.Concurrence(outcomes=[
'succeeded',
'preempted',
'aborted'],
286 default_outcome=
'aborted',
288 child_termination_cb=concurrence_child_term_cb)
293 action_concurrence.userdata.task = task
295 with action_concurrence:
296 smach.Concurrence.add(
'MONITORED', SimpleActionState(task.action, action_clz, goal=goal))
297 wiggle_room = rospy.Duration(5)
300 def task_can_be_interrupted():
303 smach.Concurrence.add(
'MONITORING',
TimerState(duration=(task.max_duration+wiggle_room), can_finish=task_can_be_interrupted))
305 smach.StateMachine.add(
'TASK_EXECUTION',
307 transitions={
'preempted':
'TASK_CANCELLED',
'aborted':
'TASK_FAILED',
'succeeded':
'TASK_SUCCEEDED'})
310 rospy.logwarn(
'Caught exception when creating the task to execute: %s' % e)
314 self.task_sm.set_initial_state([
'TASK_INITIALISATION'])
316 self.
sis = IntrospectionServer(
'task_executor', self.
task_sm,
'/TASK_ROOT')
319 self.
smach_thread = threading.Thread(target=self.task_sm.execute)
320 self.smach_thread.start()
323 """ Returns true of the smach_thread has been terminated successfully """
325 self.join_lock.acquire()
327 successfully_joined =
True
330 if self.
smach_thread is not None and self.smach_thread.is_alive():
331 self.smach_thread.join(timeout)
333 successfully_joined =
not self.smach_thread.is_alive()
335 self.join_lock.release()
337 return successfully_joined
340 preempt_timeout_secs = 30
342 rospy.loginfo(
'Requesting preempt on state machine in state %s' % self.task_sm.get_active_states())
343 self.task_sm.request_preempt()
344 rospy.loginfo(
'Waiting for exit')
347 rospy.logerr(
'Task action or navigation did not preempt after %s seconds. State at end was %s' % (preempt_timeout_secs, self.task_sm.get_active_states()))
353 rospy.loginfo(
'And relax')
def expected_navigation_duration(self, task)
def nav_termination_cb(self, userdata, terminal_states, container_outcome)
def task_failed(self, task)
def execute(self, userdata)
def nav_start_cb(self, userdata, initial_states)
def execute(self, userdata)
def is_task_interruptible(self, task)
def outcome_cb(self, outcome_map)
def get_arguments(self, argument_list)
def execute(self, userdata)
def execute(self, userdata)
def __init__(self, task_executor, outcomes)
def execute_task(self, task)
def cancel_active_task(self)
def get_task_types(self, action_name)
def __init__(self, task_executor)
def __init__(self, task_executor)
def join_smach_thread(self, timeout)
def action_termination_cb(self, userdata, terminal_states, container_outcome)
def __init__(self, task_executor)
def __init__(self, task_executor)
def execute(self, userdata)
def action_start_cb(self, userdata, initial_states)