ROS笔记三:话题

目录

简要介绍

ROS话题通信机制的一些核心概念和流程:

话题通信的流程如下

ROS常见的topic命令行指令

发布话题

1.创建ROS节点并初始化

 2.创建话题发布者

3.创建消息实例并设置内容

4.将消息发布出去

5.保持节点运行

订阅话题 

初始化ROS节点和创建NodeHandle

创建订阅者并指定回调函数

编写消息回调函数

保持节点运行:

自定义消息类型数据

创建消息文件

在CMakeLists.txt中添加消息依赖

编译和构建

使用自定义消息类型

 注意点


简要介绍

在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. rostopic echo:该命令可以用于打印某个话题的消息内容,从而实时监测该话题的状态和数据。例如,使用rostopic echo /scan可以实时显示激光雷达数据。

  2. rostopic hz:该命令可以用于查看某个话题的发布频率,从而评估系统的性能和稳定性。例如,使用rostopic hz /scan可以显示激光雷达数据的发布频率。

  3. rostopic info:该命令可以用于查看某个话题的详细信息,包括其名称、数据类型、发布者和订阅者等内容。例如,使用rostopic info /scan可以显示激光雷达数据的相关信息。

  4. rostopic list:该命令可以列举出当前ROS系统中所有可用的话题名称,从而方便用户查看和选择特定话题。例如,使用rostopic list可以显示所有可用的话题名称。

  5. rostopic pub:该命令可以用于往某个话题中输入特定的消息内容,从而模拟某些场景下的数据输入。例如,使用rostopic pub /cmd_vel geometry_msgs/Twist "{linear: {x: 0.1}, angular: {z: 0.5}}"可以向/cmd_vel话题发送一个Twist消息。

  6. rostopic bw:该命令可以用于查看某个话题的带宽使用情况,从而评估系统网络和性能瓶颈。例如,使用rostopic bw /scan可以显示激光雷达数据的带宽使用情况。

  7. rostopic find:该命令可以根据数据类型查找符合条件的话题名称,从而方便用户快速定位到特定话题。例如,使用rostopic find std_msgs/String可以查找所有数据类型为std_msgs/String的话题名称。

  8. rostopic type:该命令可以用于查看某个话题的数据类型,从而帮助用户了解该话题所传递的数据结构和内容。例如,使用rostopic type /scan可以显示激光雷达数据的数据类型。

发布话题

发布话题是指将消息发送到特定的话题,以便其他节点可以接收和处理这些消息。话题是一种基于发布-订阅模式的通信机制,它允许不同的节点之间进行异步的消息传递。

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节点中,你需要创建一个话题发布者对象。话题发布者用于将消息发送到特定的话题。你需要指定话题的名称和消息类型作为发布者的参数。

ros::Publisher pub = nh.advertise<消息类型>("话题名称", 队列大小); 

 e.g如果要发布字符串消息到名为/chatter的话题上

ros::Publisher pub = nh.advertise("/chatter", 10);

3.创建消息实例并设置内容

在发布消息之前,需要创建一个对应消息类型的实例,并设置其内容。

消息类型 message;

message.字段 = 值;

 e.g.

对于std_msgs::String消息类型,可以这样创建一个消息实例,并将其内容设置为"Hello, World!":

std_msgs::String message;

message.data = "Hello, World!";

4.将消息发布出去

使用话题发布者的publish()方法将消息发布到指定的话题上。

pub.publish(message);

5.保持节点运行

在发布消息后,一般需要调用ros::spin()或者ros::spinOnce()来保持节点处于运行状态,以便能够发送消息并接收其他节点发送的消息。

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<消息类型>("话题名称", 队列大小, 回调函数)方法创建一个订阅者,指定要订阅的消息类型、话题名称、队列大小以及接收到消息时要调用的回调函数。

 ros::Subscriber sub = nh.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.txtcatkin_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;
}

 上述将package_name替换为你的自定义消息所在的软件包名。CustomMessage是自定义消息类型的名称,需要根据实际情况进行替换。

确保在使用自定义消息之前,已经运行了catkin_make命令来编译和构建ROS软件包,以便让ROS能够正确识别和使用自定义消息类型。

 注意点

在使用自定义消息之前,要确保订阅者和发布者都使用了相同的自定义消息类型,并且正确地引用了消息类型的头文件。

你可能感兴趣的:(ROS,笔记,人工智能,机器人,ROS)