ROS学习(十四):ROS Spinning
ROS 單線程與多線程 Spinning
roscpp 不為應用程序指定具體的線程模型。
允許回調函數調用任意數量的線程
必須要調用線程,否則訂閱、服務等回調將永遠不會被調用
常見的解決方案是,在主函數開頭用 ros::spin()
注意:回調序列對內部的網絡通訊沒有影響,只能影響回調發生的時刻。它們將影響訂閱序列,取決于處理回調函數的速度、消息到達的速度、消息是否丟棄等。
1、單線程
最簡單最常用的單線程為:ros::spin()
ros::init(argc, argv, "my_node"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe(...); ... ros::spin();所有用戶的調用程序將從 ros::spin()開始調用。只到節點關閉(ros::shutdown() or a Ctrl-C),ros::spin()才有返回值。
另一個常用的模式是周期性的 ros::spinOnce()
ros::Rate r(10); // 10 hz while (should_continue) {... do some work, publish some messages, etc. ...ros::spinOnce();r.sleep(); }ros::spinOnce()將在那一刻調用所有等待調用的函數。
執行一個自己的spin()函數很簡單:
#include <ros/callback_queue.h> ros::NodeHandle n; while (ros::ok()) {ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1)); }spinOnce() 類似:
#include <ros/callback_queue.h>ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));注:spin()和spinonce()真的意味著單線程應用程序,而不是從多個線程中調用的一次優化。
2、多線程
ros::MultiThreadedSpinner
阻塞式線程,類似于ros::spin(),你可以在它的構造器上指定一定數量的線程數,但如果不指定或設置為0,則會在每個CPU上執行一個線程。
ros::MultiThreadedSpinner spinner(4); // Use 4 threads spinner.spin(); // spin() will not return until the node has been shutdownros::AsyncSpinner (since 0.10)
一個更有用的線程。它不用spin() 回調,而用start()和stop(),當它銷毀時候就會自動關閉
ros::AsyncSpinner spinner(4); // Use 4 threads spinner.start(); ros::waitForShutdown();3、回調序列
創建回調序列:
#include <ros/callback_queue.h> ... ros::CallbackQueue my_queue;CallbackQueue 有兩種方法調用回調函數: callAvailable() 和callOne()。
callavailable()調用隊列里所有的。callone()只會調用回調在隊列最舊的。
callAvailable()和callOne()都會有一個超時選項,在返回前,它會在超時時間內等待回調有效。
如果是0,同時隊列沒有回調,則直接返回。
4、高級回調序列
上面spin()執行的語句,有調用到 ros::getGlobalCallbackQueue(),默認所有的回調都會放到全局隊列,由ros::spin() 處理。
自定義回調序列:1、subscribe(), advertise(), advertiseService()
2、NodeHandle
這個可使用所有訂閱,服務,定時器等,回調通過my_callback_queue而不是 roscpp的默認隊列。意味著ros::spin() 和ros::spinOnce() 不會處理這些回調。你需要單獨處理這些回調。
你可以通過手工調用 ros::CallbackQueue::callAvailable() 和ros::CallbackQueue::callOne()方法處理。
my_callback_queue.callAvailable(ros::WallDuration()); // alternatively, .callOne(ros::WallDuration()) to only call a single callback instead of all available各種*Spinner對象可以使用指向回調隊列的指針而不是默認值:
ros::AsyncSpinner spinner(0, &my_callback_queue); spinner.start();或者:
ros::MultiThreadedSpinner spinner(0); spinner.spin(&my_callback_queue);參考
http://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning
總結
以上是生活随笔為你收集整理的ROS学习(十四):ROS Spinning的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ROS学习(十三):time 和 Tim
- 下一篇: git 基础教程总结