Rowmaとは
RowmaはROSロボットのネットワーク化を実現するシステムです。ロボットがやりとりするトピックの流れをロボット同士、またはSDKにより実装されたアプリケーションとロボット間で自由に動的に組み替えることができます。なおRowmaはOSSでありGitHubに公開されています。
Rowmaにより既存のROSワークスペースを変更すること無く、簡単にROSベースロボット同士をインターネット越しに接続できます。
概要図をこんな感じに書いてみました。まず1つ目の図はRowmaネットワークに接続されたロボットやアプリケーションが相互にトピックをやり取りする様子です。任意のトピックを任意の宛先に送ることができます。
次はロボット中で実行しているアプリケーションを切り替えながら実行する図になります。簡単に言うと遠隔rosrun/roslaunch実行にフォーカスした図です。Rowmaは実装開始当初ただの遠隔実行システムでした。
最後にデータの向き先の変更についての図です。Rowmaでは接続しているロボットやアプリケーション同士で相互にデータを送り合えます。そして分岐によって別のデータを別の宛先に送るように変更することも可能です。
詳しいドキュメントはこちらになります。
機能
以下はRowmaの特徴、機能です。
- 既存ワークスペースへの簡単な組み込み
- スマホやWebブラウザからのrosrun/roslaunchの遠隔実行
- ROSトピックの遠隔Publish/Subscribe
- 新規ROSノードの遠隔追加(Pythonのみ)
- ROSロボット同士の遠隔トピック送受信
- SDKの提供
何ができるか
とりあえず作成者が思いつくあり得るユースケースをいくつか書きます。
- 複数ロボットでのマップ作成
- サーバーサイドでのオンラインデータ処理
- ロボットによる別ロボットの操作
- スマホによるロボットの遠隔操作
システムのウリ
「ロボット同士の接続ならROSやRTM等でもできるよ」などの意見があると思うのでそれに対する答えを書いておきます。
一番大きな違いはSDKの存在です。SDKがあることによりROSの環境不要でセンサーデータをやりとりできるようになります。例えばPython SDKを使うことにより、Pythonのスクリプト中でトピックのデータを送受信することができます。
他にも例えばROSも何もセットアップしていないmacOSのPCでpip install rowmapy
をして簡単なサンプルスクリプトを実行するだけでROSのデータをそのPCでやり取りできます。
使い方
ひとまずRowmaを使ってみるためにPublicConsoleというものを提供しています。
以下はチュートリアル動画です。(YouTube)
ここではPublic Consoleを使って任意のroslaunchコマンドを実行します。
1. ロボット側の操作
まずロボット側でRowma ROSパッケージをROSワークスペース中にインストールします。以下のコマンドをターミナルで実行してください。インストーラースクリプトが走ります。
$ python <(curl "https://raw.githubusercontent.com/rowma/rowma_ros/master/install.py" -s -N)
インストールが完了したら以下のコマンドでノードを起動します。roscoreは立ち上げておいてください。
$ rosrun rowma_ros rowma
立ち上げるとUUIDが表示されます。
2. Public Consoleでの操作
次に https://rowma.github.io/public-console/ にアクセスしてください。アクセスしたらまず一番上のNetwork URL
がhttps://rowma.moriokalab.com
であることを確認してConnectボタンを押します。
できたら次にSelect Your Robot's UUID
欄でロボットで表示されたUUIDにチェックを入れてConnectボタンを押します。
そして少し下にスクロールしてSelect a roslaunch command
で任意のroslaunchコマンドを選択しExecuteボタンを押します。なお、roslauncコマンドが実行されるとログもブラウザに表示されます。
システム構成概要
RowmaはConnectionManager、Rowma ROS、各種SDKの3つで構成されています。ROSロボットとSDKで実装されたアプリケーションがConnectionManagerに接続され、ConnectionManagerを経由してデータがやり取りされます。通信には**WebSocket(Socket.io)**を使っています。
ConnectionManager
ConnectionManagerはWebSocketサーバーであり、ロボットとアプリケーションを接続します。ネットワーク機器で言うとスイッチのような役割です。ConnectionManagerは接続されたロボットとアプリケーションにUUIDを発行して管理します。
WebSocket関連はSocket.ioで実装しています。そしてWebSocketとROSの通信はrosbridgeを使って行っています。便利です。
RowmaROS
ロボットからRowmaに接続するためのWebSocketクライアントとしてRowma ROSを使います。Rowma ROSの主な役割は(1) ROS_PACKAGE_PATH
から有効なワークスペースを調べrosrun/roslaunchで実行できるコマンドのリストを取得する、(2) ワークスペース情報やトピックやコマンドをConnectionManagerと送受信する、(3) ノードのキルと実行、等です。
SDK
JavaScriptとPythonでSDKを提供しており、Rowmaアプリケーションを実装できます。RowmaアプリケーションもConnectionManagerにWebSocketクライアントとして接続し、接続ごとにUUIDが発行されます。
JavaScript SDK
JS SDKはnpm install rowma_js
でインストールすることができます。JS SDKは主にWebフロントエンドの実装に使います。上述のPublicConsoleもこのSDKを使っています。
Reactと組み合わせるチュートリアル記事を書きました。ROSトピックをインターネット経由で送受信できるWebフロントエンドの作成チュートリアル(React + ROS + Rowma)
Python SDK
Python SDKはpip install rowmapy
でインストールすることができます。
Publishのサンプルコードはこれです。ROSいらずで任意のトピックをPublishできます。Subscribeもできます(ドキュメント参照)。
from rowmapy import Rowma
rowma = Rowma()
rowma.connect()
robot_uuid = 'xxxx-xxxx-xxxx'
rowma.publish(robot_uuid, '/chatter', { "data": "topic from python" })
その他
独自ConnectionManager
デフォルトだとRowmaROSもSDKも公開サーバーに接続します。公開サーバーは主にテスト用のお試し環境である想定で、公開サーバーに接続しているロボットは誰でも操作することができます。公開されると困る人は自前でConnectionManagerを立ててプライベートサーバーを立てる必要があります。
ConnectionManagerのリポジトリはこちらです。以下のコマンドでポート3000番にWebSocketサーバーが立ちます。
git clone https://github.com/rowma/rowma
cd rowma
npm i
npm run build && npm start # ポートを変えるならROWMA_PORT=3001 npm startとする
ロボットをlocalhostのサーバーに繋ぐにはROWMA_SERVER_URL
に値をセットして接続します。
ROWMA_SERVER_URL=http://localhost:3000 rosrun rowma_ros rowma
デフォルトだとデータはプログラム中の配列に保存されます。ちなみにROWMA_DB=mongodb
とするとmongodbも使えます。使う場合はもちろん別でmongodbも立てます。
認証認可
認証認可用のサーバーを立てることでRowmaもこれを実現することができます。例えば「AdminであるAさんはトピックを送信できるがReadonly UserであるBさんはトピックの送信はできない」などです(認可の例)。具体的にはPOST: /AUTHENTICATOR_URL/applications/authorize
を使います。実装は少しOPAの考え方を参考にしました。
クラウド構成
公開サーバーはAWSのFargateにCircleCIからデプロイしています。実質ただのWebSocketサーバーなのでALBにはSticknessを設定しています。
Fluentd連携
トピックのデータをFluentdに流すことができます。連携するにはrowma_ros起動時にROWMA_FLUENTD_ENABLED=True ROWMA_FLUENTD_HOST=localhost ROWMA_FLUENTD_PORT=24224 rosrun rowma_ros rowma
のようにすれば連携できます。どのトピックをFluentdに流すかは次に示すrowma.yamlで指定できます。
rowma.yaml
rowma.yamlによってRowma ROSのトピックの向き先やFluentdに転送するトピック名、ファイルに吐き出すトピック名を起動時に指定することができます。
rosrun rowma_ros rowma ./rowma.yml
のようにrosrunの第三引数にファイルのパスを渡してやるとそれを読み込みます。なお、カレントディレクトリにrowma.ymlが存在する場合はデフォルトでそれを自動読み込みします。
topic_destinations:
- destination:
type: robot
uuid: abc-abc*
topic: /chatter
- destination:
type: robot
uuid: abc-def-ghi
topic: /test
fluentd_stream_topics:
- topic: /piyo
file_outputs:
- topic: /chatter
filepath: ./topiclog
遅延
一応遅延は計測してあります。詳しくはここをご覧くださいって感じなのですが、感覚的には北陽のLiDARを動かしても特に問題は感じなかった、という具合です。
ロボット同士で通信をする際の遅延の計測結果のグラフを下に示しておきます。横軸がデータのサイズ、縦軸が遅延時間です。遅延時間は往復時間を1つのPCで測っているので時間のズレによる誤差は発生していないはずです。黒い線がConnectionManagerをAWSに置いた環境での結果、青い点線が同じネットワーク内にConnectionManagerを置いた環境での結果です。
ROS2対応
rowma/rowma_ros2がROS2用パッケージです。今の所ros-dashingでしか動きません。
終わりに
Rowmaはまだベータ版です。気になることがあればお気軽にコメントください。