單線程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怎么譯呢, 自旋?微調還是什么(蜘蛛么...反正肯定不會是棒槌`_`)