ROS-TCP-ConnectorでPubSub通信

ROSとUnity間で通信したいときに、
Unity公式のROS-TCP-Connectorを利用したので自分用のメモ．

チュートリアルにいい感じのイメージ図があった．
ROSとUnity間をつなぐ橋渡し役のプログラムがServer Endpointらしい．
これによって低遅延でリアルタイムな通信が出来るようになったらしい．
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1876613/89f79332-7400-ca59-960b-a5bd629e86f6.png" />
</div>

#環境

Ubuntu 18.04.5
Unity 2020.3.17f1
ROS melodic

#導入
ROS側とUnity側でそれぞれ導入するものがあるようなので、それぞれ導入する


##ROS側
ROS-TCP-EndpointパッケージをCloneしてcatkin_makeする

```
cd ~/catkin_ws/src
git clone https://github.com/Unity-Technologies/ROS-TCP-Endpoint
cd ..
catkin_make
```

##Unity側
ウィンドウ->パッケージマネージャーを開き、
「gitURLからパッケージを加える」を選択して以下のURLを入力する

```
https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.ros-tcp-connector
```

#設定
こちらもそれぞれ設定するものがある

##ROS側
別の端末にroscoreを起動したあと、
ROS_IPに自身のIPアドレスを設定する

```
rosparam set ROS_IP <自分のIPアドレス>
```

Unity間の通信を行うためのTCPポートも設定する
（デフォルトでは10000）

```
rosparam set ROS_TCP_PORT 10000
```

##Unity側
Unity上部のメニューバー、Robitics->ROS Settingsで、
ROS IP AddressとROS PortをROS側と同じものにする

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1876613/e4f2cb89-8c21-2081-6f80-5b791ecdcde1.png" />
</div>

#Server Endpointの実行
rosrunで起動

```
rosrun ros_tcp_endpoint default_server_endpoint.py
```

もし、自動起動をお望みなら、
roslaunch用のlaunchファイルが用意されているので、
ROSIPの設定も含めて実行できる

#PubSub通信

ROSはある程度書けると思うので、Unity側のスクリプトを紹介する


##フォルダ構造
AssetsフォルダにScriptsフォルダを作成し、その中にスクリプトを入れていく

/Assets
　├ /Resources
　├ /Scenes
　└ /Scripts <-new

##ROSからUnityへPubSub

/Scriptsに「Sub_test」という、C#スクリプトを作成する
以下の内容をコピペする

```Sub_test.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using StringMsg = RosMessageTypes.Std.StringMsg;

public class Sub_test : MonoBehaviour{

    void Start(){
        ROSConnection.instance.Subscribe<StringMsg>("test1", Callback);
    }

    void Callback(StringMsg msg){
        Debug.Log(msg.data);
    }

}
```

ROS-TCP-Connectorでは、rosのmsg形式を名前空間で管理してくれるため、わかりやすい．

上記の例では、std_msgs/String型を受け取るSubscriberを作成している．

Unity上に適当なオブジェクトを作成してSub_test.csを適用して実行し、
rostopic pub機能を使えばデバックコンソールに表示される

```
rostopic pub /test1 std_msgs/String test!!
```

##UnityからROSへPubSub

/Scriptsに「Pub_test」という、C#スクリプトを作成する
以下の内容をコピペする

```Pub_test.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using Int32Msg = RosMessageTypes.Std.Int32Msg;

public class Pub_test : MonoBehaviour{

    ROSConnection ros;
    // Start is called before the first frame update
    void Start(){
        ros = ROSConnection.instance;
        ros.RegisterPublisher<Int32Msg>("test2");
    }

    // Update is called once per frame
    void Update(){
        Int32Msg msg_data = new Int32Msg(12345);
        ros.Send("test2", msg_data);
    }

}

```

上記の例では、std_msgs/Int32型で配信するPublisherを作成している．

Unity上に適当なオブジェクトを作成してPub_test.csを適用して実行し、
rostopic echo機能を使えば、受け取ったデータを確認できる

```
rostopic echo /test2
```


#参考

- [Unity-Robotics-Hub](https://github.com/Unity-Technologies/Unity-Robotics-Hub)
- [公式チュートリアル](https://github.com/Unity-Technologies/Unity-Robotics-Hub/blob/main/tutorials/ros_unity_integration/README.md)