0
$\begingroup$

I'm having trouble making Rviz teleop plugin using Qtcreator. I'm using Noetic and Ubuntu 20.04.

The codes is not complete yet, for now I just want to see teleop GUI on Rviz. I'm using catkin_make_isolated --install build system

Error message: [ERROR] [1694503592.866043597]: PluginlibFactory: The plugin for class 'rviz_teleop_plugin/QtTeleopPanel' failed to load. Error: Could not find library corresponding to plugin rviz_teleop_plugin/QtTeleopPanel. Make sure the plugin description XML file has the correct name of the library and that the library actually exists.

files: package name: rviz_teleop_plugin

  1. CMakeLists.txt
  2. package.xml
  3. plugin_description.xml
  4. src/qt_teleop_ui,cpp
  5. include/rviz_teleop_plugin/qt_teleop_ui.h
cmake_minimum_required(VERSION 3.0.2)
project(rviz_teleop_plugin)

find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  nav_msgs
  roscpp
  rospy
  rviz
  sensor_msgs
  std_msgs
)

find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Core REQUIRED)
find_package(Qt5OpenGL REQUIRED)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(QT_LIBRARIES Qt5::Widgets)

add_definitions(-DQT_NO_KEYWORDS)

catkin_package(
  INCLUDE_DIRS include
  LIBRARIES rviz_teleop_plugin
  CATKIN_DEPENDS geometry_msgs nav_msgs roscpp rospy rviz sensor_msgs std_msgs
  # DEPENDS system_lib
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  ${Qt5Widgets_INCLUDE_DIRS}
)

link_directories(${catkin_LIBRARY_DIRS})

qt5_wrap_cpp(MOC_FILES
  include/rviz_teleop_plugin/qt_teleop_ui.h
)

set(SOURCE_FILES
  src/qt_teleop_ui.cpp
  ${MOC_FILES}
)

add_library(${PROJECT_NAME}
  ${SOURCE_FILES}
)

add_dependencies(rviz_teleop_plugin ${PROJECT_NAME_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

target_link_libraries(${PROJECT_NAME}
  Qt5::Widgets
  ${QT_LIBRARIES}
  ${catkin_LIBRARIES}
)

install(TARGETS 
  ${PROJECT_NAME}
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

install(DIRECTORY include/${PROJECT_NAME}/ rviz
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
)

install(FILES plugin_description.xml
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)

set_target_properties(rviz_teleop_plugin PROPERTIES OUTPUT_NAME "rviz_teleop_plugin")
<?xml version="1.0"?>
<package format="2">
  <name>rviz_teleop_plugin</name>
  <version>0.0.0</version>
  <description>The rviz_teleop_plugin package</description>

  <maintainer email="[email protected]">minseojeong</maintainer>
  <license>TODO</license>

  <buildtool_depend>catkin</buildtool_depend>

  <build_depend>geometry_msgs</build_depend>
  <build_depend>nav_msgs</build_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>rviz</build_depend>
  <build_depend>sensor_msgs</build_depend>
  <build_depend>std_msgs</build_depend>

  <build_depend>qt_gui_cpp</build_depend>
  <build_depend>qtbase5-dev</build_depend>
  <build_depend>libqt5-core</build_depend>
  <build_depend>libqt5-gui</build_depend>
  <build_depend>libqt5-widgets</build_depend>

  <build_export_depend>geometry_msgs</build_export_depend>
  <build_export_depend>nav_msgs</build_export_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>rviz</build_export_depend>
  <build_export_depend>sensor_msgs</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>

  <build_export_depend>qt_gui_cpp</build_export_depend>
  <build_export_depend>qtbase5-dev</build_export_depend>
  <build_export_depend>libqt5-core</build_export_depend>
  <build_export_depend>libqt5-gui</build_export_depend>
  <build_export_depend>libqt5-widgets</build_export_depend>

  <exec_depend>geometry_msgs</exec_depend>
  <exec_depend>nav_msgs</exec_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>rviz</exec_depend>
  <exec_depend>sensor_msgs</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <exec_depend>qt_gui_cpp</exec_depend>
  <exec_depend>qtbase5-dev</exec_depend>
  <exec_depend>libqt5-core</exec_depend>
  <exec_depend>libqt5-gui</exec_depend>
  <exec_depend>libqt5-widgets</exec_depend>

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

</package>
<!-- <library path="lib/librviz_teleop_plugin"> -->
<library path="install_isolated/lib/librviz_teleop_plugin.so">
  <class name="rviz_teleop_plugin/QtTeleopPanel"
         type="rviz_teleop_plugin::QtTeleopPanel"
         base_class_type="rviz::Panel">
    <description>
      A Teleop Panel to control the robot.
    </description>
    <qtgui>
      <name>rviz_teleop_plugin/QtTeleopPanel</name>
      <class>rviz_teleop_plugin::QtTeleopPanel</class>
      <label>Teleop Panel</label>
    </qtgui>
  </class>
</library>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QDoubleSpinBox>
// #include <QtWidgets/QPainter>
// #include <QtWidgets/QLineEdit>

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
#include <QtWidgets/QSlider>

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
// #include <rviz/panel.h>

#include "rviz_teleop_plugin/qt_teleop_ui.h"

class QtTeleopPanel;

namespace rviz_teleop_plugin
{
    QtTeleopPanel::QtTeleopPanel(QWidget* parent)
        : rviz::Panel(parent),
        // : QWidget(parent),
          nh_("~"),
          cmd_vel_pub_(nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1))

    {
        QVBoxLayout* layout = new QVBoxLayout;

        QLabel* X_label = new QLabel("X ::");
        QDoubleSpinBox* X_doubleSpinBox = new QDoubleSpinBox;
        X_doubleSpinBox->setMaximum(1.0);
        X_doubleSpinBox->setSingleStep(0.01);

        QLabel* Y_label = new QLabel("Y ::");
        QDoubleSpinBox* Y_doubleSpinBox = new QDoubleSpinBox;
        Y_doubleSpinBox->setMaximum(1.0);
        Y_doubleSpinBox->setSingleStep(0.01);

        QPushButton* Send_Button = new QPushButton("Send");
        QPushButton* Up_Button = new QPushButton("UP");
        QPushButton* Stop_Button = new QPushButton("Stop");
        QPushButton* Down_Button = new QPushButton("Down");
        QPushButton* Left_Button = new QPushButton("Left");
        QPushButton* Right_Button = new QPushButton("Right");

        QLabel* Linear_label = new QLabel("Linear vel");
        QDoubleSpinBox* Linear_doubleSpinBox = new QDoubleSpinBox;
        Linear_doubleSpinBox->setMaximum(1.0);
        Linear_doubleSpinBox->setSingleStep(0.01);

        QLabel* Angular_label = new QLabel("Angular vel");
        QDoubleSpinBox* Angular_doubleSpinBox = new QDoubleSpinBox;
        Angular_doubleSpinBox->setMaximum(1.0);
        Angular_doubleSpinBox->setSingleStep(0.1);

        layout->addWidget(X_label);
        layout->addWidget(X_doubleSpinBox);
        layout->addWidget(Y_label);
        layout->addWidget(Y_doubleSpinBox);
        layout->addWidget(Send_Button);
        layout->addWidget(Up_Button);
        layout->addWidget(Stop_Button);
        layout->addWidget(Down_Button);
        layout->addWidget(Left_Button);
        layout->addWidget(Right_Button);
        layout->addWidget(Linear_label);
        layout->addWidget(Linear_doubleSpinBox);
        layout->addWidget(Angular_label);
        layout->addWidget(Angular_doubleSpinBox);

        QWidget::setLayout(layout);

        QObject::connect(Up_Button, SIGNAL(clicked()), this, SLOT(on_Up_Button_pressed()));
        QObject::connect(Down_Button, SIGNAL(clicked()), this, SLOT(on_Down_Button_pressed()));
        QObject::connect(Left_Button, SIGNAL(clicked()), this, SLOT(on_Left_Button_pressed()));
        QObject::connect(Right_Button, SIGNAL(clicked()), this, SLOT(on_Right_Button_pressed()));
        QObject::connect(Stop_Button, SIGNAL(clicked()), this, SLOT(on_Stop_Button_pressed()));
        QObject::connect(Send_Button, SIGNAL(clicked(bool)), this, SLOT(on_Send_Button_clicked(bool)));
        QObject::connect(X_doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(on_X_doubleSpinBox_valueChanged(double)));
        QObject::connect(Y_doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(on_Y_doubleSpinBox_valueChanged(double)));
        QObject::connect(Linear_doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(on_Linear_doubleSpinBox_valueChanged(double)));
        QObject::connect(Angular_doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(on_Angular_doubleSpinBox_valueChanged(double)));
    }

    void QtTeleopPanel::on_Up_Button_pressed()
    {
        geometry_msgs::Twist cmd_vel;
        cmd_vel.linear.x = this->Linear_doubleSpinBox->value();
        cmd_vel.angular.z = this->Angular_doubleSpinBox->value();

        cmd_vel_pub_.publish(cmd_vel);
    }

    void QtTeleopPanel::on_Down_Button_pressed()
    {
        geometry_msgs::Twist cmd_vel;
        cmd_vel.linear.x = -this->Linear_doubleSpinBox->value();
        cmd_vel.angular.z = -this->Angular_doubleSpinBox->value();

        cmd_vel_pub_.publish(cmd_vel);
    }

    void QtTeleopPanel::on_Left_Button_pressed()
    {
        geometry_msgs::Twist cmd_vel;
        cmd_vel.linear.x = 0.0;
        cmd_vel.angular.z = this->Angular_doubleSpinBox->value();

        cmd_vel_pub_.publish(cmd_vel);
    }

    void QtTeleopPanel::on_Right_Button_pressed()
    {
        geometry_msgs::Twist cmd_vel;
        cmd_vel.linear.x = 0.0;
        cmd_vel.angular.z = -this->Angular_doubleSpinBox->value();

        cmd_vel_pub_.publish(cmd_vel);
    }

    void QtTeleopPanel::on_Stop_Button_pressed()
    {
        geometry_msgs::Twist cmd_vel;
        cmd_vel.linear.x = 0.0;
        cmd_vel.angular.z = 0.0;

        cmd_vel_pub_.publish(cmd_vel);
    }

    void QtTeleopPanel::on_Send_Button_clicked(bool checked)
    {
    }

    void QtTeleopPanel::on_X_doubleSpinBox_valueChanged(double arg1)
    {
    }

    void QtTeleopPanel::on_Y_doubleSpinBox_valueChanged(double arg1)
    {
    }

    void QtTeleopPanel::on_Linear_doubleSpinBox_valueChanged(double arg1)
    {
    }

    void QtTeleopPanel::on_Angular_doubleSpinBox_valueChanged(double arg1)
    {
    }

} // namespae

#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_teleop_plugin::QtTeleopPanel, rviz::Panel)
/********************************************************************************
** Form generated from reading UI file 'qt_teleop.ui'
**
** Created by: Qt User Interface Compiler version 5.12.8
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

// #ifndef QT_TELEOP_UI_H
// #define QT_TELEOP_UI_H

#ifndef QT_TELEOP_UI_H
#define QT_TELEOP_UI_H

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
#include <QtWidgets/QSlider>
#include <QtWidgets/QVBoxLayout>


#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <rviz/panel.h>

// QT_BEGIN_NAMESPACE

namespace rviz_teleop_plugin
{
    // class QtTeleopPanel : public QWidget
    class QtTeleopPanel : public rviz::Panel
    {
        Q_OBJECT

    public:
        QtTeleopPanel(QWidget *parent = 0);
        // ~QtTeleopPanel();

    public Q_SLOTS:
        void on_Up_Button_pressed();
        void on_Down_Button_pressed();
        void on_Left_Button_pressed();
        void on_Right_Button_pressed();
        void on_Stop_Button_pressed();
        void on_Send_Button_clicked(bool checked);
        void on_X_doubleSpinBox_valueChanged(double arg1);
        void on_Y_doubleSpinBox_valueChanged(double arg1);
        void on_Linear_doubleSpinBox_valueChanged(double arg1);
        void on_Angular_doubleSpinBox_valueChanged(double arg1);

    private:
        ros::NodeHandle nh_;
        ros::Publisher cmd_vel_pub_;

        QWidget *centralwidget;
        QLabel *X_label;
        QDoubleSpinBox *X_doubleSpinBox;
        QLabel *Y_label;
        QDoubleSpinBox *Y_doubleSpinBox;
        QPushButton *Send_Button;
        QPushButton *Up_Button;
        QPushButton *Stop_Button;
        QPushButton *Down_Button;
        QPushButton *Left_Button;
        QPushButton *Right_Button;
        QDoubleSpinBox *Linear_doubleSpinBox;
        QLabel *Linear_label;
        QLabel *Angular_label;
        QDoubleSpinBox *Angular_doubleSpinBox;
        QMenuBar *menubar;
        QMenu *menuteleop_panel;
        QStatusBar *statusbar;
    };

} // end namespace

// QT_END_NAMESPACE

#endif // QT_TELEOP_UI_H
$\endgroup$

1 Answer 1

-1
$\begingroup$

A plugin for a ros node (which rviz is) is usually not built using an isolated build. I suggest that you review the TeleopPanel rviz tutorial at this url (but ignore the part where it refers to the older rosmake command):

http://docs.ros.org/en/kinetic/api/rviz_plugin_tutorials/html/

The fully buildable code is available at:

https://github.com/ros-visualization/visualization_tutorials.git

It builds with catkin_make. Make sure you are using the correct branch e.g. noetic-devel.

$\endgroup$
1
  • $\begingroup$ Thank you so much. I solved it. thanku!!!! $\endgroup$ Commented Sep 13, 2023 at 0:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.