# 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