Go to the documentation of this file.00001
00002 import threading
00003 import rospy
00004 import smach
00005 import smach_ros
00006 import ctypes
00007 import time
00008
00009 class UserStoppedException:
00010 def __init__(self):
00011 self.msg = "Stopped"
00012
00013 def __str__(self):
00014 return repr(self.msg)
00015
00016 class ThreadRunSM(threading.Thread):
00017
00018 def __init__(self, sm_name, sm):
00019 threading.Thread.__init__(self)
00020 self.sm = sm
00021 self.sm_name = sm_name
00022 self.outcome = None
00023
00024 self.exception = None
00025 self.termination_func = None
00026
00027 def register_termination_cb(self, func):
00028 self.termination_func = func
00029
00030 def run(self):
00031 rospy.loginfo('ThreadRunSM started %s' % self.sm_name)
00032 try:
00033
00034
00035 self.outcome = self.sm.execute()
00036 rospy.loginfo('ThreadRunSM.run: execution finished outcome %s' % self.outcome)
00037
00038 except smach.InvalidTransitionError, e:
00039 rospy.loginfo('ThreadRunSM: got InvalidTransitionError %s' % str(e))
00040 self.exception = e
00041
00042 except UserStoppedException, e:
00043
00044 self.exception = e
00045 rospy.loginfo('ThreadRunSM: execution stopped by user.')
00046
00047 if self.termination_func != None:
00048 self.termination_func(self.exception)
00049
00050
00051 rospy.loginfo('ThreadRunSM.run: exiting')
00052
00053 def preempt(self):
00054 if self.isAlive():
00055 self.sm.request_preempt()
00056
00057 def except_preempt(self):
00058 while self.isAlive():
00059 self._raise_exception()
00060 time.sleep(2.)
00061 if self.isAlive():
00062 threading.Thread._Thread__stop(self)
00063
00064 def _raise_exception(self):
00065
00066 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(self.ident), ctypes.py_object(SystemExit))
00067 print 'raised exception returned', res
00068 if res == 0:
00069 raise ValueError("Invalid thread ID")
00070 elif res != 1:
00071
00072
00073 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
00074 raise SystemError("PyThreadState_SetAsyncExc failed")