目录
1.创建节点
在home下新建一个ros_topics的文件夹
mkdir ros_topics
依次输入下面的命令,创建chapt3_ws工作空间、example_topic_rclcpp功能包和topic_publisher_01.cpp
cd ros_topics/
mkdir -p chapt3/chapt3_ws/src
cd chapt3/chapt3_ws/src
ros2 pkg create example_topic_rclcpp --build-type ament_cmake --dependencies rclcpp
touch example_topic_rclcpp/src/topic_publisher_01.cpp
2.编写发布与订阅节点
2.1 发布节点(topic_publisher_01.cpp)
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <serial/serial.h>
class TopicPublisher01 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
TopicPublisher01(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "大家好,我是%s.", name.c_str());
// 创建发布者
command_publisher_ = this->create_publisher<std_msgs::msg::String>("rostopic", 10);
// 创建定时器,500ms为周期,定时发布
timer_ = this->create_wall_timer(std::chrono::milliseconds(500), std::bind(&TopicPublisher01::timer_callback, this));
}
private:
void timer_callback()
{
// 创建消息
std_msgs::msg::String message;
message.data = "NUIST-CURRY";
// 日志打印
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
// 发布消息
command_publisher_->publish(message);
}
// 声名定时器指针
rclcpp::TimerBase::SharedPtr timer_;
// 声明话题发布者指针
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr command_publisher_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
/*产生一个的节点*/
auto node = std::make_shared<TopicPublisher01>("topic_publisher_01");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
2.2 订阅节点(topic_subscribe_01.cpp)
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <serial/serial.h>
class TopicSubscribe01 : public rclcpp::Node
{
public:
TopicSubscribe01(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "大家好,我是%s.", name.c_str());
// 创建一个订阅者订阅话题
command_subscribe_ = this->create_subscription<std_msgs::msg::String>("rostopic", 10, std::bind(&TopicSubscribe01::command_callback, this, std::placeholders::_1));
}
private:
// 声明一个订阅者
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr command_subscribe_;
// 收到话题数据的回调函数
void command_callback(const std_msgs::msg::String::SharedPtr msg)
{
double speed = 0.0f;
if(msg->data == "NUIST-CURRY")
{
speed = 0.2f;
}
RCLCPP_INFO(this->get_logger(), "收到[%s]指令,发送速度 %f", msg->data.c_str(),speed);
};
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
/*产生一个的节点*/
auto node = std::make_shared<TopicSubscribe01>("topic_subscribe_01");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
2.3 修改CmakeLists.txt及package.xml
CmakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(example_topic_rclcpp)
# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()
# Default to 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 dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# uncomment the line when a copyright and license is not present in all source files
#set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(topic_publisher_01 src/topic_publisher_01.cpp)
ament_target_dependencies(topic_publisher_01 rclcpp std_msgs)
add_executable(topic_subscribe_01 src/topic_subscribe_01.cpp)
ament_target_dependencies(topic_subscribe_01 rclcpp std_msgs)
#add_executable(topic_subscribe_02 src/topic_subscribe_02.cpp)
#ament_target_dependencies(topic_subscribe_02 rclcpp std_msgs)
#add_executable(topic_subscribe_03 src/topic_subscribe_03.cpp)
#ament_target_dependencies(topic_subscribe_03 rclcpp std_msgs)
#add_executable(topic_subscribe_04 src/topic_subscribe_04.cpp)
#ament_target_dependencies(topic_subscribe_04 rclcpp std_msgs)
install(TARGETS
topic_subscribe_01
#topic_subscribe_02
#topic_subscribe_03
#topic_subscribe_04
topic_publisher_01
DESTINATION lib/${PROJECT_NAME}
)
package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>example_topic_rclcpp</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="wjf@todo.todo">wjf</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
3.话题发布与订阅运行测试
3.1重开一个终端,启动发布节点
cd chapt3/chapt3_ws/
source install/setup.bash
ros2 run example_topic_rclcpp topic_subscribe_01
3.2再开一个终端,启动订阅节点
cd chapt3/chapt3_ws/
source install/setup.bash
ros2 run example_topic_rclcpp topic_publisher_01
4.运行结果
发布者发布NUIST-CURRY
,订阅者订阅并将其打印出来。
5.一个发布多个订阅
需要对CmakeLists.txt
进行修改,如下:
ament_package()
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(topic_publisher_01 src/topic_publisher_01.cpp)
ament_target_dependencies(topic_publisher_01 rclcpp std_msgs)
add_executable(topic_subscribe_01 src/topic_subscribe_01.cpp)
ament_target_dependencies(topic_subscribe_01 rclcpp std_msgs)
add_executable(topic_subscribe_02 src/topic_subscribe_02.cpp)
ament_target_dependencies(topic_subscribe_02 rclcpp std_msgs)
add_executable(topic_subscribe_03 src/topic_subscribe_03.cpp)
ament_target_dependencies(topic_subscribe_03 rclcpp std_msgs)
add_executable(topic_subscribe_04 src/topic_subscribe_04.cpp)
ament_target_dependencies(topic_subscribe_04 rclcpp std_msgs)
install(TARGETS
topic_subscribe_01
topic_subscribe_02
topic_subscribe_03
topic_subscribe_04
topic_publisher_01
DESTINATION lib/${PROJECT_NAME}
)
5.1测试结果
如图所示,我们创建了一个发布节点/topic_publisher_01
和四个订阅节点/topic_subscribe_01
、/topic_subscribe_02
、/topic_subscribe_03
、/topic_subscribe_04
。话题均为/rostopic
,发布者发布在话题上的消息可以由四个订阅者同时订阅,此次实验成功。