PFRL + Raspberry pi 4 + Raspberry pi camera v2 + ROS(melodic)

出田守です。

個人的に製作している[ロボットアーム君](https://detamamoru.hateblo.jp/entry/2020/11/23/164921)の動作を強化学習を使って学習させたいと思いました。ブログの記事と同じですが、ここでも共有しておこうと思い書いておきます。
今回はそのための環境構築を行います。

# 使用した環境
-  Windows 10 (PFRL, ROS) + GeForce GTX 960
- CUDA Toolkit 10.1 update2
- Raspberry pi 4, Raspberry pi camera v2 (ROS)
- Python 3.8.5
- PyTorch 1.7.0+cu101

# PFRL
友人からPreferred Networksさんが[PFRL](https://github.com/pfnet/pfrl)という強化学習のライブラリを公開したよと教えてもらいました。
Chainer RLの後継版？で、Chainer RLのコードとも互換性があるようです。
早速インストールします。前提として、Python 3.7.7以上、PyTorchがインストールされていること。

```shell
pip install pfrl
```

私の環境ではPyTorchが入っていないと、エラーが出ました。なので
https://www.kkaneko.jp/tools/win/pytorch.html
を参考に事前にPyTorchをインストールしました。ちなみにGPUを載せていますので、GPU用をインストールしました。

無事インストールできたら、[PFRL Quickstart Guide](https://github.com/pfnet/pfrl/blob/master/examples/quickstart/quickstart.ipynb)を実行し、動作確認を行います。

# Raspberry pi 4にUbuntu 18.04をインストールと設定

## 1. ARM用Ubuntu 18.04 serverをダウンロード
まず、[ARM用のUbuntu 18.04 server](https://wiki.ubuntu.com/ARM/RaspberryPi)をダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254464/876f5125-a707-fd95-9dfa-a8e47f2f8472.png)

## 2. Raspberry Pi Imagerをダウンロード・インストール
[Raspberry Pi Imager](https://www.raspberrypi.org/software/)をダウンロードし、インストールします。

## 3. Ubuntu 18.04 serverを書込み・インストール
Rasberry Pi Imagerを起動し、

1. 「Operating System」→「Use custom」→Ubuntu 18.04 serverイメージを選択
2. 「SD Card」→書込み対象のSDカードを選択
3. 「WRITE」

これでSDカードへUbuntu 18.04 serverが書き込まれます。あとは、SDカードをRaspberry pi 4へ差し込み、準備完了です。

## 4. 初回起動
Raspberry pi 4にモニタやキーボード、マウスを接続します。次に電源を接続し、モニタに起動画面が表示されるのを確認します。初回はUbuntuユーザのパスワードを求められますので、良いパスワードを設定します。しばらくするとログイン画面に進みます。
<b><注意>電源接続時はまだネットワークは接続しません！</b>

## 5. 初期設定
Ubuntuにログインしたら、
<ol>
<li> 有線ネットワークを接続(無線ネットワーク接続出来るのならそれでも良い)
</li>
<li> パッケージを更新

```
sudo apt update
sudo apt upgrade
```

</li>
<li> 初期設定
[Ubuntu18.04 インストール後の初期設定メモ](https://qiita.com/hatayan1126/items/c67f87a86f1538bb86af)を参考に、必要な設定を行いました。
</li>
<li> zram-configのインストール
Rasbian用のメモリをUbuntu用にスワップするためにインストールしておきます。

```
sudo apt install zram-config
```

</li>
<li> Ubuntuのデスクトップ環境をインストール

```
sudo apt install ubuntu-desktop
```

</li>
<li> デスクトップ環境を起動

```
startx
```

</li>
</ol>

## 6. RAMの割当て
Raspberry pi 4のRAMをUbuntuに適切に割り当てるために、zram-configを使用します。

```
sudo vim /usr/bin/init-zram-swapping
```

そして以下の赤線部分のように「* 3」を加えます。こうすることで約5.5GBのメモリスワップを確保します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254464/e4ced1f5-256e-ade2-2f7f-73b396387f2e.png)

## 7. VNC環境構築
キーボードやマウスを毎回接続するのは面倒なのでVNC環境を構築します。

```
sudo apt update
```

xfaceデスクトップ環境を使います。gnomeだとsystemdでgnome-sessionのidがうまく取得できず、画面が真っ暗になって正常動作しなかったためです。

```
sudo apt install xfce4 xfce4-goodies
```

tigervncを使うことにしました。特に理由はありません。

```
sudo apt install tigervnc-standalone-server tigervnc-common
```

初期起動時はVNCパスワードの設定を行います。このパスワードはVNCクライアントから接続する際に必要なので覚えておいてください。

```
vncserver
```

すでに起動しているvncserverをkillします。

```
vncserver -kill :*
```

xstartupを既存のものから変更します。

```
mv ~/.vnc/xstartup ~/.vnc/xstartup.bkp
vim ~/.vnc/xstartup
```

```
#!/bin/bash
xrdb $HOME/.Xresources
startxfce4 &
```

実行権限を与えます。

```
sudo chmod +x ~/.vnc/xstartup
```

systemdのサービスファイルを作成します。

```
sudo vim /etc/systemd/system/tigervnc@1.service
```

```
[Unit]
Description=tigervnc (Remote access)
After=syslog.target network.target

[Service]
Type=forking
User=ubuntu
Group=ubuntu
PIDFile=/home/ubuntu/.vnc/%H:%i.pid
WorkingDirectory=/home/ubuntu
ExecStartPre=/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver -localhost :%i
ExecStop=/usr/bin/vncserver -kill :%i

[Install]
WantedBy=multi-user.target
```

systemdに作成したサービスを登録します。

```
sudo systemctl daemon-reload
sudo systemctl enable tigerservice@1.service
sudo systemctl start tigerservice@1.service
```

下記のURLを参考にインストールしました。
https://www.journaldev.com/34074/install-tigervnc-on-ubuntu
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-vnc-on-ubuntu-20-04-ja

## 8. OpenCV 4.5.0をインストール
使うと思うのでOpenCV 4.5.0(2020/12/17時点の最新バージョン)をインストールしておきます。
<ol>
<li>必要なライブラリをインストール

```
sudo apt update
sudo apt upgrade
sudo apt install build-essential cmake gcc g++ git unzip pkg-config
sudo apt install libjpeg-dev libpng-dev libtiff-dev
sudo apt install libavcodec-dev libavformat-dev libswscale-dev
sudo apt install libgtk2.0-dev libcanberra-gtk*
sudo apt install libxvidcore-dev libx264-dev
sudo apt install python3-dev python3-numpy python3-pip
sudo apt install python-dev python-numpy
sudo apt install libtbb2 libtbb-dev libdc1394-22-dev
sudo apt install libv4l-dev v4l-utils
sudo apt install libopenblas-dev libatlas-base-dev libblas-dev
sudo apt install liblapack-dev gfortran libhdf5-dev
sudo apt install libprotobuf-dev libgoogle-glog-dev libgflags-dev
sudo apt install protobuf-compiler
```

<li> OpenCV 4.5.0をダウンロード

```
cd ~
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.0.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.0.zip
unzip opencv.zip
unzip opencv_contrib.zip
mv opencv-4.5.0 opencv
mv opencv_contrib-4.5.0 opencv_contrib
cd opencv
mkdir build
cd build
```

```
make -j4
sudo make install
sudo ldconfig
sudo apt-get update
```

</li>
</ol>

# Raspberry Pi Camera V2の接続とテスト
Raspberry Pi 4とRaspberry Pi Camera V2を接続しテストします。
<ol>
<li>接続
下記写真のように、両側の黒いピンを押し上げて、隙間に差し込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254464/c9345388-8c8f-161d-2f70-bb1cb0a8b43e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254464/c161461f-9330-48fd-3d29-9e8bf305896f.png)

<li>テスト
OpenCVで確認してみます。
テストコードは以下。VideoCaptureの引数は私の環境では0でした。

```python
#test_camera.py
import cv2

capture = cv2.VideoCapture(0)

while(True):
    ret, frame = capture.read()
    windowsize = (800, 600)
    frame = cv2.resize(frame, windowsize)

    cv2.imshow('test cameara',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

capture.release()
cv2.destroyAllWindows()
```

```
python3 test_camera.py
```
ちゃんとカメラ動画が映れば準備完了です。
</li>
</ol>

# ROS(melodic)のインストール
## Ubuntu 18.04にインストール
Ubuntu 18.04にROS(melodic)をhttp://wiki.ros.org/melodic/Installation/Ubuntu に従ってインストールします。
Keyが変わったりするので、必ずwikiを見てインストールします。
今回はros-melodic-desktop-fullをインストールします。
インストールが完了したら、ROSのワークスペースを作成・初期化しておきます。

```
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
cd ../
catkin_make
echo "source ${HOME}/devel/setup.bash" >> ~/.bashrc
```

roscoreコマンドを実行してマスターが起動するか確認します。

```
roscore
```

```
...
started core service [/rosout]
```

## Windows 10 64bitにインストール
併せて、Windows 10マシンにもROS(melodic)をhttp://wiki.ros.org/Installation/Windows に従ってインストールします。
ただし、最初のChocolateyのインストールがうまくいかなかったので、https://chocolatey.org/install#installing-chocolatey に従ってインストールします。
PowerShellを管理者権限で起動して、以下を実行します。ただし、コマンドは上記したページをコピーすること！

```
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
```

こちらもroscoreコマンドを実行してマスターが起動するか確認します。

```
roscore
```

```
...
started core service [/rosout]
```

# ROSからカメラ画像データを送信
ROSパッケージのcv_cameraを使ってカメラ画像を送ってみます。
## cv_cameraパッケージのインストール

```
cd ~/catkin_ws/src
git clone https://github.com/OTL/cv_camera.git
cd ../
catkin_make
```

## 動作確認
まずはローカル内で動かしてみます。

```
roscore
```

```
rosparam set cv_camera/device_id 0
rosrun cv_camera cv_camera_node
```

rvizで確認します。

```
rviz
```
起動後「Displays」→「Image」を追加し、「Image Topic」に「/cv_camera/image_raw」を選択するとカメラ画像が表示されます。

別マシン上でカメラ画像を確認します。
Windows 10側をペアレントとし、Raspberry Pi 4側をチャイルドとします。(ちなみに最近マスター/スレーブという呼び方は差別的として改められているようです。なのでここではマスターをペアレント、スレーブをチャイルドと呼ぶことにします。)
まず、Windows 10側、Raspberry Pi 4側どちらにも環境変数「ROS_HOSTNAME」と「ROS_MASTER_URI」を設定します。
Windows 10側はROS_HOSTNAMEに「自身のIPアドレス」を、ROS_MASTER_URIに「http://自身のIPアドレス:11311」を設定します。
Windows 10側はROS_HOSTNAMEに「自身のIPアドレス」を、ROS_MASTER_URIに「http\://Windows 10側のIPアドレス:11311」を設定します。

次に、Windows 10側でroscoreを起動します。さらに、rvizも起動しておきましょう。
Raspberry Pi 4側では先ほどと同様にcv_cameraノードを起動します。
rviz上にImageを追加して、カメラ画像が表示されていれば成功です。

>
もし、この時何もトピック名が表示されない場合は、Windows 10側のファイアウォールを疑ってください。私の場合受信規則のpythonのパブリックを許可していなかったため、TCP接続できない状態でした。


以上で、環境構築は完了です。

# 参考
- https://github.com/pfnet/pfrl
- https://qengineering.eu/install-ubuntu-18.04-on-raspberry-pi-4.html
- https://wiki.ubuntu.com/ARM/RaspberryPi
- https://www.journaldev.com/34074/install-tigervnc-on-ubuntu
- https://qiita.com/hatayan1126/items/c67f87a86f1538bb86af
- https://qiita.com/opto-line/items/7ade854c26a50a485159
- http://wiki.ros.org/melodic/Installation/Ubuntu
- http://wiki.ros.org/cv_camera