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