ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | Q&A answers.ros.org

# Create an RViz dockable panel w/ catkin and Qt5

Hi everyone,

These past days, I'm trying to write an RViz dockable panel following the tutorial here.
My goal is basically to display – for now – an empty panel (the strict minimum, for a beginning).
The problem is that all the tutorial is writing with both rosbuild and Qt4, while I would like to use catkin and Qt5. Each time I'm trying to compile, I keep having this error message :

[ERROR] [1426085794.672184440]: PluginlibFactory: The plugin for class 'plugin_panel/Hi' failed to load.  Error: Failed to load library /home/mdufour/catkin_ws_test/devel/lib/libplugin_panel.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library (Poco exception = /home/mdufour/catkin_ws_test/devel/lib/libplugin_panel.so: undefined symbol: _ZTVN8my_panel11PluginPanelE)

My package directory looks like this :

plugin_panel/
|__ CMakeLists.txt
|__ package.xml
|__ plugin_description.xml
|__ src/
|__ plugin_panel.cpp

All the code is in the .cpp file, for simplification.
Here's my CMakeLists.txt :

cmake_minimum_required(VERSION 2.8.11)

project(plugin_panel)

find_package(Qt4 REQUIRED)
find_package(catkin REQUIRED)

include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS})

add_library(${PROJECT_NAME} src/plugin_panel.cpp) target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}${catkin_LIBRARIES})

This is my .cpp (very basic!) :

#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>

#include <rviz/panel.h>

namespace my_panel
{
class PluginPanel: public rviz::Panel
{
Q_OBJECT

public:
PluginPanel(QWidget* parent = 0):
rviz::Panel(parent)
{
QHBoxLayout* topic_layout = new QHBoxLayout;
}
};
}

#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(my_panel::PluginPanel, rviz::Panel)

The package.xml (overloaded for sure) :

<?xml version="1.0"?>
<package>
<name>plugin_panel</name>

<version>0.0.0</version>

<description>
An additional (yet empty) panel in RViz.
</description>

<maintainer email="none@none.none">Matthieu</maintainer>

<buildtool_depend>catkin</buildtool_depend>

<build_depend>roscpp</build_depend>
<build_depend>roslib</build_depend>
<build_depend>rviz</build_depend>
<build_depend>pluginlib</build_depend>

<run_depend>roscpp</run_depend>
<run_depend>roslib</run_depend>
<run_depend>rviz</run_depend>
<run_depend>pluginlib</run_depend>

<export>
<rviz plugin="${prefix}/plugin_description.xml"/> </export> <package> And finally the plugin_description.xml : <library path="lib/libplugin_panel"> <class name="plugin_panel/Hi" type="my_panel::PluginPanel" base_class_type="rviz::Panel"> <description> An empty panel. </description> </class> </library> Phew! Sorry, that was heavy… I'm certainly missing something in one of those files, but I can't figure out what. Thanks for your answers. edit retag close merge delete ## 4 Answers Sort by » oldest newest most voted target_link_libraries(${PROJECT_NAME} Qt5::Widgets ${catkin_LIBRARIES})  I'm not too familiar with Qt5, but I'm not sure whether Qt5::Widgets is an actual library name under Linux. according to Using CMake with Qt 5 - Building Qt 5 projects with CMake, linking to Qt5 libraries with CMake should be done as follows (for the QtWidgets component): target_link_libraries(YOUR_TARGET [..]${Qt5Widgets_LIBRARIES})


That page has a lot of information on using CMake with Qt5 actually.

Also: according to Developing with Qt - The Transition from Qt 4.x to Qt 5, Qt5 could make use of C++11 features. Afaik, ROS (still) doesn't support that, and binary compatibility may not be guaranteed when mixing and matching (non)C++11 compatible object files/libraries.

Edit3:

find_package(catkin REQUIRED)

Shouldn't at least rviz be listed as COMPONENTS here?

Looking at the CMakeLists.txt of the catkinized version of the plugin tutorial package you linked to it would seem that you are missing some important parts:

find_package(catkin REQUIRED COMPONENTS rviz)
catkin_package()
include_directories(${catkin_INCLUDE_DIRS}) link_directories(${catkin_LIBRARY_DIRS})

## This plugin includes Qt widgets, so we must include Qt like so:
find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
include(${QT_USE_FILE}) ## I prefer the Qt signals and slots to avoid defining "emit", "slots", ## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here. add_definitions(-DQT_NO_KEYWORDS) ## Here we specify which header files need to be run through "moc", ## Qt's meta-object compiler. qt4_wrap_cpp(MOC_FILES src/drive_widget.h src/imu_display.h src/plant_flag_tool.h src/teleop_panel.h ) ## Here we specify the list of source files, including the output of ## the previous command which is stored in ${MOC_FILES}.
set(SOURCE_FILES
src/drive_widget.cpp
src/imu_display.cpp
src/imu_visual.cpp
src/plant_flag_tool.cpp
src/teleop_panel.cpp
${MOC_FILES} ) ## An rviz plugin is just a shared library, so here we declare the ## library to be called ${PROJECT_NAME} (which is
## "rviz_plugin_tutorials", or whatever your version of this project
## is called) and specify the list of source files we collected above
## in ${SOURCE_FILES}. add_library(${PROJECT_NAME} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}${catkin_LIBRARIES})

more

Unfortunately, I just re-wrote my CMakeLists.txt to follow the standards of Qt4 (using find_package(Qt4 REQUIRED) etc), and I still have the error message :(

( 2015-03-11 10:41:30 -0600 )edit

Ok, well, could you update your question then (CMakeLists.txt, etc)? Perhaps there is some other issue going on here.

( 2015-03-11 10:43:17 -0600 )edit

You say "nothing happened at all": which bits did you copy, and what didn't happen?

( 2015-03-11 11:43:58 -0600 )edit

"I'm not too familiar with Qt5, but I'm not sure whether Qt5::Widgets is an actual library name under Linux." It's called a target generator or something like that and is the recommended way now (since CMake 2.8.11/12), it will add includes, libs, flags, .. http://doc.qt.io/qt-5/cmake-manual.html

( 2015-08-17 07:59:05 -0600 )edit

I just stumbled across this error as well (while porting rviz to qt5) and will note the answer here for documentation purposes.

So the error you got from pluginloader tells you that your plugin shared object (.so) is not linked to everything it expects. This is because moc, the Meta Object Compiler is used by Qt to create some meta information about what classes, functions, signals, slots exist. moc reads header files searching for classes with the Q_OBJECT macro (short version ;) ). It then outputs a new cpp code file containing this information. This file has to be compiled and linked into your plugin.

The traditional way is what gvdhoorn wrote, the more modern way would be to add

set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)


and you are done (works for qt4 and qt5).

If some errors remain, it might be because automoc is not perfect. It then helps to just add the header file to the sources list

Writing rviz plugins in Qt5 and loading them in a rviz that was compiled with Qt4 does not work. Neither does the other way around. But the code should be almost the same, so you can just recompile once rviz got ported to qt5

more

1

Your comment "If some errors remain, it might be because automoc is not perfect. It then helps to just add the header file to the sources list" saved my day. After battling with this error for hours, this finally worked. Cheers!

( 2016-07-11 09:10:32 -0600 )edit

That saved my day too... Thank you so much for that comment.

( 2017-01-17 08:07:34 -0600 )edit

Anonymous

@inflo :
Okay, so here's my final package. I organized it this way :

plugin_panel/
|__ CMakeLists.txt
|__ package.xml
|__ plugin_description.xml
|__ include/
|__ plugin_panel.h
|__ src/
|__ plugin_panel.cpp

The plugin displays a simple dockable panel with two QPushButton.
- CMakeLists.txt :

cmake_minimum_required(VERSION 2.8.11)

project(plugin_panel)

find_package(catkin REQUIRED)
find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui)

include(${QT_USE_FILE}) include_directories(include/) qt4_wrap_cpp(QT_MOC include/plugin_panel.h) set(SOURCES src/plugin_panel.cpp${QT_MOC})

add_library(${PROJECT_NAME}${SOURCES})

target_link_libraries(${PROJECT_NAME}${QT_LIBRARIES} ${catkin_LIBRARIES}) - package.xml : <?xml version="1.0"?> <package> <name>plugin_panel</name> <version>1.0.0</version> <description> An additional panel in RViz. </description> <maintainer email="none@none.none">Matthieu</maintainer> <license>BSD</license> <buildtool_depend>catkin</buildtool_depend> <build_depend>rviz</build_depend> <run_depend>rviz</run_depend> <export> <rviz plugin="${prefix}/plugin_description.xml"/>
</export>
</package>

- plugin_description.xml :

<library path="lib/libplugin_panel">
<class name="plugin_panel/HelloWorld"
type="PluginPanel"
base_class_type="rviz::Panel">
<description>
An empty panel.
</description>
</class>
</library>

- include/plugin_panel.h :

#include <QtGui>

#include <rviz/panel.h>

class PluginPanel: public rviz::Panel
{
Q_OBJECT

public:
PluginPanel(QWidget* parent = 0);

protected:
QVBoxLayout* _vbox;

QPushButton* _button1;
QPushButton* _button2;
};

- src/plugin_panel.cpp :

#include <pluginlib/class_list_macros.h>

#include "plugin_panel.h"

PluginPanel::PluginPanel(QWidget* parent):
rviz::Panel(parent)
{
_vbox = new QVBoxLayout();

_button1 = new QPushButton(tr("Button 1"));
_button2 = new QPushButton(tr("Button 2"));

_button1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_button2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

setLayout(_vbox);
}

PLUGINLIB_EXPORT_CLASS(PluginPanel, rviz::Panel)

That's it!
That's the minimum code I found after many iterations, each time trying to remove as much thing as possible from any files.

more

hi, many thanks for re-posting.

But i got the problem that it seemed nothing to build when i run "catkin_make" in the catkin_ws directory ?

i can also not tab-complete the package after typing "catkin_make plug" tab tab ?

how do you build the package and do you do anything else (copy files,etc ?

( 2015-03-14 07:28:36 -0600 )edit

hi, it builds the lib and i can find it in /home/ros/catkin_ws/devel/lib/libplugin_panel.so but when i run, rosrun rviz rviz, , its not there?

i sourced devel/setup.bash before, and my ROS_PACKAGE_PATH=/home/ros/catkin_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks

what do i wrong? flo

( 2015-03-14 08:53:41 -0600 )edit

From my side, once I have run catkin_make in my catkin_ws folder, the only thing I have to do next is to run RViz (rosrun rviz rviz), then Add panel inside RViz.

( 2015-03-15 08:52:08 -0600 )edit

hi, i got it, i am an idiot,i was always trying to add a "display" instead of the panel.

thanks alot for your help flo

( 2015-03-15 09:06:35 -0600 )edit

Hi, when i use your posted code and then do in the workspace a "catkin_make" it returns:

Invalid package manifest "/home/ros/catkin_ws/src/plugin_panel/package.xml": The manifest contains invalid XML: no element found: line 34, column 0

could you post the package.xml and the new CMakeLists.txt file again please ?

thanks flo

EDIT: the end tag is </package> with a / infront of package.

But after re-catkin_make and running rosrun rviz rviz it is not there, when i click on the "Add" button in rviz ?

could you please post you CMakeListst.txt and package.xml file again ? would help me much

thanks flo

more

Hi flo,
I'm currently updating all my files to make them as light as possible, and running too!
I will post it here as soon as I get something satisfying :)

( 2015-03-13 14:19:19 -0600 )edit