ROS的单线程Spinning和多线程Spinning

单线程Spinning

ros::spin()是最简单的单线程自旋, 它会一直调用直到结束

用法:  ros::spin();

另一个单线程spinning是ros::spinOnce(),它定期调用等待在那个点上的所有回调

用法:  ros::spinOnce();

简单的我们自己实现一个用法相同的ros::spin()

这样:  ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));

ros::spinonce

这样:  ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));


以上,是它的基础用法,那么spin到底做了什么呢?

首先, 当我们调用ros::spin时, 会有一个互斥锁, 把你的回调队列加锁, 防止执行混乱. 

然后, 检测如果回调队列不为空, 则读取回调队列

最后,当while(nh.ok())为true时, 调用当前队列中的所有函数,如果有不满足的, 会重新放回队列中

所以listener中, 就一直执行这ros::spin来监听话题了.从这样看来,spin和spinOnce的区别之一,就是while(nh::ok())执行块的大小了. 另一个是等待时间, spin在执行时, 会指定一个返回前可以等待调用的时间. spin会等待0.1s而spinonce不会

spinOnce使得pub/sub为非阻塞锁 spin是客户端的, 因此是阻塞的.

这样就很好理解talker要用SpinOnce,有需要talk的时候发出,没有的时候不发送.而listener一直在阻塞着听


这样,再来说之前很流传的一句关于解释spin的话, "所有的回调函数都是spin调用的". 这是一句形象而不准确的话. 回调函数一直等待在回调队列中, 只要条件一满足就会发生回调, 而spin的作用, 只是创建了线程给这个回调函数去执行它, 这样多线程就不会影响其他的作业.

之所以用spin, 是因为rospy不愿指定线程模型, 在程序中将线程暴露出来, 而用spin来把它封装起来. 但你可以用多线程调用任意数量的回调函数.

没有用户订阅, 服务和回调是不会被调用的.


 

多线程Spinning

多线程Spinning

roscpp内部支持调用多线程, 有两个:

ros::MultiThreadedSpinner

ros::MultiThreadedSpinner是阻塞微调, 类似于ros::spin(), 你可以在它的构造函数中指定线程数量, 但如果不指定或者设为0, 它会根据你的CPU内核数创建线程.

1 ros::MultiThreadedSpinner spinner(4); // Use 4 threads
2 spinner.spin(); // spin() will not return until the node has been shutdown

ros::AsyncSpinner (since 0.10)

一个更有用的线程spinner是AsyncSpinner. 与阻塞的spin()不同, 它有start()和stop()调用, 并且在销毁时自动停止

1 ros::AsyncSpinner spinner(4); // Use 4 threads
2 spinner.start();
3 ros::waitForShutdown();

ROSCPP的哲学是"工具, 而非框架"

另外: 不知道大家会把spin spinner spinning怎么译呢, 自旋?微调还是什么(蜘蛛么...反正肯定不会是棒槌`_`)

原文地址:https://www.cnblogs.com/feixiao5566/p/5288206.html