00001 import roslib; roslib.load_manifest('rcommander_pr2_gui')
00002 import rospy
00003 import actionlib
00004
00005 from pr2_object_manipulation_msgs.srv import ActionInfo, ActionInfoResponse
00006 from pr2_object_manipulation_msgs.msg import *
00007 import rcommander.graph_model as gm
00008
00009 from PyQt4 import QtCore, QtGui
00010 import sys
00011 import signal
00012 import os
00013 import os.path as pt
00014 import pdb
00015
00016 class WatchDirectory(QtCore.QObject):
00017 def __init__(self, path, dir_changed_func=None, file_changed_func=None):
00018 self.path = path
00019 self.fs_watcher = QtCore.QFileSystemWatcher([path])
00020 self.fs_watcher.connect(self.fs_watcher, QtCore.SIGNAL('directoryChanged(QString)'), self.directory_changed)
00021 self.fs_watcher.connect(self.fs_watcher, QtCore.SIGNAL('fileChanged(QString)'), self.file_changed)
00022 self.file_changed_func = file_changed_func
00023 self.dir_changed_func = dir_changed_func
00024
00025 def __del__(self):
00026 rospy.loginfo('Deleting watcher for ' + self.path)
00027 self.fs_watcher.disconnect(self.fs_watcher,
00028 QtCore.SIGNAL('directoryChanged(QString)'), self.directory_changed)
00029 self.fs_watcher.disconnect(self.fs_watcher,
00030 QtCore.SIGNAL('fileChanged(QString)'), self.file_changed)
00031
00032 @QtCore.pyqtSlot(str)
00033 def directory_changed(self, path):
00034 if self.dir_changed_func != None:
00035 self.dir_changed_func(path)
00036
00037 @QtCore.pyqtSlot(str)
00038 def file_changed(self, path):
00039 if self.file_changed_func != None:
00040 self.file_changed_func(path)
00041
00042 class RCommanderAutoServer:
00043
00044 def __init__(self, robot, path_to_rcommander_files):
00045 self.path_to_rcommander_files = path_to_rcommander_files
00046 self.robot = robot
00047 self.action_dict = {}
00048 self.main_dir_watcher = WatchDirectory(self.path_to_rcommander_files, self.main_directory_changed)
00049 self.main_directory_changed(self.path_to_rcommander_files)
00050
00051 rospy.Service('list_rcommander_actions', ActionInfo, self.list_action_cb)
00052 self.actserv = actionlib.SimpleActionServer('run_rcommander_action', RunScriptAction, execute_cb=self.execute_cb, auto_start=False)
00053 self.actserv.start()
00054
00055 def execute_cb(self, goal):
00056 rospy.loginfo('Requested: group ' + goal.group_name + ' action: ' + goal.action_name)
00057 self.action_dict[goal.action_name]['server'].execute(self.actserv)
00058
00059 def _find_all_actions(self):
00060 dirs = []
00061 for d in os.listdir(self.path_to_rcommander_files):
00062 if os.path.isdir(os.path.join(self.path_to_rcommander_files, d)):
00063 dirs.append(d)
00064 return dirs
00065
00066 def _load(self, action):
00067 rospy.loginfo('Loading ' + action)
00068 action_path = os.path.join(self.path_to_rcommander_files, action)
00069 for i in range(3):
00070 try:
00071 load_dict = {'server': ScriptedActionServer(action, action_path, self.robot),
00072 'watcher': WatchDirectory(action_path, self.action_directory_changed)}
00073 rospy.loginfo('Successfully loaded ' + action)
00074 return load_dict
00075 except IOError, e:
00076 rospy.loginfo(str(e))
00077 rospy.loginfo('IOError encountered, retrying.')
00078 rospy.sleep(1)
00079
00080 def action_directory_changed(self, action_path_name):
00081 action_path_name = str(action_path_name)
00082 action_name = pt.split(action_path_name)[1]
00083 rospy.loginfo('action_name ' + action_name)
00084 rospy.loginfo('action_directory_changed: ' + action_name)
00085 self.action_dict[action_name] = self._load(action_name)
00086
00087 def main_directory_changed(self, main_path_name):
00088 rospy.loginfo('main_directory_changed: rescanning ' + main_path_name)
00089 ndict = {}
00090 actions = self._find_all_actions()
00091 for action in actions:
00092 if self.action_dict.has_key(action):
00093 ndict[action] = self.action_dict[action]
00094 else:
00095 loaded_action = self._load(action)
00096 if loaded_action != None:
00097 ndict[action] = loaded_action
00098 else:
00099 rospy.loginfo('Failed to load ' + action)
00100 self.action_dict = ndict
00101
00102 def list_action_cb(self, req):
00103 actions = self.action_dict.keys()
00104 actions.sort()
00105 return ActionInfoResponse(actions)
00106
00107 class ScriptedActionServer:
00108
00109 def __init__(self, action_name, path_to_action, robot):
00110 self.action_name = action_name
00111 self.path_to_action = path_to_action
00112 self.robot = robot
00113 self.graph_model = gm.GraphModel.load(self.path_to_action)
00114
00115
00116
00117 def execute(self, actserver):
00118 r = rospy.Rate(30)
00119
00120 state_machine = self.graph_model.create_state_machine(self.robot)
00121 self.graph_model.run(self.action_name, state_machine=state_machine)
00122 state_machine_output = None
00123
00124
00125 while True:
00126 if actserver.is_preempt_requested():
00127 self.graph_model.preempt()
00128 actserver.set_preempted()
00129 success = False
00130 break
00131
00132 if not self.graph_model.is_running():
00133 outcome = self.graph_model.get_last_outcome()
00134 if outcome != None:
00135 state_machine_output, end_time = outcome
00136 success = True
00137 else:
00138 success = False
00139 break
00140
00141 r.sleep()
00142
00143 if success:
00144 result = RunScriptResult(state_machine_output)
00145 rospy.loginfo("%s: succeeded with %s" % (self.action_name, state_machine_output))
00146 actserver.set_succeeded(result)
00147 else:
00148 actserver.set_aborted()
00149
00150 def run(robot, path):
00151
00152
00153
00154
00155 app = QtGui.QApplication(sys.argv)
00156 signal.signal(signal.SIGINT, signal.SIG_DFL)
00157 server = RCommanderAutoServer(robot, path)
00158 rospy.loginfo('RCommander server UP!')
00159 app.exec_()
00160