RViz Marker 点和线
目标: 展示如何用 visualization_msgs/msg/Marker 消息向 RViz 发送点和线。
教程级别: 中级
预计时长: 15 分钟
注意: 本教程假设你已经完成了 Marker:发送基本形状。
在 Marker:发送基本形状 中,你学会了如何用可视化 Marker 向 RViz 发送简单形状。除了基本形状,Marker 还能展示更多内容。本教程将介绍 POINTS、LINE_STRIP 和 LINE_LIST 这三种 Marker 类型。完整的类型列表请参阅 Marker:Display 类型。
使用 Points、Line Strips 和 Line Lists
Section titled “使用 Points、Line Strips 和 Line Lists”POINTS、LINE_STRIP 和 LINE_LIST Marker 都使用 visualization_msgs/msg/Marker 消息的 points 成员。POINTS 类型会在每个添加的坐标处绘制一个点;LINE_STRIP 类型将各点依次连接成一条连续的线——点 0 连到点 1,点 1 连到点 2,依此类推;LINE_LIST 类型则将点两两配对,生成彼此独立的线段,例如点 0–1、点 2–3 等。
从 visualization_tutorials 仓库 获取本教程对应的包。代码位于 visualization_marker_tutorials 包中,完整源文件可在此查看:points_and_lines.cpp。
下面逐步解析代码,跳过之前教程中已经解释过的部分。程序最终呈现的效果是一条旋转的螺旋线,每个顶点上方还附带一条竖直线段。
先来看节点所需的头文件,包括用于螺旋线计算的 cmath,以及 Marker 和点的消息定义。
#define _USE_MATH_DEFINES
#include <chrono>#include <cmath>#include <memory>
#include "rclcpp/rclcpp.hpp"#include "geometry_msgs/msg/point.hpp"#include "visualization_msgs/msg/marker.hpp"这些头文件你应该已经很熟悉了。接下来初始化 ROS 2,创建一个节点,在 visualization_marker 话题上创建发布者,并设置循环频率。
rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("points_and_lines");auto marker_pub = node->create_publisher<visualization_msgs::msg::Marker>( "visualization_marker", 10);rclcpp::Rate loop_rate(30);此外还定义了一个浮点变量,用来随时间驱动螺旋线的旋转动画。
float f = 0.0f;在主循环内部,创建三条 visualization_msgs/msg/Marker 消息,并初始化它们共有的字段。Marker 消息默认包含一个单位四元数姿态,因此只需设置本教程关心的字段。
visualization_msgs::msg::Marker points, line_strip, line_list;points.header.frame_id = line_strip.header.frame_id = line_list.header.frame_id = "my_frame";points.header.stamp = line_strip.header.stamp = line_list.header.stamp = rclcpp::Clock().now();points.ns = line_strip.ns = line_list.ns = "points_and_lines";points.action = line_strip.action = line_list.action = visualization_msgs::msg::Marker::ADD;这里为三个 Marker 分配了不同的 ID。使用 points_and_lines 命名空间可以避免与其他 Marker 发布者冲突。
points.id = 0;line_strip.id = 1;line_list.id = 2;接下来将 Marker 类型设置为 POINTS、LINE_STRIP 和 LINE_LIST。
points.type = visualization_msgs::msg::Marker::POINTS;line_strip.type = visualization_msgs::msg::Marker::LINE_STRIP;line_list.type = visualization_msgs::msg::Marker::LINE_LIST;scale 成员对不同 Marker 类型含义不同。POINTS Marker 用 x 和 y 分别表示点的宽度和高度,而 LINE_STRIP 和 LINE_LIST Marker 只用 x 分量指定线宽。缩放值的单位是米。
points.scale.x = 0.2;points.scale.y = 0.2;
line_strip.scale.x = 0.1;line_list.scale.x = 0.1;这里将点设为绿色,线段(LINE_STRIP)设为蓝色,独立线段(LINE_LIST)设为红色。与其他 Marker 一样,alpha 通道值必须为非零。
points.color.g = 1.0f;points.color.a = 1.0;
line_strip.color.b = 1.0;line_strip.color.a = 1.0;
line_list.color.r = 1.0;line_list.color.a = 1.0;接下来为点和线创建顶点。我们用正弦和余弦函数生成螺旋线。POINTS 和 LINE_STRIP Marker 每个顶点只需一个点,而 LINE_LIST Marker 每条线段需要两个点。
for (uint32_t i = 0; i < 100; ++i) { float y = 5 * sin(f + i / 100.0f * 2 * M_PI); float z = 5 * cos(f + i / 100.0f * 2 * M_PI);
geometry_msgs::msg::Point p; p.x = static_cast<int32_t>(i) - 50; p.y = y; p.z = z;
points.points.push_back(p); line_strip.points.push_back(p);
// The line list needs two points for each line line_list.points.push_back(p); p.z += 1.0; line_list.points.push_back(p);}填写完 Marker 消息后,将三者全部发布。
marker_pub->publish(points);marker_pub->publish(line_strip);marker_pub->publish(line_list);随后休眠等待,推进动画相位,回到循环开头。
loop_rate.sleep();f += 0.04f;查看 Marker
Section titled “查看 Marker”在工作空间中编译该包:
$ colcon build --packages-select visualization_marker_tutorials然后 source 工作空间并运行节点:
$ source install/setup.bash$ ros2 run visualization_marker_tutorials points_and_lines现在运行 RViz:
$ source install/setup.bash$ ros2 run rviz2 rviz2如果你从未使用过 RViz,请先阅读 RViz 用户指南。
按照上一个教程的方式配置 RViz。由于我们没有设置任何坐标变换,请将 Fixed Frame 设为 my_frame。然后添加一个 Marker Display,默认话题 visualization_marker 与节点发布的话题一致。
你应该能看到一条旋转的螺旋线,效果类似于:
{/* 截图:points_and_lines Marker 教程 */}
想了解 RViz 支持的更多 Marker 类型和选项,请继续阅读 Marker:Display 类型。不妨动手试试其他 Marker 类型。