一、创建工作空间
选择【New Project】创建项目。
。 选择【其他项目】,选择【ROS Workspace】,点击【Choose...】按钮
写入【Name:】名称,选择【Workspace Path:】工作空间路径,点击【下一步】按钮。
点击【完成】按钮,完成工作空间的创建。
二、添加自定义消息
1.创建消息包以及文件
在工作空间src下创建存放消息的包,右击【src】,选择【添加新文件...】。
选择【ROS】,选择【Package】,点击【Choose...】按钮。
写入【Name:】名称,写入【Catkin:】依赖,消息依赖于 std_msgs和message_generation。
点击【完成】按钮。
找到创建的消息包【plugin_msg】文件夹,在此新建文件夹,名称为【msg】,目录结构如下:
右击【msg】,选择【添加新文件...】。
选择【ROS】,选中【Basic msg file】,点击【Choose...】按钮。
写入【名称:】,点击【下一步】按钮。
点击【完成】按钮。
2.修改消息内容
修改ProgressBarMsg.msg内容:
std_msgs/Header header
string context
uint32 value
std_msgs/Header header:
数据类型的标准元数据,通常用于在特定坐标系中传达时间戳数据。
包含字段
uint32 seq //表示序列 ID
time stamp //表示时间戳
string frame_id //和frame有关,序列id
3.修改package.xml内容
添加编译时的依赖
<build_depend>message_generation</build_depend>
添加执行时的依赖
<exec_depend>message_runtime</exec_depend>
<exec_depend>message_generation</exec_depend>
<?xml version="1.0"?>
<package format="2">
<name>plugin_msg</name>
<version>0.1.0</version>
<description>The plugin_msg package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
<maintainer email="[email protected]">root</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>Apache 2.0</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/plugin_msg</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="[email protected]">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<build_depend>message_generation</build_depend>
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<exec_depend>message_runtime</exec_depend>
<exec_depend>message_generation</exec_depend>
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
4.修改CMakeLists.txt内容
catkin_package中添加依赖
CATKIN_DEPENDS message_runtime
#指定项目所需的最低 CMake 版本。
cmake_minimum_required(VERSION 3.0.2)
#定义项目的名称
project(plugin_msg)
#查找并导入外部依赖库。
find_package(catkin REQUIRED COMPONENTS
std_msgs
message_generation #增加message编译时依赖模块到(message_generation)
)
#增加自定义的msg文件
add_message_files(
FILES
ProgressBarMsg.msg
)
#生成msg需要依赖的消息以及服务
generate_messages(
DEPENDENCIES
std_msgs
)
#这用于指定包的依赖关系,由依赖于这个包的其他软件包使用。
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES custom_msg
CATKIN_DEPENDS message_runtime #增加message运行时依赖模块message_runtime
# DEPENDS system_lib
)
三、添加自定义插件(rviz::Display类型)
1.创建插件包以及文件
右击【src】,选择【添加新文件...】。
选择【ROS】,选择【Package】,点击【Choose..】按钮。
写入【Name:】包名称,写入【Catkin:】依赖,点击【下一步】按钮。
点击【完成】按钮。
右击【progressBar_display】包下的【src】 ,选择【添加新文件...】。
选择【C++】,选择【C++ Class】,点击【Choose...】按钮。
写入【Class name:】类名称,点击【下一步】按钮。
点击【完成】按钮。
同上述相同步骤添加C++类ProgressBar_Visual。
创建完成之后,手动将progressbar_visual.h和progressbar_display.h两个头文件移动到功能包下的include文件夹下的progressBar_display文件夹下。
此时目录结构如下:
2.添加类代码
progressbar_visual.h
#ifndef PROGRESSBAR_VISUAL_H
#define PROGRESSBAR_VISUAL_H
#include <OGRE/OgreVector3.h>
#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreBillboard.h>
#include <OGRE/OgreBillboardSet.h>
#include <rviz/properties/string_property.h>
#include <rviz/ogre_helpers/movable_text.h>
#include <rviz/ogre_helpers/shape.h>
#include <rviz/display_context.h>
#include "plugin_msg/ProgressBarMsg.h"
namespace Ogre
{
class Vector3;
class Quaternion;
class BillboardSet;
class SceneManager;
class SceneNode;
class ColourValue;
}
namespace rviz
{
class MovableText;
class Shape;
class IntProperty;
}
namespace progressBar_plugin {
class ProgressBar_Visual
{
public:
ProgressBar_Visual(Ogre::SceneManager* SceneManager, Ogre::SceneNode* ParentNode);
virtual ~ProgressBar_Visual();
void setMessage(const plugin_msg::ProgressBarMsg::ConstPtr& Msg);
void createProgressBarShape(double PowerRatio);
void setFramePosition(const Ogre::Vector3& Position);
void setFrameOrientation(const Ogre::Quaternion& Orientation);
void setTextColor(const Ogre::ColourValue& Color);
void setTextColor(float Red, float Green, float Blue, float Alpha);
void setBackgroundColor(float Red, float Green, float Blue, float Alpha);
void setProgressBarColor(float Red, float Green, float Blue, float Alpha);
void setHeaderColor(float Red, float Green, float Blue, float Alpha);
void setTextSize(float Size);
void setGraphSize(float Size);
void setOffsets(const Ogre::Vector3& Offsets);
void setOrientation(const Ogre::Vector3& Orientation);
private:
float size_{ 1.0 };
std::shared_ptr<Ogre::Vector3> base_pose_{ nullptr };
std::shared_ptr<Ogre::Vector3> offsets_{ nullptr };
std::shared_ptr<Ogre::Vector3> orientation_{ nullptr };
// the object implementing the actual text
std::shared_ptr<rviz::MovableText> progressBar_info_{ nullptr };
// the object of ProgressBar shape
std::vector<std::shared_ptr<rviz::Shape>> ProgressBar_shape_;
// a SceneNode whose pose is set to match the coordinate frame of the plugin_msg::ProgressBarMsg message header
Ogre::SceneNode* frame_node_{ nullptr };
// the SceneManager, kept here only so the destructor can ask it to destroy the `frame_node_`
Ogre::SceneManager* scene_manager_{ nullptr };
Ogre::ColourValue background_color;
Ogre::ColourValue ProgressBar_color;
Ogre::ColourValue header_color;
};
}
#endif // PROGRESSBAR_VISUAL_H
progressbar_visual.cpp
#include "progressBar_display/progressbar_visual.h"
namespace progressBar_plugin
{
ProgressBar_Visual::ProgressBar_Visual(Ogre::SceneManager *SceneManager, Ogre::SceneNode *ParentNode)
{
scene_manager_ = SceneManager;
frame_node_ = ParentNode->createChildSceneNode();
progressBar_info_.reset(new rviz::MovableText("?\%"));
progressBar_info_->setCharacterHeight(0.5);
frame_node_->attachObject(progressBar_info_.get());
//create shape of ProgressBar
base_pose_ = std::make_shared<Ogre::Vector3>(Ogre::Vector3::ZERO);
offsets_ = std::make_shared<Ogre::Vector3>(Ogre::Vector3::ZERO);
orientation_ = std::make_shared<Ogre::Vector3>(Ogre::Vector3(float(0.0), float(90.0), float(0.0)));
background_color = Ogre::ColourValue(1, 0.5, 0.5, 0.5);
ProgressBar_color = Ogre::ColourValue(1, 1, 0.5, 1);
header_color = Ogre::ColourValue(0.5, 1, 1, 1);
createProgressBarShape(1.0);
}
ProgressBar_Visual::~ProgressBar_Visual()
{
scene_manager_->destroySceneNode(frame_node_);
}
void ProgressBar_Visual::setMessage(const plugin_msg::ProgressBarMsg::ConstPtr &Msg)
{
int h = 0;
int v = 0;
progressBar_info_->setTextAlignment((rviz::MovableText::HorizontalAlignment)h, (rviz::MovableText::VerticalAlignment)v);
rviz::StringProperty text("text", (std::to_string(Msg->value) + "\%").c_str());
progressBar_info_->setCaption(text.getStdString());
progressBar_info_->setLineSpacing(0.5);
}
void ProgressBar_Visual::createProgressBarShape(double PowerRatio)
{
for (auto& it : ProgressBar_shape_)
{
it.reset();
}
ProgressBar_shape_.clear();
ProgressBar_shape_.resize(3);
Ogre::Matrix3 mat;
mat.FromEulerAnglesXYZ(Ogre::Degree(orientation_->x), Ogre::Degree(orientation_->y), Ogre::Degree(orientation_->z));
Ogre::Quaternion orientation;
orientation.FromRotationMatrix(mat);
//background
ProgressBar_shape_[0].reset(new rviz::Shape(rviz::Shape::Cylinder,scene_manager_));
ProgressBar_shape_[0]->setScale(Ogre::Vector3(float(0.5 * size_),float(3 * size_),float(0.5 * size_)));
ProgressBar_shape_[0]->setPosition(Ogre::Vector3(base_pose_->x + offsets_->x,
base_pose_->y + offsets_->y,
base_pose_->z + offsets_->z));
ProgressBar_shape_[0]->setOrientation(orientation);
ProgressBar_shape_[0]->setColor(background_color);
//ProgressBar
float length = 2.8 * size_;
//ProgressBar center pos
Ogre::Vector3 ProgressBar_vec3(0.0,- float(0.5 * length *(1 - PowerRatio)),0.0);
Ogre::Vector3 ProgressBar_pos = orientation * ProgressBar_vec3;
ProgressBar_shape_[1].reset(new rviz::Shape(rviz::Shape::Cylinder,scene_manager_));
ProgressBar_shape_[1]->setScale(Ogre::Vector3(float(0.3 * size_),length * PowerRatio,float(0.3 * size_)));
ProgressBar_shape_[1]->setPosition(Ogre::Vector3(base_pose_->x + ProgressBar_pos.x + offsets_->x,
base_pose_->y + ProgressBar_pos.y + offsets_->y,
base_pose_->z + ProgressBar_pos.z + offsets_->z));
ProgressBar_shape_[1]->setOrientation(orientation);
ProgressBar_shape_[1]->setColor(ProgressBar_color);
//header
float head_length = 0.1 * size_ * 0.5;
//header center pos
Ogre::Vector3 head_vec3(0.0,- float(0.5 * length *(1 - 2 * PowerRatio)) + head_length * 0.5,0.0);
Ogre::Vector3 head_pos = orientation * head_vec3;
ProgressBar_shape_[2].reset(new rviz::Shape(rviz::Shape::Cube,scene_manager_));
ProgressBar_shape_[2]->setScale(Ogre::Vector3(float(0.3 * size_),head_length,float(0.3 * size_)));
ProgressBar_shape_[2]->setPosition(Ogre::Vector3(base_pose_->x + head_pos.x + offsets_->x,
base_pose_->y + head_pos.y + offsets_->y,
base_pose_->z + head_pos.z + offsets_->z));
ProgressBar_shape_[2]->setOrientation(orientation);
ProgressBar_shape_[2]->setColor(header_color);
}
void ProgressBar_Visual::setFramePosition(const Ogre::Vector3 &Position)
{
*base_pose_ = Position;
frame_node_->setPosition(Position);
}
void ProgressBar_Visual::setFrameOrientation(const Ogre::Quaternion &Orientation)
{
frame_node_->setOrientation(Orientation);
}
void ProgressBar_Visual::setTextColor(const Ogre::ColourValue &Color)
{
progressBar_info_->setColor(Color);
}
void ProgressBar_Visual::setTextColor(float Red, float Green, float Blue, float Alpha)
{
setTextColor(Ogre::ColourValue(Red, Green, Blue, Alpha));
}
void ProgressBar_Visual::setBackgroundColor(float Red, float Green, float Blue, float Alpha)
{
background_color = Ogre::ColourValue(Red, Green, Blue, Alpha);
}
void ProgressBar_Visual::setProgressBarColor(float Red, float Green, float Blue, float Alpha)
{
ProgressBar_color = Ogre::ColourValue(Red, Green, Blue, Alpha);
}
void ProgressBar_Visual::setHeaderColor(float Red, float Green, float Blue, float Alpha)
{
header_color = Ogre::ColourValue(Red, Green, Blue, Alpha);
}
void ProgressBar_Visual::setTextSize(float Size)
{
progressBar_info_->setCharacterHeight(Size);
}
void ProgressBar_Visual::setGraphSize(float Size)
{
size_ = Size;
}
void ProgressBar_Visual::setOffsets(const Ogre::Vector3 &Offsets)
{
*offsets_ = Offsets;
progressBar_info_->setLocalTranslation(Ogre::Vector3(-offsets_->y, offsets_->z, -offsets_->x));
}
void ProgressBar_Visual::setOrientation(const Ogre::Vector3 &Orientation)
{
*orientation_ = Orientation;
}
}
progressbar_display.h
#ifndef PROGRESSBAR_DISPLAY_H
#define PROGRESSBAR_DISPLAY_H
#ifndef Q_MOC_RUN
#include <boost/circular_buffer.hpp>
#include <rviz/message_filter_display.h>
#include <rviz/panel_dock_widget.h>
#include "plugin_msg/ProgressBarMsg.h"
#endif
namespace Ogre
{
class SceneNode;
class ColourValue;
}
namespace rviz
{
class ColorProperty;
class FloatProperty;
class IntProperty;
class VectorProperty;
class BoolProperty;
class StringProperty;
}
namespace progressBar_plugin {
class ProgressBar_Visual;
class ProgressBar_Display: public rviz::MessageFilterDisplay<plugin_msg::ProgressBarMsg>
{
Q_OBJECT
public:
ProgressBar_Display();
virtual ~ProgressBar_Display();
protected:
virtual void onInitialize();
// a helper function to clear this display back to the initial state
virtual void reset();
private Q_SLOTS:
// these Qt slots get connected to signals indicating changes in the user-editable properties
void updateTextColorAndAlpha();
void updateBackgroundrColor();
void updateProgressBarColor();
void updateHeaderColor();
void updateHistoryLength();
void updateTextSize();
void updateGraphSize();
void updateOffsets();
void updateOrientation();
private:
// function to handle an incoming ROS message
void processMessage(const plugin_msg::ProgressBarMsg::ConstPtr& Msg);
private:
// storage for the list of visuals. It is a circular buffer,
// where data gets popped from the front (oldest) and pushed to the back (newest)
boost::circular_buffer<std::shared_ptr<ProgressBar_Visual>> visuals_;
// user-editable property variables
rviz::ColorProperty* text_color_property_;
rviz::FloatProperty* text_alpha_property_;
rviz::ColorProperty* background_color_property_;
rviz::ColorProperty* progressBar_color_property_;
rviz::ColorProperty* header_color_property_;
rviz::IntProperty* history_length_property_;
rviz::FloatProperty* text_size_property_;
rviz::FloatProperty* graph_size_property_;
rviz::VectorProperty* offsets_property_;
rviz::VectorProperty* orientation_property_;
};
}
#endif // PROGRESSBAR_DISPLAY_H
progressbar_display.cpp
#include "progressBar_display/progressbar_display.h"
#include "progressBar_display/progressbar_visual.h"
#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <rviz/window_manager_interface.h>
#include <rviz/visualization_manager.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/float_property.h>
#include <rviz/properties/int_property.h>
#include <rviz/properties/vector_property.h>
#include <rviz/properties/bool_property.h>
#include <rviz/properties/string_property.h>
#include <pluginlib/class_list_macros.h>
namespace progressBar_plugin
{
ProgressBar_Display::ProgressBar_Display()
{
text_color_property_ = new rviz::ColorProperty("Text Color", QColor(138, 226, 52),
"Color of progressBar info text.",
this, SLOT(updateTextColorAndAlpha()));
text_alpha_property_ = new rviz::FloatProperty("Text Alpha", 1.0,
"0 is fully transparent, 1.0 is fully opaque.",
this, SLOT(updateTextColorAndAlpha()));
text_size_property_ = new rviz::FloatProperty("Text Size", 0.5,
"Character size of progressBar info text.",
this, SLOT(updateTextSize()));
background_color_property_ = new rviz::ColorProperty("Background Color", QColor(255,128,128),
"Color of progressBar background.",
this, SLOT(updateBackgroundrColor()));
progressBar_color_property_ = new rviz::ColorProperty("ProgressBar Color", QColor(255,255,128),
"Color of progressBar.",
this, SLOT(updateProgressBarColor()));
header_color_property_ = new rviz::ColorProperty("Header Color", QColor(128,255,255),
"Color of progressBar header.",
this, SLOT(updateHeaderColor()));
graph_size_property_ = new rviz::FloatProperty("Graph Size", 1.0,
"Character size of progressBar graph.",
this, SLOT(updateGraphSize()));
history_length_property_ = new rviz::IntProperty("History Length", 1,
"Number of prior measurements to display.",
this, SLOT(updateHistoryLength()));
history_length_property_->setMin(1);
history_length_property_->setMax(100000);
offsets_property_ = new rviz::VectorProperty("Offsets", Ogre::Vector3::ZERO,
"Offsets to frame",
this, SLOT(updateOffsets()));
orientation_property_ = new rviz::VectorProperty("Orientation", Ogre::Vector3(float(0.0), float(90.0), float(0.0)),
"Orientation of progressBar symbol",
this, SLOT(updateOrientation()));
}
ProgressBar_Display::~ProgressBar_Display()
{
}
// after the top-level rviz::Display::initialize() does its own setup,
// it calls the subclass's onInitialize() function
// this is where all the workings of the class is instantiated
// make sure to also call the immediate super-class's onInitialize() function,
// since it does important stuff setting up the message filter
//
// note that "MFDClass" is a typedef of `MessageFilterDisplay<message type>`,
// to save typing that long templated class name every time the superclass needs to be refered
void ProgressBar_Display::onInitialize()
{
MFDClass::onInitialize();
updateTextColorAndAlpha();
updateHistoryLength();
updateTextSize();
updateGraphSize();
updateOffsets();
updateOrientation();
}
// clear the visuals by deleting their objects
void ProgressBar_Display::reset()
{
MFDClass::reset();
visuals_.clear();
}
// set the current color and alpha values for each visual
void ProgressBar_Display::updateTextColorAndAlpha()
{
float alpha = text_alpha_property_->getFloat();
Ogre::ColourValue color = text_color_property_->getOgreColor();
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setTextColor(color.r, color.g, color.b, alpha);
}
}
void ProgressBar_Display::updateBackgroundrColor()
{
Ogre::ColourValue color = background_color_property_->getOgreColor();
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setBackgroundColor(color.r, color.g, color.b, 0.5);
}
}
void ProgressBar_Display::updateProgressBarColor()
{
Ogre::ColourValue color = progressBar_color_property_->getOgreColor();
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setProgressBarColor(color.r, color.g, color.b, 1);
}
}
void ProgressBar_Display::updateHeaderColor()
{
Ogre::ColourValue color = header_color_property_->getOgreColor();
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setHeaderColor(color.r, color.g, color.b, 1);
}
}
// set the number of past visuals to show
void ProgressBar_Display::updateHistoryLength()
{
visuals_.rset_capacity(history_length_property_->getInt());
}
void ProgressBar_Display::updateTextSize()
{
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setTextSize(text_size_property_->getFloat());
}
}
void ProgressBar_Display::updateGraphSize()
{
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setGraphSize(graph_size_property_->getFloat());
}
}
void ProgressBar_Display::updateOffsets()
{
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setOffsets(offsets_property_->getVector());
}
}
void ProgressBar_Display::updateOrientation()
{
for (size_t i = 0; i < visuals_.size(); ++i)
{
visuals_[i]->setOrientation(orientation_property_->getVector());
}
}
void ProgressBar_Display::processMessage(const plugin_msg::ProgressBarMsg::ConstPtr& Msg)
{
// call the rviz::FrameManager to get the transform from the fixed frame to the frame in the header of this progressBar message
// if it fails, do nothing and return
Ogre::Quaternion orientation;
Ogre::Vector3 position;
if (!context_->getFrameManager()->getTransform(Msg->header.frame_id,Msg->header.stamp, position, orientation))
{
ROS_DEBUG("error transforming from frame '%s' to frame '%s'",
Msg->header.frame_id.c_str(), qPrintable(fixed_frame_));
return;
}
// keeping a circular buffer of visual pointers
// this gets the next one, or creates and stores it if the buffer is not full
std::shared_ptr<ProgressBar_Visual> visual;
if (visuals_.full())
{
visual = visuals_.front();
}
else
{
visual.reset(new ProgressBar_Visual(context_->getSceneManager(), scene_node_));
}
// set or update the contents of the chosen visual
float alpha = text_alpha_property_->getFloat();
Ogre::ColourValue color = text_color_property_->getOgreColor();
visual->setTextColor(color.r, color.g, color.b, alpha);
color = background_color_property_->getOgreColor();
visual->setBackgroundColor(color.r, color.g, color.b, 0.5);
color = progressBar_color_property_->getOgreColor();
visual->setProgressBarColor(color.r, color.g, color.b, 1);
color = header_color_property_->getOgreColor();
visual->setHeaderColor(color.r, color.g, color.b, 1);
visual->createProgressBarShape(Msg->value / 100.0);
visual->setMessage(Msg);
visual->setFramePosition(position);
visual->setFrameOrientation(orientation);
// send it to the end of the circular buffer
visuals_.push_back(visual);
}
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(progressBar_plugin::ProgressBar_Display, rviz::Display)
}
注册插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(progressBar_plugin::ProgressBar_Display, rviz::Display)
3.添加plugin_description.xml文件
内容如下:
<library path="lib/libprogressBar_display">
<class name="progressBar_plugin/ProgressBar"
type="progressBar_plugin::ProgressBar_Display"
base_class_type="rviz::Display">
<description>
display progressBar information
</description>
</class>
</library>
plugin_description.xml文件各字段含义 :
path:动态链接库路径
name:插件名称
type:插件的完整类型
base_class_type:插件完整类型父类
description:功能描述
4.修改package.xml文件
修改内容如下:
<?xml version="1.0"?>
<package format="2">
<name>progressBar_display</name>
<version>0.1.0</version>
<description>The progressBar_display package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
<maintainer email="[email protected]">root</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>Apache 2.0</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/progressBar_display</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="[email protected]">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>qtbase5-dev</build_depend>
<build_depend>rviz</build_depend>
<exec_depend>libqt5-core</exec_depend>
<exec_depend>libqt5-gui</exec_depend>
<exec_depend>libqt5-widgets</exec_depend>
<exec_depend>rviz</exec_depend>
<build_depend>plugin_msg</build_depend>
<build_export_depend>plugin_msg</build_export_depend>
<exec_depend>plugin_msg</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
<rviz plugin="${prefix}/plugin_description.xml"/>
</export>
</package>
5.修改CMakeLists.txt文件
修改内容如下:
#指定项目所需的最低 CMake 版本。
cmake_minimum_required(VERSION 3.0.2)
#定义项目的名称
project(progressBar_display)
#查找并导入外部依赖库
find_package(catkin REQUIRED COMPONENTS
rviz
plugin_msg
)
## This plugin includes Qt widgets, so we must include Qt like so:
find_package(Qt5 REQUIRED Core Widgets)
set(QT_LIBRARIES Qt5::Widgets)
#添加头文件搜索路径,编译器使用这些目录来查找头文件,第一个参数“include”表示包中的include/目录也是路径的一部分。
include_directories(
include
${catkin_INCLUDE_DIRS}
)
## I prefer the Qt signals and slots to avoid defining "emit", "slots",
## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here.
add_definitions(-DQT_NO_KEYWORDS)
# 设置相关变量
# 自动添加当前目录至路径中
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# 自动生成moc文件,自动运行moc
set(CMAKE_AUTOMOC ON)
# 自动运行uic
#set(CMAKE_AUTOUIC ON)
# 自动运行rcc
set(CMAKE_AUTORCC ON)
#用来匹配指定路径下所有符合通配符条件的文件的命令。具体来说,GLOB_RECURSE 是递归查找目录下的所有文件,file() 命令则可以用来获取文件列表。
file(GLOB_RECURSE SOURCE_CPP
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
)
file(GLOB_RECURSE SOURCE_H
"${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}/*.h"
)
#生成库
add_library(${PROJECT_NAME}
${SOURCE_H}
${SOURCE_CPP}
)
#在定义消息类型时,编译的库依赖这些动态生成的代码
add_dependencies(${PROJECT_NAME} plugin_msg_generate_messages_cpp)
#设置链接库,需要用到系统或者第三方库函数时候进行配置,第一个参数是可执行文件名,后面依次写入需要链接的库
#设置生成库依赖的库
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
${QT_LIBRARIES}
)
四、添加自定义插件(rviz::Panel类型)
1.创建插件包以及文件
创建名为progressBar_panel的插件包,以及名为ProgressBar_Panel的c++类,步骤同上。
创建带有UI界面的类步骤如下:
选择【Qt】,选择【Qt设计师界面类】,点击【Choose...】按钮。
选择【Widget】,点击【下一步】按钮
输入【类名:】,点击【下一步】按钮。
点击【完成】按钮。
同上将.h文件移到include下的progressBar_panel文件夹下。在src和include的同级目录下创建ui文件夹,将.ui文件移到ui文件夹下。
此时目录结构如下:
2.添加类代码
ui界面
界面如下:
panel_widget.h
#ifndef PANEL_WIDGET_H
#define PANEL_WIDGET_H
#include <QWidget>
namespace Ui {
class Panel_Widget;
}
namespace progressBar_panel {
class Panel_Widget : public QWidget
{
Q_OBJECT
public:
explicit Panel_Widget(QWidget *parent = 0);
~Panel_Widget();
Q_SIGNALS:
void sigToUpdateTopicAndProgressBarValue(QString topic,float value);
private:
Ui::Panel_Widget *ui;
};
}
#endif // PANEL_WIDGET_H
panel_widget.cpp
#include "progressBar_panel/panel_widget.h"
#include "ui_panel_widget.h"
namespace progressBar_panel {
Panel_Widget::Panel_Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Panel_Widget)
{
ui->setupUi(this);
connect(ui->topic_name,&QLineEdit::editingFinished,this,[=](){
Q_EMIT sigToUpdateTopicAndProgressBarValue(ui->topic_name->text(),ui->progressBar_value->text().toFloat());
});
connect(ui->progressBar_value,&QLineEdit::editingFinished,this,[=](){
Q_EMIT sigToUpdateTopicAndProgressBarValue(ui->topic_name->text(),ui->progressBar_value->text().toFloat());
});
connect(ui->pushButton_add,&QPushButton::clicked,this,[=](){
ui->progressBar_value->setText(QString::number(ui->progressBar_value->text().toFloat() + 5));
Q_EMIT sigToUpdateTopicAndProgressBarValue(ui->topic_name->text(),ui->progressBar_value->text().toFloat());
if(ui->progressBar_value->text().toFloat() == 100)
ui->progressBar_value->setText("0");
});
}
Panel_Widget::~Panel_Widget()
{
delete ui;
}
}
progressbar_panel.h
#ifndef PROGRESSBAR_PANEL_H
#define PROGRESSBAR_PANEL_H
#include <rviz/panel.h>
#include <ros/ros.h>
#include <rviz/panel.h>
#include "panel_widget.h"
#include "plugin_msg/ProgressBarMsg.h"
namespace progressBar_panel {
class ProgressBar_Panel: public rviz::Panel
{
public:
ProgressBar_Panel(QWidget* parent = 0 );
virtual void load( const rviz::Config& config );
virtual void save( rviz::Config config ) const;
public Q_SLOTS:
void updateTopicAndProgressBarValue(QString topic,float value);
private:
Panel_Widget *panel_widget;
// The current name of the output topic.
QString output_topic_;
// The ROS publisher for the command velocity.
ros::Publisher progressBar_publisher_;
// The ROS node handle.
ros::NodeHandle nh_;
};
}
#endif // PROGRESSBAR_PANEL_H
progressbar_panel.cpp
#include "progressBar_panel/progressbar_panel.h"
#include <rviz/properties/bool_property.h>
#include <rviz/properties/float_property.h>
#include <rviz/properties/string_property.h>
#include <rviz/window_manager_interface.h>
#include <rviz/display_context.h>
#include <QVBoxLayout>
#include <QDebug>
#include <QDateTime>
namespace progressBar_panel
{
ProgressBar_Panel::ProgressBar_Panel(QWidget* parent): rviz::Panel( parent )
{
panel_widget = new Panel_Widget;
connect(panel_widget,&Panel_Widget::sigToUpdateTopicAndProgressBarValue,this,&ProgressBar_Panel::updateTopicAndProgressBarValue);
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(panel_widget);
setLayout(layout);
}
void ProgressBar_Panel::load(const rviz::Config &config)
{
rviz::Panel::load( config );
}
void ProgressBar_Panel::save(rviz::Config config) const
{
rviz::Panel::save( config );
}
void ProgressBar_Panel::updateTopicAndProgressBarValue(QString topic, float value)
{
if( topic != output_topic_ )
{
output_topic_ = topic;
// If the topic is the empty string, don't publish anything.
if( output_topic_ == "" )
{
progressBar_publisher_.shutdown();
}
else
{
// The old ``velocity_publisher_`` is destroyed by this assignment,
// and thus the old topic advertisement is removed. The call to
// nh_advertise() says we want to publish data on the new topic
// name.
progressBar_publisher_ = nh_.advertise<plugin_msg::ProgressBarMsg>( output_topic_.toStdString(), 1 );
}
// rviz::Panel defines the configChanged() signal. Emitting it
// tells RViz that something in this panel has changed that will
// affect a saved config file. Ultimately this signal can cause
// QWidget::setWindowModified(true) to be called on the top-level
// rviz::VisualizationFrame, which causes a little asterisk ("*")
// to show in the window's title bar indicating unsaved changes.
Q_EMIT configChanged();
}
if( ros::ok() && progressBar_publisher_ )
{
plugin_msg::ProgressBarMsg msg;
msg.header.frame_id = "map";//output_topic_.toStdString();
msg.header.stamp = ros::Time(QDateTime::currentSecsSinceEpoch());
msg.value = value;
progressBar_publisher_.publish( msg );
//qDebug()<<"publisher msg";
}
}
}
// 声明此类是一个rviz的插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(progressBar_panel::ProgressBar_Panel,rviz::Panel )
3.添加plugin_description.xml文件
内容如下:
<library path="lib/libprogressBar_panel">
<class name="progressBar_panel/ProgressBarPanel"
type="progressBar_panel::ProgressBar_Panel"
base_class_type="rviz::Panel">
<description>
panel progressBar information
</description>
</class>
</library>
4.修改package.xml文件
修改内容如下:
<?xml version="1.0"?>
<package format="2">
<name>progressBar_panel</name>
<version>0.1.0</version>
<description>The progressBar_panel package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
<maintainer email="[email protected]">root</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>Apache 2.0</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/progressBar_panel</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="[email protected]">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>qtbase5-dev</build_depend>
<build_depend>rviz</build_depend>
<exec_depend>libqt5-core</exec_depend>
<exec_depend>libqt5-gui</exec_depend>
<exec_depend>libqt5-widgets</exec_depend>
<exec_depend>rviz</exec_depend>
<build_depend>custom_msg</build_depend>
<build_export_depend>custom_msg</build_export_depend>
<exec_depend>custom_msg</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
<rviz plugin="${prefix}/plugin_description.xml"/>
</export>
</package>
5.修改CMakeLists.txt文件
修改内容如下:
#指定项目所需的最低 CMake 版本。
cmake_minimum_required(VERSION 3.0.2)
#定义项目的名称
project(progressBar_panel)
#查找并导入外部依赖库
find_package(catkin REQUIRED COMPONENTS
rviz
plugin_msg
)
## 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})
macro(qt_wrap_ui)
qt4_wrap_ui(${ARGN})
endmacro()
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)
macro(qt_wrap_ui)
qt5_wrap_ui(${ARGN})
endmacro()
endif()
#添加头文件搜索路径,编译器使用这些目录来查找头文件,第一个参数“include”表示包中的include/目录也是路径的一部分。
include_directories(
include
${catkin_INCLUDE_DIRS}
)
## I prefer the Qt signals and slots to avoid defining "emit", "slots",
## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here.
add_definitions(-DQT_NO_KEYWORDS)
## I prefer the Qt signals and slots to avoid defining "emit", "slots",
## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here.
add_definitions(-DQT_NO_KEYWORDS)
# 设置相关变量
# 自动添加当前目录至路径中
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# 自动生成moc文件,自动运行moc
set(CMAKE_AUTOMOC ON)
# 自动运行uic
#set(CMAKE_AUTOUIC ON)
# 自动运行rcc
set(CMAKE_AUTORCC ON)
qt_wrap_ui(UIC_FILES
ui/panel_widget.ui
)
#用来匹配指定路径下所有符合通配符条件的文件的命令。具体来说,GLOB_RECURSE 是递归查找目录下的所有文件,file() 命令则可以用来获取文件列表。
file(GLOB_RECURSE SOURCE_CPP
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
)
file(GLOB_RECURSE SOURCE_H
"${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}/*.h"
)
#生成库
add_library(${PROJECT_NAME}
${SOURCE_H}
${SOURCE_CPP}
${UIC_FILES}
)
#在定义消息类型时,编译的库依赖这些动态生成的代码
add_dependencies(${PROJECT_NAME} plugin_msg_generate_messages_cpp)
#设置链接库,需要用到系统或者第三方库函数时候进行配置,第一个参数是可执行文件名,后面依次写入需要链接的库
#设置生成库依赖的库
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
${QT_LIBRARIES}
)
五、编译
在工作空间下打开终端,输入命令
catkin_make
六 、运行
在终端输入命令,设置环境
source devel/setup.bash
在打开rviz之前需另开一个终端打开ros环境
roscore
输入命令打开rviz可视化工具
rviz
七 、rviz的使用
1.打开Panel类型插件
点击菜单栏的【Panel】选项,点击【Add New Panel】按钮。
选择【progressBar_panel】下的【ProgressBarPanel】插件,点击【OK】按钮。
此时在rviz中显示出该插件。
2.添加Display类型插件
点击【Displays】视口的【Add】按钮。
选择【progressBar_display】下的【ProgressBar】插件,点击【OK】按钮。
此时在rviz的Displays视口显示该插件。
3.插件的使用
首先在Panel插件中输入一个topic name(推送的话题名称)。
在Display插件中选择订阅的话题,如下图:
此时修改slider value的值即可看到并修改中间部分的进度条。
需要注意的是:
推送的消息中会设置frame id,本次设置的为map,所以不需修改此值,如果推送的消息中不为map,需要一致。
资源链接
https://download.csdn.net/download/m0_67254672/88225745?spm=1001.2014.3001.5501