Orin Nanoが買えたので環境構築しました。
Setup Jetson
セットアップや接続に迷ったときはJetson Getting Startedからたどると解決しやすい。
追加で用意する必要があるのは
- L4Tを書き込むためのLocalMachine
- USB-Cのケーブル: LocalMachineと接続するため
- microSD or NVMe(M.2) SSD: 読み書きが早いNVMeのほうがおすすめ
- Keyboard + Mouse: セットアップの最後にGUIが出てくるため
Install L4T(R35.3.1)
大まかに3つの方法がある
microSDを使う場合、SDカードを作れば使い回せること、起動しなくてもLocalMachineから修正が容易なのは利点。
一方でmicroSDは転送速度が遅いので画像、機械学習モデルを動かす上ではボトルネックとなる。
またLinuxより前のBootLoaderなどは更新されないため今後バージョンを上げたときに不整合で機能しないHWが出る可能性がある。
SDKManagerを使うとGUIから操作できること、Jetpackまでセットアップできることが利点の一つ。
何度もセットアップする場合はネットワークから落とすよりも早くなると思われる。
デメリットとしてはLocalMachineのディストロに制限があったり、ストレージを圧迫すること。
ここではBSPからflushする方法を取る。
Jetpackなどは手動セットアップになるが作業の再現性がよい。
ForceRecovery Modeで起動
- NVMeなどのストレージを接続する
- J5のUSB-CとLocalMachineを接続する
- キーボードとマウスは適当に接続
- DisplayPortを適当なディスプレイに接続
- 可能なら有線LANをつなぐ
- J14の左から3,4番目PIN#10,#9を短絡させながら電源を入れる(J16にDCジャックを接続)
DS1のLEDが光るがつないだディスプレイには何も写っていない状態になる。
LocalMachineからはlsusb
でNVIDIAのデバイスが見えていればflushに進む。
Flush
FlushではLinuxストレージ以外にも書き込みが行われる。
以下にMakefileを用意しているので接続ができているなら make flush
で書き込みができます。
初回のセットアップが面倒な場合は add_user
で事前にアカウントとホスト名の設定が出来ます。
MAJOR:=35
MINOR:=3.1
L4T_RELEASE_PACKAGE:=Jetson_Linux_R${MAJOR}.${MINOR}_aarch64.tbz2
SAMPLE_FS_PACKAGE:=Tegra_Linux_Sample-Root-Filesystem_R${MAJOR}.${MINOR}_aarch64.tbz2
RELEASE_ADDR:=https://developer.download.nvidia.com/embedded/L4T/r${MAJOR}_Release_v${MINOR}/release
# STORAGE_DEVIVE:=sda1 # USB Memory or microSD
STORAGE_DEVIVE:=nvme0n1p1 # NVMe SSD
# BOARD:=p3737-0000+p3701-0000-maxn # Jetson AGX Orin DK MAXN
# BOARD:=p3509-a02+p3767-0000 # Jetson OrinNX + XavierNX DK
BOARD:=jetson-orin-nano-devkit # Jetson Orin Nano DK
HOSTNAME:=orin-nano # Need set your hostname
USERNAME:=jetson
PASSWORD:=jetson
.PHONY: flush
flush:
cd Linux_for_Tegra \
&& sudo ./tools/kernel_flash/l4t_initrd_flash.sh --external-device ${STORAGE_DEVIVE} \
-c tools/kernel_flash/flash_l4t_external.xml -p "-c bootloader/t186ref/cfg/flash_t234_qspi.xml" \
--showlogs --network usb0 ${BOARD} internal
# L4Tにデフォルトユーザーを設定する
.PHONY: add_user
add_user:
cd Linux_for_Tegra \
&& sudo ./tools/l4t_create_default_user.sh -u ${USERNAME} -p ${PASSWORD} --autologin --accept-license --hostname ${HOSTNAME}
extract: Linux_for_Tegra/rootfs
cd Linux_for_Tegra/ \
&& sudo ./apply_binaries.sh \
&& sudo ./tools/l4t_flash_prerequisites.sh
Linux_for_Tegra: download
tar xf ${L4T_RELEASE_PACKAGE}
Linux_for_Tegra/rootfs: Linux_for_Tegra
sudo tar xpf ${SAMPLE_FS_PACKAGE} -C Linux_for_Tegra/rootfs/
download: ${L4T_RELEASE_PACKAGE} ${SAMPLE_FS_PACKAGE}
${L4T_RELEASE_PACKAGE}:
wget ${RELEASE_ADDR}/${L4T_RELEASE_PACKAGE}
${SAMPLE_FS_PACKAGE}:
wget ${RELEASE_ADDR}/${SAMPLE_FS_PACKAGE}
microSDに書く方法を使わないのはNVMeだからflushするしかないのもあるが、カメラなどデバイスの認識はLinuxのBoot以前のステップで行われており、BSPのバージョン不一致が大きくなると期待通りに認識できなくなることもあるのでflushするほうがトラブルが起きにくい。Boot ArchitectureにBoot時に何が行われているのかが書かれている。
Setup by GUI
(事前にmake add_user
をした場合はこのステップは不要)
Flushが成功したらUBuntu20.04のセットアップ画面が開いているはずなので、適当に設定をする。
セットアップが終わったら、無線の場合は無線の接続設定をしてPowerModeを15Wなどに設定して再起動。
mDNSによって設定した<hostnane>.local
でアクセスできるはずなので以降SSHで作業をする。
USB経由で仮想ネットワーク接続もあるのでそちらでつないでも構わない(があまり安定していないように見受けられるので有線LANを推奨)
この記事では以降orin-nano
というhostname jetson
というユーザーで作ったという前提で進める
Setup SSH with VSCode
GUIを使った開発をすることもあると思うのでVSCode Remote SSHを利用したときに、LocalMachine側にGUI表示が出るように設定をする。
ssh configの設定を以下のように設定する。
頻繁に再インストールしてfingerprintが変わる場合はIPチェックは外しておくのが楽。
ForwardX11はGUIアプリケーションを開発する場合に必要な設定。
Host orin-nano
HostName orin-nano.local
User jetson
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null
ForwardX11 yes
ForwardX11Trusted yes
ホスト側もX11 forwardを許可してsshdを再起動する
+ X11Forwarding yes
+ X11DisplayOffset 10
+ X11UseLocalhost yes
SSHのたびにパスワードを入れなくて良いようにSSH鍵登録をする
# まだ鍵を作っていない場合
ssh-keygen -t ed25519
# orin-nano鍵を登録
ssh-copy-id orin-nano
この時点でVSCodeからCtrl+Shift+P
-> Remote SSH: Connect to Host
-> orin-nano
で接続ができる。
VSCode Remote SSHはデフォルトでX11 Forwardingをしているのでxeyes
などを実行するとLocalMachineに画面が出てくる。
注意点
xeyesなどの代表的なX11を使うアプリケーションは動作するが、NVIDIAのEGLを使うような処理の場合、例えばnvarguscamerasrc
などはDISPLAYのEGL初期化に失敗して動かせなくなる場合がある。
gst-launch-1.0 nvarguscamerasrc ! fakesink
libEGL warning: DRI3: failed to query the version
libEGL warning: DRI2: failed to authenticate
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
GST_ARGUS: Creating output stream
(Argus) Error BadParameter: (propagating from src/eglstream/FrameConsumerImpl.cpp, function initialize(), line 89)
(Argus) Error BadParameter: (propagating from src/eglstream/FrameConsumerImpl.cpp, function create(), line 44)
Error generated. /dvs/git/dirty/git-master_linux/multimedia/nvgstreamer/gst-nvarguscamera/gstnvarguscamerasrc.cpp, threadInitialize:320 Failed to create FrameConsumer
Error generated. /dvs/git/dirty/git-master_linux/multimedia/nvgstreamer/gst-nvarguscamera/gstnvarguscamerasrc.cpp, threadFunction:241 (propagating)
Error generated. /dvs/git/dirty/git-master_linux/multimedia/nvgstreamer/gst-nvarguscamera/gstnvarguscamerasrc.cpp, waitRunning:203 Invalid thread state 3
Error generated. /dvs/git/dirty/git-master_linux/multimedia/nvgstreamer/gst-nvarguscamera/gstnvarguscamerasrc.cpp, execute:806 (propagating)
Got EOS from element "pipeline0".
Execution ended after 0:00:00.092742811
Setting pipeline to NULL ...
Freeing pipeline ...
そういうときはX11Forwardを諦めてDISPLAYをunsetすると動作することがある。
unset DISPLAY
gst-launch-1.0 nvarguscamerasrc ! fakesink
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
GST_ARGUS: Creating output stream
CONSUMER: Waiting until producer is connected...
GST_ARGUS: Available Sensor modes :
...
install multimedia-api and nvidia-docker
ここからはアプリケーション向けのセットアップ。
このままJetson上で構築してももちろんいいが、実運用を考えるとコンテナで扱える方法を知っていると助かるケースがあるので、コンテナでの開発環境をセットアップする。
まずはdockerとnvidiaのruntime、そしてJetsonの特徴の一つであるmultimedia-apiをインストールする。
デフォルトのruncではL4T関連のリソースが使えないのでruntimeのデフォルトを変更する
sudo apt install -y \
libnvidia-container-tools \
libnvidia-container0 \
nvidia-container-runtime \
nvidia-docker2 \
nvidia-l4t-jetson-multimedia-api \
curl
# sudo lessで使えるようにする
sudo usermod -aG docker $USER
# nvidia runtimeをデフォルトにする
sudo vi /etc/docker/daemon.json
{
+ "default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
再起動したら以下のようになっていればOK
docker info | grep Runtime
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux nvidia runc
Default Runtime: nvidia
buildx
DevContainerが使うためbuildxをinstall
wget https://github.com/docker/buildx/releases/download/v0.10.4/buildx-v0.10.4.linux-arm64
mkdir -p $HOME/.docker/cli-plugins
cp buildx-v0.10.4.linux-arm64 $HOME/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx
docker buildxコマンドが使えるようになる
fmy:~ $ docker buildx
Usage: docker buildx [OPTIONS] COMMAND
Extended build capabilities with BuildKit
Setup VSCode Dev Container with Remote SSH
RemoteSSHからさらにVSCodeのDev Container
を使って開発する方法を紹介する。
コンテナの中でもローカル環境とほとんど操作感が変わらず作業ができてとても助かる。
設定のテンプレートはこのリポジトリにPushしてある。
DockerFileはコメントを入れているのでdevcontainer.json
について解説をする
X11の動作についてはコンテナ内では不安定な(displayが開けない、Nv関係のエラーが出る)ためまだ検証中
{
// buildの設定
"build": {
"dockerfile": "Dockerfile",
// Jetpackにあわせたベースコンテナを使う指定をする
// CUDA_VERなどはビルド時に指定が必要なことが多いので入れておくと後が楽
"args": {
"L4T_VERSION": "r35.3.1",
"BASE_IMAGE_NAME": "nvcr.io/nvidia/l4t-base:35.3.1",
"DS_VERSION": "6.2",
"CUDA_VER": "11.4"
}
},
// 前者はJetson固有のリソース
// L4Tコンテナ内ではL4Tに関するパッケージのinstallができないため
// Hostにインストールした後bindingする形になる
"mounts": [
{
"type": "bind",
"source": "/tmp/argus_socket",
"target": "/tmp/argus_socket"
},
{
"type": "bind",
"source": "/usr/src/jetson_multimedia_api",
"target": "/usr/src/jetson_multimedia_api"
},
// HostのX11の設定を引き継ぐ
{
"type": "bind",
"source": "${env:HOME}/.Xauthority",
"target": "/home/vscode/.Xauthority"
}
],
// Userの指定をしなければrootがownerのファイルができてしまうため
// コンテナ内のユーザーのUIDをhostのUIDで上書きしてowner不一致をさせない
"remoteUser": "vscode",
"updateRemoteUserUID": true,
// X11を接続するためにhostネットワークを使い、hostのDISPLAY環境変数を使う
// DISPLAYは今はdevcontainer.envで決め打ちしている
"runArgs": [
"--env-file",
".devcontainer/devcontainer.env",
"--network",
"host"
]
}
上記リポジトリの.devcontainer
以下を作業ディレクトリにコピーし、DockerFileを用途に合わせて修正したら Ctrl+Shift+P
-> Dev Container: Reopen in Container
でコンテナ内でも作業ができる。
最後に
軽くDeepStreamなどを見たところXavierNXでは変換に時間がかかりすぎていたものがOrinNanoではすぐに終わるなど部分的には上位互換と言えるような雰囲気でした。
今後カメラ周りとかも今後触っていきたい。