ROS 2 launchをXML / YAMLで記述する
海洋ロボコンをやってた人です。
今回はROS 2 のローンチファイルをPythonファイルではなくXML / YAML形式で記述し、Rviz2やGazeboを起動してみたので、その備忘録を記載していきます。
なぜまとめるかは以下です。
- ROS 1はXML形式記述なので、ROS 2でも同様の形式で記述することで可読性を上げたい
- PythonファイルをROS 2パッケージから無くしてみたい
- YAML形式で簡潔にlaunchファイルを記述したい
一方、公式ドキュメント:Using Python, XML, and YAML for ROS 2 Launch Filesに記載もあるように、Pythonでlaunchを記述することで柔軟なlaunchのファイルを作成できるという利点もあります。
このあたりの利点・欠点を理解した上で、各々使用するのが良いと思います。
また、ROS 1のlaunchをROS 2に移植する際は公式ドキュメント:Migrating launch files from ROS 1 to ROS 2も参照してください。
環境はUbuntu 22.04 HumbleでURDFモデルをRviz2とGazeboにスポーンするXMLを想定しています。
自作ノードをXMLで起動させる場合は、Referencesを参考に解読してください。
本記事に対するコメントも積極的に募集しますので、よろしくお願いいたします。
※ 追記 2023/8/21
ということなので、
XMLでlaunchを書きたければ、Autowareを学ぶのが良さそうです。
XML launchでRviz2を起動する
まずはROS 1でRvizを起動するXMLを記載しておきます。
<launch>
<arg name="model" default="$(find fish_robot_description)/urdf/fish_robot.xacro"/>
<arg name="gui" default="true"/>
<arg name="rvizconfig" default="$(find fish_robot_description)/launch/urdf.rviz"/>
<param name="robot_description" command="$(find xacro)/xacro $(arg model)"/>
<param name="use_gui" value="$(arg gui)"/>
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
<node name="rviz" pkg="rviz" args="-d $(arg rvizconfig)" type="rviz" required="true"/>
</launch>
続いてROS 2でRviz2を起動するXMLを記載します。
<?xml version='1.0' ?>
<launch>
<!-- Define arguments -->
<arg name="x" default="3.0" />
<arg name="y" default="-1.0" />
<arg name="z" default="1.0" />
<arg name="roll" default="0"/>
<arg name="pitch" default="0"/>
<arg name="yaw" default="0" />
<arg name="use_gui" default="true"/>
<arg name="robot_name" default="fish_robot" />
<arg name="description_pkg_name" default="fish_robot_description" />
<arg name="xacro_file_path" default="$(find-pkg-share $(var description_pkg_name))/urdf/fish_robot.xacro" />
<arg name="robot_description" default="$(command 'xacro $(var xacro_file_path)')"/>
<arg name="rviz_config_path"
default="$(find-pkg-share $(var description_pkg_name))/rviz/urdf.rviz" />
<!-- Launch URDF -->
<node pkg="robot_state_publisher" exec="robot_state_publisher" output="screen">
<param name="robot_description" value="$(var robot_description)"/>
</node>
<node pkg="rviz2" exec="rviz2" args="-d $(var rviz_config_path)">
<param name="robot_description" value="$(var robot_description)"/>
</node>
<node pkg="joint_state_publisher" exec="joint_state_publisher">
<param name="source_list" value="[robot_joint_states, joint_state_broadcaster/joint_states]"/>
</node>
<group if="$(var use_gui)">
<node pkg="joint_state_publisher_gui" exec="joint_state_publisher_gui" name="joint_state_publisher_gui" output="screen">
<remap from="joint_states" to="robot_joint_states"/>
</node>
</group>
</launch>
ROS 1からROS 2に移植する際の変更点は大きく以下となります。
- パラメータ渡しが$(arg xxxxx) → $(var xxx)と変更
- nodeタグ内でtypeが使用できず、nodeタグ内で別途paramタグを使用する ※1
- $(find pkg_name)/xxx → $(find-pkg-share xxx)/xxxと変更
※1について、以下のような形でparamを宣言します。
公式ドキュメントにもtype, textfile, binfile, executable
コマンドはROS 2ではサポートしていないという記載があります。
-<!-- ROS 1 -->
-<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
+<!-- ROS 2 -->
+<node pkg="robot_state_publisher" exec="robot_state_publisher" output="screen">
+ <param name="robot_description" value="$(var robot_description)"/>
+</node>
XML launchでGazeboを起動する
続いて、GazeboのlaunchもXMLで起動してみましょう。
まずはROS 1でGazeboを起動するXMLを記載しておきます。
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find fish_robot_description)/urdf/fish_robot.xacro"/>
<node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-param robot_description -urdf -model fish_robot"/>
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="paused" value="true"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="headless" value="false"/>
<arg name="debug" value="false"/>
</include>
</launch>
続いてROS 2でGazeboを起動するXMLを記載します。
<?xml version='1.0' ?>
<launch>
<arg name="robot_name" default="fish_robot" />
<arg name="description_pkg_name" default="fish_robot_description" />
<arg name="gazebo_pkg_name" default="fish_robot_gazebo" />
<arg name="xacro_file_path" default="$(find-pkg-share $(var description_pkg_name))/urdf/fish_robot.xacro" />
<arg name="robot_description" default="$(command 'xacro $(var xacro_file_path)')"/>
<arg name="rviz_config_path"
default="$(find-pkg-share $(var description_pkg_name))/rviz/urdf.rviz" />
<arg name="use_sim_time" default="true"/>
<arg name="world_file_path" default="$(find-pkg-share $(var gazebo_pkg_name))/worlds/basic.world"/>
<!-- gzserver -->
<include file="$(find-pkg-share gazebo_ros)/launch/gzserver.launch.py">
<arg name="use_sim_time" value="$(var use_sim_time)"/>
<arg name="world" value="$(var world_file_path)"/>
</include>
<!-- gzclient -->
<include file="$(find-pkg-share gazebo_ros)/launch/gzclient.launch.py">
<arg name="use_sim_time" value="$(var use_sim_time)"/>
</include>
<!-- robot_state_publisher -->
<node pkg="robot_state_publisher" exec="robot_state_publisher">
<param name="use_sim_time" value="$(var use_sim_time)"/>
<param name="robot_description" value="$(command 'xacro $(var xacro_file_path)')"/>
</node>
<!-- spawn_entity -->
<node pkg="gazebo_ros" exec="spawn_entity.py" args="-entity $(var robot_name) -topic /robot_description">
<param name="use_sim_time" value="$(var use_sim_time)"/>
</node>
</launch>
GazeboをXMLで起動する際に大きく違う点は
<!-- gzserver -->
<include file="$(find-pkg-share gazebo_ros)/launch/gzserver.launch.py">
<arg name="use_sim_time" value="$(var use_sim_time)"/>
<arg name="world" value="$(var world_file_path)"/>
</include>
<!-- gzclient -->
<include file="$(find-pkg-share gazebo_ros)/launch/gzclient.launch.py">
<arg name="use_sim_time" value="$(var use_sim_time)"/>
</include>
のgzserver, gzclientの起動箇所でしょうか。
他の記述方法もあるのかもしれませんが、見つけた中ではこの書き方で起動できたので、こちらを使用しています。
他は、ROS 1からROS 2へ移植する際の変更点が変わっているという形です。
上記を実際に動かしてみると
という感じで、XMLでRviz2やGazeboを起動することができます。
YAML launchでRviz2を起動する
launch.yamlでRviz2のconfigとノードを実行させてみます。
launch:
- let:
name: model_name
value: topic_view
- arg:
name: rviz_config
default: $(find-pkg-share ros2_topic_sample)/rviz/$(var model_name).rviz
- arg:
name: use_sim
default: "false"
- arg:
name: use_rviz
default: "true"
- node:
pkg: rviz2
exec: rviz2
if: $(var use_rviz)
args: -d $(var rviz_config)
- node:
pkg: ros2_topic_sample
exec: diagnostic_pub
name: diagnostic_node
output: screen
- node:
pkg: ros2_topic_sample
exec: float32_pub
name: float32_node
output: screen
launch.yamlの動作確認
以上、皆さんのお力添えになれば幸いです。
Likeいただけると大変励みになりますので、よろしくお願いいたします。
Discussion