# 6.2 節點初始、關閉以及NodeHandle
當執行一個ROS程序,就被加載到了內存中,就成為了一個進程,在ROS里叫做節點。每一個ROS的節點盡管功能不同,但都有必不可少的一些步驟,比如初始化、銷毀,需要通行的場景通常都還需要節點的句柄。
這一節我們來學習Node最基本的一些操作。
## 6.2.1 初始化節點
對于一個C++寫的ROS程序,之所以它區別于普通C++程序,是因為代碼中做了兩層工作:
1. 調用了`ros::init()`函數,從而初始化節點的名稱和其他信息,一般我們ROS程序一開始都會以這種方式開始。
2. 創建`ros::NodeHandle`對象,也就是節點的句柄,它可以用來創建Publisher、Subscriber以及做其他事情。
句柄(Handle)這個概念可以理解為一個“把手”,你握住了門把手,就可以很容易把整扇門拉開,而不必關心門是什么樣子。NodeHandle就是對節點資源的描述,有了它你就可以操作這個節點了,比如為程序提供服務、監聽某個topic上的消息、訪問和修改param等等。
## 6.2.2 關閉節點
通常我們要關閉一個節點可以直接在終端上按`Ctrl`+`C`,系統會自動觸發SIGINT句柄來關閉這個進程。
你也可以通過調用`ros::shutdown()`來手動關閉節點,但通常我們很少這樣做。
以下是一個節點初始化、關閉的例子。
```
#include<ros/ros.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "your_node_name");
ros::NodeHandle nh;
//....節點功能
//....
ros::spin();//用于觸發topic、service的響應隊列
return 0;
}
```
這段代碼是最常見的一個ROS程序的執行步驟,通常要啟動節點,獲取句柄,而關閉的工作系統自動幫我們完成,如果有特殊需要你也可以自定義。你可能很關心句柄可以用來做些什么,接下來我們來看看NodeHandle常用的成員函數。
## 6.2.3 NodeHandle常用成員函數
NodeHandle是Node的句柄,用來對當前節點進行各種操作。在ROS中,NodeHandle是一個定義好的類,通過`include<ros/ros.h>`,我們可以創建這個類,以及使用它的成員函數。
NodeHandle常用成員函數包括:
```cpp
//創建話題的publisher
ros::Publisher advertise(const string &topic, uint32_t queue_size, bool latch=false);
//第一個參數為發布話題的名稱
//第二個是消息隊列的最大長度,如果發布的消息超過這個長度而沒有被接收,那么就的消息就會出隊。通常設為一個較小的數即可。
//第三個參數是是否鎖存。某些話題并不是會以某個頻率發布,比如/map這個topic,只有在初次訂閱或者地圖更新這兩種情況下,/map才會發布消息。這里就用到了鎖存。
//創建話題的subscriber
ros::Subscriber subscribe(const string &topic, uint32_t queue_size, void(*)(M));
//第一個參數是訂閱話題的名稱
//第二個參數是訂閱隊列的長度,如果受到的消息都沒來得及處理,那么新消息入隊,就消息就會出隊
//第三個參數是回調函數指針,指向回調函數來處理接收到的消息
//創建服務的server,提供服務
ros::ServiceServer advertiseService(const string &service, bool(*srv_func)(Mreq &, Mres &));
//第一個參數是service名稱
//第二個參數是服務函數的指針,指向服務函數。指向的函數應該有兩個參數,分別接受請求和響應。
//創建服務的client
ros::ServiceClient serviceClient(const string &service_name, bool persistent=false);
//第一個函數式service名稱
//第二個參數用于設置服務的連接是否持續,如果為true,client將會保持與遠程主機的連接,這樣后續的請求會快一些。通常我們設為flase
//查詢某個參數的值
bool getParam(const string &key, std::string &s);
bool getParam (const std::string &key, double &d) const;
bool getParam (const std::string &key, int &i) const;
//從參數服務器上獲取key對應的值,已重載了多個類型
//給參數賦值
void setParam (const std::string &key, const std::string &s) const;
void setParam (const std::string &key, const char *s) const;
void setParam (const std::string &key, int i) const;
//給key對應的val賦值,重載了多個類型的val
```
可以看出,NodeHandle對象在ROS C++程序里非常重要,各種類型的通信都需要用NodeHandle來創建完成。
下面我們具體來看topic、service和param這三種基本通信方式的寫法。
- 前言
- 第一章 ROS簡介
- 機器人時代的到來
- ROS發展歷程
- 什么是ROS
- 安裝ROS
- 安裝ROS-Academy-for-Beginners教學包
- 二進制與源碼包
- 安裝RoboWare Studio
- 單元測試一
- 第二章 ROS文件系統
- Catkin編譯系統
- Catkin工作空間
- Package軟件包
- CMakeLists.txt
- package.xml
- Metapacakge軟件元包
- 其他常見文件類型
- 單元測試二
- 第三章 ROS通信架構(一)
- Node & Master
- Launch文件
- Topic
- Msg
- 常見msg類型
- 單元測試三
- 第四章 ROS通信架構(二)
- Service
- Srv
- Parameter server
- Action
- 常見srv類型
- 常見action類型
- 單元測試四
- 第五章 常用工具
- Gazebo
- RViz
- Rqt
- Rosbag
- Rosbridge
- moveit!
- 單元測試五
- 第六章 roscpp
- Client Library與roscpp
- 節點初始、關閉與NodeHandle
- Topic in roscpp
- Service in roscpp
- Param in roscpp
- 時鐘
- 日志與異常
- 第七章 rospy
- Rospy與主要接口
- Topic in rospy
- Service in rospy
- Param與Time
- 第八章 TF與URDF
- 認識TF
- TF消息
- tf in c++
- tf in python
- 統一機器人描述格式
- 附錄:TF數學基礎
- 三維空間剛體運動---旋轉矩陣
- 三維空間剛體運動---歐拉角
- 三維空間剛體運動---四元數
- 第九章 SLAM
- 地圖
- Gmapping
- Karto
- Hector
- 第十章 Navigation
- Navigation Stack
- move_base
- costmap
- Map_server & Amcl
- 附錄:Navigation工具包說明
- amcl
- local_base_planner
- carrot_planner
- clear_costmap_recovery
- costmap_2d
- dwa_local_planner
- fake_localization
- global_planner
- map_server
- move_base_msg
- move_base
- move_slow_and_clear
- navfn
- nav_core
- robot_pose_ekf
- rotate_recovery