ロボットミドルウェアを使ってロボットシステムを作る手順(RTM・ROS共通)

このところ学生さんや,企業の技術者でも非ソフト系の人に同じことを聞かれるのでメモしとく.

「ロボットミドルウェアの使い方はなんとなくわかったけど,次にどうしたらいい?」

という質問だ.


正確には同じ質問ではないが,大抵は以下のように答えるので,同じ質問と捉えてる.

まず,大抵は
「使いたいロボット&ソフトウェアモジュールがすでにある」か,「すでにロボットミドルウェアで作ったシステムがある」という前提に立っていて,そこに自分の制御を加えたりしたいのが希望らしい.まあ,大抵の人はそうだろう.

んで,RTMでもROSでも,チュートリアルを一通りやったんだけど,つぎにどうしたらいいのかわからない.ということだ.まあ,そうなるよね.

チュートリアルってのは流れに沿ってやっていくだけで進められるわけで,自分の頭を使わないでなぞると何にもわからなんかったりするわけだ.
そういう人に僕はお金をもらって対処を授けてるわけだけど,さわりだけここに書くと

  • 現状(使いたいモジュール,もしくはすでにあるシステム)を文書化する
  • 自分のやりたいことを文書化する
  • 自分のやりたいことを実現するソフトウェアモジュールの雛形を作る
  • 雛形の状態で全部つなげてみて,出し入れするデータを視覚化する
  • 一つ一つ実装しながら全体で動作確認する

という流れに尽きる.

まず,文書化するってのはすごく大事なこと.とりあえず相談に来てもらっても要領を得ないのは,この文書化ができてない.
なにもしっかりとした文書でなくてもいい.システムの構造や振る舞いを完全に記述する文書は,あったほうがいいに決まってるが,なくても相談には乗れる.
でも,こういうのを書いたことがない人からは相談を持ちかけられても,こっちが質問しかえす手間が多すぎて,もうやめたくなる(早稲田の学生でもない限りは無料では受けないよ)
コミュニケーションのために文書化するってのはアジャイルだろうがウォーターフォールだろうが必要です(程度が違うけどね)

次は,どんな図が必要なのか,という話になるけど,ロボットミドルウェアで開発する場合に,最初に書くポイントは,

  1. 何のモジュールを使っているのか
  2. それぞれのモジュールがどんな入出力を持っているか

という2点に着目した図が必要だ.

もしROSであればモジュール=ノードになる.その入出力というのは,各ノードのアクセスする「トピック」「サービス」および「パラメータ」とそのリマップである.
各トピックやサービスにはデータ型というのがあるので,それも必要な情報だ.
このような情報は,ROSの公式サイトに載ってるようなものなら文書化されているので,それを参考に図化する.四角+矢印で十分なので,まずはそれを書いてくれ.
rqtgraphを使うとトピックの連結はわかるはず.各トピックのタイプはrostopicやrosmsgを使って欲しい.
tfがあるせいで,移動ロボットだとすごくデータの流れが見づらい.この変は簡単にはサポートできない・・・まあ,正確じゃなくてもいいので,オドメトリを出力してるーくらいでもいい.
サービスの連携は簡単にはわからなくて,ドキュメントを見る.ドキュメントが間違ってる(ということはよくある)時はソースコードに当たるしかない.
パラメータも,一応一覧が観れるけど,どのノードに影響するのかは,ドキュメント&ソースコードで確認して欲しい.

RTMであれば,モジュール=RTCになる.RTSystemEditorを開いて,動作してるRTCの接続を確認してほしい.データ型についてもメモが必要.コンフィグレーションもRT System Editorで確認.
まあ,スクリーンショットをひたすら取ってWordにでも貼り付ければいい.こういうのはRTMの方がよくできている.

この設計というか現状確認がないと次には進めない.

次に,自分のやりたいことをノードにした時に,どういう入出力になるかを考える.
例えば,相手が移動ロボットだった場合,ロボットの位置を受け取って,ロボットに速度を送る.制御は画像処理で行うので,カメラ画像を受け取る,ってな具合で四角いモジュールに矢印が加わっていく.
最初は自分の作るモジュールは全部ひっくるめた一つのモジュールで書く.

そこから,機能を分割できるといい.
たとえば,画像処理部分とロボットの位置制御部分を分割して,カメラ画像を画像処理に入れて,そこから特徴量を3次元のベクトルで出力,3次元のベクトル特徴量をロボットの位置制御部分で受けて,さらにロボットの現在位置を受け取って,ロボットに速度を送る,なんて感じ.
機能を分割して一つのモジュールでやることが一つになると,ものすごく開発が楽になる.
ほとんどのモジュールが,来たデータを加工して別のデータを出力する,という処理をするわけで,そういうプログラムは結構書きやすい.
でも,来るデータに従って,状態マシンを変更したりモードを変えて処理を切り替える,みたいなコードはなかなか書けない.だから書きやすい部分はできるだけ抽出しておく.

次は雛型を作る.

ROSであれば,パッケージを作って,ノードを作っていく.画像処理であれば,カメラ画像を受け取るので,そういうSubscriberを.3次元ベクトルはgeometry_msgs/Vector3を使えばいい.独自のmsgを作るのもチュートリアルにあるはず.
そして空のSubscriberコールバックを持ったノードを作る.
んで,ビルドして実行

RTMであればRTC Builderを使って雛形を作る.
んで,ビルドして実行

次に繋げちゃう.うん.もう繋げちゃう.
ROSであればLaunchを書く.繋がってるかどうかは,Subscriberのコールバックで来たデータをprintすればいい.
RTMもそう.入力ポートのデータをprintするプログラムだけ書いて繋げちゃう.つなげるのはRT System Editorで.保存機能を使えば,次回以降はロードするだけで繋げられるし.

んで,printしとくとそれがデバッグ用のモジュールになってるので,そのまま一個ずつモジュールを完成させていく.

こういうやり方をして欲しい.

とにかく文書化を舐めないことだ.特に初心者は.特に.
上級者はそれを脳内でやってるだけだし,コードだけで情報が得られるのも同じことです.
そしてROSでもRTMでも,とりあえず文書化しやすい(使わないよりは.絶対)ので,この手間は省くべきではない.教育としてもそうだ.