天天看點

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()
           

繼續閱讀