Simple example of custom rqt plugin
Hi.
I would like to understand how to subscribe to a ROS topic from custom rqt plugin with Python. As for now i couldn't make it work. Can you provide some very simple example (or reference) to how to write a subscriber that updates some text in GUI based on topic data?
Thanks in advance.
EDIT: I have gone through rqt package tutorial from here and I created my own plugin. Now I want to subscribe to the data from the topic contains array of 8 integers to update 8 text labels. My problem is that the plugin is working for some time and eventually going down after 20-30seconds because of memory leakage This is my_module.py:
import os
import rospy
import rospkg
from std_msgs.msg import Int32MultiArray, String
import time
from qt_gui.plugin import Plugin
from python_qt_binding import loadUi
from python_qt_binding.QtWidgets import QWidget
class MyPlugin(Plugin):
def __init__(self, context):
super(MyPlugin, self).__init__(context)
# Give QObjects reasonable names
self.setObjectName('MyPlugin')
# Process standalone plugin command-line arguments
from argparse import ArgumentParser
parser = ArgumentParser()
# Add argument(s) to the parser.
parser.add_argument("-q", "--quiet", action="store_true",
dest="quiet",
help="Put plugin in silent mode")
args, unknowns = parser.parse_known_args(context.argv())
if not args.quiet:
print 'arguments: ', args
print 'unknowns: ', unknowns
# Create QWidget
self._widget = QWidget()
# Get path to UI file which should be in the "resource" folder of this package
ui_file = os.path.join(rospkg.RosPack().get_path('rqt_mypkg'), 'resource', 'MyPlugin.ui')
# Extend the widget with all attributes and children from UI file
loadUi(ui_file, self._widget)
# Give QObjects reasonable names
self._widget.setObjectName('MyPluginUi')
# Show _widget.windowTitle on left-top of each plugin (when
# it's set in _widget). This is useful when you open multiple
# plugins at once. Also if you open multiple instances of your
# plugin at once, these lines add number to make it easy to
# tell from pane to pane.
if context.serial_number() > 1:
self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))
# Add widget to the user interface
context.add_widget(self._widget)
#Subscriber
self.sub_status = rospy.Subscriber('/random_status', String, self.callback_string, queue_size=20)
self.sub = rospy.Subscriber("/random_ints", Int32MultiArray, self.callback, queue_size=20)
def shutdown_plugin(self):
# TODO unregister all publishers here
pass
def callback(self, msg):
self._widget.label_10.setText(repr(msg.data[0]))
self._widget.label_12.setText(repr(msg.data[1]))
self._widget.label_14.setText(repr(msg.data[2]))
self._widget.label_15.setText(repr(msg.data[3]))
self._widget.label_17.setText(repr(msg.data[4]))
self._widget.label_19.setText(repr(msg.data[5]))
self._widget.label_21.setText(repr(msg.data[6]))
self._widget.label_23.setText(repr(msg.data[7]))
def callback_string(self, msg):
self._widget.label_2.setText(msg.data)
def save_settings(self, plugin_settings, instance_settings):
# TODO save intrinsic configuration, usually using:
# instance_settings.set_value(k, v)
pass
def restore_settings(self, plugin_settings, instance_settings):
# TODO restore intrinsic configuration, usually using:
# v = instance_settings.value(k)
pass
#def trigger_configuration(self):
# Comment in to signal that the plugin has a way to configure
# This will enable a setting button (gear ...
Perhaps lucasw/rqt_mypkg can help.
Thanks. However, I cannot find any declaration of subscriber/publisher there?
I'd missed the part about the subscriber. In general you'd create your subscribers (and publishers) in the ctor though.
For other readers:
this is typically not enough information. Please describe what you've tried and what exactly is failing for you.
I edited the question and gave more information.