ドローンを動かす 実機・Raspberry Pi編

# はじめに
このページは，

[ドローン操作システムを作ろう](https://qiita.com/hsgucci/items/86eedb5555b4234ee0e7)

の１ページです．
全体を見たい場合は上記ページへお戻りください．

# 概要

前回までに，dronekit-sitl（シミュレータ）とPixhawk(実際のフライトコントローラ)を動かしてみました．
今回は，Pixhawkを搭載したドローンを動かしてみたいと思います．

# システム構成
システム構成は図のようになります．
Wi-Fiを使って，ドローンとＰＣとの通信を行います．
「SSHでRaspberry Piにログインする」という形で制御してみます．
![lan_system.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/a514b9a2-9ef3-ea2d-d630-68cb5a6d15f9.png)

IPアドレスは仮に与えたものなので，
適宜，自分の使う無線LANに合わせて読み替えてください．

**余談**
今回はLAN(Local Area Network)なので，あくまでもローカルでの通信です．
本企画の最終目標はグローバルネット(WAN)を通じて制御することです．

例えば，「夜空のLEDドローンアート」では，ローカルでの通信で十分ですね．
(何百台の無線機の輻輳が問題になりますが)

一方，ドローン輸送などの目視外飛行ではグローバルが必須でしょう．

ローカルで十分か，グローバルが必要か，目的に応じて検討する必要があります．


# 準備するもの

ArdupilotのGUIDEDモードを利用するには，GPSで位置が取れている必要があります．
　　[フライトモード概要](http://ardupilot.org/copter/docs/flight-modes.html)
従って，GPSの効かない屋内で実験することはできません．
屋外で実験するためには，ノートパソコンなどの電源を気にせず起動できるコンピュータが必要です．

## 準備する機材

・SSHクライアントのあるノートＰＣ
　　このＰＣからRaspberry PiにSSHでリモートログインし，プログラムを実行します．
　　OSがLinuxである必要はありません．WindowsでもTera Term等のSSHクライアントを利用できます．

・無線LANアクセスポイント
　　ノートＰＣとRaspberry Piは同じローカルエリアネットワーク(LAN)に属している必要があります．
　　ポケットWi-Fiのような無線ルータでもかまいません．(**ポケットルーターは通信距離が短いので注意**)
　　アドホックで接続しても良いのですが，設定が大変なので．
　
・Raspberry Pi 3B または 3B+
　　今回は無線でSSHログインするので，無線LAN搭載の3B以上とさせてもらいました．
　　USBドングルの無線LANを用いれば，2でも大丈夫かと思います．
　　(**Raspberry Piの内蔵アンテナは通信距離が10m程度なので注意**)


・フライトコントローラ： Pixhawkシリーズ．ただし少なくとも1つはテレメトリ(Telem)ポートを持っていること．　

・ファームウェア： ArduPilot(ArduCopter)．PX4の方は未確認です．

・ドローン本体
　　上記のRaspberry Piを搭載してください．
　　おそらく対角モータ軸間距離450mm以上のサイズの機体になると思います。
　　250サイズにRaspberry Pi Zero Wでもいけそうですが、試したことはありません。
　　**<font color="blue">ラジコン受信機やテレメトリ装置は外さず、搭載したままにしておいてください．
　　プログラム暴走時の保険です。</font>**

・Raspberr Pi用の電源
　　ドローンのバッテリーから別のBECで5V作るか、
　　携帯用モバイルバッテリーなどの別の5V電源を用意してください。
　　**<font color="red">PixhawkのTelemの5V(fromパワーモジュール)を供給するのは危険です．</font>**
　　参考例：5V BEC 


## 参考
参考として，本企画用に作製した**Raspberry Pi 3搭載のF450互換機**を示します．
![my450.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/7b50bf37-89eb-8ef2-8d9a-bd0f71e874bf.png)
無理やりRaspberry Pi3の上にPixhawkを載せています(^^;)
送信機はT10J，テレメトリはXBee S2Bです．


イームズのこの製品とほぼ同じ内容です．これにRaspberry Piを追加してください．(Pixhawk1系でもPixhawk Miniでも同じように使えます)
　　[LAB445 ドローン組立キット フルセット](https://store.shopping.yahoo.co.jp/elab-store/lab001.html)


他にも，
**Pixhawk2とRaspberry Pi3を積んだ900サイズ機**
![pixhawk2_raspberrypi3_900.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/beac901c-2c4d-d447-41e5-371401cd11e6.png)

**Navio+やNavio2(Raspberry Pi3)を積んだF550**
![navio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/1dc6ba20-a07b-7c86-86b9-5aa4d2d6da84.png)

**Pixhawk MiniとNano Piを積んだTurnigy Talon トライコプター**
![tricopter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/020b539f-b226-ada7-d9f2-05384c4bd56c.png)
などで試しています．


## 実験する場所

改正航空法に抵触しない場所・時間で実験を行いましょう．

もちろん，[DIPS](https://www.dips.mlit.go.jp/portal/)で申請しても良いのですが，
Raspberry Piの搭載などで機体を改変するたびに再申請が必要になるので，大変です．
DJIのような完成品は改造しないので楽です．
しかし自作機を徐々に開発していく場合には都度申請が必要になるのです．

DIDについては以下のページを見るか，
　[人口集中地区（DID） 平成27年](http://maps.gsi.go.jp/#9/35.906015/139.623528/&base=std&ls=std%7Cdid2015&blend=0&disp=11&lcd=did2010&vs=c1j0l0u0t0z0r0f0&d=vl)
「ドローンフライトナビ」「ドローン飛行チェック」「楽天AirMap」などのスマホアプリを利用してください．
本企画でも将来的にDIDの表示機能を持たせようと思います．



# SSHクライアントのあるノートＰＣの準備

Linuxであれば，SSHクライアントの機能はデフォルトでインストールされているはずです．
あるいは「Putty」などのGUIアプリケーションを使っても良いです．

Windowsであれば，「Tera Term」「Putty」などのSSHクライアントソフトをインストールしてください．



# Raspberry Piのセットアップ

Raspberry PiのOSには，公式のRaspbianを使用します．

## OSのダウンロードとSDカードの準備
Raspbianは2019年4月から，Full，標準，Liteの３種類になりました．(以前はFullとLiteの２種類)
今回は標準版を使います．FullだとOfficeやマインクラフトなど不要なソフトがディスク容量を圧迫するからです．
(空飛ぶドローンにデスクトップ画面は不要なので，本来はLiteを使いたいところですが，その場合は様々な依存関係を自力で解決する必要があり，ハードルが高くなります．)

[公式ページ](https://www.raspberrypi.org/downloads/raspbian/)から，標準版である
「Raspbian Stretch with desktop」
をダウンロードしてください．
![raspbian_standard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/4de98dc3-1f30-6056-58dc-0f9808f46f4b.png)


ダウンロードしたイメージは，

Win32 Disk Imagerの紹介ページ(参考)
https://forest.watch.impress.co.jp/docs/review/1067836.html

Etcherの紹介ページ(参考)
https://raspi-japan.com/sd-format-etcher

などを利用してマイクロSDカードへ書き込んでください．

## Raspbianの初期設定
最近のRaspbianは，初回起動時にウィザード形式で初期設定が出るようになっています．

・無線LANの接続先は，ノートＰＣと同じアクセスポイントにしてください．

・ＯＳの更新(`sudo apt update`と`sudo apt upgrade`)もウィザードでやってくれるようになっています．

## シリアルポートの有効化
Raspberry Piに標準装備されているシリアルポート(UART)をPixhawkに繋ぐので，
デフォルトでは[無効]になっているシリアルポートを[有効]にする必要があります．

**<font color="red">注意点</font>**
ディスプレイを持たないコンピュータ，すなわちサーバーやマイコンボードなどは，UARTの端子を利用して管理をすることがあります．
端末(コンソール)ウィンドウの代わりにUARTの通信を使って，ログインし，`apt`したり設定ファイルを書き換えたりなどのシステム管理が行えます．

Raspberry Piも同様に，標準装備のシリアルポートを端末(コンソール，ログインシェル)として利用することができます．

しかし，**<font color="red">今回はPythonのプログラムが(具体的にはdronekitが)シリアルポートを利用してPixhawkに接続するので，端末としての機能は不要です．</font>**

以下，マウスを使ってGUIで操作する方法と，コマンドラインから変更する方法の二種類がありますが，どちらの方法でも，**<font color="blue">端末の機能(コンソール，ログインシェル)は使わない</font>**ことに注意してください．

### GUIで設定する
スタートメニュー-[設定]-[Raspberry Piの設定]をクリックして，アプリケーションを起動します．
[インターフェイス]のタブを開き，
1. Serial Portの項目を[有効]に
1. Serial Consoleの項目を[無効]に
してから，[OK]を押して終了してください．
![raspi-config-gui-serial1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/30c05873-f526-50a9-1d6e-244b3fbc8c6e.png)
再起動を促されるので，再起動すれば完了です．

### 端末から設定する
端末(ターミナル)を開き，次のコマンドを入力してください．
システム設定に関わるので，管理者として実行する`sudo`が必要です．

```bash:raspi-configの起動
$ sudo raspi-config
```
こんなTUI(テキスト ユーザ インターフェイス)画面が出てきたら，
[Interfacing Options]を選択してEnterキーを押します．
![raspi-config-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/a2b26d28-b66e-ea75-804d-6d670d04f444.png)
次の画面に移ったら，[Serial]を選択してEnter．
![raspi-config-serial1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/c546bd2b-34db-24d6-69f2-3741163220a4.png)
まずは，ログインシェルとして使うかどうか聞いてきますが，
**端末の機能は不要なので[いいえ]です．**
![raspi-config-serial2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/4f667106-7c60-6272-fe9e-0c4f0db6d52d.png)
次に，ハードウェアとしてシリアルポートを有効にするかどうか聞いてきますが，
**プログラムからシリアルポートを使いたいので[はい]です．**
![raspi-config-serial3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/f48a4533-46a2-d5b6-88f5-8f300a0a1e0c.png)
ログインシェルは無効で，シリアルインターフェイスは有効ですね，[はい]でEnter．
![raspi-config-serial4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/d8668c81-d11b-dcdc-ca61-0298f2ffccd1.png)
最初の画面に戻ってきたので，
TABキーとカーソルキーを使って[Finish]を選択してEnter．
![raspi-config-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/cab8f676-684a-0fa0-8ca2-f4da6f7ec629.png)
すると，再起動するか聞いてくるので，[はい]を選択してEnter.
![raspi-config-serial5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/ee9ecf46-cbd1-fe48-e41a-b51e9568277f.png)
再起動すれば完了です．

## SSHの有効化
Rasberry PiのSSHサーバーの機能もデフォルトで無効になっているので，有効に変える必要があります．
マウスを使ってGUIで操作する方法と，コマンドラインから変更する方法の二種類があるので，好きな方法で作業してください．

### GUIで設定する
スタートメニュー-[設定]-[Raspberry Piの設定]をクリックして，アプリケーションを起動します．
[インターフェイス]のタブを開き，SSHの項目を[有効]にしてから，[OK]を押して終了してください．
![rpi-config-gui.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/b4d681a5-16e2-95b1-6322-b436ee6c6f23.png)
これで完了です．

### 端末から設定する
端末(ターミナル)を開き，次のコマンドを入力してください．
システム設定に関わるので，管理者として実行する`sudo`が必要です．

```bash:raspi-configの起動
sudo raspi-config
```
こんなTUI(テキスト ユーザ インターフェイス)画面が出てきたら，
[Interfacing Options]を選択してEnterキーを押します．
![raspi-config-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/a2b26d28-b66e-ea75-804d-6d670d04f444.png)
次の画面に移ったら，[SSH]を選択してEnter．
![raspi-config-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/6d3062d9-9859-4adb-9c65-24640ea290d3.png)
「enabledにしたいか？」と聞いているので，[はい]を選択してEnter.
![raspi-config-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/a46b2e38-19ea-c1bf-6f50-866af7108fa3.png)
「enabledになったよ」ということで[了解]，Enter．
![raspi-config-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/81a34764-099e-1cbc-1da6-4f8a758a9c5e.png)
最初の画面に戻ってきたので，
TABキーとカーソルキーを使って[Finish]を選択してEnter．
![raspi-config-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/cab8f676-684a-0fa0-8ca2-f4da6f7ec629.png)
以上で完了です．




## Pythonライブラリのインストール
ドローンの操作プログラムに必要なライブラリのインストールを行います．
端末(ターミナル)を開いて作業を行ってください．

必要なPythonライブラリは以下の２つです．

- dronekit　　Pixhawkとの通信用
- paho-mqtt　MQTT通信用

### dronekitのインストール
dronekitに必要なライブラリが不足しているので，まずは依存ライブラリをインストールします．

```bash:dronekitのために必要なライブラリのインストール
sudo apt install libxml2-dev libxslt-dev
```
次にdronekit自体のインストールです．
**<font color="red">1度コマンドを打ってもエラーが出て上手くいかないことが多いです．
何回か実行してください．．．</font>**

```bash:dronekitのインストール
pip install dronekit
```

最新版のdronekit-pythonをインストールしたい場合は，以下のように打ちます．

```bash:gitからdronekitをインストール
pip install git+https://github.com/dronekit/dronekit-python
```

### paho-mqttのインストール
paho-mqttのインストールには，特に依存ライブラリはありません．

```bash:paho-mqttのインストール
pip install paho-mqtt
```


# Pixhawkのセットアップ
ドローンのセットアップに関しては割愛します．

「ドローンの組み立て」や「Mission Plannerの使い方」は，
**イームズラボ**のドキュメントがオススメです．
http://elab.co.jp/docs/


# PixhawkとRaspberry Piの配線
Raspberry PiとPixhawkの接続の仕方は，ardupilotのサイトにある「コンパニオン・コンピュータの接続方法」を参考にします．
http://ardupilot.org/dev/docs/raspberry-pi-via-mavlink.html

GND,TX,RXだけ参考にしてください．

![RaspberryPi_Pixhawk_wiring1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/fb0e9c88-743a-59fc-6038-57fa7e964cec.jpeg)

実は，この図はあまり良い例ではありません．
5V，GND,TX,RXの4本となっていますが，<font color="red">5Vの線は不要</font>です．

この図の使い方は，

- **Pixhawkのパワーモジュールから来た5Vを，Raspberry Piに供給する．**
- **携帯用モバイルバッテリーなどで動いているRaspberry Piの5Vを，Pixhawkに供給する．**

を意味しています．

Raspberry Piにヘビーな計算や通信をさせたら，最大2.5A消費する可能性があります．
すると，PixhawkのCPUが電流不足で停止する危険性があります．
飛行中に姿勢制御装置がブラウンアウトする，という状況は致命的ですね．
有人機で言えばパイロット死亡みたいな状況です．


なので**<font color="blue">電源は別々に用意すべき</font>**です．

例1：
Pixhawkの5Vがパワーモジュールから供給され，
Raspberry Pi3は携帯用モバイルバッテリーで駆動する場合には，
互いの5Vを接続する必要はありません．
GND,TX,RXの3本だけです．

例2：
また，この写真の様に，別のBECを使ってバッテリーから5Vを作った場合も，
Raspberry Pi3とPixhawkの接続はGND,TX,RXの3本です．
![pinout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/423490a4-cb2f-4376-962e-c4d9fc00f892.png)

## 「BECのケンカ」に注意

ドローンを組み立てる際，BEC内蔵のESCが複数ある場合には，１本だけ使うように他の5V線を外します．

ラジコン用語で「BECがケンカする」と言いますが，
**同じ電圧の電源を並列で接続するのは故障の原因になる**ので１つしか使わない，という意味です．
例えば，わずかに電圧の高い5.03Vの電源が，わずかに電圧の低い4.96Vの電源を充電しに行ってしまい，壊れるのです．
かわロボ([かわさきロボット競技会](https://kawasaki-sanshinkaikan.jp/robo/))などのロボコンをやっている方はよくご存知でしょう．

これはESCだけじゃなく，PixhawkとRaspberry Piの電源についても同様です．
電源のケンカをさせないように，配線には注意しましょう．

本来は太陽電池と同様に，逆流防止ダイオードを入れる等の処置を施すべきなのです．

# Raspberry Piで動かすプログラム

[ドローンを動かす(SITL編)](https://qiita.com/hsgucci/items/c795cb1e66879ccfe755)　の記事で作ったプログラム
　[key_ctrl_sitl.py](https://raw.githubusercontent.com/DCoJA/OpenUVTM/master/chapter04/key_ctrl_sitl.py)
を，dronekit-sitlではなくpixhawk用に改変します．

## キー入力のライブラリ

キーボード入力を取る必要があるので，[dronekit-python を使ってみる(実機編)](https://qiita.com/hsgucci/items/e72ef6c172b9d2e62d72#%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E5%85%A5%E5%8A%9B%E3%82%92%E5%8F%96%E3%82%8B%E6%96%B9%E6%B3%95)　で使ったkbhit.pyが必要です．

リンクも貼っておきます　[kbhit.py](https://raw.githubusercontent.com/DCoJA/OpenUVTM/master/chapter03/kbhit.py)

## プログラム本体
[ここ](https://raw.githubusercontent.com/DCoJA/OpenUVTM/master/chapter05/key_ctrl.py)　を右クリック-[名前を付けて保存]するか，
以下のコードをコピー＆ペーストしてファイルを作成してください．

```python:key_ctrl.py
#!usr/bin/env python
# -*- coding: utf-8 -*-
print( "dronekitスタート" )    # 開始メッセージ

# 必要なライブラリをインポート
from kbhit import *                 # kbhitを使うために必要(同じフォルダにkbhit.pyを置くこと)
from signal import signal, SIGINT   # Ctrl+C(SIGINT)の送出のために必要 
from dronekit import connect        # connectを使いたいのでインポート
from dronekit import VehicleMode    # VehicleModeも使いたいのでインポート
from dronekit import LocationGlobal, LocationGlobalRelative   # ウェイポイント移動に使いたいのでインポート
import time                         # ウェイト関数time.sleepを使うために必要

# kbhit()を使うための「おまじない」を最初に２つ書く
atexit.register(set_normal_term)
set_curses_term()

#connection_stringの生成
connection_string = "/dev/ttyS0,57600" # Raspberry Piのシリアル接続だとttyS0、ボーレートは57.6k

# フライトコントローラ(FC)へ接続
print( "FCへ接続: %s" % (connection_string) )    # 接続設定文字列を表示
vehicle = connect(connection_string, wait_ready=True)    # 接続

#Ctrl+cが押されるまでループ
try:
    while True:
        if kbhit():     # 何かキーが押されるのを待つ
            key = getch()   # 1文字取得

            # keyの中身に応じて分岐
            if key=='g':                # guided
                vehicle.mode = VehicleMode( 'GUIDED' )
            elif key=='l':              # land
                vehicle.mode = VehicleMode( 'LAND' )
            elif key=='a':              # arm
                vehicle.armed = True
            elif key=='d':              # disarm
                vehicle.armed = False
            elif key=='t':              # takeoff
                vehicle.simple_takeoff(alt=10)
            elif key=='1':              # simple_goto
                # 柏の葉キャンパス交番上空30mへ
                point = LocationGlobalRelative( 35.893246, 139.954909 , 30 )
                vehicle.simple_goto(point)
            elif key=='2':              # simple_goto
                # 三井ガーデンホテル上空50mへ
                point = LocationGlobalRelative( 35.895236, 139.952468 , 50 )
                vehicle.simple_goto(point)
            elif key=='r':              # RTL
                vehicle.mode = VehicleMode( 'RTL' )


        # ここはif文と同じインデントなので，キーに関係なく1秒に1回実行される
        # 現在の状態を表示
        print("--------------------------" )
        print(" System status: %s" % vehicle.system_status.state)
        print(" Is Armable?: %s" % vehicle.is_armable)
        print(" Armed: %s" % vehicle.armed) 
        print(" Mode: %s" % vehicle.mode.name )
        print(" Global Location: %s" % vehicle.location.global_frame)
        time.sleep(1)

except( KeyboardInterrupt, SystemExit):    # Ctrl+cが押されたら離脱
    print( "SIGINTを検知" )

# フライトコントローラとの接続を閉じる
vehicle.close()

time.sleep(1)   # 終了完了のために1秒待つ

print("終了．")    # 終了メッセージ
```
このプログラム(key_ctrl.py)とkibhi.pyを，Rasberry Pi3のホームディレクトリなどに置いてください．
USBメモリを使う，SFTPで転送する，ラズパイのWebブラウザでこのページを見る，など方法は色々あります．

## プログラム解説
dronekit-sitlの起動部分が無くなっているので，シンプルになりましたね．

### connection_stringの書き方
ポイントは，この行です．

```python:ラズパイのシリアルポートはttyS0
connection_string = "/dev/ttyS0,57600" # Raspberry Piのシリアル接続だとttyS0、ボーレートは57.6k
```
Raspberry Piが持つレガシーなシリアル(ttyS0)を使います．
**Raspbianではpiユーザは最初からdialoutグループに属しています．**
したがって，[dronekit-python を使ってみる(実機編)#事前準備](https://qiita.com/hsgucci/items/e72ef6c172b9d2e62d72#%E4%BA%8B%E5%89%8D%E6%BA%96%E5%82%99)の記事でやったような作業は不要です．

connection_stringさえ変えれば，レガシーでもUSBでもソケット通信(TCP,UDP)でも対応できるというのは，便利ですね．

### 目的の緯度・経度に注意！

これまでの記事で使っていた，柏の葉キャンパス前駅周辺の緯度/経度が書かれているので注意してください．
**<font color="red">必ず，自分が使う飛行場の周辺座標を書いてください！</red>**
でないと千葉県柏市まで飛んでいってしまいますよ（笑

```python:キー入力で移動する目的座標に注意
            elif key=='1':              # simple_goto
                # 柏の葉キャンパス交番上空30mへ
                point = LocationGlobalRelative( 35.893246, 139.954909 , 30 )
                vehicle.simple_goto(point)
            elif key=='2':              # simple_goto
                # 三井ガーデンホテル上空50mへ
                point = LocationGlobalRelative( 35.895236, 139.952468 , 50 )
                vehicle.simple_goto(point)
```
任意の地点の緯度・経度を取得したい場合，
Google Mapsを使うよりも，[地理院地図](https://maps.gsi.go.jp/#16/35.893040/139.940736/&base=std&ls=std&disp=1&vs=c1j0h0k0l0u0t0z0r0s0m0f1)　が便利です．
![chiriin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/59be6750-c31a-f47c-8c6c-c724fb15df71.png)
地図をドラッグして移動させると，マウスのボタンを離した時点での中心点の座標がアドレスバーに入ります．
これをコピー＆ペーストするのがプログラミングには一番楽です．

## SSHでRaspberry Piに接続

ノートパソコンで，お好みのSSHクライアントを使って，Raspberry Piに接続してください．

ここでは，Raspberry PiのIPアドレスを仮に`192.168.0.10`としておきます．

Raspberry Piのログインユーザー名とパスワードは，
**初期設定では**
　ユーザ名：　**pi**
パスワード：　**raspberry**
です．
変更している場合には，そのユーザ名とパスワードを打ち込んでください．

ログインが完了すると，通常の端末(ターミナル)を開いたときと同様にコマンドを打って作業ができます．
![logined.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/d9d8154f-d501-ea55-07fb-69572c40e2bc.png)



### Linuxのsshコマンドで接続する場合

母艦側のLinuxのユーザー名は，Raspbianのユーザー名と同じではないと思いますので，
sshでログインする際には`ユーザー名@IPアドレス`と書きます．
初期設定では，`pi`ユーザ，パスワード`raspberry`ですね．

```bash:piユーザとしてログインする
ssh pi@192.168.0.10
```
初めてSSH接続する際には，警告が表示されますが，気にせず`yes`と打ち込んでEnterします．

```bash:初めてのSSH接続の際には確認があるのでyes
Are you sure you want to continue connecting (yes/no)?
```
参考：[インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識](https://qiita.com/tag1216/items/5d06bad7468f731f590e)


### Puttyで接続する場合
Windows版，Linux版の両方があるGUIアプリのPuttyは，次のようにして接続します．
![putty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/cbdadeff-6860-f161-610e-cd3f3e9785c4.png)
ログインユーザー名とパスワードを聞かれるので，打ち込んでください．

初めてSSH接続する際は，警告が表示されますが，気にせず[はい]しましょう．
参考：[Windowsからssh 2でLinuxにログインするには](https://www.atmarkit.co.jp/flinux/rensai/linuxtips/416usessh2.html)


### TeraTermで接続する場合
Windows版のみのTeraTermでは，次のようにして起動します．
![teraterm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/c77db360-b7c5-4832-8d5b-df0662ad4082.png)
ログインユーザー名とパスワードを聞かれるので，打ち込んでください．

初めてSSH接続する際は，警告が表示されますが，気にせず[続行]しましょう．
参考：[Windows用定番SSHクライアント「Tera Term」の使い方](https://mag.osdn.jp/09/02/02/0412259)

## プログラムを実行
SSHクライアント上で，これまでと同様にコマンドを打ちます．

```bash:プログラムを実行
python key_ctrl.py
```

## 実行結果

正しくPixhawkに接続できていれば，dronekit-sitlの際と同じ表示がされます．

```bash:key_ctrl.pyの実行結果
pi@raspberrypi:~ $ python key_ctrl.py
dronekitスタート
FCへ接続: /dev/ttyS0,57600
--------------------------
 System status: STANDBY
 Is Armable?: False
 Armed: False
 Mode: STABILIZE
 Global Location: LocationGlobal:lat=0.0,lon=0.0,alt=1.8
--------------------------
 System status: STANDBY
 Is Armable?: False
 Armed: False
 Mode: STABILIZE
 Global Location: LocationGlobal:lat=0.0,lon=0.0,alt=1.72
CRITICAL:autopilot:PreArm: Hardware safety switch
CRITICAL:autopilot:PreArm: gyros still settling
--------------------------
 System status: STANDBY
 Is Armable?: False
 Armed: False
 Mode: STABILIZE
 Global Location: LocationGlobal:lat=0.0,lon=0.0,alt=1.63
CRITICAL:autopilot:PreArm: Waiting for Nav Checks
```
ポイントは２点あります．

１つ目は，`CRITICAL:`で始まるメッセージです．
これはdronekitが勝手にprintしている文字列です．
「PixhawkのセーフティスイッチがONになっていない」「ジャイロはまだ設定中」などは，
Mission Plannerのフライトデータ画面に表示されるようなエラーメッセージですね．

２つ目は，`LocationGlobal:lat=0.0,lon=0.0,alt=1.63`の部分です．
今は室内で起動した実験結果なので，GPSが取れていません．
なので，変数の初期値であるゼロが入り，緯度=0°，経度=0°（アフリカのギニア湾）にいることになってしまっています(笑


# SSHの切断対策

SSHクライアントを終了させたり，強制終了してしまったりした場合，
SSH接続中に起動していたプログラム(プロセス)も終了してしまいます．

シミュレーション，有限要素解析，ニューラルネットの学習，，，などの数時間以上かかる計算で，SSHが切断したら計算が終了してしまうのでは，膨大な時間が無駄になります．
**<font color="red">ドローン上のRaspberry PiとのSSHが切断されたら，プログラムが落ちるだけでは済まず，ドローンが墜ちてしまう可能性もあります.</font>((((；ﾟДﾟ))))**
特に今回のシステム構成では，**Wi-FiルータやRaspberyy Piの通信距離が短いので，簡単に圏外になって切断してしまいます．**

この問題を解決してくれるのが**<font color="blue">仮想端末</font>**です．
仮想端末を使えば，急な切断があっても処理中の内容を保持しており，再接続すれば続きからできます．

具体的には**<font color="biolet">screen</font>**もしくは**<font color="green">tmux</font>**というコマンドを使うのですが，少々複雑な設定が必要です．
これらを簡単に使えるようにしてくれたラッパー機能が**<font color="red">byobu</font>**です．

今回は，この**<font color="red">byobu</font>**を使って仮想端末でプログラムを走らせます．


byobuの詳細に関しては，以下のページが役立ちます．

・インストールと起動の方法：　　[byobu導入+操作メモ](https://qiita.com/kayama0fa/items/82d3ebab8bb297bdfd23)
・コマンド解説：　　[byobu操作まとめ](https://qiita.com/miyashiiii/items/90ba726dd331ae103b7b)

## 必要なパッケージのインストール
Raspberry Piにbyobuをインストールします．

```bash:byobuのインストール
sudo apt install byobu
```

## 仮想端末の起動
新しい仮想端末セッションの開始は`byobu new`ですが，セッションに名前を付けておくと複数のプログラムを走らせるときに管理が楽になります．
具体的には，`-s 名前`と追記します．今回は仮に`drone001`としました．

```bash:新しいbyobu端末の起動
byobu new -s drone001
```
![byobu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/ade5c6c5-ff62-626a-6ecf-1a54d9b003bf.png)

byobuが起動すると，端末画面が少々変化します．
　・RaspberryPiのマシン名`raspberrypi`が赤くなるなど，プロンプトの書式が変わった
　・一番下にステータスバーが表示されるようになった
などです．

ステータスバーに表示させる情報は変えることができます．
　参考：　[できるbyobu – 5分でわかる? 仮想端末入門 –](https://techracho.bpsinc.jp/kazumasa-ogawa/2013_09_05/13493)
特に，ステータスバー左端に表示される[logo]が画面表示を崩してしまうことがあるので，
問題があったらlogoのチェックを外しましょう．

## プログラムを実行/切断/再接続

### プログラムの実行
普段の端末と同様に，コマンドを打って実行できます．

```bash:プログラムを実行
$ python key_ctrl.py
```

### 仮想端末を終了させる
仮想端末のプロセスを**終了させたい場合**は`exit`と打てば，
終了して以前のコンソールに戻ります．
(**通常コンソールで`exit`と打つとSSHクライアントが終了するので気をつけましょう**)

### 仮想端末から抜け出す
仮想端末から**一時的に抜け出して，前のコンソールに戻りたい場合**は
F6キーを押します．

<font color="blue">抜け出しても，プログラムはバックグラウンドで走っています．</font>

### 仮想端末に再度入る
抜け出した後に，再度仮想端末に入りたい場合は

```bash
$ byobu
```
とだけ打ちます．

もしも複数の仮想端末が起動している場合は，どの端末に入るかメニュー表示してくれます．

---
試しに，仮想端末で`key_ctrl.py`起動中に，SSHクライアントを終了させ，
再度接続してプログラムが動いているか確認してみてください．

# おわりに

実際のドローンで動作確認ができました．

しかし，「SSH接続してキーを打つ」というのは，面倒ですね．
もっと簡単にドローンを操作したいものです．

次回からは，IoTデバイスでよく利用されるMQTTを利用して，ドローンをコントロールしたいと思います．