ROS学习笔记一:publishers and subscribers

ROS学习笔记一:publishers and subscribers

个人把ROS看做是一种通信机制的框架,围绕着三种通信机制有很多其他的功能,核心还是三种通信机制

  • publishers/subscribers
  • services/clients
  • action-servers/action-clients

为了确保这种通信机制能够顺利运行,引入了nodes、topic和messages等等的概念,使得这种通信机制更具逻辑性以及便于理解。

在ROS框架下,可以把一个大项目分成若干个小部分,让不同的人去完成,最后通过ROS这个框架,将每个人负责完成的那部分作为一个node,通过在topic上发布和订阅messages,这就实现了各个nodes之间的通信,将各个node连接起来,组合完成这个项目。

一.publishers/subscribers

一个node既可以是publishers也可以是subscribers,可以同时发布topic的信息,也可以订阅topic上的信息,这里面有一个很重要的特性,一个subscriber只需要知道它要订阅的那个topic的名称,并不需要准确知道是哪一个publisher发布的这个topic,同样的,一个publisher也只管发布topic的消息就行了,不用管谁会来订阅这个topic上的信息,一个subscriber可以订阅很多个topic上的信息。

信息发布的间隔是不确定的,所以subscribers有可能会错过这个消息,这种通信机制比较适合重复的消息,比如产生的某种传感器的数值。

以下是一个publisher节点的代码:

#include <ros/ros.h> //惯例第一头文件,ROS的源码
#include <std_msgs/Float64.h> //传递的消息类型文件,根据实际需要选择对应的消息类型头文件 

int main(int argc, char **argv) {  //每一个节点只有一个main函数
    ros::init(argc, argv, "minimal_publisher2"); // 初始化这个节点, 双引号中的是节点名, 可以通过.launch文件启动时更改节点名(不建议)
    ros::NodeHandle n; // 创建一个与ROS系统对话的pulisher对象(n是随意命名的)
    ros::Publisher my_publisher_object = n.advertise<std_msgs::Float64>("topic1", 1); 
    //创建一个发布消息类型为std_msgs::Float64的topic(即topic1)的对象(即my_publisher_object)
    //这里定义了发布topic的名称,其他subscribers想要订阅这个topic的信息只需要知道这个topic的名字是topic1就可以了
    //参数1是指queue size,可以理解为通道大小,一般设置为1,即传递的信息是1个接着1个,不是多个齐头并进传输到subscribers处的    
    
    std_msgs::Float64 input_float; //定义了一个以std_msgs::Float64为消息类型的变量
    //任何发布到topic上的信息都必须要定义好对应的格式,这样subscribers才知道怎么去解读这个信息
 
   
   ros::Rate naptime(1.0); //设置发布信息的间隔时间,如果不设置,系统会尽全力去输出,有多快就多快的去发布信息,很多时候是没必要的,浪费CPU
   //还要在while循环里加上naptime.sleep(); 这样就完成了间隔时间的设定

    input_float.data = 0.0;初始化变量input_float的值
   
    while (ros::ok()) 
    {
        input_float.data = input_float.data + 0.001; //变量以0.001的速度迭代增长
        my_publisher_object.publish(input_float); // 在topic上发布变量(input_float)的数值信息

    naptime.sleep(); 与ros::Rate naptime(1.0)对应,设置间隔时间
    }
}



以下是一个subscriber节点的代码:

#include<ros/ros.h>  //惯例第一头文件,ROS的源码
#include<std_msgs/Float64.h> //传递的消息类型文件,根据实际需要选择对应的消息类型头文件
void myCallback(const std_msgs::Float64& message_holder) //subscriber节点与publishers节点有一个很大不同就是需要有一个回调函数即callback function
{ 
  //函数中的std_msgs::Float64是topic1的信息类型,并把接收到的信息储存在参数message_holder中
  // 每当有信息发布到topic1上,就会激活回调函数,很多工作都是在回调函数中进行的,main函数中一般都是获取最后的结果 
  ROS_INFO("received value is: %f",message_holder.data); 
  //ROS_INFO跟cout和printf很像,但在ROS中要优于cout和prinf,它发布的消息会被记录或监测,可以通过rosbag这个指令来对被记录的数据进行回放
} 

int main(int argc, char **argv) 
{ 
  ros::init(argc,argv,"minimal_subscriber"); //初始化,命名这个subscriber节点
  ros::NodeHandle n; // 创建一个与topic1通信的对象,订阅topic上的信息
  
  ros::Subscriber my_subscriber_object= n.subscribe("topic1",1,myCallback); 
  //这个跟publisher很像,但是需要在queue size后面加上回调函数名

  ros::spin(); //callback函数需要时间响应,所以加入ros::spin()只有当callback函数完成计算后才会进行下一个运算周期,这个时候main函数会被暂停,而callback函数不受影响
  return 0; //一般不会运行到这里,除了roscore被kill
} 

最后要整个包编译成功,还需要

  1. 在package.xml文件中添加相应的依赖项和包
  2. 在CMakeLists.txt中添加生成可执行文件的命令行及其依赖的库文件

最后通过rosrun分别在两个terminal中运行两个node,再通过rqt_graph查看两节点的关系


二.ROS Tools:

常用的指令

常用指令说明
rosnode list查看所有激活的节点
rostopic list查看所有激活的topic
rostopic info <topic name>可以查看topic的调用信息类型,还有它的发布者以及订阅者
rostopic echo <topic name>查看对应topic发布的消息
rqt_graph以图像的形式表现整个正在运行的ROS系统
rqt_plot velocity/data以二维图的形式查看topic的输出
rosmsg show package/messageName例如:rosmsg show std_msgs/Float64 查看对应的消息类型
rosrun <packagename> <node name>运行包中的节点(编译成功后才能运行)
roslaunch <package name> <launch file>启动.launch文件
catkin_make进入到工作区间后,执行会编译所有的包
catkin_make -DCATKIN_WHITELIST_PACKAGES=package编译指定的包


边学边总结吧,有新的理解再更新,欢迎多多交流学习,共同进步。

### ROS2 C++ Topic Communication Learning Materials and Tutorials For those interested in exploring how to use topics for communication within the ROS2 framework using C++, several resources provide comprehensive guidance on this subject. The official documentation of ROS 2 offers an extensive tutorial that covers setting up publishers and subscribers with detailed explanations and code examples written in C++. This resource is invaluable as it not only explains the theory but also provides practical steps necessary to establish topic-based communications between nodes[^1]. Additionally, a popular choice among developers includes tutorials available from Robot Ignite Academy which presents step-by-step instructions alongside video demonstrations specifically tailored towards understanding message passing through topics via C++ interfaces in ROS2 environments. These sessions are designed to cater both beginners who need foundational knowledge about ROS concepts along with more advanced users looking into optimizing their applications' performance when dealing with real-time data exchange over networks. Another noteworthy mention goes out to Open Robotics’ own set of educational materials where one can find well-documented samples illustrating various aspects related to working with messages across different programming languages including C++; these documents often include best practices recommendations ensuring efficient utilization while adhering closely to community standards established around ROS ecosystem development processes. ```cpp // Example Code Snippet Demonstrating Basic Publisher Node Implementation Using rclcpp Library In C++ #include "rclcpp/rclcpp.hpp" using namespace std::chrono_literals; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("example_publisher"); auto publisher = node->create_publisher<std_msgs::msg::String>("topic", 10); auto msg = std_msgs::msg::String(); msg.data = "Hello, world!"; rclcpp::WallRate loop_rate(1s); // Publish every second while (rclcpp::ok()) { RCLCPP_INFO(node->get_logger(), "Publishing: '%s'", msg.data.c_str()); publisher->publish(msg); rclcpp::spin_some(node); loop_rate.sleep(); } rclcpp::shutdown(); } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值