先学习一波
ROS CmakeLists.txt解读
先来看看CMakeList.txt
cmake_minimum_required(VERSION 2.8.3)
list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
# PACKAGE SETUP ########################################
project(status_panel)
find_package(catkin REQUIRED COMPONENTS std_msgs roscpp rviz)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS std_msgs
)
# QT ########################################
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
## This plugin includes Qt widgets, so we must include Qt.
## We'll use the version that rviz used so they are compatible.
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})
qt4_wrap_cpp(QT_MOC include/status_panel/status_panel.h)
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::Core Qt5::Widgets)
qt5_wrap_cpp(QT_MOC include/status_panel/status_panel.h)
endif()
add_definitions(-DQT_NO_KEYWORDS)
# FILES ########################################
include_directories(
${catkin_INCLUDE_DIRS}
include/
)
set(SOURCES src/status_panel.cpp src/status_logger.cpp ${QT_MOC})
# LIBRARY ########################################
add_library(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${catkin_LIBRARIES})
# INSTALL ########################################
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})
install(DIRECTORY icons/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/icons)
看不懂的先在上面学习一波,主要分为5个部分:PACKAGE SETUP (自身包的配置)、QT(QT环境的配置)、FILES(文件引入)、LIBRARY(生成库文件设置)、INSTALL(打包发布的配置)
再来看看status_panel.h
///
// Title : Status panel
// Project : ROSSTEP
// Created : 7/15/2015
// Author : Adam Allevato
// Platforms : Ubuntu 64-bit
// Copyright : Copyright© The University of Texas at Austin, 2014-2017. All rights reserved.
//
// All files within this directory are subject to the following, unless an alternative
// license is explicitly included within the text of each file.
//
// This software and documentation constitute an unpublished work
// and contain valuable trade secrets and proprietary information
// belonging to the University. None of the foregoing material may be
// copied or duplicated or disclosed without the express, written
// permission of the University. THE UNIVERSITY EXPRESSLY DISCLAIMS ANY
// AND ALL WARRANTIES CONCERNING THIS SOFTWARE AND DOCUMENTATION,
// INCLUDING ANY WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE, AND WARRANTIES OF PERFORMANCE, AND ANY WARRANTY
// THAT MIGHT OTHERWISE ARISE FROM COURSE OF DEALING OR USAGE OF TRADE.
// NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH RESPECT TO THE USE OF
// THE SOFTWARE OR DOCUMENTATION. Under no circumstances shall the
// University be liable for incidental, special, indirect, direct or
// consequential damages or loss of profits, interruption of business,
// or related expenses which may arise from use of software or documentation,
// including but not limited to those resulting from defects in software
// and/or documentation, or loss or inaccuracy of data of any kind.
//
///
#ifndef STATUS_PANEL_H
#define STATUS_PANEL_H
#ifndef Q_MOC_RUN
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <rviz/panel.h>
#endif
class QLineEdit;
class QLabel;
namespace status_panel {
class StatusPanel: public rviz::Panel
{
Q_OBJECT
public:
StatusPanel( QWidget* parent = 0 );
virtual void load( const rviz::Config& config );
virtual void save( rviz::Config config ) const;
void message_cb(std_msgs::String msg);
public Q_SLOTS:
void setMessage( const QString& message );
void setTopic();
protected:
/// One-line text editor for entering the ROS topic to monitor for messages.
QLineEdit* input_topic_editor;
/// Where to display the status messages.
QLabel* message_display;
/// The current name of the input topic.
QString input_topic;
/// The ROS publisher for the incoming messages.
ros::Subscriber subscriber;
/// The ROS node handle.
ros::NodeHandle nh;
};
} // end namespace
#endif
这里StatusPanel继承了rviz::Panel类,覆写了2个函数
virtual void load( const rviz::Config& config );
virtual void save( rviz::Config config ) const;
使用了2个Qt控件,用于接收和显示
/// One-line text editor for entering the ROS topic to monitor for messages.
QLineEdit* input_topic_editor;
/// Where to display the status messages.
QLabel* message_display;
其他没有什么了,具体实现的cpp如下
///
// Title : Status logger panel
// Project : ROSSTEP
// Created : 7/15/2015
// Author : Adam Allevato
// Platforms : Ubuntu 64-bit
// Copyright : Copyright© The University of Texas at Austin, 2014-2017. All rights reserved.
//
// All files within this directory are subject to the following, unless an alternative
// license is explicitly included within the text of each file.
//
// This software and documentation constitute an unpublished work
// and contain valuable trade secrets and proprietary information
// belonging to the University. None of the foregoing material may be
// copied or duplicated or disclosed without the express, written
// permission of the University. THE UNIVERSITY EXPRESSLY DISCLAIMS ANY
// AND ALL WARRANTIES CONCERNING THIS SOFTWARE AND DOCUMENTATION,
// INCLUDING ANY WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE, AND WARRANTIES OF PERFORMANCE, AND ANY WARRANTY
// THAT MIGHT OTHERWISE ARISE FROM COURSE OF DEALING OR USAGE OF TRADE.
// NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH RESPECT TO THE USE OF
// THE SOFTWARE OR DOCUMENTATION. Under no circumstances shall the
// University be liable for incidental, special, indirect, direct or
// consequential damages or loss of profits, interruption of business,
// or related expenses which may arise from use of software or documentation,
// including but not limited to those resulting from defects in software
// and/or documentation, or loss or inaccuracy of data of any kind.
//
#include "status_panel/status_panel.h"
#include <stdio.h>
#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>
#include <geometry_msgs/Twist.h>
namespace status_panel {
StatusPanel::StatusPanel( QWidget* parent ) :
rviz::Panel( parent ),
input_topic("/status")
{
// Next we lay out the "output topic" text entry field using a
// QLabel and a QLineEdit in a QHBoxLayout.
QHBoxLayout* topic_layout = new QHBoxLayout;
topic_layout->addWidget( new QLabel( "Status Topic:" ));
input_topic_editor = new QLineEdit;
topic_layout->addWidget( input_topic_editor );
message_display = new QLabel("");
message_display->setTextFormat(Qt::RichText);
message_display->setAlignment(Qt::AlignCenter);
// Lay out the topic field next to the control widrivzget.
QGridLayout* layout = new QGridLayout();
layout->setColumnStretch(1,100);
layout->addWidget( message_display, 0,0,1,4);
layout->addLayout( topic_layout, 0,4,1,1 );
setLayout( layout );
input_topic_editor->resize(150, input_topic_editor->height());
// Next we make signal/slot connections.
connect( input_topic_editor, SIGNAL( editingFinished() ), this, SLOT( setTopic() ));
input_topic_editor->setText( input_topic );
setTopic();
}
void StatusPanel::setTopic()
{
if(subscriber) {
subscriber.shutdown();
}
input_topic = input_topic_editor->text();
subscriber = nh.subscribe(std::string(input_topic.toStdString()), 100, &StatusPanel::message_cb, this);
Q_EMIT configChanged();
}
// Save all configuration data from this panel to the given
// Config object. It is important here that you call save()
// on the parent class so the class id and panel name get saved.
void StatusPanel::save( rviz::Config config ) const
{
rviz::Panel::save( config );
config.mapSetValue( "topic", input_topic );
}
// Load all configuration data for this panel from the given Config object.
void StatusPanel::load( const rviz::Config& config )
{
rviz::Panel::load( config );
QString topic;
if( config.mapGetString( "topic", &topic ))
{
input_topic_editor->setText( topic );
setTopic();
}
}
void StatusPanel::setMessage( const QString& msg) {
message_display->setText(QString("<span style='font-weight: bold; font-size: 14pt;'>") + msg + "</span>");
}
void StatusPanel::message_cb(std_msgs::String msg)
{
setMessage(QString(msg.data.c_str()));
}
} // end namespace
// Tell pluginlib about this class. Every class which should be
// loadable by pluginlib::ClassLoader must have these two lines
// compiled in its .cpp file, outside of any namespace scope.
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(status_panel::StatusPanel,rviz::Panel )
最后一步编写plugin_description.xml文件
<library path="libstatus_panel">
<class name="Status"
type="status_panel::StatusPanel"
base_class_type="rviz::Panel">
<description>
A simple panel to display info messages to the user.
</description>
</class>
</library>
我们可能还注意到了插件的icons图标,放一个png在路径/icons/classes/*.png即可。