def getTopics(self): def topic_type(t, pub_topics): matches = [t_type for t_name, t_type in pub_topics if t_name == t] if matches: return matches[0] return 'unknown type' master = scriptutil.get_master() topic = None state = succeed(master.getSystemState('/rostopic')) pubs, subs, _ = state pub_topics = succeed(scriptutil.get_master().getPublishedTopics('/rostopic', '/')) pubtopics = [t for t,_ in pubs] pubtopics.sort() subtopics = [t for t,_ in subs] subtopics.sort() nodes = [] for s in state: for t, l in s: nodes.extend(l) nodes = set(nodes) nodes = list(nodes) nodes.sort() topics = (tuple(pubtopics), tuple(subtopics), tuple(nodes)) return topics
def get_node_names(namespace=None): """ @param namespace: optional namespace to scope return values by. Namespace must already be resolved. @type namespace: str @return: list of node caller IDs @rtype: [str] @raise ROSNodeIOException: if unable to communicate with master """ master = scriptutil.get_master() try: state = _succeed(master.getSystemState(ID)) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") nodes = [] import itertools if namespace: # canonicalize namespace with leading/trailing slash import roslib.names g_ns = roslib.names.make_global_ns(namespace) for s in state: for t, l in s: nodes.extend( [n for n in l if n.startswith(g_ns) or n == namespace]) else: for s in state: for t, l in s: nodes.extend(l) return list(set(nodes))
def node_info(node): caller_id = make_caller_id('nodeutil-%s'%os.getpid()) node_name = node #scriptutil.script_resolve_name(caller_id, node) master = scriptutil.get_master() # go through the master system state first try: state = _remote_call(master.getSystemState(caller_id)) except socket.error: raise Exception("Unable to communicate with master!") pubs = [t for t, l in state[0] if node_name in l] subs = [t for t, l in state[1] if node_name in l] srvs = [t for t, l in state[2] if node_name in l] results = { "publications": pubs, "subscriptions": subs, "services": srvs } node_api = get_api_uri(master, node_name, caller_id) if not node_api: results["error"] = "cannot contact [%s]: unknown node"%node_name return results
def rosnode_ping_all(verbose=False): """ Ping all running nodes @return [str], [str]: pinged nodes, un-pingable nodes @raise ROSNodeIOException: if unable to communicate with master """ master = scriptutil.get_master() try: state = _succeed(master.getSystemState(ID)) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") nodes = [] import itertools for s in state: for t, l in s: nodes.extend(l) nodes = list(set(nodes)) #uniq if verbose: print "Will ping the following nodes: \n" + ''.join( [" * %s\n" % n for n in nodes]) pinged = [] unpinged = [] for node in nodes: if rosnode_ping(node, max_count=1, verbose=verbose): pinged.append(node) else: unpinged.append(node) return pinged, unpinged
def _sub_rosnode_listnodes(namespace=None, list_uri=False, list_all=False): """ Subroutine for rosnode_listnodes(). Composes list of strings to print to screen. @param namespace: (default None) namespace to scope list to. @type namespace: str @param list_uri: (default False) return uris of nodes instead of names. @type list_uri: bool @param list_all: (default False) return names and uris of nodes as combined strings @type list_all: bool @return: new-line separated string containing list of all nodes @rtype: str """ master = scriptutil.get_master() nodes = get_node_names(namespace) nodes.sort() if list_all: return '\n'.join([ "%s \t%s" % (get_api_uri(master, n) or 'unknown address', n) for n in nodes ]) elif list_uri: return '\n'.join([(get_api_uri(master, n) or 'unknown address') for n in nodes]) else: return '\n'.join(nodes)
def rosnode_info(node_name): """ Print information about node, including subscriptions and other debugging information. This will query the node over the network. @param node_name: name of ROS node @type node_name: str @raise ROSNodeIOException: if unable to communicate with master """ def topic_type(t, pub_topics): matches = [t_type for t_name, t_type in pub_topics if t_name == t] if matches: return matches[0] return 'unknown type' master = scriptutil.get_master() node_name = scriptutil.script_resolve_name('rosnode', node_name) print('-'*80) print(get_node_info_description(node_name)) node_api = get_api_uri(master, node_name) if not node_api: print("cannot contact [%s]: unknown node"%node_name, file=sys.stderr) return print("\ncontacting node %s ..."%node_api) print(get_node_connection_info_description(node_api))
def get_node_names(namespace=None): """ @param namespace: optional namespace to scope return values by. Namespace must already be resolved. @type namespace: str @return: list of node caller IDs @rtype: [str] @raise ROSNodeIOException: if unable to communicate with master """ master = scriptutil.get_master() try: state = _succeed(master.getSystemState(ID)) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") nodes = [] import itertools if namespace: # canonicalize namespace with leading/trailing slash import roslib.names g_ns = roslib.names.make_global_ns(namespace) for s in state: for t, l in s: nodes.extend([n for n in l if n.startswith(g_ns) or n == namespace]) else: for s in state: for t, l in s: nodes.extend(l) return list(set(nodes))
def topic_info(topic): caller_id = make_caller_id('nodeutil-%s'%os.getpid()) master = scriptutil.get_master() # go through the master system state first try: state = _remote_call(master.getSystemState(caller_id)) except socket.error: raise IOException("Unable to communicate with master!") pubs, subs, _ = state publists = [publist for t, publist in pubs if t == topic] sublists = [sublist for t, sublist in subs if t == topic] #pub_topics = _succeed(master.getPublishedTopics(caller_id, '/')) if publists == []: return { "error": "This topic does not appear to be published yet." } elif sublists == []: return { "publishers": publists[0], "subscribers": [] } else: return { "publishers": publists[0], "subscribers": sublists[0] }
def rosnode_info(node_name): """ Print information about node, including subscriptions and other debugging information. This will query the node over the network. @param node_name: name of ROS node @type node_name: str @raise ROSNodeIOException: if unable to communicate with master """ def topic_type(t, pub_topics): matches = [t_type for t_name, t_type in pub_topics if t_name == t] if matches: return matches[0] return 'unknown type' master = scriptutil.get_master() node_name = scriptutil.script_resolve_name('rosnode', node_name) print '-' * 80 print get_node_info_description(node_name) node_api = get_api_uri(master, node_name) if not node_api: print >> sys.stderr, "cannot contact [%s]: unknown node" % node_name return print "\ncontacting node %s ..." % node_api print get_node_connection_info_description(node_api)
def is_node_running(node): """ Return true if the given node is running. """ master = scriptutil.get_master() node_info = master.lookupNode(rospy.get_name(), node) return node_info[0] == 1
def rosnode_ping_all(verbose=False): """ Ping all running nodes @return [str], [str]: pinged nodes, un-pingable nodes @raise ROSNodeIOException: if unable to communicate with master """ master = scriptutil.get_master() try: state = _succeed(master.getSystemState(ID)) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") nodes = [] import itertools for s in state: for t, l in s: nodes.extend(l) nodes = list(set(nodes)) #uniq if verbose: print("Will ping the following nodes: \n"+''.join([" * %s\n"%n for n in nodes])) pinged = [] unpinged = [] for node in nodes: if rosnode_ping(node, max_count=1, verbose=verbose): pinged.append(node) else: unpinged.append(node) return pinged, unpinged
def kill_nodes(node_names): """ Call shutdown on the specified nodes @return: list of nodes that shutdown was called on successfully and list of failures @rtype: ([str], [str]) """ master = scriptutil.get_master() success = [] fail = [] tocall = [] try: # lookup all nodes keeping track of lookup failures for return value for n in node_names: try: uri = _succeed(master.lookupNode(ID, n)) tocall.append([n, uri]) except: fail.append(n) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") for n, uri in tocall: # the shutdown call can sometimes fail to succeed if the node # tears down during the request handling, so we assume success try: p = xmlrpclib.ServerProxy(uri) _succeed(p.shutdown(ID, 'user request')) except: pass success.append(n) return success, fail
def is_node_running(node): """ Return true if the given node is running. Note that a socket is created to query the master. """ master = scriptutil.get_master() node_info = master.lookupNode(rospy.get_name(), node) return node_info[0] == 1
def get_node_info_description(node_name): def topic_type(t, pub_topics): matches = [t_type for t_name, t_type in pub_topics if t_name == t] if matches: return matches[0] return 'unknown type' master = scriptutil.get_master() # go through the master system state first try: state = _succeed(master.getSystemState(ID)) pub_topics = _succeed(scriptutil.get_master().getPublishedTopics( ID, '/')) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") pubs = [t for t, l in state[0] if node_name in l] subs = [t for t, l in state[1] if node_name in l] srvs = [t for t, l in state[2] if node_name in l] buff = "Node [%s]" % node_name if pubs: buff += "\nPublications: \n" buff += '\n'.join( [" * %s [%s]" % (l, topic_type(l, pub_topics)) for l in pubs]) + '\n' else: buff += "\nPublications: None\n" if subs: buff += "\nSubscriptions: \n" buff += '\n'.join( [" * %s [%s]" % (l, topic_type(l, pub_topics)) for l in subs]) + '\n' else: buff += "\nSubscriptions: None\n" if srvs: buff += "\nServices: \n" buff += '\n'.join([" * %s" % l for l in srvs]) + '\n' else: buff += "\nServices: None\n" return buff
def rosnode_ping(node_name, max_count=None, verbose=False): """ Test connectivity to node by calling its XMLRPC API @param node_name: name of node to ping @type node_name: str @param max_count: number of ping requests to make @type max_count: int @param verbose: print ping information to screen @type verbose: bool @return: True if node pinged @rtype: bool """ master = scriptutil.get_master() node_api = get_api_uri(master, node_name) if not node_api: print >> sys.stderr, "cannot ping [%s]: unknown node" % node_name return False timeout = 3. if verbose: print "pinging %s with a timeout of %ss" % (node_name, timeout) socket.setdefaulttimeout(timeout) node = xmlrpclib.ServerProxy(node_api) lastcall = 0. count = 0 acc = 0. try: while True: try: start = time.time() pid = _succeed(node.getPid(ID)) end = time.time() dur = (end - start) * 1000. acc += dur count += 1 if verbose: print "xmlrpc reply from %s\ttime=%fms" % (node_api, dur) # 1s between pings except socket.error: print >> sys.stderr, "connection to [%s] timed out" % node_name return False if max_count and count >= max_count: break time.sleep(1.0) except KeyboardInterrupt: pass if verbose and count > 1: print "ping average: %fms" % (acc / count) return True
def get_node_info_description(node_name): def topic_type(t, pub_topics): matches = [t_type for t_name, t_type in pub_topics if t_name == t] if matches: return matches[0] return 'unknown type' master = scriptutil.get_master() # go through the master system state first try: state = _succeed(master.getSystemState(ID)) pub_topics = _succeed(scriptutil.get_master().getPublishedTopics(ID, '/')) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") pubs = [t for t, l in state[0] if node_name in l] subs = [t for t, l in state[1] if node_name in l] srvs = [t for t, l in state[2] if node_name in l] buff = "Node [%s]"%node_name if pubs: buff += "\nPublications: \n" buff += '\n'.join([" * %s [%s]"%(l, topic_type(l, pub_topics)) for l in pubs]) + '\n' else: buff += "\nPublications: None\n" if subs: buff += "\nSubscriptions: \n" buff += '\n'.join([" * %s [%s]"%(l, topic_type(l, pub_topics)) for l in subs]) + '\n' else: buff += "\nSubscriptions: None\n" if srvs: buff += "\nServices: \n" buff += '\n'.join([" * %s"%l for l in srvs]) + '\n' else: buff += "\nServices: None\n" return buff
def get_nodes_by_machine(machine): """ Find nodes by machine name. This is a very costly procedure as it must do N lookups with the Master, where N is the number of nodes. @return: list of nodes on the specified machine @rtype: [str] @raise ROSNodeException: if machine name cannot be resolved to an address @raise ROSNodeIOException: if unable to communicate with master """ import urlparse master = scriptutil.get_master() try: machine_actual = socket.gethostbyname(machine) except: raise ROSNodeException("cannot resolve machine name [%s] to address" % machine) # get all the node names, lookup their uris, parse the hostname # from the uris, and then compare the resolved hostname against # the requested machine name. matches = [machine, machine_actual] not_matches = [] # cache lookups node_names = get_node_names() retval = [] for n in node_names: try: code, msg, uri = master.lookupNode(ID, n) # it's possible that the state changes as we are doing lookups. this is a soft-fail if code != 1: continue h = urlparse.urlparse(uri).hostname if h in matches: retval.append(n) elif h in not_matches: continue else: r = socket.gethostbyname(h) if r == machine_actual: matches.append(r) retval.append(n) else: not_matches.append(r) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") return retval
def get_nodes_by_machine(machine): """ Find nodes by machine name. This is a very costly procedure as it must do N lookups with the Master, where N is the number of nodes. @return: list of nodes on the specified machine @rtype: [str] @raise ROSNodeException: if machine name cannot be resolved to an address @raise ROSNodeIOException: if unable to communicate with master """ import urlparse master = scriptutil.get_master() try: machine_actual = socket.gethostbyname(machine) except: raise ROSNodeException("cannot resolve machine name [%s] to address"%machine) # get all the node names, lookup their uris, parse the hostname # from the uris, and then compare the resolved hostname against # the requested machine name. matches = [machine, machine_actual] not_matches = [] # cache lookups node_names = get_node_names() retval = [] for n in node_names: try: code, msg, uri = master.lookupNode(ID, n) # it's possible that the state changes as we are doing lookups. this is a soft-fail if code != 1: continue h = urlparse.urlparse(uri).hostname if h in matches: retval.append(n) elif h in not_matches: continue else: r = socket.gethostbyname(h) if r == machine_actual: matches.append(r) retval.append(n) else: not_matches.append(r) except socket.error: raise ROSNodeIOException("Unable to communicate with master!") return retval
def rosnode_ping(node_name): max_count = 1 master = scriptutil.get_master() node_api = get_api_uri(master, node_name) if not node_api: #print >> sys.stderr, "cannot ping [%s]: unknown node"%node_name #print 'NODE IS DOWN' return False timeout = 3. #print "pinging %s with a timeout of %ss"%(node_name, timeout) socket.setdefaulttimeout(timeout) node = xmlrpclib.ServerProxy(node_api) lastcall = 0. acc = 0. count = 0 try: while True: try: start = time.time() pid = _succeed(node.getPid(ID)) end = time.time() dur = (end - start) * 1000. acc += dur count += 1 #print 'NODE IS UP' #print "xmlrpc reply from %s\ttime=%fms"%(node_api, dur) # 1s between pings except socket.error: #print 'NODE IS DOWN' #print >> sys.stderr, "connection to [%s] timed out"%node_name return False if max_count and count >= max_count: break #time.sleep(1.0) except KeyboardInterrupt: pass return True
def stop_node(node): """ Stop the given node. Return true on success. """ master = scriptutil.get_master() node_info = master.lookupNode(rospy.get_name(), node) [code, msg, uri] = master.lookupNode(rospy.get_name(), node) if code != 1: if msg.startswith('unknown node'): rospy.loginfo('Unknown node "%s"; ignored stop request.', node) return True else: rospy.logwarn('Couldn\'t stop "%s", problem retrieving information: %s', node, msg) return False try: proxy = xmlrpclib.ServerProxy(uri) result = proxy.shutdown(rospy.get_name(), 'pal_common') except Exception, e: rospy.logwarn('Couldn\'t stop "%s": %s', node, str(e)) return False
def node_info(node): caller_id = make_caller_id('nodeutil-%s' % os.getpid()) node_name = node #scriptutil.script_resolve_name(caller_id, node) master = scriptutil.get_master() # go through the master system state first try: state = _remote_call(master.getSystemState(caller_id)) except socket.error: raise Exception("Unable to communicate with master!") pubs = [t for t, l in state[0] if node_name in l] subs = [t for t, l in state[1] if node_name in l] srvs = [t for t, l in state[2] if node_name in l] results = {"publications": pubs, "subscriptions": subs, "services": srvs} node_api = get_api_uri(master, node_name, caller_id) if not node_api: results["error"] = "cannot contact [%s]: unknown node" % node_name return results
def topic_info(topic): caller_id = make_caller_id('nodeutil-%s' % os.getpid()) master = scriptutil.get_master() # go through the master system state first try: state = _remote_call(master.getSystemState(caller_id)) except socket.error: raise IOException("Unable to communicate with master!") pubs, subs, _ = state publists = [publist for t, publist in pubs if t == topic] sublists = [sublist for t, sublist in subs if t == topic] #pub_topics = _succeed(master.getPublishedTopics(caller_id, '/')) if publists == []: return {"error": "This topic does not appear to be published yet."} elif sublists == []: return {"publishers": publists[0], "subscribers": []} else: return {"publishers": publists[0], "subscribers": sublists[0]}
def _sub_rosnode_listnodes(namespace=None, list_uri=False, list_all=False): """ Subroutine for rosnode_listnodes(). Composes list of strings to print to screen. @param namespace: (default None) namespace to scope list to. @type namespace: str @param list_uri: (default False) return uris of nodes instead of names. @type list_uri: bool @param list_all: (default False) return names and uris of nodes as combined strings @type list_all: bool @return: new-line separated string containing list of all nodes @rtype: str """ master = scriptutil.get_master() nodes = get_node_names(namespace) nodes.sort() if list_all: return '\n'.join(["%s \t%s"%(get_api_uri(master, n) or 'unknown address', n) for n in nodes]) elif list_uri: return '\n'.join([(get_api_uri(master, n) or 'unknown address') for n in nodes]) else: return '\n'.join(nodes)
def rosnode_cleanup(): """ This is a semi-hidden routine for cleaning up stale node registration information on the ROS Master. The intent is to remove this method once Master TTLs are properly implemented. """ pinged, unpinged = rosnode_ping_all() if unpinged: master = scriptutil.get_master() print("Unable to contact the following nodes:") print('\n'.join(' * %s'%n for n in unpinged)) print("cleanup will purge all information about these nodes from the master") print("Please type y or n to continue") input = sys.stdin.readline() while not input.strip() in ['y', 'n']: input = sys.stdin.readline() if input.strip() == 'n': print('aborting') return cleanup_master_blacklist(master, unpinged) print("done")
def rosnode_cleanup(): """ This is a semi-hidden routine for cleaning up stale node registration information on the ROS Master. The intent is to remove this method once Master TTLs are properly implemented. """ pinged, unpinged = rosnode_ping_all() if unpinged: master = scriptutil.get_master() print "Unable to contact the following nodes:" print '\n'.join(' * %s' % n for n in unpinged) print "cleanup will purge all information about these nodes from the master" print "Please type y or n to continue" input = sys.stdin.readline() while not input.strip() in ['y', 'n']: input = sys.stdin.readline() if input.strip() == 'n': print 'aborting' return cleanup_master_blacklist(master, unpinged) print "done"
def rosnode_ping(node_name, max_count=None, verbose=False): """ Test connectivity to node by calling its XMLRPC API @param node_name: name of node to ping @type node_name: str @param max_count: number of ping requests to make @type max_count: int @param verbose: print ping information to screen @type verbose: bool @return: True if node pinged @rtype: bool """ master = scriptutil.get_master() node_api = get_api_uri(master,node_name) if not node_api: print("cannot ping [%s]: unknown node"%node_name, file=sys.stderr) return False timeout = 3. if verbose: print("pinging %s with a timeout of %ss"%(node_name, timeout)) socket.setdefaulttimeout(timeout) node = xmlrpclib.ServerProxy(node_api) lastcall = 0. count = 0 acc = 0. try: while True: try: start = time.time() pid = _succeed(node.getPid(ID)) end = time.time() dur = (end-start)*1000. acc += dur count += 1 if verbose: print("xmlrpc reply from %s\ttime=%fms"%(node_api, dur)) # 1s between pings except socket.error as e: # 3786: catch ValueError on unpack as socket.error is not always a tuple try: # #3659 errnum, msg = e if errnum == -2: #name/service unknown p = urlparse.urlparse(node_api) print("ERROR: Unknown host [%s] for node [%s]"%(p.hostname, node_name), file=sys.stderr) elif errnum == errno.ECONNREFUSED: p = urlparse.urlparse(node_api) print("ERROR: connection refused to [%s]"%(node_api), file=sys.stderr) else: print("connection to [%s] timed out"%node_name, file=sys.stderr) return False except ValueError: print("unknown network error contacting node: %s"%(str(e))) if max_count and count >= max_count: break time.sleep(1.0) except KeyboardInterrupt: pass if verbose and count > 1: print("ping average: %fms"%(acc/count)) return True