サービスの書き方
ROSチュートリアルの流れ
- サービスの書き方 ←今ここ 
はじめに
この章では、サービスの書き方について説明したいと思います。
サービスにはデータを要求する「クライアント」と応答する「サーバ」があります。
これはトピックの「サブスクライバ」と「パブリッシャ」の関係に似ていますが、サービスは更に応答の成否を知ることができます。
またトピックではメッセージ(.msg)を使用しましたが、サービスではサービスのファイル(.srv)を使用します。
詳しくはROSでよく使用する用語を御覧ください。
サービスファイル
サービスでは.srvという拡張子になっているファイルを使用します。 まず標準のサービスstd_srvsのSetBool.srvを見てみましょう。
rossrv show std_srvs/SetBool以下のように表示されるはずです。
bool data
---
bool success
string message---の上が入力、下が出力になります。
サービスサーバ
最初にサーバ側から書いていきます。
server.pyを作成します。
roscd ros_tutorial/
vim scripts/server.py#!/usr/bin/env python                                                           
import rospy
from std_srvs.srv import SetBool, SetBoolResponse
def callback_srv(data):
    resp = SetBoolResponse()
    if data.data == True:
        resp.message = "called"
        resp.success = True
    else:
        resp.message = "ready"
        resp.success = False
    print(resp.message)
    return resp
if __name__ == "__main__":
    rospy.init_node("srv_server")
    srv = rospy.Service('service_call', SetBool, callback_srv)
    print("ready")
    rospy.spin()実行権限を与えます。
chmod +x scripts/server.pyコード解説
#!/usr/bin/env python                                                           
import rospyここまで今までと同じです。
from std_srvs.srv import SetBool, SetBoolResponse標準のサービスのstd_srvsの中にあるSetBoolとその出力に関するSetBoolResponseをインポートしています。
先にメイン関数について説明します。
if __name__ == "__main__":
    rospy.init_node("srv_server")srv_serverというノードの名前にしています。
      srv = rospy.Service('service_call', SetBool, callback_srv)ここでサービスをインスタンスしています。service_callがサービス名、SetBoolがサービスの型、callback_srvがサービスの引数を返すコールバック関数名になります。
      print("ready")一番最初はreadyと表示させておきます。
      rospy.spin()プログラムを終了させないようにしています。
最後にコールバック関数について解説します。
def callback_srv(data):callback_srvという関数名で、受け取った値をdataという名前にしてます。
resp = SetBoolResponse()SetBoolResponseをrespという名前でインスタンス化しています。
    if data.data == True:
        resp.message = "called"
        resp.success = True
    else:
        resp.message = "ready"
        resp.success = FalseTrueが入力された場合、つまり呼び出しがあった時、messageにcalledを書き込み、呼び出されたことを伝えるためsuccessにTrueを書き込んでいます。
それ以外の場合やFalseが入力された場合は、messageにreadyを書き込み、呼び出されていないことを伝えるためsuccessにFalseを書き込んでいます。
    print(resp.message)
    return resp確認のため、messageを表示しています。
最後にサービスの型を返す必要があり、SetBoolResponseをインスタンス化したrespを返しています。
サービスクライアント
次にクライアント側を書いていきます。
client.pyを作成します。
roscd ros_tutorial/
vim scripts/client.py#!/usr/bin/env python
import rospy
from std_srvs.srv import SetBool
if __name__ == "__main__":
    rospy.wait_for_service('service_call')
    try:
        service_call = rospy.ServiceProxy('service_call', SetBool)
        service_call(True)
    except rospy.ServiceException, e:
        print ("Service call failed: %s" % e)実行権限を与えます。
chmod +x scripts/client.pyコード解説
#!/usr/bin/env python                                                           
import rospyここまで同じです。
std_srvs.srv import SetBoolSetBool型をインポートしています。
    rospy.wait_for_service('service_call')ここでservice_callというサービスが立ち上がるのを待ちます。
トピックを違い、サービスは一対一通信のため相手がいないとエラーを吐きます。 そのためサービスの立ち上がりを待っています。
    try:
        service_client = rospy.ServiceProxy('service_call', SetBool)
        service_client(True)
    except rospy.ServiceException, e:
        print ("Service call failed: %s" % e)sarvice_callという名前のSetBool型のサービスプロキシservice_clientを作成しています。
service_clientにTrueを与えています。
実行方法
それぞれ別のターミナルで実行してください。
roscorerosrun ros_tutorial server.pyrosrun ros_tutorial client.py実行結果
rosrun ros_tutorial client.pyを実行した時、rosrun ros_tutorial server.pyを実行しているターミナルで、
calledと表示されたら、正常に動作しています。
別の方法
roscorerosrun ros_tutorial server.pyここまで同じですが、こちらではrosserviceというコマンドを使用します。 このコマンドでもサーバに要求できます。
rosservice call /service_call "data: true"rosservice call /service_call "data: false"Last updated
Was this helpful?
