概要
ROS1でも使われていたxml形式のlauncherは見やすく扱いやすい反面、イマイチどんな時にどう書けば良いのかのドキュメントが不足している印象があります。
本記事では下記の2ケースについて書き方を記します。
- 通常の条件分岐
- 重ね合わせの条件分岐
通常の条件分岐
group ifの構文を使って条件分岐が可能です。
<let name="true_arg" value="true"/>
<let name="eval_str" value="hogefuga"/>
<!-- normal case1 -->
<group if="$(var true_arg)">
<group/>
<!-- normal case2 -->
<group if="$(eval "'$(var eval_str)'=='hogefuga'")">
<group/>
多重の条件分岐
ちょっと凝ったlauncherを考えるとANDやORで条件分岐を重ねたいときがあります。(設計として良いかは別問題ですが)
動作確認はROS2 humbleで行いました。
ANDとORの正解ケース
結論から言うと下記のように書くことで複数条件のAND/ORの条件分岐が可能でした。
3つ以上の要素は未検証です。(誰かやってみてください)
<let name="true_arg" value="true"/>
<let name="false_arg" value="false"/>
# AND
<group if="$(eval "'$(var false_arg)'=='true' and '$(var true_arg)'=='true'")"> #ちゃんとFalse
<group/>
# OR
<group if="$(eval "'$(var false_arg)'=='true' or '$(var true_arg)'=='true'")"> #ちゃんとTrue
<group/>
なお、当時のmarkdownのメモ書きなのでコメントなどの文法が無効な点にはご注意ください。
意図しない挙動をする書き方例
True and True
みたいな文をイメージして下記のように書くと意図しない挙動になるのでご注意ください。
eval quotの中身がPythonの記述として処理されるらしいのですが純Pythonだとそうはならないと思ってるので自分は理由をうまく説明できません。
#後ろが評価される
<group if="$(eval "'$(var false_arg)'and'$(var true_arg)'")"> これはTrue
#前が実行される
<group if="$(eval "'$(var false_arg)'or'$(var true_arg)'")"> これはFalse
おまけ(boolではなく0,1の数値の場合)
0,1でフラグ管理すること自体は不可能ではなく、珍しくもないですが重ね合わせ時には見づらいのでやめたほうが良いと感じました。
<let name="true_arg" value="1"/>
<let name="false_arg" value="0"/>
<group if="$(eval "$(var false_arg)+$(var true_arg)")"> これは怒られる
expected one of [true, 1, false, 0] but got '01'内部ではStringになっているみたい。
<group if="$(eval "$(var false_arg)+$(var true_arg)")"> これなら平気だが1+1=2になると怒られる
<group if="$(eval "$(var true_arg)+$(var true_arg)==2")"> これはANDとして使える
<group if="$(eval "$(var false_arg)+$(var true_arg)>0")"> ORはこう書ける
おわりに
他にもROS2のxmlのlauncherでcontainerを設定したりなど、「あまりどこにも書かれていないけど実はできる」みたいな機能が結構あるのでもし知っている人が居たら雑記ぶん投げでも良いので公知にしていってほしいです。