| name | plugin-development |
| description | RViz2 插件开发技能 - 自定义显示类型、工具插件、面板插件 |
| argument-hint | rviz插件开发 OR 自定义显示 OR 工具插件 |
| user-invocable | true |
RViz2 Plugin Development Skill
用于开发 RViz2 插件和扩展
何时使用
当需要以下帮助时使用此技能:
- 创建自定义显示类型
- 开发工具插件
- 添加新的面板
- 扩展 RViz2 功能
快速参考
创建插件包
cd ~/ros2_ws/src
ros2 pkg create rviz2_my_plugin --dependencies rviz_rendering rviz_ogre_vendor
cd rviz2_my_plugin
mkdir src
显示插件
基本显示类
#include <rviz_common/display.hpp>
namespace rviz_my_plugin
{
class MyDisplay : public rviz_common::Display
{
Q_OBJECT
public:
MyDisplay();
~MyDisplay() override;
protected:
void onInitialize() override;
void update(float dt, ros::Time time) override;
void reset() override;
private:
rviz_rendering::Object * object_;
Ogre::SceneNode * scene_node_;
};
}
实现文件
#include "my_display.h"
namespace rviz_my_plugin
{
MyDisplay::MyDisplay()
: Display()
{
auto * category = property_manager_->createCategory("My Properties");
color_property_ = new rviz_common::properties::ColorProperty(
"Color", QColor(255, 255, 255),
"Color of the object",
this, SLOT(updateColor()));
}
void MyDisplay::onInitialize()
{
scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
object_ = new rviz_rendering::Shape(
rviz_rendering::Shape::Type::Sphere,
scene_manager_,
scene_node_);
}
void MyDisplay::update(float dt, ros::Time time)
{
}
void MyDisplay::reset()
{
}
}
#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(rviz_my_plugin::MyDisplay, rviz_common::Display)
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(rviz2_my_plugin)
# 找到 RViz2
find_package(ament_cmake REQUIRED)
find_package(rviz_common REQUIRED)
find_package(rviz_rendering REQUIRED)
find_package(rviz_ogre_vendor REQUIRED)
# 创建插件库
add_library(rviz2_my_plugin SHARED
src/my_display.cpp
)
target_link_libraries(rviz2_my_plugin
rviz_common::rviz_common
rviz_rendering::rviz_rendering
)
# 安装插件
pluginlib_export_plugin_config_file(rviz2_my_plugin_plugins.xml)
# 安装
ament_export_targets(rviz2_my_pluginTargets HAS_LIBRARY_TARGET)
ament_install_hooks(PROJECT space "${ament_cMAKE_PROJECT_HOOK_INSTALL_SPACE_DIR}/rviz2_my_plugin_hooks.cmake")
install(
TARGETS rviz2_my_plugin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
插件描述文件
<library path="rviz2_my_plugin">
<class name="rviz_my_plugin/MyDisplay"
type="rviz_my_plugin::MyDisplay"
base_class_type="rviz_common::Display">
<description>My custom display plugin</description>
</class>
</library>
工具插件
基本工具类
#include <rviz_common/tool.hpp>
namespace rviz_my_plugin
{
class MyTool : public rviz_common::Tool
{
Q_OBJECT
public:
MyTool();
~MyTool() override;
virtual void onInitialize() override;
virtual void activate() override;
virtual void deactivate() override;
virtual int processKeyEvent(QKeyEvent *event, rviz_common::RenderPanel *panel) override;
virtual int processMouseEvent(rviz_common::MouseEvent &event, rviz_common::RenderPanel *panel) override;
private:
void onSelect(const Ogre::Vector3 &point);
};
}
工具实现
#include "my_tool.h"
namespace rviz_my_plugin
{
MyTool::MyTool()
: Tool()
{
shortcut_key_ = 'm';
}
void MyTool::onInitialize()
{
cursor_ = QCursor(Qt::CrossCursor);
}
void MyTool::activate()
{
}
void MyTool::deactivate()
{
}
int MyTool::processMouseEvent(rviz_common::MouseEvent &event, rviz_common::RenderPanel *panel)
{
if (event.leftDown())
{
Ogre::Vector3 point;
if (panel->getManager()->getScene()->getRaycastResult(event.x(), event.y(), point))
{
onSelect(point);
}
}
return 0;
}
}
#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(rviz_my_plugin::MyTool, rviz_common::Tool)
面板插件
基本面板类
#include <rviz_common/panel.hpp>
namespace rviz_my_plugin
{
class MyPanel : public rviz_common::Panel
{
Q_OBJECT
public:
MyPanel(QWidget *parent = nullptr);
protected:
void load(const rviz_common::Config &config) override;
void save(rviz_common::Config config) const override;
private:
QPushButton * button_;
QLabel * label_;
private Q_SLOTS:
void onButtonClicked();
};
}
面板实现
#include "my_panel.h"
namespace rviz_my_plugin
{
MyPanel::MyPanel(QWidget *parent)
: Panel(parent)
{
QVBoxLayout * layout = new QVBoxLayout;
button_ = new QPushButton("Click Me");
label_ = new QLabel("Status: Ready");
layout->addWidget(button_);
layout->addWidget(label_);
setLayout(layout);
connect(button_, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
}
void MyPanel::load(const rviz_common::Config &config)
{
Panel::load(config);
}
void MyPanel::save(rviz_common::Config config) const
{
Panel::save(config);
}
void MyPanel::onButtonClicked()
{
label_->setText("Clicked!");
}
}
#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(rviz_my_plugin::MyPanel, rviz_common::Panel)
属性系统
创建属性
#include <rviz_common/properties/property.hpp>
auto * prop = property_manager_->createProperty<BoolProperty>(
"Enabled", "Enable display", true, this, SLOT(onEnableChanged()));
auto * color_prop = property_manager_->createProperty<ColorProperty>(
"Color", "Object color", QColor(255, 0, 0), this, SLOT(onColorChanged()));
auto * float_prop = property_manager_->createProperty<FloatProperty>(
"Scale", "Object scale", 1.0, this, SLOT(onScaleChanged()));
auto * string_prop = property_manager_->createProperty<StringProperty>(
"Topic", "Topic name", "/my_topic", this, SLOT(onTopicChanged()));
场景管理
创建对象
auto * mesh = new rviz_rendering::MeshObject(scene_manager_, scene_node_);
auto * line = new rviz_rendering::Line(scene_manager_, scene_node_);
line->setPoints(start, end);
line->setColor(r, g, b, a);
auto * arrow = new rviz_rendering::Arrow(scene_manager_, scene_node_);
arrow->setDirection(direction);
arrow->setScale(scale);
auto * text = new rviz_rendering::MovableText("Label", "Arial", 0.1);
text->setPosition(position);
构建和安装
cd ~/ros2_ws
colcon build --packages-select rviz2_my_plugin
rviz2
常见问题
问题 1: 插件不加载
解决方案:检查插件描述文件路径,确认库文件安装位置正确
另见