iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0
自我挑戰組

ROS 筆記:要怎麼叫無人機自己飛系列 第 12

【ROS 筆記:要怎麼叫無人機自己飛】Day 12:使用 Python 撰寫服務代理(Service Proxy)

  • 分享至 

  • xImage
  •  

這一篇繼續介紹如何用 Python 來寫一個服務代理,我們就能做到 Day 10 介紹的 rosservice call 指令相同的效果。

建立服務代理(Service Proxy)

這一個範例 turtle_callsrv_reset.py 可以做到呼叫服務 /reset 的效果,並重置烏龜的位置和狀態。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import rospy
# 訊息: std_srvs/Empty 表示不需要參數的標準服務
from std_srvs.srv import Empty as EmptySrv

def turtle_callsrv_reset():
    # 設定暫停等待服務可用
    rospy.wait_for_service('/reset')
    try:
        call1 = rospy.ServiceProxy('/reset', EmptySrv)
        resp1 = call1()
        return resp1
    except rospy.ServiceException as e:
        print ("Service call failed: {}".format(e))
    
    rospy.spin()

if __name__ == '__main__':
    # 節點初始化
    rospy.init_node('turtle_srv_reset', anonymous=True)
    turtle_callsrv_reset()

下面來解釋這段腳本的每個部份在做什麼。

匯入必要的模組

import rospy
from std_srvs.srv import Empty as EmptySrv

在這之前可以先查詢服務的訊息類型,輸入指令 rosservice type /reset 查到訊息類型是 std_srvs/Empty。和上一篇同理,這個訊息是定義在 std_srvs.srv 模組的 Empty 類別,因此 python 程式開頭先匯入。

定義 turtle_callsrv_reset() 函式

def turtle_callsrv_reset():
    rospy.wait_for_service('/reset')
    try:
        # 建立服務代理
        callsrv = rospy.ServiceProxy('/reset', EmptySrv)
        # 呼叫服務取得回應
        response = callsrv()
        return response
    
    # 處理異常狀況
    except rospy.ServiceException as e:
        print ("Service call failed: {}".format(e))
    
    rospy.spin()

在這段函式中包含了幾個功能:

  • 設定暫停:

    rospy.wait_for_service('/reset') 這行的用意是讓腳本暫停,等待直到 /reset 這個服務可以使用時才用,避免出現錯誤。

  • 建立服務代理:

    callsrv = rospy.ServiceProxy('/reset', EmptySrv) 這行利用 rospy.ServiceProxy 建立了一個服務代理,它會負責向服務 /reset 提出請求並將結果儲存起來。

    格式:

    callsrv = rospy.ServiceProxy(proxy_name, srv_class)
    
    • callsrv:用一個變數儲存服務代理的資訊,以便後面可以直接使用。

    • proxy_name:服務代理的名稱。

    • srv_class:提供的服務的類型。

    服務代理是客戶端呼叫服務的仲介,實際上是一個可呼叫(Callable)的物件,這個服務代理會負責所有底層的通訊細節,包括與 ROS 伺服器建立連接、傳送請求以及接收回應。也就是說我們可以不理它的原理,只要知道我們能加上 () 後像函式一樣使用它。

  • 呼叫服務

    response = callsrv() 這行是呼叫 callsrv(),並且將呼叫後得到的回應儲存到變數 response 中。callsrv 會按照前面所說去向服務 /reset 提出請求,再回傳結果。

  • 處理異常

    最後處理 rospy.ServiceException 這個異常狀況,包含呼叫服務過程中出現的問題,並且用變數 e 來保存。當異常狀況發生時,這段程式碼可以顯示錯誤的原因。


扣掉第一天的開賽宣言,不知不覺就寫完十一篇了,到這裡差不多把 ROS 的基本概念介紹過一遍,現在我們可以建立節點,也可以寫出各種對機器人下指令的程式,可以說熱身完畢了。

不過接下來,先不急著馬上開始控制無人機。後面幾篇我將介紹與 ROS 平台整合最好的機器人模擬器: Gazebo ,以及如何匯入機器人到模擬環境中,這樣就不用真的跑去買一台無人機來控制囉。


上一篇
【ROS 筆記:要怎麼叫無人機自己飛】Day 11:使用 Python 撰寫話題的發布者(Publisher)和訂閱者(Subscriber)
下一篇
【ROS 筆記:要怎麼叫無人機自己飛】Day 13:機器人學的基礎知識
系列文
ROS 筆記:要怎麼叫無人機自己飛14
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言