Ubuntu22.04でros2-for-unityの環境構築

# 概要
Ubuntu22.04でros2-for-unityを用いてRos 2メッセージのやり取りを行う。マシン間通信もできた
これを行うモチベーションとしては、カスタムメッセージをros2-for-unityで使用するにはメッセージを仕込んだ上でビルドをする必要があるが、Windowsではros2のビルド環境を整えるのが面倒なのでUbuntuでやりたいというところ。

# 動作環境・バージョン
### 動作環境
Ubuntu : 22.04
VScode : 1.95.3

記事作成者の個人的好みでVSではなくVScodeを用いた。VSでも同じことが実現可能なはず（未検証）

### バージョン
ros 2 : humble
Unity : 6000.0.28f1

# 前提条件
- ros2がインストールされていること

# コンテンツ
## Unityのインストール
### Unity Hubのインストール
- パブリックキーの追加
    ```
    wget -qO - https://hub.unity3d.com/linux/keys/public | gpg --dearmor | sudo tee /usr/share/keyrings/Unity_Technologies_ApS.gpg > /dev/null
    ```
- リポジトリを追加
    ```
    sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/Unity_Technologies_ApS.gpg] https://hub.unity3d.com/linux/repos/deb stable main" > /etc/apt/sources.list.d/unityhub.list'
    ```
- インストール
    ```
    sudo apt update
    sudo apt-get install unityhub
    ```
### Unityのインストール
1. 上記でインストールしたUnity Hubを起動
1. Unity Hubへのログインを求められるので、ログイン（アカウントが無ければ作成する）
1. InstallsからInstall Editorを選択し、Unity 6をインストール（或いはインストールするようポップアップが出る）
    <img width="1027" alt="image.png (42.8 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/5a845158-6b5f-49a5-8271-b152b2576c45.png">

## .NET開発環境の構築
1.  .NET SDKのインストール
    ```
    sudo apt update
    sudo apt install dotnet-sdk-6.0
    ```
2. VScode拡張機能のインストール
    - [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)
    - [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit)
    - [IntelliCode for C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.vscodeintellicode-csharp)
    - [.NET Install Tool](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.vscode-dotnet-runtime)
    - [Unity](https://marketplace.visualstudio.com/items?itemName=visualstudiotoolsforunity.vstuc)

## unityの動作確認
1. 新しいプロジェクトを作成
    <img width="1027" alt="image.png (40.3 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/5d581639-ebd0-42a6-89ef-d3002c455920.png">

1. Window > Package Manager を選択して、 Package Manager を起動し、Visual Studio Editorを選択する
    - バージョンが2.0.20以上であることを確認
    - UnlockされていなければUnlockする
    <img width="1211" alt="image.png (178.5 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/2885cbc6-65b8-4131-b6cb-3498c4bd92eb.png">

1. Edit > Preferences を選択して Preferences を開く
    - External Script Editor が Visual Studio Codeになっているか確認
    -  バージョンがVisual Studio Editor v2.X.X enabledになっているか確認 
    <img width="1211" alt="image.png (233.1 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/823adea9-dd45-4403-944a-dcefedad4a32.png">


1. Assetsビューで右クリック/Create/MonoBehavior Script/でテスト用スクリプト作成
     <img width="1207" alt="Screenshot from 2024-11-25 11-38-32.png (188.3 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/5f2a20e2-d9ff-4832-8202-b8551bf6e5b3.png">
1. ダブルクリックした際にVScodeが立ち上がり、下のようになっていれば成功
    - サインインを求められたらマイクロソフトアカウントでサインインする
    <img width="1130" alt="Screenshot from 2024-11-25 11-39-02.png (68.8 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/872c3352-66d5-4465-bd94-f5bafcf8df0a.png">

## ros2-for-unityのインストール
### ros2csのインストール
1. 依存パッケージのインストール
    ```
    # Install rmw and tests-msgs for your ROS2 distribution
    apt install -y ros-${ROS_DISTRO}-test-msgs
    apt install -y ros-${ROS_DISTRO}-fastrtps ros-${ROS_DISTRO}-rmw-fastrtps-cpp
    apt install -y ros-${ROS_DISTRO}-cyclonedds ros-${ROS_DISTRO}-rmw-cyclonedds-cpp
    
    # Install vcstool package
    curl -s https://packagecloud.io/install/repositories/dirk-thomas/vcstool/script.deb.sh | sudo bash
    sudo apt-get update
    sudo apt-get install -y python3-vcstool
    
    # install .NET core 6.0 SDK
    sudo apt-get update; \
      sudo apt-get install -y apt-transport-https && \
      sudo apt-get update && \
      sudo apt-get install -y dotnet-sdk-6.0
    
    # install patchelf for standalone build
    sudo apt install patchelf
    ```

2. ros2csのhumbleバージョンをcloneする
`git clone https://github.com/RobotecAI/ros2cs.git`

3. ビルド
    ```
    source /opt/ros/humble/setup.bash
    cd ros2cs
    ./get_repos.sh
    ./build.sh --standalone
    ```

### ros2-for-unityのインストール
1. ビルド
    ```
    git clone git@github.com:RobotecAI/ros2-for-unity.git ~/ros2-for-unity
    . /opt/ros/humble/setup.bash
    cd ros2-for-unity
    ./pull_repositories.sh
    ./build.sh --standalone
    ```
2. unity_packageの作成
`create_unity_package.sh -u <your-path-to-unity-editor-executable>`
unity-editorのパスは`/Unity/Hub/Editor/<version>/Editor/Unity`
上記スクリプトにより、`install/unity_package/`以下に`Ros2ForUnity.unitypackage`が作成される

3. インポート
Assets -> Import Package -> Custom Packageからさきほど作成したunity_packageを選択

### ros2-for-unityの動作確認
1. スクリプトを作成し、適当なGameObjectにアタッチ
    ```Ros2MsgTest.cs
    using UnityEngine;
    using ROS2;
    
    public class Ros2MsgTest : MonoBehaviour
    {
        private ROS2UnityComponent ros2Unity;
        private ROS2Node ros2Node;
        private IPublisher<std_msgs.msg.String> chatter_pub;
        private int i = 0;
        // Start is called once before the first execution of Update after the MonoBehaviour is created
        void Start()
        {
            TryGetComponent(out ros2Unity);
        }
    
        // Update is called once per frame
        void Update()
        {
            if (ros2Unity.Ok())
            {
                if (ros2Node == null)
                {
                    // Nodeの名前を指定する
                    ros2Node = ros2Unity.CreateNode("ROS2UnityTalkerNode");
                    //トピックの名前と型を指定する
                    chatter_pub = ros2Node.CreatePublisher<std_msgs.msg.String>("hello_from_Unity");
                }
            }
    
            // スペースキーが押されたら
            if (Input.GetKeyDown(KeyCode.Space))
            {
                Debug.Log("Space key was pressed.");
    
                i++;
                std_msgs.msg.String msg = new std_msgs.msg.String();
                msg.Data = "Hello world from Unity" + i;
                chatter_pub.Publish(msg);
            }
        }
    }
    
    ```

2. /Ros2ForUnity/Scripts/Ros2UnityComponent.csも同じオブジェクトにアタッチ
    左右のHierarchyウィンドウとInspectorウィンドウが以下のようになっていれば概ねOK
    <img width="1835" alt="image.png (204.0 kB)" src="https://img.esa.io/uploads/production/attachments/19744/2024/11/25/148658/5e6b9df0-b1cc-483f-b305-8eb1656fd9a1.png">

3. ターミナルを開き、`ros2 topic echo hello_from_Unity`を実行後、Unityのゲームを開始し、スペースキーの入力でトピックがパブリッシュされていることが確認できれば成功

# 終わりに
謎にUbuntuではUnityが動かないと勘違いしていたが、そんなことはなかった

# 参考文献
[unityのインストール](https://symfoware.blog.fc2.com/blog-entry-2745.html)
[unity公式](https://docs.unity3d.com/hub/manual/InstallHub.html#install-hub-linux)
[VScodeの設定](https://qiita.com/riekure/items/ec35feeef553637a4113)
[ros2-for-unityのインストール](https://qiita.com/TakanoTaiga/items/b3cb116c73b9e5624c47)
[ros2cs公式](https://github.com/RobotecAI/ros2cs/tree/master)
[ros2-for-unity公式](https://github.com/RobotecAI/ros2-for-unity)