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 ではない
「*.launch.py' にアクセスできません: そのようなファイルやディレクトリはありません」というログが表示され手動起動できない
~.launch.pyファイルを作成したのに、下記ログが表示されて起動できない場合、colcon buildやアンダーレイ用のスクリプトの実行できていないかも。
4月 25 22:21:25 g-tune ros2_twist_stamper-start[4387]: ls: '/etc/ros/humble/ros2_foxglove_bridge .d/*.xacro' にアクセスできません: そのようなファイルやディレクトリはありません 4月 25 22:21:25 g-tune ros2_twist_stamper-start[4390]: ls: '/etc/ros/humble/ros2_foxglove_bridge .d/*.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= セクションの文字列を指定します。 |