これまで、ROSをラズパイにいれ、デバックしやすいようにエディタを用意し、Topicを軽く紹介しました。今回はその続きで、service,parameterに関しての記事です。
目次
はじめに Service Service のサンプルコード service の動作 service の他の項目 Parameter Parameter のサンプルコード Parameter の動作 roslaunch 雑記 参考
はじめに
OSとは、ロボット開発を促進するミドルウェアで、特に取り上げる基本要素は以下の3つです。
これまでインストールやTopicについて書いてきましたので良ければ参考にしてください。ROSの詳細についても書いています。Ubuntuに入れた回でROSの理念の概要、Topicの回でROSの通信や構造について多少詳しく書いています。
また、この記事では参考本に沿ってやっていきます。サンプルコードとして記載したのは一部です。全文は本に載っているので参考にしてください。
参考本
Service
Topic回と同様に濃い青が実際に作るプログラム、薄い青がプログラムによって作られたもの、矢印がデータの流れを表しています。
serviceのイメージ図
serviceはNode間の1対1の双方向同期通信です。Topicは複数のNodeにmessageを送っていましたが、serviceは送ったデータを相手が受け取ったかどうかを知りたい場合などに使用します。
非連続的な通信であり、応答が終了すると通信の接続は切断されます。
serviceのサンプルコード
tutorial_serviceを作成します。依存パッケージはmessage_generation , roscpp, std_srvs です。
service_server.cpp
int main(int argc, char **argv){
ros::init(argc, argv, "service_server");
ros::NodeHandle nh;
ros::ServiceServer srv = nh.advertiseService("say_hello", serviceSayHello);
ros::spin();
return 0;
}
service_serverノードは、"say_hello"サービスを提供し、コールバック関数serviceSayHelloを呼び出します。 serviceSayHelloはコンソールで"Hello World"と言うだけの関数ですので、カットしました。 ros::spin関数で永遠にコールバックを待機させています。
service_client.cpp
int main(int argc, char** argv)
{
using std_srvs::Empty;
ros::init(argc, argv, "service_client");
ros::NodeHandle nh;
ros::ServiceClient cli = nh.serviceClient<Empty>("say_hello");
Empty args;
bool ret = cli.call(args);
if(ret) ROS_INFO("Sucess");
else ROS_INFO("Failure");
return 0;
}
service_clientノードは、"say_hello"サービスを利用するクライアントです。 ros::ServiceClient::callでサービスビスを呼び出し、戻り値をうけとり、呼び出しの成否をbool型retで受け取ります(ちょっと自信無いですが)。 成功した場合はコンソールで"Sucess"と表示します。"成功"は正しくは"Success"ですが、綴りを間違えました。
CMakeListでservice_server,service_clientノードを指定し、ビルドします。
serviceの動作
serviceの動作
以下のように表示されてますね(Sucess は Successです)。
Client ->Sucess Server ->Hello World
ノードの様子を確認します。グラフを表示するときには以下のようにコマンド入力します。
$rosrun rqt_graph rqt_graph
tutorial_service動作中のノード
service_serverノードが起動されていることがわかります。serverしか表示されないみたいですね。
Serviceの他の項目
actionはサービスに似た双方向非同期通信です。目標(Goal)、結果(Result)、中間結果(Feedback)で構成されます。 要請から応答までの時間が長い場合や処理中に中間結果が必要な場合に利用されます。
parameter
parameterのイメージ図
ParameterはROSに用意されている設定ファイルに当たる機能です。変数とデフォルトが設定されます。 実機の設定値を決定するのは大変ですが、parameterを利用すると、毎回ソースファイルから変更する手間を省くことができます。
parameterのコード
tutorial_paramパッケージを作成します。依存パッケージはroscppだけです。
param_test.cpp
int main(int argc, char **argv)
{
ros::init(argc, argv, "param_test");
ros::NodeHandle nh;
std::string text = nh.param<std::string>("text", "Hello World");
int repeat_times = nh.param<int>("repeat_times", 10);
double frequency = nh.param<double>("frequency", 0.5);
ros::Rate loop_rate(frequency);
for(int i = 0; i < repeat_times; i++){
ROS_INFO("%s", text.c_str() );
loop_rate.sleep();
}
return 0;
}
パラメータの登録とコンソールへの表示を指示しています。
ros::NodeHandle::paramでパラメータを登録します。text,repeat_time,frequencyを指定し、第一引数の名前のParameterがParameter Server上にない場合、第2引数で与えた値を引数に返すように設定します。
param_testノードを作成してビルドします。
parameterの動作
Parameterの動作
text ->"Hello World" repeat_times -> 10回 frequency -> 0.5Hz
Parameterを指定せずに実行すると、それぞれが指定されていないのでparam_test.cppで記述した通りの規定値(デフォルト)で実行されました。
tutorial_paramのノード
Parameterの登録
以下のようにコマンドを入力すると、Parameter test,5回,2Hzで実行されます。
$ rosparam set /text "Parameter test"
$ rosparam set /repeat_times 5
$ rosparam set /frequency 2.0
$ rosrun tutorial_param param_test
この設定ファイルを外部に保存する場合dump、書き込む場合load機能を実行します。
$rosparam dump ~/params.yaml
作成されたファイルは以下のようになっています。
frequency: 2.0 //記述した部分
repeat_times: 5 //記述した部分
rosdistro: 'melodic
'
roslaunch:
uris: {host_ubuntu__38799: 'http://ubuntu:38799/'}
rosversion: '1.14.3
'
run_id: 74601454-52ee-11e9-94d4-000c2958b845
text: Parameter test //記述した部分
roscoreを再起動すると、これらのパラメータが起動していない状態になりますが、loadするとパラメータが復元できます。
$ rosparam load ~/params.yaml
inomata@ubuntu:~/catkin_ws/src/tutorial_param$ rosparam list
/frequency
/repeat_times
/text
~省略(重要部分のみ表記)~
roslaunch
rosrun以外でノードを起動する方法にroslaunchがあります。roslaunchは複数のノードを実行するときなどに使用される機能です。
tutorial_paramパッケージ内にlaunchディレクトリを作成し、launchファイルを作成し、node,parameterを記述します。
param_test.launch.txt
<?xml version="1.0"?>
<launch>
<node pkg="tutrial_param" type="param.test" name="param.test" output="screen" />
<param name="text" value="parameter test" type="string" />
<param name="repeat_times" value="5" type="int" />
<param name="frequency" value="2.0" type="double" />
</laaunch>
roslaunchを実行します。roscoreを事前に起動しておかなくてもlaunchと同時に起動します。以下のように使用します。
$roslaunch [パッケージ] [launchファイル]
$roslaunch tutorial_param param_test.launch
... logging to /home/inomata/.ros/log/74601454-52ee-11e9-94d4-000c2958b845/roslaunch-ubuntu-14888.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://ubuntu:42297/
SUMMARY
========
PARAMETERS
* /frequency: 2.0
* /repeat_times: 5
* /rosdistro: melodic
* /rosversion: 1.14.3
* /text: parameter test
NODES
/
param_test (tutorial_param/param_test)
ROS_MASTER_URI=http://localhost:11311
process[param_test-1]: started with pid [14912]
[ INFO] [1553954248.157679236]: parameter test
[ INFO] [1553954248.658104672]: parameter test
[ INFO] [1553954249.158001451]: parameter test
[ INFO] [1553954249.658660154]: parameter test
[ INFO] [1553954250.157878784]: parameter test
~省略~
shutting down processing monitor complete done
このように、launchファイルの設定が読み込まれるので、パラメータの設定や動作のログの保存が簡単にできます。 以下のようにしてノードを複数作成することもできます。
<?xml version="1.0"?>
<launch>
<node pkg="tutorial_param" type="param_test" name="param_test1" output="screen" >
<remap from="text" to="param_test1/text" />
<remap from="repeat_times" to="param_test1/repeat_times" />
<remap from="frequency" to="param_test1/frequency" />
<param name="text" value="parameter test1" type="string" />
<param name="repeat_times" value="5" type="int" />
<param name="frequency" value="2.0" type="double" />
</node>
<node pkg="tutorial_param" type="param_test" name="param_test2" output="screen" >
<remap from="text" to="param_test2/text" />
<remap from="repeat_times" to="param_test2/repeat_times" />
<remap from="frequency" to="param_test2/frequency" />
<param name="text" value="parameter test2" type="string" />
<param name="repeat_times" value="10" type="int" />
<param name="frequency" value="1.0" type="double" />
</node>
</launch>
実行結果
$roslaunch tutorial_param param_test_multi.launch
~省略~
process[param_test1-2]: started with pid [16453]
process[param_test2-3]: started with pid [16461]
[ INFO] [1553955293.937496298]: parameter test2
[ INFO] [1553955293.950236042]: parameter test1
[ INFO] [1553955294.448465352]: parameter test1
[ INFO] [1553955294.922201847]: parameter test2
[ INFO] [1553955294.930736280]: parameter test1
[ INFO] [1553955295.430756405]: parameter test1
[ INFO] [1553955295.921917747]: parameter test2
[ INFO] [1553955295.930332254]: parameter test1
[param_test1-2] process has finished cleanly
log file: /home/inomata/.ros/log/2a93dc86-52f6-11e9-94d4-000c2958b845/param_test1-2*.log
[ INFO] [1553955296.921807747]: parameter test2
[ INFO] [1553955297.921376642]: parameter test2
[ INFO] [1553955298.922054324]: parameter test2
[ INFO] [1553955299.922576736]: parameter test2
[ INFO] [1553955300.921124094]: parameter test2
[ INFO] [1553955301.921790482]: parameter test2
[ INFO] [1553955302.921487235]: parameter test2
[param_test2-3] process has finished cleanly
~省略~
done
雑記
ROSシリーズはなんの独自性もない記事になってしまい、反省してます。ラズパイにモータを取り付けるか、Scamperを動かしてもう少し面白い記事にしていきます。
参考