Go to the documentation of this file.00001
00002
00003 """
00004 rosping_existence.py
00005
00006 check the existence of the ros nodes and publish the result to diagnostics
00007 """
00008
00009 import rospy
00010 try:
00011 from xmlrpc.client import ServerProxy
00012 except ImportError:
00013 from xmlrpclib import ServerProxy
00014
00015 from rosnode import *
00016 import sys
00017 import roslaunch
00018 import diagnostic_updater
00019 import diagnostic_msgs
00020
00021 def _succeed(args):
00022 code, msg, val = args
00023 if code != 1:
00024 raise ROSNodeException("remote call failed: %s"%msg)
00025 return val
00026
00027 def ping(node_name, max_count=None, verbose=False):
00028 """
00029 Test connectivity to node by calling its XMLRPC API
00030 @param node_name: name of node to ping
00031 @type node_name: str
00032 @param max_count: number of ping requests to make
00033 @type max_count: int
00034 @param verbose: print ping information to screen
00035 @type verbose: bool
00036 @return: True if node pinged
00037 @rtype: bool
00038 @raise ROSNodeIOException: if unable to communicate with master
00039 """
00040 master = rosgraph.Master(ID)
00041 node_api = get_api_uri(master,node_name)
00042 if not node_api:
00043
00044 return False
00045
00046 timeout = 3.
00047
00048 if verbose:
00049 print("pinging %s with a timeout of %ss"%(node_name, timeout))
00050 socket.setdefaulttimeout(timeout)
00051 node = ServerProxy(node_api)
00052 lastcall = 0.
00053 count = 0
00054 acc = 0.
00055 try:
00056 while True:
00057 try:
00058 count += 1
00059 start = time.time()
00060 pid = _succeed(node.getPid(ID))
00061 end = time.time()
00062
00063 dur = (end-start)*1000.
00064 acc += dur
00065
00066
00067 if verbose:
00068 print("xmlrpc reply from %s\ttime=%fms"%(node_api, dur))
00069
00070 except socket.error as e:
00071
00072 try:
00073
00074 errnum, msg = e
00075 if errnum == -2:
00076 p = urlparse.urlparse(node_api)
00077
00078 elif errnum == errno.ECONNREFUSED:
00079
00080 new_node_api = get_api_uri(master,node_name, skip_cache=True)
00081 if not new_node_api:
00082
00083 return False
00084 if new_node_api != node_api:
00085 if verbose:
00086 print("node url has changed from [%s] to [%s], retrying to ping"%(node_api, new_node_api))
00087 node_api = new_node_api
00088 node = ServerProxy(node_api)
00089 continue
00090
00091 else:
00092 pass
00093
00094 return False
00095 except ValueError:
00096 print("unknown network error contacting node: %s"%(str(e)))
00097 if max_count and count >= max_count:
00098 break
00099 time.sleep(1.0)
00100 except KeyboardInterrupt:
00101 pass
00102
00103 if verbose and count > 1:
00104 print("ping average: %fms"%(acc/count))
00105 return True
00106
00107 def checkNodeExistence(stat):
00108 global nodes
00109 result = {}
00110 have_dead = False
00111 for n in nodes:
00112 res = ping(n, max_count = 1, verbose = False)
00113 result[n] = res
00114 if not res:
00115 have_dead = True
00116 if have_dead:
00117 stat.summary(diagnostic_msgs.msg.DiagnosticStatus.ERROR,
00118 "dead nodes: " + ", ".join([n for (n, res)
00119 in result.items() if not res]))
00120 else:
00121 stat.summary(diagnostic_msgs.msg.DiagnosticStatus.OK,
00122 "every node is alive")
00123 for n, res in result.items():
00124 stat.add(n, res)
00125 return stat
00126
00127 if __name__ == "__main__":
00128 rospy.init_node('rosping_existence')
00129 updater = diagnostic_updater.Updater()
00130 updater.setHardwareID(rospy.get_name())
00131 updater.add("node existence", checkNodeExistence)
00132 argv = rospy.myargv()
00133
00134 launch_files = argv[1:]
00135 config = roslaunch.config.load_config_default(launch_files, 0)
00136 nodes = [n.namespace + n.name for n in config.nodes]
00137 r = rospy.Rate(0.1)
00138 while not rospy.is_shutdown():
00139 updater.update()
00140 r.sleep()
00141