【ROS2】自動起動をサポートするパッケージ robot_upstart を使ってみた

スポンサーリンク

PCを立ち上げるたびに毎回手動でLaunchファイルを立ち上げるのはとても面倒。
PC起動時に自動で起動させれば楽できるけど、そのためにはsystemdのユニットファイルというのを作らないといけない。 ユニットファイルは自由度が高いので書き方に迷うし、使用するファイルの管理も迷うところ。。。
そこで、ROS2向けにLaunchファイルからユニットファイルを作成してくれる robot_upstart というパッケージを見つけたので使ってみました。

robot_upstartを使うメリット

自分にとっては、詳しい人が作ってくれたユニットファイルをそのまま使える点が大きいです。 昔、自分でユニットファイルを書いたことがありますが、自由度が高いので迷いがちです。

  • ユニットファイルに実行したい内容を直接書かない方がデバッグしやすいけど、複数ファイルに分割する?
  • 複数ファイルに分けたら、ファイルはどこに置く?
  • ユーザーはrootのままでいい?
  • stop時に停止させる必要があるけど、どうやって実現する?

自分で書くと悩む点も多いですが、robot_upstart を使えば全部解決。

Ver. 1.0.3時点での制約

Ver. 1.0.3で確認したところ、自動起動できるLaunchファイルには次の制約がありました。

  • Launchファイルのファイル名の末尾が .launch.py であること
  • Launchファイルはどこかのパッケージに含まれていること
  • コマンドラインオプションを使っての引数設定やremapはできない
  • 自動起動対象がデバイスにアクセスする場合は、udevルールと呼ばれる登録が必要

上記条件に当てはまらないLaunchについては、一度上記に当てはまるように「Launchを呼び出すLaunchファイル」を作って、どこかのパッケージに含める必要があります。作り方は公式チュートリアル参照。

環境

PC: TRIGKEY Green G5
OS: Ubuntu 22.04.3
ROS2 : Humble

robot_upstartのインストール

$ sudo apt install ros-humble-robot-upstart

自動起動の設定例

次のLaunchファイルを自動起動させる場合の例です。
ワークスペース:/home/taro/ros2_ws
パッケージ名:susumu_robo
Launchファイル:ros2_teleop_twist_joy.launch.py

事前確認

まずは自動起動させたいLaunchファイルが普通に起動できるか確認

$ source /home/taro/ros2_ws/install/setup.bash
$ ros2 launch susumu_robo ros2_foxglove_bridge.launch.py


自動起動の設定

あとはros2 run robot_upstart instal を実行すれば、ユニットファイルの作成、自動起動の有効化までやってくれる。

$ ros2 run robot_upstart install --job ros2_foxglove_bridge --systemd-after nss-lookup.target --setup /home/taro/ros2_ws/install/setup.bash --symlink susumu_robo/launch/ros2_foxglove_bridge.launch.py

「--job」オプションを指定するのがオススメ。指定しないとJOB名はパッケージ名から適当に作られてしまう。
ワークスペースのsetup.bashを実行する必要があるなら、「--setup」オプションの指定も必要。
他サービス起動後に起動させたい場合は、「--systemd-after」オプションを指定する。

実行時の出力。 色々作ってくれます。

found_path: /home/taro/ros2_ws/install/susumu_robo/share/susumu_robo/launch/ros2_foxglove_bridge.launch.py
candidate : /home/taro/ros2_ws/install/susumu_robo/share/susumu_robo/launch/ros2_foxglove_bridge.launch.py
b'/usr/lib/systemd/systemd'
Preparing to install files to the following paths:
  /etc/ros/humble/ros2_foxglove_bridge.d/.installed_files
  /etc/ros/humble/ros2_foxglove_bridge.d/ros2_foxglove_bridge.launch.py
  /etc/systemd/system/multi-user.target.wants/ros2_foxglove_bridge.service
  /lib/systemd/system/ros2_foxglove_bridge.service
  /usr/sbin/ros2_foxglove_bridge-start
  /usr/sbin/ros2_foxglove_bridge-stop
Now calling: /usr/bin/sudo /opt/ros/humble/share/robot_upstart/scripts/mutate_files
Filesystem operation succeeded.
** To complete installation please run the following command:
 sudo systemctl daemon-reload && sudo systemctl start ros2_foxglove_bridge


再起動して確認

先程のコマンドで自動起動の設定は終わっているので、あとはPC再起動して確認するだけ。

$ ros2 node list
/foxglove_bridge
/foxglove_bridge_component_manager

設定した自動起動の削除

自動起動が不要になったら、「ros2 run robot_upstart uninstall JOB名」でキレイさっぱり削除してくれる。

$ ros2 run robot_upstart uninstall ros2_foxglove_bridge


サービスの操作例

JOB名を ros2_foxglove_bridge にした場合の例

状況確認

$ sudo systemctl status ros2_foxglove_bridge


手動起動

$ sudo systemctl start ros2_foxglove_bridge


手動停止

$ sudo systemctl stop ros2_foxglove_bridge


自動起動が有効かどうか確認

$ sudo systemctl is-enabled ros2_foxglove_bridge


自動起動の無効化

$ sudo systemctl disable ros2_foxglove_bridge


自動起動の有効化

$ sudo systemctl enable ros2_foxglove_bridge


ログ確認

$ sudo journalctl -u ros2_foxglove_bridge

ログの行末が途切れる場合は、次のように指定すれば表示される。

$ sudo journalctl -u ros2_foxglove_bridge --no-pager


名前にros2が含まれるサービス状況(概要)

$ sudo systemctl list-units --type=service | grep -e ros2 -e UNIT


名前にros2が含まれるサービスの自動起動設定状況(概要)

$ sudo systemctl list-unit-files --type=service | grep -e ros2 -e UNIT


トラブル対応

自動起動に失敗する

別記の 手動起動 でも再現するか、手動起動で確認する。
別記の journalctl か systemctl status で ログを確認する。

手動起動は成功するのに自動起動に失敗する

「--systemd-after」オプションを指定していないと、他サービスが立ち上がってない状態でも起動しようとする。
依存サービスを「--systemd-after」オプションで指定する必要があるが、何が必要になるかは自動起動させる内容次第。
ネットワーク名前解決が必要なら「nss-lookup.target」、ネットワーク通信が必要なら「network-online.target」を指定が必要。

Unable to generate amalgamated launchfile. というログが表示されて起動できない

  • ユニットファイルを作成するコマンド「ros2 run robot_upstart install」で間違った指定をした
  • Launchファイル名の末尾が .launch.py ではない

自動起動やsystemctlで起動した場合のみ、各種デバイスにアクセスできない

udevルールと呼ばれる設定が必要

udevルールの記述例:

$ sudo vi /etc/udev/rules.d/99-custom.rules

ファイルの中身の例:

ACTION=="add", KERNEL=="tty[A-Z]*[0-9]", MODE="0666"
ACTION=="add", KERNEL=="js[0-9]*", SUBSYSTEM=="input", MODE="0666"
ACTION=="add", KERNEL=="event*", SUBSYSTEM=="input", MODE="0666"

udevルールの再読み込み

$ sudo udevadm control --reload

robot_upstart installの使い方

$  ros2 run robot_upstart install -h
usage: install [-h] [--job JOB] [--rmw rmw_fastrtps_cpp] [--rmw_config RMW_CONFIG] [--interface ethN]
               [--ros_domain_id ROS_DOMAIN_ID] [--user NAME] [--setup path/to/setup.bash] [--rosdistro DISTRO]
               [--logdir path/to/logs] [--augment] [--provider [upstart|systemd]] [--symlink] [--wait]
               [--systemd-after After=]
               pkg/path [pkg/path ...]
省略

pkg/pathはパッケージ名から始まるlaunchファイルのパス

オプション内容 (ほぼ機械翻訳)

オプション 説明
-h, --help ヘルプ
--job JOB ジョブ名を指定します。 指定しない場合、パッケージ名 (前の最初の要素) から構築されます。アンダースコアが取得されます。例: パッケージ名が「myrobot_bringup」の場合は「myrobot」)。
--rmw rmw_fastrtps_cpp 使用するRMW DDSを指定します。 rmw_fastrtps_cpp または rmw_cyclonedds_cpp
--rmw_config RMW_CONFIG RMW構成URI
--interface ethN ジョブを関連付けるネットワーク インターフェイス名を指定します。
--ros_domain_id ROS_DOMAIN_ID ROS_DOMAIN_ID 値。
--user NAME ジョブを起動するユーザーを指定します。デフォルトは現在のユーザー。
--setup path/to/setup.bash ジョブ起動コンテキストのワークスペース設定ファイルを指定します。
--rosdistro DISTRO 対象となる ROS ディストリビューションを指定します。
--logdir path/to/logs パス/ログへのジョブ起動コンテキストで ROS_LOG_DIR の値を指定します。
--augment ジョブの作成をバイパスし、ユーザー ファイルのみをコピーします。 ジョブが以前に作成されていると仮定します。
--provider [upstart|systemd] 自動検出が正しいプロバイダーを識別できない場合はプロバイダーを指定してください
--symlink ジョブ起動ファイルをコピーするのではなく、そのファイルへのシンボリック リンクを作成します。
--wait 待機フラグを roslaunch に渡します。
--systemd-after 生成するsystemd ユニットファイルの After= セクションの文字列を指定します。

リンク

robot_upstart
Launchファイルの作成方法(公式)