UE4 と ROS を連携させてみた

非常に高機能なゲーム開発エンジンであるUnreal Engine4 (UE4)。
物理エンジンも備えているため、ゲームだけではなくシミュレータとしての利用もされていて、ISPでも活用する機会が増えています。

今回はロボティクスへの活用を踏まえて、ロボティクス分野でデファクトスタンダードになりつつある ROS を使った通信と UE4 との連携に挑戦してみました。

環境

ROS は Ubuntu でしか動作しないのですが、WSL (Windows Subsystem for Linux) を使うことで、Windows10 の同一マシン内に Ubuntu、Windows 両方の環境を用意しました。

 ※ 今回は対象外ですが、もちろん、ROS Core 経由で他の ROS ノードとの連携も可能です。
※ 今回は対象外ですが、もちろん、ROS Core 経由で他の ROS ノードとの連携も可能です。

実現方法概要

ROSBridge

ROS を使った通信を行うためには、ROS の環境一式が入っている必要がありますが、OS 等の違いによってはそもそも導入ができない場合があります。
そういった環境のために「ROSBridge」という、まさに橋渡しのための仕組みがあり、WebSocket or TCP or UDP を利用して ROS Core と通信することができます。
UE4 側ではこちらを用いて通信を行います。
ROSBridge Suite … http://wiki.ros.org/rosbridge_suite

UE4 側からの ROS 通信

UE4 側からの通信は主に2つの方法があります。
今回は実装の少なさから、(2) ROSIntegration を使用しました。

(1) UEWebSocket を使った通信

UEWebSocket (https://github.com/feixuwu/UEWebsocket) というプラグインを使うことで、UE4 で WebSocket 通信ができます。
こちらを用いることで WebSocket 経由で ROSBridge と通信ができますが、Publish、Subscribe 等のコードは自作する必要があります。

(2) UE4 ROSIntegration を使った通信

ROSIntegration (https://github.com/code-iai/ROSIntegration) というプラグインを使うことで、TCP 経由でROSBridge と通信することができます。
基本的な Topic による通信はカバーされていて、Topic の拡張も容易なようです。

サンプルコード

以下の2種類のTopicを定義し、UE4上においたキャラクターをROS通信で動かしてみます。

Topic名 送受信 説明
/target_pos geometry_msgs/Vector3 * → UE4 キャラクター移動先
/location geometry_msgs/Vector3 UE4 → * キャラクター現在位置

「/target_pos」を送信することでキャラクターを動かします。
「/location」はキャラクターの現在位置を ROS 側で表示するのに使用します。

( 画面キャプチャ。ROS で操っているのが分からないですが…。)
( 画面キャプチャ。ROS で操っているのが分からないですが…。)

プロジェクトは以下 github に置いています。
https://github.com/ISP-Kazuki-Nagasawa/CommROSBridgeSample.git

作成について

作成する際の要点をまとめました。
UE4 ROSIntegration の詳しい使用方法は、ROSIntegration の github を参照してください。

サーバ側

ROSIntegration は ROSBridge のプロトコルのうち、TCP に対応しています。
また、bson で送ることを基本としているようなので bson 指定して ROSBridge を起動しておきます。
( ポートは 9090 としました。 )

$ roslaunch rosbridge_server rosbridge_tcp.launch port:=9090 bson_only_mode:=True

プロジェクト作成

プラグインを使用するので、UE4 は C++ プロジェクトとして作成します。
プロジェクトができたらいったん終了して、Plugins に ROSIntegration を追加してから再起動してプラグインが使用できるようにしておきます。

ROSIntegration の使用

ROS 環境の設定は GI (Game Instance) で定義します。
新規 BP (ブループリント) から「ROSIntegrationGameInstance」を基にした BP を作成し、ROS 接続先の host と port を指定します。

作成した GI は、プロジェクト設定のマップ&モードで指定するのを忘れずに。

C++ 版で通信部を作成

ROSIntegration を試したところ、BP 版では簡易なものしか送れないようなので、C++ 版を使います。
Actor クラスを継承した C++ コード (Communiator.h & Communicator.cpp) を作成しました。
詳しくは実際のコード (Communicator.cpp) を参照してください。

levelbp

作成したら、BP と合わせます。全体像は以下の形です。

使ってみる。

作成できたら試してみます。
ROSBridge TCP 起動後、UE4 側を起動することで通信が始まります。
( ROS と通じている ) コンソールから geometry_msgs/Vector3 の Topic を送信することで、キャラクターを動かすことができます。

$ rostopic pub -1 /target_pos geometry_msgs/Vector3 “x: 120.0 y: 260.0 z: 0.0”

※ フィールドのX座標、Y座標は -350 ~ 350です。また、Z座標は無視します。

また、( ROS と通じている ) コンソール上でキャラクターの現在位置を受信することも可能です。

$ rostopic echo /location
x: 84.0738983154
y: -40.0875854492
z: 110.149993896

x: 226.607559204
y: 133.208755493
z: 110.149993896

x: 275.485900879
y: 266.171844482
z: 110.149993896

備考

ROSBridge を起動していない状態で実行すると、UE4 自体が落ちるので注意です。
接続チェック処理があると思われるので、必要ならその辺りの処理の追加も必要ですね。

まとめ

ROSBridge を経由して UE4 と ROS の通信ができるようになりました。
この仕組みや既存の ROS の仕組みを活かして UE4 の開発も面白くしていきたいです。