極楽とんぼのロボット製作記

情報工学系大学院生がロボットとその周辺技術や身の回りの出来事について紹介するブログ

【ROS】一斉にnodeを起動するLaunchの書き方

roslaunchとは

予めlaunchファイルに記述したnodeとroscoreを同時に複数立ち上げてくれるツールです。launchファイルはXMLで記述します。

f:id:gokuraku104robot:20170923103729p:plain
launchファイルの例

基本的なlaunchの書き方

基本的な書き方はROSの公式に書いてあります。
ja/roslaunch/XML - ROS Wiki

<launch>
    <node pkg="ros_pkg" name="node_name" type="file_name"/>
</launch>

launchタグで囲んで、起動したいノードをnodeタグで囲みます。
pkg:パッケージ名(ex. hoge_ros)
type:実行ファイル名(ex. hoge_ros_node)
name:ノード名(ex. hoge_ros)

起動方法

$ roslaunch ros_pkg ros_pkg.launch

これだけだと普通にrosrunするのと手間が変わらなく感じますが、launchの良い所はroscoreが立ち上げっていなければ、自動的にroscoreも立ち上げてくれるところです。

同一実行ファイル複数ノードの立ち上げ方法

ここからがlaunchの本来の目的である複数ノードに対して様々な設定を施しながら起動する方法です。

<launch>
    <node pkg="ros_pkg" name="node_first" type="file_name"/>
    <node pkg="ros_pkg" name="node_second" type="file_name"/>
</launch>

name="node_first", name="node_second"のように、ノード名を変更することで同一実行ファイルを複数起動できます。

パラメータを設定する(param)

複数ノード立ち上げるとノードごとにパラメータを設定したくなりますよね。その際はnodeタグの間にparamタグを書き、パラメータを設定します。こうすることでそのノードのプライベートパラメータを設定できます。

<launch>
    <node pkg="ros_pkg" name="node_first" type="file_name">
        <param name="init_param" value="1"/>
    </node>
    <node pkg="ros_pkg" name="node_second" type="file_name">
        <param name="init_param" value="2"/>
    </node>
</launch>

これらのパラメータをプログラム上で読み出すには以下のようにします。
C++での例

    ros::NodeHandle node_private("~");  //プライベートパラメータを読みだすためのノードハンドル
    int initNum //プライベートパラメータを格納する変数
    if(node_private.getParam("init_param", initNum))  //プライベートパラメータの取得
    {
        ROS_INFO_STREAM("initialization in: " << initNum ); //パラメータ取得時,パラメータを表示
    }
    else
    {
        ROS_ERROR_STREAM("Failed to get init_param at " << ros::this_node::getName()); //パラメータ取得失敗時,ノード名を表示
    }

引数を与える(arg)

パラメータを変更するのにいちいちlaunchファイルを変更するのも面倒ですよね。そんな時はargで引数を設定しましょう。引数を設定するには以下のようにします。

<launch>
    <arg name="hoge"/>
    <node pkg="ros_pkg" name="node_name" type="file_name">
    </node>
</launch>

これでhogeという名前の引数を設定できます。当然これだけではただその引数が"ある"というだけで何の約にも立ちません。引数をパラメータに入れるには次のようにします。

<launch>
    <arg name="hoge"/>
    <node pkg="ros_pkg" name="node_name" type="file_name">
    <param name="piyo" value="$(arg hoge)"/> 
    </node>
</launch>

これで引数"hoge"をパラメータ"piyo"に入れることができます。
実行する際は

$ roslaunch ros_pkg ros_pkg.launch hoge:=1

のようにして実行します。
パラメータの与え方は3種類あります。

<arg name="hoge"/> 
<!-- 引数hogeの宣言 必ずコマンドライン引数を与える必要があります。-->
<!-- 引数を設定しなかった場合、requires the 'hoge' arg to be set 
と言われ、launchの起動が中止されます。-->

<arg name="hoge" default="1.0"/>
<!-- 引数hogeにデフォルトの値を設定できます。
もちろんコマンドラインからデフォルトの値を上書きすることもできます。-->

<arg name="hoge" value="1.0"/>
<!-- 引数hogeをvalueの値で初期化します。上書きができません。-->
<!-- 上書きしようとすると、
Invalid <arg> tag: cannot override arg 'hoge', which has already been set. 
と言われ、launchの起動が中止されます。-->

引数として設定するものとしては画像データのパブリッシュのフラグなどがあります。デバック時にはカメラのimageを出していてほしいけど、通常は要らない場合などに、パラメータとしてフラグを設定して、画像の有り無しを切り替えることができます。

topic名を変更する(remap)

ソースファイル内でトピック名を決め打ちしていると、いざ別名でトピックをパブリッシュしたりサブスクライブしたりしたくなった時に不便です。普通なら名前を変えてからもう一度コンパイルすることを考えますが、ROSではその必要はありません。remapを使うことでトピック名も編集することができます。
またトピックをパブリッシュするノードを複数立ち上げると、同じ名前でそれぞれがトピックをパブリッシュしてしまいます。こんな時もremapの出番です。
以下はhoge_pubというトピックをpiyo_pubというトピックに変更しています。もちろんパブリッシャーだけでなくサブスクライバーのトピックも変更できます。
fromに変更したいトピック名、toに変更後のトピック名を設定してください。

<launch>
    <node pkg="ros_pkg" name="node_name" type="file_name">
    <remap from="/hoge_pub" to="/piyo_pub" />
    </node>
</launch>

名前空間を設定する(group)

起動するノードが増えてくるとでのノード名の変更やremapでのトピック名変更が面倒になってきます。そんな時はgroupで名前空間を設定しましょう。こうすることで、同じノードでも1つのroscore上に存在できます。

<launch>
    <group ns="ns1">
        <node pkg="ros_pkg" name="node_name" type="file_name">
        <remap from="/hoge_pub" to="/piyo_pub" />
        </node>
    </group>

    <group ns="ns2">
        <node pkg="ros_pkg" name="node_name" type="file_name">
        <remap from="/hoge_pub" to="/piyo_pub" />
        </node>
    </group>
</launch>

名前空間を設定するとノード名やトピック名が名前空間で修飾されます。具体的にはrosnode listすると

$ rosnode list
/ns1/node_name
/ns2/node_name

のようになります。
同じようにトピック名に関しても

$ rostopic list
/ns1/node_name/piyo_pub
/ns2/node_name/piyo_pub

のようになります。

ROS_INFO,ROS_WARN,標準出力を表示する

通常、launchを用いて起動すると、ROS_INFO,ROS_WARN,標準出力などが表示されません。デバッグ等でこれらを表示したい時は以下のようにします。
launch起動時に--screen

$ roslaunch ros_pkg ros_pkg.launch --screen

or
launchのnodeにoutput="screen"

<launch>
    <node pkg="ros_pkg" name="node_name" type="file_name" output="screen"/>
</launch>

さらに複雑なlaunchを作りたい方はこちらが参考になります。
大きなプロジェクトでどのようにlaunchを設定すべきか解説されています。
ja/roslaunch/Tutorials/Roslaunch tips for larger projects - ROS Wiki


参考
ja/roslaunch/Commandline Tools - ROS Wiki
ja/roslaunch/XML - ROS Wiki
roslaunch/XML/arg - ROS Wiki
ろすでろぼっと: launchファイルを調べる
ROS launchファイルの使い方
ja/roslaunch/Tutorials/Roslaunch tips for larger projects - ROS Wiki

ROS初心者向けの参考書です。インストール方法からシミュレータ上でロボットを動かすところまで解説されています。ROSの公式のチュートリアルよりもバリエーションが多くRoombaやPR2などを動かせるので飽きないところも良いところです。