Oculus GoにRaspiのカメラ画像を表示する&姿勢を取得する

Oculus GoにRaspberry Piに接続したUSBカメラの画像を表示する方法と、Oculus Goの姿勢をRaspberry Piに送信する方法について説明します。
と言っても、ほぼ他の方がやったことをそのまま行っただけです。

Oculus Go(Unity)とRaspberry Piの間の通信にはROSを使用します。

# デバイス・環境一覧
- Windows PC
  - Unityのアプリ開発用
  - Unity 2017.4.1
  - [ROS#](https://github.com/siemens/ros-sharp/releases)  version 1.2c
- Oculus Go
- Raspberry Pi4 Model B
  - Ubuntu Server 18.04
  - ROS melodic
- Raspberry Pi Camera Module V2.1

Raspberry Piの環境構築は「[Rasberry Pi 4に Ubuntu server 18.04をインストール](https://qiita.com/hiro-han/items/56c4fb6a1ad4c1713a7f)」を参照してください。
ROSの環境構築は[公式](http://wiki.ros.org/melodic/Installation/Ubuntu)に説明があります。また、多くの人がまとめています。


# 実装
## Unity側
### ビルド環境構築
[こちら](https://bluebirdofoz.hatenablog.com/entry/2018/12/28/075408)のサイトを参考にして環境構築しました。

### 実装
ROSからカメラ画像を表示する機能と、ROSにOculus Goの姿勢を送信する機能を持ったアプリを実装します。
基本的には[こちら](https://qiita.com/Spritaro/items/5eb99b2fcdc26a3816ce)のサイトの解説に沿いましたが、自分の環境に合わせて以下のパラメータ等だけ変更しました。

- ROS#のバージョン [[対応箇所 : 2)-2](https://qiita.com/Spritaro/items/5eb99b2fcdc26a3816ce#2-ros%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6ros%E3%81%A8%E9%80%9A%E4%BF%A1%E3%81%99%E3%82%8B)]  
  - v1.2cを使用。[こちら](https://github.com/siemens/ros-sharp/releases/tag/v1.2c)からダウンロードできます。
- ImageReceiverのRotateとScaleを変更 [対応箇所  : [3)-1](https://qiita.com/Spritaro/items/5eb99b2fcdc26a3816ce#3-%E3%82%AB%E3%83%A1%E3%83%A9%E7%94%BB%E5%83%8F%E3%82%92%E5%8F%97%E4%BF%A1%E3%81%99%E3%82%8B)]
  - rotate (-90, 180, 0) : カメラを上下逆さまで取り付けたため、反転しました
  - scale (-1.5, -1. 0.84375) : 参考記事よりも大きく表示しました
- ImageReceiverのInspectorで、Mesh Colidarの`Cooking Options`で`Inflate Convex Mesh`を追加
- SubscriberのTopic名を変更 [対応箇所  : [3)-2](https://qiita.com/Spritaro/items/5eb99b2fcdc26a3816ce#3-%E3%82%AB%E3%83%A1%E3%83%A9%E7%94%BB%E5%83%8F%E3%82%92%E5%8F%97%E4%BF%A1%E3%81%99%E3%82%8B)]  
  `/cv_camera/image_raw/compressed`->`/image_raw/compressed`
- UnityTimePublisherのTopic名を変更 [対応箇所  : [5)-2](https://qiita.com/Spritaro/items/5eb99b2fcdc26a3816ce#5-oculusgo%E3%81%AE%E5%A7%BF%E5%8B%A2%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B)]   
  `/camera`->`/oculus_pose` 

## ROS側
### パッケージのインストール
ROS側は公開されているパッケージをインストールします。

```
$ sudo apt install -y ros-melodic-rosbridge-server
$ sudo apt install -y ros-melodic-uvc_camera
$ sudo apt install -y ros-melodic-image-transport
$ sudo apt install -y ros-melodic-image-transport-plugins
```
- uvc_camera
  - [ここ](https://bluebirdofoz.hatenablog.com/entry/2018/12/28/075408)では`cv_camera`を使用していましたが、自分は`uvc_camera`を使用しました
- ros-melodic-image-transport, ros-melodic-image-transport-plugins
  - ROS#の`ImageReceiver`はimage_raw型には対応しておらず、image_raw/compressed型に対応しています。上記2つのパッケージをインストールすることで、uvc_cameraからimage_raw/compressed型が出力されるようになります


# 実行
最初にROS側から実行します。

## ROS側
以下のlaunchファイルを作成して実行しました。`value`には、実行するデバイスのIPアドレスを設定してください。

```
<launch>
  <include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" /> 
  <param name="rosbridge_websocket/address" value="192.168.xxx.xxx"/>
  <node name="uvc_camera" pkg="uvc_camera" type="uvc_camera_node">
  </node>
</launch>
```

## Unity側
上記の参考記事のとおり`Build & Run`をしただけです。


## 結果
Oculus Goで、以下のようにカメラ画像が表示できていれば正しく動作しています。

![com.HiroHan.ARCar-20201210-234421.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293692/2aef97d3-2e6b-bea5-b880-6c7dec51e87d.jpeg)


ROSの方は、以下のような出力が得られれば正しくOculus Goの姿勢を取得できています。

```
$ rostopic echo /oculus_pose
---
header: 
  seq: 82
  stamp: 
    secs: 35
    nsecs:        36
  frame_id: ''
pose: 
  position: 
    x: 0.09448901
    y: 0.05349608
    z: -0.09275523
  orientation: 
    x: 0.399406433
    y: -0.024657717
    z: 0.05147786
    w: -0.9149953
---
```



# 補足
今回Unity 2017.4.1を使いましたが、2018.2.17f1でも動くようで、その場合は、ROS#の v1.3以上を使う必要があるそうです。
ROS# v1.3はv1.2と使い方が異なります。v1.3を使い場合は[こちら](https://kuwamai.hatenablog.com/entry/2018/11/28/200011)や[こちら](https://mozyanari.hatenablog.com/entry/2018/11/11/224556)が参考になります。

# 参考
- [UnityでOculus Go向けアプリをビルドしてインストールする その１（開発者登録とJDKのインストール）](https://kuwamai.hatenablog.com/entry/2019/01/27/200000)
- [ROS# v1.2](https://github.com/siemens/ros-sharp/releases/tag/v1.2c)
- [OculusGoをROSと通信させる](https://qiita.com/Spritaro/items/5eb99b2fcdc26a3816ce)
- [ROS#:UnityとROSの接続](https://kuwamai.hatenablog.com/entry/2018/11/28/200011)
- [2018/11/11(Oculus GoとROSをROSSharpで通信させてLRFのデータ表示)](https://mozyanari.hatenablog.com/entry/2018/11/11/224556)

# リンク
ARラジコンを開発する記事の一覧

1. [ARラジコンを作る](https://qiita.com/hiro-han/private/b2e5ae68d16e9116b37e) (概要)
1. Oculus GoにRaspiのカメラ画像を表示する&姿勢を取得する (本記事)
1. [Oculus Goの姿勢を使ってサーボモーターをコントロールする](https://qiita.com/hiro-han/items/01561be3bfdc484a8407)
1. [Raspberry Pi, Arduinoでタミヤラジコンを制御する](https://qiita.com/hiro-han/items/86b2ef8aa589c9f916f8)