ros::spin()
的作用
在 ROS 中,ros::spin()
的主要作用是:
- 讓 ROS 節點持續執行,並處理所有註冊的回撥函式。
- 在內部,它不斷地檢查 ROS 網路中的訊息、服務請求,並呼叫相應的回撥函式來處理它們。
內部原理
-
事件迴圈 (Event Loop):
ros::spin()
進入一個事件迴圈。這個迴圈不斷地輪詢 ROS 網路,檢查是否有新的訊息到達或者服務請求到達。- 如果有訊息到達,它會觸發與該訊息相關聯的回撥函式。
- 這個迴圈會持續執行,直到程式結束或者節點被關閉。
-
訊息佇列 (Message Queue):
- ROS 使用訊息佇列來儲存接收到的訊息。每個訂閱者都與其訂閱的主題關聯,並將收到的訊息放入佇列中。
ros::spin()
從佇列中獲取訊息,並呼叫相應的回撥函式來處理這些訊息。
-
執行緒與多工處理:
- ROS 的實現通常是單執行緒的,但可以透過
ros::AsyncSpinner
來支援多執行緒處理,以便併發處理訊息和服務請求。
- ROS 的實現通常是單執行緒的,但可以透過
使用 ros::spin()
的情境
- 單執行緒節點:如果你的節點需要處理多個訂閱者的回撥,並且你希望在主執行緒中處理所有的回撥,可以使用
ros::spin()
。 - 多執行緒節點:如果你希望你的節點能夠在多個執行緒中處理回撥,可以使用
ros::AsyncSpinner
,它允許你建立多個執行緒來併發處理訊息。
#include <ros/ros.h> #include <std_msgs/String.h> #include <iostream> void messageCallback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("Received message: [%s]", msg->data.c_str()); } int main(int argc, char** argv) { ros::init(argc, argv, "async_spinner_example"); ros::NodeHandle nh; // 建立訂閱者 ros::Subscriber sub = nh.subscribe("chatter", 1000, messageCallback); // 建立 AsyncSpinner 物件,指定使用 4 個執行緒 ros::AsyncSpinner spinner(4); // 啟動 spinner spinner.start(); // 主執行緒可以執行其他操作 ros::Rate rate(1); // 1 Hz while (ros::ok()) { ROS_INFO("Main thread doing other work..."); rate.sleep(); } // 停止 spinner spinner.stop(); return 0; }