aptpod Tech Blog

株式会社アプトポッドのテクノロジーブログです

クラウドで動くOpen-RMFシミュレーション環境を作ってみた

intdashを介してRMF WebとGazeboシミュレーションを実行している様子(詳細な動画は最後の方にあります)

本記事の内容

こんにちは、Aptpodのエンジニアの影山と申します。普段はintdash CONTROL CENTER関係の開発を担当しています。

昨年のROSCon JPでも基調講演がありましたが、フリートの群制御のためのプラットフォームとして、オープンソースで開発が進められているOpen-RMFの名前を聞くことが近頃増えている気がします。

本記事では、話題のOpen-RMFと弊社製品のintdashを使って、クラウドを介してフリートを管理することを目的として、AWS上にOpen-RMF検証のためのシミュレーション環境を構築する手順を紹介したいと思います。

intdashを用いた事例の紹介とはなっていますが、内容はOpen-RMFを試してみたいという方へ向けて、Open-RMFにフォーカスして説明していますので、Open-RMFの使い方の一例として、参考にして頂ければ幸いです。

注:現在も開発が進行中なので、本記事の説明が最新のリポジトリの内容と合っていない場合があります。その点はご了承ください。

背景

これまで弊社ではROSとintdashを組み合わせて、ROSメッセージの可視化や、インターネットを跨いだリアルタイム遠隔操作を実現してきました。

現在、intdash CONTROL CENTERの一環として、フリート群管理システムについても研究開発を進めており、その過程でOpen-RMFの利用を検討してきました。 本記事では、検討の過程で得た知見をみなさまと共有できればと思っています。

Open-RMFと連携したintdash CONTROL CENTERの構成

Open-RMFとは

Open-RMFとは、異なるベンダーのフリートであっても、統一されたインタフェースで管理できることを目標として、 Open Source Robotics Foundationが開発を進めているプロジェクトです。

"https://osrf.github.io/ros2multirobotbook/intro.html" より引用

基本的なことは公式のドキュメントによくまとまっていますが、 現在も活発に開発が進んでいることもあり、公式のドキュメント以外には、導入に関する情報もまだ多くありません。

まずは公式のドキュメントやrmf-demoのREADME.mdを参考に、デモを試してみるのがよいかと思います。

フリートに対して、タスクを割り当てて、その内容に従ってロボットが動作する様子が確認できるかと思います。

クラウド上での環境構築の目的

しかしデモを試しただけでは、実際どのようにノード群が動作しているのかを理解するのはなかなか大変です。 実環境を想定して、理解を深めるには、独自の評価環境を作って試行錯誤を繰り返すのが近道だと思います。

弊社のintdashサーバと連携させることで、クラウド側からのフリート管理を実現させたい、という目標がありますので、そのためのお試し環境をクラウド上に構築してみました。

RMF Webの利用

Open-RMFの操作方法として、デモではシンプルなWebアプリが容易されています。そのほかにもRMF Webというリポジトリ上では、より充実したUIを持つアプリも開発されています。

RMF WebのフロントエンドはReactで実装されており、APIサーバと連動して、ロボットのモニタリングや、タスクのアサイン、ユーザ管理などの機能を備えています。

APIサーバの機能も充実しており、APIサーバを利用することで、独自のフロントエンドを持つWebアプリも実装可能かと思います。

APIサーバはFastAPIを利用して実装されており、起動した状態でhttp://127.0.0.1:8000/openapi.jsonにアクセスすると、OpenAPIのJSONスキーマが取得できます。これを眺めるとAPIを利用してどんなことができるかなんとなく理解できるかと思います。

OpenAPIのスキーマをredocで見やすくしたもの

環境構築

前提条件

  • 利用するクラウド環境: AWS EC2 G4dn
  • OS: Ubuntu22.04
  • ROSのディストリビューション:ROS2 Humble

システム構成図

シミュレーション環境全体の構成図

Open-RMFのROS2ノード群とGazeboのシミュレーション環境は、別々のROSドメインで分かれており、そのドメイン間をintdashで繋いでいます。 シミュレーション環境をDomain A、Open-RMFサーバ環境をDomain Bとしています。 ここでintdashはROSのトピックを双方向で中継する役割を担っています。 今回は手軽に開発環境を準備することが目的なので、シミュレーション環境がOpen-RMFと同じインスタンス上に置いていますが、実際は同じインスタンスに存在している必要はなく、NAT越えについてはintdashがカバーしてくれるのでシミュレーション側は、ローカルのPCで動かすことも可能です。

Open-RMFに含まれる、RMF Webを利用して、ロボットの稼働状態をブラウザ上で確認できます。 また、シミュレーションの状態もVNCサーバを利用することで、Gazeboの画面を確認できます。 intdashが提供するData Visualizerでintdashを通過するトピックの内容を確認することもできます。

Data Visualizerで/clockと/fleet_statesのトピックをリアルタイムで可視化した例

AWS EC2インスタンスの準備

GPUが搭載されたPCを都度準備するのは大変なため、AWSのEC2を利用しています。

GUIが不要であれば、デスクトップ環境は必須ではありませんが、今回はGazebo clientを利用したいので、GPUが使えるインスタンス上で、Ubuntuデスクトップをインストールします。今回はg4dn.2xlargeを利用しています。ストレージは50GB以上あった方がよいと思います。IPアドレスを固定したい場合は、加えてElastic IPを設定してください。 インターネットを上にも情報が色々あるので詳細は割愛しますが、NVIDIAのドライバとVNCサーバをインストールして、適切に設定をすることで、VNCを使ってデスクトップ環境にアクセスできるようになります。

海外リージョンだとGUI操作のレスポンスが悪いので、インスタンスは日本のリージョンで作成するのがよいです。

VNCのポートを公開するのは危険なので、開発時はSSHでポートフォワードしています。以下にVNC接続向けの.ssh/configのポートフォワード設定例を載せておきます。 こうしておけば、ssh aws-rmf-simulationで接続したあとに、VNC Viewerのようなツールで、localhost:5900にアクセスすればデスクトップ環境に接続できます。

Host aws-rmf-simulation
  Hostname xxx.amazonaws.com
  User ubuntu
  LocalForward 5900 xxx.amazonaws.com:5900
  IdentityFile ~/.ssh/aws_rsa_key

Open-RMFサーバの準備

Open-RMFの実行に必要なコンテナの作り方は、rmf_deployment_templateリポジトリの内容が参考になります。 こちらをベースとして、必要な部分を改造していくことで準備できるかと思います。

ビルド時に必要な変数などは、CIの設定を読むことで確認できます。

テンプレートではデモを実行するので、rmf-demosやrmf_simulationを取り込んだrmf-simulationというDockerイメージを作成して利用していますが(参考)、rmf-simulationを使わずに、オリジナルのDockerイメージを作成することで、独自の環境で動かすことができます。 テンプレートのREADME.mdにもある通り、rmf-simulationはOpen-RMFの基本的なパッケージを取り込んだrmfというDockerイメージをベースに作られています。オリジナルの環境もrmfをベースにして、自作のパッケージを/opt/rmf/srcに追加していく形になります。

どんなノードを起動する必要があるかについては、rmd-demosのlaunchファイルが参考になります。

以下にrmf_demoのlaunchをベースとして、オリジナルの環境を作る際の注意点を挙げます。

  • GazeboやRvizはOpen-RMFサーバ側では不要です
  • dashboardはRMF Webを実行するので不要です
  • デモ用のFleet Adapterの代わりに、Full Control Fleet Adapterを起動します
    • Fleet Adapterの詳細については、こちらの説明を参照ください
    • 起動の方法については、こちらのlaunch設定を参照ください
  • 現場環境側とサーバ側でROS Domainを別々にします
    • サーバ側のROSと現場環境側が直接通信せずに、常にintdashを介して通信するようにすることで、遠隔地との接続を模擬します

参考に、主要なノードへの起動時に設定必要なパラメータの情報をまとめた図を載せておきます。以下で説明するBuilding Mapと、をそれから生成するnav graphが環境を定義する重要な情報となっていることが分かるかと思います。

Open-RMFノードへのパラメータ

ロボットのシミュレーション環境の準備

ロボットをシミュレーションするために、rmf-demosを参考にGazeboを用います。 Full Control Fleet Adapterと組み合わせて簡単にAGVを試せるように、SlotcarというGazeboプラグインが容易されているので、そちらを利用します。 こちらとロボットのモデルを組み合わせることで、デモのようにロボットを操作することができます。 自己位置推定や自律走行をするわけではないので、その点は留意ください。

Slotcarプラグインはrmf_simulationリポジトリに含まれています。

プラグインをビルドするために次のようなリポジトリをcloneして、colcon buildする必要あります。

ロボットのモデルには、rmf_demoで使われているTinyRobotを利用します。 ロボットの初期位置は、ワールドを生成するときに同時に定義されるので、特にこの時点では気にする必要はありません。

TinyRobot

シミュレーション環境とOpen-RMFサーバの接続

シミュレーション環境とOpen-RMFサーバとの接続には、intdash Edge Agent2intdash ROS2Bridgeを用いています。

詳細な設定の方法はリンク先のマニュアルの通りですが、ポイントとして以下のトピックをブリッジする必要があります。

  • シミュレーション環境→Open-RMFサーバ
    • /clock
    • /fleet_states
  • Open-RMFサーバ→シミュレーション環境
    • /robot_path_requests
    • /robot_mode_requests
    • /robot_destination_requests
    • /map (slotcarを用いたシミュレーションの時のみ必要)

/fleet_statesトピックはslotcarプラグインが生成してくれないので、slotcarプラグインから配信される、/robot_stateトピックを配列にまとめて/fleet_statesトピックとして配信するノードが必要になります。

マップの準備

実際に試してみたいマップを作成します。Open-RMFで利用するマップはYAML形式のBuilding Mapファイルで定義されています。Open-RMFでは、Building Mapを編集しやすくするために、Traffic EditorというGUIツールが提供されています。

Open-RMFではロボットが走行する経路をBuilding Mapから変換して作成するYAML形式のnav graphで定義しています。 以下のコマンドで作成できます。

ros2 run rmf_building_map_tools building_map_generator nav <building mapのパス> <出力先ディレクトリ>

Traffic Editorでは壁やオブジェクトの位置なども定義できますが、建物の形状に関する情報は主にGazebo用のワールドを生成する際に用いられます。

マップ画像の準備

壁や障害物などが分かる図面の画像を用意します。この画像の上をTraffic Editorでなぞって、レーンなどを定義します。こちらの図は弊社の会議室の形に合わせた画像です。

マップ画像

縮尺の定義

Measurementツールで、地図上で線分が何メートルであるかを定義します。定義した内容に応じて画像ファイルの1ピクセルが何メートルであるかが計算されます。

measurementで引いた線分に実際の長さを設定する

一度保存して、Traffic Editorを再起動する必要あります。

※Traffic Editorはある程度大きなロボットを想定しているため、小さなロボットの経路を編集するには、画面上のレーンの太さなどがマッチしていません。UI上のレーンの太さなどは設定で変えることができないので、どうしても変えたい場合はソースコードの修正が必要です。

Waypoint、レーン、床、壁の定義
  • Waypoint
    • ロボットの走行する経路の頂点にあたる点です。名前を付けることで、タスクを作成するときにその名前で参照できます。
  • レーン
    • WaypointとWaypointを直線で結ぶロボットの走行経路です。
  • 床、壁
    • Gazebo用のワールド生成時に使用される情報です。設定しないと床が抜けたりしてシミュレーションに支障があります。

Waypoint属性の設定

spawn_robot_typeとspawn_robot_nameでシミュレーション上でのロボットのスポーン位置を指定することができます。

※注: レーンで接続されたWaypointのうち、一つはis_charger=trueである必要があります。

レーンを設定している様子

Building MapからGazeboで使用するワールドの生成

Building Mapの準備ができたら、以下のコマンドを実行することで、Gazeboで利用できるワールド情報を自動生成できます。この際に、Traffic Editor上でWaypointの属性情報で設定した情報を利用して、ロボットの初期スポーン位置がワールドデータに反映されます。初期位置を随時変えたい場合は、毎回Traffic Editorで編集するのが手間なので、building.yamlの内容を直接編集するスクリプト等を用意しておくと作業がはかどります。

ros2 run rmf_building_map_tools building_map_generator gazebo <building.yamlのパス> <ワールドデータの出力先> <モデルデータの出力先>

壁の高さや厚さなどが固定値のため、もし修正したい場合はソースコードの修正が必要です。以下に例を示します。

sed -i 's/self.wall_height = 2.5/self.wall_height = 0.5/g' src/rmf_traffic_editor/rmf_building_map_tools/building_map/wall.py
sed -i 's/self.wall_thickness = 0.1/self.wall_thickness = 0.05/g' src/rmf_traffic_editor/rmf_building_map_tools/building_map/wall.py

シミュレーションを利用したOpen-RMF環境の起動

準備お疲れさまでした!

シミュレーションを利用して、indashと組み合わせたOpen-RMF環境を起動して、Open-RMFから制御できることを確認します。 まずGazeboを起動します。 まず次のように環境変数でモデルやプラグインのパスを設定します。

current_path=`pwd`
export GAZEBO_MODEL_PATH=<ロボットのSDFが保存されているディレクトリへのパス>:<生成したワールドのモデルへのパス>:/usr/share/gazebo-11/models:$GAZEBO_MODEL_PATH
export GAZEBO_RESOURCE_PATH=/usr/share/gazebo-11:$GAZEBO_RESOURCE_PATH
export GAZEBO_PLUGIN_PATH=${current_path}/install/rmf_robot_sim_gz_classic_plugins/lib/rmf_robot_sim_gz_classic_plugins:${current_path}/install/rmf_building_sim_common/lib:/usr/share/gazebo-11:$GAZEBO_PLUGIN_PATH

そして、ワールドへのパスを引数に与えてGazeboを起動します。

次に、Open-RMF環境のコンテナを起動します。 こちらは準備したコンテナをそれぞれ起動すれば良いですが、複数のコンテナを扱うことになるので、docker compose用のYAMLファイルにまとめておくと便利です。

実際の操作の様子

操作の様子は動画を参照ください。RMF Webのブラウザのウィンドウと、VNC Viewerで表示しているGazeboのシミュレーションの様子を重ねて撮影しています。

www.youtube.com

動画では、2台のロボットが縦方向に往復しているところに、横方向の往復をするタスクを割り当てています。RMF Webのコンソールからタスクを設定して、それがロボットにアサインされる様子が確認できると思います。 (シミュレーションでは時刻がUNIX時間になってしまうので、1970年1月1日を基準とした時刻で画面上表示されています。)

動画ではRMF Webからタスクをアサインする様子を紹介しています。APIサーバにRESTでコマンドを送ることで、ブラウザや、ROSを利用することなく、外部から操作することも可能です。

停止する際は、docker compose downでコンテナを停止して、Gazeboを起動しているターミナルで、ctrl-cでシミュレーションを停止します。

最後に

いかがでしたでしょうか? 自作のマップをベースに環境を構築できれば、色々なパターンの検証などがはかどるかと思います。これをご覧になったみなさまのOpen-RMF導入の参考になれば幸いです。

今回はTinyRobotを利用して環境を構築していますが、リアルな自律走行ロボットを、Free FleetとNav2を合わせて利用して制御する方式も今回の内容を拡張することで実現可能です。弊社でもTurtlebot3 Burgerの実機を用いて検証していますので、別の機会に紹介できればと思います。

弊社会議室でTurtlebot3 Burgerを使った検証を行っている様子

最後に、宣伝になってしまいますが、ROSConJP 2023で、「Open-RMFを応用したクラウドフリート管理システムの構築」というタイトルで登壇予定です。 弊社アプトポッドもROSConJPスポンサーになり、ブースを出す予定です。

そちらでは、検討の過程で学んだOpen-RMFのより深い部分についても紹介できればと思いますので、ぜひ発表を聞いたりブースに訪れて頂ければ幸いです。

弊社ソリューションのご案内

弊社ではモビリティやロボットのリアルタイムでインタラクティブな管制制御システムの迅速な構築を可能にするintdash CONTROL CENTERを推進しております。

www.aptpod.co.jp

スマートシティにおける自動運転車、工場や物流倉庫における搬送ロボット、建設現場における建設機械など、モビリティ群の統合遠隔監視・管理、遠隔制御システムなどでお困りのことがあれば、ぜひお声掛けください。

弊社お問合せフォームはこちらです。

www.aptpod.co.jp