警告
您正在阅读的 ROS 2 文档版本已达到 EOL(生命周期结束),不再受官方支持。如果您想了解最新信息,请访问 Jazzy.
编写简单的发布器和订阅器(C++)
目标 使用 C++ 创建并运行一个发布者和订阅者节点。
辅导水平: 初学者
时间 20 分钟
背景介绍
节点 是通过 ROS 图进行通信的可执行进程。在本教程中,节点将以字符串信息的形式通过 主题.这里使用的示例是一个简单的 "说者 "和 "听者 "系统;一个节点发布数据,另一个节点订阅主题以便接收数据。
先决条件
任务
1 创建软件包
打开一个新终端,然后 为您的 ROS 2 安装提供源代码 以便 玫瑰2
命令即可运行。
导航进入 dev_ws
目录中创建的 上一个教程.
回顾一下,软件包应在 来源
目录,而不是工作区的根目录。因此,导航到 dev_ws/src
然后运行软件包创建命令:
ros2 pkg create --build-type ament_cmake cpp_pubsub
您的终端将返回一条信息,验证是否创建了软件包 cpp_pubsub
及其所有必要的文件和文件夹。
导航进入 dev_ws/src/cpp_pubsub/src
.请注意,这是 CMake 软件包中包含可执行文件的源文件所在的目录。
2 写入发布节点
输入以下命令下载通话代码示例:
wget -O publisher_member_function.cpp https://raw.githubusercontent.com/ros2/examples/dashing/rclcpp/minimal_publisher/member_function.cpp
wget -O publisher_member_function.cpp https://raw.githubusercontent.com/ros2/examples/dashing/rclcpp/minimal_publisher/member_function.cpp
右键单击此链接并选择另存为 publisher_member_function.cpp
:
https://raw.githubusercontent.com/ros2/examples/dashing/rclcpp/minimal_publisher/member_function.cpp
现在将有一个名为 publisher_member_function.cpp
.使用您喜欢的文本编辑器打开文件。
#include 时间顺序<chrono>;
#include 功能强大;
#include <内存>;
#include <字符串>;
#include "rclcpp/rclcpp.hpp";
#include "std_msgs/msg/string.hpp";
使用 命名空间 标准::计时器;
/* 本例创建了一个 Node 子类,并使用 std::bind() 注册了一个
* 成员函数作为定时器的回调。*/
类 最小出版商 : 公 rclcpp::节点
{
公:
最小出版商()
: 节点("minimal_publisher";), count_(0)
{
出版商_ = 此->;创建出版商<;std_msgs::信息::字符串>;("主题";, 10);
定时器 = 此->;创建隔离墙计时器(
500毫秒, 标准::约束(及样品;最小出版商::定时器回调, 此));
}
私人:
空白 定时器回调()
{
汽车 信息 = std_msgs::信息::字符串();
信息.数据 = 世界,你好!"; + 标准::to_string(count_++);
RCLCPP_INFO(此->;get_logger(), "出版:'%s'";, 信息.数据.c_str());
出版商_->;发布(信息);
}
rclcpp::定时器基数::SharedPtr 定时器;
rclcpp::出版商<;std_msgs::信息::字符串>::SharedPtr 出版商_;
size_t count_;
};
int 主要(int 参数, 烧焦 * 参数[])
{
rclcpp::启动(参数, 参数);
rclcpp::后旋(标准::共享<;最小出版商>;());
rclcpp::关闭();
返回 0;
}
2.1 检查代码
代码顶部包含您将使用的标准 C++ 头文件。标准 C++ 头文件之后是 rclcpp/rclcpp.hpp
include 允许你使用 ROS 2 系统中最常用的组件。最后是 std_msgs/msg/string.hpp
,其中包括用于发布数据的内置消息类型。
这些线条代表节点的依赖关系。请注意,必须将依赖关系添加到 package.xml
和 CMakeLists.txt
您将在下一节中完成这一操作。
#include 时间顺序<chrono>;
#include 功能强大;
#include <内存>;
#include <字符串>;
#include "rclcpp/rclcpp.hpp";
#include "std_msgs/msg/string.hpp";
使用 命名空间 标准::计时器;
下一行创建节点类 最小出版商
继承自 rclcpp::Node
.每 此
是指节点。
类 最小出版商 : 公 rclcpp::节点
公共构造函数为节点命名 最小出版商
并初始化 count_
初始化为 0。 字符串
消息类型、主题名称 主题
以及所需的队列大小,以便在备份时限制信息。下一页 定时器
被初始化,这会导致 定时器回调
函数每秒执行两次。
公:
最小出版商()
: 节点("minimal_publisher";), count_(0)
{
出版商_ = 此->;创建出版商<;std_msgs::信息::字符串>;("主题";, 10);
定时器 = 此->;创建隔离墙计时器(
500毫秒, 标准::约束(及样品;最小出版商::定时器回调, 此));
}
"(《世界人权宣言》) 定时器回调
函数是设置信息数据和实际发布信息的地方。该 RCLCPP_INFO
宏确保每一条发布的消息都会打印到控制台。
私人:
空白 定时器回调()
{
汽车 信息 = std_msgs::信息::字符串();
信息.数据 = 世界,你好!"; + 标准::to_string(count_++);
RCLCPP_INFO(此->;get_logger(), "出版:'%s'";, 信息.数据.c_str());
出版商_->;发布(信息);
}
最后是定时器、发布者和计数器字段的声明。
rclcpp::定时器基数::SharedPtr 定时器;
rclcpp::出版商<;std_msgs::信息::字符串>::SharedPtr 出版商_;
size_t count_;
继 最小出版商
类是 主要
,节点实际执行的位置。
rclcpp::init
初始化 ROS 2,以及 rclcpp::spin
开始处理来自节点的数据,包括来自定时器的回调。
int 主要(int 参数, 烧焦 * 参数[])
{
rclcpp::启动(参数, 参数);
rclcpp::后旋(标准::共享<;最小出版商>;());
rclcpp::关闭();
返回 0;
}
2.2 添加依赖项
导航一级回到 dev_ws/src/cpp_pubsub
目录中的 CMakeLists.txt
和 package.xml
文件已为您创建。
开放 package.xml
使用文本编辑器。
正如 上一个教程请确保填写 <描述>;
, <维护者>;
和 许可证
标签
<描述>;实例 的 极少 出版商/订户 使用 rclcpp</description>;
维护者 电子邮件="[email protected]";>;您的 名称维护人员</maintainer>;
许可证阿帕奇 许可证 2.0</license>;
在 ament_cmake
buildtool 依赖关系,并粘贴与节点的 include 语句相对应的下列依赖关系:
<依赖>;rclcpp依赖</depend>;
<依赖>;std_msgs依赖</depend>;
这就声明了软件包需要 rclcpp
和 std_msgs
当其代码被执行时。
确保保存文件。
2.3 CMakeLists.txt
现在打开 CMakeLists.txt
文件。在现有依赖关系的下方 find_package(ament_cmake 必填)
添加这几行:
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
然后,添加可执行文件并将其命名为 话匣子
这样您就可以使用 玫瑰2 运行
:
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
最后,添加 install(TARGETS...)
因此 玫瑰2 运行
能找到你的可执行文件:
install(TARGETS
话匣子
DESTINATION lib/${PROJECT_NAME})
您可以清理您的 CMakeLists.txt
删除了一些不必要的部分和注释,所以看起来像这样:
cmake_minimum_required(VERSION 3.5)
项目(cpp_pubsub)
# 默认值 至 C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
install(TARGETS
话匣子
DESTINATION lib/${PROJECT_NAME})
ament_package()
你可以现在就构建你的软件包,获取本地设置文件,然后运行它,但让我们先创建用户节点,这样你就能看到整个系统的运行情况。
3 写入用户节点
返回 dev_ws/src/cpp_pubsub/src
来创建下一个节点。在终端中输入以下代码
wget -O subscriber_member_function.cpp https://raw.githubusercontent.com/ros2/examples/dashing/rclcpp/minimal_subscriber/member_function.cpp
wget -O subscriber_member_function.cpp https://raw.githubusercontent.com/ros2/examples/dashing/rclcpp/minimal_subscriber/member_function.cpp
右键单击此链接并选择另存为 subscriber_member_function.cpp
:
进入 ls
现在将返回控制台中的
publisher_member_function.cpp subscriber_member_function.cpp
打开 subscriber_member_function.cpp
使用文本编辑器。
#include <内存>;
#include "rclcpp/rclcpp.hpp";
#include "std_msgs/msg/string.hpp";
使用 标准::占位符::_1;
类 最小订阅者 : 公 rclcpp::节点
{
公:
最小订阅者()
: 节点("minimal_subscriber";)
{
订阅_ = 此->;创建订阅<;std_msgs::信息::字符串>;(
"主题";, 10, 标准::约束(及样品;最小订阅者::topic_callback, 此, _1));
}
私人:
空白 topic_callback(缢 std_msgs::信息::字符串::SharedPtr 信息) 缢
{
RCLCPP_INFO(此->;get_logger(), "我听说:'%s'";, 信息->;数据.c_str());
}
rclcpp::订阅<;std_msgs::信息::字符串>::SharedPtr 订阅_;
};
int 主要(int 参数, 烧焦 * 参数[])
{
rclcpp::启动(参数, 参数);
rclcpp::后旋(标准::共享<;最小订阅者>;());
rclcpp::关闭();
返回 0;
}
3.1 检查代码
订阅者节点的代码与发布者节点几乎完全相同。现在节点被命名为 最小订阅者
,构造函数使用节点的 创建订阅
类来执行回调。
没有计时器,因为订阅者只需在数据发布到 主题
主题。
公:
最小订阅者()
: 节点("minimal_subscriber";)
{
订阅_ = 此->;创建订阅<;std_msgs::信息::字符串>;(
"主题";, 10, 标准::约束(及样品;最小订阅者::topic_callback, 此, _1));
}
回顾 主题教程 发布者和订阅者使用的主题名称和信息类型必须匹配,才能进行通信。
"(《世界人权宣言》) topic_callback
函数接收通过主题发布的字符串消息数据,并使用 RCLCPP_INFO
宏观。
该类中唯一的字段声明是订阅。
私人:
空白 topic_callback(缢 std_msgs::信息::字符串::SharedPtr 信息) 缢
{
RCLCPP_INFO(此->;get_logger(), "我听说:'%s'";, 信息->;数据.c_str());
}
rclcpp::订阅<;std_msgs::信息::字符串>::SharedPtr 订阅_;
"(《世界人权宣言》) 主要
函数完全相同,只不过现在它会旋转 最小订阅者
节点。对发布节点来说,旋转意味着启动定时器,但对订阅节点来说,旋转只是意味着准备随时接收信息。
由于该节点与发布者节点具有相同的依赖关系,因此没有什么新内容需要添加到 package.xml
.
3.2 CMakeLists.txt
重新开放 CMakeLists.txt
并在发布者条目下方为订阅者节点添加可执行文件和目标。
add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp std_msgs)
install(TARGETS
话匣子
听众
DESTINATION lib/${PROJECT_NAME})
确保保存文件,然后您的出版/子系统就可以使用了。
4 构建和运行
您可能已经拥有 rclcpp
和 std_msgs
软件包是 ROS 2 系统的一部分。运行 rosdep
在工作区的根目录 (dev_ws
) 在构建前检查是否缺少依赖项:
rosdep install -i --from-path src --rosdistro <distro> -y
rosdep 只能在 Linux 上运行,因此可以跳到下一步。
rosdep 只能在 Linux 上运行,因此可以跳到下一步。
还是在工作区的根目录下、 dev_ws
, 构建您的新软件包:
colcon build --packages-select cpp_pubsub
打开一个新终端,导航至 dev_ws
并获取设置文件:
install/setup.bash
install/setup.bash
调用 install/setup.bat
现在运行 Talker 节点:
ros2 运行 cpp_pubsub talker
终端应该开始每 0.5 秒发布一次信息,就像这样:
[INFO] [minimal_publisher]:Publishing: "Hello World: 0";
[INFO] [minimal_publisher]:Publishing: "Hello World: 1";
[INFO] [minimal_publisher]:Publishing: "Hello World: 2";
[INFO] [minimal_publisher]:Publishing: "Hello World: 3";
[INFO] [minimal_publisher]:Publishing: "Hello World: 4";
打开另一个终端,从里面获取设置文件的源代码 dev_ws
然后启动监听节点:
ros2 运行 cpp_pubsub 监听器
监听器将开始向控制台打印消息,从发布者当时的消息计数开始,就像这样:
[INFO] [minimal_subscriber]:我听到: "Hello World: 10";
[INFO] [minimal_subscriber]:我听到: "Hello World: 11";
[INFO] [minimal_subscriber]:我听到: "Hello World: 12";
[INFO] [minimal_subscriber]:我听到: "Hello World: 13";
[INFO] [minimal_subscriber]:我听到: "Hello World: 14";
进入 Ctrl+C
以阻止节点旋转。
摘要
您创建了两个节点,用于通过主题发布和订阅数据。在编译和运行它们之前,您在软件包配置文件中添加了它们的依赖项和可执行文件。