(訳注:最新の情報は原文を参照してください.)
Note: This tutorial assumes that you have completed the previous tutorials: シンプルなPublisherと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. |
C++でシンプルなサービスとクライアントを書く
Description: このチュートリアルではサービスとクライアントノードのC++での書き方を学びますTutorial Level: BEGINNER
Next Tutorial: シンプルなサービスとクライアントを実行してみる
シンプルなサービスとクライアントを書く (C++)
サービスノードを書く
さてここでは、("add_two_ints_server")という二つのintegerを受け取りその合計を戻り値にもつサービスノードを作っていきます。
ディレクトリを以前のチュートリアル(ROSパッケージを作る)で作成したbeginner_tutorialsのパッケージの中に移動させましょう。
roscd beginner_tutorials
以前catkinワークスペースで作成したbeginner_tutorialsパッケージに移動してください。
cd ~/catkin_ws/src/beginner_tutorials
このチュートリアルで必要なサービスを作る以前のチュートリアル(ROSのmsgやsrvなどを作る)の指示に従ったことを確認してください。
コード
src/add_two_ints_server.cppというファイルをbeginner_tutorialsの中につくり以下のコードを書き込んでください:
1 #include "ros/ros.h"
2 #include "beginner_tutorials/AddTwoInts.h"
3
4 bool add(beginner_tutorials::AddTwoInts::Request &req,
5 beginner_tutorials::AddTwoInts::Response &res)
6 {
7 res.sum = req.a + req.b;
8 ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
9 ROS_INFO("sending back response: [%ld]", (long int)res.sum);
10 return true;
11 }
12
13 int main(int argc, char **argv)
14 {
15 ros::init(argc, argv, "add_two_ints_server");
16 ros::NodeHandle n;
17
18 ros::ServiceServer service = n.advertiseService("add_two_ints", add);
19 ROS_INFO("Ready to add two ints.");
20 ros::spin();
21
22 return 0;
23 }
コード解説
さてコードを読み解いていきましょう。
beginner_tutorials/AddTwoInts.hは以前作ったsrvファイルを作成したときに生成されたヘッダーファイルです。
この関数は、2つのint型を足し合わせる働きのサービスで、srvファイルに定義されたリクエストとレスポンスのタイプを読み込み、booleanを返します。
ここでは、2つのintegerは加えられ、レスポンスの中に保管されます。その後、リクエストとレスポンスのいくらかの情報が、ログに残されます。最後に、サービスは完了したタイミングでtrueを返します。
18 ros::ServiceServer service = n.advertiseService("add_two_ints", add);
ここでは、サービスが生成され、ROSにこのサービスが登録されます。
クライアントNodeを書く
コード
src/add_two_ints_client.cppというファイルをbeginner_tutorialsの中につくり以下のコードを書き込んでください:
1 #include "ros/ros.h"
2 #include "beginner_tutorials/AddTwoInts.h"
3 #include <cstdlib>
4
5 int main(int argc, char **argv)
6 {
7 ros::init(argc, argv, "add_two_ints_client");
8 if (argc != 3)
9 {
10 ROS_INFO("usage: add_two_ints_client X Y");
11 return 1;
12 }
13
14 ros::NodeHandle n;
15 ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
16 beginner_tutorials::AddTwoInts srv;
17 srv.request.a = atoll(argv[1]);
18 srv.request.b = atoll(argv[2]);
19 if (client.call(srv))
20 {
21 ROS_INFO("Sum: %ld", (long int)srv.response.sum);
22 }
23 else
24 {
25 ROS_ERROR("Failed to call service add_two_ints");
26 return 1;
27 }
28
29 return 0;
30 }
コード解説
さて、コードを読み解いていきましょう。
15 ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
これは、add_two_intsサービスのためのクライアントを作成しています。 ros::ServiceClientオブジェクトは、サービスを後で呼び出すために使用します。
ここで、自動生成されたサービスのクラスをインスタンス化し、そのリクエストのフィールドに値を代入します。サービスクラスは、二つのメンバーrequest とresponseを持ちます。 これは二つのクラスの定義 Request と Responseも内包しています。
19 if (client.call(srv))
これは、実際は、サービスを呼び出します。サービスの呼び出しは待機させられ、呼び出しが終わるとreturnします。サービスコールがうまくいけば、call()は、trueを返却し、srv.responseの中の値が使えます。もし呼び出しが失敗していたら、call()はfalseを返却し、srv.responseの中の値は、使えません。
nodeをビルドする
また、beginner_tutorialsのCMakeLists.txtを編集しましょう。
$ rosed beginner_tutorials CMakeLists.txt
最後に以下を加えます。
rosbuild_add_executable(add_two_ints_server src/add_two_ints_server.cpp) rosbuild_add_executable(add_two_ints_client src/add_two_ints_client.cpp)
これは、デフォルトでは、binディレクトリに格納される二つの実行ファイル"add_two_ints_server"と"add_two_ints_client"を生成します。
ROSでCMakeを利用するに当たりさらに情報がほしい場合は、CMakeListsをご覧ください。
さて、makeをしましょう。
$ make
サービスとクライアントのノードをビルドする
また、~/catkin_ws/src/beginner_tutorials/CMakeLists.txtにあるCMakeLists.txtを編集します。そして以下を最後に加えます: https://raw.github.com/ros/catkin_tutorials/master/create_package_srvclient/catkin_ws/src/beginner_tutorials/CMakeLists.txt
27 add_executable(add_two_ints_server src/add_two_ints_server.cpp)
28 target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
29 add_dependencies(add_two_ints_server beginner_tutorials_gencpp)
30
31 add_executable(add_two_ints_client src/add_two_ints_client.cpp)
32 target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
33 add_dependencies(add_two_ints_client beginner_tutorials_gencpp)
これは、デフォルトではdevel spaceの下のパッケージディレクトリに行く二つの実行ファイル"add_two_ints_server" と "add_two_ints_client"を生成します。
これは、デフォルトでは~/catkin_ws/devel/lib/share/<package name>にあるdevel spaceの下のパッケージディレクトリに行く二つの実行ファイル"add_two_ints_server" と "add_two_ints_client"を生成します。実行ファイルを直接実行することも、rosrunを使って実行することもできます。それらは、ROSのシステムにあなたのパッケージをインストールするときにPATHの邪魔になってしまうので、'<prefix>/bin'の中には、置かれていません。インストール時に、PATHのなかに実行ファイルを入れたい場合は、インストール対象を準備することもできます。方法についてはcatkin/CMakeLists.txtを確認してください。
よりCMakeLists.txtファイルについて詳細を知りたい場合は、catkin/CMakeLists.txtを参照してください。
さてcatkin_makeをしましょう:
#catkin ワークスペースで cd ~/catkin_ws catkin_make
もし、なんらかの理由でビルドが失敗したなら、
以前のROSのmsgやsrvなどを作るのチュートリアルの指示通りに行ってきたことを確認する
rosls beginner_tutorials/srv_gen/cpp/include/beginner_tutorials/と打ち、.hファイルが、クライアントやサーバーの.cppファイルでインクルードしたものと一致するかを確認する
ここではシンプルなサービスとクライアントを書きました.次はシンプルなサービスとクライアントをテストしましょう.