00001
00002 import roslib; roslib.load_manifest('ptu_control')
00003 import rospy
00004 from sensor_msgs.msg import JointState
00005 from logitech_pantilt.msg import PanTilt
00006 from ptu_control.Calibration import pantiltReset
00007 import actionlib
00008 import ptu_control.ptu_tracker
00009 import ptu_control.msg
00010 import threading
00011
00012 import tf
00013 import geometry_msgs.msg
00014
00015
00016 class PTUControl(object):
00017
00018 pan = 0
00019 tilt = 0
00020 pan_vel = 0
00021 tilt_vel = 0
00022 state_lock = threading.Lock()
00023
00024 kf = ptu_control.ptu_tracker.PanTiltKF()
00025
00026 def __init__(self, reset=True):
00027 self.PAN_RANGE = rospy.get_param('pan_range', 70)
00028 self.TILT_RANGE = rospy.get_param('tilt_range', 30)
00029 self.PARENT_FRAME = rospy.get_param('parent_frame', 'odom')
00030 self.PTU_FRAME = rospy.get_param('parent_frame', 'ptu')
00031
00032
00033
00034 self.joint_pub = rospy.Publisher('state', JointState)
00035 self.ptu_pub = rospy.Publisher('/pantilt', PanTilt)
00036 self.as_goto = actionlib.SimpleActionServer('SetPTUState', \
00037 ptu_control.msg.PtuGotoAction, execute_cb=self.cb_goto)
00038 self.as_reset = actionlib.SimpleActionServer('ResetPtu', \
00039 ptu_control.msg.PtuResetAction, execute_cb=self.cb_reset)
00040 rospy.Subscriber('ground_truth_pantilt', PanTilt, self.ground_truth_cb)
00041
00042 self.br = tf.TransformBroadcaster()
00043 threading.Thread(target=self.send_transform).start()
00044
00045 if reset:
00046 rospy.sleep(1.0)
00047 pantiltReset(self.ptu_pub)
00048
00049 def cb_goto(self, msg):
00050 self.state_lock.acquire()
00051 pan, tilt, pan_vel, tilt_vel = msg.pan, msg.tilt, msg.pan_vel, msg.tilt_vel
00052 pan = min(pan, self.PAN_RANGE)
00053 pan = max(pan, -self.PAN_RANGE)
00054 tilt = min(tilt, self.TILT_RANGE)
00055 tilt = max(tilt, -self.TILT_RANGE)
00056
00057 pan_cmd = pan - self.pan
00058 tilt_cmd = tilt - self.tilt
00059
00060 self.pan, self.tilt = self.kf.control((pan_cmd, tilt_cmd))
00061
00062
00063
00064
00065 if pan_cmd == 0 and tilt_cmd == 0:
00066 pass
00067 else:
00068 self.ptu_pub.publish(PanTilt(pan=pan_cmd,tilt=tilt_cmd,reset=False))
00069
00070 result = ptu_control.msg.PtuGotoResult()
00071 result.state.position = [self.pan, self.tilt]
00072 self.state_lock.release()
00073 self.as_goto.set_succeeded(result)
00074
00075
00076
00077 def cb_reset(self, msg):
00078 self.kf.__init__()
00079
00080 self.state_lock.acquire()
00081 pantiltReset(self.ptu_pub)
00082 result = ptu_control.msg.PtuResetResult()
00083 self.pan = 0
00084 self.tilt = 0
00085 self.state_lock.release()
00086 self.as_reset.set_succeeded(result)
00087
00088 def ground_truth_cb(self, msg):
00089 self.state_lock.acquire()
00090
00091
00092 self.pan, self.tilt = self.kf.measurement((msg.pan, msg.tilt))
00093 self.state_lock.release()
00094
00095
00096 def send_transform(self):
00097 rate = rospy.Rate(10)
00098 while not rospy.is_shutdown():
00099 self.br.sendTransform(
00100 (0,0,0),
00101 tf.transformations.quaternion_from_euler(0, self.tilt, self.pan),
00102 rospy.Time.now(),
00103 self.PTU_FRAME,
00104 self.PARENT_FRAME
00105 )
00106 rate.sleep()
00107
00108 if __name__ == '__main__':
00109 rospy.init_node('ptu_node')
00110 PTUControl()
00111 rospy.spin()