Go to the documentation of this file.00001
00002 import roslib
00003 roslib.load_manifest("hack_the_web_program_executor")
00004 roslib.load_manifest("museum_srvs")
00005 roslib.load_manifest("slider_gui")
00006
00007 import rospy
00008 import base64
00009 import time
00010 from threading import Lock, Thread, Condition
00011
00012 from museum_msgs.msg import *
00013 from museum_srvs.srv import *
00014 from sensor_msgs.msg import Joy
00015 from program_queue.srv import CallProgram, CallProgramResponse
00016 from actions.DefaultAction import DefaultAction
00017
00018
00019 class WebProgramExecutor:
00020
00021 lock = None
00022 executor = None
00023 previous_request = None
00024
00025 def __init__(self):
00026 self.lock = Lock()
00027 self.execution_service = rospy.Service("/museum/run_web_slider_program", CallProgram, self.execute_program)
00028 self._default_pose = DefaultAction()
00029 self._default_pose.set_duration(8.0)
00030 rospy.Subscriber('joy', Joy, self._joy_callback)
00031
00032 def execute_program(self, request):
00033 print "Received program execution request"
00034 sequence = PoseSequence()
00035 sequence.deserialize(base64.b64decode(request.code))
00036 poses = sequence.poses
00037
00038
00039 print "Executing program"
00040
00041 with self.lock:
00042 if self.executor:
00043 self.executor.cancel()
00044 self.executor = None
00045 executor = SequenceExecutor(poses, self._default_pose)
00046 executor.start()
00047 self.executor = executor
00048
00049 executor.join()
00050
00051 print "Program execution finished"
00052
00053 return CallProgramResponse()
00054
00055 def _joy_callback(self, request):
00056 triggered_buttons = request.buttons
00057 left_pressed = (not self.previous_request and request.buttons[7]) or (request.buttons[7] and not self.previous_request.buttons[7])
00058 square_pressed = (not self.previous_request and request.buttons[15]) or (request.buttons[15] and not self.previous_request.buttons[15])
00059 if left_pressed:
00060 with self.lock:
00061 if self.executor:
00062 self.executor.cancel()
00063 if square_pressed:
00064 with self.lock:
00065 if self.executor:
00066 with self.executor.play:
00067 self.executor.play.notify()
00068
00069
00070 class SequenceExecutor(Thread):
00071
00072 lock = Lock()
00073 active = True
00074 play = Condition()
00075
00076 def __init__(self, poses, default):
00077 Thread.__init__(self)
00078 self.service = rospy.ServiceProxy("/museum/pose_robot_real", PoseRobot)
00079 self.poses = poses
00080 self.default = default
00081
00082 def cancel(self):
00083 with self.lock:
00084 self.active = False
00085 with self.play:
00086 self.play.notify()
00087
00088 def run(self):
00089 with self.lock:
00090 if not self.active:
00091 print "sequence executor interrupted"
00092 return
00093 print "Moving to default pose"
00094 self.default.execute()
00095 time.sleep(8)
00096
00097 while True:
00098 with self.play:
00099 print "Awaiting play or cancel"
00100 self.play.wait()
00101 poses = self.poses
00102 print "Executing %d poses" % len(poses)
00103 for pose in poses:
00104 print "Posing robot..."
00105 with self.lock:
00106 if not self.active:
00107 print "sequence executor interrupted"
00108 return
00109 self.service.call(pose)
00110 time.sleep(pose.duration)
00111
00112 if __name__=="__main__":
00113 rospy.init_node("robot_program_executor")
00114
00115 executor = WebProgramExecutor()
00116
00117 print "Execution service started"
00118 rospy.spin()