(訳注:最新の情報は原文を参照してください.)

Note: This tutorial assumes that you have completed the previous tutorials: examining the simple publisher and subscriber.
(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

シンプルなサービスとクライアントを書く (Python)

Description: このチュートリアルはPythonでのサービスとクライアントノードの書き方について扱います

Tutorial Level: BEGINNER

Next Tutorial: シンプルなサービスとクライアントを実行する

サービスノードを書く

ここでは、2つの整数を受け取り合計を返すサービス ("add_two_ints_server")ノードを作ります。

  • creating a packageで作成済みのbeginner_tutorialsパッケージのディレクトリに移りましょう:

$ roscd beginner_tutorials

このチュートリアルで必要なサービスを作るための、前のチュートリアル(ROSのmsgやsrvなどを作る)の指示に従ったことを確認してください。(リンクのWikiページのトップが使用しているビルドツールと同じバージョンであることを確認してください).

コード

scripts/add_two_ints_server.pyというファイルをbeginner_tutorialsの中に作り以下のコードを書き込んでください。

   1 #!/usr/bin/env python
   2 import roslib; roslib.load_manifest('beginner_tutorials')
   3 from beginner_tutorials.srv import *
   4 import rospy
   5 
   6 def handle_add_two_ints(req):
   7     print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))
   8     return AddTwoIntsResponse(req.a + req.b)
   9 
  10 def add_two_ints_server():
  11     rospy.init_node('add_two_ints_server')
  12     s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
  13     print "Ready to add two ints."
  14     rospy.spin()
  15 
  16 if __name__ == "__main__":
  17     add_two_ints_server()

   1 #!/usr/bin/env python
   2 
   3 from beginner_tutorials.srv import *
   4 import rospy
   5 
   6 def handle_add_two_ints(req):
   7     print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))
   8     return AddTwoIntsResponse(req.a + req.b)
   9 
  10 def add_two_ints_server():
  11     rospy.init_node('add_two_ints_server')
  12     s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
  13     print "Ready to add two ints."
  14     rospy.spin()
  15 
  16 if __name__ == "__main__":
  17     add_two_ints_server()

ノードを実行可能にすることを忘れないでください:

chmod +x scripts/add_two_ints_server.py

コード解説

では、コードを読み解いていきましょう。

rospyを使ってサービスを書くのにコードはそれほど要りません。init_node() を使ってnodeを宣言し、そのあとにサービスを宣言しています。

  12     s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)

これは、AddTwoIntsというサービスのタイプのadd_two_intsという名前の新しいサービスを宣言しています。すべてのリクエストはhandle_add_two_ints関数に引き渡されます。handle_add_two_intsAddTwoIntsRequestのインスタンスによって呼び出され、 AddTwoIntsResponseのインスタンスを返します。

購読者の例と同じように、rospy.spin()はサービスが完了するまでコードを終了しないようにしています。

クライアントノードを書く

コード

scripts/add_two_ints_client.pyというファイルをbeginner_tutorialsの中に作り、以下のコードを書き込んでください:

   1 #!/usr/bin/env python
   2 
   3 import sys
   4 import rospy
   5 from beginner_tutorials.srv import *
   6 
   7 def add_two_ints_client(x, y):
   8     rospy.wait_for_service('add_two_ints')
   9     try:
  10         add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
  11         resp1 = add_two_ints(x, y)
  12         return resp1.sum
  13     except rospy.ServiceException, e:
  14         print "Service call failed: %s"%e
  15 
  16 def usage():
  17     return "%s [x y]"%sys.argv[0]
  18 
  19 if __name__ == "__main__":
  20     if len(sys.argv) == 3:
  21         x = int(sys.argv[1])
  22         y = int(sys.argv[2])
  23     else:
  24         print usage()
  25         sys.exit(1)
  26     print "Requesting %s+%s"%(x, y)
  27     print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))

ノードを実行可能にすることを忘れないでください:

$ chmod +x scripts/add_two_ints_client.py

コード解説

では、コードを読み解いていきましょう。

サービスを呼ぶクライアントコードも同じくシンプルです。クライアントは、init_node()を呼ぶ必要がありません。まずはじめに呼ぶものは:

   8     rospy.wait_for_service('add_two_ints')

これは、add_two_intsの名前のサービスが使えるようになるまで待機する便利なメソッドです。次に、サービスを呼ぶハンドラを作りましょう。

  10         add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)

普通の関数と同じようにハンドラを使って呼び出すことができます:

  11         resp1 = add_two_ints(x, y)
  12         return resp1.sum

AddTwoIntsというタイプのサービスを宣言したので、AddTwoIntsRequestのオブジェクトが作られています。(代わりに、自分のオブジェクトに入れてもかまいません。) 戻り値は、AddTwoIntsResponseオブジェクトです。呼び出しが失敗した場合、rospy.ServiceExceptionのエラーが投げられるので、それを受け取る適切なtry/exceptのブロックを用意すべきです。

ノードをビルドする

CMakeをビルドシステムで利用するので、もちろん、PythonのノードのときであってもCMakeを使わなければなりません。これは、メッセージとサービスのための自動生成のPythonコードが作られるのを確実にするためです。

我々は、ちょっとした利便性を得られるためMakefile利用しています。 roscreate-pkgは自動的に、Makefileをつくるので、編集する必要はありません。

では、makeをしてください。

$ make

catkin ワークスペースに移動して、catkin_makeを実行してください。

# catkin workspaceの中で
$ cd ~/catkin_ws
$ catkin_make

実行してみる!

新しいターミナルの中で、サーバを実行します。

$ rosrun beginner_tutorials add_two_ints_server.py

新しいターミナルの中で、引数無しで実行すると、

$ rosrun beginner_tutorials add_two_ints_client.py

以下のような使い方の情報が出力されるでしょう。

  • /home/user/catkin_ws/src/beginner_tutorials/scripts/add_two_ints_client.py [x y]

ここで、以下のように実行します。

$ rosrun beginner_tutorials add_two_ints_client.py 4 5

すると、このような出力を得ます。

  • Requesting 4+5
    4 + 5 = 9

そしてサーバ側は以下のように出力します。

  • Returning [4 + 5 = 9]

これでシンプルなサービスとクライアントを書くことが出来ました。次はシンプルなサービスとクライアントを実行するに進みましょう.

Wiki: ja/ROS/Tutorials/WritingServiceClient(python) (last edited 2017-04-06 12:52:51 by Kei Okada)