2014/12/8 更新しました.
以前,Edisonにロボット用のOSであるROSを導入しました.
ROSを導入した理由は,これから数多くの機能をEdison上に構築していくわけですが,それらの機能間の結合を粗結合にしておくことで,機能の取り外しや,他人が作った機能を自分のシステムに組込むことを容易にするためです.また,ROSを使うと,C/C++やPython,Lispといった処理系が混在したシステムを簡単に構築できます.そのため,仕様の変更や追加が多く開発速度を重視したい処理はPythonを,速度が求められる処理はCをといった使い分けができるようになります.ROSの詳しい説明は,このあたりをご覧下さい.
まー,”ロボット用のOS”なんて,大風呂敷広げてますが,これの主要な機能って,プロセス間の情報のやり取りが簡単にできることくらいです.全然大掛かりでも何でもない.あー.自作の機能について,それを実行するのに必要なライブラリを記述することができて,それをやっておくと,別のマシンに持って行ったときにライブラリのインストールをパッケージマネージャを駆使してコマンド一発でやってくれる機能があり,デプロイが簡単になるというのは利点かなぁ.
ROSは,”ノード”という単位で一つ一つの機能を管理しています.今回は練習なので,ROSの簡単なノードを作ってみようと思います.
この記事は,2014年のEdisonのアドベントカレンダーと,ROSのアドベントカレンダーの両方に登録しています☆
catkinワークスペースの作成
場所について
どこにでも作れるが,全部同じところに入れておいたほうが管理が楽.
以下は作ったことがない人だけ.
$ mkdir ~/catkin_ws
$ cd ~/catkin_ws
$ mkdir src
catkinワークスペースのイニシャライズ
最初に,おまじないを唱える.
$ wstool init
これからワークスペース内に,参照するリポジトリ群をどんどん入れて行く際の初期化をするとか何とか(今イチわかってない).
空のワークスペースをビルド
$ catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release
正常に終了すると, build_isolated と devel_isolated というディレクトリができているはず.
新しいワークスペース用に現在の環境変数を設定
$ source ~/catkin_ws/install_isolated/setup.bash
しばらくこのワークスペースを使い続けるなら,環境変数として ~/.bashrc に上記コマンドを追加しておく.
Tweetするパッケージの入手
ROSを使うからには,コードなんか最小限しか書きたくないわけです.Twitter APIの仕様なんか,一切知りたくないわけです.そのため,他人様が作ったパッケージを導入します.
必要なPythonパッケージの事前の入手
Debianだと,rosdepがうまく動いてくれない・・.・゚・(ノд`)゚・.
仕方ないので,手動でインストールした.
$ pip install oauth2 requests simplejson
rostwitterの入手
ROSはパッケージのリストがまとまっているので便利ですね.
JSKが作っている rostwitter というパッケージが,それっぽい機能を提供してくれそうなので,お借りしましょうかね.
まだ,私がどのようにパッケージを配置するべきなのか分かっていないので,catkinワークスペースの外でリポジトリをcloneして,rostwitterの部分だけ,catkinワークスペース内のsrc下にコピーするようにしました.
正しいやり方を,どなたかに教えて欲しいです..(;´Д`)
$ cd ~/work
$ git clone https://github.com/jsk-ros-pkg/jsk_common.git
$ cd ./catkin_ws
$ cp -R ../../jsk_common/rostwitter ./src
ワークスペース下のsrcにwstoolで持ってくるのが正解のようです.
$ cd ~/catkin_ws/src
$ wstool set --git jsk_common https://github.com/jsk-ros-pkg/jsk_common.git
$ wstool update jsk_common
この時点で,試しにビルドしてみましょう.
んで,この状態でビルドしようとすると,jsk_commonの中にrostwitterと一緒に入っている諸々高機能パッケージが,「ライブラリが足りなくてビルドできない!」と騒ぎだすので,rostwitterだけを選択してビルドしましょう.
$ catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --pkg rostwitter
-- catkin 0.6.9
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~ traversing 2 packages in topological order:
-- ~~ - rostwitter
-- ~~ - mytute1
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'rostwitter'
-- ==> add_subdirectory(rostwitter)
-- +++ processing catkin package: 'mytute1'
-- ==> add_subdirectory(mytute1)
-- Configuring done
-- Generating done
こんなかんじで出たので,うまくいったようです.
アカウントとbotの情報を保存するファイルを作成する
ロボット関連の情報は, /var/lib/robot 以下に配置します.
まずはディレクトリの作成
$ sudo mkdir /var/lib/robot
このディレクトリ内に, account.yaml という名前でファイルを作成し,中にTwitter関連の情報を記述します.Twitterにアプリケーションからアクセスするためには,自作アプリを登録して,コンシューマーキーを発行し,さらにアクセスするアカウントのアクセストークンを取得する必要があります.このへん参照.
{AKEY: 428639810-dwufhiEhi04FWIi3Lluh3fwiuhIWhi2fi8fwuFWf, ASECRET: fo9f3fwufwiGiuHF57Fui1ohifut7kfwuFKwufhwuF,
CKEY: iruafhiiUEHWIiuHFWIUli, CSECRET: Eiuhf4fFW0fwwfehi2fWEiWooifwQEIUUfh2efFui}
上記の値は適当なので,自分で入手したものに書き換えること.
メインのパッケージを自作する
catkinパッケージの作成
$ cd src
$ catkin_create_pkg mytute1 std_msgs rospy rostwitter
上は,「mytute1という名前の新しいパッケージを作ります.このパッケージは,std_msgsとrospyとrostwitter」というパッケージに依存しています.」という意味です.
mytute1というディレクトリが作成され,中に CMakeLists.txt と package.xml というファイルと, src というディレクトリが作成されます.
作成された package.xml 内の description , maintainer , license などのタグ内を適切に編集しましょう.
ここに, script というディレクトリを作り,その中に以下のスクリプトを作成.
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('/tweet', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
r = rospy.Rate(0.01) # 0.01[Hz]
while not rospy.is_shutdown():
str = "Tweet from Edison through ROS Api : %s" % rospy.get_time()
rospy.loginfo(str)
pub.publish(str)
r.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
ROSのPythonチュートリアルをそのままで,Publishする先を /tweet に変えただけです.
忘れずに,実行権限をつけておきましょう.
$ chmod +x ./talker.py
また,このときにCMakeLists.txtも編集します.該当箇所は,
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
install(PROGRAMS
script/talker.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
上記のように,install(PROGRAMS の項のコメントアウトを外して,作成したスクリプトをインストールするように指定します.
ビルド&インストールする
$ catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --pkg mytute1
実行する
一つ一つノードを起動していく方法
3枚ターミナルを開く必要があります.
1枚目で,ROSシステムの全体を制御する roscore を実行します.
$ roscore
続けて,別のターミナルで, rostweet/tweet.py を実行します.
$ rosrun rostwitter tweet.py
さらに別のターミナルで, mytute1/talker.py を実行します.
$ rosrun mytute1 talker.py
すると,100秒ごとに,「Tweet from Edison through ROS Api : タイムスタンプ 」とTweetするようになるはずです.
Launcherで一発起動する方法
launchディレクトリを作成.
$ roscd mytute1
$ mkdir launch
中に,以下のファイルを記述する.
<launch>
<node pkg="rostwitter" name="tweet" type="tweet.py" />
<node pkg="mytute1" name="mytute1" type="talker.py" output="screen" />
</launch>
CMakeLists.txtも修正する必要があります.install(FILES の項のコメントアウトを外して,作成した.launchファイルの登録.
## Mark other files for installation (e.g. launch and bag files, etc.)
install(FILES
launch/mytute1.launch
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
その後,パッケージのビルド&インストール.
$ catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --pkg mytute1
そして,
$ roslaunch mytute1 mytute1.launch
これで,先ほどと同様にTweetが始まる.
注. どうやら,roslaunchに起動の順序を制御する方法はないらしく, rostwitter/tweet.py より先に mytute1/talker.py が起動した場合は,最初のTweetは空振りに終わる.
この,roslaunchをシーケンシャルな起動に対応させるかどうかについては,過去に議論があったらしいが,そのときは「デッドロックを防ぐためにも,そのような機能はむしろないほうが望ましい」という意見が出ていたみたい.
これで,ボタンを押したらTweetするみたいなのは,簡単に作れそう.
「それ.わざわざEdison/ROSでやる必要あんの?」って指摘もあるんですが,Edisonの良いところは,これまで私たちがLinuxで普通にやってきたことを,当たり前のように使って組込みシステムで実現できるところにあると思っています.