Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 from __future__ import with_statement
00038
00039 PKG='continuous_ops_alerts'
00040 import roslib; roslib.load_manifest(PKG)
00041
00042 import rospy
00043 from googlevoice import Voice
00044 from googlevoice.util import input
00045
00046 import tf2
00047 import tf2_ros
00048
00049 import math
00050
00051 from geometry_msgs.msg import PoseStamped
00052 from pr2_msgs.msg import PowerState
00053 from std_msgs.msg import Bool
00054 import tf2_geometry_msgs
00055
00056 import threading
00057
00058 class ContinuousOpsMonitor:
00059 def __init__(self, voice):
00060 self.voice = voice
00061 self.tf_client = tf2_ros.BufferClient('tf2_buffer_server')
00062 rospy.loginfo('Continuous ops monitor waiting for tf server')
00063 self.tf_client.wait_for_server()
00064 rospy.loginfo('Continuous ops monitor connected to tf server')
00065
00066 self.move_distance = rospy.get_param('~move_distance', 2.0)
00067 self.move_timeout = rospy.get_param('~move_timeout', 300.0)
00068
00069 self.phone_numbers = ['5107100513', '6505294522']
00070
00071 self.last_pose = PoseStamped()
00072 self.last_pose.header.stamp = rospy.Time.now()
00073
00074 self.mutex = threading.Lock()
00075 self.plugged_in = True
00076
00077 self.power_sub = rospy.Subscriber('power_state', PowerState, self.power_cb)
00078 self.motor_sub = rospy.Subscriber('pr2_etherCAT/motors_halted', Bool, self.motor_cb)
00079 self.motors_halted = False
00080
00081
00082 def motor_cb(self, msg):
00083 with self.mutex:
00084 if msg.data:
00085 if not self.motors_halted:
00086 self.send_sms('My leg hurts, by casters suck, my motors halted... ')
00087 self.motors_halted = True
00088 else:
00089 self.motors_halted = False
00090
00091 def power_cb(self, msg):
00092 with self.mutex:
00093 if msg.AC_present == 0:
00094 if self.plugged_in:
00095 self.last_pose.header.stamp = rospy.Time.now()
00096 self.plugged_in = False
00097
00098 else:
00099 self.plugged_in = True
00100
00101 def distance(self, p1, p2):
00102 dx = p1.pose.position.x - p2.pose.position.x
00103 dy = p1.pose.position.y - p2.pose.position.y
00104 distance = math.sqrt(dx * dx + dy * dy)
00105 return distance
00106
00107 def distance_check(self):
00108 base_pose = PoseStamped()
00109 base_pose.header.stamp = rospy.Time(0.0)
00110 base_pose.header.frame_id = 'base_link'
00111 base_pose.pose.orientation.w = 1.0
00112
00113 try:
00114 map_pose = self.tf_client.transform(base_pose, 'map')
00115 dist = self.distance(map_pose, self.last_pose)
00116
00117
00118 if dist > self.move_distance:
00119 self.last_pose = map_pose
00120 return
00121
00122
00123 if self.last_pose.header.stamp + rospy.Duration(self.move_timeout) < rospy.Time.now():
00124 self.send_sms('Robot has not moved in %s seconds, please check if it needs help.' % self.move_timeout)
00125
00126 self.last_pose.header.stamp = rospy.Time.now()
00127
00128 except tf2.TransformException as e:
00129 rospy.logerr("%s" % e)
00130
00131 def send_sms(self, text):
00132 for number in self.phone_numbers:
00133 self.voice.send_sms(number, text)
00134
00135 def run(self):
00136 r = rospy.Rate(0.1)
00137 while not rospy.is_shutdown():
00138 with self.mutex:
00139 if not self.plugged_in:
00140
00141 self.distance_check()
00142 r.sleep()
00143
00144 if __name__ == '__main__':
00145 rospy.init_node('continuous_ops_alert')
00146 voice = Voice()
00147 voice.login()
00148 com = ContinuousOpsMonitor(voice)
00149
00150 try:
00151 com.run()
00152 except rospy.ROSInterruptException: pass
00153