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()