Node-REDでつなぐUnreal EngineとROS

# はじめに

　[Node-RED Advent Calendar 2024](https://qiita.com/advent-calendar/2024/node-red)の21日目です。

　English Version:

https://qiita.com/background/items/b051fcebba3f67e8c7d8

　去年は[Node-RED MCUのノードの作成](https://qiita.com/background/items/9b820251aa9dda5a3167)について書かせて頂きました。
　今年度から研究室に配属され、新たにUnreal Engine 5(UE5)とROSを使うことになりました。これらを通信して連携させるために、Node-REDも使っています。

　この記事ではUE5とROSとNode-REDの連携に関する概要について書きます。技術的な要素は私のホームページに書いているので、ご興味があればご覧ください。各項目で関連記事を載せています。

# ソフトウェアについて

　使用するソフトウェアについて、簡単な概要と利用方針を紹介します。

### Node-RED

　フロー型のプログラミングツールです。HTTP、WebSocket、TCP、UDP、MQTTなどの通信を利用することができます。IoTとも相性がいいです。
　私が使ったプラグインやソフトウェアだと、ROS側がWebSocket通信、UE5側がHTTP通信だったのですが、Node-REDを使えば通信を中継できました。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/652efcea-91fe-82cf-23c4-3c4ab599c4d3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/c9b99ba7-ac7b-707d-226e-de41af4b68c8.png)

### ROS

　ロボットを制御するためのソフトウェアです。UE5でもロボットアームの運動学の計算をすることはできるようですが、どうせなら実機と同じ計算の方が良いだろうということで使うことにしました。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/2a70001e-822a-6ec5-9631-40df3bc22f29.png)

### Unreal Engine 5(UE5)

　ゲームエンジンです。特にGPUを活用したグラフィック処理を活かそうと思っています。現実で3Dスキャンしたデータを取り込むことができます。
　Node-REDと同様に、ブループリントでフロー型のプログラミングができます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/619fc6d3-0c47-81e3-f58c-c279dfbe2a8c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/93a9b04c-7a6e-0751-82ed-84be99bff133.png)
関連記事：[Unreal Engine 5を使ってみる　その10（Scaniverse、点群データの取り込み）](https://404background.com/ue5/unreal-engine-5-10/)

# Open Manipulatorで動作検証

## 全体の構成
　全体の構成は以下の図のようになっています。Open Manipulatorはソフトウェアが整っているので、このくらいの構成であればノーコードレベルで動作させることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/a39ba638-79b5-b335-1805-af05ffda2b6d.png)

　ROSでOpen Manipulatorのジョイントの角度を計算し、その値を実機とUE5に同時に送信するようになっています。
　逆にUE5の入力をROSに送信して、実機を操作できるというのも確認しました。

　当初はWindows 10のノートPC、Windows 11のデスクトップPCでNode-REDを使って通信して、UE5とROSを起動するPCを分けて負荷を分散していました。
　最近はWindows 11、GPUがRTX3050のゲーム用ノートPCを使っているのですが、1台で処理できています。UE5を実行するうえではGPUが大事なようです。

## Node-REDとROSの連携

### ROS側

　WSL2でUbuntu 20.04をインストールし、ROS Noeticの環境を構築しています。
関連記事： [WSL2を使ってみる　その３（Ubuntu 20.04、ROS Noetic、Open Manipulator）](https://404background.com/program/wsl2-3/)

　予めrosservice callでパラメータを送信して動かすことができるのは確認しました。この形式に合わせて、Node-REDで送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/08ca8383-abbd-5f0b-f68c-e4f27bfc4250.png)

　rosノードがROS Bridgeを起動している前提になっているので、実行しておく必要があります。
関連記事：[WSL2のROSとWebSocket通信（ROS Bridge、Node-RED、Gazebo）](https://404background.com/program/ros-bridge/)

### Node-RED側

　事前にturtlesimのカメをNode-REDで操作できることは確認していました。
関連記事：[ROS1を使ってみる　その１（Turtlesim、Node-RED）](https://404background.com/ros/ros1-1/)
<iframe width="560" height="315" src="https://www.youtube.com/embed/gRtFNCnwPUM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　全体のフローは以下のようになっています。ros callSrvノードを使っています。スライダーで操作できるようにしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/cbfc07ac-9cd8-65e6-f914-fe5fb91babea.png)
関連記事：[ROS1を使ってみる　その３（Open Manipulatorの操作、Node-RED）](https://404background.com/ros/ros1-3/)

　templateノードで先程rosservice callで送信した値になるようにしています。flow変数を使っているのは、スライダーの値を保持するためです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/66a6de74-83cb-6873-6fbf-0d6c7d04f275.png)

　dashboardノードで以下のような画面を作成してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/41311162-8113-94cf-d44a-5456bcc736c6.png)

### 実際の動作

　スライダーの値に合わせてジョイントが回転するようにしてみました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/KBqswSWB6b4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

## Node-REDとUE5の連携

### UE5側

　UE5のHTTP Requestを使うと、HTTP通信を扱うことができます。WebSocket通信もできるらしいというのは聞いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/9de08572-bf8a-9635-9a9c-0cb384b752bf.png)

　他にもRemote Control APIなどがあるのですが、Node-REDと連携させるうえではHTTP Requestノードが一番使いやすかったです。JSON形式のデータを加工することもできます。
関連記事：[Unreal Engine 5を使ってみる　その８（HTTP Request、Remote Control Web Interface、Node-RED）](https://404background.com/ue5/unreal-engine-5-8/)

　Open Manipulatorのモデルも作成しました。
関連記事：[Unreal Engine 5を使ってみる　その７（Open Manipulator）](https://404background.com/ue5/unreal-engine-5-7/)
<iframe width="560" height="315" src="https://www.youtube.com/embed/gl_4xUENoJc" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

### Node-RED側

　http in/out、requestノードを利用して通信します。
関連記事：[Unreal Engine 5を使ってみる　その9（Remote Control API、Node-RED）](https://404background.com/ue5/unreal-engine-5-9/)

　Remote Control APIを使った場合の例ですが、こちらもROSとの連携と同様にスライダーで操作できるようにしました。APIの仕様に合わせたデータ形式になるように加工しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/506c3052-544a-c8b1-d0a4-2303339d5532.png)


### 実際の動作

　UE5のRemote Control APIを使ったものですが、ジョイントの角度を操作できました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/0j4AB2rYCT0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

## UE5とROSの連携
　Node-REDとROS、Node-REDとUE5でそれぞれ通信できたので、UE5とROSの通信をNode-REDで中継することができました。

　以下の動画では処理を制限していたのでUE5側の動きが遅いですが、実機とほぼ同時に動かすことができました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/XNlZTDqnUVI" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　以下の動画はROSのシミュレータとUE5の画面を並べています。
<iframe width="560" height="315" src="https://www.youtube.com/embed/BhJnOT9fMPs" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　ちなみにOpen Manipulatorは4軸＋エンドエフェクタで自由度が少ないのですが、6軸のモデルもMoveItのパッケージを作成して運動学の計算を行い、UE5で動作させることができました。自分で設計したロボットでも自由に動かすことができそうです。


# ロボットのデジタルツインに向けて

　シミュレーションをするだけならROSのシミュレータでもできるのですが、私はUE5のグラフィックを活かして画像処理関連のソフトウェアを併用しつつ、ロボットのシミュレーションをしようと考えています。
　例えば光源の位置が変わると、以下の画像のように変化します。影も考慮して画像処理を行えそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/89c5661a-80d0-0d7c-9534-f8c33efb4627.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/4ea936be-7425-5724-79b1-0111d0b9b881.png)

　UE5のSet View Target with BlendノードとTake High Res Screenshotノードを使うと、以下の動画のような画面で撮影を行うことができます。[Quixel Megascans](https://quixel.com/megascans)のリアルなモデルを利用しています。
 関連記事：[Unreal Engine 5を使ってみる　その12（Screenshot ）](https://404background.com/ue5/unreal-engine-5-12/)
<iframe width="560" height="315" src="https://www.youtube.com/embed/L_CF6PQqfcY" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　ロボットで物体を検出するときは、YOLOというソフトウェアを使ってリアルタイムに検出しています。
　UE5でもNode-REDでPythonを実行し、YOLOで物体を検出して、その結果を他のノードと組み合わせることができました。
関連記事：[YOLOで物体検出　その２（Python、Node-RED）](https://404background.com/program/yolo-2/)
[Unreal Engine 5を使ってみる　その11（Pixel Streaming ）](https://404background.com/ue5/unreal-engine-5-11/)
<iframe width="560" height="315" src="https://www.youtube.com/embed/lJGo7YjbGmk" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　映像の3Dスキャンしたトマトの苗のデータは荒いのですが、最近他のプラグインで取り込むとScaniverseでスキャンしたまま表示させることができました。以下の画像は私のハニワです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/4db7cb75-906e-ebb8-df53-4950fe144438.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/c800dff8-f1ea-acf3-5c2f-190141e65f42.png)

　YOLOの姿勢検出モデルを利用して、PC2台でそれぞれのカメラ映像から座標を取得し、3次元座標にしてUE5上の物体を動かすこともできました。簡易的な全身トラッキングができそうです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/3VK54l226DA" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　このトラッキングは、よくイベントでご一緒している@mshioji さんの記事がヒントになりました。２つのカメラでワークの位置をフィードバックしながらロボットを制御されています。
[チトセロボティクスの「クルーボ」で産業用ロボットのビジュアルフィードバック技術を試してみた（２）](https://qiita.com/mshioji/items/01443911f0903d300205)

　光源色を変化させるとYOLOの検出結果が変わることも確認できました。現実には無さそうな状況ですし、トマトのモデルでリンゴを検出しているので、そもそも誤検出ではあります。
<iframe width="560" height="315" src="https://www.youtube.com/embed/fiNxOwfHmkY" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

# 最後に
 　
　Unreal EngineとROSを使い始めてまだ１年経っていないのですが、Node-REDに慣れていたおかげで連携させることができました。実装もローコードレベルです。
　今後もソフトウェアごとの得意な部分を活かして、ロボットのシミュレーションを行いたいなと思っています。