くいでのあるあし

ロボットの研究とか たぶんそのままだと役に立たない

わたしがROSで使ってるシェル芸(と芸未満)

またROSの記事

他に書くことないのかと.

そして8割書いた記事が一回消えたので,わたしには再び感が凄い

シェル芸

いわゆるシェルのワンライナー. コマンドをパイプ | で繋げて実行.

いろんなレベルのものが書かれていますが,とりあえず,自分がそこそこ幸せになれるレベルで使えればいいとわたしは思ってます.

動機 読み飛ばし推奨

最近,世界のほんの片隅で,そこそこの人数の初対面の方々にROSの講習をする機会があったのですが, やはりCUIという部分がネックとなっているようでした.

ROSの良さはRVizやrqtによるデータ可視化の分もありますが, やはりその開発と習得にはCUIが本質的に必須なのではないかとわたしは考えています.

わたしはぼっちなので独学でROSを覚えたのですが, そのときはまだ書籍とかも揃ってなかった (なんとかできるって気がしてきたとき,日本語ROS本が出てきた) 状況で,どういう流れを通ってきたかというと


ROSわからん →  なんか端末叩かされてるけどわからん →  そもそもubuntuとかLinuxがわからん →  とりあえずコマンドってなんだ →  シェル芸の本?


確かこんな感じだったわけで.その後,


cd とか ls とかlessがわかった.オプションとかもあるんだな →  ググるだけじゃなくて,実際にファイルを見に行くように →  Linuxって設定とかがファイルで書いてあって大抵所定のところにあるのか →  awk とか sedとかわかってシェル芸で笑えるくらいになる →  実行しろっていわれるシェルスクリプトとか読むようになる →  Vimでコード書いて端末で作業するように →  ROSのドキュメント読んでわからない時,pythonシェルスクリプト見る →  あれ,そういえばわたしROS使えてるっぽい


みたいにポロロッカしてました.

わたしはプログラミングとかのプロフェッショナルではないし, 本業もかなりアレな大した人間ではないのだけど, ちょっと良く使うROSで使うCUIでの作業をまとめて見ようと思い立ち, 当記事に至ります.

ROSで使っているシェル芸(と芸未満)

本編.思い出せる限り.殴り書きしてます.

# ワークスペースへの移動.芸未満
anywhere$ cd ~/catkin_ws # ~ は自分のホームディレクトリを意味する
anywhere$ cd /home/(your_user_name)/catkin_ws # 上記と同じ結果
# 移動の結果が以下のようになる.$ マークの前に表示.
~/catkin_ws$ pwd # 現在居るディレクトリを表示
/home/(your_user_name)/catkin_ws # こんな結果が出るはず
# ビルドする時,catkin_makeを実行するにはcatkinワークスペースの
# ルートディレクトリに居る必要がある(オプションで指定する方法もある)
~/catkin_ws/src/hoge_pkg/scripts$ cd ~/catkin_ws; catkin_make && cd -
# ;はコマンドを連続して実行する.
# &&は前のコマンドの終了ステータスが成功(戻り値ゼロ)の時,次のコマンドを実行する
# cd - は前に居たディレクトリに移動する.
# 分割して実行しても勿論いいけれども,
# 何度も繰り返すならワンライナーにしてしまったほうが,
# キーボードの上矢印でコマンド履歴が辿れるので楽なのではと個人的には思う.
# ディレクトリにどんなファイルがあるのかは,lsで見る.芸未満.
~/catkin_ws$ ls
build devel src
~/catkin_ws$ ls src/hoge_pkg/scripts
node1.py node2.py
~/catkin_ws$ ls src/hoge_pkg/scripts -la # 詳細を知りたいならオプションで
合計 16
drwxrwxr-x 2 you you 4096  911 02:33 .
drwxrwxr-x 6 you you 4096  911 02:33 ..
-rwxrwxr-x 1 you you  776  911 02:33 node1.py
-rw-rw-r-- 1 you you  833  911 02:33 node2.py
# 左端に読み取り,書き込み,実行が可能かの情報が書かれている(rwx)

# node2.pyを実行するには権限を付けなければならない
~/catkin_ws$ chmod +x src/hoge_pkg/scripts/node2.py
~/catkin_ws$ ls src/hoge_pkg/scripts -la
合計 16
drwxrwxr-x 2 you you 4096  911 02:33 .
drwxrwxr-x 6 you you 4096  911 02:33 ..
-rwxrwxr-x 1 you you  776  911 02:33 node1.py
-rwxrwxr-x 1 you you  833  911 02:34 node2.py # 変更された

# ls 以外にもtree というコマンドがある
~/catkin_ws/src/hoge_pkg$ tree
.
├── CMakeLists.txt
├── msg
│   └── foo.msg
├── package.xml
├── scripts
│   ├── node1.py
│   └── node2.py
├── src
│   ├── node3.cpp
│   └── node4.cpp
└── srv
    └── bor.srv

4 directories, 8 files
# ROSのcatkinワークスペースでは,packageという単位でコードが置かれる.
# また,そのpackageという単位で実際に実行ファイルやmsgが利用される
# パッケージ名が分かれば,roscdでそのパッケージがインストールされているディレクトリまで移動できる.
# ROSのパッケージは普通, sudo apt-get install ... で,
# /opt/ros/(distro) ... にインストールされているはず.
# そのようにシステムにインストールされたパッケージは次のコマンドで表示される
~/catkin_ws$ rospack list
actionlib /opt/ros/indigo/share/actionlib
actionlib_msgs /opt/ros/indigo/share/actionlib_msgs
actionlib_tutorials /opt/ros/indigo/share/actionlib_tutorials
amcl /opt/ros/indigo/share/amcl
angles /opt/ros/indigo/share/angles
ar_track_alvar_msgs /opt/ros/indigo/share/ar_track_alvar_msgs
assimp_devel /opt/ros/indigo/share/assimp_devel
astra_camera /opt/ros/indigo/share/astra_camera
astra_launch /opt/ros/indigo/share/astra_launch
audio_common_msgs /opt/ros/indigo/share/audio_common_msgs
# ... 省略
# 表示されるものは/opt以下にあるpackageと,
# source ~/(your_workspace)/devel/setup.bashでpathを通しているなら,
# そのワークスペースにあるpackageとなる.

# ただ,このままだと見難いのでパイプを繋いでフィルタする.
~/catkin_ws$ rospack list | head -n3 # 最初の3行のみ表示
actionlib /opt/ros/indigo/share/actionlib
actionlib_msgs /opt/ros/indigo/share/actionlib_msgs
actionlib_tutorials /opt/ros/indigo/share/actionlib_tutorials

~/catkin_ws$ rospack list | grep -i hoge # hogeという文字列を含むもの.オプション -iは大文字小文字の区別をつけない
hoge_pkg ~/catkin_ws/src/hoge_pkg

~/catkin_ws$ rospack list | percol # percolはpipでインストールできる
# 端末上でrospack listから出た結果のフィルタ画面が出てくる
# また,percolでは選択したある一行が標準出力に出される.
actionlib /opt/ros/indigo/share/actionlib

# このようにパッケージの名前や,そのpathを調べることが出来る.
# インストールされているmsg, srv, launchファイルをこのpathから調べることが多いと思う.
# rosed でも良いが,/opt以下と~/your_ws以下に同じパッケージで違う内容を突っ込んで気づかない事故が経験上あったので...
  • ノード,トピックの調査 その1
# ROSのシステムを実行させている時に,現在動いているノードを調べたいときは,
~/catkin_ws$ rosnode list # nodeの名前を表示
/node1
/node2
/rosout
~/catkin_ws$ rosnode info /rosout # nodeの詳細を表示
--------------------------------------------------------------------------------
Node [/rosout]
Publications: 
 * /rosout_agg [rosgraph_msgs/Log]

Subscriptions: 
 * /rosout [rosgraph_msgs/Log]

Services: 
 * /rosout/set_logger_level
 * /rosout/get_loggers


contacting node http://your_pc:58523/ ...
Pid: 9094
Connections:
 * topic: /rosout
    * to: /node1_1_9318_1505071783105 (http://your_pc:50006/)
    * direction: inbound
    * transport: TCPROS
# 上記のように出力される(一例,手元の環境を弄ってるので微妙に出力内容おかしいかも)

# 大量のnodeが立ち上がって調べにくい場合はgrepで何かの文字列でフィルタする
~/catkin_ws$ rosnode list | grep -i image_node
image_node1
image_node2

# xargsを使って名前の探索と詳細の表示を同時に行う
~/catkin_ws$ rosnode list | xargs rosnode info
~/catkin_ws$ rosnode list | grep -i image_node | xargs rosnode info
~/catkin_ws$ rosnode list | percol | xargs rosnode info
# わたしは状況に応じて使い分けている
  • ノード,トピックの調査 その2
# topicの名前や詳細もnodeの場合と同様に調査できる
~/catkin_ws$ rostopic list
/rosout
/rosout_agg
/string_data
~/catkin_ws$ rostopic info /rosout
Type: rosgraph_msgs/Log

Publishers: 
 * /node1_9318_1505071783105 (http://your_pc:50006/)

Subscribers: 
 * /rosout (http://your_pc:58523/)
# 上記のように詳細が出力される

# xargs を使う場合はオプションを入れて,(rostopic infoの都合)
~/catkin_ws$ rostopic list | xargs -n1 rostopic info
~/catkin_ws$ rostopic list | grep -i name | xargs -n1 rostopic info
~/catkin_ws$ rostopic list | percol | xargs rostopic info

# rostopic echoでtopicの内容を出力できるので同様に,
~/catkin_ws$ rostopic list | percol | xargs rostopic echo
  • ノード,トピックの調査 その2
# rostopic echo -n1 /topic で一度だけtopicの内容が得られる
~/catkin_ws$ rostopic echo -n1 /joint_states
header: 
  seq: 158
  stamp: 
    secs: 1505074289
    nsecs:   3087043
  frame_id: ''
name: ['joint1_01', 'joint1_12', 'joint1_23', 'joint1_34', 'joint2_01', 'joint2_12', 'joint2_23', 'joint2_34', 'joint3_01', 'joint3_12', 'joint3_23', 'joint3_34', 'joint4_01', 'joint4_12', 'joint4_23', 'joint4_34']
position: [-0.3529775813644944, -1.780097737750369, -1.464398623717453, -0.9656845881959149, -2.2365590983272536, 0.9881491526112725, 0.9437552086194985, 0.7689903038383807, 2.4342880115931553, -0.056669058888774604, 1.1904601906872596, -0.8253714396635548, 0.8509743673174297, -0.3859188461407257, -0.8952479217516776, -0.9185304306070528]
velocity: []
effort: []
---
# sensor_msgs/JointState型など,topic の内容に可変配列などが含まれるとき,見づらい場合がある

# grep でtopicの出力から必要なものを得て,Open usp tukubaiのコマンドで縦横入れ替え
~/catkin_ws$ rostopic echo -n1 /joint_states | grep -e name -e position | tateyoko | tr -d "[]"
name: position:
'joint1_01', -0.3529775813644944,
'joint1_12', -1.780097737750369,
'joint1_23', -1.464398623717453,
'joint1_34', -0.9656845881959149,
'joint2_01', -2.2365590983272536,
'joint2_12', 0.9881491526112725,
'joint2_23', 0.9437552086194985,
'joint2_34', 0.7689903038383807,
'joint3_01', 2.4342880115931553,
'joint3_12', -0.056669058888774604,
'joint3_23', 1.1904601906872596,
'joint3_34', -0.8253714396635548,
'joint4_01', 0.8509743673174297,
'joint4_12', -0.3859188461407257,
'joint4_23', -0.8952479217516776,
'joint4_34' -0.9185304306070528
# tr コマンドで[]を除去している

最後に

あれ,前振りの割にそんな芸してなくない? (割と書いてみた後,自分で驚いている)

特殊なほどのCUIの技術は必須ではない(持ってるならすっごーい!)と思います. そんな怖がることは無いのでちょっと調べてみたらいいんじゃないかなって.

…細かいコマンドの解説を省いてしまったのでCUI不慣れの人には逆にわかりづらいかもしれない