ROS2 话题
ROS2 中节点通过发布和订阅话题来传递信息,一个节点可以作为发布者发布信息,也可以同时作为订阅者订阅其它节点发布的话题。
话题由主题和消息类型组成:
- 主题是一个字符串
- 消息类型是传输数据的格式
话题查看
启动小海龟节点
1ros2 run turtlesim turtlesim_node查看小海龟节点信息
1ros2 node info /turtlesim可以看到 node 的相关信息
1 2 3 4 5 6 7 8 9/turtlesim Subscribers: /parameter_events: rcl_interfaces/msg/ParameterEvent /turtle1/cmd_vel: geometry_msgs/msg/Twist Publishers: /parameter_events: rcl_interfaces/msg/ParameterEvent /rosout: rcl_interfaces/msg/Log /turtle1/color_sensor: turtlesim/msg/Color /turtle1/pose: turtlesim/msg/PoseSubscribers 列出节点订阅了哪些话题,前面为主题,后面为话题消息类型,Publishers 列出发布哪些话题
查看一个话题信息
1ros2 topic info /turtle1/cmd_vel显示出数据类型,发布者数量,被订阅的数量
查看消息类型的详细定义
1ros2 interface show geometry_msgs/msg/Twist可以看到消息类型为两个数组,第一个为线速度,第二个为角速度
使用 ros2 命令发布话题消息
1ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0, y: 0.0}, angular: {z: 1.0}}"
C++ 发布话题
用 C++ 实现每秒发布一个字符串
创建功能包
1ros2 pkg create cpp_topic_publish_demo --destination-directory src --build-type ament_cmake --dependencies rclcpp std_msgs --license Apache-2.0新建节点,每秒发布字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36#include "rclcpp/node.hpp" #include "rclcpp/executors.hpp" #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; class TopicPublishDemo : public rclcpp::Node { public: TopicPublishDemo(): Node("topic_publish_demo_node"), count_(0) { publisher_ = create_publisher<std_msgs::msg::String>("topic_string", 10); auto timer_callback = [this]() { auto msg = std_msgs::msg::String(); msg.data = "Hello, Now is " + std::to_string(count_++); RCLCPP_INFO(get_logger(), "Publishing: %s", msg.data.c_str()); publisher_->publish(msg); }; timer_ = create_wall_timer(1s, timer_callback); } private: rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; size_t count_; }; int main(int argc, char* argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<TopicPublishDemo>()); rclcpp::shutdown(); return 0; }
C++ 订阅话题
创建功能包
节点订阅代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28#include "rclcpp/node.hpp" #include "rclcpp/executors.hpp" #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; class TopicSubscribeDemo : public rclcpp::Node { public: TopicSubscribeDemo(): Node("topic_subscribe_demo_node") { auto topic_callback = [this](std_msgs::msg::String::UniquePtr msg) { RCLCPP_INFO(get_logger(), "I received: %s", msg->data.c_str()); }; subscriber_ = create_subscription<std_msgs::msg::String>("topic_string", 10, topic_callback); } private: rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscriber_; }; int main(int argc, char* argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<TopicSubscribeDemo>()); rclcpp::shutdown(); return 0; }
自定义消息类型
创建一个功能包,用来定义消息类型
1ros2 pkg create --destination-directory=src --build-type=ament_cmake --license Apache-2.0 --dependencies std_msgs demo_interfaces在包根目录下新建一个 msg 目录,里面创建一个 Demo.msg 文件
1std_msgs/String name在 CMakeLists.txt 中添加以下代码
在 package.xml 中添加以下代码
使用
colcon build编译
使用自定义消息
将前面的 publish 和 subscribes 改成使用自定义消息
在 package.xml 中添加依赖
1<depend>demo_interfaces</depend>在
CMakeLists.txt中添加依赖
- 将原来的
std_msgs::msg::String改为demo_interface::msg::Demo1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28#include "rclcpp/node.hpp" #include "rclcpp/executors.hpp" #include "demo_interfaces/msg/demo.hpp" using namespace std::chrono_literals; class TopicSubscribeDemo : public rclcpp::Node { public: TopicSubscribeDemo(): Node("topic_subscribe_demo_node") { auto topic_callback = [this](demo_interfaces::msg::Demo::UniquePtr msg) { RCLCPP_INFO(get_logger(), "I received: %s", msg->name.data.c_str()); }; subscriber_ = create_subscription<demo_interfaces::msg::Demo>("topic_string", 10, topic_callback); } private: rclcpp::Subscription<demo_interfaces::msg::Demo>::SharedPtr subscriber_; }; int main(int argc, char* argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<TopicSubscribeDemo>()); rclcpp::shutdown(); return 0; }