Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Launch a new rviz plugin failed, Error:Failed to load library XXX.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.

Hi all. I'm trying to write a rviz plugin which is a panel and output the joint_state of my robot.I foolow the tutorial in Mastering ROS for Robotics Programmingchapter 6. After catkin_make successfully, I wanted to load it in rviz panel.But when I chose it, there was an erroe output like this:

The class required for this panel, 'joint_value_monitor/joint_value', could not be loaded.
Error:
Failed to load library /home/shantengfei/catkin_ws/devel/lib//libjoint_value_monitor.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/shantengfei/catkin_ws/devel/lib//libjoint_value_monitor.so: undefined symbol: _ZN19joint_value_monitor11joint_value4loadERKN4rviz6ConfigE)

this is my package tree:

    .
├── CMakeLists.txt
├── include
│   └── joint_value_monitor
│       └── joint_value.h
├── package.xml
├── plugin_description.xml
└── src
    └── joint_value.cpp

my package.xml:

<?xml version="1.0"?>
<!--package format="2"-->
<package format="2">
  <name>joint_value_monitor</name>
  <version>0.0.0</version>
  <description>The joint_value_monitor package</description>

  <maintainer email="shantengfei@todo.todo">shantengfei</maintainer>


  <license>TODO</license>

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rviz</build_depend>
  <build_depend>sensor_msgs</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</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>

  <exec_depend>roscpp</exec_depend>
  <exec_depend>rviz</exec_depend>
  <exec_depend>sensor_msgs</exec_depend>
  <exec_depend>std_msgs</exec_depend>

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

my plugin_description.xml:

<library path="lib/libjoint_value_monitor">
  <class name="joint_value_monitor/joint_value"
         type="joint_value_monitor::joint_value"
         base_class_type="rviz::Panel">
    <description>
      A panel widget allowing simple diff-drive style robot base control.
    </description>
  </class>
</library>

my CMakeList.txt

cmake_minimum_required(VERSION 2.8.3)
project(joint_value_monitor)

## Compile as C++11, supported in ROS Kinetic and newer
 add_compile_options(-std=c++11)
##原cmake文件
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rviz
  sensor_msgs
  std_msgs
)

#原cmake文件
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES joint_value_monitor
#  CATKIN_DEPENDS roscpp rviz sensor_msgs std_msgs
#  DEPENDS system_lib
)

#原cmake文件
include_directories(
  include ${catkin_INCLUDE_DIRS}
# include
  ${catkin_INCLUDE_DIRS}
)
link_directories(${catkin_LIBRARY_DIRS})

find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
include(${QT_USE_FILE})

add_definitions(-DQT_NO_KEYWORDS)
qt4_wrap_cpp(MOC_FILES
  include/joint_value_monitor/joint_value.h
)
set(SOURCE_FILES
  src/joint_value.cpp 
  ${MOC_FILES}
)
add_library(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} ${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(FILES 
  plugin_description.xml
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})

my joint_value.h

#ifndef JOINT_VALUE_H
#define JOINT_VALUE_H

#include <ros/ros.h>
#include <ros/console.h>

#include <rviz/panel.h> //plugin基类的头文件
#include <sensor_msgs/JointState.h>
#include <QLabel>
class QLineEdit;

namespace joint_value_monitor
{

class joint_value : public rviz::Panel
 {
  // 后边需要用到Qt的信号和槽,都是QObject的子类,所以需要声明Q_OBJECT宏
  Q_OBJECT

public:
  // 构造函数,在类中会用到QWidget的实例来实现GUI界面,这里先初始化为0即可
 joint_value(QWidget *parent = 0);

 // 重载rviz::Panel积累中的函数,用于保存、加载配置文件中的数据,在我们这个plugin
 // 中,数据就是topic的名称 
 //这里还是不知道怎么用
 virtual void load(const rviz::Config &config);
 virtual void save(rviz::Config config) const;

 //公共槽

 //内部槽
 protected Q_SLOTS:
 void update_joint_value();
protected:
  void chatterCB(const sensor_msgs::JointState& msg);
      //内部变量,各个关节的实际数据,使用QLabel来显示
QLabel *QLjoint1;
QLabel* QLjoint2;
QLabel *QLjoint3;
QLabel *QLjoint4;
QLabel *QLjoint5;

QLabel *QLjoint6;
QString joint1Value;
QString joint2Value;
QString joint3Value;
QString joint4Value;
QString joint5Value;
QString joint6Value;

 double joint1{0};
 double joint2{0};
 double joint3{0};
 double joint4{0};
 double joint5{0};
 double joint6{0};

 ros::Subscriber sub;
 ros::NodeHandle nh_;

};
} // end of namespace joint_value_monitor
#endif

and my joint_value.cpp

#include "joint_value_monitor/joint_value.h"
#include <stdio.h>
#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
//#include <sensor_msgs/JointState.h>
#include <QTimer>
//#include <ros/ros.h>
#include <QDebug>

namespace joint_value_monitor 
{
joint_value::joint_value(QWidget *parent): rviz::Panel(parent)
 {
     //创建joint_value的显示窗口 
      QVBoxLayout *topic_layout = new QVBoxLayout;
      //创建joint_1显示栏
      topic_layout->addWidget(new QLabel("joint1_value"));
      QLjoint1 = new QLabel;

  topic_layout->addWidget(QLjoint1);
  //创建joint_2显示栏
  topic_layout->addWidget(new QLabel("joint2_value"));
  QLjoint2 = new QLabel;
  topic_layout->addWidget(QLjoint2);
  //创建joint_3显示栏
  topic_layout->addWidget(new QLabel("joint3_value"));
  QLjoint3 = new QLabel;
  topic_layout->addWidget(QLjoint3);

  //创建joint_4显示栏
  topic_layout->addWidget(new QLabel("joint4_value"));
  QLjoint4 = new QLabel;
  topic_layout->addWidget(QLjoint4);
  //创建joint_5显示栏
  topic_layout->addWidget(new QLabel("joint5_value"));
  QLjoint5 = new QLabel;
  topic_layout->addWidget(QLjoint5);
  //创建joint_6显示栏
  topic_layout->addWidget(new QLabel("joint6_value"));
  QLjoint6 = new QLabel;

  topic_layout->addWidget(QLjoint6);

  //
  QHBoxLayout *layout = new QHBoxLayout;
  layout->addLayout(topic_layout);
  setLayout(layout);
  // 创建一个定时器,用来定时显示信息;

  QTimer *output_timer = new QTimer(this);
  //设置定时器回调函数,按周期调用update函数
  connect(output_timer, SIGNAL(timeout()), this, SLOT(update_joint_value()));
  output_timer->start(10);
 }
 void joint_value::chatterCB(const sensor_msgs::JointState& msg) 
 {

      joint1=msg.position[0];
  QLjoint1->setNum(joint1);

  joint2 = msg.position[1];
  QLjoint2->setNum(joint2);
        joint3 = msg.position[2];
          QLjoint3->setNum(joint3);

          joint4 = msg.position[3];
          QLjoint4->setNum(joint4);

          joint5 = msg.position[4];
          QLjoint5->setNum(joint5);

          joint6 = msg.position[5];
          QLjoint6->setNum(joint6);
  }

   void joint_value::update_joint_value()
   {
       if(ros::ok())
       {
         sub =
             nh_.subscribe("jakaUr/joint_states", 1000, &joint_value::chatterCB,this);
       }
       ros::spinOnce();
   }


} // end of namespace joint_value_monitor

// 声明此类是一个rviz的插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(joint_value_monitor::joint_value, rviz::Panel)

I have spent several days on it and I searched the solution in Q&A but I still didn't find the error because I didn't realized the CMakList very well. I guess where I didn't config well. So could someone please help me to find the error? Thanks!