Jetson TX2にJetpack 3.3とROSをインストールして、LRFも認識させてみた

どうもはじめまして、ハルヒのSS以外でインターネットにまとまった長文を投稿するのは初めてのぞはるです。

2018年度のNHK学生ロボコンでは、多くの大学が **LRF(Laser Range Finder : レーザー測域センサ)** を使用した自己位置推定を試みていましたね。真面目にUARTを使って通信するとなると結構、いや、かなり面倒くさそうなLRFですが、それでもロボットの多くに搭載されたのはおそらくロボット用ミドルウェアである **ROS(Robot Operating System)** の普及によるところが大きいのではないでしょうか。

というわけで、この記事ではJetson TX2にJetpack 3.0とROS kineticをインストールし、代表的なLRFであるHokuyo UTM-30LXをJetsonに認識させるまでの手順を詳細に解説します。ここではJetpackのインストールに **Ubuntu 18.04 64-bit** を使用しました。**Ubuntu 16.04/14.04 64-bit** であればほぼ同じ手順でインストールが可能かと思われますが、一方でJetpackインストーラが対応していない32-bit OSでのインストール方法については解説していません、すみません。

# 用意するもの
* UbuntuがインストールされたPC
* Jetson TX2 Developer Kit
* Hokuyo UTM-30LX

# 注意
* コンソールに入力するコマンドのうち、`$` から始まるものは通常の権限、 `#` から始まるものはroot権限で実行してください。
* これより先ではJetson TX2のことを **Jetson** 、Hokuyo UTM-30LXのことを **LRF** と表記します。

# JetPack 3.3のインストール
Jetsonを電源に接続し、 **POWER** ボタンを押して起動すればUbuntuが立ち上がります。しかしこのままでは開発を行うには適さないので、Jetpackをインストールする必要があります。

## 前準備
Jetsonとホストとなるコンピューターで通信が行える状態にする必要があります。最も簡単な方法は共通のWi-Fiスポット、例えば自宅であれば自宅用のLANに接続することでしょう。
ちなみに、この際IPの固定なども行っておくと後々SSHで通信するときなどに便利ですが、その方法はここでは割愛します。

## インストール作業
インストール作業は概ね次のページの方法の通りです。

> JetsonTX2初期セットアップ(Jetpack)からサンプルのコンパイルまでの手順 - Qiita

> https://qiita.com/akrian/items/54c321bfa95d8eaef17d

1. https://developer.nvidia.com/embedded/jetpack にアクセスして、「Download Jetpack 3.3」と書かれたボタンをクリックします。
(現在は開発版である4.1がリリースされているようですが、3.3をインストールするのが無難でしょう)
1. JetPackという文字をクリックすると、ツリービューが開きます。その中に「 **Ubuntu [64-bit]** 」と書かれている部分を探して、クリックします。
1. NVIDIA Developer Programへのログイン画面が出てきますので、まだアカウントを作成していない方は「**Join**」でアカウントを作成し、アカウントを既に持っている人は「**Login**」でログインして、ダウンロードを続行してください。
1. ダウンロードが完了したら、おそらく`~/Downloads`の中にインストーラが入っているはずなので、端末を開いて

    ```
    $ cd ~/Downloads
    ```
と打ち込んで、`~/Downloads`に移動しましょう。
1. ダウンロードしただけではまだ実行できないのが困りものです。インストーラに実行権限を付与しましょう。

    ```
    $ chmod +x JetPack-L4T-3.3-linux-x64_b39.run
    ```
1. インストーラを実行します。

    ```
    $ ./JetPack-L4T-3.3-linux-x64_b39.run
    ```
この際いくつかUbuntu 18.04をサポートしていないという旨の警告が出てきますが、無視して続行します。その結果インストーラが終了してしまうときはどうやらlibpng12が足りないそうなので、次に示すコマンドを実行すれば解決します。

    ```
    # wget -q -O /tmp/libpng12.deb http://mirrors.kernel.org/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.54-1ubuntu1_amd64.deb
    # dpkg -i /tmp/libpng12.deb
    # rm /tmp/libpng12.deb
    ```
( <https://devtalk.nvidia.com/default/topic/1033194/installing-jetpack-3-2-on-ubuntu-18-04/> )より引用
1. NVIDIA's Privacy Policy.を読んだ上で、チェックボックスのどちらかに印を入れて、次に進みます。インストール用ファイルが置かれるフォルダを変更したい場合は、この段階で指定しましょう。
1. **Jetson TX2** のところのラジオボタンをオンにして、次に進みます。そうしたら管理者権限を要求されるので、パスワードを入力してください。
1. 一度ウィンドウが閉じて、Jetpack 3.3 Components Managerが開きます。インストールするパッケージの設定をここで行いますが、デフォルトのまま何も変更せずに、次へと進みます。
1. 利用規約やライセンスの一覧が出てきます。目を通した上で、 **Accept all** を押して次に進みます。
1. パッケージのダウンロード、コンパイルが開始されます。しばらく待ちましょう。
1. Jetsonのインターネットへの接続方法を尋ねられるので、自分の環境に合っている方を選択しましょう。JetsonがWiFiなどに接続されている場合は上の「 **Device accesses Internet via same router/switch** 」を選択します。

    ![01 Network_Layout.jpg](https://qiita-image-store.s3.amazonaws.com/0/275739/dfabbec2-bd1f-1655-170d-545193066037.jpeg)

1. インターネットに接続するインターフェースを尋ねられるので、これも自分の環境に合っている方を選択しましょう。
    1. 前項で「 **Device accesses Internet via same router/switch** 」を選択した場合

        ![02 Network_Interface_Selection1.jpg](https://qiita-image-store.s3.amazonaws.com/0/275739/e598303c-ab6a-08ba-4812-a2864377a0af.jpeg)

    これはJetson側の接続インターフェースではなく、「Jetson TX2と同じルーター・スイッチングハブに接続しているこのコンピューターのインターネットインターフェース」を指定します。おそらくeth0またはwlan0になるでしょう
    1. 前項で「 **Device get IP assigned by DHCP server on host and access Internet via host machine** 」を選択した場合

       ![03 Network_Interface_Selection2.jpg](https://qiita-image-store.s3.amazonaws.com/0/275739/46f7447c-8f1e-ba30-1398-27220d955e0f.jpeg)

    ホスト側（このコンピュータのことです）とJetson側のインターネットインターフェースの両方を指定する必要があります。
1. この後行われる操作の一覧が表示されます。次へと進みましょう。
    ![04 Post_Installation.jpg](https://qiita-image-store.s3.amazonaws.com/0/275739/e290c276-94f1-00b3-4a7d-dba1ced8f09d.jpeg)

1. インストーラのウィンドウが閉じて、コンソール画面が表示されます。コンソール画面にはJetsonをUSBリカバリーモードで起動させる方法が書かれています。
    ![05 Instruction_Of_Setup.jpg](https://qiita-image-store.s3.amazonaws.com/0/275739/7acf6709-b961-67f3-7e2b-c6f25c12a2b6.jpeg)

    1. Jetsonの電源を落とします。サスペンド状態やスリープモードだといけないので、電源ケーブルが接続されていたら一度引き抜きましょう。
    1. 付属のUSBケーブルの、Micro-B端子側をJetsonに、もう一方をこのコンピュータのUSBポートに接続します。
    1. Jetsonに電源ケーブルを接続します。
    1. Jetson本体の **POWER** ボタンを押した後に、同じくJetson本体の **FORCE RECOVERY** ボタンを押さえながら **RESET** ボタンを一度押します。これでJetsonがUSBリカバリーモードで起動されます。
    1. このコンピュータで

        ```
        $ lsusb
        ```
    を使用して、Nvidia Corpと書かれた行が存在すれば、正しくUSBリカバリーモードに入っています。
1. Enterキーを押すと、OSの書き込みが開始されます。かなりの時間がかかりますので、気長に待ちましょう。
1. OSの書き込みが終了すると、次のような画面が表示されます。Finishを押してJetpackのインストールは完了です。
    ![06 Finish.jpg](https://qiita-image-store.s3.amazonaws.com/0/275739/697004af-3dec-3fdf-e13c-46cfa86a2464.jpeg)

# ROSのインストール
Jetpack 3.3でインストールされるOSがUbuntu 16.04なので、インストールするROSのバージョンはkineticとなります。特に通常のインストール作業と違う点は存在しないので、リンク先の指示通りにインストールしてみてください。

> kinetic Installation Ubuntu - ROS Wiki
> http://wiki.ros.org/ja/kinetic/Installation/Ubuntu

# カーネルの再コンパイル
ROSもインストールできたので、とうとう地図生成…と行きたいところですが、今のJetsonにLRFを接続してもUSBデバイスとして認識されません。この問題を解決するためには、OSのカーネルを再コンパイルする必要があります。以下では、専用のツールを用いてカーネルを再コンパイルする方法を紹介します。

> 参考にしたもの（ほぼそのまま）

> 解説動画
> > https://www.youtube.com/watch?v=fxWObd1nK4s&t=0s&list=PLJ_Ht8ReE3Z0bEqO15-V3R_pV7WOB4VmP&index=2

> 解説ページ
>>  https://www.jetsonhacks.com/2017/07/31/build-kernel-ttyacm-module-nvidia-jetson-tx2/

次に示す作業は、Jetsonにディスプレイを接続、またはホスト側のコンピュータからリモートデスクトップ接続をして行ってください。

1. カーネルの再コンパイルはかなり重い処理なので、まずは最適化のためプロセッサの設定を変更します。

    ```
    $ sudo nvpmodel -m 0
    ```
1. カーネル再ビルド用のツールをダウンロードします。

    ```
    $ git clone https://github.com/jetsonhacks/buildJetsonTX2Kernel
    ```
1. カーネルのソースコードをダウンロードします。

    ```
    $ cd buildJetsonTX2Kernel
    $ ./getKernelSources.sh
    ```
1. ソースコードがダウンロードされた後に、そのまま自動でカーネルの設定画面が開きます。
    1. `General Setup` の項をクリックして、右側に現れたオプションの中にある `Local version` の項目を`-(好きな文字列)` にしてください。(例： `-jetsonbot-v0.1` )
    1. `USB Modem (CDC ACM) support` 、`
CONFIG_USB_ACM`
    の二つを有効化させてください。 `Ctrl + F` で項目を検索することができます。
    1. 変更が完了したら、`[File]->[Save]` で設定を保存して終了してください。
1. カーネルをビルドします。全ての作業が完了するまで約11分程かかります。

    ```
    $ ./makeKernel.sh
    ```
1. 完成したカーネルをインストールします。

    ```
    $ ./copyImage.sh
    ```
1. 再起動します

    ```
    $ reboot
    ```

# LRFの確認
LRFを接続した上で、

```
$ ls -l /dev/ | grep ttyACM
```

で検索して、結果が出てきたらLRFの認識に成功しています。

# 終わりに
使用したことのあるLRFが北陽のURGしか無いために、このような中途半端な内容になってしまいましたが、年明けまでには、北陽のURGとROSの連携、そしてそれを電源投入時に自動起動する方法などを解説した内容をここに追記したいと考えています。(2018/12/22)