您正在阅读的是开发版本的文档。有关最新发布的版本,请访问 Jazzy.
定制 RViz 显示屏
背景介绍
RViz 中已有许多可视化数据类型。但是,如果有一种信息类型还没有插件来显示它,那么有两种选择可以在 RViz 中看到它。
将信息转换为另一种类型,例如
可视化_msgs/标记
.编写自定义 RViz 显示。
第一种方案的网络流量更大,数据表示方式也受到限制。但它同样快速灵活。本教程将解释后一种方案。它需要一些工作,但能带来更丰富的可视化效果。
本教程的所有代码都可以在 此存储库.为了查看本教程中编写的插件的增量进度,版本库中有不同的分支 (步骤2
, 步骤3
......),每个都可以编译并运行。
Point2D 信息
我们将使用在 rviz_plugin_tutorial_msgs
包装 Point2D.msg
:
std_msgs/页眉 页眉
浮点64 x
浮点64 y
基本插件的模板
请注意,这里有很多代码。您可以通过分支名称查看完整版代码 步骤1
.
文件头
以下是 point_display.hpp
#ifndef RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_
#define RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_
#include <rviz_common/message_filter_display.hpp>;
#include <rviz_plugin_tutorial_msgs/msg/point2_d.hpp>;
命名空间 rviz_plugin_tutorial
{
类 点显示
: 公 rviz_common::信息过滤显示<;rviz_plugin_tutorial_msgs::信息::Point2D>;
{
Q_OBJECT
受保护的:
空白 处理信息(缢 rviz_plugin_tutorial_msgs::信息::Point2D::ConstSharedPtr 信息) 否决;
};
} // 名称空间 rviz_plugin_tutorial
#endif // rviz_plugin_tutorial__point_display_hpp_
我们正在实施 信息过滤显示 类,该类可用于任何带有
std_msgs/Header
.该类使用我们的
Point2D
信息类型。由于本教程范围之外的原因您需要
Q_OBJECT
宏,以使图形用户界面的 QT 部分正常工作。处理信息
是唯一需要实现的方法,我们将在 cpp 文件中实现该方法。
源文件
point_display.cpp
#include <rviz_plugin_tutorial/point_display.hpp>;
#include <rviz_common/logging.hpp>;
命名空间 rviz_plugin_tutorial
{
空白 PointDisplay::processMessage(缢 rviz_plugin_tutorial_msgs::信息::Point2D::ConstSharedPtr 信息)
{
rviz_common_log_info_stream("我们收到一条带框架的信息"; <<; 信息->;页眉.frame_id);
}
} // 名称空间 rviz_plugin_tutorial
#include <pluginlib/class_list_macros.hpp>;
pluginlib_export_class(rviz_plugin_tutorial::点显示, rviz_common::显示屏)
记录日志并非绝对必要,但有助于调试。
为了让 RViz 找到我们的插件,我们需要这样做
PLUGINLIB
调用(以及下面的其他内容)。
package.xml
我们需要在 package.xml 中加入以下三个依赖项:
<依赖>;插件库依赖</depend>;
<依赖>;rviz_common依赖</depend>;
<依赖>;rviz_plugin_tutorial_msgs依赖</depend>;
rviz_common_plugins.xml
图书馆 path="point_display";>;
类别 type="rviz_plugin_tutorial::PointDisplay"; base_class_type="rviz_common::Display";>;
<description></description>;
</class>;
</library>;
这是标准
插件库
代码图书馆
路
是我们将在 CMake 中指定的库名。该类应与
PLUGINLIB
从上面调用。
我保证,我们稍后会再来描述的。
CMakeLists.txt
在标准模板顶部添加以下几行。
查找软件包(ament_cmake_ros 要求)
查找软件包(插件库 要求)
查找软件包(rviz_common 要求)
查找软件包(rviz_plugin_tutorial_msgs 要求)
设置(CMAKE_AUTOMOC 关于)
qt5_wrap_cpp(MOC_FILES
include/rviz_plugin_tutorial/point_display.hpp
)
add_library(点显示 src/point_display.cpp ${MOC_FILES})
目标包含目录(点显示 公众
$<;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>;
$<;INSTALL_INTERFACE:include>;
)
ament_target_dependencies(点显示
插件库
rviz_common
rviz_plugin_tutorial_msgs
)
安装(目标 点显示
出口 export_rviz_plugin_tutorial
存档 目的地 lib
图书馆 目的地 lib
运行时间 目的地 箱柜
)
安装(目录 包括
目的地 包括
)
安装(文件 rviz_common_plugins.xml
目的地 分享/${项目名称}
)
ament_export_include_directories(包括)
输出目标(export_rviz_plugin_tutorial)
pluginlib_export_plugin_description_file(rviz_common rviz_common_plugins.xml)
要生成合适的 Qt 文件,我们需要
转弯
CMAKE_AUTOMOC
上。通过调用
qt5_wrap_cpp
的每个标头Q_OBJECT
中。包括
MOC_FILES
和其他 cpp 文件一起放在库中。
请注意,如果不封装头文件,在运行时尝试加载插件时可能会收到错误信息,大致如下
[rviz2]:PluginlibFactory:类 'rviz_plugin_tutorial::PointDisplay' 的插件加载失败。Error:Failed to load library /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so.请确保在库代码中调用了 PLUGINLIB_EXPORT_CLASS 宏,并确保该宏和 XML 名称一致。错误字符串:无法加载库 LoadLibrary error:/home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so: undefined symbol:_ZTVN20rviz_plugin_tutorial12PointDisplayE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84
许多其他代码确保插件部分正常工作。也就是说,调用
pluginlib_export_plugin_description_file
是让 RViz 找到新插件的关键。
测试
编译代码并运行 rviz2
.通过点击 添加
左下角,然后选择软件包/插件。

起初,显示屏将处于错误状态,因为您尚未分配主题。

如果我们把主题 /点
在这种情况下,加载应该正常,但不会显示任何内容。

您可以使用以下命令发布消息:
玫瑰2 主题 酒吧 /点 rviz_plugin_tutorial_msgs/msg/Point2D "{header:{frame_id: map}, x: 1, y: 2}"; -r 0.5
这样,"我们收到一条信息 "日志就会出现在 数据输出
的 RViz。
实际可视化
您可以查看此步骤的完整版本,分支名称为 步骤2
.
首先,您需要在 CMakeLists.txt
和 package.xml
包装上 rviz_rendering
.
我们需要在头文件中添加三行:
#include <rviz_rendering/objects/shape.hpp>;
- 有 rviz_rendering 软件包中有很多选项 对象来构建可视化。这里我们使用的是一个简单的形状。类中,我们将添加一个新的
受保护的
虚拟方法:空白 onInitialize() 覆盖;
我们还为形状对象添加了一个指针:
std::unique_ptr<rviz_rendering::Shape>; 点形状;
然后在 cpp 文件中定义 初始化时
方法:
空白 PointDisplay::onInitialize()
{
中频分类::初始化时();
点形状 =
标准::make_unique<;rviz_rendering::形状>;(rviz_rendering::形状::类型::立方体, 场景管理器,
场景节点);
}
中频分类
是 别名 到模板化的父类,以方便使用。形状对象必须在此处的
初始化时
方法,而不是构造函数,因为否则场景管理器
和场景节点
还没有准备好。
我们还更新了 处理信息
方法:
空白 PointDisplay::processMessage(缢 rviz_plugin_tutorial_msgs::信息::Point2D::ConstSharedPtr 信息)
{
rviz_common_log_info_stream("我们收到一条带框架的信息"; <<; 信息->;页眉.frame_id);
食人魔::向量3 位置;
食人魔::四元数 方向;
如果 (!上下文_->;getFrameManager()->;获取变换(信息->;页眉, 位置, 方向)) {
rviz_common_log_debug_stream("Error transforming from frame '"; <<; 信息->;页眉.frame_id <<;
"'to frame '"; <<; qPrintable(固定框架) <<; "'";);
}
场景节点->;设置位置(位置);
场景节点->;设置方向(方向);
食人魔::向量3 point_pos;
point_pos.x = 信息->;x;
point_pos.y = 信息->;y;
点形状->;设置位置(point_pos);
}
我们需要为我们的信息获取适当的框架,并将其转换为
场景节点
因此。这样可以确保可视化效果不会总是相对于固定框架显示。最后四行才是真正的可视化:我们设置了可视化的位置,使其与信息的位置相匹配。
结果应该是这样的

如果方框没有出现在该位置,可能是因为:
您目前没有发布该主题
该信息在过去 2 秒内未被发布。
您没有在 RViz 中正确设置主题。
有选择真好
如果要允许用户自定义可视化的不同属性,则需要添加 rviz_common::Property 对象.
您可以查看此步骤的完整版本,分支名称为 步骤3
.
标题更新
包含颜色属性的头文件: #include <rviz_common/properties/color_property.hpp>;
.颜色只是您可以设置的众多属性之一。
添加 更新样式
,每当通过 Qt 的 SIGNAL/SLOT 框架更改图形用户界面时都会调用它:
私人 Q_SLOTS:
空白 更新样式();
添加一个新属性来存储属性本身: std::unique_ptr<rviz_common::properties::ColorProperty>; color_property_;
Cpp 更新
#include <rviz_common/properties/parse_color.hpp>;
- 包含将属性转换为 OGRE 颜色的辅助函数。致我们的
初始化时
我们加上
颜色属性 = 标准::make_unique<;rviz_common::属性::颜色属性>;(
"点颜色";, QColor(36, 64, 142), 绘制点的颜色;, 此, 位子(更新样式()));
更新样式();
这将构建包含名称、默认值、描述和回调的对象。
我们称之为
更新样式
这样,即使在属性更改之前,颜色也会在开始时设置。然后我们定义回调。
空白 PointDisplay::updateStyle()
{
食人魔::颜色值 颜色 = rviz_common::属性::qtToOgre(颜色属性->;获取颜色());
点形状->;设置颜色(颜色);
}
结果应该是这样的

哦,粉红色

现状报告
您可以查看此步骤的完整版本,分支名称为 步骤4
.
您还可以设置显示屏的状态。举个简单的例子,当 x 坐标为负数时,显示屏会显示警告,为什么不呢?在 处理信息
:
如果 (信息->;x <; 0) {
设置状态(状态属性::警告, "信息";,
"我会抱怨 x 值为负的点;);
} 不然 {
设置状态(状态属性::好的, "信息";, "确定";);
}
我们假设以前
使用 rviz_common::properties::StatusProperty;
申报。将状态视为键/值对,键是某个字符串(这里我们使用
"信息";
),值是状态级别(错误/警告/正常)和描述(其他字符串)。


清理
现在是时候清理一下了。这可以让东西看起来更漂亮,使用起来更方便,但并非严格要求。您可以查看此步骤的完整版本,分支名称为 步骤5
.
首先,我们更新插件声明。
图书馆 path="point_display";>;
类别 名称"Point2D"; type="rviz_plugin_tutorial::PointDisplay"; base_class_type="rviz_common::Display";>;
<描述>;教程 至 展示 a 点</description>;
<消息类型>;rviz_plugin_tutorial_msgs/msg/Point2D</message_type>;
</class>;
</library>;
我们添加了
名字
字段到类
标签。这会更改 RViz 中显示的名称。在代码中,将其称为点显示
但在 RViz 中,我们希望简化。我们在描述中加入了实际文字。别偷懒
在此声明特定的信息类型后,当您尝试添加 "按主题显示 "时,它将为该类型的主题推荐此插件。
我们还在以下位置为插件添加了一个图标 icons/classes/Point2D.png
.文件夹是硬编码,文件名应与插件声明中的名称一致(如未指定,则与类名一致)。 [图标来源]
我们需要在 CMake 中安装映像文件。
安装(文件 icons/classes/Point2D.png
目的地 分享/${项目名称}/图标/类别
)
现在,当您添加显示屏时,它应该会显示一个图标和说明。

以下是尝试按主题添加时的显示:

最后,这是标准界面中的图标:

注意,如果更改插件名称,以前的 RViz 配置将不再有效。