如何使用 RQT 插件创建简单的 GUI?

问题描述 投票:0回答:1

我是 ROS 2 的新手,我正在尝试使用 RQT 插件创建一个简单的 GUI。为此,我遵循本指南中描述的流程:

https://robobe.github.io/blog/ROS2/rqt/custom_plugin/step1/

请注意,我使用的是 ros2 iron 和 Python 3.10.12,操作系统是 Linux Mint。

目前项目结构如下:

~/ros2_custom_rqt_plugin $ tree
.
└── src
    └── rqt_mypkg
        ├── LICENSE
        ├── package.xml
        ├── plugin.xml
        ├── resource
        │   └── rqt_mypkg
        ├── rqt_mypkg
        │   ├── __init__.py
        │   └── my_module.py
        ├── setup.cfg
        ├── setup.py
        └── test
            ├── test_copyright.py
            ├── test_flake8.py
            └── test_pep257.py

5 directories, 11 files

在 my_module.py 文件中,我有以下内容:

#!/usr/bin/env python3

# File: rqt_mypkg/rqt_mypkg/my_module.py

from rqt_gui_py.plugin import Plugin
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel

class MyPlugin(Plugin):
    def __init__(self, context):
        super(MyPlugin, self).__init__(context)
        self.setObjectName('MyPlugin')

        # GUI initialization code 
        self._widget = MyWidget()
        self._widget.setObjectName('UniqueWidget') 
        self.setWidget(self._widget)

class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()

        # Create a layout
        layout = QVBoxLayout(self)

        # Create a button
        self.button = QPushButton('Click Me!', self)
        self.button.clicked.connect(self.on_button_click)

        # Create a label for text display
        self.label = QLabel('Hello, World!', self)

        # Add the button and label to the layout
        layout.addWidget(self.button)
        layout.addWidget(self.label)

    def on_button_click(self):
        self.label.setText('Button Clicked!')

在此代码中,MyPlugin 类应该继承自 rqt_gui_py.Plugin 并创建 MyWidget 类的实例。

在 package.xml 文件中,我有:

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>rqt_mypkg</name>
  <version>0.0.0</version>
  <description>My RQT plugin</description>
  <maintainer email="[email protected]">Sam</maintainer>
  <license>Apache License 2.0</license>

  <depend>rclpy</depend>
  <depend>rqt_gui</depend>
  <depend>rqt_gui_py</depend>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
    <rqt_gui plugin="${prefix}/plugin.xml"/>
  </export>
</package>

与链接指南保持一致,我在

<rqt_gui plugin="${prefix}/plugin.xml"/>
标签内添加了
<export>
行。

在plugin.xml中我有:

<library path="src">
  <class name="My Plugin" type="rqt_mypkg.my_module.MyPlugin" base_class_type="rqt_gui_py::Plugin">
    <description>
      An example Python GUI plugin to create a great user interface.
    </description>
    <qtgui>
      <group>
        <label>Visualization</label>
      </group>
      <label>My first Python Plugin</label>
      <icon type="theme">system-help</icon>
      <statustip>Great user interface to provide real value.</statustip>
    </qtgui>
  </class>
</library>

此代码与链接指南中提供的示例完全相同。

在 setup.py 中我有:

from setuptools import find_packages, setup

package_name = 'rqt_mypkg'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml', 'plugin.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='sam',
    maintainer_email='[email protected]',
    description='TODO: Package description',
    license='Apache-2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)

值得注意的是,我修改了 data_files 部分以包含plugin.xml

为了构建项目并加载插件,我尝试执行以下命令:

~/ros2_custom_rqt_plugin $ colcon build
~/ros2_custom_rqt_plugin $ source install/setup.bash 
~/ros2_custom_rqt_plugin $ rqt --force-discover --standalone rqt_mypkg

该项目似乎构建没有问题,但是当我尝试加载插件时,我得到以下信息:

~/ros2_custom_rqt_plugin $ rqt --force-discover --standalone rqt_mypkg
PluginManager._load_plugin() could not load plugin "rqt_mypkg/My Plugin":
Traceback (most recent call last):
  File "/opt/ros/iron/lib/python3.10/site-packages/qt_gui/plugin_handler.py", line 102, in load
    self._load()
  File "/opt/ros/iron/lib/python3.10/site-packages/qt_gui/plugin_handler_direct.py", line 55, in _load
    self._plugin = self._plugin_provider.load(self._instance_id.plugin_id, self._context)
  File "/opt/ros/iron/lib/python3.10/site-packages/qt_gui/composite_plugin_provider.py", line 72, in load
    instance = plugin_provider.load(plugin_id, plugin_context)
  File "/opt/ros/iron/lib/python3.10/site-packages/qt_gui/composite_plugin_provider.py", line 72, in load
    instance = plugin_provider.load(plugin_id, plugin_context)
  File "/opt/ros/iron/lib/python3.10/site-packages/rqt_gui_py/ros_py_plugin_provider.py", line 69, in load
    return super(RosPyPluginProvider, self).load(plugin_id, ros_plugin_context)
  File "/opt/ros/iron/lib/python3.10/site-packages/qt_gui/composite_plugin_provider.py", line 72, in load
    instance = plugin_provider.load(plugin_id, plugin_context)
  File "/opt/ros/iron/lib/python3.10/site-packages/rqt_gui/ros_plugin_provider.py", line 107, in load
    return class_ref(plugin_context)
  File "/home/sam/ros2_custom_rqt_plugin/install/rqt_mypkg/lib/python3.10/site-packages/rqt_mypkg/my_module.py", line 16, in __init__
    self.setWidget(self._widget)
AttributeError: 'MyPlugin' object has no attribute 'setWidget'

Failed to delete datawriter, at ./src/publisher.cpp:45 during '__function__'
Warning: class_loader.ClassLoader: SEVERE WARNING!!! Attempting to unload library while objects created by this loader exist in the heap! You should delete your objects before attempting to unload the library or destroying the ClassLoader. The library will NOT be unloaded.
         at line 127 in ./src/class_loader.cpp

从这条消息来看,由于属性错误,插件无法加载:

AttributeError: 'MyPlugin' object has no attribute 'setWidget'

我原以为setWidget属性是rqt_gui_py.plugin的一部分,所以MyPlugin类应该能够访问它。我可以进行哪些更改才能正确加载插件?

python qt robotics ros2 rqt
1个回答
0
投票

更新:我可以通过将以下内容放入 my_modules.py 来使插件正常工作

#!/usr/bin/env python3

# File: rqt_mypkg/rqt_mypkg/my_module.py

from rqt_gui_py.plugin import Plugin
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel

class MyPlugin(Plugin):
    def __init__(self, context):
        super(MyPlugin, self).__init__(context)
        self.setObjectName('MyPlugin')

        # GUI initialization code 
        self._widget = MyWidget()
        print("MyWidget instance created")

        self._widget.show()
        
       
class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()

        print("MyWidget constructor called...")

        self.setStyleSheet("background-color: white;")

        # Create a layout
        layout = QVBoxLayout(self)

        # Create a button
        self.button = QPushButton('Click Me!', self)
        self.button.clicked.connect(self.on_button_click)

        # Create a label for text display
        self.label = QLabel('Hello, World!', self)

        # Add the button and label to the layout
        layout.addWidget(self.button)
        layout.addWidget(self.label)

         # Set the layout for the widget
        self.setLayout(layout)

    def on_button_click(self):
        self.label.setText('Button Clicked!')
© www.soinside.com 2019 - 2024. All rights reserved.