複数のRaspberry Pi(Ubuntu20.04)を有線接続し、さらにPCを無線で接続するネットワーク設定

##はじめに
認識用と制御用にRaspberry Piを2台、ロボットに搭載しようと考えています。
あと、家庭用の無線経由でPC側から指示を送ったりrvizで計測したりということも実現したいです。

そこで、今回はその目標を達成するネットワーク構成と設定方法について書いていきます。 
なお、Raspberry Piのセットアップについては[こちらの記事](https://qiita.com/gtkr/items/cecd0463748c848850b9)にまとめてあります。

##使用デバイス
* Raspberry Pi 3 Model B+

##ネットワーク構成
![multi-raspi-network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653070/6c5286e1-4a70-eb97-d427-92218c8d08b1.png)
Raspberry Pi1とRasberry Pi2は有線接続し、Raspberry Pi1とPCは無線ルーターを経由して接続します。これら3つの端末を同じROSネットワークに参加させるため、Raspberry Pi1を経由してRaspberry Pi2とPCを通信できるように設定します。

##NICの設定(netplan)
###Raspberry Pi1
/etc/netplan/50-cloud-init.yamlを編集します。
Raspberry Pi1は無線と有線の両方を設定します。
また、無線側はDHCPを有効にしているので、予め固定のIP(192.168.1.5)が割り当てられるように無線ルータの設定をしておいてください。

```yaml
network:
    ethernets:
        eth0:
            dhcp4: false
            addresses: [192.168.2.1/24]
            optional: true
    version: 2

    wifis:
        wlan0:
            optional: true
            dhcp4: true
            access-points:
                "アクセスポイント名":
                    password: "パスワード"

```

編集後は以下のコマンドで設定を適用します。
うまく行かない場合は再起動します。

```console
$ sudo netplan apply
$ sudo systemctl daemon-reload
```

ifconfigで以下のように表示されればOKです。

```console
ubuntu@ubuntu:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.1  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::ba27:ebff:fe31:e53e  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:31:e5:3e  txqueuelen 1000  (Ethernet)
        RX packets 5002  bytes 379576 (379.5 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 237  bytes 16350 (16.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 192  bytes 14664 (14.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 192  bytes 14664 (14.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.5  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 240d:1a:368:2400:ba27:ebff:fe64:b06b  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::ba27:ebff:fe64:b06b  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:64:b0:6b  txqueuelen 1000  (Ethernet)
        RX packets 1399  bytes 100319 (100.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5855  bytes 678734 (678.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

###Raspberry Pi2
同じく/etc/netplan/50-cloud-init.yamlを編集します。

```yaml
network:
    ethernets:
        eth0:
            dhcp4: false
            addresses: [192.168.2.2/24]
            optional: true
    version: 2
```
編集後はRaspberry Pi1と同様に設定を適用します。
ifconfigで以下のように表示されればOKです。

```console
ubuntu@ubuntu:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.1  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::ba27:ebff:fe31:e53e  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:31:e5:3e  txqueuelen 1000  (Ethernet)
        RX packets 5002  bytes 379576 (379.5 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 237  bytes 16350 (16.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 192  bytes 14664 (14.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 192  bytes 14664 (14.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

###PC
Raspberry1と同じように固定のIP(192.168.1.4)が割り当てられるように無線ルータの設定をしておいてください。

##IPフォワーディング、ルーティングの設定
[こちらの記事](https://qiita.com/KazukiTakahashi/items/5416c0df40ee6cd37f89)を参考にしています。

###Raspberry Pi1
/etc/sysctl.conf内の

```conf
#net.ipv4.ip_forward=1
```
のコメントアウトを解除し、IPフォワードを有効にします。
再起動すると、上記の設定が適用されます。

###Raspberry Pi2
既にデフォルトゲートウェイがRaspberryPi1なので、特に追加の設定は不要です。

###PC
RaspberryPi1経由でRaspberryPi2に通信するようにルート設定を追加します。

```console
$ sudo ip route add 192.168.2.0/24 via 192.168.1.5 dev wlp4s0
```

この設定方法だと永続化はしませんが、普段から使うものでもないので、必要なときだけ上記コマンドを打てばいいかと思います。

###動作確認
####PC

```console
$ ping 192.168.2.2
PING 192.168.2.2 (192.168.2.2) 56(84) バイトのデータ
64 バイト応答 送信元 192.168.2.2: icmp_seq=1 ttl=63 時間=211 ミリ秒
```

####RaspberryPi2

```consol
$ ping 192.168.1.4
PING 192.168.1.4 (192.168.1.4) 56(84) bytes of data.
64 bytes from 192.168.1.4: icmp_seq=1 ttl=63 time=3.07 ms
```

##ROSの設定
###Raspberry Pi1
Raspberry Pi1をROS Masterにするので、ROS_IPだけ設定します。

```console
$ echo "export ROS_IP=192.168.2.1" >> .bashrc
$ source .bashrc
```

###Raspberry Pi2
ROS_IPに加えて、Raspberry Pi1をROS Masterに指定するためROS_MASTER_URIも設定します。

```console
$ echo "export ROS_IP=192.168.2.2" >> .bashrc
$ echo "export ROS_MASTER_URI=http://192.168.2.1:11311" >> .bashrc
$ source .bashrc
```

###PC
Raspberry Pi2と同様に設定します。

```console
$ echo "export ROS_IP=192.168.1.4" >> .bashrc
$ echo "export ROS_MASTER_URI=http://192.168.2.1:11311" >> .bashrc
$ source .bashrc
```

##最終確認
###Raspberry Pi1

```
$ roscore
```

###Raspberry Pi2

```
$ rostopic echo /test
```

###PC

```
$ rostopic pub /test std_msgs/Int32 1
```

Rasberry Pi2で「1」が表示されれば通信OKです。