ros2-for-unity でサクッとROS2 アプリ

# ros2-for-unity とは？

3D アプリを簡単に作れる Unity で、サクッと ROS2 通信できるようになります。
とても便利！

<br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/65e3b42c-f3d2-573f-334c-8d2b3503f6e8.png)

<br>

Unity で ROS2 と通信する仕組みは主に下記３つがありますが、

| パッケージ | 通信ベース |  |
|:-----------|------------:|:------------:|
| Unity-Robotics-Hub (Unity 公式)      | TCP 通信        | [Unity-Robotics-Hub](https://github.com/Unity-Technologies/Unity-Robotics-Hub "Unity-Robotics-Hub")         |
| ros2-for-unity                       | DDS ネイティブ      | [ros2-for-unity](https://github.com/RobotecAI/ros2-for-unity "ros2-for-unity")       |
| ros-sharp                            | json 文字列        | [ros-sharp](https://github.com/siemens/ros-sharp "ros-sharp")         |


今回の ros2-for-unity は、

:::note info
・速い　（DDS ネイティブ、インストールはディレクトリコピーで、利用コードは簡単に使い始められる）
・安い　（Apache-2.0、オープンで無償で使えるという意味で）
・うまい（Win, Linux, あとフォークで[Android](https://qiita.com/Kotakku/items/cdc3eca89dd8aec4ee86 "Android")も。）
:::
の３点でオススメと言えます！

しかも
**「オープンソースでのリリースは TIER IVとの協力により実現しました（chrome 翻訳）」**
などと書かれており、ワクワクしますねｗ


※参考：片岡さんの記事

https://zenn.dev/hakuturu583/articles/ros2_for_unity


# ということで

サクッと使ってみましょう。

最初の一歩は

:::note info
①　ダウンロード
②　そのフォルダをそのまま Unity プロジェクトの Asset ディレクトリにコピー
③　Empty Object に「ROS2UnityComponent.cs」「ROS2TalkerExample.cs」をアタッチ
:::

コピーしてアタッチ。これだけで自作アプリが Topic を publish するようになります。
簡単すぎィ！

<br>

可視化に使うも良し、コントローラアプリにするも良し。
点群出すコードを書いたり、スマホから使ったり。
ChatGPT にコード出させたり、たくさんの入門書のコードを参考にしたり。

自分は rviz より Unity の方がとっつきやすく、便利に使っています♪



# 環境
ROS2 Humble

① Win 11 (Unity 2022.3.20f1)
② Ubuntu 22.04 (ROS2 Humble)

今回は２つの端末の構成で試しました。
(Unity 2020～、Win10/11、Ubuntu 20.04/22.04 対応とのこと)


# 手順

一応手順のスクショ残しておきます。

①　ros2-for-unity の「ビルド済」 zip を、 Release 一覧からダウンロード。
　（Android で使いたい方は[こちら](https://qiita.com/Kotakku/items/cdc3eca89dd8aec4ee86 "こちら")を参考に。）

今回は「 Ros2ForUnity_humble_standalone_windows11.zip 」を使いました。

https://github.com/RobotecAI/ros2-for-unity/releases

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/0fe166d3-f679-b6ea-858c-f46a59eda4a0.png)

<br>

②　Unity の Asset ディレクトリ内に先ほどダウンロードした zip の中身を解凍してコピーします。
（show in Explorer でエクスプローラでディレクトリを開けます）
（README には unitypackage を作ると書いてありますが、これで動きました。）

<br>

③ Unity エディタ上で、Create Empty で空のオブジェクトを作り、そこに「Scripts」内の「ROS2UnityComponent.cs」「ROS2TalkerExample.cs」をアタッチすれば、トピックのパブリッシュが行われるアプリがサクッと完成です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/45cc5528-63e1-32e4-002e-1a20301e5ebc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/a23a1d3b-ec9c-cbfb-818a-7bac3753bce8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/40d5faf0-6737-df58-f1aa-ee9112005c23.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/8f3db250-e77a-a9ae-c81e-2957b9ef4fd2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/7e8ee51a-bc25-c909-4983-ccc73110a020.png)

# ROS2TalkerExample.cs の中身

とても短いコードです。

https://github.com/RobotecAI/ros2-for-unity/blob/develop/src/Ros2ForUnity/Scripts/ROS2TalkerExample.cs

```csharp:ROS2TalkerExample.cs
// Copyright 2019-2021 Robotec.ai.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using UnityEngine;

namespace ROS2
{

/// <summary>
/// An example class provided for testing of basic ROS2 communication
/// </summary>
public class ROS2TalkerExample : MonoBehaviour
{
    // Start is called before the first frame update
    private ROS2UnityComponent ros2Unity;
    private ROS2Node ros2Node;
    private IPublisher<std_msgs.msg.String> chatter_pub;
    private int i;

    void Start()
    {
        ros2Unity = GetComponent<ROS2UnityComponent>();
    }

    void Update()
    {
        if (ros2Unity.Ok())
        {
            if (ros2Node == null)
            {
                ros2Node = ros2Unity.CreateNode("ROS2UnityTalkerNode");
                chatter_pub = ros2Node.CreatePublisher<std_msgs.msg.String>("chatter");
            }

            i++;
            std_msgs.msg.String msg = new std_msgs.msg.String();
            msg.Data = "Unity ROS2 sending: hello " + i;
            chatter_pub.Publish(msg);
        }
    }
}

}  // namespace ROS2
```

# 使用例


Unity の画面上の Play ボタン（三角）を押して実行すれば、

ros2 topic list
ros2 topic echo /chatter

でトピックを受信する様子が見れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/ea0792ac-ebd0-83e7-3a0e-1b9127986ac9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/fb79ae50-c238-66a6-6ba6-e53c485123bb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/15ee9ba5-f4a1-b493-d862-34263f9c3cad.png)

なお、リスナーの方のコードは「ROS2ListenerExample.cs」です。

https://github.com/RobotecAI/ros2-for-unity/blob/develop/src/Ros2ForUnity/Scripts/ROS2ListenerExample.cs

```csharp:ROS2ListenerExample.cs
// Copyright 2019-2021 Robotec.ai.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using UnityEngine;

namespace ROS2
{

/// <summary>
/// An example class provided for testing of basic ROS2 communication
/// </summary>
public class ROS2ListenerExample : MonoBehaviour
{
    private ROS2UnityComponent ros2Unity;
    private ROS2Node ros2Node;
    private ISubscription<std_msgs.msg.String> chatter_sub;

    void Start()
    {
        ros2Unity = GetComponent<ROS2UnityComponent>();
    }

    void Update()
    {
        if (ros2Node == null && ros2Unity.Ok())
        {
            ros2Node = ros2Unity.CreateNode("ROS2UnityListenerNode");
            chatter_sub = ros2Node.CreateSubscription<std_msgs.msg.String>(
              "chatter", msg => Debug.Log("Unity listener heard: [" + msg.Data + "]"));
        }
    }
}

}  // namespace ROS2
```



# 引っかかったところ

・Windows ファイアウォールで Unity 通信が遮断されていると、他PCからそのトピックだけ見えなくなったりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/71385622-d680-df74-2cd5-55f5775bfb25.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/7252b1b7-2597-9813-2b83-d03990585fd4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/0e225a84-04fc-827a-27cd-76c6203617bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478524/b4243b7e-f121-e31c-7240-8d3e1fce3730.png)


<br>
<br>


・ROS_DOMAIN_ID を各端末で揃えないと、ROS2 通信が端末同士で共有されません。
（特に設定してなければ大丈夫と思いますが）

Unity コード上からなら
```csharp
using System;
```
```csharp
Environment.SetEnvironmentVariable("ROS_DOMAIN_ID", "0");
```

Windows PowerShell だと環境変数の設定方法は、
```dosbatch
$Env:ROS_DOMAIN_ID = 0
echo $Env:ROS_DOMAIN_ID
```

Ubuntu は、
```dosbatch
export ROS_DOMAIN_ID=0
echo $ROS_DOMAIN_ID
```


# 参考

これは ros2-for-unity ではなく、Unity 公式の Unity-Robotics-Hub 利用例ですが、
やはり Unity が使えると 豊富な 3D 関連の関数やアセットが使えるので便利ですね…！

https://x.com/devemin/status/1558645894920056832

URDF Importer は別途個別に使えます。

https://x.com/devemin/status/1867612856856064395

xacro ファイルは xacro コマンドで一度 URDF にするそうです。

参考：

https://qiita.com/Ninagawa123/items/b24ceee29755e09b4d73


# 謝辞

ROS2 コミュニティ界隈の方々、いつもたくさん記事を参考にさせて頂いてます。
この場でみなさんに感謝お伝え申し上げます！

devemin