えいあーるれいの技術日記

ROS2やM5 Stack、Ubuntuについて書いています

YAMLでComposableNodeを起動する(ROS2・launch_yaml)②

この記事はROS2アドベントカレンダー2022、12/18 の記事です。


同じアドベントカレンダーでcomposable nodeを含むlaunchをPythonからxmlに置き換える記事が出ています。

qiita.com

記事中の 冗長なPythonのlaunchを書く必要があったのですが、HumbleからはXMLで記述できるようになりました。 を見て、

これは、yamlについて書かなくては…! と思ったので私もまた言及しようと思いました。


(ちなみに、composable_nodeをyamlで呼び出すこと自体は半年前の記事にあります。)

YAMLでComposableNodeを起動する(ROS2・launch_yaml) - えいあーるれいの技術日記


バージョンを重ねるたびに機能が追加されており、composable_nodeはROS-Humbleからの機能です。


LaunchのYAMLXML(仕様)

launch_rosでは、Pythonからのlaunch操作は直接呼び出して、それ以外はParserを介して解釈させます。

解釈されたタグをもとに @expose_action(node_container) などのデコレータ関数に飛ばします。

github.com

仕組みがコレなので、XMLYAMLの仕様は同一というわけです。

XMLで使えるものはYAMLでも使える(はず)です。

解釈部分については launch 内の launch_yaml と launch_xml に記載されています。

github.com

LaunchのYAMLXML(記法)

でも、XMLYAMLはぱっと見る感じ全然違う雰囲気があるのですぐ乗り換えるのはな〜…と思いがちですが、

いくつかポイントを押さえれば簡単です。

(元記事の「XMLでの記述方法」を参考に説明します。)

qiita.com


ハッシュ

ハッシュとは、YAMLキーワード: 値 の組み合わせのことです。

素数は一つだけでなく、複数にすることもできます。

# ハッシュの例
a: b
b:
  c: d
  d: e
  f: g


XMLの属性(abc="def"のように記述するやつ)はすべてハッシュで記述されます。

例えば、以下のように書かれているxmlがあるとします。

<node_container pkg="rclcpp_components" exec="component_container" name="my_container" namespace="" args="test_args"/>

これをYAMLに直すと次のようになります。

node_container:
    pkg: "rclcpp_components"
    exec: "component_container"
    name: "my_container"
    namespace: ""
    args: "test_args"


配列

配列は - で接続された主に複数の要素を記述するものです。

こちらは、XML名前空間入れ子にする際に使用します。

例えば、以下のように書かれているxmlがあるとします。

<load_composable_node target="my_container">
  <composable_node pkg="demo_nodes_cpp" plugin="demo_nodes_cpp::ParameterBlackboard" name="board2" namespace="test_namespace">
    <param name="test" value="aaa" />
    <extra_arg name="use_intra_process_comms" value="true" />
  </composable_node>
</load_composable_node>

これをYAMLに直すと次のようになります。

- load_composable_node:
     target: "my_container"
     composable_node:
        -
          pkg: demo_nodes_cpp
          plugin: "demo_nodes_cpp::ParameterBlackboard"
          name: "board2"
          param:
             -
               name: "test"
               value: "aaa"
          extra_arg:
             -
               name: "use_intra_process_comms"
               value: "true"

値が紐づけられない名前空間の接続は全て配列になっています。


以上を踏まえて、先の記事のXMLからYAMLに変換したコードを以下に示します。

launch:
    - node_container:
        pkg: "rclcpp_components"
        exec: "component_container"
        name: "my_container"
        namespace: ""
        args: "test_args"
        composable_node:
           -
             pkg: demo_nodes_cpp
             plugin: "demo_nodes_cpp::ParameterBlackboard"
             name: "board1"
             namespace: "test_namespace"
             param:
             -
               name: "test"
               value: "aaa"
             extra_arg:
             -
               name: "use_intra_process_comms"
               value: "true"
    - load_composable_node:
             target: "my_container"
             composable_node:
               -
                 pkg: demo_nodes_cpp
                 plugin: "demo_nodes_cpp::ParameterBlackboard"
                 name: "board2"
                 namespace: "test_namespace"
                 param:
                 -
                   name: "test"
                   value: "aaa"
                 extra_arg:
                 -
                   name: "use_intra_process_comms"
                   value: "true"


demo_nodes_cpp の talker_listener.launch.py も次のように書けます。

launch:
  - node_container:
      pkg: "rclcpp_components"
      exec: "component_container"
      name: "my_container"
      namespace: ""
      composable_node:
        -
          pkg: "demo_nodes_cpp"
          plugin: "demo_nodes_cpp::Talker"
          name: "node_talker"
          remap:
          -
            from: /chatter
            to: /talker_listener
        -
          pkg: "demo_nodes_cpp"
          plugin: "demo_nodes_cpp::Listener"
          name: "node_listener"
          remap:
          -
            from: /chatter
            to: /talker_listener


まだまだある!?オプション

launch/test_executable.py at galactic · ros2/launch · GitHubより

launch:
    - executable:
        cmd: ls -l -a -s
        cwd: '/'
        name: my_ls
        shell: true
        output: log
        'launch-prefix': $(env LAUNCH_PREFIX '')
        env:
            - name: var
              value: '1'

ls コマンドをルートディレクトリに対して行うlaunch.yamlです。executableキーを使用して実行するみたいです。


launch/test_include.py at humble · ros2/launch · GitHubxml)より

launch:
    - let: { name: launch_path, value: "/opt/ros/humble/share/demo_nodes_cpp/launch/topics/" }
    - include:
        file: "$(var launch_path)talker_listener.launch.py"

他のlaunchファイルもyamlで実行できます。

includeもとを辿る方法は見つけられませんでした…

ROS1で見られた $(find <pkg>) は使えませんでした。


サンプルが少ないので流行りにくさは感じますが、かなりスッキリとかけると思います。