コンテンツへスキップ

NVIDIA Jetson Nano B01 の電源セレクター

NVIDIA Jetson Nanoを導入する人は、機械学習などの推論デバイスとして、Jetson Nanoの主な利用目的だと思います。

Jetson Nanoには、2系統の電源入力が選べ、マイクロUSB経由での給電か、ACアダプターからの給電が選択可能です。

  • マイクロUSBコネクターからの給電。最大2A
  • ACアダプターからの給電。最大4A

推論デバイス用途で利用する際は、CUDAコアをフルに稼働させたいと思いますので、その際は、マイクロUSBからの給電では、電力不足に陥るので、ACアダプターからの給電となります。ACアダプターは、以下の仕様となります。

  • 5V/4A DC
  • 電源ジャックは外径5.5mmφ、内径2.1mmφでセンター+

電源セレクターのジャンパーピン

以前のモデルのNVIDIA Jetson Nano A01の際は、利用する電源を選択するセレクター(Power Select Header (J48))に、自分で準備したジャンパーピンを用いてショートさせる必要がありました。

モデルチェンジ版のNVIDIA Jetson Nano B01には、写真のようにジャンパーピンが付属しておりました。
セレクターをショートさせずに付属しているので、アダプター利用時には、ジャンパーピンを用いて、J48をショートさせて、電源アダプター給電を利用します。

created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

NVIDIA Jetson Nano 追加

機械学習向けシングルボードコンピューターNVIDIA Jetson Nano、追加導入しました。
新しいラインナップなどが出ていないか、調べると、マイナーチェンジを行ったみたいです。

大きな違いはないですが、ボードから変わっているので、見えない安定性なども向上していることを期待してしまいます。

created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

NVIDIA Jetson Nano A02 と B01 違い

  • カメラコネクターが一つから二つに追加
    • カメラコネクターの追加(J49)
    • カメラコネクターの場所変更(J13)
  • ボタンヘッダー削除 (J40)
  • シリアルボードヘッダーの削除 (J44)
  • 入力電源選択の場所を変更 (J48)

NVIDIA Jetson Nano B01 仕様

GPU128-core Maxwell
CPUQuad-core ARM A57 @ 1.43 GHz
Memory4 GB 64-bit LPDDR4 25.6 GB/s
StoragemicroSD (not included)
Video Encoder4K @ 30 | 4x 1080p @ 30 | 9x 720p @ 30 (H.264/H.265)
Video Decoder4K @ 60 | 2x 4K @ 30 | 8x 1080p @ 30 | 18x 720p @ 30|(H.264/H.265)
Camera2 x MIPI CSI-2 DPHY lanes
ConnectivityGigabit Ethernet, M.2 Key E
DisplayHDMI 2.0 and eDP 1.4
USB4 x USB 3.0, USB 2.0 Micro-B
OthersGPIO, I2C, I2S, SPI, UART
Mechanical100 mm x 80 mm x 29 mm
created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

NVIDIA Jetson NanoへのGoogle Home Notifier導入は、  こちら

google-tts-apiからHOYA社のVoice Text Web APIへ

Google Home Notifierは、テキストをgoogle-tts-apiを用いて、音声変換を実施しております。十分に内容は把握できますし、実利用には支障はないのですが、HOYA社より優れたWeb APIが公開されているので、HOYA社のVoice Text Web APIを用いた音声に変更を実施します。HOYA株式会社 VoiceText Web API

  1. HOYA社Voice Text Web APIの利用登録
  2. 「voicetext」のインストール
  3. google-home-notifierソースコード修正

前提条件

導入手順

1.HOYA社Voice Text Web APIの利用登録

HOYA株式会社 VoiceText Web APIの「無料利用登録」より利用登録を実施して下さい。利用登録後に、API KEYがメールで送付されて来ます。

2.「voicetext」のインストール

以下のコマンドで、「voicetext」をインストールします。

root@jetson:~# cd google-home-notifier/
root@jetson:~/google-home-notifier# npm update
root@jetson:~/google-home-notifier# npm install voicetext
npm WARN deprecated superagent@0.18.2: Please note that v5.0.1+ of superagent removes User-Agent header by default, therefore you may need to add it yourself (e.g. GitHub blocks requests without a User-Agent header).  This notice will go away with v5.0.2+ once it is released.
google-home-notifier@1.2.0 /root/google-home-notifier
└── voicetext@0.0.7  extraneous

npm WARN google-home-notifier@1.2.0 No repository field.
root@jetson:~/google-home-notifier# npm install -g npm
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
/usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js
/usr/local/lib
├── ansi-regex@2.1.1
├── aproba@2.0.0
├── aws4@1.8.0
├── bin-links@1.1.3
├── bluebird@3.5.5
├── byte-size@5.0.1
├── cacache@12.0.3
├── call-limit@1.1.1
├── chownr@1.1.2

3.google-home-notifierソースコード修正

「google-home-notifier.js」ファイルの修正

以下を参考に2箇所追加および1箇所コメントアウト(削除)を実施します。

var Client = require('castv2-client').Client;
var DefaultMediaReceiver = require('castv2-client').DefaultMediaReceiver;
var mdns = require('mdns');
var browser = mdns.createBrowser(mdns.tcp('googlecast'));
var deviceAddress;
var language;

//Add (((((((((((
var VoiceTextWriter = require('./VoiceTextWriter');
var voiceTextWriter = new VoiceTextWriter();
//Add ))))))))))

var device = function(name, lang = 'en') {
    device = name;
    language = lang;
    return this;
};

var ip = function(ip, lang = 'en') {
  deviceAddress = ip;
  language = lang;
  return this;
}

var googletts = require('google-tts-api');
var googlettsaccent = 'us';
var accent = function(accent) {
  googlettsaccent = accent;
  return this;
}

var notify = function(message, callback) {
  if (!deviceAddress){
    browser.start();
    browser.on('serviceUp', function(service) {
      console.log('Device "%s" at %s:%d', service.name, service.addresses[0], service.port);
      if (service.name.includes(device.replace(' ', '-'))){
        deviceAddress = service.addresses[0];
        getSpeechUrl(message, deviceAddress, function(res) {
          callback(res);
        });
      }
      browser.stop();
    });
  }else {
    getSpeechUrl(message, deviceAddress, function(res) {
      callback(res);
    });
  }
};

var play = function(mp3_url, callback) {
  if (!deviceAddress){
    browser.start();
    browser.on('serviceUp', function(service) {
      console.log('Device "%s" at %s:%d', service.name, service.addresses[0], service.port);
      if (service.name.includes(device.replace(' ', '-'))){
        deviceAddress = service.addresses[0];
        getPlayUrl(mp3_url, deviceAddress, function(res) {
          callback(res);
        });
      }
      browser.stop();
    });
  }else {
    getPlayUrl(mp3_url, deviceAddress, function(res) {
      callback(res);
    });
  }
};

var getSpeechUrl = function(text, host, callback) {
//Delete ((((((((((
//  googletts(text, language, 1, 1000, googlettsaccent).then(function (url) {
//    onDeviceUp(host, url, function(res){
//      callback(res)
//    });
//  }).catch(function (err) {
//    console.error(err.stack);
//  });
//Delete )))))))))
//Add (((((((((
	voiceTextWriter.convertToText(text).then(function(result, reject){
        onDeviceUp(host, result, function(res){
            callback(res)
        });
    }).catch(function onRejected(error){
		console.error(error);
	});
//Add )))))))))
};

var getPlayUrl = function(url, host, callback) {
    onDeviceUp(host, url, function(res){
      callback(res)
    });
};

var onDeviceUp = function(host, url, callback) {
  var client = new Client();
  client.connect(host, function() {
    client.launch(DefaultMediaReceiver, function(err, player) {

      var media = {
        contentId: url,
        contentType: 'audio/mp3',
        streamType: 'BUFFERED' // or LIVE
      };
      player.load(media, { autoplay: true }, function(err, status) {
        client.close();
        callback('Device notified');
      });
    });
  });

  client.on('error', function(err) {
    console.log('Error: %s', err.message);
    client.close();
    callback('error');
  });
};

exports.ip = ip;
exports.device = device;
exports.accent = accent;
exports.notify = notify;
exports.play = play;

「VoiceTextWriter.js」ファイルの新規作成

  • 「@APIKEY@」を利用登録時に受信したAPIKEYに変更
  • 「@WEBPAHT@」にWEBサーバの公開フォルダに格納する音声ファイルを指定
    例:/var/www/html/voice-text.wav
  • 「@URL@」にWEBサーバの音声ファイルへアクセスする際のURLを指定
    例:http://192.168.0.200/voice-text.wav
var fs = require('fs');
var VoiceText = require('voicetext');
var voice = new VoiceText('@APIKEY@');
var OUT_PATH = '@WEBPAHT@';
var OUTPUT_URL = '@URL@';

class VoiceTextWriter{

	convertToText(text){
	return new Promise(function(resolve,reject){
	voice
	.speaker(voice.SPEAKER.HIKARI)
	.emotion(voice.EMOTION.HAPPINESS)
//	.emotion_level(voice.EMOTION_LEVEL.HIGH)
	.emotion_level(2)
        .speed(100)
	.volume(120)
	.speak(text, function(e, buf){
	    if(e){
	      console.error(e);
	      reject(e);

	    }else{
	   	 fs.writeFileSync(OUT_PATH, buf, 'binary');
	  	 resolve(OUTPUT_URL);
	    }
	  });
	});
	}
}
module.exports = VoiceTextWriter;

VoiceText Web APIマニュアルを参考に、speedやvolumeなどのオプション指定を変更して、好みの音声に変更して下さい。設定ファイル変更時には、Google Home Notifierの再起動が必要となります。

created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)
created by Rinker
¥11,550 (2024/11/22 22:07:49時点 楽天市場調べ-詳細)

NVIDIA Jetson Nano の動作温度

Raspberry Piを導入した際に、高負荷時の動作が遅かったので、温度を疑い、見事に高温からくるCPUクロック速度の制御が行われておりました。
参考記事:Raspberry Pi 熱対策 ファン導入

NVIDIA Jetson Nano導入時より温度の履歴を取得しておりました。

NVIDIA Jetson Nanoのセンサー情報取得

/sys/devices/virtual/thermal/thermal_zone[0-9]/type にセンサタイプ、
/sys/devices/virtual/thermal/thermal_zone[0-9]/temp に温度が記載されています。

$ cat /sys/devices/virtual/thermal/thermal_zone[0-9]/type
AO-therm
CPU-therm
GPU-therm
PLL-therm
PMIC-Die
thermal-fan-est
$ cat /sys/devices/virtual/thermal/thermal_zone[0-9]/temp
45500
35500
36000
33500
100000
35750

それぞれの内容を調べたのですが、以下の説明しか入手出来なかったです。
とりあえず、CPU温度とGPU温度の履歴を収集しました。
AO: always on,
PLL: phase locking loop,
PMIC: power management IC,
Tdiode: temperature of thermal diode in chip,
Tboard: temperature of board read from a thermal diode on board.

CPU温度とGPU温度をDBへ保存する際に利用したPHPスクリプト

//ログのファイル名
define("SENDGRID_API_LOG_NAME","jetson-temp");
//DB
define("DB_HOST","@DB_IP@:3307");
define("DB_USER","@USER@");
define("DB_PASS","@PASS@");
define("DB_DBNAME","@DB_NAME@");
define("DB_TABLENAME1","@TABLE_NAME@"); 

//温度取得ファイル名 CPU
define("FILE_NAME1","/sys/devices/virtual/thermal/thermal_zone1/temp");
//温度取得ファイル名 GPU
define("FILE_NAME2","/sys/devices/virtual/thermal/thermal_zone2/temp");

function addDBRecord($table, $datetime, $value1, $value2) {
    ##$mysqli = new mysqli($host_name, $user_name, $password, $database_name);
    $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBNAME);

    /* 接続状況をチェックします */ 
    if (mysqli_connect_errno()) {
        logger("Connect failed: ".mysqli_connect_error(),"INFO");
        exit();
    }
    echo "DB接続";

    // SQL(INSERT)を作成
    $sql = "INSERT INTO $table (
	    DATETIME, CPUTHERM, GPUTHERM
	        ) VALUES (
	        '$datetime', $value1, $value2
		)";
        
    $mysqli->query($sql);
    $mysqli->close();
}


function logger($text, $level) {
	$datetime = date('Y-m-d H:i:s');
	$date = date('Ym');
	$file_name = __DIR__ . "/log/".SENDGRID_API_LOG_NAME."-{$date}.log";
	$text = "{$datetime} [{$level}] {$text}" . PHP_EOL;
	echo $text;
	if(!(file_exists($file_name))){
		touch($file_name);
		chmod($file_name, 0777);
	}
	return error_log(print_r($text, TRUE), 3, $file_name);
}

//function logger($text, $level)

logger("Start Jetson temperature","INFO");

$datetime = date("Y/m/d H:i:s");

// ファイルを配列に格納し、さらに変数に格納
$lines1 = file(FILE_NAME1);
$temp1 = (float) $lines1[0] / 1000;
$lines2 = file(FILE_NAME2);
$temp2 = (float) $lines2[0] / 1000;

//echo $datetime;
//echo $lines[0];
#addDBRecord($table, $time, $value1) {
addDBRecord(DB_TABLENAME1,$datetime,$temp1,$temp2);

logger("End Raspi temperature : DATETIME: {$datetime}, CPU-TEMP: {$temp1}, GPU-TEMP: {$temp2}","INFO");

NVIDIA Jetson NanoのCPU温度・GPU温度の蓄積結果

平日の結果です。4回のめざましじゃんけんに合わせて、温度が高くなっています。
ただし、60℃以下ですし、ファンの導入は行っておりません。
Raspberry Piの発熱量と比べると非常に優秀です。

created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

Linux間のボリュームマウントNFS

今回は、Jetson NanoのUbuntuボリュームを、Intel NUCのUbuntuからマウントする方法を紹介します。

  1. ボリュームを提供するサーバー側にnfs-kernel-serverを導入および設定
  2. クライアント側にnfs-commonを挿入およびマウント

サーバー側:Ubuntu にnfs-kernel-server導入

Nvidia jetson NanoのUbuntuにNFSをインストールします。

$ sudo apt install nfs-kernel-server -y

共有したいボリュームを/etc/exportsに記載します。

$ sudo vi /etc/exports
# 最終行にマウント設定を記述

/home 192.0.0.0/24(rw,no_root_squash)

クライアント側:Intel NUCにnfs-common導入

Intel NUCのUbuntuにNFSツールをインストールします。
$ sudo apt -y install nfs-common
マウントポイントとなるフォルダーを作成し、マウントコマンドでマウントを実行します。
root@Intel-NUC:~# mkdir /mnt/jetson

root@Intel-NUC:~# mount -t nfs 192.168.0.xxx:/home /mnt/jetson
created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

Google Home Notifier導入準備

Google Home Notifier導入に向けてNode.jsとnpmをインストールします。

root@jetson:~# apt update
root@jetson:~# apt upgrade -y
root@jetson:~# apt install nodejs npm -y
root@jetson:~# npm cache clean
root@jetson:~# npm install npm n -g
root@jetson:~# npm -v
3.5.2

google-home-notifierインストール

@raspberrypi $ curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
@raspberrypi$ sudo apt-get install nodejs
@raspberrypi $ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev

apt install libavahi-compat-libdnssd-dev

root@jetson:~# git clone https://github.com/noelportugal/google-home-notifier
Cloning into 'google-home-notifier'...
remote: Enumerating objects: 155, done.
remote: Total 155 (delta 0), reused 0 (delta 0), pack-reused 155
Receiving objects: 100% (155/155), 26.28 KiB | 48.00 KiB/s, done.
Resolving deltas: 100% (84/84), done.
root@jetson:~# cd google-home-notifier/
root@jetson:~/google-home-notifier# npm install

GoogleTTSの仕様変更対応

GoogleTTSの新バージョンがリリースされており、このままでは、うまく動作しません。この手順を実施していないと、以下のエラーメッセージが表示されます。

Error: get key failed from google
at /root/google-home-notifier/node_modules/google-tts-api/lib/key.js:27:13
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)

GitHubでクローンしたレポジトリのとオプフォルダーにある、package.jsonのバージョン情報を変更。(0.0.2から0.0.4に変更)

root@jetson:~/google-home-notifier# vi package.json
"keywords": [
"google home",
"notifications",
"notifier"
],
"license": "MIT",
"dependencies": {
"body-parser": "^1.15.2",
"castv2-client": "^1.1.2",
"express": "^4.14.0",
"google-tts-api": "0.0.4",// ここを0.0.4に書き換える
"mdns": "^2.3.3",
"ngrok": "^2.2.4"
},

pakage.jason変更後に、google-tts-apiのアップデートを実施。

root@jetson:~/google-home-notifier# npm update google-tts-api
google-home-notifier@1.2.0 /root/google-home-notifier
└── google-tts-api@0.0.4

Webhook(WEBリクエスト)形式での運用準備

google-home-notifierフォルダにあるexample.jsを流用して、以下の形式でのリクエストによりGoogleホームより音声出力を実現します。以下のコマンドで、WEBアクセスの待ち状態となります。

root@jetson:~/google-home-notifier# nodejs example.js

起動時に以下のWARNINGが出るのですが、ほかの方もWARNINGが出たまま運用しているようです。(WARNINGを消す情報は見つけられませんでした)

*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/blog/projects/avahi-compat.html>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/blog/projects/avahi-compat.html>Endpoints:

google-home-notifierフォルダにあるexample.jsをコピーして、実際に利用するスクリプトを準備します。

  • serverPort:NVIDIA Jetson Nanoの受付ポート番号
  • deviceName:Google Homeのニックネーム
  • ip:Google HomeのIPアドレス
  • 言語設定を2か所 'ja' に変更します。
const serverPort = @PORT_NUM@; // default port

var deviceName = 'Google-Home-2F';
var ip = '192.168.xxx.xxx'; // Google-Home-IP


var language = 'ja'; // default language code

今回は3台分のGoogle Home Miniを運用したいので、example.jsを3個コピーして、3個のスクリプトを起動する方式にしました。

  • Google-Home-1:192.168.xxx.81:ポート番号9081
    http://192.168.xxx.xxx:9081/google-home-notifier?text=Hello+Google+Home
  • Google-Home-2:192.168.xxx.82:ポート番号9082
    http://192.168.xxx.xxx:9082/google-home-notifier?text=Hello+Google+Home
  • Google-Home3:192.168.xxx.83:ポート番号9083
    http://192.168.xxx.xxx:9083/google-home-notifier?text=Hello+Google+Home

forever導入による常時起動化とサーバー再起動時の自動起動

foreverモジュールの導入方法

root@jetson:~/google-home-notifier# npm install -g forever

起動時のコマンドは、以下となります。

/usr/local/bin/forever start /home/user/google-home-notifier/google-home-1.js

再起動時にスクリプトが自動起動するようにクーロン登録します。

root@jetson:~/google-home-notifier# crontab -e

以下を登録します。

@reboot /usr/local/bin/forever start /home/user/google-home-notifier/google-home-1.js
@reboot /usr/local/bin/forever start /home/user/google-home-notifier/google-home-2.js
@reboot /usr/local/bin/forever start /home/user/google-home-notifier/google-home-3.js

foreverコマンドは、「stop」「restart」がそれぞれ停止と再起動となります。
「list」では、foreverで実行しているNode.jsアプリのパスや実行時間、ログファイルの保存場所などの詳細情報を出力します。

YOLO動作環境

YOLO v3を動作することが出来なかったので、利用を見送りましたが、darkflowというフレームワークを導入したので、インストール方法を残しておきます。

pipやaptでインストール出来なかったですが、gitよりダウンロードし簡単に導入出来ます。

NVIDIA Jetson Nano、Raspberry Piで導入し、動作テストを実施しました。

git clone https://github.com/thtrieu/darkflow.git
cd darkflow
pip3 install .
created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

 

YOLO v3, YOLO v3 tinyなどの動作環境

OpenCVのdnnモジュールやTensorFlow-Kerasを用いた方法などで、YOLO v3やTiny YOLO v3を動作させていました。

NVIDIA Jetson Nanoでは、NVIDIAのGPUエンジンが使えるということもあり、AlexeyAB / darknetをインストールが可能です。
(Raspberry Piにおいては、NCS2を導入し、OpenVINOで動作可能なフレームワークでYOLOを動作させる環境がおすすめです。 Movidius Neural Compute Stick 2、OpenVINO™ toolkit for Raspbian OS導入

Jetson Nanoへ libdarknet.so 導入

以前に紹介した、NVIDIA Jetson Nanoへの AlexeyAB / darknet / YOLO3 インストール(Nvidia Jetson Nano)と同様の方法でAlexeyAB Darknetの導入を行います。

手順の異なりは、Makefileの内容となり、「LIBSO」のフラグを1に設定します。「LIBSO=1」

ライブラリーアップデート

  1. apt update
  2. apt upgrade -y

Cuda関係のパスを環境変数に登録

  1. export PATH=/usr/local/cuda-10.0/bin${PATH:+:${PATH}}
  2. export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

DarknetのダウンロードとYoloモデルのダウンロード

  1. git clone https://github.com/AlexeyAB/darknet
  2. cd darknet
  3. wget https://pjreddie.com/media/files/yolov3.weights
  4. wget https://pjreddie.com/media/files/yolov3-tiny.weights

MakeFileを変更しGPU、OPENCV対応へ

Makefileを変更し、GPU、CudaとOpencv対応となるようにコンパイルオプションを変更します。.

  1. sudo vi Makefile

MakeFile変更内容
GPU=1
CUDNN=1
CUDNN_HALF=1
OPENCV=1
AVX=0
OPENMP=0
LIBSO=1
ZED_CAMERA=0

Darknetをコンパイル

  1. make

Pythonからlibdarknet.so利用方法

「darknet」インストールフォルダーの直下にある、「darknet.py」がサンプルスクリプトとなります。Python3にも完全に対応されているので、そのまま利用可能です。

サンプルスクリプト内で、「from ctypes import *」「lib = CDLL("darknet/libdarknet.so", RTLD_GLOBAL)」で、libdarknet.soをロードし、利用可能となります。
画像検出結果を画像表示する部分で、「
from skimage import io, draw」を利用する部分があり、動作確認を行うJetsonには未導入でしたので、別途導入を行いました。

Installing collected packages: networkx, imageio, PyWavelets, scikit-image
Successfully installed PyWavelets-1.0.3 imageio-2.6.1 networkx-2.3 scikit-image-0.15.0

import darknet.pyとサンプルファイルをそのままロードしてしまい、
darknet.performDetect(imagePath=, thresh= , configPath = , weightPath = , metaPath= , showImage= , makeImageOnly = , initOnly= ):
で画像検出を実施すれば良いと思います。
OpenCVを利用する際の
BGRとRGB画像形式の利用方法もdarknet.pyのサンプルファイル内に記載されております。

created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

NVIDIA Jetson Nano初期設定②

SDカードなどを用いて、最初のOSイメージを作成し、Jetson Nanoを起動させます。
参考記事:Jetson Nano DeveloperをUSB 接続HDD/SSDルート構成
初期設定①(こちら)で、初期の起動から、必須性の高い、TensorFlow、Keras、OpenCVまでのインストールを実施しております。
初期設定②は、(必要に応じて導入するソフトが大半なので)個人的なメモ代わりの要素が大きいです。

ufwファイアーウォール導入

aptでufwファイアーウォールを導入し、SSHなど必要なサービスが利用出来るように設定します。ufwを有効化する際に、SSHが利用できなくなる旨のメッセージが表示されます。SSHポート(22)を許可に変更しないと、次回のセッションよりブロックされるので必ずSSHポート(22)が利用できるように設定してください。

root@Jetson:~# apt install ufw

root@Jetson:~# ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y

root@Jetson:~# ufw allow 22
root@Jetson:~# ufw allow 80
root@Jetson:~# ufw allow 443

root@Jetson:~# ufw reload

ufwコマンド

ufwコマンド説明
ufw enableufwを有効化
ufw disableufwを無効化
ufw statusufwの状態とルールを表示
ufw status verboseufwの状態とルールを詳細表示
ufw delete 番号指定した番号のルールを削除する
ufw allow from ネットワークアドレス to ホストアドレス(or any) port ポート番号

例:ufw allow from 192.168.1.0/24 to any port ssh

fromで指定したアドレスからtoで指定したアドレスかつポートへの通信を受信する

ネットワークアドレス:192.168.1.0/24形式で指定

Apache2導入

Apacheをインストールする

$ apt install apache2

PHP、DB関係モジュール導入

root@Jetson:~# apt install php
root@Jetson:~# apt install mysql-server
root@Jetson:~# apt install php-mysql

samba導入

root@Jetson:~# apt install samba -y
root@jetson:~# vi /etc/samba/smb.conf 

#smb.conf 記載内容

[global]
#"下2行追加"
dos charset = CP932
unix charset = UTF-8

[share]
comment = share on Jetson Nano
path = /var/share
browseable = yes
writable = yes
create mode = 0777
directory mode = 0777

Python関連モジュール導入 (Pip3)

以下のモジュールをpip3 install で導入。

  • matplotlib
  • pandas
  • python-dev
  • default-lib
  • mysqlclient-dev
  • mysqlclient
  • python3-dev
  • sklearn
  • pillow
created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)

NVIDIA Jetson Nano初期設定①

SDカードなどを用いて、最初のOSイメージを作成し、Jetson Nanoを起動させます。
参考記事:Jetson Nano DeveloperをUSB 接続HDD/SSDルート構成

導入パッケージのアップデート

sudo apt update
sudo apt upgrade -y

SWAP領域作成

SWAP領域は、ディスクアクセスが多いので、USB接続のHDD上にSWAP領域を作成しました。
/dev/sda1 swap swapをSWAPとしました。
また、各種ユーザー領域として、/dev/sda2のパーティションを作成し、両方のパーティションがブート時に自動マウントされるように、/etc/fstabに登録します。また、デバイス名(/dev/sda, /dev/sdbなど)はブート時に変わる場合もあるので、UUIDを用いて、fstabaへの設定をおすすめします。

UUID=75f4a210-081e-4572-8f0a-bffb1f3d84c3 swap   swap     defaults                    0  0

UUIDは、デバイスの以下のコマンドで確認出来ます。

root@jetson:~# ls -l /dev/disk/by-uuid
total 0
lrwxrwxrwx 1 root root 10 10月 1 17:41 408b9b27-133c-475d-8b8e-151ebe91e6e9 -> ../../sda2
lrwxrwxrwx 1 root root 10 10月 1 17:41 75f4a210-081e-4572-8f0a-bffb1f3d84c3 -> ../../sda1

各種パッケージ導入

TensorFlow導入

NVIDIAの開発者コミュニティに記載されている内容で、インストールを行います。

https://docs.nvidia.com/deeplearning/frameworks/install-tf-jetson-platform/index.html#install

    1. 前提ソフトをaptコマンドを用いてインストールします。
      $ sudo apt install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev
      
    2. pip3のアップデートを行います。
      $ sudo apt install python3-pip
      $ sudo pip3 install -U pip
    3. NVIDIAの開発サイトからtensorflow-gpuをインストールします。
      $ sudo pip3 install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v42 tensorflow-gpu

インストールコマンド実行により、以下のパッケージがインストールされました。

Successfully installed absl-py-0.8.0 astor-0.8.0 gast-0.2.2 google-pasta-0.1.7 grpcio-1.24.0 h5py-2.10.0 keras-applications-1.0.8 keras-preprocessing-1.1.0 markdown-3.1.1 numpy-1.17.2 protobuf-3.10.0rc1 setuptools-41.2.0 tensorboard-1.14.0 tensorflow-estimator-1.14.0 tensorflow-gpu-1.14.0+nv19.9 termcolor-1.1.0 werkzeug-0.16.0 wrapt-1.11.2

keras導入

インストール自体は 「pip3 install keras」 なのですが、依存関係のあるscipyのインストールに失敗します。scipyインストールに必要なライブラリーを事前にインストールしておきます。
以下インストール失敗時の画面コピーです。
  Downloading https://files.pythonhosted.org/packages/ee/5b/5afcd1c46f97b3c2ac3489dbc95d6ca28eacf8e3634e51f495da68d97f0f/scipy-1.3.1.tar.gz (23.6MB)
     |████████████████████████████████| 23.6MB 20.9MB/s 
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... error
    ERROR: Command errored out with exit status 1:
     command: /usr/bin/python3 /usr/local/lib/python3.6/dist-packages/pip/_vendor/pep517/_in_process.py prepare_metadata_for_build_wheel /tmp/tmp4e1y85sd
         cwd: /tmp/pip-install-_nnfhs_r/scipy
    Complete output (139 lines):
    lapack_opt_info:
    lapack_mkl_info:
    customize UnixCCompiler
      libraries mkl_rt not found in ['/usr/local/lib', '/usr/lib', '/usr/lib/aarch64-linux-gnu']
      NOT AVAILABLE
    
    openblas_lapack_info:
    customize UnixCCompiler
    customize UnixCCompiler
      libraries openblas not found in ['/usr/local/lib', '/usr/lib', '/usr/lib/aarch64-linux-gnu']
      NOT AVAILABLE
    
    openblas_clapack_info:
    customize UnixCCompiler
    customize UnixCCompiler
      libraries openblas,lapack not found in ['/usr/local/lib', '/usr/lib', '/usr/lib/aarch64-linux-gnu']
      NOT AVAILABLE
    
    flame_info:
    customize UnixCCompiler
      libraries flame not found in ['/usr/local/lib', '/usr/lib', '/usr/lib/aarch64-linux-gnu']
      NOT AVAILABLE
    
    atlas_3_10_threads_info:
    Setting PTATLAS=ATLAS
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries tatlas,tatlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib
    customize UnixCCompiler
      libraries tatlas,tatlas not found in /usr/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib/aarch64-linux-gnu
    customize UnixCCompiler
      libraries tatlas,tatlas not found in /usr/lib/aarch64-linux-gnu
    <class 'numpy.distutils.system_info.atlas_3_10_threads_info'>
      NOT AVAILABLE
    
    atlas_3_10_info:
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries satlas,satlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib
    customize UnixCCompiler
      libraries satlas,satlas not found in /usr/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib/aarch64-linux-gnu
    customize UnixCCompiler
      libraries satlas,satlas not found in /usr/lib/aarch64-linux-gnu
    <class 'numpy.distutils.system_info.atlas_3_10_info'>
      NOT AVAILABLE
    
    atlas_threads_info:
    Setting PTATLAS=ATLAS
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries ptf77blas,ptcblas,atlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib
    customize UnixCCompiler
      libraries ptf77blas,ptcblas,atlas not found in /usr/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib/aarch64-linux-gnu
    customize UnixCCompiler
      libraries ptf77blas,ptcblas,atlas not found in /usr/lib/aarch64-linux-gnu
    <class 'numpy.distutils.system_info.atlas_threads_info'>
      NOT AVAILABLE
    
    atlas_info:
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries f77blas,cblas,atlas not found in /usr/local/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib
    customize UnixCCompiler
      libraries f77blas,cblas,atlas not found in /usr/lib
    customize UnixCCompiler
      libraries lapack_atlas not found in /usr/lib/aarch64-linux-gnu
    customize UnixCCompiler
      libraries f77blas,cblas,atlas not found in /usr/lib/aarch64-linux-gnu
    <class 'numpy.distutils.system_info.atlas_info'>
      NOT AVAILABLE
    
    accelerate_info:
      NOT AVAILABLE
    
    lapack_info:
    customize UnixCCompiler
      libraries lapack not found in ['/usr/local/lib', '/usr/lib', '/usr/lib/aarch64-linux-gnu']
      NOT AVAILABLE
    
    lapack_src_info:
      NOT AVAILABLE
    
      NOT AVAILABLE
    
    setup.py:388: UserWarning: Unrecognized setuptools command ('dist_info --egg-base /tmp/pip-install-_nnfhs_r/scipy/pip-wheel-metadata'), proceeding with generating Cython sources and expanding templates
      ' '.join(sys.argv[1:])))
    Running from scipy source directory.
    /usr/local/lib/python3.6/dist-packages/numpy/distutils/system_info.py:1712: UserWarning:
        Lapack (http://www.netlib.org/lapack/) libraries not found.
        Directories to search for the libraries can be specified in the
        numpy/distutils/site.cfg file (section [lapack]) or by setting
        the LAPACK environment variable.
      if getattr(self, '_calc_info_{}'.format(lapack))():
    /usr/local/lib/python3.6/dist-packages/numpy/distutils/system_info.py:1712: UserWarning:
        Lapack (http://www.netlib.org/lapack/) sources not found.
        Directories to search for the sources can be specified in the
        numpy/distutils/site.cfg file (section [lapack_src]) or by setting
        the LAPACK_SRC environment variable.
      if getattr(self, '_calc_info_{}'.format(lapack))():
    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/dist-packages/pip/_vendor/pep517/_in_process.py", line 207, in <module>
        main()
      File "/usr/local/lib/python3.6/dist-packages/pip/_vendor/pep517/_in_process.py", line 197, in main
        json_out['return_val'] = hook(**hook_input['kwargs'])
      File "/usr/local/lib/python3.6/dist-packages/pip/_vendor/pep517/_in_process.py", line 69, in prepare_metadata_for_build_wheel
        return hook(metadata_directory, config_settings)
      File "/usr/local/lib/python3.6/dist-packages/setuptools/build_meta.py", line 156, in prepare_metadata_for_build_wheel
        self.run_setup()
      File "/usr/local/lib/python3.6/dist-packages/setuptools/build_meta.py", line 237, in run_setup
        self).run_setup(setup_script=setup_script)
      File "/usr/local/lib/python3.6/dist-packages/setuptools/build_meta.py", line 142, in run_setup
        exec(compile(code, __file__, 'exec'), locals())
      File "setup.py", line 505, in <module>
        setup_package()
      File "setup.py", line 501, in setup_package
        setup(**metadata)
      File "/usr/local/lib/python3.6/dist-packages/numpy/distutils/core.py", line 137, in setup
        config = configuration()
      File "setup.py", line 403, in configuration
        raise NotFoundError(msg)
    numpy.distutils.system_info.NotFoundError: No lapack/blas resources found.
    ----------------------------------------
ERROR: Command errored out with exit status 1: /usr/bin/python3 /usr/local/lib/python3.6/dist-packages/pip/_vendor/pep517/_in_process.py prepare_metadata_for_build_wheel /tmp/tmp4e1y85sd Check the logs for full command output.

依存ライブラリのインストール

# apt install libatlas-base-dev gfortran

次に、cythonをインストールします。

root@jetson:~# pip3 install -U cython
Collecting cython
Installing collected packages: cython
Successfully installed cython-0.29.13
pip3 install Keras

Kerasインストール後に以下のメッセージが表示されます。

Installing collected packages: scipy, Keras
Successfully installed Keras-2.3.0 scipy-1.3.1

OpenCV導入

NVIDIAのJetson Nanoでは、Open CVインストール向けに各種スクリプトが公開されています。基本的に、公開されているスクリプトを用いれば、簡単にOpenCVを導入することが出来ます。

NVIDIAのCuda対応のOpenCVが、各種バージョン簡単に導入できるのは、非常に助かります。
バージョン3系と4系を複数導入してみましたが、特に問題は起きませんでした。

#!/bin/bash
#
# Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA Corporation is strictly prohibited.
#

if [ "$#" -ne 1 ]; then
    echo "Usage: $0 <Install Folder>"
    exit
fi
folder="$1"
user="nvidia"
passwd="nvidia"

echo "** Remove OpenCV3.3 first"
sudo sudo apt-get purge *libopencv*

echo "** Install requirement"
sudo apt-get update
sudo apt-get install -y build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
sudo apt-get install -y python2.7-dev python3.6-dev python-dev python-numpy python3-numpy
sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
sudo apt-get install -y libv4l-dev v4l-utils qv4l2 v4l2ucp
sudo apt-get install -y curl
sudo apt-get update

echo "** Download opencv-4.0.0"
cd $folder
curl -L https://github.com/opencv/opencv/archive/4.0.0.zip -o opencv-4.0.0.zip
curl -L https://github.com/opencv/opencv_contrib/archive/4.0.0.zip -o opencv_contrib-4.0.0.zip
unzip opencv-4.0.0.zip 
unzip opencv_contrib-4.0.0.zip 
cd opencv-4.0.0/

echo "** Building..."
mkdir release
cd release/
cmake -D WITH_CUDA=ON -D CUDA_ARCH_BIN="5.3" -D CUDA_ARCH_PTX="" -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.0.0/modules -D WITH_GSTREAMER=ON -D WITH_LIBV4L=ON -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
make -j3
sudo make install

echo "** Install opencv-4.0.0 successfully"
echo "** Bye :)"
mkdir opencv
sh install_opencv4.0.0_Nano.sh opencv
(コンパイル/インストールが始まります)

python3-opencv (3.2.0+dfsg-4ubuntu0.1) を設定しています ...
python-opencv (3.2.0+dfsg-4ubuntu0.1) を設定しています ...
libc-bin (2.27-3ubuntu1) のトリガを処理しています ...
** Install opencv-4.1.0 successfully
** Bye 🙂

インストール後の確認

root@jetson:/home/miki# python3
Python 3.6.8 (default, Aug 20 2019, 17:12:48)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.1.0'

created by Rinker
NVIDIA
¥19,000 (2021/08/19 16:46:56時点 Amazon調べ-詳細)