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() 区别及详解相关推荐

  1. ros::spin() 和 ros::spinOnce() 区别及用法

    1 函数意义 ros::spin() 和 ros::spinOnce() 是ROS消息回调处理函数.它俩通常会出现在ROS的主循环中,程序需要不断调用ros::spin() 或 ros::spinOn ...

  2. ros::spin() 和 ros::spinOnce()

    ROS的回调处理函数spin/spinOnce 作用 区别 使用 作用 spin/spinOnce是ROS消息回调处理函数.它俩通常会出现在ROS的主循环中,程序需要不断调用ros::spin() 或 ...

  3. 【ROS进阶】常用函数——ros::ok(),ros::Rate,ros::spin()和ros::spinOnce()

    (一)ros::ok() 用于检查系统状态,适用于在while循环中判断状态 语法: while(ros::ok()) {//... } ros::ok()在以下几种情况下会返回false: 1.按下 ...

  4. ROS入门笔记(七):详解ROS文件系统

    ROS入门笔记(七):详解ROS文件系统 文章目录 01 Catkin编译系统 1.1 Catkin特点 1.2 Catkin工作原理 1.3 使用`catkin_make`进行编译 02 Catki ...

  5. python时间函数报错_python3中datetime库,time库以及pandas中的时间函数区别与详解...

    1介绍datetime库之前 我们先比较下time库和datetime库的区别 先说下time 在 Python 文档里,time是归类在Generic Operating System Servic ...

  6. python获取系统时间函数_python3中datetime库,time库以及pandas中的时间函数区别与详解...

    1介绍datetime库之前 我们先比较下time库和datetime库的区别 先说下time 在 Python 文档里,time是归类在Generic Operating System Servic ...

  7. 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...

    超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...

  8. 操作系统 - 进程与线程的区别[超详解]

    操作系统 - 进程与线程的区别[超详解]面试高频考题

  9. C++中数组和指针的关系(区别)详解

    C++中数组和指针的关系(区别)详解 本文转自:http://c.biancheng.net/view/1472.html 博主在阅读后将文中几个知识点提出来放在前面: 没有方括号和下标的数组名称实际 ...

最新文章

  1. 基于stm32f405控制三相无刷电机例程_无刷电机确定霍尔传感器位置的通用方法
  2. android--创建自己的内容提供器
  3. python profile_python程序之profile分析
  4. setup.s 分析—— Linux-0.11 学习笔记(二)
  5. Netgear wndr3700v2 路由器刷OpenWrt打造全能服务器(五)SVN服务
  6. R开发(part1)--R语言知识体系结构
  7. C++ 包含目录、库目录、附加依赖项总结
  8. Linux 下 Oracle 内核参数优化
  9. 在Oracle中添加用户登录名称
  10. 2017.6.28 文艺平衡树 思考记录
  11. php 获取子类的方法名,php获取分类下的所有子类方法
  12. 大学计算机基础课学几年,大学计算机基础类课程教学(2017年开始)-杭州师范大学计算机教育与.PDF...
  13. c语言的高级编程,C语言高级编程
  14. Uploadify—借助Uploadify插件实现图片预览时如何解决Chrome浏览器报“喔唷,崩溃啦”
  15. R与RStudio的详细安装教程(有每一步的详细教程!!!!)
  16. 图灵奖得主Alan Kay如何读书
  17. 各种调制方式OFDM(QPSK,16QAM,64QAM)系统性能仿真
  18. 佳博GP2120TU标签打印机 安装和使用教程(PC)
  19. C-COT跟踪算法在OTB数据集上测试的接口函数
  20. 简化企业组网 H3C S1224F以太网交换机评测

热门文章

  1. 解决“此图片来自微信公众平台未经允许不可引用”的方法
  2. 如何在python中识别未知的日期时区时区
  3. oracle存储格式化时间,ORACLE日期时间的格式化参数大全
  4. TCP方式的网络通信【聊天器示例】
  5. linux 内核参数分析,linux 内核参数VM调优 之 参数调节和场景分析
  6. 蓝牙:深入浅出低功耗蓝牙(BLE)协议栈
  7. android 面向对象,android 面向对象六大原则
  8. java线程属性_Java 并发 线程属性
  9. fastdfs中浏览器访问获取不到文件_SpringBoot 2.0 开发案例之整合FastDFS分布式文件系统...
  10. L1-026 I Love GPLT