Jetson nanoにVSCode+Pythonの開発環境を整えリモートアクセスする

##はじめに
この記事では先日発売されたJetson nanoについて、環境構築手順を自分の作業メモ兼ねて解説します。
セットアップ系の記事は多くありますが、一つの視点として皆様の参考になれば幸いです。

この記事の内容は以下の通りです。

1. 本体のセットアップ(略式)
1. 環境構築
 - nanoエディタやpip
 - Tensorflow
 - PyTorch
 - OpenCV4
 - GPIO
 - その他
1. VSCodeをインストール
1. リモートアクセス(RDP/VNC)

##本体セットアップ
公式の解説([Getting Started With Jetson Nano Developer Kit](https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit))に従いセットアップを行います
とは言っても、この辺はRapberry Piとまったく同じ手順です。

###1. Jetson nano用のJetpack(SDカードイメージ)をダウンロードする
イメージのダウンロードはこちら(https://developer.nvidia.com/embedded/jetpack)
5.3GBくらいのzipファイルをダウンロードします。解凍すると12.6BGくらい。
ファイルサイズがzipの規格外なので解凍できないアーカイバがあります(Lhaplusなど)
私は7zipで解凍しました。

###2. SDカードをフォーマットする
SD Associationの**[SDメモリカードフォーマッター](https://www.sdcard.org/jp/downloads/formatter/)**でフォーマットします。
パーティション区切っていても無視して元の綺麗な状態になるので楽ですね。

###3. イメージファイルをSDカードに焼く
イメージが12.6GBであることから分かる通り、16GB以上のSDカードを準備します。
今回は32GBのSDカードを使用しました。
swap領域を作ったりしないといけないので、容量は大きめが良いです。
上限は不明ですが、[128GBや200GBの動作報告はフォーラムに上がっています](https://devtalk.nvidia.com/default/topic/1049191/jetson-nano/what-size-in-gb-of-sd-card-is-recommended-/post/5325967/#5325967)。

イメージの書き込みに公式では**[Etcher](https://www.balena.io/etcher/)**というソフトを使っています~~が、使い慣れているソフトがあればそれで良いです。
私はWin32DiskImagerを使いました。~~
2019.9.15追記：近頃のイメージファイルはWin32DiskImagerだと初回起動で失敗する様子。Etcherを使うのが良さそうです。

###4. 初回起動の設定
この辺は普通のLinuxと同じなので英語を読みつつセットアップを行います。

注意点としては、**使用言語をEnglishにする**という点です。
ネットでも経験談がよく聞かれますが、日本語はトラブルの元です。


##環境構築
毎回時間が掛かる作業です
最後までうまくいったらSDカードの中身をイメージ化して保存しておきましょう。

デフォルトでSSHが有効になっているので、ネットワーク設定を行えば、
TeraTermなどからIPアドレスを指定すればログインして作業ができます。

###よく使うものをインストール
Python環境を整える前に(個人的に)よく使うものを入れておきます
Rapbianにはあった以下の二つが入ってないので入れます。

- nanoエディタ
- pip


```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install nano
sudo apt-get install python3-pip
```

###Python環境の整備
####深層学習フレームワークのインストール
Tensorflowはバイナリが準備されています。
インストールは以下のコマンドを実行します。(参考:[公式フォーラム](https://devtalk.nvidia.com/default/topic/1048776/jetson-nano/official-tensorflow-for-jetson-nano-/)) 

```bash
#2019.8.23現在のバージョンに合わせて更新
sudo apt-get install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev
sudo apt-get install python3-pip  #上記でインストール済みなら省略する
sudo pip3 install -U pip
sudo pip3 install -U numpy grpcio absl-py py-cpuinfo psutil portpicker six mock requests gast h5py astor termcolor protobuf keras-applications keras-preprocessing wrapt google-pasta
sudo pip3 install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v42 tensorflow-gpu==1.14.0+nv19.7
```

ちなみにpyTorch(for Python3.6)は次のコマンドで入ります。(参考:[公式フォーラム](https://devtalk.nvidia.com/default/topic/1049071/pytorch-for-jetson-nano/))

```bash
#2019.8.23現在のバージョンに合わせて更新
wget https://nvidia.box.com/shared/static/06vlvedmqpqstu1dym49fo7aapgfyyu9.whl -O torch-1.2.0a0+8554416-cp36-cp36m-linux_aarch64.whl
sudo pip3 install numpy torch-1.2.0a0+8554416-cp36-cp36m-linux_aarch64.whl

#続けてtorchvision
sudo apt-get install libjpeg-dev zlib1g-dev
git clone -b v0.3.0 https://github.com/pytorch/vision torchvision
cd torchvision
sudo python3 setup.py install
```

みんな大好きscipyやKerasのインストールは次の通り

```bash
pip3 install h5py
sudo apt-get install python3-scipy python3-keras
```
~~ネットで調べた時に上のコマンドが出てきたので私はその通りやりましたが、
後々考えてみると```sudo pip3 install```で試しても良かったかも。そのうちやります。~~
2019.8.23追記：pip3でインストールできず・・・。

------補足------
**python-○○とpipは別物**として扱われます。
同じモジュールをそれぞれでインストールすると、import時に競合を起こしてエラーを吐きます。
------補足終わり------

### OpenCV4.0.0のインストール
普通に入れると大変面倒ですが、公式インストールスクリプトがあります。([フォーラムの記事](https://devtalk.nvidia.com/default/topic/1049972/jetson-nano/opencv-cuda-python-with-jetson-nano/post/5331315/#5331315))
スクリプト配布元(https://github.com/AastaNV/JEP/blob/master/script/install_opencv4.0.0_Nano.sh)

実行するだけでインストールできる・・・と思いきや、ビルドの最後で失敗します。
原因はメモリ不足ですので、swap領域が必要です。
swap領域を作る方法は色々なところで言及されていますが、大規模ビルドする時など一時的な場合が多いです。
と言う訳で、再起動すると解除される一時的なswap領域は次のように設定します。

```bash
#(必要ならば)空き領域を確認
df -h

#swap領域(ここでは6GB)の作成
fallocate -l 6G swapfile
chmod 600 swapfile
mkswap swapfile
sudo swapon swapfile

#swap領域が設定されているかの確認
free -m
```

一度再起動するとswapfileは無用の長物です。削除しましょう。

------補足------
先ほど、一時的に必要な場合が多いと述べましたが、場合によっては常時必要なこともあります。
起動時に自動的にマウントする設定まで含めたスワップ領域の作り方は**[こちら](https://www.jetsonhacks.com/2019/04/14/jetson-nano-use-more-memory/)**を参照
引数なしでスクリプトを実行するだけで6GBのswap領域を作ってくれます。

SDカード上にswap領域を作るのはメリット・デメリットがあります。（特に寿命の面のデメリットが目立ちます）
長期間使うときはUSBタイプのSSDをつないで、その上にswap領域を作る方が良い気がします。
------補足おわり------

OpenCV4.0.0のインストールは次のコマンドを実行します。

```bash
wget https://raw.githubusercontent.com/AastaNV/JEP/master/script/install_opencv4.0.0_Nano.sh
chmod 774 install_opencv4.0.0_Nano.sh
./install_opencv4.0.0_Nano.sh ~
```
しっかり計測はしていませんが、ビルドは2時間程度の印象です。
Raspberry Piのような熱暴走もなく完了しました。


また、OpenCV4.1.0を使いたい方は先人で挑戦している方がいらっしゃるので、そちらを参照ください。
<[Jetson nano へ OpenCV 4.1.0 をインストールする](https://qiita.com/asahi0301/items/3c287190348552f19415)>
<[NVIDIA Jetson Nanoで最新版の OpenCV 4.1.0を全自動でビルドしてインストールする方法](http://www.neko.ne.jp/~freewing/raspberry_pi/nvidia_jetson_nano_build_opencv_410/)>

###その他のライブラリも入れる
(個人的に)よく使うものを入れていきます。
pillowやpandasなど入れていきますが、一部はpip3をsudoで実行します。

```bash
pip3 install pillow
sudo pip3 install pandas
sudo pip3 install scikit-learn
pip3 install matplotlib
```
Pandasは30分程度かかります。しかも画面が固まります。放置しましょう。

####GPIOライブラリ
Raspberry Piと同様の使い方です。

```bash
sudo pip3 install Jetson.GPIO
```

####その他あると良いツールなど
```bash
sudo apt-get install htop
```

##VSCodeのインストール
VSCodeでSSHを駆使したリモートな開発も可能ですが、そもそも外からアクセス出来ない、アクセスする道具が無い、アクセスが面倒など実際に使うときには色々あります。
（企業の中とかで外部から隔離された環境や、外部持ち込み端末の接続がNGとか）
私含めニーズがある(気がする)ので解説しておきます。


###本体をビルドする

これもフォーラムに[報告](https://devtalk.nvidia.com/default/topic/1049448/jetson-nano/quick-build-guide-for-visual-studio-code-on-the-nano/post/5331503/#5331503)が上がっています。
確実にビルドするには**swap領域が必要**です。

フォーラムに張り付けられているコマンドを順に実行するだけですが、
swap領域のおかげか一部不要なコマンドがありました。
とりあえず、私の場合は以下のコマンドでインストールできました。(2019年5月時点)

```bash
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

sudo apt update
sudo apt install -y libx11-dev libxkbfile-dev libsecret-1-dev fakeroot npm curl nodejs nodejs-dev yarn

git clone https://github.com/Microsoft/vscode.git
pushd vscode
sed -i 's/4095/2048/g' package.json
yarn
yarn run gulp vscode-linux-arm64-min
yarn run gulp vscode-linux-arm64-build-deb
sudo dpkg -i ./.build/linux/deb/arm64/deb/code-oss_1.??.?-*_arm64.deb
```

1時間くらいはかかります。気長な作業です。
上記が完了後に```sudo reboot```で再起動します。

※2019.9.5追記
ビルド済みパッケージを配布してくれている方が。ありがたいです。
以下のコマンドでvscode1.32.3がインストールできます([参考サイト](https://dev.to/azure/getting-started-with-iot-edge-development-on-nvidia-jetson-devices-2dfl))

```
curl -L https://github.com/toolboc/vscode/releases/download/1.32.3/code-oss_1.32.3-arm64.deb -o code-oss_1.32.3-arm64.deb
sudo dpkg -i code-oss_1.32.3-arm64.deb
```


vscodeの起動は以下のコマンドです。

```bash
code-oss
```

###拡張機能ギャラリーの有効化
ソースコードからビルドしてインストールすると初期状態では拡張機能ギャラリーが無効になっています。

拡張機能のインストール方法は以下の2通りです。

- 設定を弄ってギャラリーを有効化して拡張機能をインストールする
- VSIXファイルからインストールする

ここでは、設定を弄って拡張機能ギャラリーを有効化していきます。

問題の設定ファイル(product.json)を先ほどインストールしたnanoエディタで開きます。
(記事執筆時、たまたまTeraTermで作業しているので。
GUIが使える人はvscodeかgeditで作業すれば良いと思います)

```bash
sudo nano /usr/share/code-oss/resources/app/product.json
```

以下を追記します。（[参考:stackoverflow](https://stackoverflow.com/questions/37143536/no-extensions-found-when-running-visual-studio-code-from-source)）

```json:product.json
,"extensionsGallery": {
    "serviceUrl": "https://marketplace.visualstudio.com/_apis/public/gallery",
    "cacheUrl": "https://vscode.blob.core.windows.net/gallery/index",
    "itemUrl": "https://marketplace.visualstudio.com/items"
}
```
上書き保存して終了します。
json形式で分かりやすいとはいえ、**カンマ忘れ**や**ペースト位置間違い**には注意です。
上のコードブロックの先頭のカンマ、元記事には無いですが忘れがちなのであえて追加してあります。
間違うとVSCodeが起動エラーを吐いて起動しません。

次回起動時からは拡張機能ギャラリーが表示されるようになるので、Python拡張などをインストールします。
これでデバッグやコーディング支援を受けられるので開発もやりやすくなります。

###メニューバーを表示する
不要な人は無視してください。
VSCodeを入れると、メニューバーが表示されていない場合があります。
デスクトップ環境によっては表示できなかったりします。

このままでは扱いにくいので、Visual Studio Codeと同じような表示にします。([参考](https://www.atmarkit.co.jp/ait/articles/1811/16/news032.html))

<設定手順>

 1. まず```Ctrl + Shift + P```でコマンドパレットを起動
 1. ```open user settings```とタイプしてユーザー設定を開く
 3. そのまま```window title bar```と入れる
 4. window.titleBarStyle項目を```custom```に変更
 5. 設定を変更すると再起動を要求されるので再起動する

するとVisual Studio Codeのように、タイトルバーのところにメニューバーが表示されるようになります。

##リモートアクセス
リモートで作業を行うにあたり、必要なことは次の通りです。

 - ファイルのやりとり・共有
 - リモート操作

###ファイルのやり取り
[WinSCP](https://forest.watch.impress.co.jp/library/software/winscp/)でファイルのやりとりが可能です。IPアドレスを打ち込んでJetsonにログインするだけです。
これを利用するためのJetson nano側の設定はありません。
また、NASなどを所有しているならネットワーク経由でやり取りするのでも良いかも知れません。

また、ローカル側のVSCodeに**SSH FS**([参考](https://qiita.com/informationsea/items/5c9f05c81a41fb885460))の拡張機能をインストールすると、リモートでJetson nanoにアクセスしてファイルを編集しやすいです。


###リモート操作(リモートデスクトップ)
~~色々試しているところですが、現状VNC(vino)を使う方法しか成功していません。~~
リモートデスクトップが出来るようになりました。(2019/4/22追記)
[こちら](https://ossyaritoori.hatenablog.com/entry/2017/10/27/Windows10%E3%81%8B%E3%82%89Ubuntu16%EF%BC%88jetsonTX1%29%E3%81%B8%E3%81%A8%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97%E6%8E%A5%E7%B6%9A)のやり方でできました。
手順は以下の通りです。

```bash
#XRDPのインストール
sudo apt-get update
sudo apt-get install xrdp

#homeディレクトリに移動してXfceをインストールして設定を行う
cd /home
sudo apt-get install xfce4 
echo xfce4-session >~/.xsession
```
最後に設定ファイルを修正します。
もちろんエディタは自由です。GUIの人はgeditとかですね。

```bash
sudo nano /etc/xrdp/startwm.sh
```

ファイルの最後2行を以下の感じに修正します

```shell:startwm.sh
#test -x /etc/X11/Xsession && exec /etc/X11/Xsession      ←コメントアウト
#exec /bin/sh /etc/X11/Xsession                           ←コメントアウト
startxfce4                                                ←追加
```
サービスをリスタートします

```bash
sudo service xrdp restart
```
これでWindows側からアクセスできるようになるはずです。

リモートデスクトップでアクセスすると以下の感じでした。
画面が開いた後にパスワード入力を求められますが素直に入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248663/943fa654-ce42-cc2d-ec8a-102343a27599.png)
やはり雰囲気が違いますね。

雰囲気が異なるのは、xrdpでアクセスするためにデスクトップ環境を切り替えているためです。
今回はXfceというXubuntuで採用しているデスクトップ環境に切り替えています。
xrdpがUbuntu標準のGNOMEデスクトップ環境に対応していないことが原因ですね。

同じ理屈でLXDEとかMATEでRDPすることも可能です。

ただ、なぜかターミナルが開きません。
(ターミナル自体は起動していて、全部GNOMEデスクトップの方で立ち上がっている。)
致命的です。
とりあえず、画面左上の**Applications > Development > Code-OSS**(またはApplications > RunProgram... から ```code-oss```を入力)でVSCodeを起動し、コマンドパレットからターミナルを起動してなんとか凌ぐことにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248663/665a0bb3-ab68-f410-2948-222a6fbb7a55.png)
コマンドパレットは右クリックメニューから開けます。または```Ctrl + Shift + P```です。
レスポンスは普通のリモートデスクトップと同等な感じです。良い感じです。

###リモート操作(vino/VNC)
VNC(vino)を使う方法はこちらになります。
レスポンスが悪く、特別な理由が無い限り使う気になりません。
一応手順を載せておきます。

```bash
#vinoのインストール
sudo apt update
sudo apt install vino
gsettings set org.gnome.Vino prompt-enabled false
gsettings set org.gnome.Vino require-encryption false

#UUIDを表示する
nmcli connection show

#ネットワークカードのUUIDを以下のコマンドに張り付ける
dconf write /org/gnome/settings-daemon/plugins/sharing/vino-server/enabled-connections "['<UUID of the ethernet>']"

#vinoサーバーを立てる
export DISPLAY=:0
/usr/lib/vino/vino-server
```
これで準備は完了で、あとは操作側から[VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/)などを使ってアクセスします。

###X11フォワーディングについて
あとはWindowsからX11画面転送で作業できるようにしたかったのですが、まだ実現できていません。
参考情報だけ貼っておきます。

- [NVIDIA Jetson Nano 開発者キットで X11 フォワーディングを利用する](https://qiita.com/tsutof/items/978a61d8c31c5eb9da91)

私の環境(Win10 Pro)では、xeyesやxcalc、xtermは走るのですが、何故かVSCodeが走ってくれません。


(2019/5/30追記)
限定的に可能でした。
Windows10 の Hyper-V で Ubuntu19.04 を走らせ、SSH接続 → 画面転送 は問題なく動作しました。
となるとJetson nano側の設定は特に問題なさそうですし、Ubuntuで表示するならイケそうです。
ただWindowsではVxServやXmingで失敗しました。もうしばらく調査ですかね。

###VSCodeのリモート開発機能について
先日、Visual Studio Code Insiders向けにリモート開発機能が出てきました。
[Remote Development with VS Code](https://code.visualstudio.com/blogs/2019/05/02/remote-development#_get-started)
しかしこの機能、リモート側はx86/x64でないとダメらしく、ARMでは機能しませんでした。(2019年5月時点)

※2019.9.5追記
先日、RPi(arm7l)でも使えるようになったらしいですが、arm64はまだですかね・・・？
と思っていたら7日前にnightly buildで出たらしい。出来立てホヤホヤ。
[GitHub Issues: Please add support for Linux on ARM64](https://github.com/microsoft/vscode-remote-release/issues/69)

解説を見かけないので記事書きました。
[Visual Studio Code で Jetson nano(arm64) のリモート開発を行う](https://qiita.com/koppe/items/425a5dd0494b1dc8e1b2)


##最後に
リモートデバッグする方法もあるようですが・・・。~~調査中です。
→Pythonに限っては[方法](https://qiita.com/MasashiSD/items/ed6f14be35119c99e680#_reference-07641dd2760a1936ebc6)がありました。(2019.5.30追記)~~
→上でも書きましたが、Visual Studio Code InsiderのRemote-SSHでARM64がサポートされたのでそれですべて解決です。(2019.9.21追記)

環境構築に関連した追加や修正などがあればこの記事を随時加筆修正していく予定です。
次は深層学習周りを頑張ってみようと思います。


##参考サイト
- 公式フォーラム(https://devtalk.nvidia.com/default/board/371/)
- 公式wiki(https://elinux.org/Jetson_Nano)
- [Jetson nano へ OpenCV 4.1.0 をインストールする](https://qiita.com/asahi0301/items/3c287190348552f19415)
- [JetsonHacks](https://www.jetsonhacks.com/)