Robotics StackExchange | Archived questions

Error: MultiLibraryClassLoader: Could not create class of type

I made a plugin which had been compiled. However, it doesn't work in the rviz. The error message is as followed:

The class required for this panel, 'pathmarkplugin/PathMarkPlugin', could not be loaded. Error: MultiLibraryClassLoader: Could not create class of type autolabor_plugin1::PathMarkPlugin

here is my rosbag file: CMakeLists.txt package.xml plugindescription.xml pathmarkplugin.h pathmark_plugin.cpp

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(path_mark_plugin)

add_compile_options(-std=c++11)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  path_server
  random_numbers
  rviz
  geometry_msgs
  std_msgs
  actionlib_msgs
  tf2
  tf2_ros
)

catkin_package(
  CATKIN_DEPENDS message_runtime
#  LIBRARIES path_mark_plugin
#  CATKIN_DEPENDS roscpp rviz
#  DEPENDS system_lib
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

link_directories(${catkin_LIBRARY_DIRS})


set(CMAKE_AUTOMOC ON)

if(rviz_QT_VERSION VERSION_LESS "5")
    message(STATUS "Using Qt4 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
    find_package(Qt4 ${rviz_QT_VERSION} EXACT REQUIRED QtCore QtGui)
    ## pull in all required include dirs, define QT_LIBRARIES, etc.
    include(${QT_USE_FILE})
else()
    message(STATUS "Using Qt5 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
    find_package(Qt5 ${rviz_QT_VERSION} EXACT REQUIRED Core Widgets)
    ## make target_link_libraries(${QT_LIBRARIES}) pull in all required dependencies
    set(QT_LIBRARIES Qt5::Widgets)
endif()

add_definitions(-DQT_NO_KEYWORDS)

add_library(path_mark_plugin src/path_mark_plugin.cpp include/path_mark_plugin/path_mark_plugin.h)
add_dependencies(path_mark_plugin ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(path_mark_plugin ${QT_LIBRARIES} ${catkin_LIBRARIES})

package.xml

<package>
  <name>path_mark_plugin</name>
  <version>0.0.0</version>
  <description>The path_mark_plugin package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="colin@todo.todo">colin</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <buildtool_depend>catkin</buildtool_depend>

  <build_depend>qtbase5-dev</build_depend>
  <build_depend>rviz</build_depend>
  <build_depend>path_server</build_depend>
  <build_depend>random_numbers</build_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>geometry_msgs</build_depend>
  <build_depend>actionlib_msgs</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>message_generation</build_depend>
  <build_depend>tf2</build_depend>
  <build_depend>tf2_ros</build_depend>

  <run_depend>libqt5-core</run_depend>
  <run_depend>libqt5-gui</run_depend>
  <run_depend>libqt5-widgets</run_depend>
  <run_depend>rviz</run_depend>
  <run_depend>path_server</run_depend>
  <run_depend>random_numbers</run_depend>
  <run_depend>roscpp</run_depend>
  <run_depend>std_msgs</run_depend>
  <run_depend>geometry_msgs</run_depend>
  <run_depend>message_runtime</run_depend>
  <run_depend>actionlib_msgs</run_depend>
  <run_depend>tf2</run_depend>
  <run_depend>tf2_ros</run_depend>

  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <rviz plugin="${prefix}/plugin_description.xml"/>
  </export>
</package>

plugin_description.xml

<library path="lib/libpath_rviz_plugin">
    <class name="path_mark_plugin/PathMarkPlugin"
           type="autolabor_plugin1::PathMarkPlugin"
           base_class_type="rviz::Panel">
        <description>
            A panel widget is used to record path.
        </description>
    </class>
</library>

pathmarkplugin.h

#ifndef PROJECT_PATH_MARK_PLUGIN_H
#define PROJECT_PATH_MARK_PLUGIN_H

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

#include <QHBoxLayout>
#include <QPushButton>
#include <QString>

#include <random_numbers/random_numbers.h>

#include <ros/package.h>

#include <string>
#include <fstream>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <tf/transform_listener.h>
#include <tf/transform_datatypes.h>

#include <path_server/SetPathName.h>
#include <std_srvs/Empty.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include <geometry_msgs/PoseStamped.h>

#include <tf/transform_datatypes.h>

#include <std_srvs/Empty.h>
#include <actionlib_msgs/GoalID.h>

#include <geometry_msgs/PoseStamped.h>


#include <cstdio>

#include <ros/console.h>

#include <fstream>
#include <sstream>

#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QDebug>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/qheaderview.h>

#include <string>



#include <tf2_ros/transform_listener.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>



#include <QPushButton>
#include <QTableWidget>
#include <QCheckBox>

#include <visualization_msgs/Marker.h>
#include <geometry_msgs/PoseArray.h>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/PoseStamped.h>
#include <std_msgs/String.h>
#include <actionlib_msgs/GoalStatus.h>
#include <actionlib_msgs/GoalStatusArray.h>
#include <tf/transform_datatypes.h>
namespace autolabor_plugin1 {
    class PathMarkPlugin : public rviz::Panel {
    Q_OBJECT
    public:
        PathMarkPlugin(QWidget *parent = 0);

        virtual void load(const rviz::Config &config);

        virtual void save(rviz::Config config) const;

    protected Q_SLOTS:

        void start_record_callback();

        void stop_record_callback();

        void start_task_callback();

        void stop_task_callback();

        void markPose(const geometry_msgs::PoseStamped::ConstPtr &pose);

    void initPoseTable();
    void writePose(const geometry_msgs::PoseStamped::ConstPtr& msg);

    void photo_point_callback(int row, int column);
/*  void deleteMark();*/

    protected:
        QTableWidget *poseArray_table_;
        QCheckBox *cycle_checkbox_;
        QTableWidgetItem*item_;
    geometry_msgs::PoseArray pose_array_;

    private:
        random_numbers::RandomNumberGenerator generator_;
        ros::NodeHandle nh_;
        ros::ServiceClient start_record_client_, stop_record_client_;
        ros::Publisher start_task_pub_, cancel_task_pub_,marker_pub_;

        ros::Subscriber point_sub_;

        QPushButton *start_record_button_;
        QPushButton *stop_record_button_;
        QPushButton *start_task_button_;
        QPushButton *stop_task_button_;

        void record_callback(const nav_msgs::Odometry::ConstPtr &msg);
        void record_data(double x, double y, double yaw);
    };
}


#endif //PROJECT_PATH_MARK_PLUGIN_H

pathmarkplugin.cpp

#include <tf/transform_datatypes.h>

#include <std_srvs/Empty.h>
#include <actionlib_msgs/GoalID.h>
#include <path_server/SetPathName.h>
#include <geometry_msgs/PoseStamped.h>
#include <path_mark_plugin/path_mark_plugin.h>

#include <cstdio>

#include <ros/console.h>

#include <fstream>
#include <sstream>

#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QDebug>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/qheaderview.h>

namespace autolabor_plugin1 {

    PathMarkPlugin::PathMarkPlugin(QWidget *parent) : Panel(parent) {
        auto *table_layout = new QVBoxLayout;
        poseArray_table_ = new QTableWidget;
        item_ = new QTableWidgetItem();
        initPoseTable();
        table_layout->addWidget(poseArray_table_);

        auto *button_layout = new QHBoxLayout;
        start_record_button_ = new QPushButton(tr("录制路径"), this);
        button_layout->addWidget(start_record_button_);
        stop_record_button_ = new QPushButton(tr("保存路径"), this);
        button_layout->addWidget(stop_record_button_);

        start_task_button_ = new QPushButton(tr("开始任务"), this);
        button_layout->addWidget(start_task_button_);
        stop_task_button_ = new QPushButton(tr("取消任务"), this);
        button_layout->addWidget(stop_task_button_);

        table_layout->addLayout(button_layout);
        setLayout(table_layout);

        stop_record_button_->setEnabled(false);

        connect(start_record_button_, SIGNAL(clicked()), this, SLOT(start_record_callback()));
        connect(stop_record_button_, SIGNAL(clicked()), this, SLOT(stop_record_callback()));
        connect(start_task_button_, SIGNAL(clicked()), this, SLOT(start_task_callback()));
        connect(stop_task_button_, SIGNAL(clicked()), this, SLOT(stop_task_callback()));

        connect(poseArray_table_,  SIGNAL(cellChanged(int,int)), this, 
SLOT(photo_point_callback(int,int)));

        start_record_client_ = nh_.serviceClient<path_server::SetPathName>("start_record_path");
        stop_record_client_ = nh_.serviceClient<std_srvs::Empty>("stop_record_path");

        start_task_pub_ = nh_.advertise<geometry_msgs::PoseStamped>("move_base_simple/goal", 1);
        cancel_task_pub_ = nh_.advertise<actionlib_msgs::GoalID>("move_base/cancel", 1);

        point_sub_ = nh_.subscribe("my_pose_topic", 10, &PathMarkPlugin::writePose, this );

    marker_pub_ = nh_.advertise<visualization_msgs::Marker>("visualization_marker", 1);
    }

    void PathMarkPlugin::load(const rviz::Config &config) {
        Panel::load(config);
    }

    void PathMarkPlugin::save(rviz::Config config) const {
        Panel::save(config);
    }

    void PathMarkPlugin::start_record_callback() {
        path_server::SetPathName msg;
        msg.request.path_name = "default_path";
        if (!start_record_client_.call(msg)) {
            ROS_ERROR_STREAM("记录路径发生错误,请重试!");
        } else {
            stop_record_button_->setEnabled(true);
            start_task_button_->setEnabled(false);
        }
    }

    void PathMarkPlugin::stop_record_callback() {
        std_srvs::Empty msg;
        if (!stop_record_client_.call(msg)) {
            ROS_ERROR_STREAM("保存路径发生错误,请重试!");
        } else {
            start_task_button_->setEnabled(true);
        }
    }

    void PathMarkPlugin::start_task_callback() {
        geometry_msgs::PoseStamped msg;
        msg.header.stamp = ros::Time::now();
        msg.header.frame_id = "map";
        msg.pose.orientation = tf::createQuaternionMsgFromYaw(generator_.uniformReal(-M_PI, M_PI));
        msg.pose.position.x = generator_.uniformReal(-100, 100);
        msg.pose.position.y = generator_.uniformReal(-100, 100);
        msg.pose.position.z = generator_.uniformReal(-100, 100);
        start_task_pub_.publish(msg);
    }

    void PathMarkPlugin::stop_task_callback() {
        actionlib_msgs::GoalID msg;
        msg.stamp = ros::Time::now();
        cancel_task_pub_.publish(msg);
    }
    void PathMarkPlugin::initPoseTable(){
        ROS_INFO("Initialize");
        poseArray_table_->clear();
        pose_array_.poses.clear();
//        deleteMark();
        poseArray_table_->setColumnCount(4);
        poseArray_table_->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        QStringList pose_header;
        pose_header << "设为拍照点"  << "x" << "y" << "yaw";
        poseArray_table_->setHorizontalHeaderLabels(pose_header);

    }
    void PathMarkPlugin::writePose(const geometry_msgs::PoseStamped::ConstPtr& msg) {
        int row = poseArray_table_->rowCount();
        poseArray_table_->insertRow(row);
        item_->setTextAlignment(Qt::AlignCenter);
        item_->setFont( poseArray_table_->font());
        item_->setCheckState(Qt::Unchecked);
        poseArray_table_->setItem(-1, 0, item_);

        double x = msg->pose.position.x;
        double y = msg->pose.position.y;
        double yaw = tf::getYaw(msg->pose.orientation);
        ROS_INFO("Received pose: x=%f, y=%f, yaw=%f", x, y, yaw);

        poseArray_table_->setItem(pose_array_.poses.size() - 1, 1,
                                    new QTableWidgetItem(QString::number(x, 'f', 2)));
        poseArray_table_->setItem(pose_array_.poses.size() - 1, 2,
                                    new QTableWidgetItem(QString::number(y, 'f', 2)));
        poseArray_table_->setItem(pose_array_.poses.size() - 1, 3,
                                    new QTableWidgetItem(
                                            QString::number(yaw * 180.0 / 3.14, 'f', 2)));

    }

    void PathMarkPlugin::photo_point_callback(int row, int column){
    if (column == 0) // 判断是否是第一列
    {
        QTableWidgetItem* item = poseArray_table_->item(row, column);
            if (item->checkState() == Qt::Checked)
            {
                ROS_INFO("Row %d is checked", row);
                double point_x = poseArray_table_->item(row,1)->text().toDouble();
                double point_y = poseArray_table_->item(row,2)->text().toDouble();
                double point_yaw = poseArray_table_->item(row,3)->text().toDouble();

                visualization_msgs::Marker number;
    //            number.ns = "navi_point_number";
                number.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
                number.pose.position.x = point_x;
                number.pose.position.y = point_y;
                number.pose.position.z = 0;
                number.scale.z = 1.0;
                number.color.r = 1.0f;
                number.color.g = 0.98f;
                number.color.b = 0.80f;
                number.color.a = 1.0;
                number.id = row;//fan hui shu liang
                number.text = std::to_string(row);
                marker_pub_.publish(number);

            }
            else
            {
                ROS_INFO("Row %d is unchecked", row);
            }
    }
    else
    {
        ROS_INFO("Row %d is changed", row);
    }}

}

#include <pluginlib/class_list_macros.h>

PLUGINLIB_EXPORT_CLASS(autolabor_plugin1::PathMarkPlugin, rviz::Panel)

Asked by yolic on 2023-05-20 23:14:56 UTC

Comments

Answers