手把手教你编写一个自己的rqt plugin (C++版)

ROS里的rqt plugin以Python语言编写的居多,c++的较少,如rqt_image_view和rviz是C++。Python版的见上一篇总结:https://blog.csdn.net/yaked/article/details/118420240

cd ~/pcl_ws/src (任一个ROS工作空间即可,我这里为pcl_ws, 你可以替换为catkin_ws)

catkin_create_pkg rqt_example_cpp roscpp rqt_gui rqt_gui_cpp std_msgs

还是之前的六步:

1. 修改package.xml,填入export语句让我们的plugin能够被系统找到进行调用。

2. 创建plugin.xml ,描述plugin,最重要的是,在rqt_gui界面中的分组与顺序。

3.  setup.py 通过ROS的catkin, 利用CMake 来将脚本文件放在一个不在PATH中但是又跟package关联的文件夹下让系统找得到。

4. 修改CMakeLists.txt

5. 创建src/rqt_example_cpp/my_plugin.cpp 和 include/rqt_example_cpp/my_plugin.h

6. 界面元素及布局 MyPlugin.ui
 

一、文件详述

1.1 package.xml

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

1.2 plugin.xml 确定在rqt_gui界面中的名字(label)与分组(group)

<library path="lib/librqt_example_cpp">
  <class name="rqt_example_cpp/MyPlugin" type="rqt_example_cpp::MyPlugin" base_class_type="rqt_gui_cpp::Plugin">
    <description>
      An example C++ GUI plugin to create a great user interface.
    </description>
    <qtgui>
      <!-- optional grouping...
      <group>
        <label>Group</label>
      </group>
      <group>
        <label>Subgroup</label>
      </group>
      -->
      <label>yake first C++ Plugin</label>
      <icon type="theme">system-help</icon>
      <statustip>Great user interface to provide real value.</statustip>
    </qtgui>
  </class>
</library>

library path 及class name ,名字(label)与分组(group)

1.3 setup.py 

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

# fetch values from package.xml
setup_args = generate_distutils_setup(
    packages=['rqt_example_cpp'],
    package_dir={'': 'src'},
    requires=['std_msgs', 'roscpp']
)

setup(**setup_args)

requires 和 setup不一样 

1.4 CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(rqt_example_cpp)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  roslint
  rqt_gui
  rqt_gui_cpp
  std_msgs
)

if("${qt_gui_cpp_USE_QT_MAJOR_VERSION} " STREQUAL "5 ")
  find_package(Qt5Widgets REQUIRED)
else()
  find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
  include(${QT_USE_FILE})
endif()

catkin_python_setup()

roslint_cpp()

catkin_package(
#  INCLUDE_DIRS include
  LIBRARIES ${PROJECT_NAME}
  CATKIN_DEPENDS roscpp rqt_gui_cpp std_msgs
#  DEPENDS system_lib
)


set (rqt_example_cpp_SRCS
  src/rqt_example_cpp/my_plugin.cpp
)

set(rqt_example_cpp_HDRS
  include/rqt_example_cpp/my_plugin.h
)

set(rqt_example_cpp_UIS
  src/rqt_example_cpp/my_plugin.ui
)

if("${qt_gui_cpp_USE_QT_MAJOR_VERSION} " STREQUAL "5 ")
  qt5_wrap_cpp(rqt_example_cpp_MOCS ${rqt_example_cpp_HDRS})
  qt5_wrap_ui(rqt_example_cpp_UIS_H ${rqt_example_cpp_UIS})
else()
  qt4_wrap_cpp(rqt_example_cpp_MOCS ${rqt_example_cpp_HDRS})
  qt4_wrap_ui(rqt_example_cpp_UIS_H ${rqt_example_cpp_UIS})
endif()

include_directories(
  include
  ${CMAKE_CURRENT_BINARY_DIR}/..
  ${catkin_INCLUDE_DIRS}
)

add_library(${PROJECT_NAME}
    ${rqt_example_cpp_SRCS}
    ${rqt_example_cpp_MOCS}
    ${rqt_example_cpp_UIS_H}
    )

target_link_libraries(${PROJECT_NAME}
  ${catkin_LIBRARIES}
)

if("${qt_gui_cpp_USE_QT_MAJOR_VERSION} " STREQUAL "5 ")
  target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
else()
  target_link_libraries(${PROJECT_NAME} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
endif()

生成动态库*.so 

1.5 src/rqt_example_cpp/my_plugin.cpp 

#include "rqt_example_cpp/my_plugin.h"
#include <pluginlib/class_list_macros.h>
#include <QStringList>

namespace rqt_example_cpp
{

MyPlugin::MyPlugin()
  : rqt_gui_cpp::Plugin()
  , widget_(0)
{
  // Constructor is called first before initPlugin function, needless to say.

  // give QObjects reasonable names
  setObjectName("MyPlugin");
}

void MyPlugin::initPlugin(qt_gui_cpp::PluginContext& context)
{
  // access standalone command line arguments
  QStringList argv = context.argv();
  // create QWidget
  widget_ = new QWidget();
  // extend the widget with all attributes and children from UI file
  ui_.setupUi(widget_);
  // add widget to the user interface
  context.addWidget(widget_);
}

void MyPlugin::shutdownPlugin()
{
  // unregister all publishers here
}

void MyPlugin::saveSettings(qt_gui_cpp::Settings& plugin_settings,
    qt_gui_cpp::Settings& instance_settings) const
{
  // instance_settings.setValue(k, v)
}

void MyPlugin::restoreSettings(const qt_gui_cpp::Settings& plugin_settings,
    const qt_gui_cpp::Settings& instance_settings)
{
  // v = instance_settings.value(k)
}

/*bool hasConfiguration() const
{
  return true;
}

void triggerConfiguration()
{
  // Usually used to open a dialog to offer the user a set of configuration
}*/

}  // namespace rqt_example_cpp
//PLUGINLIB_DECLARE_CLASS(rqt_example_cpp, MyPlugin, rqt_example_cpp::MyPlugin, rqt_gui_cpp::Plugin)
PLUGINLIB_EXPORT_CLASS(rqt_example_cpp::MyPlugin, rqt_gui_cpp::Plugin)

1.6 src/rqt_example_cpp/MyPlugin.ui 

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QPushButton" name="Test">
   <property name="geometry">
    <rect>
     <x>120</x>
     <y>70</y>
     <width>98</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>C++ button</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

1.7 include/rqt_example_cpp/MyPlugin.h 

#ifndef RQT_EXAMPLE_CPP_MY_PLUGIN_H
#define RQT_EXAMPLE_CPP_MY_PLUGIN_H

#include <rqt_gui_cpp/plugin.h>
#include <rqt_example_cpp/ui_my_plugin.h>
#include <QWidget>

namespace rqt_example_cpp
{

class MyPlugin
  : public rqt_gui_cpp::Plugin
{
  Q_OBJECT
public:
  MyPlugin();
  virtual void initPlugin(qt_gui_cpp::PluginContext& context);
  virtual void shutdownPlugin();
  virtual void saveSettings(qt_gui_cpp::Settings& plugin_settings,
      qt_gui_cpp::Settings& instance_settings) const;
  virtual void restoreSettings(const qt_gui_cpp::Settings& plugin_settings,
      const qt_gui_cpp::Settings& instance_settings);

  // Comment in to signal that the plugin has a way to configure it
  // bool hasConfiguration() const;
  // void triggerConfiguration();
private:
  Ui::MyPluginWidget ui_;
  QWidget* widget_;
};
}  // namespace rqt_example_cpp
#endif  // RQT_EXAMPLE_CPP_MY_PLUGIN_H

编译运行 

cd ~/pcl_ws/

catkin_make

rosrun rqt_mypkg rqt_mypkg

或rqt -s rqt_mypkg  (-s, 指的是standalone)

如果没有找到试试 rqt --force-discover

参考:

https://github.com/ros-visualization/rqt_image_view

https://github.com/lucasw/rqt_mypkg/tree/master/rqt_example_cpp

https://fjp.at/ros/rqt-turtle/ 较为复杂的案例,知识点较多,慢慢品味

猜你喜欢

转载自blog.csdn.net/yaked/article/details/118498926