Note: This tutorial assumes that you have completed the previous tutorials: Writing a Simple Publisher and Subscriber (Euslisp). |
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. |
Writing Simple Service and Client (EusLisp)
Description: This tutorial covers how to write a service and client node in EusLisp.Tutorial Level: BEGINNER
Contents
サービスノードを書く
ここでは、2つの整数を受け取り合計を返すサービス ("add_two_ints_server")ノードを作ります。
creating a packageで作成済みのbeginner_tutorialsパッケージのディレクトリに移りましょう:
$ roscd beginner_tutorials
このチュートリアルで必要なサービスを作るための、前のチュートリアル(ROSのmsgやsrvなどを作る)の指示に従ったことを確認してください。(リンクのWikiページのトップが使用しているビルドツールと同じバージョンであることを確認してください).
コード
scripts/add_two_ints_server.lというファイルをbeginner_tutorialsの中に作り以下のコードを書き込んでください。
1 #!/usr/bin/env roseus
2 ;;;
3 ;;; euslisp version of ros_tutorials/rospy_tutorials/005_add_two_ints
4 ;;;
5 (ros::load-ros-manifest "roseus")
6
7 ;;;
8 (defun add-two-ints (req)
9 (let ((m (send req :response)))
10 (format *error-output* "Returning [~d + ~d = ~d]~%"
11 (send req :a) (send req :b)
12 (+ (send req :a) (send req :b)))
13 (send m :sum (+ (send req :a) (send req :b)))
14 m))
15 ;;;
16 ;;;
17 (ros::roseus "add_two_ints_server")
18 (ros::advertise-service "add_two_ints" roseus::AddTwoInts #'add-two-ints)
19 (do-until-key
20 (ros::spin-once))
ノードを実行可能にすることを忘れないでください:
chmod +x scripts/add_two_ints_server.l
コード解説
では、コードを読み解いていきましょう。
roseusを使ってサービスを書くのにコードはそれほど要りません。(ros::roseus "add_two_ints_server") を使ってnodeを宣言し、そのあとにサービスを宣言しています。
18 (ros::advertise-service "add_two_ints" roseus::AddTwoInts #'add-two-ints)
これは、AddTwoIntsというサービスのタイプのadd_two_intsという名前の新しいサービスを宣言しています。
購読者の例と同じように、
`はサービスが完了するまでコードを終了しないようにしています。
クライアントノードを書く
コード
scripts/add_two_ints_client.lというファイルをbeginner_tutorialsの中に作り、以下のコードを書き込んでください:
1 #!/usr/bin/env roseus
2 ;;;
3 ;;; euslisp version of ros_tutorials/rospy_tutorials/005_add_two_ints
4 ;;;
5 (ros::load-ros-manifest "roseus")
6
7 ;;;
8 ;;;
9 (ros::roseus "add_two_ints_client")
10 (ros::wait-for-service "add_two_ints")
11 (dotimes (i 100)
12 (setq req (instance roseus::AddTwoIntsRequest :init))
13 (send req :a (random 10))
14 (send req :b (random 20))
15 (setq before (ros::time-now))
16 (case (mod i 3)
17 (0 (setq res (ros::service-call "add_two_ints" req t)))
18 (1 (setq res (ros::service-call "add_two_ints" req nil)))
19 (2 (setq res (ros::service-call "add_two_ints" req))))
20 (setq after (ros::time-now))
21 (format t "~d + ~d = ~d~ (~A sec)~%" (send req :a) (send req :b) (send res :sum) (send (ros::time- after before) :to-sec))
22 (unix:sleep 1))
ノードを実行可能にすることを忘れないでください:
$ chmod +x scripts/add_two_ints_client.l
コード解説
では、コードを読み解いていきましょう。
サービスを呼ぶクライアントコードも同じくシンプルです。クライアントも、(ros::roseus "add_two_ints_client")を呼ぶ必要があります。
10 (ros::wait-for-service "add_two_ints")
これは、add_two_intsの名前のサービスが使えるようになるまで待機する便利なメソッドです。
12 (setq req (instance roseus::AddTwoIntsRequest :init))
AddTwoIntsというタイプのサービスを宣言したので、AddTwoIntsRequestのオブジェクトが作られています。
add_two_ints関数を引数retで呼び出しています.戻り値は、AddTwoIntsResponseオブジェクトです。
ノードをビルドする
CMakeをビルドシステムで利用するので、もちろん、EusLispのノードのときであってもCMakeを使わなければなりません。これは、メッセージとサービスのための自動生成のEusLispコードが作られるのを確実にするためです。
catkin ワークスペースに移動して、catkin_makeを実行してください。
# catkin workspaceの中で $ cd ~/catkin_ws $ catkin_make
実行してみる!
新しいターミナルの中で、サーバを実行します。
$ rosrun beginner_tutorials add_two_ints_server.l
新しいターミナルの中で、以下のように実行します。
$ rosrun beginner_tutorials add_two_ints_client.l 4 5
すると、このような出力を得ます。
Requesting 4+5 4 + 5 = 9
そしてサーバ側は以下のように出力します。
Returning [4 + 5 = 9]