[Documentation] [TitleIndex] [WordIndex

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

サービスノードを書く

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

$ 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という名前の新しいサービスを宣言しています。

購読者の例と同じように、

  19 (do-until-key
  20  (ros::spin-once))

`はサービスが完了するまでコードを終了しないようにしています。

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

コード

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のオブジェクトが作られています。

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

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

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

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


2019-12-07 12:41