目录
简要介绍
在ROS中,话题(topics)是最常用的通信机制之一,它允许节点之间以异步的方式进行消息的发布和订阅。一个节点可以发布某个话题的消息,而其他节点则可以订阅该话题以接收相应的消息。
话题通信机制是一种:一(发布者)对多(订阅者)、异步的通信机制
ROS话题通信机制的一些核心概念和流程:
1.消息类型(Message type):在ROS中,每个话题都有一个特定的消息类型,该消息类型定义了该话题所传递的数据结构和内容。例如,一个表示激光雷达扫描数据的消息类型可能包括激光雷达的位置、角度、距离等信息。
2.发布者(Publisher):发布者是一个ROS节点,它可以将特定消息类型的数据发布到某个话题中,其他节点可以通过订阅该话题来接收该消息。一个节点可以同时作为多个话题的发布者。
3.订阅者(Subscriber):订阅者是一个ROS节点,它可以从某个话题中接收特定消息类型的数据,从而实现对该话题的订阅。一个节点可以同时订阅多个话题。
4.话题名称(Topic name):话题名称是一个字符串,用来标识某个话题在ROS系统中的唯一性。在进行订阅或发布操作时,节点需要指定要订阅或发布的话题名称。
5.消息队列(Message queue):消息队列是一个缓存区,用来存储已发布但未被订阅者接收的消息。当节点订阅某个话题时,如果该话题之前已经有消息发布,那么这些消息会首先被放入消息队列中,等待订阅者进行接收。
话题通信的流程如下
1.发布者创建一个话题,并将特定消息类型的数据发布到该话题中。
2.订阅者订阅特定话题,等待接收该话题中的消息。
3.如果在订阅者订阅之前已经有消息发布到该话题中,那么这些消息会被放入消息队列中,等待订阅者进行接收。
4.当发布者发布新的消息时,订阅者会收到该消息并进行处理。
ROS常见的topic命令行指令
发布话题
发布话题是指将消息发送到特定的话题,以便其他节点可以接收和处理这些消息。话题是一种基于发布-订阅模式的通信机制,它允许不同的节点之间进行异步的消息传递。
1.创建ROS节点并初始化
在开始发布消息之前,需要先创建一个ROS节点,并进行初始化。这个节点将负责发布消息到指定的话题。
#include "ros/ros.h"
int main(int argc, char **argv)
{
// 初始化ROS节点
ros::init(argc, argv, "publisher_node");
// 创建NodeHandle对象
ros::NodeHandle nh;
// 在这里编写发布者的代码
return 0;
}
2.创建话题发布者
在ROS节点中,你需要创建一个话题发布者对象。话题发布者用于将消息发送到特定的话题。你需要指定话题的名称和消息类型作为发布者的参数。
e.g如果要发布字符串消息到名为/chatter
的话题上
ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter", 10);
3.创建消息实例并设置内容
在发布消息之前,需要创建一个对应消息类型的实例,并设置其内容。
4.将消息发布出去
使用话题发布者的publish()
方法将消息发布到指定的话题上。
5.保持节点运行
在发布消息后,一般需要调用ros::spin()
或者ros::spinOnce()
来保持节点处于运行状态,以便能够发送消息并接收其他节点发送的消息。
订阅话题
订阅者(Subscriber)用于接收和处理其他节点发布的消息。订阅者通过订阅特定的话题来接收消息,并在接收到消息后执行相应的回调函数进行处理。下面是订阅话题的详细步骤:
初始化ROS节点和创建NodeHandle
在开始订阅消息之前,首先需要初始化ROS节点并创建一个NodeHandle对象。
#include "ros/ros.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "subscriber_node");
ros::NodeHandle nh;
// 在这里编写订阅者的代码
ros::spin(); // 保持节点运行
return 0;
}
创建订阅者并指定回调函数
使用NodeHandle对象的subscribe<消息类型>("话题名称", 队列大小, 回调函数)
方法创建一个订阅者,指定要订阅的消息类型、话题名称、队列大小以及接收到消息时要调用的回调函数。
e.g如果要订阅名为/chatter
的字符串消息,可以这样创建订阅者:
void messageCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("Received message: %s", msg->data.c_str());
}
ros::Subscriber sub = nh.subscribe("/chatter", 10, messageCallback);
编写消息回调函数
消息回调函数是在接收到消息时被调用的函数,用于处理接收到的消息数据。
void messageCallback(const 消息类型::ConstPtr& msg)
{
// 处理接收到的消息
}
保持节点运行:
最后,在订阅消息后,通常需要调用ros::spin()
或者ros::spinOnce()
来保持节点处于运行状态,以便接收和处理消息。
完整的订阅者代码:
#include "ros/ros.h"
#include "std_msgs/String.h"
void messageCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("Received message: %s", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "subscriber_node");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("/chatter", 10, messageCallback);
ros::spin();
return 0;
}
自定义消息类型数据
创建消息文件
使用ROS消息描述语言(Message Description Language,简称msg)创建一个消息文件,该文件定义了自定义消息的结构和字段。通常,消息文件位于msg
文件夹中。
e.g创建一个名为CustomMessage.msg
的消息文件,其中包含一个字符串字段data
string data
在CMakeLists.txt
中添加消息依赖
在ROS软件包的CMakeLists.txt
文件中添加对自定义消息的依赖项。
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation # 添加这行
)
add_message_files(
FILES
CustomMessage.msg # 添加你创建的消息文件
)
generate_messages(
DEPENDENCIES
std_msgs
)
确保在CMakeLists.txt
的catkin_package()
函数之前添加了message_generation
依赖。
编译和构建
运行catkin_make
命令编译和构建ROS软件包。
cd catkin_ws
catkin_make
使用自定义消息类型
在代码中使用自定义消息类型,包括订阅者和发布者。
#include "ros/ros.h"
#include "package_name/CustomMessage.h" // 替换成你的自定义消息类型
void messageCallback(const package_name::CustomMessage::ConstPtr& msg)
{
ROS_INFO("Received message: %s", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "subscriber_node");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("/chatter", 10, messageCallback);
ros::spin();
return 0;
}
注意点
在使用自定义消息之前,要确保订阅者和发布者都使用了相同的自定义消息类型,并且正确地引用了消息类型的头文件。