Windows上でUnityとROS2を連携させる(3) ~Oculus Quest2でTurtlebot3を操作する~

#はじめに

本記事では、Oculus Quest2とROS2を連携させることを目的として、Quest2のコントローラであるOculus TouchでTurtlebot3を操作する方法を解説します。

※この先はTurtlebot3, Oculus Quest2のセットアップが完了していることを前提に進めます。




#実行環境

本記事で用いる実行環境は以下の通りです。

###Windows PC
| 項目 | 値 |
|:-:|:-:|
| CPU | Core i7-9750H  |
|  OS |  Windows10 |
| ROS2    |  Foxy Fitzroy |
|Unity|2020.3.16f1|

###Raspberry Pi 4

| 項目 | 値 |
|:-:|:-:|
| CPU |1.5GHz クアッドコア Cortex-A72(ARMv8、64bit L1=32KB、L2=1M) |
|メモリ |UD-RP4B8：8GB|
|  OS |  Ubuntu Desktop 20.04 |
| ROS2    |  Foxy Fitzroy |
|Turtlebot3|Waffle Pi|


#Oculus Quest2でTurtlebot3を操作する

##システム概略

Oculus Quest2のコントローラであるOculus TouchのJoy Stickの入力情報を元にTwist MessageをPublishし、Turtlebot3はそのMessageをSubscribeし移動します。


* Nodes
 * **turtlebot3_node(ROS2側)**：Twist MessageをSubscribeし、移動する
 * **quest2_control_node(Unity側)**：Oculus Touch(Joy Stick)の操作によってTwist MessageをPublishする

* Topic
 * /cmd_vel[geometry_msgs/msg/Twist]
 * /odom[nav_msgs/msg/Odometry]
 * unity/odom[nav_msgs/msg/Odometry]



##quest2_control_node(Unity側)の作成

```quest2_control_node.cs
using UnityEngine;
using System.Collections;
using System.Collections;
using System.Collections.Generic;using System;
using Unity.Robotics.ROSTCPConnector;
using RosMessageTypes.Geometry;
  
public class controller : MonoBehaviour
{
  
    //Oculus Touch Information
    public OVRInput.Controller controlL;
    public OVRInput.Controller controlR;
  
  
    ROSConnection ros;
  
    //Twist
    Vector3Msg linear = new Vector3Msg(0f, 0f, 0f);
    Vector3Msg angular = new Vector3Msg(0f, 0f, 0f);
  
    // Start is called before the first frame update
    void Start()
    {
        // start the ROS connection
        ros = ROSConnection.instance;
        ros.RegisterPublisher<TwistMsg>("/cmd_vel");
         
        cube = GetComponent<Rigidbody>();
    }
  
    // Update is called once per frame
    void Update()
    {
        //初期化
        if (Input.GetKey(KeyCode.Space))
        {
            OVRManager.display.RecenterPose();
            linear.x = 0;
            angular.z = 0;
        }
  
  
        if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickUp))
        {
            Debug.Log("左アナログスティックを上に倒した");
            linear.x =linear.x+ 0.1;
        }
        if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickDown))
        {
            Debug.Log("左アナログスティックを下に倒した");
            linear.x =linear.x+  (-0.1);
        }
        if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickLeft))
        {
            Debug.Log("左アナログスティックを左に倒した");
            angular.z = angular.z +0.1;
        }
        if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickRight))
        {
            Debug.Log("左アナログスティックを右に倒した");
            angular.z = angular.z + (-0.1);
        }
  
        print(linear);
        //Send untiy_odom to turtlebot_control
        TwistMsg Twist = new TwistMsg(
               linear,
               angular
            );
  
        // Finally send the message to server_endpoint.py running in ROS
        ros.Send("cmd_vel", Twist);
    }
}

```

##実際に通信する

###Oculus Linkの起動

PCとリアルタイム通信が可能なOculus Linkを起動する必要があります。
（※Oculus LinkはWindowsのみ対応）

###ros_tcp_endpointの起動

```
$ call C:\opt\ros\foxy\x64\local_setup.bat
$ cd \dev_ws
$ call install/setup.bat
$ ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=<your IP address>
```

###Subscriber(ROS側)の起動

[turtlebot3_bringup](https://emanual.robotis.com/docs/en/platform/turtlebot3/bringup/#bringup)を実行し、Nodeを立ち上げます。

Oculus Touchを操作してTurtlebot3が動くのを確認してください。

![quest2_turtlebot3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2035642/e14565c1-3174-7f0e-cb73-ec8386afafef.gif)


#おわりに

今回はOculus Quest2とROS2の連携を目的として、Oculus Touchをコントローラとして使用し、Turtlebot3を操作する方法を解説しました。

Oculus Quest2と連携ができることによって様々な応用方法が考えられます。

#####例１）Turtlebot3のカメラで取得した映像をQuest2にリアルタイムで反映し遠隔操作する

これを実現する方法は別の記事で解説しているので参考にしてください

[UnityでROS2の画像をサブスクライブする
](https://qiita.com/sfc_nakanishi_lab/items/78294038542a386739fd)


#####例２）Turtlebot3の位置・姿勢情報を使用してUnityのオブジェクトを動かしVRコンテンツを作成する

これを実現する方法も別の記事で解説しているので参考にしてください

[オドメトリを使ってROS2とUnityの間でロボットの位置を同期させる](https://qiita.com/sfc_nakanishi_lab/items/946dd74481e3c8c2fc92)