Raspberry Pi 4BにUbuntu 18.04をインストールし，ROS Melodicを動かすまで

# 初めに
この記事は[機械系 Advent Calendar 2020](https://adventar.org/calendars/5201)の記事です.
機情B3の自主プロにあたって，ラズパイの上でROSを走らせるつもりでインストールしたのですが，何気に躓くポイントが多かったのでその手順を残しておきます．今後，同じようなことをしようとした誰かの役に立てば嬉しいです(どちらかというとROSのインストールというより，その前のセットアップ部分の内容が大きいです)．

Raspberry Pi 4B にUbuntu 18.04を入れて，その上にROSをインストールしていきます．
<img width="600" alt="Screen Shot 2020-05-21 at 5.31.42.png" src="https://www.raspberrypi.org/homepage-9df4b/homepage-9df4b/static/opengraph-14d75a9de2682c48a368048e0e8c3410.png">
(https://www.raspberrypi.org/products/raspberry-pi-4-model-b/?resellerType=home)
# 必要なもの

- [Raspberry Pi 4 Model B](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/?resellerType=home)
- micro SDカード
- SDカードリーダ
- ディスプレイ
- キーボード
- 作業用PC(学科PCなど)

今後SSHでログインするのであれば，ディスプレイとキーボードは最初のセットアップのみ必要．

# Ubuntu 18.04 LTSのインストール
[Cononical公式サイト](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)にはUbuntu Serverを入れるものなので，今回の場合は以下のサイトに従ってUbuntu LTSをインストールします．(Ubuntu Serverを入れてからその後にDesktopをインストールする方法も上記のサイトに載っていますが，今回は実践しません．)

- [Install Ubuntu 18.04.4 LTS on your Raspberry Pi board](https://maker.pro/raspberry-pi/projects/install-ubuntu-18044-lts-on-your-raspberry-pi-board)

**ただ，上のサイトのイメージファイルのリンクはUbuntu 20.04 になっているため，SDカードへの書き込みまでは[このサイト](https://rt-net.jp/mobility/archives/12773)の通り行うと良いです．**

ネットワークの設定までできたら，`ifconfig` と打ち込んで，ラズパイのIPアドレスを確認しておきましょう(後のSSHログイン時に必要になります)．また，可能ならネットワークのプロバイダの設定からIPアドレスを固定しておくと便利です[^1]

また，wifiの設定が正しく行われ，外部のネットワークに繋がっているかを確認するため，

```bash
$ ping 8.8.8.8
```
としてGoogleを叩くなどしてみると良いでしょう．ちゃんと応答が返ってくれば大丈夫です．

ここまでできたら，

```bash
$ sudo poweroff
```
としてラズパイの電源を切り，ディスプレイやキーボードを取り外してオッケーです．

## Gnome Desktopのインストール
今後SSHログインで外部PCからしか利用しないなら，上記のインストール手順のうち[デスクトップのインストール](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#5-install-a-desktop)はスキップしても大丈夫ですが，もしラズパイ本体を学科PCのようにしてGUIで操作したいと思ったらデスクトップをインストールする必要があります．
ただ，上記の公式サイトにもGnome Desktopのインストールは載っていないですし，実際XubuntuやLubuntuのように

```bash
$ sudo apt install ubuntu-desktop
```
としても上手くいかなかったので，下のように

```bash
$ sudo apt install tasksel
$ sudo tasksel install ubuntu-desktop
```
としてtaskselを用いるとインストールできました．(正直ここは「色々試したら上手くいった案件」なので，中身を理解しているわけではありません...) 

###追記(03/17/2021)
このときに試したら`sudo apt install ubuntu-desktop`で上手くいきました．初めに

```bash
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)  
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
```
とエラーが出たのですが，[このサイト](https://askubuntu.com/questions/1109982/e-could-not-get-lock-var-lib-dpkg-lock-frontend-open-11-resource-temporari)に従って

```bash
$ sudo rm /var/lib/apt/lists/lock
$ sudo rm /var/cache/apt/archives/lock
$ sudo rm /var/lib/dpkg/lock*
$ sudo dpkg --configure -a
```
とすることで解決しました．

## 細かな設定(個人的な趣味)

- 日本語キーボードレイアウトに変更  
デフォルトだとUS配列になっているので，[このサイト](https://qiita.com/vochicong/items/6452ac54bde56b0e0bb3#%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E4%BD%BF%E3%81%86%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A)に従って変更
- デフォルトのエディタをGNU nanoからVimに変更  
bashのデフォルトエディタがnanoになっているので，以下のコマンドを打ってVimに変更．

```bash
$ sudo update-alternatives --set editor /usr/bin/vim.basic
```
- 矢印キーによるコマンド履歴補完  
bashのコマンド履歴補完が微妙なので，この[サイト](https://qiita.com/wankoromaru/items/92a85bd84bb3e3a08c71)に従って ~/.bashrc にその設定を追加．これによって，ターミナルのコマンド履歴を遡りやすくなる．

# SSHの設定
前項までで，同じネットワークに接続された作業用PCから，

```bash
$ ssh ubuntu@<IPアドレス> -p 22
```
としてパスワードを入力すればSSHでログインができるはずです(ラズパイの初期設定でポート番号が22であるため)．

ラズパイを電源に接続してすぐはネットワークに接続されていないかもしれないので，SSHが通らないとき`ping`コマンドを使ってネットワーク状況を確認しましょう．

```bash
$ ping <IPアドレス>
```

## セキュリティの強化
上記まででネットワークの設定が完了すれば， `ifconfig` で確認されるIPアドレスを使ってSSHログインはできるのですが，ユーザ名が"ubuntu", ポート番号が22というデフォルト設定のままで，セキュリティがガバガバなので，以下の1つ目のサイトの①~③までを参考に，新しいユーザの登録・ポート番号の変更を行います．

- [買ったらまず実施！RaspberryPiのセキュリティ対策](https://qiita.com/c60evaporator/items/ebe9c6e8a445fed859dc)
- [Securing your Raspberry Pi](https://www.raspberrypi.org/documentation/configuration/security.md) ←公式ページも随時参考に

設定が完了したら，

```bash
$ ssh <ユーザ名>@<IPアドレス> -p <ポート番号>
$ # 例 ssh taro@111.111.11.11 -p 50
```
と打って，設定したパスワードを打ち込めばラズパイにログインできます．

#### SSH接続を公開鍵認証に
上記のSSH接続はパスワード認証で実施されている(SSHログインのときにパスワードを打ち込んでログインする)のですが，これをよりセキュリティ性の高い公開鍵認証に変更します．前項でも参照した[このサイト](https://qiita.com/c60evaporator/items/ebe9c6e8a445fed859dc)の④を参考にしながら，以下のサイトに則って進めていきます．

- [Passwordless SSH access](https://www.raspberrypi.org/documentation/remote-access/ssh/passwordless.md) ←公式サイト
- [Raspberry Piに公開鍵認証を使ってssh接続する](https://tool-lab.com/raspi-key-authentication-over-ssh/)

<img width="400" alt="Screen Shot 2020-05-21 at 5.31.42.png" src="https://tool-lab.com/wp-content/uploads/2013/11/raspi-ssh-key-preparation.png">
(https://tool-lab.com/raspi-key-authentication-over-ssh/)

#### 秘密鍵と公開鍵の作成(作業用PC側)
ラズパイに接続したい作業用PCに既に秘密鍵と公開鍵が生成されているか確認します．`~/.ssh/` 以下に `id_rsa.pub` か `id_dsa.pub` というファイルがあれば以前に生成した印です．(そのPCでGitHubにSSHキー登録などしていれば，その際に生成しているはずです．)
もし無ければ

```bash
$ ssh-keygen
```
として作成しましょう．

#### 公開鍵をラズパイにコピー
上で作った公開鍵をラズパイにコピーします．作業用PC側で

```bash
$ ssh-copy-id <ユーザ名>@<IPアドレス> -p <ポート番号>
```
とするとSSH経由で，ラズパイ側の `~/.ssh/authorized_keys` というファイルの中に，作業用PCの公開鍵 `~/.ssh/id_rsa.pub` の中身がコピーされるはずなので，それを確認します．
これができていれば，

```bash
$ ssh <ユーザ名>@<IPアドレス> -i <秘密鍵ファイル> -p <ポート番号>
$ # 例 ssh taro@111.111.11.11 -i ~/.ssh/id_rsa -p 50
```
としてログインしたときに，パスワード入力なしでログインできるはずです．

*＊この方法で上手くいかない場合は，[このサイト](https://qiita.com/c60evaporator/items/ebe9c6e8a445fed859dc)にある方法でやってみましょう．*

#### 公開鍵認証のみを許可(パスワード認証の無効化)
上記までで，パスワード認証に加えて公開鍵認証を許可することができました．ということは，未だパスワード認証はできてしまうので，セキュリティが向上したわけではありません．よってパスワード認証を無効化します．
ラズパイ側で

```bash
$ sudo vi /etc/ssh/sshd_confg
```
としてsudo権限でこのファイルを編集し，真ん中付近に記載されている
「#PasswordAuthentication yes」を「PasswordAuthentication no」に変更して保存します．

ここまでしたら**ラズパイを再起動**(`$ sudo reboot`) 又は

```bash
$ sudo /etc/init.d/ssh restart
```
としてSSHサーバを再起動しましょう．先程公開鍵を登録したPCからはSSHログインできますが，他のPCから同様にログインしようとしても， `Permission denied (publickey).` と表示されてログインできないはずです．
こうしてセキュリティ対策ができました．SSH接続するPCを増やしたい場合は，同じ要領で公開鍵を登録すればいいだけです．

#### configファイルの作成
ここまでで基本的な設定は終了しましたが，SSHログインの度に毎回毎回IPアドレスやポート番号を打ち込むのは面倒です．そこで，それらをまとめたconfigファイルを作っておくと便利です．実はこのファイルは，後に設定す(ラズパイの初期設定でポート番号が22であるため)る，VSCodeからSSHログインするために必要なので，ここで作っておきます．
作業用PC側で，`~/.ssh/config` というファイルを作成し(既に存在する場合は追記する形で)

```bash
Host <ホスト名>
	HostName <IPアドレス>
	User <ユーザ名>
	Port <ポート番号>
	IdentityFile <秘密鍵ファイル>
```

```bash:例
Host raspi
	HostName 111.111.11.11
	User taro
	Port 50
	IdentityFile ~/.ssh/id_rsa
```
と記述します．
そうすれば，次回以降は

```bash
$ ssh <ホスト名>
```
と打ち込むだけでSSHログインすることができます．

## VSCodeからSSHで遠隔操作するための設定
以下の記事を参考に，VSCodeに"[Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)"という拡張機能を追加します．
先程作成したconfigファイルのおかげで，SSH接続が行えるようになります．

- [【正式リリース版】VS CodeのRemote DevelopmentでRaspberry Pi内のファイルを編集する](https://qiita.com/hukatama024e/items/9f96730381f0a34c6da6)
- [VSCodeのSSH接続機能で、RaspberryPi内のコードを編集してデバッグ](https://qiita.com/c60evaporator/items/26ab9cfb9cd36facc8fd)

# ROS Melodicのインストール
[http://wiki.ros.org/melodic/Installation/Ubuntu](http://wiki.ros.org/melodic/Installation/Ubuntu)に従ってインストールしていけばいいです．

### Ubuntu repositoriesの許可
Ubuntuでは `apt update` や `apt upgrade` によって `/etc/apt/source.list` を参照し，その中に記載されている[リポジトリ](https://help.ubuntu.com/community/Repositories/Ubuntu)の管理を行います．リポジトリにはその信頼度やライセンスによって"Main", "Restricted", "Universe", "Multiverse"の4種類に分かれており，まずはこれを全て許可する必要があります．
現在許可されているリポジトリの種類を見るためには以下のコマンドを打てばよく，

```bash
$ grep ^deb /etc/apt/sources.list
```
コマンド出力に記載のあるリポジトリの種類が許可されていることを意味します．

心配ならば

```bash
$ sudo add-apt-repository main
$ sudo add-apt-repository restricted
$ sudo add-apt-repository universe
$ sudo add-apt-repository multiverse
```
とすれば，改めてそれぞれを許可することができます．

### ROS Melodicのインストール
ここからもwikiに従って以下のように実行すれば良いです．(wikiがアップデートされているかもしれないので，随時確認してください．)

```bash
# packages.ros.org からのパッケージの許可
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
# packages.ros.org の公開鍵の取得
$ sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
# Debian packageのアップデートの確認
$ sudo apt update
```

あとは，自分の用途や好みに従って以下のうち，好きなものをインストールすれば良いです．僕はラズパイにUbuntuデスクトップをインストールしませんでしたが，なんとなく一番上のdesktop-fullをインストールしました．

```bash
# Desktop-Full Install: (Recommended) : ROS, rqt, rviz, robot-generic libraries, 2D/3D simulators and 2D/3D perception
$ sudo apt install ros-melodic-desktop-full
# Desktop Install: ROS, rqt, rviz, and robot-generic libraries
$ sudo apt install ros-melodic-desktop
# ROS-Base: (Bare Bones) ROS package, build, and communication libraries. No GUI tools.
$ sudo apt install ros-melodic-ros-base
```

### 確認
正しくインストールがなされたかを確認しておきましょう．ROSコマンドを利用するために

```bash
$ source /opt/ros/melodic/setup.bash
```
としてソースを通し(もしくは `~/.bashrc` に記述してもいいです)，別々のターミナルから

```bash
# それぞれ別々のターミナルで
$ roscore
$ rosrun roscpp_tutorials talker
$ rosrun roscpp_turorials listener
```
として実行してみます．
以下のように出力されればROSプログラムが正しく実行され，ノード間で通信できていることを意味しています．

<img width="700" alt="Screen Shot 2020-05-21 at 5.31.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505262/6e7b2a12-2fc9-6a96-83dc-f4328969b3a2.png">
<img width="700" alt="Screen Shot 2020-05-21 at 5.31.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505262/80dde1e8-1b88-f5b9-bbe4-a030ad4b3206.png">






# I2C通信の有効化，GPIOピンの設定
ラズパイの良いところは，小型である上にGPIOピンを使えることですが，通常のUbuntu 18.04にはGPIOピンを使うためのドライバが入っていないので，何かの方法でインストールしなくてはいけません．
僕はまだ行っていませんが，この辺りの記事が参考になるのではないかと思っています．できたら追記します．もしくは，できた人がいれば教えてください．

- [Raspberry Pi & Ubuntu 18.04 でGPIOを使う](https://qiita.com/myasu/items/e3f81b2826ed5797a040)
- [Raspberry Pi 4 + ROS2 で、最低限のロボットプログラムを作る準備](https://qiita.com/nasu_onigiri/items/39a0b16107e8e7fbbbe1)
- [Ubuntu 18.04 を入れたRaspberryPi 3 Model B+でGPIOを有効化する](https://qiita.com/frafrakki/items/3b14b0a318039e51dadd)
- [電子工作ファン向けのRaspberry Pi・セットアップ（Ubuntu 20.04LTS編）
](https://qiita.com/myasu/items/5b122c782c5a616d8b60)


[^1]: `/etc/netplan/50-cloud-init.yaml` の中の `dhcp4: true` という記述は[DHCPサーバ](https://wa3.i-3-i.info/word1960.html)を利用することを意味しています．DHCPサーバはネットワークに接続されている機器に自動的にIPアドレスを割り振るものなので，`ifconfig`と打ってそのIPアドレスを確認する必要があります．また，基本的には毎回同じIPアドレスに割り振られるそうですが，特定のIPアドレスに確定させたい場合はプロバイダに確認して設定する必要があります．(僕はNECのwifiを利用しているので，[このサイト](https://www.aterm.jp/function/wg2600hp3/guide/dhcpfixedset.html)から設定できるらしいです．)