ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
4

Is there a way to subscribe to a topic without setting the type?

asked 2012-06-19 18:13:21 -0500

updated 2014-01-28 17:12:44 -0500

ngrennan gravatar image

I try to create some UI to allow users to select a topic and visualize the data published on that topic. To get started I wanted to have only one field for the topic name and connect to it with python. In theory it should be possible to receive callbacks without knowing the message type since the messages are introspectable in python using:

message.__slots__
message._slot_types
message.__getattribute__('x')

I tried to use the Subscriber class but that one enforces the use of a data class when you subscribe to a topic.

edit retag flag offensive close merge delete

5 Answers

Sort by ยป oldest newest most voted
1

answered 2012-06-22 11:13:59 -0500

You can try and use the internal rostopic API directly to list topic names and detect the topic type (see the code API page for rostopic here)

The only drawback of using the API directly is that code breaking changes may be made to it in the future. If you are worried about this, you could potentially try and parse the output of the rostopic command, as this command line tool is stable.

edit flag offensive delete link more
1

answered 2019-06-05 07:32:15 -0500

Davide Faconti gravatar image

For your information, there is a package in C++ that does exactly this:

https://github.com/facontidavide/ros_...

edit flag offensive delete link more
1

answered 2020-10-05 04:48:15 -0500

fivef gravatar image

A version using a callback to make it a drop-in replacement for a rospy.Subscriber(). Based on KindDragon's answer.

Usage:

my_subscriber = GenericMessageSubscriber('topic_name', message_callback)

def message_callback(data):
    # handle your callback exactly as you would do it with a normal Subscriber
    print(data)

Class:

class GenericMessageSubscriber(object):
def __init__(self, topic_name, callback):
    self._binary_sub = rospy.Subscriber(
        topic_name, rospy.AnyMsg, self.generic_message_callback)
    self._callback = callback

def generic_message_callback(self, data):
    assert sys.version_info >= (2,7) #import_module's syntax needs 2.7
    connection_header =  data._connection_header['type'].split('/')
    ros_pkg = connection_header[0] + '.msg'
    msg_type = connection_header[1]
    msg_class = getattr(import_module(ros_pkg), msg_type)
    msg = msg_class().deserialize(data._buff)
    self._callback(msg)
edit flag offensive delete link more
1

answered 2012-06-23 08:41:31 -0500

SL Remy gravatar image

piyushk is correct, but according to the wiki, "rostopic is a stable command-line tool within the ROS core toolchain. The underlying code may undergo refactoring for easier library use, but the external API is expected to be fairly stable."

Using functions like:

get_topic_type

data_type = rostopic.get_topic_type('my_topic', blocking=False)[0]
if data_type:
      data_class = roslib.message.get_message_class(data_type)
      #... do fun things here

Now, according to REP100 roslib.message is supposed to be moved to rosgraph but I can't find it there, even in fuerte.

I hope that this was really a reference to something else.. because there is sooo much code that is still using roslib.message...

edit flag offensive delete link more

Comments

2

Thank you! To get the data class you can use "rostopic.get_topic_class('topic')" directly.

Felix Kaser gravatar image Felix Kaser  ( 2012-06-24 13:54:13 -0500 )edit

Thank you!To get the data class you can use "rostopic.get_topic_class('topic')" directly.

Felix Kaser gravatar image Felix Kaser  ( 2012-06-24 13:54:13 -0500 )edit
1

answered 2019-05-22 04:28:45 -0500

KindDragon gravatar image

updated 2020-10-05 04:31:51 -0500

fivef gravatar image

import rospy import sys

from importlib import import_module

class Listener(object):
    def __init__(self):
        self._binary_sub = rospy.Subscriber(
            'some_topic', rospy.AnyMsg, self.topic_callback)

    def topic_callback(self, data):
        assert sys.version_info >= (2,7) #import_module's syntax needs 2.7
        connection_header =  data._connection_header['type'].split('/')
        ros_pkg = connection_header[0] + '.msg'
        msg_type = connection_header[1]
        print 'Message type detected as ' + msg_type
        msg_class = getattr(import_module(ros_pkg), msg_type)
        msg = msg_class().deserialize(data._buff)

        print data.known_field

Based on article http://schulz-m.github.io/2016/07/18/...

edit flag offensive delete link more

Question Tools

3 followers

Stats

Asked: 2012-06-19 18:13:21 -0500

Seen: 4,184 times

Last updated: Oct 05 '20