爆速でJETSON-TX2の初期セットアップをする

#0. 概要
これまでエッジでAIを動作させる代表格といえばFPGAが挙げられていたが、最近では低消費電力のGPUを用いることが増えているそうである。FPGAはコードをVERILOGに変換するコストが非常に高く、母艦のマシンで動かしていたコードをそのままエッジ側に流用させたいという需要が高まってきているからである。この需要に呼応して、NVIDIAからエッジ側で動作する低消費電力向けのエッジGPUがいくつも出始めている。

今回は、その中でも大容量といわれているJETSON TX2をセットアップしていきたい。
![41r3IKoLzoL._AC_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/179d0faf-fa73-ca6a-b92b-2dfb5300ef9b.jpeg)

#1. Preparing
- JETSON TX2
 - 本体。32GBのeMMCが本体に内蔵されているため、こちらにUbuntuをインストールする
- USBケーブル
 - JETSON TX2と母艦のマシンをつなぐケーブル 
- HDMIケーブル
 - JETSON TX2とディスプレイをつなぐケーブル 
- キーボード
 - JETSON TX2用キーボード
- 母艦マシン(Ubuntu)
 - JETSONにUbuntuをインストールするための母艦マシン

#2. Installation
では、さっそく母艦マシンからJETSON TX2の環境構築を行っていく。

##2.1. JETSON TX2のリカバリーモード接続
母艦マシンからJETSON TX2へインストールを行うには、
JETSON TX2をリカバリーモードで起動して母艦マシンに接続する必要がある。

これからJETSON TX2のボタンをいくつか押すため以下を参考にして頂きたい。
![HTB1j6XYvGQoBKNjSZJnq6yw9VXaC.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/104c18ce-fe73-e88a-9ecd-f640ef471614.jpeg)

- まずJETSON TX2に電源をつなぎ、USBを母艦マシンと接続する。

- 次に、`POWER BTN`と書かれたボタンを押し、LEDの点灯を確認する。

- 30秒ほど待ってから、`REC`を押しながら`RST`ボタンを2秒程度押す。

- その後、`RST`、`REC`の順で離していく。

- これで、リカバリーモードに入る。

なお、母艦マシンがJETSON TX2を認識出来ているかの確認は、以下を母艦マシンで実行することで確認出来る。

``` bash
$ lsusb
  # Bus 003 Device 002: ID 0955:7c18 NVidia Corp.
```

##2.2. 母艦マシンの環境構築
母艦マシンの環境を構築する。なお、これからの操作は母艦上で行うものとする。
以下からsdk managerのDEBをダウンロードする(JetPack 4.3)。
https://developer.nvidia.com/embedded/jetpack
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/9c675227-dd0d-43db-6ade-63db4e08953c.png)

途中でログイン等が求められるので適宜、入力していく。
では、母艦のマシンに`sdkmanager_1.0.0-5517_amd64.deb`がダウンロードできたとする。

次に、以下のコマンドでインストールする。

```bash
$ sudo apt install ./sdkmanager_1.0.0-5517_amd64.deb
```

次に実行する。

```bash
$ sdkmanager
```

以下のような画面が開くのでログインする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/f82c7014-bdf6-c058-98a4-caae943fa2d0.png)


##2.3. インストールのセッティング
母艦マシンで開いた`sdkmanager`にログインして、セッティングを進めて行く。

### STEP1: Target HardwareをJetson TX2にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/bad5a480-e600-93ce-5a47-2d639617c494.png)

他の項目が画像と同じになっているか確認してContinueを押す。

### STEP2: インストール項目を確認して規約に同意する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/f2b55d90-e83b-0b08-ce6b-d991c999be32.png)
他の項目が画像と同じになっているか確認してContinueを押す。
すると`sudo`が実行されるので母艦マシンのログインパスワードを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/419cb266-b8d4-a76f-cfdc-f12de350025c.png)

### STEP3-1: ダウンロードが終わるのを待つ
後は環境にもよるが30分程待っていればダウンロードが終わり、インストールが始まる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/abd437df-024e-6161-8c13-a957f189c28b.png)

### STEP3-2: インストールを行う
必要なファイルのダウンロードが終わると、OSのインストールが始まる。
OSのインストールが終わると、CUDA等のパッケージをインストールするかと聞いてくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/5acc8089-df08-1ac9-940e-ed06bd4f864e.png)

一先ず、この画面は放置しておく。

OSのインストールが終わったタイミングでJETSON TX2のLinuxが起動している。
USB経由のシリアルコンソールから操作できるので、母艦マシンからログインする。

まず、認識しているか確認。ボーレートは`115200`の模様

```bash
$ dmesg | grep bau
 # [    2.634954] 00:04: ttyACM0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
```

次にCOMポートを見つけ、接続できるようにする。

``` bash
$ ls -lrt /dev/serial/by-id/
 # usb-NVIDIA_Linux_for_Tegra_0421518037878-if02 -> ../../ttyACM0
$ sudo chmod 666 /dev/ttyACM0
```

後は接続するだけであるが、今回は`gtkterm`を使う。

``` bash
$ sudo apt install gtkterm
$ gtkterm
```

後は開いた画面から`configuration->port`を選択し、シリアルポートに接続する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/df49c1e6-dcc6-112f-06fb-6ec5cbb71343.png)

Linuxの初期設定画面が出てくるのでUser名やPasswordを決めて行く。
ちゃんとネットワークにも接続させておくこと。でないと、後の行程でエラーが出る。
最後までいくとこのような画面になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/08bc0bb5-6f5e-3bb3-21e1-e5bec895d566.png)

ログインして`ifconfig`でネットワーク環境を見る。

``` bash
l4tbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.55.1  netmask 255.255.255.0  broadcast 192.168.55.255
        inet6 fe80::3c3b:b1ff:fe4f:112d  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::1  prefixlen 128  scopeid 0x20<link>
        ether 3e:3b:b1:4f:11:2d  txqueuelen 1000  (Ethernet)
        RX packets 632  bytes 48160 (48.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 80  bytes 9576 (9.5 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

このように表示されていればOK。
母艦マシンから`ssh user@192.168.55.1`と打てばSSHログインできることを確認する。

ここまでで出揃った情報を以下に入力して`install`を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/5acc8089-df08-1ac9-940e-ed06bd4f864e.png)


完了すれば`Finish`と文字が変わるので押して終了。


なお、失敗などで工場出荷状態に戻すためには以下の手順を踏む。
- JETSON TX2 FLASH JETPACK 電源オフ
- POWER BTNを5秒間保持する
- USBを接続
- シリアル接続（オプション）
 - ボーレート: 115200

##2.4. Ubuntuの設定
全てが終了したら、JETSON TX2はリブートしてUbuntuが立ち上がり、初期設定が求められる。
この時に、HDMIを接続して、後は指示通りに設定を終えれば環境構築完了である。

# 3. Installation of Tensorflow
GPUが使えるようになっても`Tensorflow`を入れなければ意味がない。
これはドキュメントで整理されているのでこちらを読めばOK。
https://docs.nvidia.com/deeplearning/frameworks/install-tf-jetson-platform/index.html

取り合えず`pip`の調子が悪い場合は全部入れなおす。

``` bash
$ sudo apt-get remove python3
$ sudo apt-get install software-properties-common
# die repository
$ sudo add-apt-repository --remove ppa:jonathonf/python-3.6
$ sudo add-apt-repository ppa:deadsnakes/ppa
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblapack-dev libblas-dev python-dev libjpeg8-dev

$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc
$ pyenv install 3.6.0
$ pyenv global 3.6.0
$ sudo apt-get install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev
$ pip install -U pip testresources setuptools
$ pip install -U numpy==1.16.1 future==0.17.1 mock==3.0.5 h5py==2.9.0 keras_preprocessing==1.0.5 keras_applications==1.0.8 gast==0.2.2 enum34 futures protobuf
$ pip install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v43 tensorflow-gpu
$ python
 import tensorflow
$ pip uninstall enum34
$ sudo apt-get install libatlas-base-dev gfortran
$ pip install keras
$ python
 import keras
```

Enjoy !

# 3.1. scipyのインストールでエラーが出る

``` bash
$ wget https://github.com/scipy/scipy/releases/download/v1.3.3/scipy-1.3.3.tar.gz
$ tar -xzvf scipy-1.3.3.tar.gz scipy-1.3.3
$ cd scipy-1.3.3/
$ python setup.py install --user
```

# 99. Other
## wlan0の接続
初期設定でWPA2のネットワークをつなげようとすると大体上手く行かない。
そこで、OSが立ち上がった後に接続させる方法を紹介する。

まずパスフレーズを生成する。

``` bash 
$ wpa_passphrase 'MySSID' 'MyPassword'

network={
    ssid="MySSID"
    #psk="MyPassword"
    psk=a66e97b9a1008a97285c78c2b95082bed3541d3dd01165b0128f7f3c18563797
}
```

次に設定ファイルの生成

```bash
$ sudo vi /etc/network/interfaces.d/wlan0
$ sudo chmod 600 /etc/network/interfaces.d/wlan0
```

こんな感じで設定を書く。

```bash:wlan0
auto wlan0
iface wlan0 inet dhcp
    wpa-ssid "MySSID"
    wpa-psk a66e97b9a1008a97285c78c2b95082bed3541d3dd01165b0128f7f3c18563797
```

次に、設定ファイルを読み込むように記述

``` bash
$ sudo vi /etc/network/interfaces
```

こんな感じ

``` bash:interfaces
source-directory /etc/network/interfaces.d
source interfaces.d/wlan0
```

最後に再起動であるが、大ハマりポイント
wpa_supplicantが死に体で動いているので終了してからじゃないとエラーがでる。

``` bash
$ ps aux | grep wpa
 # root      4606  0.0  0.0   9684  6856 ?        Ss   10:58   0:00 /sbin/wpa_supplicant -u -s -O /run/wpa_supplicant
$ kill ID
$ /etc/init.d/networking restart
```