def test_caller_id(self): from rospy.names import get_caller_id, get_name, _set_caller_id, get_namespace # test get_name, get_caller_id, and _set_caller_id try: self.assertEquals('/unnamed', get_name()) self.assertEquals('/', get_namespace()) _set_caller_id('/foo') self.assertEquals('/foo', get_name()) self.assertEquals('/', get_namespace()) _set_caller_id('/foo/bar') self.assertEquals('/foo/bar', get_name()) self.assertEquals('/foo/', get_namespace()) finally: _set_caller_id('/unnamed') # older get_caller_id usage try: self.assertEquals('/unnamed', get_caller_id()) self.assertEquals('/', get_namespace()) _set_caller_id('/foo') self.assertEquals('/foo', get_caller_id()) self.assertEquals('/', get_namespace()) _set_caller_id('/foo/bar') self.assertEquals('/foo/bar', get_caller_id()) self.assertEquals('/foo/', get_namespace()) finally: _set_caller_id('/unnamed')
def reg_removed(self, resolved_name, data_type_or_uri, reg_type): """ RegistrationListener callback @param resolved_name: resolved name of topic or service @type resolved_name: str @param data_type_or_uri: either the data type (for topic regs) or the service URI (for service regs). @type data_type_or_uri: str @param reg_type: Valid values are L{Registration.PUB}, L{Registration.SUB}, L{Registration.SRV} @type reg_type: str """ master_uri = self.master_uri if not master_uri: self.logger.error("Registrar: master_uri is not set yet, cannot inform master of deregistration") else: try: master = xmlrpcapi(master_uri) if reg_type == Registration.PUB: self.logger.debug("unregisterPublisher(%s, %s)", resolved_name, self.uri) master.unregisterPublisher(get_caller_id(), resolved_name, self.uri) elif reg_type == Registration.SUB: self.logger.debug("unregisterSubscriber(%s, %s)", resolved_name, data_type_or_uri) master.unregisterSubscriber(get_caller_id(), resolved_name, self.uri) elif reg_type == Registration.SRV: self.logger.debug("unregisterService(%s, %s)", resolved_name, data_type_or_uri) master.unregisterService(get_caller_id(), resolved_name, data_type_or_uri) except: logwarn("unable to communicate with ROS Master, registrations are now out of sync") self.logger.error(traceback.format_exc())
def test_caller_id(self): from rospy.names import get_caller_id, get_name, _set_caller_id, get_namespace # test get_name, get_caller_id, and _set_caller_id try: self.assertEquals("/unnamed", get_name()) self.assertEquals("/", get_namespace()) _set_caller_id("/foo") self.assertEquals("/foo", get_name()) self.assertEquals("/", get_namespace()) _set_caller_id("/foo/bar") self.assertEquals("/foo/bar", get_name()) self.assertEquals("/foo/", get_namespace()) finally: _set_caller_id("/unnamed") # older get_caller_id usage try: self.assertEquals("/unnamed", get_caller_id()) self.assertEquals("/", get_namespace()) _set_caller_id("/foo") self.assertEquals("/foo", get_caller_id()) self.assertEquals("/", get_namespace()) _set_caller_id("/foo/bar") self.assertEquals("/foo/bar", get_caller_id()) self.assertEquals("/foo/", get_namespace()) finally: _set_caller_id("/unnamed")
def reg_added(self, resolved_name, data_type_or_uri, reg_type): """ RegistrationListener callback @param resolved_name: resolved name of topic or service @type resolved_name: str @param data_type_or_uri: either the data type (for topic regs) or the service URI (for service regs). @type data_type_or_uri: str @param reg_type: Valid values are L{Registration.PUB}, L{Registration.SUB}, L{Registration.SRV} @type reg_type: str """ #TODO: this needs to be made robust to master outages master_uri = self.master_uri if not master_uri: self.logger.error( "Registrar: master_uri is not set yet, cannot inform master of registration" ) else: master = xmlrpcapi(master_uri) args = (get_caller_id(), resolved_name, data_type_or_uri, self.uri) registered = False first = True while not registered and not is_shutdown(): try: if reg_type == Registration.PUB: self.logger.debug( "master.registerPublisher(%s, %s, %s, %s)" % args) code, msg, val = master.registerPublisher(*args) if code != 1: logfatal( "unable to register publication [%s] with master: %s" % (resolved_name, msg)) elif reg_type == Registration.SUB: self.logger.debug( "master.registerSubscriber(%s, %s, %s, %s)" % args) code, msg, val = master.registerSubscriber(*args) if code == 1: self.publisher_update(resolved_name, val) else: # this is potentially worth exiting over. in the future may want to add a retry # timer logfatal( "unable to register subscription [%s] with master: %s" % (resolved_name, msg)) elif reg_type == Registration.SRV: self.logger.debug( "master.registerService(%s, %s, %s, %s)" % args) code, msg, val = master.registerService(*args) if code != 1: logfatal( "unable to register service [%s] with master: %s" % (resolved_name, msg)) registered = True except Exception as e: if first: msg = "Unable to register with master node [%s]: master may not be running yet. Will keep trying." % master_uri self.logger.error(str(e) + "\n" + msg) print(msg) first = False time.sleep(0.2)
def reg_added(self, resolved_name, data_type_or_uri, reg_type): """ RegistrationListener callback @param resolved_name: resolved name of topic or service @type resolved_name: str @param data_type_or_uri: either the data type (for topic regs) or the service URI (for service regs). @type data_type_or_uri: str @param reg_type: Valid values are L{Registration.PUB}, L{Registration.SUB}, L{Registration.SRV} @type reg_type: str """ # TODO: this needs to be made robust to master outages master_uri = self.master_uri if not master_uri: self.logger.error("Registrar: master_uri is not set yet, cannot inform master of registration") else: master = xmlrpcapi(master_uri) args = (get_caller_id(), resolved_name, data_type_or_uri, self.uri) registered = False first = True while not registered and not is_shutdown(): try: if reg_type == Registration.PUB: self.logger.debug("master.registerPublisher(%s, %s, %s, %s)" % args) code, msg, val = master.registerPublisher(*args) if code != 1: logfatal("unable to register publication [%s] with master: %s" % (resolved_name, msg)) elif reg_type == Registration.SUB: self.logger.debug("master.registerSubscriber(%s, %s, %s, %s)" % args) code, msg, val = master.registerSubscriber(*args) if code == 1: self.publisher_update(resolved_name, val) else: # this is potentially worth exiting over. in the future may want to add a retry # timer logfatal("unable to register subscription [%s] with master: %s" % (resolved_name, msg)) elif reg_type == Registration.SRV: self.logger.debug("master.registerService(%s, %s, %s, %s)" % args) code, msg, val = master.registerService(*args) if code != 1: logfatal("unable to register service [%s] with master: %s" % (resolved_name, msg)) registered = True except Exception as e: if first: msg = ( "Unable to register with master node [%s]: master may not be running yet. Will keep trying." % master_uri ) self.logger.error(str(e) + "\n" + msg) print(msg) first = False time.sleep(0.2)
def cleanup(self, reason): """ Cleans up registrations with master and releases topic and service resources @param reason: human-reasonable debug string @type reason: str """ self.logger.debug("registration cleanup starting") try: self.cond.acquire() self.cond.notifyAll() finally: self.cond.release() # we never successfully initialized master_uri if not self.master_uri: return master = xmlrpcapi(self.master_uri) # we never successfully initialized master if master is None: return caller_id = get_caller_id() tm = get_topic_manager() sm = get_service_manager() try: if tm is not None: for resolved_name, _ in tm.get_subscriptions(): self.logger.debug("unregisterSubscriber [%s]" % resolved_name) master.unregisterSubscriber(caller_id, resolved_name, self.uri) for resolved_name, _ in tm.get_publications(): self.logger.debug("unregisterPublisher [%s]" % resolved_name) master.unregisterPublisher(caller_id, resolved_name, self.uri) if sm is not None: for resolved_name, service_uri in sm.get_services(): self.logger.debug("unregisterService [%s]" % resolved_name) master.unregisterService(caller_id, resolved_name, service_uri) except socket.error, (errno, msg): if errno == 111 or errno == 61: #can't talk to master, nothing we can do about it self.logger.warn( "cannot unregister with master due to network issues") else: self.logger.warn("unclean shutdown\n%s" % traceback.format_exc())
def __init__(self, name, port=0, rpc_handler=None): """ Node constructor @param name: name of this node @type name: str @param port: port to use for starting XML-RPC API. Set to 0 or omit to bind to any available port. @type port: int @param rpc_handler: XML-RPC API handler for node. @type rpc_handler: roslib.xmlrpc.XmlRpcHandler """ super(ROSNode, self).__init__(port, rpc_handler) self.name = scoped_name(get_namespace(), name) #use the de-contexted name #TODO: move out of ROSNode _set_caller_id(name) #update global name context logging.getLogger('rospy.msnode').info( "Node initialized: callerId[%s] local name[%s] port[%s]", get_caller_id(), self.name, self.port)
def cleanup(self, reason): """ Cleans up registrations with master and releases topic and service resources @param reason: human-reasonable debug string @type reason: str """ self.logger.debug("registration cleanup starting") try: self.cond.acquire() self.cond.notifyAll() finally: self.cond.release() # we never successfully initialized master_uri if not self.master_uri: return master = xmlrpcapi(self.master_uri) # we never successfully initialized master if master is None: return caller_id = get_caller_id() # clear the registration listeners as we are going to do a quick unregister here rl = get_registration_listeners() if rl is not None: rl.clear() tm = get_topic_manager() sm = get_service_manager() try: multi = xmlrpcclient.MultiCall(master) if tm is not None: for resolved_name, _ in tm.get_subscriptions(): self.logger.debug("unregisterSubscriber [%s]"%resolved_name) multi.unregisterSubscriber(caller_id, resolved_name, self.uri) for resolved_name, _ in tm.get_publications(): self.logger.debug("unregisterPublisher [%s]"%resolved_name) multi.unregisterPublisher(caller_id, resolved_name, self.uri) if sm is not None: for resolved_name, service_uri in sm.get_services(): self.logger.debug("unregisterService [%s]"%resolved_name) multi.unregisterService(caller_id, resolved_name, service_uri) multi() except socket.error as se: (errno, msg) = se.args if errno == 111 or errno == 61: #can't talk to master, nothing we can do about it self.logger.warn("cannot unregister with master due to network issues") else: self.logger.warn("unclean shutdown\n%s"%traceback.format_exc()) except: self.logger.warn("unclean shutdown\n%s"%traceback.format_exc()) self.logger.debug("registration cleanup: master calls complete") #TODO: cleanup() should actually be orchestrated by a separate #cleanup routine that calls the reg manager/sm/tm if tm is not None: tm.close_all() if sm is not None: sm.unregister_all()
def start(self, uri, master_uri): """ Start the RegManager. This should be passed in as an argument to a thread starter as the RegManager is designed to spin in its own thread @param uri: URI of local node @type uri: str @param master_uri: Master URI @type master_uri: str """ self.registered = False self.master_uri = master_uri self.uri = uri first = True tm = get_topic_manager() sm = get_service_manager() ns = get_namespace() caller_id = get_caller_id() if not master_uri or master_uri == uri: registered = True master = None else: registered = False master = xmlrpcapi(master_uri) self.logger.info("Registering with master node %s", master_uri) while not registered and not is_shutdown(): try: try: # prevent TopicManager and ServiceManager from accepting registrations until we are done tm.lock.acquire() sm.lock.acquire() pub, sub, srv = tm.get_publications(), tm.get_subscriptions(), sm.get_services() for resolved_name, data_type in pub: self.logger.info("Registering publisher topic [%s] type [%s] with master", resolved_name, data_type) code, msg, val = master.registerPublisher(caller_id, resolved_name, data_type, uri) if code != 1: logfatal("cannot register publication topic [%s] with master: %s"%(resolved_name, msg)) signal_shutdown("master/node incompatibility with register publisher") for resolved_name, data_type in sub: self.logger.info("registering subscriber topic [%s] type [%s] with master", resolved_name, data_type) code, msg, val = master.registerSubscriber(caller_id, resolved_name, data_type, uri) if code != 1: logfatal("cannot register subscription topic [%s] with master: %s"%(resolved_name, msg)) signal_shutdown("master/node incompatibility with register subscriber") else: self.publisher_update(resolved_name, val) for resolved_name, service_uri in srv: self.logger.info("registering service [%s] uri [%s] with master", resolved_name, service_uri) code, msg, val = master.registerService(caller_id, resolved_name, service_uri, uri) if code != 1: logfatal("cannot register service [%s] with master: %s"%(resolved_name, msg)) signal_shutdown("master/node incompatibility with register service") registered = True # Subscribe to updates to our state get_registration_listeners().add_listener(self) finally: sm.lock.release() tm.lock.release() if pub or sub: logdebug("Registered [%s] with master node %s", caller_id, master_uri) else: logdebug("No topics to register with master node %s", master_uri) except Exception as e: if first: # this use to print to console always, arguable whether or not this should be subjected to same configuration options as logging logerr("Unable to immediately register with master node [%s]: master may not be running yet. Will keep trying."%master_uri) first = False time.sleep(0.2) self.registered = True self.run()
def __init__(self, name, port=0, rpc_handler=None): """ Node constructor @param name: name of this node @type name: str @param port: port to use for starting XML-RPC API. Set to 0 or omit to bind to any available port. @type port: int @param rpc_handler: XML-RPC API handler for node. @type rpc_handler: roslib.xmlrpc.XmlRpcHandler """ super(ROSNode, self).__init__(port, rpc_handler) self.name = scoped_name(get_namespace(), name) #use the de-contexted name #TODO: move out of ROSNode _set_caller_id(name) #update global name context logging.getLogger('rospy.msnode').info("Node initialized: callerId[%s] local name[%s] port[%s]", get_caller_id(), self.name, self.port)