# 7.1 rospy與主要接口
## 7.1.1 rospy vs roscpp
rospy是Python版本的ROS客戶端庫,提供了Python編程需要的接口,你可以認為rospy就是一個Python的模塊(Module)。這個模塊位于`/opt/ros/kineetic/lib/python2.7/dist-packages/rospy`之中。
rospy包含的功能與roscpp相似,都有關于node、topic、service、param、time相關的操作。但同時rospy和roscpp也有一些區別:
1. rospy沒有一個NodeHandle,像創建publisher、subscriber等操作都被直接封裝成了rospy中的函數或類,調用起來簡單直觀。
2. rospy一些接口的命名和roscpp不一致,有些地方需要開發者注意,避免調用錯誤。
相比于C++的開發,用Python來寫ROS程序開發效率大大提高,諸如顯示、類型轉換等細節不再需要我們注意,節省時間。但Python的執行效率較低,同樣一個功能用Python運行的耗時會高于C++。因此我們開發SLAM、路徑規劃、機器視覺等方面的算法時,往往優先選擇C++。
ROS中絕大多數基本指令,例如`rostopic`,`roslaunch`都是用python開發的,簡單輕巧。
## 7.1.2 ROS中Python代碼的組織方式
要介紹rospy,就不得不提Python代碼在ROS中的組織方式。通常來說,Python代碼有兩種組織方式,一種是單獨的一個Python腳本,適用于簡單的程序,另一種是Python模塊,適合體量較大的程序。
### 單獨的Python腳本
對于一些小體量的ROS程序,一般就是一個Python文件,放在script/路徑下,非常簡單。
```
your_package
|- script/
|- your_script.py
|-...
```
### Python模塊
當程序的功能比較復雜,放在一個腳本里搞不定時,就需要把一些功能放到Python Module里,以便其他的腳本來調用。ROS建議我們按照以下規范來建立一個Python的模塊:
```
your_package
|- src/
|-your_package/
|- _init_.py
|- modulefiles.py
|- scripts/
|- your_script.py
|- setup.py
```
在src下建立一個與你的package同名的路徑,其中存放`_init_.py`以及你的模塊文件。這樣就建立好了ROS規范的Python模塊,你可以在你的腳本中調用。
如果你不了解_init_.py的作用,可以參考這篇博客http://www.cnblogs.com/Lands-ljk/p/5880483.html
ROS中的這種Python模塊組織規范與標準的Python模塊規范并不完全一致,你當然可以按照Python的標準去建立一個模塊,然后在你的腳本中調用,但是我們還是建議按照ROS推薦的標準來寫,這樣方便別人去閱讀。
通常我們常用的ROS命令,大多數其實都是一個個Python模塊,源代碼存放在ros_comm倉庫的tools路徑下:https://github.com/ros/ros_comm/tree/lunar-devel/tools
你可以看到每一個命令行工具(如rosbag、rosmsg)都是用模塊的形式組織核心代碼,然后在`script/`下建立一個腳本來調用模塊。
## 7.1.3 常用rospy的API
這里分類整理了rospy常見的一些用法,請你瀏覽一遍,建立一個初步的影響。
具體API請查看http://docs.ros.org/api/rospy/html/rospy-module.html
### Node相關
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | rospy.init_node(name, argv=None, anonymous=False) | 注冊和初始化node|
| MasterProxy| rospy.get_master() | 獲取master的句柄 |
| bool| rospy.is_shutdown() | 節點是否關閉 |
| | rospy.on_shutdown(fn)| 在節點關閉時調用fn函數 |
| str | get_node_uri() | 返回節點的URI |
| str | get_name() | 返回本節點的全名 |
| str | get_namespace() | 返回本節點的名字空間 |
| ... | ...|...|
### Topic相關
函數:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| [[str, str]] | get_published_topics() | 返回正在被發布的所有topic名稱和類型|
| Message| wait_for_message(topic, topic_type, time_out=None) | 等待某個topic的message |
| | spin() | 觸發topic或service的回調/處理函數,會阻塞直到關閉節點 |
| ... | ...|...|
Publisher類:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | _init_(self, name, data_class, queue_size=None)|構造函數 |
| | publish(self, msg) | 發布消息 |
| str | unregister(self) | 停止發布 |
| ... | ...|...|
Subscriber類:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | _init__(self, name, data_class, call_back=None, queue_size=None)|構造函數 |
| | unregister(self, msg) | 停止訂閱 |
| ... | ...|...|
### Service相關
函數:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | wait_for_service(service, timeout=None) | 阻塞直到服務可用|
| ... | ...|...|
Service類(server):
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | _init_(self, name, service_class, handler) |構造函數,handler為處理函數,service_class為srv類型|
| | shutdown(self) | 關閉服務的server|
| ... | ...|...|
ServiceProxy類(client):
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | _init_(self, name,?service_class) |構造函數,創建client|
| | _call_(self, *args, **kwds) | 發起請求|
| | call(self, *args, **kwds) | 同上|
| | close(self) | 關閉服務的client|
| ... | ...|...|
### Param相關
函數:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| XmlRpcLegalValue | get_param(param_name, default=_unspecified) |獲取參數的值|
| [str] | get_param_names() | 獲取參數的名稱 |
| | set_param(param_name,?param_value) | 設置參數的值 |
| | delete_param(param_name) | 刪除參數 |
| bool | has_param(param_name) | 參數是否存在于參數服務器上 |
| str | search_param() | 搜索參數|
| ... | ...|...|
### 時鐘相關
函數:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| Time | get_rostime() |獲取當前時刻的Time對象 |
| float | get_time() | 返回當前時間,單位秒 |
| | sleep(duration) | 執行掛起 |
| ... | ...|...|
Time類:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | _init_(self, secs=0, nsecs=0) | 構造函數 |
| Time| now() | 靜態方法 返回當前時刻的Time對象 |
| ... | ...|...|
Duration類:
| 返回值 | 方法 | 作用 |
| :------: | :------: | :------: |
| | _init_(self, secs=0, nsecs=0) | 構造函數 |
| ... | ...|...|
- 前言
- 第一章 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