😀

ROS 2のcomposable nodeを含むlaunchをPythonからXMLに置き換える(Humble)

2022/11/27に公開

この記事ではROS 2 Humbleから使えるlaunch xmlの記述方法について紹介したいと思います。

ROS 2におけるlaunchの形式

ROS 2で使えるlaunchの形式はPython, XML, YAMLの3つがあります。
ただしすべて同じ機能が使えるわけではなく、すべての機能はPythonで実装されており、
expose_action/expose_substitutionのデコレーターが付与されてるものが、
XML/YAMLでtag/keyとして使えるようになっています。

Galacticまでは、composable nodeのloadやcontainerの起動をするには、
冗長なPythonのlaunchを書く必要があったのですが、Humbleからは
XMLで記述できるようになりました。(私の同僚の@kenji-miyake さんが実装してくれました。)

Pythonでの記述方法

まずは従来のPythonでの記述方法から見ていきます。

from launch import LaunchDescription
from launch_ros.actions import LoadComposableNodes, ComposableNodeContainer
from launch_ros.descriptions import ComposableNode

def generate_launch_description():
    container = ComposableNodeContainer(
        name="my_container",
        package="rclcpp_components",
        executable="component_container",
        namespace="",
        arguments="test_args",
        composable_node_descriptions=[
            ComposableNode(
                package="demo_nodes_cpp",
                plugin="demo_nodes_cpp::ParameterBlackboard",
                name="board1",
                parameters=[
                    {"test": "aaa"}
                ],
                extra_arguments=[{"use_intra_process_comms": True}],
            ),
        ],
        output="screen",
    )

    load_composable_nodes = LoadComposableNodes(
        target_container="my_container",
        composable_node_descriptions=[
            ComposableNode(
                package="demo_nodes_cpp",
                plugin="demo_nodes_cpp::ParameterBlackboard",
                name="board2",
                namespace="test_namespace",
                parameters=[
                    {"test": "aaa"}
                ],
                extra_arguments=[{"use_intra_process_comms": True}],
            ),
        ],
    )

    return LaunchDescription([
        container,
        load_composable_nodes,
    ])

ComposableNodeContainerがcomposable nodeをloadするためのcontainerです。
composable_node_descriptionsにloadするcomposable nodeを記述します。
またすでにcontainerが起動している場合は、LoadComposableNodestarget_containerにcomposable nodeをloadしたいcontainerを指定することで、composable_node_descriptionsに記述したnode群をloadすることができます。

XMLでの記述方法

上記のPythonで記述されたlaunchをXMLで置き換えたものが以下になります。

<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" />
    </composable_node>
  </node_container>

  <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>
</launch>

PythonのclassとXMLのtagの対応関係は以下のようになっています。

  • ComposableNodeContainernode_container (exposeの実装)
  • ComposableNodecomposable_node
  • LoadComposableNodesload_composable_node (exposeの実装)

(composable_nodeのみnode_container/load_composable_nodeの下のcomposable_node entityを読みにいくという実装だったため、exposeの記述はありませんでした。実装箇所)

コードの記述量が減り、だいぶスッキリしました。

GitHubで編集を提案

Discussion