ros::spin() 和 ros::spinOnce() 区别及详解
1 函数意义
首先要知道,这俩兄弟学名叫ROS消息回调处理函数。它俩通常会出现在ROS的主循环中,程序需要不断调用ros::spin() 或 ros::spinOnce(),两者区别在于前者调用后不会再返回,也就是你的主程序到这儿就不往下执行了,而后者在调用后还可以继续执行之后的程序。
其实消息回调处理函数的原理非常简单。我们都知道,ROS存在消息发布订阅机制,什么?不知道?不知道还不快去:http://wiki.ros.org/ROS/Tutorials (ROS官方基础教程) 瞅瞅。
好,我们继续,如果你的程序写了相关的消息订阅函数,那么程序在执行过程中,除了主程序以外,ROS还会自动在后台按照你规定的格式,接受订阅的消息,但是所接到的消息并不是立刻就被处理,而是必须要等到ros::spin()或ros::spinOnce()执行的时候才被调用,这就是消息回到函数的原理,怎么样,简单吧,至于为什么这么设计?咳咳,嗯,肯定有他的道理。。。
2 区别
就像上面说的,ros::spin() 在调用后不会再返回,也就是你的主程序到这儿就不往下执行了,而 ros::spinOnce() 后者在调用后还可以继续执行之后的程序。
其实看函数名也能理解个差不多,一个是一直调用;另一个是只调用一次,如果还想再调用,就需要加上循环了。
这里一定要记住,ros::spin()函数一般不会出现在循环中,因为程序执行到spin()后就不调用其他语句了,也就是说该循环没有任何意义,还有就是spin()函数后面一定不能有其他语句(return 0 除外),有也是白搭,不会执行的。ros::spinOnce()的用法相对来说很灵活,但往往需要考虑调用消息的时机,调用频率,以及消息池的大小,这些都要根据现实情况协调好,不然会造成数据丢包或者延迟的错误。
3 常见使用方法
这里需要特别强调一下,如果大兄弟你的程序写了相关的消息订阅函数,那千万千万千万不要忘了在相应位置加上ros::spin()或者ros::spinOnce()函数,不然你是永远都得不到另一边发出的数据或消息的,博主血的教训,万望紧记。。。
3.1 ros::spin()
ros::spin()函数用起来比较简单,一般都在主程序的最后,加入该语句就可。例子如下:
订阅端:
#include "ros/ros.h"
#include "std_msgs/String.h"void chatterCallback(const std_msgs::String::ConstPtr& msg)
{ROS_INFO("I heard: [%s]", msg->data.c_str());
}int main(int argc, char **argv)
{ros::init(argc, argv, "listener");ros::NodeHandle n;ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);/*** ros::spin() 将会进入循环, 一直调用回调函数chatterCallback(),每次调用1000个数据。* 当用户输入Ctrl+C或者ROS主进程关闭时退出,*/ros::spin();return 0;
}
发送端:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>int main(int argc, char **argv)
{ros::init(argc, argv, "talker");ros::NodeHandle n;ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);ros::Rate loop_rate(10);int count = 0;while (ros::ok()){std_msgs::String msg;std::stringstream ss;ss << "hello world " << count;msg.data = ss.str();ROS_INFO("%s", msg.data.c_str());/*** 向 Topic: chatter 发送消息, 发送频率为10Hz(1秒发10次);消息池最大容量1000。*/chatter_pub.publish(msg);loop_rate.sleep();++count;}return 0;
}
3.2 ros::spinOnce()
对于ros::spinOnce()的使用,虽说比ros::spin()更自由,可以出现在程序的各个部位,但是需要注意的因素也更多。比如:
1 对于有些传输特别快的消息,尤其需要注意合理控制消息池大小和ros::spinOnce()执行频率; 比如消息送达频率为10Hz, ros::spinOnce()的调用频率为5Hz,那么消息池的大小就一定要大于2,才能保证数据不丢失,无延迟。
/**接收端**/
#include "ros/ros.h"
#include "std_msgs/String.h"void chatterCallback(const std_msgs::String::ConstPtr& msg)
{/*...TODO...*/
}int main(int argc, char **argv)
{ros::init(argc, argv, "listener");ros::NodeHandle n;ros::Subscriber sub = n.subscribe("chatter", 2, chatterCallback);ros::Rate loop_rate(5);while (ros::ok()){/*...TODO...*/ ros::spinOnce();loop_rate.sleep();}return 0;
}
2 ros::spinOnce()用法很灵活,也很广泛,具体情况需要具体分析。但是对于用户自定义的周期性的函数,最好和ros::spinOnce并列执行,不太建议放在回调函数中;
/*...TODO...*/
ros::Rate loop_rate(100);while (ros::ok())
{/*...TODO...*/user_handle_events_timeout(...);ros::spinOnce(); loop_rate.sleep();
}
3. spinOnce( )较常用的做法是while里放publisher所要发布的msg的赋值处理,然后一直循环发布topic。
ros::Rate loop_rate(10);while (ros::ok()){std_msgs::String msg;std::stringstream ss;ss << "hello world " << count;msg.data = ss.str();chatter_pub.publish(msg);ros::spinOnce();loop_rate.sleep();}
ros::spin() 和 ros::spinOnce() 区别及详解相关推荐
- ros::spin() 和 ros::spinOnce() 区别及用法
1 函数意义 ros::spin() 和 ros::spinOnce() 是ROS消息回调处理函数.它俩通常会出现在ROS的主循环中,程序需要不断调用ros::spin() 或 ros::spinOn ...
- ros::spin() 和 ros::spinOnce()
ROS的回调处理函数spin/spinOnce 作用 区别 使用 作用 spin/spinOnce是ROS消息回调处理函数.它俩通常会出现在ROS的主循环中,程序需要不断调用ros::spin() 或 ...
- 【ROS进阶】常用函数——ros::ok(),ros::Rate,ros::spin()和ros::spinOnce()
(一)ros::ok() 用于检查系统状态,适用于在while循环中判断状态 语法: while(ros::ok()) {//... } ros::ok()在以下几种情况下会返回false: 1.按下 ...
- ROS入门笔记(七):详解ROS文件系统
ROS入门笔记(七):详解ROS文件系统 文章目录 01 Catkin编译系统 1.1 Catkin特点 1.2 Catkin工作原理 1.3 使用`catkin_make`进行编译 02 Catki ...
- python时间函数报错_python3中datetime库,time库以及pandas中的时间函数区别与详解...
1介绍datetime库之前 我们先比较下time库和datetime库的区别 先说下time 在 Python 文档里,time是归类在Generic Operating System Servic ...
- python获取系统时间函数_python3中datetime库,time库以及pandas中的时间函数区别与详解...
1介绍datetime库之前 我们先比较下time库和datetime库的区别 先说下time 在 Python 文档里,time是归类在Generic Operating System Servic ...
- 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...
超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...
- 操作系统 - 进程与线程的区别[超详解]
操作系统 - 进程与线程的区别[超详解]面试高频考题
- C++中数组和指针的关系(区别)详解
C++中数组和指针的关系(区别)详解 本文转自:http://c.biancheng.net/view/1472.html 博主在阅读后将文中几个知识点提出来放在前面: 没有方括号和下标的数组名称实际 ...
最新文章
- 基于stm32f405控制三相无刷电机例程_无刷电机确定霍尔传感器位置的通用方法
- android--创建自己的内容提供器
- python profile_python程序之profile分析
- setup.s 分析—— Linux-0.11 学习笔记(二)
- Netgear wndr3700v2 路由器刷OpenWrt打造全能服务器(五)SVN服务
- R开发(part1)--R语言知识体系结构
- C++ 包含目录、库目录、附加依赖项总结
- Linux 下 Oracle 内核参数优化
- 在Oracle中添加用户登录名称
- 2017.6.28 文艺平衡树 思考记录
- php 获取子类的方法名,php获取分类下的所有子类方法
- 大学计算机基础课学几年,大学计算机基础类课程教学(2017年开始)-杭州师范大学计算机教育与.PDF...
- c语言的高级编程,C语言高级编程
- Uploadify—借助Uploadify插件实现图片预览时如何解决Chrome浏览器报“喔唷,崩溃啦”
- R与RStudio的详细安装教程(有每一步的详细教程!!!!)
- 图灵奖得主Alan Kay如何读书
- 各种调制方式OFDM(QPSK,16QAM,64QAM)系统性能仿真
- 佳博GP2120TU标签打印机 安装和使用教程(PC)
- C-COT跟踪算法在OTB数据集上测试的接口函数
- 简化企业组网 H3C S1224F以太网交换机评测
热门文章
- 解决“此图片来自微信公众平台未经允许不可引用”的方法
- 如何在python中识别未知的日期时区时区
- oracle存储格式化时间,ORACLE日期时间的格式化参数大全
- TCP方式的网络通信【聊天器示例】
- linux 内核参数分析,linux 内核参数VM调优 之 参数调节和场景分析
- 蓝牙:深入浅出低功耗蓝牙(BLE)协议栈
- android 面向对象,android 面向对象六大原则
- java线程属性_Java 并发 线程属性
- fastdfs中浏览器访问获取不到文件_SpringBoot 2.0 开发案例之整合FastDFS分布式文件系统...
- L1-026 I Love GPLT