テーマ記事へのリンク
以下の記事には今回のテーマを設定した目的や関連記事がまとめてあります。自分が見たい項目がある場合は利用してください。
自作ロボット(ローバー)のROS対応
目次
準備するもの
- Ubuntu 16.04
- Arduino IDE
- 3WD48mmオムニホイールモバイルロボット(以下ローバー)
ROS化の定義
ROS対応ロボットにはTurtleBotやHSRなどが挙げられる。しかし、ROS対応と書かれていなければROSが使えないわけではなく、最近ではプリメイドロボットが有志によってROS化が進んでいる。なのでサーボやカメラなどのハードに制約があるわけではない。やっていることはROSメッセージを使ってセンサやサーボの値をやり取りしているだけである。
つまりROSメッセージを使ってセンサから取得した情報をPublishしたり、値をSubscribeしてサーボを動かせればそれはROS対応ということになる。
そこで本記事で定義する自作ロボットのROS化とは、Pub・Sub通信を用いてデータのやり取りを行い、ROSの既存のパッケージを利用可能にすることを指す。
システムの構成
システムの構成を以下の図に示す。
"〇"で書かれたものがROSノードである。前回の記事と異なりArduinoの部分もrosserialを用いてROS化を行っている。
本記事では以下の流れでローバーの操作を行った。
- キーボードの入力を読み込み、中継ノードにキーに対応したデータを送信
- 中継ノードが送られてきたデータを読み込み、rosserialを介してArduinoを制御
起動するノードの解説
launchファイルを使うことで複数のノードを一括で起動することができる。
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<node name="rover_teleop" pkg="rover" type="teleop_keyboard_omni3.py" output="screen" launch-prefix = "xterm -e">
<remap from="odm_robot/joint_controller0/command" to="rover/joint_controller0/command" />
<remap from="odm_robot/joint_controller1/command" to="rover/joint_controller1/command" />
<remap from="odm_robot/joint_controller2/command" to="rover/joint_controller2/command" />
</node>
<node name="rover_serial_node" pkg="rover" type="serial_node.py" output="screen">
<param name="port" value="/dev/ttyUSB0" />
<param name="baud" value="115200" />
</node>
</launch>
今回はキーボード入力を用いてローバーをコントロールする"rover_teleop"とローバーとシリアル通信を行う"rover_serial_node"を立ち上げている。これに加えてAruduino側では、キーボードの入力を受信し、速度制御を行うノードが立ち上がっている。
"rover_teleop"で記述されていることについて解説する。launchで起動する場合にノードごとにプロンプトを開きたい場合(今回ならキー入力画面と"serial_node"のROS_INFOを出力するために2つのコマンドプロンプトが欲しい)、"rover_teleop"の起動の仕方を参考にすると良い。output="screen" launch-prefix = "xterm -e"と書けば新しくxtermが開き、そちらに"rover_teleop"のROS_INFOが出力されるようになる。
続いて"rover_serial"について解説する。remapはトピック名がプログラムで定義されている(teleop_keyboard_omni3.py)が、トピック名が他のトピックと被ったり、自分がわかりやすいトピック名にしたい場合にトピック名を変更するときに使う。
paramはプログラム(serial_node.py)で定義されている変数の中に"rospy.get_param"(pythonの場合)を使っている変数がある場合、その変数に対してlaunchファイルから値を代入するときに使う。このプログラムでは変数"port"にarduinoが接続されているポートを指定している。変数"baud"では通信速度を指定している。
remapについてはこちら、paramについてはこちらを参考にするとよい。
ソースコードのダウンロード&コンパイル
以下のフォルダをROSのワーキングディレクトリにダウンロードし、コンパイルする。
$ cd ~/catkin_ws/src
$ git clone https://github.com/NaotakaKawata/rover
$ cd ..
$ catkin_make
$ chmod +x rover/src/teleop_keyboard_omni3.py
$ chmod +x rover/src/serial_node.py
次にPub・Subノードの設定を変更する。普段PCで開発する際に意識したことはないが、arduinoなどに組み込む場合、初期のノード数だとメモリが足りなくなってしまう。そこで必要最低限の設定に書き換えることにした。arduinoのlibraries/ros_lib/ros.hの54行目に以下の変更を加える。数字については左からPublisherの個数の上限、Subscriberの個数の上限、入力バッファー、出力バッファーを表している。
$ typedef NodeHandle_<ArduinoHardware, 3, 3, 128, 128> NodeHandle;
その後。ローバーにArduino IDEを使ってarduino_scripts/rover_ros.inoを書き込む。
環境構築
Arduinoを用いたローバー制御(実機編)の「ros_libの生成」「ArduinoIDEでの書き込み設定」を参照。
実行
ローバーにシリアルケーブルが刺さった状態で以下のコマンドを実行。別の窓が開くため、そこにキー入力を行うことでローバーを操作することが可能になる。
2020/11/27追記:kineticでの動作確認はできていたが、melodicだと動かなくなっていた。原因を調べてみると、Arduino側とPC側の通信速度を揃えて設定しているはずだが、どうもずれており、メッセージが正しくやり取りできていないことが原因だとわかった。PC側の通信速度をArduino側の倍にしてあげるとうまくいっている。
例:rover_ros.launch11行目valueに19200を設定している場合、rover_ros.inoではnode_handle.getHardware()->setBaud(9600);と設定する。
$ roslaunch rover rover_ros.launch
自作ロボットを使う場合
rover_ros.inoのモーター制御の部分を書き換える。3輪駆動の場合ならdefineで定義しているPWMなどのポート番号を任意の数字に変えるだけで動くと思う。2輪や4輪の場合はさらにモーターの回転関数を追加、削除すればよい。
総括
「自作ロボットのROS化」というテーマで4章にわたってローバーのROS化に取り組んだ。
ここまでやってROSを使用することはできた。しかし「ROS化のメリットとは?」という疑問も出ると思う。これについての筆者の答えは「ROSを用いることでノード毎の開発が可能になり、カメラやセンサなどを追加する際の開発コストを大幅に減らすことができる」である。しかしこの答えは一つの解に過ぎないため、人によっては別の答えを出すだろう。
もし、この記事を読んでもっと勉強したいと思う方はROSロボットプログラミングバイブルで勉強するとより基本から勉強ができるのでおすすめ。筆者が(他人の)研究室で一通り読んだ中で一番わかりやすいと感じた。
2020年1月1日にPython2のサポートは終了するため、Python3系のROS2に移行した方がいいのでは?と思う方はこちら。
おすすめの書籍
以下に筆者が読んだ書籍の一部を示す。どの書籍もROS1入門用なので、C++とPythonのどちらで書きたいかを基準にして選ぶのが良いと思う。
また、筆者が気になっているが読めていない書籍を以下に示す。読んでないので何とも言えませんが、勉強になると思う。
- ROS2ではじめよう 次世代ロボットプログラミング(近藤 豊)
- SLAM入門: ロボットの自己位置推定と地図構築の技術(友納 正裕)
- ROS 2 IN 5 DAYS: Entirely Practical Robot Operating System Training(Alberto、Ricardo et al.)
余談
本記事と関係ないです。一区切りついたので余談を以下に示します。主に今後大学院修士課程に進学しようか迷っている学生用です。
去年からROSを勉強し始めたが、WRS2018やロボカップ2019ジャパンオープンなど数々の大会に出場する機会を与えてくださった教員、および筆者が「大会の準備してて進捗ないです」と報告しても暖かく見守ってくれた指導教官には非常に感謝しています。
他大学の研究室のメンバーと共同で開発作業したことは、自分の専門分野以外の知識を得る良いきっかけになりました。残念ながら自分の研究には全く役立っていませんが、就活で「チームで~」とか話せたり、自分の興味の幅が広がりました。大学院に進学しなければこのような機会に巡り合うこともなかったので、進学して良かったと感じています。
大学院に進学することについて、「特に理由はないけど理系だから大学院行っておくか」という人は勉強嫌いじゃないなら行ってもいいんじゃない?と思います。筆者も流されて進学を決めました。
成績がよいorめっちゃ開発が得意な人しか大学院で成功できないのでは?と思われるかもしれませんが、成功の定義が人それぞれなのである意味正解である意味間違いです。論文めっちゃ出す人がいるとしてその人は頑張っているし優秀だと思います。しかし、あんまり出せていなくても分野・教員・テーマの運などがあるので、決して論文出していない人が頑張っていないわけでも不出来なわけでもないです。人それぞれ成功の定義が異なるので、自分が満足出来たら博士課程に進んで正解だと思います。満足しなくても2年留年しちゃった☆彡くらいでテヘペロしときましょう。たかが2年です。迷ったら行ってみようぐらいでもいいと思います。
修士2年間で良かった経験は、先行研究をたくさん読んだり、提案手法何回も没にされたり、締め切り前に死ぬ気で実験したことだと思います。ついでに研究を忘れて趣味に走れたこと(ロボット製作など)も楽しかったです。
筆者は高学歴の大学院出身ではないので、この記述はあくまで地方の大学院生で「海外旅行したいので国際学会出せるよう研究頑張りました」くらいのモチベで研究頑張っていた人間の感想文だと思っていただくのが正解です。自分の事は自分で決めるのが最良の決断ですので、こういう考え方もあるのだと参考程度に思ってください。
現在筆者は修論に苦戦中です。しかし、自分の拙い文章に対してここまで添削指導してもらえるのは修士の特権だと思います。卒論・修論を書いている皆さん、あきらめずがんばりましょう。そして今後卒論・修論を書く予定の人はたくさん指導してもらえるように期限に余裕を持って提出しましょう。