Unity & gRPC & Rust & C/C++で作るマイコン制御ロボット・シミュレーション環境

# 概要
TOPPERS/箱庭プロジェクトでは、「[マイコン制御ロボットシミュレーション](https://toppers.github.io/hakoniwa/prototypes/single-robot/)」環境を提供しています。

本シミュレーション環境は、１個のロボットを１個の仮想マイコン(Athrill)で制御することに特化したものです。

一方で、箱庭のアーキテクチャは、「[箱庭コンセプト](https://toppers.github.io/hakoniwa/docs/concept/)」が示すように、様々なコンポーネントを組み合わせた協調シミュレーション環境です。

コンセプトレベルのアーキテクチャは下図のイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/d17f56a1-67be-aafa-f70c-643bd8bcc7a3.png)


本記事では、複数の仮想マイコン(Athrill)がUnity内の複数のロボットを制御するためのシミュレーション・アーキテクチャ案を検討し、サンプル・デモをお見せします。

# 実現レベルのアーキテクチャ案

実現レベルのアーキテクチャ案は、下図の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/a6444415-a9f3-e806-1908-62f422dc7597.png)

アーキテクチャのポイント

* 右上に箱庭アセット(Athrill)が複数あり、ここで複数の仮想マイコンを実現しています。
* 左上に箱庭アセット(Unity)があり、ここで複数のロボットを実現しています。
  * 負荷分散のため、Unityは複数のPC上で連携させることができます。
  * 複数のUnity連携方法としては、マルチプレイゲームを実現する[Photon](https://www.photonengine.com/ja/)のサービスを利用します。
* 箱庭の基盤技術で[C++版箱庭コア機能](https://www.toppers.jp/docs/contest/2022/A01_mori.pdf)は、箱庭アセット間のシミュレーション時間の同期とアセット間の通信機能([PDU](https://github.com/toppers/hakoniwa-ros2pdu))を提供します。
  * C++で作成しているのは、オブジェクト指向言語で性能面で一番優位と思ったためです。
* 中央上にある[箱庭マスタ(Rust)](https://github.com/toppers/hakoniwa-master-rust/tree/main/main)は、C++版箱庭コア機能のgRPC サーバーの位置づけです。
  * 別 PC にいる箱庭アセットが箱庭と連携する場合に、箱庭マスタが提供するgRPCサービスAPIを呼び出します。
  * なお、Windows版UnityがWSL2内の箱庭との連携する際に、WSL2のメモリ空間とWindowsのメモリ空間が分離されているために、C++版箱庭コア機能を直接呼び出せないという課題がありました。この課題解決方法として、箱庭マスタをRustで作成するという動機づけにもなりました。。
  * ちなみに、Mac/Linux の場合は、箱庭マスタを介さずに、直接C++版箱庭コア機能を呼び出すことが可能です。

# 箱庭マスタをRustで作った理由
ここで、箱庭マスタをRustで作った理由を書いておきます。

箱庭マスタを実現するには、以下が必要となります。

* C/C++のAPI関数を直接呼び出しできること
* gRPC を利用できること
* 性能面で高速に動作すること
* 自分のモチベーションを維持できること

選択肢としては、以下がありました。

* C++
* Go
* Rust

この中で、C++ は「C++版箱庭コア機能」の開発延長線上で一番有力なものでした。
しかし、gRPC の導入が若干面倒であったのと、自分の開発モチベーションが上がらなかったので対象から外しました。

gRPC を簡単に利用出来て、新しい言語を試せそうなものが何かないか探していて最初にヒットしたのは「Go」でした。

Goを調べ始めていると、Rust なるものが検索でたまたまヒットして、Rust も調べようということになり、Rustは自分の開発者魂を十分に揺さぶってくれました。

決め手は以下です。

* GC なしで、メモリリークしない言語（高速かつ安全）
  * C++のスマートポインタが言語レベルでサポートされいてる！と思った。
* パッケージ管理システムがめちゃ優秀
  * gRPC も簡単に導入できた(tokio というパッケージを利用)
* C 関数コールも簡単
  * Rust版箱庭マスタの[C++版箱庭コア機能のAPIコール実装](https://github.com/toppers/hakoniwa-master-rust/blob/610d965828de5961a9dd21f2a54f65aae0980ad6/main/src/hako/api/mod.rs)

# 実装

本アーキテクチャを実装したリポジトリを以下で公開しました。

https://github.com/toppers/hakoniwa-base

ちなみに、本リポジトリの構想としては、マイコン制御だけでなく、TOPPERS/箱庭がプロトタイプモデルとして個別に開発している様々なリポジトリの統合も視野に入れています。


# サンプル・デモ
複数の仮想マイコン(Athrill)がUnity内の複数のロボットを制御するためのシミュレーションとして、[SWEST24](https://swest.toppers.jp/SWEST24/program/s3b.html#s3)で紹介された電車モデルと信号モデルを題材としました。

電車モデルを制御する仮想マイコン(Athrill)と信号モデルを制御する仮想マイコン(Athrill)が、Unity内の電車と信号を制御する様子はこちらです。

https://user-images.githubusercontent.com/164193/210167332-f685d856-a19b-4471-944f-7f9f03bb1e47.mp4

ちなみに、ここで利用しているマイコン制御アプリケーションは、実機で利用されているものをそのまま使用しています。

現時点で、電車の方は正しく動作していることを確認しておりますが、信号の方はポートの設定、カラーセンサの精度調整が必要なため、へんな動きをします。。

# 最後に
これまで、箱庭コンセプトを実現するために必要な技術調査を目的として、４年ほどかけて、様々な[プロトタイプモデル](https://toppers.github.io/hakoniwa/prototypes/)を作成してきました。

だいぶ知見が溜まってきましたので、今後は、箱庭コア機能としてこれらのプロトタイプモデルを統合した新シミュレーション環境を構築していきたいと考えております。

最終的にはこんな感じの分散シミュレーション環境の構築を目指します。乞うご期待ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/6cc3d1a9-6ff3-a68f-efb9-0fbffc0a3718.png)