pinger.py
Go to the documentation of this file.
00001 #
00002 # License: BSD
00003 #   https://raw.github.com/robotics-in-concert/rocon_tools/license/LICENSE
00004 #
00005 ##############################################################################
00006 # Imports
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 # Helper class
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 # Pinger class
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         # Keep track of the last 5 values
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             # In case of failure, this call will take approx 10s
00076             try:
00077                 # Send 5 pings at an interval of 0.2s
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                     # Since this was a single ping, min = max = avg
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                     # Had one occasion when something was wrong with ping output
00095                     rospy.logwarn("Unable to update latency statistics from " +
00096                                   self.ip + ". Error parsing ping output: " +
00097                                   str(e))
00098             except subprocess.CalledProcessError:
00099                 # Ping failed. Do not update time last seen
00100                 pass
00101             rate.sleep()


rocon_python_utils
Author(s): Daniel Stonier
autogenerated on Fri May 2 2014 10:35:39