ROS のコマンドラインツールでシェル芸をしました。
ROS のコマンドラインツールをシェル芸で使う
みなさん ROS のコマンドラインツールは毎日使ってると思います。
rostopic, rosnode, rosparam, rosbag, rosservice... どれも便利です。
しかし、コマンドラインツールなんだからシェル芸で使っても良さそうなのに、
あんまりそういう使い方はされてない感じがしますね。
出力を grep するくらいでしょうか。
今回は ROS のコマンドラインツールを使ってシェル芸をやってみました。
やりたいこと
$ rostopic echo|なんかコマンド|rostopic pub
という感じで、pub されているメッセージを標準出力に持ってきて、それを何か加工して、
rostopic pub に入力して pub/sub の世界に戻してやる、
みたいなことができたら面白そうなのでやってみます。
できるの?
rostopic echo された文字列を加工するところまでは普通にできそうですが、
rostopic pub にデータをパイプで渡して pub することってできるんでしょうか?
試してみましょう。
ターミナルを3つ立てて
$ rostopic pub hoge std_msgs/String "data: 'fuga'"
$ rostopic echo hoge|rostopic pub piyo std_msgs/String
$ rostopic echo piyo
すると、term3 でdata: "fuga"
が受信できます。
つまり、term2 では、rostopic echo で pub/sub の空間の hoge トピックからメッセージを受信して、
標準入出力の空間に持ってきて、それを rostopic pub で
pub/sub の空間に戻して piyo トピックに流し込むことができているわけです。
こうなるともうやりたいことはできそうな感じですね。
sed で加工
term2 のコマンドを止めて、受信したメッセージをそのまま戻すのではなく、
ちょっと加工して戻してみましょう。
$ rostopic echo hoge|sed 's/g/n/g'|rostopic pub piyo std_msgs/String
sed で g を n に置換してみました。
これで term3 で data: "funa"
が受信できるはずですね。
ところが term3 では何も受信されません。
term2 で rostopic pub に渡さずに
$ rostopic echo hoge|sed 's/g/n/g'
とすると、data: "funa"
が繰り返し出力されるのに、不思議ですね。
これは sed がパイプラインへの出力をバッファするからです。
rostopic echo hoge|sed -u 's/g/n/g'|rostopic pub piyo std_msgs/String
として、バッファせずに頻繁に出力するようにすると、
term3 で data: "funa"
が受信できました。
亀を動かす
文字列をいじってるだけでは ROS らしくないので、亀でも動かしましょう。
何かセンサーの入力があって、それを処理して、亀が動くというのが ROS らしくてよさそうです。
ウェブカメラの Image メッセージを echo して、それをシェル芸で処理して、
Twist メッセージを作って、亀の目標速度として pub しましょう。
$ rosrun usb_cam usb_cam_node
$ rosrun turtlesim turtlesim_node
して、ウェブカメラの Image メッセージを pub、亀の目標速度の Twist メッセージを sub します。
そして、この間をつなぐシェル芸が
$ rostopic echo /usb_cam/image_raw|tr -d '[,]'|awk 'BEGIN{c=0}$1=="width:"{width=$2}$1=="height:"{height=$2}$1=="step:"{step=$2}$1=="data:"{if(c%3==0){a=0;b=0;for(i=2;i<=NF;i=i+30){if((i-2)%step<step/2){a+=$i}else{b+=$i}}{printf "linear:\n x: 0.1\n y: 0.0\n z: 0.0\nangular:\n x: 0.0\n y: 0.0\n z: "(a>b?"0.1":"-0.1")"\n---\n";fflush()}}c++}'|rostopic pub /turtle1/cmd_vel geometry_msgs/Twist
のようになります。rostopic echo
から````rostopic pub```まで
パイプラインで繋がったワンライナーになっています。
動かすと
こんな感じになります。 これで、やりたかったことができました。$ rostopic echo|<シェル芸>|rostopic pub
— 闇ときどき豚 (@yami_buta) December 6, 2021
で、ウェブカメラに写った焼酎のある方向に亀が曲がっていくやつができました。 pic.twitter.com/58xtZEN3Xb
経緯
なんでこういうことをやったかというと、以前から
ということを考えていたんですが、これに対して[@ryuichiueda](https://twitter.com/ryuichiueda)先生からrostopic echoの、シェル芸でいじりやすい形式で出力してくれるバージョンみたいなやつと、その出力(またはそれをシェル芸でいじったやつ)をパイプで受け取ってpubするやつがあったら面白いんじゃないかな。
— 闇ときどき豚 (@yami_buta) December 4, 2021
という反応があり「えっできるの?」と思ってやってみたらできました。rostopic echo | なんかコマンド | xargs rostopic pub
— 上田 隆一 (@ryuichiueda) December 4, 2021
というのはできそう