remap がよくわからない
launch ファイル内で,ROS上のいろいろなものの名前を再割当てできる remap という要素があるのですが,公式ドキュメントの素っ気なさに泣いた人はいませんか.
自分は泣きました.
結構な時間,見てみないふりをしつつなんとなくで使っていたのですが, remap について動作確認をして納得したのでここにメモ書きします.
ちなみに remap は,いろいろなものの名前を置き換えることができるので,一度理解すると便利に使えると思います.
from と to ってどっちにどっちを書くの?
公式ドキュメントにはこう書かれています.
from="original-name"
Name that you are remapping.
to="new-name"
Target name.
正直良くわかりません.
結論からいうと, from には,その有効範囲の物の名前を, to には最終的に ROS 上で共有される名前を記入します.
remap が node 要素内で使われている場合では, node 内で使われている名前を from に書くということです.
考え方として重要なのは,roslaunch の remap 機能を使うと,完全に ROS上の名前が置き換えられるということです.
エイリアスが作られて,別名でもアクセス出来るようになる,という機能ではありません.
例えば Topic 名を remap する場合を考えて,すでに publish されている topic を remap して subscribe する場合を考えるとわかりやすいかと思います.
もし from がすでに publish されている topic 名だとすると, remap することで,publish 済みの topic 名まで変わらないと整合しないことになってしまいます.
remap のネームスペースの書き方がわからない
例えば pubtime というノードが, /time_abs
と ~time_rel
という名前で topic を publish している場合を考えます.
これをroslaunch で pubtime を pubtime1 という名前で実行すると,rostopic listの結果は次のようになるはずです.
/pubtime1/time_rel
/time_abs
~
が頭に付いている名前はローカルネームスペース内に展開されるため,上記のようになります.
これをlaunchファイル内でremapしたい時の書き方は次のとおりです.
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<node pkg="ros_sandbox" type="pubtime" name="pubtime1">
</node>
<node pkg="ros_sandbox" type="pubtime" name="pubtime2">
<remap from="~time_abs" to="time_abs_remaped" />
<remap from="~time_rel" to="time_rel_remaped" />
</node>
<node pkg="ros_sandbox" type="pubtime" name="pubtime3">
<remap from="time_abs" to="time_abs_remaped" />
<remap from="time_rel" to="time_rel_remaped" />
</node>
<node pkg="ros_sandbox" type="pubtime" name="pubtime4">
<remap from="~time_abs" to="~time_abs_remaped" />
<remap from="~time_rel" to="~time_rel_remaped" />
</node>
<node pkg="ros_sandbox" type="pubtime" name="pubtime5">
<remap from="/time_abs" to="~time_abs_remaped" />
<remap from="/pubtime5/time_rel" to="~time_rel_remaped" />
</node>
<!-- "_" は使えない
<node pkg="ros_sandbox" type="pubtime" name="pubtime5">
<remap from="_time_abs" to="_time_abs_remaped" />
<remap from="_time_rel" to="_time_rel_remaped" />
</node>
-->
</launch>
これの実行時にrostopic listすると,次のようになります.
/pubtime1/time_rel
/pubtime3/time_rel
/pubtime4/time_rel_remaped
/pubtime5/time_abs_remaped
/pubtime5/time_rel_remaped
/time_abs
/time_abs_remaped
/time_rel_remaped
この結果は,Remap についての公式ドキュメントと組み合わせて読むのと理解しやすいかと思います.
一番ハマったのは,launchファイル内でローカルネームスペースの書き換え方についてドキュメントで辿りつけなかったことです.
上記remapのドキュメントを読む感じだと,頭に/
をつけていなければ良いように思えるのですが,上記実行結果のpubtime3とpubtime4を見比べてもらえるとそうではないことがわかるかと思います.
要は~
をつけろということですね.
group を使った場合
launch ファイルで group 要素を使うと,ネームスペースを区切ることができます.
ノードが増えてくると,名前の衝突を避けたり,見やすさを整理するためにもネームスペースは区切るほうがいいでしょう.
そしてこれを使うと,まとめてリマップするということができます.
ジョイスティックの情報を受け取って処理するプログラムが複数あるとして,入力のトピック名をローカルネームスペースで ~joy
みたいに定義してある,ような例だとこんな感じ.
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<arg name="pollingMode" default="true" />
<arg name="joy_dev" default="/dev/input/js0" />
<group ns="rc">
<remap from="~joy" to="joy" />
<param name="~pollingMode" value="$(arg pollingMode)" />
<node pkg="joy" name="joy_node" type="joy_node" output="screen">
<param name="dev" value="$(arg joy_dev)"/>
</node>
<node pkg="joy_rc" name="vel" type="vel_rc" output="screen" />
<node pkg="joy_rc" name="angvel" type="angvel_rc" output="screen" />
</group>
</launch>
この例では, joy_node が /joy
でトピックを出力しているので, /rc/joy
という名前になります.
vel_rc と angvel_rc というノードは,それぞれ ~joy
を受け取るようにコーディングされているとすると,標準では /rc/vel/joy
と /rc/angvel/joy
を受け取ろうとしますが,読みたいのは /rc/joy
なのでリマップが必要です.
それで,上記の例では, group 要素内全体に効力があるように remap 要素をおいています.
そしてこの書き方がまたよくわからんのですが,上記のように
<remap from="~joy" to="joy" />
となります.
こうすると,このネームスペース内であればどんな階層でもいいので joy というトピック名を,ネームスペースのルート下の名前である joy に変換しています.
ネームスペースが rc という名前なので,最終的には /rc/joy になる,ということのようです.
うん,ややこしい.
ちなみに,group 内だけでなく, launch 直下でも同じことはできます.
まとめ
とりあえずの分だけ記述しました.
ROSの公式ページにあるパッケージでも,割とよくtopic名をparamで受け取って変更するタイプのパッケージ,ノードをよく見かけますが,実はすべてremapで解決できる話です.
あんまりそのような使い方をしている例が少ないようなのは,やっぱりremapが浸透していないから?
それとも何か別の理由があるんでしょうか.詳しい人教えてください…