创建内容过滤订阅
目标 创建内容过滤订阅。
辅导水平: 高级
时间 15 分钟
概述
ROS 2 应用程序通常由主题组成,用于从发布者向订阅者传输数据。基本上,订阅会接收发布者在主题上发布的所有数据。但有时,订阅可能只对发布者发送的部分数据感兴趣。内容过滤订阅可以只接收应用程序感兴趣的数据。
在本演示中,我们将重点介绍如何创建内容过滤订阅及其工作原理。
RMW 支持
内容过滤订阅需要 RMW 实施支持。
rmw_fastrtps |
支持 |
rmw_connextdds |
支持 |
rmw_cyclonedds |
不支持 |
目前,所有支持内容过滤订阅的 RMW 实施都是 DDS 为基础。这意味着支持的过滤表达式和参数也取决于 DDS您可以参考 DDS 规格 附件 B - 语法 对于 查询 和 过滤器
了解详情。
安装演示版
参见 安装说明 了解安装 ROS 2 的详情。
如果您从软件包中安装了 ROS 2,请确保有 ros-jazzy-demo-nodes-cpp
已安装。如果您下载了压缩包或从源代码构建了 ROS 2,那么它已经是安装的一部分了。
温度滤波演示
该演示展示了如何使用内容过滤订阅来只接收超出可接受温度范围的温度值,以检测紧急情况。内容过滤订阅会过滤掉不感兴趣的温度数据,因此不会发出订阅回调。
内容过滤出版商
https://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/topics/content_filtering_publisher.cpp
#include 时间顺序<chrono>;
#include <cstdio>;
#include <内存>;
#include <utility>;
#include "rclcpp/rclcpp.hpp";
#include "rclcpp_components/register_node_macro.hpp";
#include "std_msgs/msg/float32.hpp";
#include "demo_nodes_cpp/visibility_control.h";
使用 命名空间 标准::计时器;
命名空间 演示节点
{
// 模拟温度数据从 -100.0 开始,到 150.0 结束,步长为 10.0
常式 标准::矩阵<;浮动, 3>; temperature_setting {-100.0f, 150.0f, 10.0f};
// 创建一个内容过滤发布者(ContentFilteringPublisher)类,该类子类化了通用的 rclcpp::Node 基类。
// 下面的主函数将把该类实例化为一个 ROS 节点。
类 内容过滤出版商 : 公 rclcpp::节点
{
公:
demo_nodes_cpp_public
不含糊 内容过滤出版商(缢 rclcpp::节点选项 及样品; 选项)
: 节点("content_filtering_publisher";, 选项)
{
// 创建一个用于发送信息的函数。
setvbuf(数据输出, NULL, _IONBF, BUFSIZ);
汽车 发布消息 =
[此]() ->; 空白
{
msg_ = 标准::make_unique<;std_msgs::信息::浮点数 32>;();
msg_->;数据 = 温度_;
温度_ += temperature_setting[2];
如果 (温度_ >; temperature_setting[1]) {
温度_ = temperature_setting[0];
}
RCLCPP_INFO(此->;get_logger(), "出版:'%f'";, msg_->;数据);
// 将消息放入队列,由中间件处理。
// 该调用是非阻塞的。
公共_->;发布(标准::行动(msg_));
};
// 创建一个具有自定义服务质量配置文件的发布者。
// 建议进行统一初始化,这样就可以简单地改为
// rclcpp::KeepAll{}(如果用户希望)。
// (rclcpp::KeepLast(7) -> rclcpp::KeepAll() 编译失败)
rclcpp::服务质量 优先权(rclcpp::保持最后{7});
公共_ = 此->;创建出版商<;std_msgs::信息::浮点数 32>;("温度";, 优先权);
// 使用定时器定期发布消息。
定时器 = 此->;创建隔离墙计时器(1s, 发布消息);
}
私人:
浮动 温度_ = temperature_setting[0];
标准::唯一参数<;std_msgs::信息::浮点数 32>; msg_;
rclcpp::出版商<;std_msgs::信息::浮点数 32>::SharedPtr 公共_;
rclcpp::定时器基数::SharedPtr 定时器;
};
} // 名称空间 demo_nodes_cpp
内容过滤器是在订阅端定义的,不需要对出版商进行任何特殊配置就能允许内容过滤。内容过滤器 内容过滤出版商
节点以每秒 10.0 的步长发布从-100.0 到 150.0 的模拟温度数据。
我们可以通过运行 玫瑰2 运行 演示节点 内容过滤出版商
可执行文件(别忘了先获取设置文件的源代码):
$ 玫瑰2 运行 演示节点 内容过滤出版商
[信息] [1651094594.822753479] [内容过滤出版商]: 出版: '-100.000000'
[信息] [1651094595.822723857] [内容过滤出版商]: 出版: '-90.000000'
[信息] [1651094596.822752996] [内容过滤出版商]: 出版: '-80.000000'
[信息] [1651094597.822752475] [内容过滤出版商]: 出版: '-70.000000'
[信息] [1651094598.822721485] [内容过滤出版商]: 出版: '-60.000000'
[信息] [1651094599.822696188] [内容过滤出版商]: 出版: '-50.000000'
[信息] [1651094600.822699217] [内容过滤出版商]: 出版: '-40.000000'
[信息] [1651094601.822744113] [内容过滤出版商]: 出版: '-30.000000'
[信息] [1651094602.822694805] [内容过滤出版商]: 出版: '-20.000000'
[信息] [1651094603.822735805] [内容过滤出版商]: 出版: '-10.000000'
[信息] [1651094604.822722094] [内容过滤出版商]: 出版: '0.000000'
[信息] [1651094605.822699960] [内容过滤出版商]: 出版: '10.000000'
[信息] [1651094606.822748946] [内容过滤出版商]: 出版: '20.000000'
[信息] [1651094607.822694017] [内容过滤出版商]: 出版: '30.000000'
[信息] [1651094608.822708798] [内容过滤出版商]: 出版: '40.000000'
[信息] [1651094609.822692417] [内容过滤出版商]: 出版: '50.000000'
[信息] [1651094610.822696426] [内容过滤出版商]: 出版: '60.000000'
[信息] [1651094611.822751913] [内容过滤出版商]: 出版: '70.000000'
[信息] [1651094612.822692231] [内容过滤出版商]: 出版: '80.000000'
[信息] [1651094613.822745549] [内容过滤出版商]: 出版: '90.000000'
[信息] [1651094614.822701982] [内容过滤出版商]: 出版: '100.000000'
[信息] [1651094615.822691465] [内容过滤出版商]: 出版: '110.000000'
[信息] [1651094616.822649070] [内容过滤出版商]: 出版: '120.000000'
[信息] [1651094617.822693616] [内容过滤出版商]: 出版: '130.000000'
[信息] [1651094618.822691832] [内容过滤出版商]: 出版: '140.000000'
[信息] [1651094619.822688452] [内容过滤出版商]: 出版: '150.000000'
[信息] [1651094620.822645327] [内容过滤出版商]: 出版: '-100.000000'
[信息] [1651094621.822689219] [内容过滤出版商]: 出版: '-90.000000'
[信息] [1651094622.822694292] [内容过滤出版商]: 出版: '-80.000000'
[...]
内容过滤订阅者:
https://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/topics/content_filtering_subscriber.cpp
#include "rclcpp/rclcpp.hpp";
#include "rclcpp_components/register_node_macro.hpp";
#include "rcpputils/join.hpp";
#include "std_msgs/msg/float32.hpp";
#include "demo_nodes_cpp/visibility_control.h";
命名空间 演示节点
{
// 紧急温度数据小于 -30 或大于 100
常式 标准::矩阵<;浮动, 2>; 紧急温度 {-30.0f, 100.0f};
// 创建一个内容过滤订阅者(ContentFilteringSubscriber)类,该类子类化了通用的 rclcpp::Node 基类。
// 下面的主函数将把该类实例化为一个 ROS 节点。
类 内容过滤订阅者 : 公 rclcpp::节点
{
公:
demo_nodes_cpp_public
不含糊 内容过滤订阅者(缢 rclcpp::节点选项 及样品; 选项)
: 节点("content_filtering_subscriber";, 选项)
{
setvbuf(数据输出, NULL, _IONBF, BUFSIZ);
// 在收到信息时创建一个回调函数。
汽车 回调 =
[此](缢 std_msgs::信息::浮点数 32 及样品; 信息) ->; 空白
{
如果 (信息.数据 <; 紧急温度[0] || 信息.数据 >; 紧急温度[1]) {
RCLCPP_INFO(
此->;get_logger(),
"我收到紧急温度数据:[%f]";, 信息.数据);
} 不然 {
RCLCPP_INFO(此->;get_logger(), "我收到一个温度数据:[%f]";, 信息.数据);
}
};
// 用内容过滤器初始化订阅,以接收紧急温度数据,这些数据包括
// 小于 -30 或大于 100。
rclcpp::订阅选项 子选项;
子选项.内容过滤器选项.过滤表达式 = "data < %0 OR data > %1";;
子选项.内容过滤器选项.表达式参数 = {
标准::to_string(紧急温度[0]),
标准::to_string(紧急温度[1])
};
子_ = 创建订阅<;std_msgs::信息::浮点数 32>;("温度";, 10, 回调, 子选项);
如果 (!子_->;is_cft_enabled()) {
RCLCPP_WARN(
此->;get_logger(), "由于不支持内容过滤器,因此未启用'";);
} 不然 {
RCLCPP_INFO(
此->;get_logger(),
订阅主题 \";%s\"; 带内容过滤选项 \";%s, {%s}\";";,
子_->;获取主题名称(),
子选项.内容过滤器选项.过滤表达式.c_str(),
rcpputils::加入(子选项.内容过滤器选项.表达式参数, ",";).c_str());
}
}
私人:
rclcpp::订阅<;std_msgs::信息::浮点数 32>::SharedPtr 子_;
};
} // 名称空间 demo_nodes_cpp
要启用内容过滤功能,应用程序可在 "内容过滤 "中设置过滤表达式和表达式参数。 订阅选项
.应用程序还可以检查订阅是否启用了内容过滤功能。
在这个演示中, 内容过滤订阅者
节点创建了一个内容过滤订阅,只有当温度值小于 -30.0 或大于 100.0 时才会接收信息。
如前所述,内容过滤订阅支持取决于 RMW 的实现。应用程序可以使用 is_cft_enabled
方法来检查订阅是否真的启用了内容过滤功能。
要测试内容过滤订阅,让我们运行它:
$ 玫瑰2 运行 演示节点 内容过滤订阅者
[信息] [1651094590.682660703] [内容过滤订阅者]: 已订阅 至 主题 "/temperature"; 与 内容 过滤 选项 "data < %0 OR data > %1, {-30.000000, 100.000000}";
[信息] [1651094594.823805294] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-100.000000]
[信息] [1651094595.823419993] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-90.000000]
[信息] [1651094596.823410859] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-80.000000]
[信息] [1651094597.823350377] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-70.000000]
[信息] [1651094598.823282657] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-60.000000]
[信息] [1651094599.823297857] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-50.000000]
[信息] [1651094600.823355597] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-40.000000]
[信息] [1651094615.823315377] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [110.000000]
[信息] [1651094616.823258458] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [120.000000]
[信息] [1651094617.823323525] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [130.000000]
[信息] [1651094618.823315527] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [140.000000]
[信息] [1651094619.823331424] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [150.000000]
[信息] [1651094620.823271748] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-100.000000]
[信息] [1651094621.823343550] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-90.000000]
[信息] [1651094622.823286326] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-80.000000]
[信息] [1651094623.823371031] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-70.000000]
[信息] [1651094624.823333112] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-60.000000]
[信息] [1651094625.823266469] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-50.000000]
[信息] [1651094626.823284093] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-40.000000]
只有当温度值小于 -30.0 或大于 100.0 时,您才会看到一条信息,显示所使用的内容过滤选项和收到的每条信息的日志。
如果 RMW 实现不支持内容过滤,则订阅仍将在未启用内容过滤的情况下创建。我们可以通过执行 RMW_IMPLEMENTATION=rmw_cyclonedds_cpp 玫瑰2 运行 演示节点 内容过滤出版商
.
$ rmw_implementation=rmw_cyclonedds_cpp 玫瑰2 运行 演示节点 内容过滤订阅者
[警告] [1651096637.893842072] [内容过滤订阅者]: 内容 过滤 是 不 启用 因为 它 是 不 支持
[信息] [1651096641.246043703] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-100.000000]
[信息] [1651096642.245833527] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-90.000000]
[信息] [1651096643.245743471] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-80.000000]
[信息] [1651096644.245833932] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-70.000000]
[信息] [1651096645.245916679] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-60.000000]
[信息] [1651096646.245861895] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-50.000000]
[信息] [1651096647.245946352] [内容过滤订阅者]: I 接收 一个 紧急事件 温度 数据 [-40.000000]
[信息] [1651096648.245934569] [内容过滤订阅者]: I 接收 a 温度 数据 [-30.000000]
[信息] [1651096649.245877906] [内容过滤订阅者]: I 接收 a 温度 数据 [-20.000000]
[信息] [1651096650.245939068] [内容过滤订阅者]: I 接收 a 温度 数据 [-10.000000]
[信息] [1651096651.245911450] [内容过滤订阅者]: I 接收 a 温度 数据 [0.000000]
[信息] [1651096652.245879830] [内容过滤订阅者]: I 接收 a 温度 数据 [10.000000]
[信息] [1651096653.245858329] [内容过滤订阅者]: I 接收 a 温度 数据 [20.000000]
[信息] [1651096654.245916370] [内容过滤订阅者]: I 接收 a 温度 数据 [30.000000]
[信息] [1651096655.245933741] [内容过滤订阅者]: I 接收 a 温度 数据 [40.000000]
[信息] [1651096656.245833975] [内容过滤订阅者]: I 接收 a 温度 数据 [50.000000]
[信息] [1651096657.245971483] [内容过滤订阅者]: I 接收 a 温度 数据 [60.000000]
您可以看到以下信息 内容 过滤 是 不 启用
因为底层 RMW 实现不支持该功能,但演示仍成功创建了正常订阅,以接收所有温度数据。