Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 from rocon_python_comms import WallRate
00010
00011 import rospy
00012 import subprocess
00013 import threading
00014 import time
00015
00016
00017
00018
00019
00020
00021 def mean(vals):
00022 return sum(vals) / len(vals)
00023
00024
00025 def mdev(vals):
00026 mean_val = mean(vals)
00027 mean_diff = [abs(vals[i] - mean_val) for i in range(len(vals))]
00028 return mean(mean_diff)
00029
00030
00031
00032
00033
00034
00035 class Pinger(threading.Thread):
00036 '''
00037 The pinger class can run a threaded pinger at the desired frequency to
00038 check if a machine is available or not
00039 '''
00040
00041 def __init__(self, ip, ping_frequency=0.2):
00042
00043 threading.Thread.__init__(self)
00044 self.daemon = True
00045
00046 self.ip = ip
00047 self.ping_frequency = ping_frequency
00048 self.time_last_seen = time.time()
00049
00050
00051 self.buffer_size = 5
00052 self.buffer = [0.0, 0.0, 0.0, 0.0, 0.0]
00053 self.values_available = 0
00054 self.current_ring_counter = 0
00055
00056 def get_time_since_last_seen(self):
00057 return time.time() - self.time_last_seen
00058
00059 def get_latency(self):
00060 '''
00061 Latency states are returned as list of 4 values
00062 [min,avg,max,mean deviation]
00063 '''
00064 if self.values_available == 0:
00065 return [0.0, 0.0, 0.0, 0.0]
00066 latency_stats = [min(self.buffer[:self.values_available]),
00067 mean(self.buffer[:self.values_available]),
00068 max(self.buffer[:self.values_available]),
00069 mdev(self.buffer[:self.values_available])]
00070 return latency_stats
00071
00072 def run(self):
00073 rate = WallRate(self.ping_frequency)
00074 while True:
00075
00076 try:
00077
00078 output = subprocess.check_output("ping -c 1 %s" % self.ip,
00079 shell=True, stderr=subprocess.STDOUT)
00080 self.time_last_seen = time.time()
00081 try:
00082 parsed_output = \
00083 output.splitlines()[-1].split(' ')[3].split('/')
00084 latency_stats = [float(x) for x in parsed_output]
00085
00086 self.buffer[self.current_ring_counter] = latency_stats[1]
00087 self.values_available = self.values_available + 1 \
00088 if self.values_available < self.buffer_size \
00089 else self.buffer_size
00090 self.current_ring_counter = \
00091 (self.current_ring_counter + 1) % self.buffer_size
00092
00093 except (KeyError, ValueError) as e:
00094
00095 rospy.logwarn("Unable to update latency statistics from " +
00096 self.ip + ". Error parsing ping output: " +
00097 str(e))
00098 except subprocess.CalledProcessError:
00099
00100 pass
00101 rate.sleep()