天天看点

ROS学习笔记—— rospyrospy中和 Node Topic Service Param Time 相关的函数Topic_demo (https://github.com/DroidAITech/ROS-Academy-for-Beginners/tree/master/topic_demo)service_demo(https://github.com/DroidAITech/ROS-Academy-for-Beginners/tree/master/service_demo)

所有资料均来自于 https://www.icourse163.org/learn/ISCAS-1002580008#/learn/announce  和

https://github.com/DroidAITech/ROS-Academy-for-Beginners  和 

https://sychaichangkun.gitbooks.io/ros-tutorial-icourse163/content/

rospy具体接口:https://docs.ros.org/api/rospy/html/

ROS Wiki rospy介绍:https://wiki.ros.org/rospy 

rospy中和 Node Topic Service Param Time 相关的函数

rospy_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() 返回本节点的名字空间

初始化node

import rospy
rospy.init_node('my_node')
           

rospy_Topic 相关

函数:

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

注:rospy里没有 spinOnce() 函数 

Publisher类:

返回值 方法 作用
__init__(self, name, data_class, queue_size=None) 构造函数
publish(self, msg) 发布消息
str unregister(self) 停止发布
pub = rospy.Publisher('topic_name',msg_type,queue_size = None) #若queue_size是 None 则为同步通信方式,若为整数则为异步通信方式
pub.publish(msg)    #发布消息
pub.unregister()    #停止发布
           

Subscriber类:

返回值 方法 作用
__init__(self, name, data_class, call_back=None, queue_size=None) 构造函数
unregister(self, msg) 停止订阅

 rospy-Service相关

函数:

返回值 方法 作用
wait_for_service(service, timeout=None) 阻塞直到服务可用

Service类(server):

返回值 方法 作用
__init__(self, name, service_class, handler) 构造函数,handler为处理函数,service_class为srv类型
shutdown(self) 关闭服务的server

关于回调函数handle,在rospy中传入参数是request 返回参数是response:

def handler(req):
....
return res
           

而在roscpp中传入参数是request和response,返回参数是一个布尔值:

bool handler(req,res)
{    
    ...
    return bool;
}
           

ServiceProxy类(client):

返回值 方法 作用
__init__(self, name, service_class) 构造函数,创建client
__call__(self, args, *kwds) 发起请求
call(self, args, *kwds) 同上
close(self) 关闭服务的client

 rospy-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() 搜索参数

rospy-Time相关

函数:

返回值 方法 作用
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) 构造函数

 注:Time+Time=Duration     Time+Duration=Time     Duration+Duration=Duration     Duration-Duration=Duration      Time+Time无意义  

Rate类:

返回值 方法 作用
__init__(self,frequency) 构造函数
sleep(self) 挂起 考虑上一次的rate.sleep()的时间
Time remaining(self) 成员函数 剩余sleep时间

Topic_demo 

(https://github.com/DroidAITech/ROS-Academy-for-Beginners/tree/master/topic_demo)

功能描述和步骤和roscpp的Topic_demo相同

gps.msg文件在经过catkin_make后,会在以下路径生成py文件

~/catkin_ws/devel/lib/python2.7/dis-pacakges/topic_demo/msg/__init__.py
           

引用格式如下:

from topic_demo.msg import gps
           

pylistener.py

#!/usr/bin/env python
#coding=utf-8
import rospy
import math
#导入mgs
from topic_demo.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()
           

pytalker.py

#!/usr/bin/env python
#coding=utf-8
import rospy
#导入自定义的数据类型
from topic_demo.msg import gps

def talker():
    #Publisher 函数第一个参数是话题名称,第二个参数 数据类型,现在就是我们定义的msg 最后一个是缓冲区的大小
    #queue_size: None(不建议)  #这将设置为阻塞式同步收发模式!
    #queue_size: 0(不建议)#这将设置为无限缓冲区模式,很危险!
    #queue_size: 10 or more  #一般情况下,设为10 。queue_size太大了会导致数据延迟不同步。
    pub = rospy.Publisher('gps_info', gps , queue_size=10)
    rospy.init_node('pytalker', anonymous=True)
    #更新频率是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',x,y)
        pub.publish(gps(state,x,y))
        x=1.03*x
        y=1.01*y
        rate.sleep()

if __name__ == '__main__':
    talker()
           

CMakeList.txt 和 package.xml 同前

service_demo

(https://github.com/DroidAITech/ROS-Academy-for-Beginners/tree/master/service_demo)

功能描述和步骤同前。

Greeting.srv文件在经过catkin_make后,会在以下路径生成py文件

~/catkin_ws/devel/lib/python2.7/dis-pacakges/service_demo/srv/__init__.py
           

引用格式如下:

from service_demo.srv import *  #import的有 Greeting GreetingResponse GreetingRequest
           

server_demo.py

#!/usr/bin/env python
#coding=utf-8
import rospy
from service_demo.srv import *

def server_srv():
    # 初始化节点,命名为 "greetings_server"
    rospy.init_node("greetings_server")
    # 定义service的server端,service名称为"greetings", service类型为Greeting
    # 收到的request请求信息将作为参数传递给handle_function进行处理
    s = rospy.Service("greetings", Greeting, handle_function)
    rospy.loginfo("Ready to handle the request:")
    # 阻塞程序结束
    rospy.spin()

def handle_function(req):
    # 注意我们是如何调用request请求内容的,是将其认为是一个对象的属性,在我们定义
    # 的Service_demo类型的service中,request部分的内容包含两个变量,一个是字符串类型的name,另外一个是整数类型的age
    rospy.loginfo( 'Request from %s with age %d', req.name, req.age)
    # 返回一个Service_demo.Response实例化对象,其实就是返回一个response的对象,其包含的内容为我们在Service_demo.srv中定义的
    # response部分的内容,我们定义了一个string类型的变量feedback,因此,此处实例化时传入字符串即可
    return GreetingResponse("Hi %s. I' server!"%req.name)

# 如果单独运行此文件,则将上面定义的server_srv作为主函数运行
if __name__=="__main__":
    server_srv()
           

 client_demo.py

#!/usr/bin/env python
# coding:utf-8
import rospy
from service_demo.srv import *

def client_srv():
    rospy.init_node('greetings_client')
    # 等待有可用的服务 "greetings"
    rospy.wait_for_service("greetings")
    try:
        # 定义service客户端,service名称为“greetings”,service类型为Greeting
        greetings_client = rospy.ServiceProxy("greetings",Greeting)

        # 向server端发送请求,发送的request内容为name和age,其值分别为"HAN", 20
        # 此处发送的request内容与srv文件中定义的request部分的属性是一致的
        #resp = greetings_client("HAN",20)
        resp = greetings_client.call("HAN",20)
        rospy.loginfo("Message From server:%s"%resp.feedback)
    except rospy.ServiceException, e:
        rospy.logwarn("Service call failed: %s"%e)

# 如果单独运行此文件,则将上面函数client_srv()作为主函数运行
if __name__=="__main__":
    client_srv()
           

继续阅读