rospy介绍(一)

rospy是Python版本的ROS客户端库,提供了Python程序需要的接口(rospy就是一个Python模块),位于/opt/ros/kineetic/lib/python2.7/dist-packages/rospy。

rospy和roscpp

rospy功能与roscpp相似,都有关于node、topic、service、param、time相关操作,也有一些区别:

  1. rospy没有NodeHandle。
  2. 创建publisher、subscriber等操作被直接封装成了rospy中的函数或类,调用简单。
  3. rospy部分接口命名和roscpp不同。
    相较于C++开发,Python写ROS程序的开发效率较高,不用需要再注意显示、类型转换等细节,但执行效率低,同样一个功能用Python运行的耗时高于C++。所以开发SLAM、路径规划、机器视觉等方面算法时,往往优先选择C++。
    ROS中绝大多数基本指令(rostopic、roslaunch等)都是用Python开发的,简单轻巧。

ROS中Python代码的组织方式

Python代码有两种组织方式:单独的Python脚本(适用于简单的程序),Python模块(适用于提体量较大的程序)。

单独的Python脚本:
小体量的ROS程序,一般就是一个Python文件,放在script/路径下

test(包名)/scripts/file_name.py

Python模块
当程序的功能比较复杂时,无法放到一个脚本里,就要把一些功能放到PythonModule中,使用其他的脚本来调用。

ROS建立Python模块的规范:
test/src/test(与package同名)/init.py 可参考http://www.cnblogs.com/Lands-ljk/p/5880483.html
test/src/test(与package同名)/modulefiles.py
test/scripts/your_script.py
test/scripts/setup.py

常用的ROS命令大多数都是Python模块,源码存放在ros_comm仓库的tools路径下:https://github.com/ros/ros_comm/tree/lunar-devel/tools
每一个命令行工具(如rosbag、rosmsg)都是用模块的形式组成核心代码,然后在script/下建立一个脚本来调用。

常用rospy的API

具体查看http://docs.ros.org/api/rospy/html/rospy-module.html

Node相关

返回值方法作用
rospy.init_node(name,argv=None,anonymous=False)注册和初始化node
MasterProxyrospy.get_master()获取master的句柄
boolrospy.is_shoudow()节点是否关闭
rospy.on_shutdown()在节点关闭时调用fn函数
strget_node_uri返回节点的URI
strget_name()返回本节点的全名
strget_namespace()返回本节点的名字空间

Topic相关

函数:

返回值方法作用
[[str,str]]get_published_topics()返回正在被发布的所有topic名称和类型
Messagewait_for_message()等待某个topic的message
spin()触发topic或service的回调/处理函数,会阻塞直到关闭节点

Publisher类:

返回值方法作用
init(self,name,data_class,queue_size=None)构造函数
publish(self,msg)发布消息
strunregister(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,ars,*kwds)发起请求
call(self,args,*kwds)同上
close(self)关闭服务的client

Param相关

函数

返回值方法作用
XmlRpcLegalValueget_param(param_name,default=_unspecified)获取参数的值
[str]get_param_names()获取参数的名称
set_param(param_name,param_value)设置参数的值
delete_param(param_name)删除参数
boolhas_param(param_name)参数是否存在于参数服务器上
strsearch_param()搜索参数

时钟相关

函数:

返回值方法作用
Timeget_rostime()获取当前时刻的Time对象
floatget_time()返回当前时间,单位秒
sleep(duration)执行挂起

Time类

返回值方法作用
init(self,secs=0,nsecs=0)构造函数
Timenow()静态方法 返回当前时刻的Time对象

Duration类:

返回值方法作用
init(self,secs=0,nsecs=0)构造函数

topic in rospy

用Python写一个节点间消息收发的demo,创建一个自定义的gps类型的消息,一个节点发布模拟gps信息,另一个接收和计算原点的距离。

1. 自定义消息的生成
string state
float x
float y
2. CMakeLists.txt和package.xml

CMakeLists.txt

find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
message_generation
)
add_message_files(
FILES
gps.msg
)
generate_messages(DEPENDENCIES std_msgs)

package.xml

<build_depend>message_generation</build_depend>
<run_depend>message_runtion</run_depend>

对创建的msg进行catkin_make会在~/catkin_ws(workspace)/devel/lib/python2.7/dist-packages/topic_demo下生成msg模块(module),即可在Python程序中通过from test.msg import gps进行gps类型的消息的操作。

3. 消息发布节点

文件位置:test/scripts/pytalker.py

#!/usr/bin/env python
#coding = utf-8

import rospy
from test.msg import gps

def talker():
	rospy.init_node("pytalker",anonymous=True)
	pub = rospy.Publisher("gps_info",gps,queue_size=10) #Publisher 函数第一个参数是话题名称,第二个参数 数据类型,现在就是我们定义的msg 最后一个是缓冲区的大小
	#queue_size:None 不建议,会设置成为阻塞式同步收发模式
	#queue_size:0 不建议,会设置为无限缓冲区模式,危险
	#queue_size:10 or more  一般情况下设为10,queue_size太大会导致数据延时不同步
	#更新频率是1hz
	rate = rospy.Rate(1)
	x = 1.0
	y = 2.0
	state = "working"
	while not rospy.is_shutdown():
		rospy.loginfo('talker:gps:x=%f,y=%f')
		pub.publish(gps(state,x,y))
		x = 2*x
		y = 2*y
		rate.sleep()
if __name__ = "__main__":
	talker()

与C++代码区别:

  1. rospy创建和初始化一个node,不再需要NodeHandle(rospy没有设计NodeHandle这个句柄),创建topic、service等操作都直接用rospy里对应的方法即可。
  2. rospy节点的初始化补衣服ing必须放在开头,在Publisher建立后再初始化也可以。
  3. 消息的创建更加简单,例如gps类型的消息可以直接用类似与构造函数的方式gps(state,x,y)创建。
  4. 日志的输出方式不同,C++是ROS_INFO(),Python中为rospy.loginfo()。
  5. 判断节点是否关闭的函数不同,C++为ros::ok(),Python为rospy.is_shutdown()。

roscpp 和rospy的接口并不一致,实现原理上两套客户端库也有各自的实现,没有基于一个同意的核心库来开发,要避免混用。
ROS2就解决了这一问题,ROS2中的客户端库有rclcpp(ROS Client Library C++)、rclpy(ROS Client Library Python)和其他语言版本,都是基于一个共同的核心ROS客户端库rcl开发(核心库由C语言实现)。

3. 消息订阅节点

文件位置:test/scripts/pylistener.py:

#!/usr.bin/env python
#coding = utf-8

import rospy
import math
#导入mgs
from test.msg import gps

#回调函数输入的应该是msg
def callback(gps):
	distance = math.sqrt(math.pow(gps.x,2)+math.pow(gps.y,2))
	rospy.loginfo("listener:gps:distance=%f,state=%s",distance,gps.state)

def listener():
	rospy.init_node("pylistener",anonymous=True)
	#Subscriber函数第一个参数是topic的名称,第二个参数是接受的数据类型 第三个参数是回调函数的名称
	rospy.Subscriber("gps_info",gps,callback)
	rospy.spin()

if __name__ = "__main__"
	listener()

在订阅节点中,rospy没有spinOnce(),只有spin()。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐