手把手教你编写一个自己的rqt plugin (C++版)
Posted yaked
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手教你编写一个自己的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/ 较为复杂的案例,知识点较多,慢慢品味
以上是关于手把手教你编写一个自己的rqt plugin (C++版)的主要内容,如果未能解决你的问题,请参考以下文章
手把手教你编写一个自己的rqt plugin (Python版)