Could not find library corresponding to plugin
Hi all. I'm trying to learn how to write rviz plugins from the book Mastering Ros for robotics.But there is a problem I cannot solve. I created the package and then created the teleop_pad.h
file here:
#ifndef TELEOP_PAD_H
#define TELEOP_PAD_H
#include <ros/ros.h>
#include <ros/console.h>
#include <rviz/panel.h>
class QLineEdit;
namespace rviz_teleop_commander
{
//所有的plugin都必须是rviz::panel的子类
class TeleopPanel: public rviz::Panel
{
//后面需要用到Qt的信号和槽,都是Qobject的子类,所以需要声明Q_OBJECT宏
Q_OBJECT
public:
//构造函数。在类中会用到QWidget的实力来实现GUI界面,这里先初始化为0
TeleopPanel(QWidget* parent =0 );
//重载rviz::Panel基类中的函数,用于保存、加载配置文件中的数据,在我们这个plugin
// 中,数据就是topic的名称
virtual void load(const rviz::Config& config);
virtual void save(rviz::Config config) const;
//公共槽
public Q_SLOTS:
// 当用户输入topic的命名并按下回车后,回调用此槽来创建一个相应名称的topic publisher
void setTopic (const QString& topic)
//内部槽
protected Q_SLOTS:
void sendvel(); // 发布当前的速度值
void update_Linear_Velocity(); // 根据用户的输入更新线速度值
void update_Angular_Velocity(); // 根据用户的输入更新角速度值
void updateTopic(); // 根据用户的输入更新topic name
//内部变量
protected:
//topic names输入框
QLineEdit* output_topic_editor_;
QString output_topic_;
//线速度输入框
QLineEdit* output_topic_editor_1;
QString output_topic_1;
//角速度输入框
QLineEdit* output_topic_editor_2;
QString output_topic_2;
//// ROS的publisher,用来发布速度topic
ros::Publisher velocity_publisher_;
//ROS node handle
ros::NodeHandle nh_;
//当前保存的线速度和角速度
float linear_velocity_;
float angular_velocity_;
};
} //end namespace rviz_plugin_tutorial
#endif //TELEOP_PANEL_H
the teleop_pad.cpp file
#include <studio.h>
#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>
#include <geometry_msgs/Twist.h>
#include <QDebug>
#include "teleop_pad.h"
namespace rviz_teleop_commander {
//构造函数,初始化变量
TeleopPanel::TeleopPanel(QWidget *parent)
: rviz::Panel(parent), linear_velocity_(0), angular_velocity_(0) {
// 创建一个输入topic命名的窗口
QVBoxLayout *topic_layout = new QVBoxLayout;
topic_layout->addwidget(new QLabel("Teleop Topic"));
output_topic_editor_ = new QLineEdit;
topic_layout->addwidget(output_topic_editor_);
// 创建一个输入线速度的窗口
topic_layout->addwidget(new QLabel("Linear Velocity"));
output_topic_editor_1 = new QLineEdit;
topic_layout->addwidget(output_topic_editor_1);
//创建一个输入角速度窗口
topic_layout->addwidget(new QLabel("Angular Velocity"));
output_topic_editor_2 = new QLineEdit;
topic_layout->addwidget(output_topic_editor_2);
QHBoxLayout *layout = new QHBoxLayout;
layout->addLayout(topic_layout);
setLayout(layout);
//创建定时器,发布消息
QTimer *output_timer = new QTimer(this);
//设置信号与槽连接
connect(output_topic_editor_, SIGNAL(editingFinished()), this,
SLOT(updateTopic())); //输入topic命名,回车后,调用updateTopic()
connect(
output_topic_editor_1, SIGNAL(editingFinished()), this,
SLOT(
update_Linear_velocity())); //输入线速度值,回车后,调用update_Linear_Velocity()
connect(
output_topic_editor_2, SIGNAL(editingFinished()), this,
SLOT(
update_Angular_velocity())); //输入角速度值,回车后,调用update_Angular_Velocity()
//设置定时器的回调函数。按周期调用sendvle
connect(output_timer, SIGNAL(timerout()), this, SLOT(sendVel()));
output_timer->start(100);
}
//更新线速度
void TeleopPanel::update_Linear_velocity() {
//获取输入框内的数据
QString temp_string = output_topic_editor_1->text();
//将字符串转换为浮点数
float lin = temp_string.toFloat();
//保存当前输入值
linear_velocity_ = lin;
}
void TeleopPanel::update_Angular_velocity {
QString temp_string = output_topic_editor_2->text();
float ang = temp_string.toFloat();
angular_velocity_ = ang;
}
//更新topic命名
void TeleopPanel::setTopic(const QString &new_topic) {
//检查topic是否改变
if (new_topic != output_topic_) {
output_topic_ = new_topic;
//如果命名空,不发布任何信息
if (output_topic_ == "") {
velocity_publisher_.shutdown();
}
//否则初始化publisher
else {
velocity_publisher_ =
nh.advertise<geometry_msgs::Twist>(output_topic_.toStdstring(), 1);
}
Q_EMIT configChanged();
}
}
//发布消息
void TeleopPanel::sendVel() {
if (ros::ok() && velocity_publisher_) {
geometry_msgs::Twist msg;
msg.linear.x = linear_velocity_;
msg.linear.y = 0;
msg.linear.z = 0;
msg.angular.x = 0;
msg.angular.y = 0;
msg.angular.z = angular_velocity_;
velocity_publisher_.publish(msg);
}
}
//重载基类功能
void TeleopPanel::save(rviz::Config config) const {
rviz::Panel::save(config);
config.mapSetvalue("Topic", output_topic_);
}
// 重载父类的功能,加载配置数据
void TeleopPanel::load(const rviz::Config &config) {
rviz::Panel::load(config);
QString topic;
if (config.mapGetString("Topic", &topic)) {
output_topic_editor_->setText(topic);
updateTopic();
}
}
} // end namespace rviz_plugin_tutorials
// 声明此类是一个rviz的插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_telop_commander::TeleopPanel,rviz::Panel)
//tutorial
the package.xml:
<?xml version="1.0"?>
<package format="2">
<name>rviz_teleop_commander</name>
<version>0.0.0</version>
<description>The rviz_teleop_commander package</description>
<maintainer email="shantengfei@todo.todo">shantengfei</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend ...
There are quite some inconsistencies in the various file you show:
rviz_telop_commander/Teleop
vsrviz_teleop_commander/TeleopPanel
is one.I would suggest you check all of them.
Thanks gvdhoorn.I have changed allteloptoteleop,but still doesn't work but it still doesn't work. I checked several times,but still have no idea where the error is.
gvdhoorn,I rebuilt the whole example from the beginning and now it works.Maybe I still didn't find the inconsistencies in the first version.Thanks!