def _register_subscriber(self, node_master, name, type_info, xmlrpc_uri): ''' This one is not necessary, since you can pretty much guarantee the existence of the subscriber here, but it pays to be safe - we've seen some errors come out here when the ROS_MASTER_URI was only set to localhost. @param node_master : node-master xmlrpc method handler @param type_info : type of the subscriber message @param xmlrpc_uri : the uri of the node (xmlrpc server) @type string @param name : fully resolved subscriber name ''' # This unfortunately is a game breaker - it destroys all connections, not just those # connected to this master, see #125. pub_uri_list = node_master.registerSubscriber(name, type_info, xmlrpc_uri) try: #rospy.loginfo("register_subscriber [%s][%s][%s]" % (name, xmlrpc_uri, pub_uri_list)) xmlrpcapi(xmlrpc_uri).publisherUpdate('/master', name, pub_uri_list) except socket.error, v: errorcode = v[0] if errorcode != errno.ECONNREFUSED: rospy.logerr( "Gateway : error registering subscriber (is ROS_MASTER_URI and ROS_HOSTNAME or ROS_IP correctly set?)" ) rospy.logerr("Gateway : errorcode [%s] xmlrpc_uri [%s]" % (str(errorcode), xmlrpc_uri)) raise # better handling here would be ideal else: pass # subscriber stopped on the other side, don't worry about it
def _unregister_subscriber(self, node_master, xmlrpc_uri, name): ''' It is a special case as it requires xmlrpc handling to inform the subscriber of the disappearance of publishers it was connected to. It also needs to handle the case when that information doesn't get to the subscriber because it is down. @param node_master : node-master xmlrpc method handler @param xmlrpc_uri : the uri of the node (xmlrpc server) @type string @param name : fully resolved subscriber name ''' # This unfortunately is a game breaker - it destroys all connections, not just those # connected to this master, see #125. try: xmlrpcapi(xmlrpc_uri).publisherUpdate('/master', name, []) except socket.error as v: errorcode = v[0] if errorcode != errno.ECONNREFUSED: raise # better handling here would be ideal else: pass # subscriber stopped on the other side, don't worry about it except xmlrpclib.Fault: # This occurs when the subscriber has gone down and unflipped. # For us this is not an error since we were only informing # the subscriber of an updated publisher state...which # it no longer needs! pass except httplib.CannotSendRequest: # This occurs if the master has shut down, just ignore this gracefully. # I'm not aware that it's important to catch this at any othe time. pass node_master.unregisterSubscriber(name, xmlrpc_uri)
def service_update_task(api, service, uri): """ Contact api.serviceUpdate with specified parameters @param api: XML-RPC URI of node to contact @type api: str @param service: Service name to send to node @type service: str @param uri: URI to send to node @type uri: str """ mloginfo("serviceUpdate[%s, %s] -> %s", service, uri, api) xmlrpcapi(api).serviceUpdate('/master', service, uri)
def service_update_task(api, service, uri): """ Contact api.serviceUpdate with specified parameters @param api: XML-RPC URI of node to contact @type api: str @param service: Service name to send to node @type service: str @param uri: URI to send to node @type uri: str """ mloginfo("serviceUpdate[%s, %s] -> %s",service, uri, api) xmlrpcapi(api).serviceUpdate('/master', service, uri)
def publisher_update_task(api, topic, pub_uris): """ Contact api.publisherUpdate with specified parameters @param api: XML-RPC URI of node to contact @type api: str @param topic: Topic name to send to node @type topic: str @param pub_uris: list of publisher APIs to send to node @type pub_uris: [str] """ mloginfo("publisherUpdate[%s] -> %s", topic, api) #TODO: check return value for errors so we can unsubscribe if stale xmlrpcapi(api).publisherUpdate('/master', topic, pub_uris)
def param_update_task(self, caller_id, caller_api, param_key, param_value): """ Contact api.paramUpdate with specified parameters @param caller_id: caller ID @type caller_id: str @param caller_api: XML-RPC URI of node to contact @type caller_api: str @param param_key: parameter key to pass to node @type param_key: str @param param_value: parameter value to pass to node @type param_value: str """ mloginfo("paramUpdate[%s]", param_key) code, _, _ = xmlrpcapi(caller_api).paramUpdate('/master', param_key, param_value) if code == -1: try: # ps_lock is required due to potential self.reg_manager modification self.ps_lock.acquire() # reverse lookup to figure out who we just called matches = self.reg_manager.reverse_lookup(caller_api) for m in matches: retval = self.param_server.unsubscribe_param( param_key, (m.id, caller_api)) finally: self.ps_lock.release()
def publisher_update_task(api, topic, pub_uris): """ Contact api.publisherUpdate with specified parameters @param api: XML-RPC URI of node to contact @type api: str @param topic: Topic name to send to node @type topic: str @param pub_uris: list of publisher APIs to send to node @type pub_uris: [str] """ is_rosout_topic = 'rosout' in topic start_ms = time.time() msg = "publisherUpdate[%s] -> %s %s" % (topic, api, str(pub_uris)) if not is_rosout_topic: mloginfo(msg) #TODO: check return value for errors so we can unsubscribe if stale try: ret = xmlrpcapi(api).publisherUpdate('/master', topic, pub_uris) except Exception as ex: if not is_rosout_topic: delta_sec = (time.time() - start_ms) * 1000.0 mloginfo("%s: secs=%0.2f, exception=%s", msg, delta_sec, str(ex)) raise if not is_rosout_topic: delta_sec = (time.time() - start_ms) * 1000.0 mloginfo("%s: secs=%0.2f, result=%s", msg, delta_sec, ret)
def shutdown_node_task(api, caller_id, reason): """ Method to shutdown another ROS node. Generally invoked within a separate thread as this is used to cleanup hung nodes. @param api: XML-RPC API of node to shutdown @type api: str @param caller_id: name of node being shutdown @type caller_id: str @param reason: human-readable reason why node is being shutdown @type reason: str """ try: xmlrpcapi(api).shutdown('/master', reason) except: pass #expected in many common cases
def _register_subscriber(self, node_master, name, type_info, xmlrpc_uri): ''' This one is not necessary, since you can pretty much guarantee the existence of the subscriber here, but it pays to be safe - we've seen some errors come out here when the ROS_MASTER_URI was only set to localhost. @param node_master : node-master xmlrpc method handler @param type_info : type of the subscriber message @param xmlrpc_uri : the uri of the node (xmlrpc server) @type string @param name : fully resolved subscriber name ''' # This unfortunately is a game breaker - it destroys all connections, not just those # connected to this master, see #125. pub_uri_list = node_master.registerSubscriber(name, type_info, xmlrpc_uri) # Be nice to the subscriber, inform it that is should refresh it's publisher list. try: rospy.loginfo( "resetting publishers for this node's subscriber [%s][%s][%s]" % (name, xmlrpc_uri, pub_uri_list)) # this publisherUpdate will overwrite any other publisher currently known by the subscriber xmlrpcapi(xmlrpc_uri).publisherUpdate('/master', name, pub_uri_list) except (socket.error, socket.gaierror) as v: errorcode = v[0] if errorcode != errno.ECONNREFUSED: rospy.logerr( "Gateway : error registering subscriber " + "(is ROS_MASTER_URI and ROS_HOSTNAME or ROS_IP correctly set?)" ) rospy.logerr("Gateway : errorcode [%s] xmlrpc_uri [%s]" % (str(errorcode), xmlrpc_uri)) raise # better handling here would be ideal else: pass # subscriber stopped on the other side, so don't worry about telling it to 'refresh' its publishers except xmlrpclib.Fault as e: # as above with the socket error, don't worry about telling it to 'refresh' its publishers rospy.logerr( "Gateway : serious fault while communicating with a subscriber - its xmlrpc server was around but in a bad state [%s]" % str(e)) rospy.logerr( "Gateway : if this happened, add to the collected information gathered at https://github.com/robotics-in-concert/rocon_multimaster/issues/304" )
def _unregister_subscriber(self, node_master, xmlrpc_uri, name): ''' It is a special case as it requires xmlrpc handling to inform the subscriber of the disappearance of publishers it was connected to. It also needs to handle the case when that information doesn't get to the subscriber because it is down. @param node_master : node-master xmlrpc method handler @param xmlrpc_uri : the uri of the node (xmlrpc server) @type string @param name : fully resolved subscriber name ''' # This unfortunately is a game breaker - it destroys all connections, not just those # connected to this master, see #125. try: xmlrpcapi(xmlrpc_uri).publisherUpdate('/master', name, []) except socket.error, v: errorcode = v[0] if errorcode != errno.ECONNREFUSED: raise # better handling here would be ideal else: pass # subscriber stopped on the other side, don't worry about it
def publisher_update_task(api, topic, pub_uris): """ Contact api.publisherUpdate with specified parameters @param api: XML-RPC URI of node to contact @type api: str @param topic: Topic name to send to node @type topic: str @param pub_uris: list of publisher APIs to send to node @type pub_uris: [str] """ msg = "publisherUpdate[%s] -> %s %s" % (topic, api, pub_uris) mloginfo(msg) start_sec = time.time() try: #TODO: check return value for errors so we can unsubscribe if stale ret = xmlrpcapi(api).publisherUpdate('/master', topic, pub_uris) msg_suffix = "result=%s" % ret except Exception as ex: msg_suffix = "exception=%s" % ex raise finally: delta_sec = time.time() - start_sec mloginfo("%s: sec=%0.2f, %s", msg, delta_sec, msg_suffix)
def param_update_task(self, caller_id, caller_api, param_key, param_value): """ Contact api.paramUpdate with specified parameters @param caller_id: caller ID @type caller_id: str @param caller_api: XML-RPC URI of node to contact @type caller_api: str @param param_key: parameter key to pass to node @type param_key: str @param param_value: parameter value to pass to node @type param_value: str """ mloginfo("paramUpdate[%s]", param_key) code, _, _ = xmlrpcapi(caller_api).paramUpdate('/master', param_key, param_value) if code == -1: try: # ps_lock is required due to potential self.reg_manager modification self.ps_lock.acquire() # reverse lookup to figure out who we just called matches = self.reg_manager.reverse_lookup(caller_api) for m in matches: retval = self.param_server.unsubscribe_param(param_key, (m.id, caller_api)) finally: self.ps_lock.release()