はじめに
ロボット制御ROSを自動起動する必要があり、ROSパッケージのrobot_upstartと
ROSを自動起動するを参考に自分で書く、2パターンでトライしてみましたのでそのメモです。
結論としては、使うデバイスやLaunchファイルの数が少ないシンプルな構成の時はrobot_upstart
、デバイスやPermissionが複雑な構成の時は自分で書いた方が幸せになれるように思います。
環境
- Ubuntu 18.04 (JetPack 4.1.1 Developer Preview)
- ROS Melodic Morenia
- Jetson AGX Xavier
#比較
どちらも、実施していることはサービスの作成です。なので、robot_upstart特有のトレードオフというよりは「ツールを使うか自作するか」という種の問題に一般的な長所短所があります。
長所 | 短所 | |
---|---|---|
robot_upstart | - 導入と使用方法が簡便 - Linux特有の知識はほぼ不要 |
- 自動化されすぎててデバッグが面倒 |
自分で書く | - 柔軟性が高い - デバッグが容易 |
- Linux (Ubuntu)の知識がある程度必要 |
robot_upstartを使ってみた
robot_upstart
の導入は簡単です。わずか一行。
sudo apt-get install ros-<distro>-robot-upstart
次に、自動で起動させたいlaunch fileを登録します。これも簡単。
rosrun robot_upstart install <your_package_name>/launch/<your_launch_file>.launch
これだけで、次回起動時には登録したlaunchファイルが起動するようになります。
robot_upstartのつまづきポイント
ログの出力先がドキュメントと異なる。
たぶんドキュメントが更新されてないだけだと思いますが、私の環境ではドキュメントに書いてある/var/log/upstart
ではなく/var/log/syslog
に出力されていました。
環境変数の設定
setuidgid
で直接roslaunch
を叩いているためか.bash_profile
や.bashrc
が読み込まれないので、必要な環境変数が無かったり意図しない値になってたりすることがあります。
こちらにあるように、必要な設定を書いた.robotrc
などの適当なファイルを作って/opt/ros/<distro>/setup.bash
や<your_catkin_ws>/devel/setup.bash
からsource path/to/your/file
してあげるのが良いようです。
【参考】
ログインシェルとインタラクティブシェルと~/.bashrc達の関係
How to reference environmental variables inside an upstart installed launch file
CUDAがエラーになる(未解決)
CPUオンリーのノード群は問題なく上記の設定で動いたのですが、私の環境ではCUDAを使っているノードがエラーでコケてしまい立ち上がりませんでした。
おそらく何かのPermissionが適切に設定されてないためだと思うのですが、未解決です。
自分で書いてみた
一見とっつきづらいですが、ROSを自動起動するを参考に書いていくと意外と簡単に書けました。
非常にわかりやすい記事を書いてくださった@strv様に感謝です。
robot_upstartで直面したCUDAエラーもこちらでは発生しなかったので、私は現在こちらを使用しています。
自分で書いた場合のつまづきポイント
デバイスをsystemdで利用可能にする
systemdで利用可能なデバイス名については、
systemctl --t device -a --full
で確認することが出来ます。
とありますが、デバイスによってはデフォルトのままだとこのリストに出てこないことがあります。
そういう時は、該当するデバイスのudevルールにTAG+="systemd"
を追加してあげましょう。
既存のルールが無い場合は自分で作成しても大丈夫です。私の場合は下記のようなudevルールを用意しました。
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", TAG+="systemd", SYMLINK+="sensor_device%n", MODE="0666"
【参考】
Raspberry Pi 2 + systemd + udevで、USBデバイス挿入時にサービスを起動する、Linux でデバイスを接続している時だけ動くサービスを作る)
roscoreの検出
元記事だとExecStartPre=/bin/bash -l -c 'rostopic list'
でroscoreの検出を行っていますが、このやり方だとrostopic list
が失敗した時点でサービス自体が落ちるので、後ろに書いてあるRestart=always
との合わせ技で成立しています。
ExecStartPre=/bin/bash -l -c 'rostopic list'
<中略>
Restart=always
元々の方針としてRestart=always
であるlaunchファイルならこのやり方が良いと思いますが、私の場合は多数のデバイスが絡むlaunchファイルになっていて頻繁に再起動するような仕様にしたくなかったのでRestart=no
にしています。
この場合rostopic list
でのroscore検出が出来ないので、元記事のコメントにあるようにroslaunch --wait
オプションで待ってあげる必要があります。
ExecStart=/usr/bin/screen -S mavros -ADm bash -l -c 'roslaunch --wait mavros px4.launch'