state_machine_tool.py
Go to the documentation of this file.
00001 #import roslib; roslib.load_manifest('rcommander_core')
00002 import rospy
00003 from PyQt4.QtGui import *
00004 from PyQt4.QtCore import *
00005 import tool_utils as tu
00006 import smach
00007 import os.path as pt
00008 import graph_model as gm
00009 
00010 
00011 class StateMachineTool(tu.ToolBase):
00012 
00013     def __init__(self, rcommander):
00014         tu.ToolBase.__init__(self, rcommander, 'state_machine', 'State Machine', StateMachineNode)
00015         self.child_gm = None
00016 
00017     def fill_property_box(self, pbox):
00018         formlayout = pbox.layout()
00019         self.filename_edit = QLineEdit(pbox)
00020         self.filename_edit.setText("...")
00021         self.open_file_button = QPushButton(pbox)
00022         self.open_file_button.setText('Select...')
00023         self.rcommander.connect(self.open_file_button, SIGNAL('clicked()'), self.open_file_cb)
00024 
00025         formlayout.addRow('&Filename', self.filename_edit)
00026         formlayout.addRow(self.open_file_button)
00027 
00028     def open_file_cb(self):
00029         dialog = QFileDialog(self.rcommander, 'Open State Machine', '~')
00030         dialog.setFileMode(QFileDialog.Directory)
00031         dialog.setViewMode(QFileDialog.List)
00032 
00033         #Fix messed up bug, weird interaction between file dialog and rospy!
00034         import rospy.core as rpc
00035         rpc._shutdown_flag = False
00036 
00037         if dialog.exec_():
00038             filenames = dialog.selectedFiles()
00039             filename = str(filenames[0])
00040             self.filename_edit.setText(filename)
00041 
00042     def new_node(self, name=None):
00043         child_gm = self.child_gm
00044         self.child_gm = None
00045 
00046         if (child_gm == None) and (str(self.filename_edit.text()) != '...'):
00047             #nname = pt.split(str(self.filename_edit.text()))[1]
00048             print 'state machine tool loading', self.filename_edit.text()
00049             child_gm = gm.GraphModel.load(str(self.filename_edit.text()))
00050             #curr_document = gm.FSMDocument(child_gm.get_document().get_name(), modified=True, real_filename=False)
00051             curr_document = gm.FSMDocument(name, modified=True, real_filename=False)
00052             child_gm.set_document(curr_document)
00053         else:
00054             if child_gm != None:
00055                 curr_document = gm.FSMDocument(name, modified=True, real_filename=False)
00056                 child_gm.set_document(curr_document)
00057                 return StateMachineNode(name, child_gm)
00058             if name == None:
00059                 nname = self.name + str(self.counter)
00060                 return StateMachineNode(nname, None)
00061             else:
00062                 #raise RuntimeError('Need to specify filename.')
00063                 return None
00064 
00065         return StateMachineNode(name, child_gm)
00066 
00067     def set_node_properties(self, my_node):
00068         self.child_gm = my_node.child_gm
00069         if self.child_gm == None:
00070             return
00071         if self.child_gm.get_document() != None:
00072             fname = self.child_gm.get_document().get_filename()
00073             if fname != None:
00074                 self.filename_edit.setText(fname)
00075 
00076     def reset(self):
00077         self.filename_edit.setText("...")
00078         self.child_gm = None
00079 
00080 
00081 class StateMachineNode(tu.EmbeddableState):
00082 
00083     def __init__(self, name, child_gm):
00084         tu.EmbeddableState.__init__(self, name, child_gm)
00085 
00086     def get_smach_state(self):
00087         return StateMachineNodeSmach(self.child_gm)
00088 
00089     def recreate(self, graph_model):
00090         #return StateMachineNode(graph_model.document.get_name(), graph_model)
00091         return StateMachineNode(self.get_name(), graph_model)
00092 
00093 class StateMachineNodeSmach(smach.State):
00094 
00095     def __init__(self, child_gm):
00096         self.child_gm = child_gm
00097 
00098     def set_robot(self, robot):
00099         self.robot = robot
00100         input_keys = []
00101         output_keys = []
00102         outcomes = []
00103         if self.child_gm != None:
00104             sm = self.child_gm.create_state_machine(robot)
00105             input_keys = list(sm.get_registered_input_keys())
00106             output_keys = list(sm.get_registered_output_keys())
00107             outcomes = list(sm.get_registered_outcomes()) + ['preempted']
00108         smach.State.__init__(self, outcomes = outcomes, input_keys = input_keys, output_keys = output_keys)
00109 
00110 
00111     def execute(self, userdata):
00112         child_gm = self.child_gm
00113         sm = child_gm.create_state_machine(self.robot, userdata=userdata._ud)
00114         child_gm.run(self.child_gm.get_start_state(), state_machine=sm)
00115         rthread = child_gm.sm_thread['run_sm']
00116 
00117         preempted = False
00118         r = rospy.Rate(30)
00119         while True:
00120             if rthread.exception != None:
00121                 raise rthread.exception
00122 
00123             if rthread.outcome != None:
00124                 rospy.loginfo('State Machine Node: child node finished with outcome ' + rthread.outcome)
00125                 break
00126 
00127             if not rthread.isAlive():
00128                 rospy.loginfo('State Machine Node: child node died')
00129                 break
00130 
00131             if self.preempt_requested():
00132                 rospy.loginfo('State Machine Node: preempt requested')
00133                 rthread.preempt()
00134                 self.service_preempt()
00135                 preempted = True
00136                 break
00137 
00138             r.sleep()
00139 
00140         #child_gm.sm_thread = {} #Reset sm thread dict
00141         if preempted:
00142             return 'preempted'
00143         else:
00144             return rthread.outcome
00145 
00146 
00147 ###
00148 ## need to be able to generate state machines
00149 ## act as a smach state, like gripper event but does nothing else beside execute state machine
00150 ## TODO: maybe we can recognize this special case in graph model and add its child state machine directly during compilation?
00151 #class StateMachineNode(smach.State, tu.EmbeddableState): 
00152 #
00153 #    def __init__(self, name, child_gm):
00154 #        tu.EmbeddableState.__init__(self, name, child_gm)
00155 #        self.__init_unpicklables__()
00156 #
00157 #    def __init_unpicklables__(self):
00158 #        #Init smach stuff
00159 #        input_keys = []
00160 #        output_keys = []
00161 #        outcomes = []
00162 #
00163 #        if self.get_child() != None:
00164 #            sm = self.get_child().create_state_machine()
00165 #            input_keys = list(sm.get_registered_input_keys())
00166 #            output_keys = list(sm.get_registered_output_keys())
00167 #            outcomes = list(sm.get_registered_outcomes())         
00168 #        smach.State.__init__(self, outcomes = outcomes, input_keys = input_keys, output_keys = output_keys)
00169 #
00170 #    def execute(self, userdata):
00171 #        child_gm = self.get_child()
00172 #        sm = child_gm.create_state_machine(userdata=userdata._ud)
00173 #        child_gm.run(self.child_gm.get_start_state(), state_machine=sm)
00174 #        rthread = child_gm.sm_thread['run_sm']
00175 #
00176 #        preempted = False
00177 #        r = rospy.Rate(100)
00178 #        while True:
00179 #            if rthread.exception != None:
00180 #                raise rthread.exception
00181 #
00182 #            if rthread.outcome != None:
00183 #                rospy.loginfo('State Machine Node: child node finished with outcome ' + rthread.outcome)
00184 #                break
00185 #
00186 #            if not rthread.isAlive():
00187 #                rospy.loginfo('State Machine Node: child node died')
00188 #                break
00189 #
00190 #            if self.preempt_requested():
00191 #                rospy.loginfo('State Machine Node: preempt requested')
00192 #                self.service_preempt()
00193 #                preempted = True
00194 #                break
00195 #
00196 #        rthread.preempt()
00197 #        rthread.except_preempt()
00198 #        child_gm.sm_thread = {} #Reset sm thread dict
00199 #        if preempted:
00200 #            return 'preempted'
00201 #        else:
00202 #            return rthread.outcome
00203 #
00204 #    def recreate(self, graph_model):
00205 #        return StateMachineNode(graph_model.document.get_name(), graph_model)
00206 #
00207 #    def __getstate__(self):
00208 #        state = tu.EmbeddableState.__getstate__(self)
00209 #        return {'state_base': state}
00210 #
00211 #    def __setstate__(self, state):
00212 #        tu.EmbeddableState.__setstate__(self, state['state_base'])
00213 #        self.__init_unpicklables__()
00214 
00215 


rcommander
Author(s): Hai Nguyen (haidai@gmail.com)
autogenerated on Thu Nov 28 2013 11:46:34