Example #1
0
 def unregister(self):
     """
     unpublish/unsubscribe from topic. Topic instance is no longer
     valid after this call. Additional calls to unregister() have no effect.
     """
     # as we don't guard unregister, have to protect value of
     # resolved_name for release_impl call
     resolved_name = self.resolved_name
     if resolved_name and self.impl:
         get_topic_manager().release_impl(self.reg_type, resolved_name)
         self.impl = self.resolved_name = self.type = self.md5sum = self.data_class = None
Example #2
0
 def unregister(self):
     """
     unpublish/unsubscribe from topic. Topic instance is no longer
     valid after this call. Additional calls to unregister() have no effect.
     """
     # as we don't guard unregister, have to protect value of
     # resolved_name for release_impl call
     resolved_name = self.resolved_name
     if resolved_name and self.impl:
         get_topic_manager().release_impl(self.reg_type, resolved_name)
         self.impl = self.resolved_name = self.type = self.md5sum = self.data_class = None
Example #3
0
 def getBusInfo(self, caller_id):
     """
     Retrieve transport/topic connection information
     @param caller_id: ROS caller id    
     @type  caller_id: str
     """
     return 1, "bus info", get_topic_manager().get_pub_sub_info()
Example #4
0
  def requestTopic(self, caller_id, topic, protocols):
      """
      Publisher node API method called by a subscriber node.
 
      Request that source allocate a channel for communication. Subscriber provides
      a list of desired protocols for communication. Publisher returns the
      selected protocol along with any additional params required for
      establishing connection. For example, for a TCP/IP-based connection,
      the source node may return a port number of TCP/IP server. 
      @param caller_id str: ROS caller id    
      @type  caller_id: str
      @param topic: topic name
      @type  topic: str
      @param protocols: list of desired
       protocols for communication in order of preference. Each
       protocol is a list of the form [ProtocolName,
       ProtocolParam1, ProtocolParam2...N]
      @type  protocols: [[str, XmlRpcLegalValue*]]
      @return: [code, msg, protocolParams]. protocolParams may be an
      empty list if there are no compatible protocols.
      @rtype: [int, str, [str, XmlRpcLegalValue*]]
      """
      if not get_topic_manager().has_publication(topic):
          return -1, "Not a publisher of [%s]" % topic, []
      for protocol in protocols:  #simple for now: select first implementation
          protocol_id = protocol[0]
          for h in self.protocol_handlers:
              if h.supports(protocol_id):
                  _logger.debug("requestTopic[%s]: choosing protocol %s",
                                topic, protocol_id)
                  return h.init_publisher(topic, protocol)
      return 0, "no supported protocol implementations", []
Example #5
0
  def requestTopic(self, caller_id, topic, protocols):
      """
      Publisher node API method called by a subscriber node.
 
      Request that source allocate a channel for communication. Subscriber provides
      a list of desired protocols for communication. Publisher returns the
      selected protocol along with any additional params required for
      establishing connection. For example, for a TCP/IP-based connection,
      the source node may return a port number of TCP/IP server. 
      @param caller_id str: ROS caller id    
      @type  caller_id: str
      @param topic: topic name
      @type  topic: str
      @param protocols: list of desired
       protocols for communication in order of preference. Each
       protocol is a list of the form [ProtocolName,
       ProtocolParam1, ProtocolParam2...N]
      @type  protocols: [[str, XmlRpcLegalValue*]]
      @return: [code, msg, protocolParams]. protocolParams may be an
      empty list if there are no compatible protocols.
      @rtype: [int, str, [str, XmlRpcLegalValue*]]
      """
      if not get_topic_manager().has_publication(topic):
          return -1, "Not a publisher of [%s]"%topic, []
      for protocol in protocols: #simple for now: select first implementation 
          protocol_id = protocol[0]
          for h in self.protocol_handlers:
              if h.supports(protocol_id):
                  _logger.debug("requestTopic[%s]: choosing protocol %s", topic, protocol_id)
                  return h.init_publisher(topic, protocol)
      return 0, "no supported protocol implementations", []
Example #6
0
def _rosout(level, msg, fname, line, func):
    global _in_rosout
    try:
        if _rosout_pub is not None:
            # protect against infinite recursion
            if not _in_rosout:
                try:
                    _in_rosout = True
                    msg = str(msg)

                    # check parameter server/cache for omit_topics flag
                    # the same parameter is checked in rosout_appender.cpp for the same purpose
                    # parameter accesses are cached automatically in python
                    if rospy.has_param("/rosout_disable_topics_generation"):
                        disable_topics_ = rospy.get_param("/rosout_disable_topics_generation")
                    else:
                        disable_topics_ = False

                    if not disable_topics_:
                        topics = get_topic_manager().get_topics()
                    else:
                        topics = ""

                    l = Log(level=level, name=str(rospy.names.get_caller_id()), msg=str(msg), topics=topics, file=fname, line=line, function=func)
                    l.header.stamp = Time.now()
                    _rosout_pub.publish(l)
                finally:
                    _in_rosout = False
    except Exception as e:
        #traceback.print_exc()
        # don't use logerr in this case as that is recursive here
        logger = logging.getLogger("rospy.rosout")        
        logger.error("Unable to report rosout: %s\n%s", e, traceback.format_exc())
        return False
Example #7
0
 def getSubscriptions(self, caller_id):
     """Retrieve a list of topics that this node subscribes to
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return [int, str, [ [topic1, topicType1]...[topicN, topicTypeN]]]: list of topics this node subscribes to
     """
     return 1, "subscriptions", get_topic_manager().get_subscriptions()
    def _unregisterPublisherCallback(self, data):
        name = data[NODE_NAME]
        topic = data[TOPIC_NAME]
        uri = data[XMLRPC_URI]
        uri_list = [uri]

        tm = get_topic_manager()
        try:
            tm.lock.acquire()
            if tm.has_subscription(topic):
                self._logger.debug("I has sub topic, recv unregisSub: %s" % topic)
                get_node_handler().reg_man.reg_removed(topic, uri_list, Registration.SUB)
        except Exception as e:
            self._logger.error(
                "unregisterPublisherCallback error is  %s" % e)
            self._logger.error(traceback.format_exc())
        finally:
            tm.lock.release()

        try:
            self._pubs[topic].remove(uri)
        except KeyError:
            pass

        try:
            self._pub_history[topic].remove(self._encode(data))
        except KeyError:
            pass
Example #9
0
    def _registerSubscriberCallback(self, data):
        name = data[NODE_NAME]
        topic = data[TOPIC_NAME]
        datatype = data[TOPIC_TYPE]
        uri = data[XMLRPC_URI]

        url_data = [uri]

        tmp = [topic, [name]]
        if tmp not in self._stat_info[1]:
            self._stat_info[1].append(tmp) 

        tm = get_topic_manager()
        try:
            tm.lock.acquire()
            if tm.has_publication(topic):
                self._logger.debug("I has pub topic :%s" % topic)
                self.registerPublisher(
                    get_node_handler().name, topic, datatype, get_node_handler().uri)
        except Exception as e:
            self._logger.error(
                "_registerSubscriberCallback error is  %s" % e)
            self._logger.error(traceback.format_exc())
        finally:
            tm.lock.release()
Example #10
0
def _rosout(level, msg):
    global _in_rosout
    try:
        if _rosout_pub is not None:
            # protect against infinite recursion
            if not _in_rosout:
                try:
                    _in_rosout = True
                    msg = str(msg)
                    topics = get_topic_manager().get_topics()
                    l = Log(level=level,
                            name=str(rospy.names.get_caller_id()),
                            msg=str(msg),
                            topics=topics)
                    l.header.stamp = Time.now()
                    _rosout_pub.publish(l)
                finally:
                    _in_rosout = False
    except Exception as e:
        #traceback.print_exc()
        # don't use logerr in this case as that is recursive here
        logger = logging.getLogger("rospy.rosout")
        logger.error("Unable to report rosout: %s\n%s", e,
                     traceback.format_exc())
        return False
Example #11
0
 def getSubscriptions(self, caller_id):
     """Retrieve a list of topics that this node subscribes to
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return [int, str, [ [topic1, topicType1]...[topicN, topicTypeN]]]: list of topics this node subscribes to
     """
     return 1, "subscriptions", get_topic_manager().get_subscriptions()
Example #12
0
    def _registerPublisherCallback(self, data):
        name = data[NODE_NAME]
        topic = data[TOPIC_NAME]
        topic_type = data[TOPIC_TYPE]
        topic_uri = data[XMLRPC_URI]
        url_data = [topic_uri]

        tmp = [topic, [name]]
        if tmp not in self._stat_info[0]:
            self._stat_info[0].append(tmp)

        topic_info = [x for x in self._topic_info if x[0] == topic]
        if topic_info:
            topic_info[0][1] = topic_type
        else:
            self._topic_info.append([topic, topic_type])

        tm = get_topic_manager()
        try:
            tm.lock.acquire()
            if tm.has_subscription(topic):
                self._logger.debug("I has sub topic : %s" % topic)
                get_node_handler().publisherUpdate(name, topic, url_data)
        except Exception as e:
            self._logger.error(
                "registerPublisherCallback error is  %s" % e)
            self._logger.error(traceback.format_exc())
        finally:
            tm.lock.release()
Example #13
0
 def getBusInfo(self, caller_id):
     """
     Retrieve transport/topic connection information
     @param caller_id: ROS caller id    
     @type  caller_id: str
     """
     return 1, "bus info", get_topic_manager().get_pub_sub_info()
Example #14
0
    def reregister(self):
        """
        Resets some of the attributes in order to restore the state of the object before
        the `unregister` method was called

        Reversing the `Topic.unregister()` and `Subscriber.unregister()` methods from
        `here <http://docs.ros.org/api/rospy/html/rospy.topics-pysrc.html>`_.

        """

        # Restore what was removed by the Topic.unregister() method
        self.impl = get_topic_manager().acquire_impl(
            self.reg_type, self._attributres_keeper['resolved_name'],
            self._attributres_keeper['data_class'])
        self.resolved_name = self._attributres_keeper['resolved_name']
        self.data_class = self._attributres_keeper['data_class']
        self.type = self.data_class._type
        self.md5sum = self.data_class._md5sum

        # Restore what was removed by the Subscriber.unregister() method
        if self._attributres_keeper['queue_size'] is not None:
            self.impl.set_queue_size(self._attributres_keeper['queue_size'])
        if self._attributres_keeper['buff_size'] != DEFAULT_BUFF_SIZE:
            self.impl.set_buff_size(self._attributres_keeper['buff_size'])
        if self._attributres_keeper['callback'] is not None:
            self.impl.add_callback(self._attributres_keeper['callback'],
                                   self._attributres_keeper['callback_args'])
            self.callback = self._attributres_keeper['callback']
            self.callback_args = self._attributres_keeper['callback_args']
        else:
            self.callback = self.callback_args = None
        if self._attributres_keeper['tcp_nodelay']:
            self.impl.set_tcp_nodelay(self._attributres_keeper['tcp_nodelay'])
Example #15
0
 def test_get_set_topic_manager(self):
     from rospy.impl.registration import get_topic_manager, set_topic_manager
     # rospy initialization sets this, but it is out of scope of
     # rospy.impl.registrations to test its value
     orig = get_topic_manager()
     try:
         self.assert_(orig is not None)
         class TopicManager(object): pass
         x = TopicManager()
     # currently untyped
         set_topic_manager(x)
         self.assertEquals(x, get_topic_manager())
         set_topic_manager(None)
         self.assert_(get_topic_manager() is None)
     finally:
         set_topic_manager(orig)            
Example #16
0
    def _connect_topic(self, topic, pub_uri):
        """
        Connect subscriber to topic
        @param topic: topic name to connect 
        @type  topic: str
        @param pub_uri: API URI of topic publisher
        @type  pub_uri: str
        @return: [code, msg, numConnects]. numConnects is the number
           of subscribers connected to the topic
        @rtype: [int, str, int]
        """
        caller_id = rospy.names.get_caller_id()
        sub = get_topic_manager().get_subscriber_impl(topic)
        if not sub:
            return -1, "No subscriber for topic [%s]" % topic, 0
        elif sub.has_connection(pub_uri):
            return 1, "_connect_topic[%s]: subscriber already connected to publisher [%s]" % (
                topic, pub_uri), 0

        #Negotiate with source for connection
        # - collect supported protocols
        protocols = []
        for h in self.protocol_handlers:  #currently only TCPROS
            protocols.extend(h.get_supported())
        if not protocols:
            return 0, "ERROR: no available protocol handlers", 0

        _logger.debug("connect[%s]: calling requestTopic(%s, %s, %s)", topic,
                      caller_id, topic, str(protocols))
        # 1) have to preserve original (unresolved) params as this may
        #    go outside our graph
        # 2) xmlrpclib doesn't give us any way of affecting the
        #    timeout other than affecting the global timeout. We need
        #    to set a timeout to prevent infinite hangs. 60 seconds is
        #    a *very* long time. All of the rospy code right now sets
        #    individual socket timeouts, but this could potentially
        #    affect user code.
        socket.setdefaulttimeout(60.)
        try:
            code, msg, result = \
                xmlrpcapi(pub_uri).requestTopic(caller_id, topic, protocols)
        except Exception as e:
            return 0, "unable to requestTopic: %s" % str(e), 0

        #Create the connection (if possible)
        if code <= 0:
            _logger.debug("connect[%s]: requestTopic did not succeed %s, %s",
                          pub_uri, code, msg)
            return code, msg, 0
        elif not result or type(protocols) != list:
            return 0, "ERROR: publisher returned invalid protocol choice: %s" % (
                str(result)), 0
        _logger.debug("connect[%s]: requestTopic returned protocol list %s",
                      topic, result)
        protocol = result[0]
        for h in self.protocol_handlers:
            if h.supports(protocol):
                return h.create_transport(topic, pub_uri, result)
        return 0, "ERROR: publisher returned unsupported protocol choice: %s" % result, 0
Example #17
0
 def getPublications(self, caller_id):
     """
     Retrieve a list of topics that this node publishes.
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: list of topics published by this node.
     @rtype: [int, str, [ [topic1, topicType1]...[topicN, topicTypeN]]]
     """
     return 1, "publications", get_topic_manager().get_publications()
Example #18
0
 def getPublications(self, caller_id):
     """
     Retrieve a list of topics that this node publishes.
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: list of topics published by this node.
     @rtype: [int, str, [ [topic1, topicType1]...[topicN, topicTypeN]]]
     """
     return 1, "publications", get_topic_manager().get_publications()
Example #19
0
    def test_get_set_topic_manager(self):
        from rospy.impl.registration import get_topic_manager, set_topic_manager
        # rospy initialization sets this, but it is out of scope of
        # rospy.impl.registrations to test its value
        orig = get_topic_manager()
        try:
            self.assert_(orig is not None)

            class TopicManager(object):
                pass

            x = TopicManager()
            # currently untyped
            set_topic_manager(x)
            self.assertEquals(x, get_topic_manager())
            set_topic_manager(None)
            self.assert_(get_topic_manager() is None)
        finally:
            set_topic_manager(orig)
Example #20
0
    def _connect_topic(self, topic, pub_uri): 
        """
        Connect subscriber to topic
        @param topic: topic name to connect 
        @type  topic: str
        @param pub_uri: API URI of topic publisher
        @type  pub_uri: str
        @return: [code, msg, numConnects]. numConnects is the number
           of subscribers connected to the topic
        @rtype: [int, str, int]
        """
        caller_id = rospy.names.get_caller_id()
        sub = get_topic_manager().get_subscriber_impl(topic)
        if not sub:
            return -1, "No subscriber for topic [%s]"%topic, 0
        elif sub.has_connection(pub_uri):
            return 1, "_connect_topic[%s]: subscriber already connected to publisher [%s]"%(topic, pub_uri), 0
        
        #Negotiate with source for connection
        # - collect supported protocols
        protocols = []
        for h in self.protocol_handlers: #currently only TCPROS
            protocols.extend(h.get_supported())
        if not protocols:
            return 0, "ERROR: no available protocol handlers", 0

        _logger.debug("connect[%s]: calling requestTopic(%s, %s, %s)", topic, caller_id, topic, str(protocols))
        # 1) have to preserve original (unresolved) params as this may
        #    go outside our graph
        # 2) xmlrpclib doesn't give us any way of affecting the
        #    timeout other than affecting the global timeout. We need
        #    to set a timeout to prevent infinite hangs. 60 seconds is
        #    a *very* long time. All of the rospy code right now sets
        #    individual socket timeouts, but this could potentially
        #    affect user code.
        socket.setdefaulttimeout(60.)
        try:
            code, msg, result = \
                xmlrpcapi(pub_uri).requestTopic(caller_id, topic, protocols)
        except Exception as e:
            return 0, "unable to requestTopic: %s"%str(e), 0

        #Create the connection (if possible)
        if code <= 0:
            _logger.debug("connect[%s]: requestTopic did not succeed %s, %s", pub_uri, code, msg)
            return code, msg, 0
        elif not result or type(protocols) != list:
            return 0, "ERROR: publisher returned invalid protocol choice: %s"%(str(result)), 0
        _logger.debug("connect[%s]: requestTopic returned protocol list %s", topic, result)
        protocol = result[0]
        for h in self.protocol_handlers:
            if h.supports(protocol):
                return h.create_transport(topic, pub_uri, result)
        return 0, "ERROR: publisher returned unsupported protocol choice: %s"%result, 0
Example #21
0
    def __init__(self, name, data_class, reg_type):
        """
        @param name: graph resource name of topic, e.g. 'laser'. 
        @type  name: str
        @param data_class: message class for serialization
        @type  data_class: L{Message}
        @param reg_type Registration.PUB or Registration.SUB
        @type  reg_type: str
        @raise ValueError: if parameters are invalid
        """

        if not name or not isstring(name):
            raise ValueError("topic name is not a non-empty string")
        try:
            if python3 == 1:
                name.encode("utf-8")
            else:
                name = name.encode("utf-8")
        except UnicodeError:
            raise ValueError("topic name must be ascii/utf-8 compatible")
        if data_class is None:
            raise ValueError("topic parameter 'data_class' is not initialized")
        if not type(data_class) == type:
            raise ValueError("data_class [%s] is not a class" % data_class)
        if not issubclass(data_class, genpy.Message):
            raise ValueError("data_class [%s] is not a message data class" %
                             data_class.__class__.__name__)
        # #2202
        if not rosgraph.names.is_legal_name(name):
            import warnings
            warnings.warn(
                "'%s' is not a legal ROS graph resource name. This may cause problems with other ROS tools"
                % name,
                stacklevel=2)

        # this is a bit ugly, but necessary due to the fact that we allow
        # topics and services to be initialized before the node
        if not rospy.core.is_initialized():
            self.resolved_name = rospy.names.resolve_name_without_node_name(
                name)
        else:
            # init_node() has been called, so we can do normal resolution
            self.resolved_name = resolve_name(name)

        self.name = self.resolved_name  # #1810 for backwards compatibility

        self.data_class = data_class
        self.type = data_class._type
        self.md5sum = data_class._md5sum
        self.reg_type = reg_type
        self.impl = get_topic_manager().acquire_impl(reg_type,
                                                     self.resolved_name,
                                                     data_class)
Example #22
0
 def getBusInfo(self, caller_id, client_ip_address):
     """
     Retrieve transport/topic connection information
     @param caller_id: ROS caller id    
     @type  caller_id: str
     """
     """ Only master is authorized to call this method """
     if is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn("getBusInfo( %s, %s ) method not authorized" %
                          (caller_id, client_ip_address))
         return 1, "bus info", get_topic_manager().get_pub_sub_info()
     else:
         return -1, "method not authorized", []
Example #23
0
 def getPublications(self, caller_id, client_ip_address):
     """
     Retrieve a list of topics that this node publishes.
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: list of topics published by this node.
     @rtype: [int, str, [ [topic1, topicType1]...[topicN, topicTypeN]]]
     """
     if not is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn(
             "getPublications( %s, %s ) method not authorized" %
             (caller_id, client_ip_address))
         return -1, "method not authorized", []
     return 1, "publications", get_topic_manager().get_publications()
Example #24
0
    def __init__(self, name, data_class, reg_type):
        """
        @param name: graph resource name of topic, e.g. 'laser'. 
        @type  name: str
        @param data_class: message class for serialization
        @type  data_class: L{Message}
        @param reg_type Registration.PUB or Registration.SUB
        @type  reg_type: str
        @raise ValueError: if parameters are invalid
        """

        if not name or not isstring(name):
            raise ValueError("topic name is not a non-empty string")
        try:
            if python3 == 1:
                name.encode("utf-8")
            else:
                name = name.encode("utf-8")
        except UnicodeError:
            raise ValueError("topic name must be ascii/utf-8 compatible")
        if data_class is None:
            raise ValueError("topic parameter 'data_class' is not initialized")
        if not type(data_class) == type:
            raise ValueError("data_class [%s] is not a class" % data_class)
        if not issubclass(data_class, genpy.Message):
            raise ValueError("data_class [%s] is not a message data class" % data_class.__class__.__name__)
        # #2202
        if not rosgraph.names.is_legal_name(name):
            import warnings

            warnings.warn(
                "'%s' is not a legal ROS graph resource name. This may cause problems with other ROS tools" % name,
                stacklevel=2,
            )

        # this is a bit ugly, but necessary due to the fact that we allow
        # topics and services to be initialized before the node
        if not rospy.core.is_initialized():
            self.resolved_name = rospy.names.resolve_name_without_node_name(name)
        else:
            # init_node() has been called, so we can do normal resolution
            self.resolved_name = resolve_name(name)

        self.name = self.resolved_name  # #1810 for backwards compatibility

        self.data_class = data_class
        self.type = data_class._type
        self.md5sum = data_class._md5sum
        self.reg_type = reg_type
        self.impl = get_topic_manager().acquire_impl(reg_type, self.resolved_name, data_class)
Example #25
0
 def getBusStats(self, caller_id):
     """
     Retrieve transport/topic statistics
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: [publishStats, subscribeStats, serviceStats]::
        publishStats: [[topicName, messageDataSent, pubConnectionData]...[topicNameN, messageDataSentN, pubConnectionDataN]]
            pubConnectionData: [connectionId, bytesSent, numSent, connected]* . 
        subscribeStats: [[topicName, subConnectionData]...[topicNameN, subConnectionDataN]]
            subConnectionData: [connectionId, bytesReceived, dropEstimate, connected]* . dropEstimate is -1 if no estimate. 
        serviceStats: not sure yet, probably akin to [numRequests, bytesReceived, bytesSent] 
     """
     pub_stats, sub_stats = get_topic_manager().get_pub_sub_stats()
     #TODO: serviceStats
     return 1, '', [pub_stats, sub_stats, []]
Example #26
0
 def getBusStats(self, caller_id):
     """
     Retrieve transport/topic statistics
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: [publishStats, subscribeStats, serviceStats]::
        publishStats: [[topicName, messageDataSent, pubConnectionData]...[topicNameN, messageDataSentN, pubConnectionDataN]]
            pubConnectionData: [connectionId, bytesSent, numSent, connected]* . 
        subscribeStats: [[topicName, subConnectionData]...[topicNameN, subConnectionDataN]]
            subConnectionData: [connectionId, bytesReceived, dropEstimate, connected]* . dropEstimate is -1 if no estimate. 
        serviceStats: not sure yet, probably akin to [numRequests, bytesReceived, bytesSent] 
     """
     pub_stats, sub_stats = get_topic_manager().get_pub_sub_stats()
     #TODO: serviceStats
     return 1, '', [pub_stats, sub_stats, []]
Example #27
0
 def getBusStats(self, caller_id, client_ip_address):
     """
     Retrieve transport/topic statistics
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: [publishStats, subscribeStats, serviceStats]::
        publishStats: [[topicName, messageDataSent, pubConnectionData]...[topicNameN, messageDataSentN, pubConnectionDataN]]
            pubConnectionData: [connectionId, bytesSent, numSent, connected]* . 
        subscribeStats: [[topicName, subConnectionData]...[topicNameN, subConnectionDataN]]
            subConnectionData: [connectionId, bytesReceived, dropEstimate, connected]* . dropEstimate is -1 if no estimate. 
        serviceStats: not sure yet, probably akin to [numRequests, bytesReceived, bytesSent] 
     """
     is_master = is_uri_match(self.masterUri, client_ip_address)
     pub_stats, sub_stats = get_topic_manager().get_pub_sub_stats()
     #TODO: serviceStats
     if is_master:
         return 1, '', [pub_stats, sub_stats, []]
     else:
         return -1, "Only master authorized to call getBusStats()", []
def _rosout(level, msg):
    global _in_rosout
    try:
        if _rosout_pub is not None:
            # protect against infinite recursion
            if not _in_rosout:
                try:
                    _in_rosout = True
                    msg = str(msg)
                    topics = get_topic_manager().get_topics()
                    l = Log(level=level, name=str(rospy.names.get_caller_id()), msg=str(msg), topics=topics)
                    l.header.stamp = Time.now()
                    _rosout_pub.publish(l)
                finally:
                    _in_rosout = False
    except Exception as e:
        #traceback.print_exc()
        # don't use logerr in this case as that is recursive here
        logger = logging.getLogger("rospy.rosout")        
        logger.error("Unable to report rosout: %s\n%s", e, traceback.format_exc())
        return False
Example #29
0
    def _connect_topic(self, topic, pub_uri):
        """
        Connect subscriber to topic.
        @param topic: Topic name to connect.
        @type  topic: str
        @param pub_uri: API URI of topic publisher.
        @type  pub_uri: str
        @return: [code, msg, numConnects]. numConnects is the number
           of subscribers connected to the topic.
        @rtype: [int, str, int]
        """
        caller_id = rospy.names.get_caller_id()
        sub = get_topic_manager().get_subscriber_impl(topic)
        if not sub:
            return -1, "No subscriber for topic [%s]" % topic, 0
        elif sub.has_connection(pub_uri):
            return 1, "_connect_topic[%s]: subscriber already connected to publisher [%s]" % (
                topic, pub_uri), 0

        #Negotiate with source for connection
        # - collect supported protocols
        protocols = []
        for h in self.protocol_handlers:  #currently only TCPROS
            protocols.extend(h.get_supported())
        if not protocols:
            return 0, "ERROR: no available protocol handlers", 0

        _logger.debug("connect[%s]: calling requestTopic(%s, %s, %s)", topic,
                      caller_id, topic, str(protocols))
        # 1) have to preserve original (unresolved) params as this may
        #    go outside our graph
        # 2) xmlrpclib doesn't give us any way of affecting the
        #    timeout other than affecting the global timeout. We need
        #    to set a timeout to prevent infinite hangs. 60 seconds is
        #    a *very* long time. All of the rospy code right now sets
        #    individual socket timeouts, but this could potentially
        #    affect user code.
        socket.setdefaulttimeout(60.)
        success = False
        interval = 0.5  # seconds
        # while the ROS node is not shutdown try to get the topic information
        # and retry on connections problems after some wait
        # Abort the retry if the we get a Connection Refused since at that point
        # we know for sure the URI is invalid
        while not success and not is_shutdown():
            try:
                code, msg, result = \
                      xmlrpcapi(pub_uri, cache=False).requestTopic(caller_id, topic, protocols)
                success = True
            except Exception as e:
                if getattr(e, 'errno', None) == errno.ECONNREFUSED:
                    code = -errno.ECONNREFUSED
                    msg = str(e)
                    break
                elif not is_shutdown():
                    _logger.debug("Retrying for %s" % topic)
                    if interval < 30.0:
                        # exponential backoff (maximum 32 seconds)
                        interval = interval * 2
                    time.sleep(interval)

        #Create the connection (if possible)
        if code <= 0:
            _logger.debug("connect[%s]: requestTopic did not succeed %s, %s",
                          pub_uri, code, msg)
            return code, msg, 0
        elif not result or type(protocols) != list:
            return 0, "ERROR: publisher returned invalid protocol choice: %s" % (
                str(result)), 0
        _logger.debug("connect[%s]: requestTopic returned protocol list %s",
                      topic, result)
        protocol = result[0]
        for h in self.protocol_handlers:
            if h.supports(protocol):
                return h.create_transport(topic, pub_uri, result)
        return 0, "ERROR: publisher returned unsupported protocol choice: %s" % result, 0
Example #30
0
    def _connect_topic(self, topic, pub_uri): 
        """
        Connect subscriber to topic.
        @param topic: Topic name to connect.
        @type  topic: str
        @param pub_uri: API URI of topic publisher.
        @type  pub_uri: str
        @return: [code, msg, numConnects]. numConnects is the number
           of subscribers connected to the topic.
        @rtype: [int, str, int]
        """
        caller_id = rospy.names.get_caller_id()
        sub = get_topic_manager().get_subscriber_impl(topic)
        if not sub:
            return -1, "No subscriber for topic [%s]"%topic, 0
        elif sub.has_connection(pub_uri):
            return 1, "_connect_topic[%s]: subscriber already connected to publisher [%s]"%(topic, pub_uri), 0
        
        #Negotiate with source for connection
        # - collect supported protocols
        protocols = []
        for h in self.protocol_handlers: #currently only TCPROS
            protocols.extend(h.get_supported())
        if not protocols:
            return 0, "ERROR: no available protocol handlers", 0

        _logger.debug("connect[%s]: calling requestTopic(%s, %s, %s)", topic, caller_id, topic, str(protocols))
        # 1) have to preserve original (unresolved) params as this may
        #    go outside our graph
        # 2) xmlrpclib doesn't give us any way of affecting the
        #    timeout other than affecting the global timeout. We need
        #    to set a timeout to prevent infinite hangs. 60 seconds is
        #    a *very* long time. All of the rospy code right now sets
        #    individual socket timeouts, but this could potentially
        #    affect user code.
        socket.setdefaulttimeout(60.)
        success = False
        interval = 0.5  # seconds
        # while the ROS node is not shutdown try to get the topic information
        # and retry on connections problems after some wait
        # Abort the retry if the we get a Connection Refused since at that point
        # we know for sure the URI is invalid
        while not success and not is_shutdown():
            try:
                code, msg, result = \
                      xmlrpcapi(pub_uri).requestTopic(caller_id, topic, protocols)
                success = True
            except Exception as e:
                if getattr(e, 'errno', None) == errno.ECONNREFUSED:
                    code = -errno.ECONNREFUSED
                    msg = str(e)
                    break
                elif not is_shutdown():
                    _logger.debug("Retrying for %s" % topic)
                    if interval < 30.0:
                        # exponential backoff (maximum 32 seconds)
                        interval = interval * 2
                    time.sleep(interval)

        #Create the connection (if possible)
        if code <= 0:
            _logger.debug("connect[%s]: requestTopic did not succeed %s, %s", pub_uri, code, msg)
            return code, msg, 0
        elif not result or type(protocols) != list:
            return 0, "ERROR: publisher returned invalid protocol choice: %s"%(str(result)), 0
        _logger.debug("connect[%s]: requestTopic returned protocol list %s", topic, result)
        protocol = result[0]
        for h in self.protocol_handlers:
            if h.supports(protocol):
                return h.create_transport(topic, pub_uri, result)
        return 0, "ERROR: publisher returned unsupported protocol choice: %s"%result, 0
    def test_Subscriber_unregister(self):
        # regression test for #3029 (unregistering a Subcriber with no
        # callback) plus other unregistration tests
        import rospy
        from rospy.impl.registration import get_topic_manager, Registration
        from rospy.topics import Subscriber, DEFAULT_BUFF_SIZE

        #Subscriber: name, data_class, callback=None, callback_args=None,
        #queue_size=None, buff_size=DEFAULT_BUFF_SIZE, tcp_nodelay=False):

        name = 'unregistertest'
        rname = rospy.resolve_name(name)
        data_class = test_rospy.msg.Val

        sub = Subscriber(name, data_class)
        self.assertEquals(None, sub.callback)

        # verify impl (test_Subscriber handles more verification, we
        # just care about callbacks and ref_count state here)
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == sub.impl)
        self.assertEquals(1, impl.ref_count)
        self.assertEquals([], impl.callbacks)
        
        # unregister should release the underlying impl
        sub.unregister()
        self.assertEquals(None, get_topic_manager().get_impl(Registration.SUB, rname))

        # create two subs
        sub2 = Subscriber(name, data_class)
        sub3 = Subscriber(name, data_class)        

        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        # - test that they share the same impl
        self.assert_(impl == sub2.impl)
        self.assert_(impl == sub3.impl)
        # - test basic impl state
        self.assertEquals([], impl.callbacks)
        self.assertEquals(2, impl.ref_count)
        sub2.unregister()
        self.assertEquals(1, impl.ref_count)
        # - make sure double unregister is safe
        sub2.unregister()
        self.assertEquals(1, impl.ref_count)
        # - clean it up
        sub3.unregister()
        self.assertEquals(0, impl.ref_count)
        self.assertEquals(None, get_topic_manager().get_impl(Registration.SUB, rname))

        # CALLBACKS
        cb_args5 = 5
        cb_args6 = 6
        cb_args7 = 7
        sub4 = Subscriber(name, data_class, callback1)
        # - use should be allowed to subcribe using the same callback
        # and it shouldn't interfere on unregister
        sub5 = Subscriber(name, data_class, callback2, cb_args5)        
        sub6 = Subscriber(name, data_class, callback2, cb_args6)        
        sub7 = Subscriber(name, data_class, callback2, cb_args7)        
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assertEquals(4, impl.ref_count)
        
        self.assertEquals([(callback1, None), (callback2, cb_args5), (callback2, cb_args6), (callback2, cb_args7)], impl.callbacks)
        # unregister sub6 first to as it is most likely to confuse any callback-finding logic
        sub6.unregister()
        self.assertEquals([(callback1, None), (callback2, cb_args5), (callback2, cb_args7)], impl.callbacks)
        self.assertEquals(3, impl.ref_count)
        sub5.unregister()
        self.assertEquals([(callback1, None), (callback2, cb_args7)], impl.callbacks)
        self.assertEquals(2, impl.ref_count)
        sub4.unregister()
        self.assertEquals([(callback2, cb_args7)], impl.callbacks)
        self.assertEquals(1, impl.ref_count)
        sub7.unregister()
        self.assertEquals([], impl.callbacks)
        self.assertEquals(0, impl.ref_count)
        self.assertEquals(None, get_topic_manager().get_impl(Registration.SUB, rname))

        # one final condition: two identical subscribers
        sub8 = Subscriber(name, data_class, callback1, 'hello')
        sub9 = Subscriber(name, data_class, callback1, 'hello')
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assertEquals([(callback1, 'hello'), (callback1, 'hello')], impl.callbacks)
        self.assertEquals(2, impl.ref_count)
        sub8.unregister()
        self.assertEquals([(callback1, 'hello')], impl.callbacks)
        self.assertEquals(1, impl.ref_count)
        sub9.unregister()
        self.assertEquals([], impl.callbacks)
        self.assertEquals(0, impl.ref_count)
    def test_Subscriber(self):
        #TODO: test callback args
        #TODO: negative buff_size
        #TODO: negative queue_size        
        import rospy
        from rospy.impl.registration import get_topic_manager, Registration
        from rospy.topics import Subscriber, DEFAULT_BUFF_SIZE

        #Subscriber: name, data_class, callback=None, callback_args=None,
        #queue_size=None, buff_size=DEFAULT_BUFF_SIZE, tcp_nodelay=False):

        name = 'foo'
        rname = rospy.resolve_name('foo')
        data_class = test_rospy.msg.Val

        # test invalid params
        for n in [None, '', 1]:
            try:
                Subscriber(n, data_class)
                self.fail("should not allow invalid name")
            except ValueError: pass
        for d in [None, 1, TestRospyTopics]:
            try:
                Subscriber(name, d)
                self.fail("should now allow invalid data_class")
            except ValueError: pass
        try:
            Subscriber(name, None)
            self.fail("None should not be allowed for data_class")
        except ValueError: pass
        
        sub = Subscriber(name, data_class)
        self.assertEquals(rname, sub.resolved_name)
        self.assertEquals(data_class, sub.data_class)
        self.assertEquals('test_rospy/Val', sub.type)
        self.assertEquals(data_class._md5sum, sub.md5sum)
        self.assertEquals(Registration.SUB, sub.reg_type)
        
        # verify impl as well
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == sub.impl)
        self.assertEquals([], impl.callbacks)
        self.assertEquals(rname, impl.resolved_name)
        self.assertEquals(data_class, impl.data_class)                
        self.assertEquals(None, impl.queue_size)
        self.assertEquals(DEFAULT_BUFF_SIZE, impl.buff_size)
        self.failIf(impl.tcp_nodelay)
        self.assertEquals(1, impl.ref_count)
        self.failIf(impl.closed)
        
        # round 2, now start setting options and make sure underlying impl is reconfigured
        name = 'foo'
        data_class = test_rospy.msg.Val
        queue_size = 1
        buff_size = 1
        sub = Subscriber(name, data_class, callback=callback1,
                         queue_size=queue_size, buff_size=buff_size, tcp_nodelay=True)
        self.assertEquals(rname, sub.resolved_name)
        # - sub.name is a backwards-compat field as it is public API
        self.assertEquals(rname, sub.name)        
        self.assertEquals(data_class, sub.data_class)

        # verify impl 
        impl2 = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == impl2) # should be same instance
        self.assertEquals([(callback1, None)], impl.callbacks)
        self.assertEquals(rname, impl.resolved_name)
        self.assertEquals(data_class, impl.data_class)                
        self.assertEquals(queue_size, impl.queue_size)
        self.assertEquals(buff_size, impl.buff_size)
        self.assert_(impl.tcp_nodelay)
        self.assertEquals(2, impl.ref_count)
        self.failIf(impl.closed)

        # round 3, make sure that options continue to reconfigure
        # underlying impl also test that tcp_nodelay is sticky. this
        # is technically undefined, but this is how rospy chose to
        # implement.
        name = 'foo'
        data_class = test_rospy.msg.Val
        queue_size = 2
        buff_size = 2
        sub = Subscriber(name, data_class, callback=callback2, 
                         queue_size=queue_size, buff_size=buff_size, tcp_nodelay=False)

        # verify impl 
        impl2 = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == impl2) # should be same instance
        self.assertEquals(set([(callback1, None), (callback2, None)]), set(impl.callbacks))
        self.assertEquals(queue_size, impl.queue_size)
        self.assertEquals(buff_size, impl.buff_size)
        self.assert_(impl.tcp_nodelay)
        self.assertEquals(3, impl.ref_count)
        self.failIf(impl.closed)
    def test_Publisher(self):
        import rospy
        from rospy.impl.registration import get_topic_manager, Registration
        from rospy.topics import Publisher, DEFAULT_BUFF_SIZE
        # Publisher(self, name, data_class, subscriber_listener=None, tcp_nodelay=False, latch=False, headers=None)

        name = 'foo'
        rname = rospy.resolve_name('foo')
        data_class = test_rospy.msg.Val

        # test invalid params
        for n in [None, '', 1]:
            try:
                Publisher(n, data_class)
                self.fail("should not allow invalid name")
            except ValueError: pass
        for d in [None, 1, TestRospyTopics]:
            try:
                Publisher(name, d)
                self.fail("should now allow invalid data_class")
            except ValueError: pass
        try:
            Publisher(name, None)
            self.fail("None should not be allowed for data_class")
        except ValueError: pass

        # round 1: test basic params
        pub = Publisher(name, data_class)
        self.assertEquals(rname, pub.resolved_name)
        # - pub.name is left in for backwards compatiblity, but resolved_name is preferred
        self.assertEquals(rname, pub.name)        
        self.assertEquals(data_class, pub.data_class)
        self.assertEquals('test_rospy/Val', pub.type)
        self.assertEquals(data_class._md5sum, pub.md5sum)
        self.assertEquals(Registration.PUB, pub.reg_type)
        
        # verify impl as well
        impl = get_topic_manager().get_impl(Registration.PUB, rname)
        self.assert_(impl == pub.impl)
        self.assertEquals(rname, impl.resolved_name)
        self.assertEquals(data_class, impl.data_class)                
        self.failIf(impl.is_latch)
        self.assertEquals(None, impl.latch)                
        self.assertEquals(0, impl.seq)
        self.assertEquals(1, impl.ref_count)
        self.assertEquals('', impl.buff.getvalue())
        self.failIf(impl.closed)
        self.failIf(impl.has_connections())
        # check publish() fall-through
        from test_rospy.msg import Val
        impl.publish(Val('hello world-1'))
        
        # check stats
        self.assertEquals(0, impl.message_data_sent)
        # check acquire/release don't bomb
        impl.acquire()
        impl.release()        

        # do a single publish with connection override. The connection
        # override is a major cheat as the object isn't even an actual
        # connection. I will need to add more integrated tests later
        co1 = ConnectionOverride('co1')
        self.failIf(impl.has_connection('co1'))
        impl.add_connection(co1)
        self.assert_(impl.has_connection('co1'))
        self.assert_(impl.has_connections())        
        impl.publish(Val('hello world-1'), connection_override=co1)

        import cStringIO
        buff = cStringIO.StringIO()
        Val('hello world-1').serialize(buff)
        # - check equals, but strip length field first
        self.assertEquals(co1.data[4:], buff.getvalue())
        self.assertEquals(None, impl.latch)
        
        # Now enable latch
        pub = Publisher(name, data_class, latch=True)
        impl = get_topic_manager().get_impl(Registration.PUB, rname)
        # have to verify latching in pub impl
        self.assert_(impl == pub.impl)
        self.assertEquals(True, impl.is_latch)
        self.assertEquals(None, impl.latch)
        self.assertEquals(2, impl.ref_count)        

        co2 = ConnectionOverride('co2')
        self.failIf(impl.has_connection('co2'))
        impl.add_connection(co2)
        for n in ['co1', 'co2']:
            self.assert_(impl.has_connection(n))
        self.assert_(impl.has_connections())        
        v = Val('hello world-2')
        impl.publish(v, connection_override=co2)
        self.assert_(v == impl.latch)

        buff = cStringIO.StringIO()
        Val('hello world-2').serialize(buff)
        # - strip length and check value
        self.assertEquals(co2.data[4:], buff.getvalue())

        # test that latched value is sent to connections on connect
        co3 = ConnectionOverride('co3')
        self.failIf(impl.has_connection('co3'))
        impl.add_connection(co3)
        for n in ['co1', 'co2', 'co3']:
            self.assert_(impl.has_connection(n))
        self.assert_(impl.has_connections())
        self.assertEquals(co3.data[4:], buff.getvalue())        
        
        # TODO: tcp_nodelay
        # TODO: suscribe listener
        self.assert_(impl.has_connection('co1'))
        impl.remove_connection(co1)
        self.failIf(impl.has_connection('co1'))
        self.assert_(impl.has_connections())
        
        self.assert_(impl.has_connection('co3'))
        impl.remove_connection(co3)        
        self.failIf(impl.has_connection('co3'))
        self.assert_(impl.has_connections())
        
        self.assert_(impl.has_connection('co2'))
        impl.remove_connection(co2)        
        self.failIf(impl.has_connection('co2'))
        self.failIf(impl.has_connections())

        # test publish() latch on a new Publisher object (this was encountered in testing, so I want a test case for it)
        pub = Publisher('bar', data_class, latch=True)
        v = Val('no connection test')
        pub.impl.publish(v)
        self.assert_(v == pub.impl.latch)

        # test connection header
        h = {'foo': 'bar', 'fuga': 'hoge'}
        pub = Publisher('header_test', data_class, headers=h)
        self.assertEquals(h, pub.impl.headers)
Example #34
0
    def test_Publisher(self):
        import rospy
        from rospy.impl.registration import get_topic_manager, Registration
        from rospy.topics import Publisher, DEFAULT_BUFF_SIZE
        # Publisher(self, name, data_class, subscriber_listener=None, tcp_nodelay=False, latch=False, headers=None)

        name = 'foo'
        rname = rospy.resolve_name('foo')
        data_class = test_rospy.msg.Val

        # test invalid params
        for n in [None, '', 1]:
            try:
                Publisher(n, data_class)
                self.fail("should not allow invalid name")
            except ValueError:
                pass
        for d in [None, 1, TestRospyTopics]:
            try:
                Publisher(name, d)
                self.fail("should now allow invalid data_class")
            except ValueError:
                pass
        try:
            Publisher(name, None)
            self.fail("None should not be allowed for data_class")
        except ValueError:
            pass

        # round 1: test basic params
        pub = Publisher(name, data_class)
        self.assertEquals(rname, pub.resolved_name)
        # - pub.name is left in for backwards compatiblity, but resolved_name is preferred
        self.assertEquals(rname, pub.name)
        self.assertEquals(data_class, pub.data_class)
        self.assertEquals('test_rospy/Val', pub.type)
        self.assertEquals(data_class._md5sum, pub.md5sum)
        self.assertEquals(Registration.PUB, pub.reg_type)

        # verify impl as well
        impl = get_topic_manager().get_impl(Registration.PUB, rname)
        self.assert_(impl == pub.impl)
        self.assertEquals(rname, impl.resolved_name)
        self.assertEquals(data_class, impl.data_class)
        self.failIf(impl.is_latch)
        self.assertEquals(None, impl.latch)
        self.assertEquals(0, impl.seq)
        self.assertEquals(1, impl.ref_count)
        self.assertEquals('', impl.buff.getvalue())
        self.failIf(impl.closed)
        self.failIf(impl.has_connections())
        # check publish() fall-through
        from test_rospy.msg import Val
        impl.publish(Val('hello world-1'))

        # check stats
        self.assertEquals(0, impl.message_data_sent)
        # check acquire/release don't bomb
        impl.acquire()
        impl.release()

        # do a single publish with connection override. The connection
        # override is a major cheat as the object isn't even an actual
        # connection. I will need to add more integrated tests later
        co1 = ConnectionOverride('co1')
        self.failIf(impl.has_connection('co1'))
        impl.add_connection(co1)
        self.assert_(impl.has_connection('co1'))
        self.assert_(impl.has_connections())
        impl.publish(Val('hello world-1'), connection_override=co1)

        import cStringIO
        buff = cStringIO.StringIO()
        Val('hello world-1').serialize(buff)
        # - check equals, but strip length field first
        self.assertEquals(co1.data[4:], buff.getvalue())
        self.assertEquals(None, impl.latch)

        # Now enable latch
        pub = Publisher(name, data_class, latch=True)
        impl = get_topic_manager().get_impl(Registration.PUB, rname)
        # have to verify latching in pub impl
        self.assert_(impl == pub.impl)
        self.assertEquals(True, impl.is_latch)
        self.assertEquals(None, impl.latch)
        self.assertEquals(2, impl.ref_count)

        co2 = ConnectionOverride('co2')
        self.failIf(impl.has_connection('co2'))
        impl.add_connection(co2)
        for n in ['co1', 'co2']:
            self.assert_(impl.has_connection(n))
        self.assert_(impl.has_connections())
        v = Val('hello world-2')
        impl.publish(v, connection_override=co2)
        self.assert_(v == impl.latch)

        buff = cStringIO.StringIO()
        Val('hello world-2').serialize(buff)
        # - strip length and check value
        self.assertEquals(co2.data[4:], buff.getvalue())

        # test that latched value is sent to connections on connect
        co3 = ConnectionOverride('co3')
        self.failIf(impl.has_connection('co3'))
        impl.add_connection(co3)
        for n in ['co1', 'co2', 'co3']:
            self.assert_(impl.has_connection(n))
        self.assert_(impl.has_connections())
        self.assertEquals(co3.data[4:], buff.getvalue())

        # TODO: tcp_nodelay
        # TODO: suscribe listener
        self.assert_(impl.has_connection('co1'))
        impl.remove_connection(co1)
        self.failIf(impl.has_connection('co1'))
        self.assert_(impl.has_connections())
        # TODO: need to validate DeadTransport better
        self.assert_(
            [d for d in impl.dead_connections if d.endpoint_id == 'co1'])

        self.assert_(impl.has_connection('co3'))
        impl.remove_connection(co3)
        self.failIf(impl.has_connection('co3'))
        self.assert_(impl.has_connections())
        for id in ['co1', 'co3']:
            self.assert_(
                [d for d in impl.dead_connections if d.endpoint_id == id])

        self.assert_(impl.has_connection('co2'))
        impl.remove_connection(co2)
        self.failIf(impl.has_connection('co2'))
        self.failIf(impl.has_connections())
        for id in ['co1', 'co2', 'co3']:
            self.assert_(
                [d for d in impl.dead_connections if d.endpoint_id == id])

        # test publish() latch on a new Publisher object (this was encountered in testing, so I want a test case for it)
        pub = Publisher('bar', data_class, latch=True)
        v = Val('no connection test')
        pub.impl.publish(v)
        self.assert_(v == pub.impl.latch)

        # test connection header
        h = {'foo': 'bar', 'fuga': 'hoge'}
        pub = Publisher('header_test', data_class, headers=h)
        self.assertEquals(h, pub.impl.headers)
Example #35
0
    def test_Subscriber(self):
        #TODO: test callback args
        #TODO: negative buff_size
        #TODO: negative queue_size
        import rospy
        from rospy.impl.registration import get_topic_manager, Registration
        from rospy.topics import Subscriber, DEFAULT_BUFF_SIZE

        #Subscriber: name, data_class, callback=None, callback_args=None,
        #queue_size=None, buff_size=DEFAULT_BUFF_SIZE, tcp_nodelay=False):

        name = 'foo'
        rname = rospy.resolve_name('foo')
        data_class = test_rospy.msg.Val

        # test invalid params
        for n in [None, '', 1]:
            try:
                Subscriber(n, data_class)
                self.fail("should not allow invalid name")
            except ValueError:
                pass
        for d in [None, 1, TestRospyTopics]:
            try:
                Subscriber(name, d)
                self.fail("should now allow invalid data_class")
            except ValueError:
                pass
        try:
            Subscriber(name, None)
            self.fail("None should not be allowed for data_class")
        except ValueError:
            pass

        sub = Subscriber(name, data_class)
        self.assertEquals(rname, sub.resolved_name)
        self.assertEquals(data_class, sub.data_class)
        self.assertEquals('test_rospy/Val', sub.type)
        self.assertEquals(data_class._md5sum, sub.md5sum)
        self.assertEquals(Registration.SUB, sub.reg_type)

        # verify impl as well
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == sub.impl)
        self.assertEquals([], impl.callbacks)
        self.assertEquals(rname, impl.resolved_name)
        self.assertEquals(data_class, impl.data_class)
        self.assertEquals(None, impl.queue_size)
        self.assertEquals(DEFAULT_BUFF_SIZE, impl.buff_size)
        self.failIf(impl.tcp_nodelay)
        self.assertEquals(1, impl.ref_count)
        self.failIf(impl.closed)

        # round 2, now start setting options and make sure underlying impl is reconfigured
        name = 'foo'
        data_class = test_rospy.msg.Val
        queue_size = 1
        buff_size = 1
        sub = Subscriber(name,
                         data_class,
                         callback=callback1,
                         queue_size=queue_size,
                         buff_size=buff_size,
                         tcp_nodelay=True)
        self.assertEquals(rname, sub.resolved_name)
        # - sub.name is a backwards-compat field as it is public API
        self.assertEquals(rname, sub.name)
        self.assertEquals(data_class, sub.data_class)

        # verify impl
        impl2 = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == impl2)  # should be same instance
        self.assertEquals([(callback1, None)], impl.callbacks)
        self.assertEquals(rname, impl.resolved_name)
        self.assertEquals(data_class, impl.data_class)
        self.assertEquals(queue_size, impl.queue_size)
        self.assertEquals(buff_size, impl.buff_size)
        self.assert_(impl.tcp_nodelay)
        self.assertEquals(2, impl.ref_count)
        self.failIf(impl.closed)

        # round 3, make sure that options continue to reconfigure
        # underlying impl also test that tcp_nodelay is sticky. this
        # is technically undefined, but this is how rospy chose to
        # implement.
        name = 'foo'
        data_class = test_rospy.msg.Val
        queue_size = 2
        buff_size = 2
        sub = Subscriber(name,
                         data_class,
                         callback=callback2,
                         queue_size=queue_size,
                         buff_size=buff_size,
                         tcp_nodelay=False)

        # verify impl
        impl2 = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == impl2)  # should be same instance
        self.assertEquals(set([(callback1, None), (callback2, None)]),
                          set(impl.callbacks))
        self.assertEquals(queue_size, impl.queue_size)
        self.assertEquals(buff_size, impl.buff_size)
        self.assert_(impl.tcp_nodelay)
        self.assertEquals(3, impl.ref_count)
        self.failIf(impl.closed)
Example #36
0
    def test_Subscriber_unregister(self):
        # regression test for #3029 (unregistering a Subcriber with no
        # callback) plus other unregistration tests
        import rospy
        from rospy.impl.registration import get_topic_manager, Registration
        from rospy.topics import Subscriber, DEFAULT_BUFF_SIZE

        #Subscriber: name, data_class, callback=None, callback_args=None,
        #queue_size=None, buff_size=DEFAULT_BUFF_SIZE, tcp_nodelay=False):

        name = 'unregistertest'
        rname = rospy.resolve_name(name)
        data_class = test_rospy.msg.Val

        sub = Subscriber(name, data_class)
        self.assertEquals(None, sub.callback)

        # verify impl (test_Subscriber handles more verification, we
        # just care about callbacks and ref_count state here)
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assert_(impl == sub.impl)
        self.assertEquals(1, impl.ref_count)
        self.assertEquals([], impl.callbacks)

        # unregister should release the underlying impl
        sub.unregister()
        self.assertEquals(
            None,
            get_topic_manager().get_impl(Registration.SUB, rname))

        # create two subs
        sub2 = Subscriber(name, data_class)
        sub3 = Subscriber(name, data_class)

        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        # - test that they share the same impl
        self.assert_(impl == sub2.impl)
        self.assert_(impl == sub3.impl)
        # - test basic impl state
        self.assertEquals([], impl.callbacks)
        self.assertEquals(2, impl.ref_count)
        sub2.unregister()
        self.assertEquals(1, impl.ref_count)
        # - make sure double unregister is safe
        sub2.unregister()
        self.assertEquals(1, impl.ref_count)
        # - clean it up
        sub3.unregister()
        self.assertEquals(0, impl.ref_count)
        self.assertEquals(
            None,
            get_topic_manager().get_impl(Registration.SUB, rname))

        # CALLBACKS
        cb_args5 = 5
        cb_args6 = 6
        cb_args7 = 7
        sub4 = Subscriber(name, data_class, callback1)
        # - use should be allowed to subcribe using the same callback
        # and it shouldn't interfere on unregister
        sub5 = Subscriber(name, data_class, callback2, cb_args5)
        sub6 = Subscriber(name, data_class, callback2, cb_args6)
        sub7 = Subscriber(name, data_class, callback2, cb_args7)
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assertEquals(4, impl.ref_count)

        self.assertEquals([(callback1, None), (callback2, cb_args5),
                           (callback2, cb_args6), (callback2, cb_args7)],
                          impl.callbacks)
        # unregister sub6 first to as it is most likely to confuse any callback-finding logic
        sub6.unregister()
        self.assertEquals([(callback1, None), (callback2, cb_args5),
                           (callback2, cb_args7)], impl.callbacks)
        self.assertEquals(3, impl.ref_count)
        sub5.unregister()
        self.assertEquals([(callback1, None), (callback2, cb_args7)],
                          impl.callbacks)
        self.assertEquals(2, impl.ref_count)
        sub4.unregister()
        self.assertEquals([(callback2, cb_args7)], impl.callbacks)
        self.assertEquals(1, impl.ref_count)
        sub7.unregister()
        self.assertEquals([], impl.callbacks)
        self.assertEquals(0, impl.ref_count)
        self.assertEquals(
            None,
            get_topic_manager().get_impl(Registration.SUB, rname))

        # one final condition: two identical subscribers
        sub8 = Subscriber(name, data_class, callback1, 'hello')
        sub9 = Subscriber(name, data_class, callback1, 'hello')
        impl = get_topic_manager().get_impl(Registration.SUB, rname)
        self.assertEquals([(callback1, 'hello'), (callback1, 'hello')],
                          impl.callbacks)
        self.assertEquals(2, impl.ref_count)
        sub8.unregister()
        self.assertEquals([(callback1, 'hello')], impl.callbacks)
        self.assertEquals(1, impl.ref_count)
        sub9.unregister()
        self.assertEquals([], impl.callbacks)
        self.assertEquals(0, impl.ref_count)