はじめに
このページは,
の1ページです.
全体を見たい場合は上記ページへお戻りください.
概要
前回までに,dronekit-sitl(シミュレータ)とPixhawk(実際のフライトコントローラ)を動かしてみました.
今回は,Pixhawkを搭載したドローンを動かしてみたいと思います.
システム構成
システム構成は図のようになります.
Wi-Fiを使って,ドローンとPCとの通信を行います.
「SSHでRaspberry Piにログインする」という形で制御してみます.
IPアドレスは仮に与えたものなので,
適宜,自分の使う無線LANに合わせて読み替えてください.
余談
今回はLAN(Local Area Network)なので,あくまでもローカルでの通信です.
本企画の最終目標はグローバルネット(WAN)を通じて制御することです.
例えば,「夜空のLEDドローンアート」では,ローカルでの通信で十分ですね.
(何百台の無線機の輻輳が問題になりますが)
一方,ドローン輸送などの目視外飛行ではグローバルが必須でしょう.
ローカルで十分か,グローバルが必要か,目的に応じて検討する必要があります.
準備するもの
ArdupilotのGUIDEDモードを利用するには,GPSで位置が取れている必要があります.
フライトモード概要
従って,GPSの効かない屋内で実験することはできません.
屋外で実験するためには,ノートパソコンなどの電源を気にせず起動できるコンピュータが必要です.
準備する機材
・SSHクライアントのあるノートPC
このPCからRaspberry PiにSSHでリモートログインし,プログラムを実行します.
OSがLinuxである必要はありません.WindowsでもTera Term等のSSHクライアントを利用できます.
・無線LANアクセスポイント
ノートPCと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でもいけそうですが、試したことはありません。
ラジコン受信機やテレメトリ装置は外さず、搭載したままにしておいてください.
プログラム暴走時の保険です。
・Raspberr Pi用の電源
ドローンのバッテリーから別のBECで5V作るか、
携帯用モバイルバッテリーなどの別の5V電源を用意してください。
PixhawkのTelemの5V(fromパワーモジュール)を供給するのは危険です.
参考例:5V BEC
参考
参考として,本企画用に作製したRaspberry Pi 3搭載のF450互換機を示します.
無理やりRaspberry Pi3の上にPixhawkを載せています(^^;)
送信機はT10J,テレメトリはXBee S2Bです.
イームズのこの製品とほぼ同じ内容です.これにRaspberry Piを追加してください.(Pixhawk1系でもPixhawk Miniでも同じように使えます)
LAB445 ドローン組立キット フルセット
他にも,
Pixhawk2とRaspberry Pi3を積んだ900サイズ機
Navio+やNavio2(Raspberry Pi3)を積んだF550
Pixhawk MiniとNano Piを積んだTurnigy Talon トライコプター
などで試しています.
実験する場所
改正航空法に抵触しない場所・時間で実験を行いましょう.
もちろん,DIPSで申請しても良いのですが,
Raspberry Piの搭載などで機体を改変するたびに再申請が必要になるので,大変です.
DJIのような完成品は改造しないので楽です.
しかし自作機を徐々に開発していく場合には都度申請が必要になるのです.
DIDについては以下のページを見るか,
人口集中地区(DID) 平成27年
「ドローンフライトナビ」「ドローン飛行チェック」「楽天AirMap」などのスマホアプリを利用してください.
本企画でも将来的にDIDの表示機能を持たせようと思います.
SSHクライアントのあるノートPCの準備
Linuxであれば,SSHクライアントの機能はデフォルトでインストールされているはずです.
あるいは「Putty」などのGUIアプリケーションを使っても良いです.
Windowsであれば,「Tera Term」「Putty」などのSSHクライアントソフトをインストールしてください.
Raspberry Piのセットアップ
Raspberry PiのOSには,公式のRaspbianを使用します.
OSのダウンロードとSDカードの準備
Raspbianは2019年4月から,Full,標準,Liteの3種類になりました.(以前はFullとLiteの2種類)
今回は標準版を使います.FullだとOfficeやマインクラフトなど不要なソフトがディスク容量を圧迫するからです.
(空飛ぶドローンにデスクトップ画面は不要なので,本来はLiteを使いたいところですが,その場合は様々な依存関係を自力で解決する必要があり,ハードルが高くなります.)
公式ページから,標準版である
「Raspbian Stretch with desktop」
をダウンロードしてください.
ダウンロードしたイメージは,
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の接続先は,ノートPCと同じアクセスポイントにしてください.
・OSの更新(sudo apt update
とsudo apt upgrade
)もウィザードでやってくれるようになっています.
シリアルポートの有効化
Raspberry Piに標準装備されているシリアルポート(UART)をPixhawkに繋ぐので,
デフォルトでは[無効]になっているシリアルポートを[有効]にする必要があります.
注意点
ディスプレイを持たないコンピュータ,すなわちサーバーやマイコンボードなどは,UARTの端子を利用して管理をすることがあります.
端末(コンソール)ウィンドウの代わりにUARTの通信を使って,ログインし,apt
したり設定ファイルを書き換えたりなどのシステム管理が行えます.
Raspberry Piも同様に,標準装備のシリアルポートを端末(コンソール,ログインシェル)として利用することができます.
しかし,今回はPythonのプログラムが(具体的にはdronekitが)シリアルポートを利用してPixhawkに接続するので,端末としての機能は不要です.
以下,マウスを使ってGUIで操作する方法と,コマンドラインから変更する方法の二種類がありますが,どちらの方法でも,**端末の機能(コンソール,ログインシェル)は使わない**ことに注意してください.
GUIで設定する
スタートメニュー-[設定]-[Raspberry Piの設定]をクリックして,アプリケーションを起動します.
[インターフェイス]のタブを開き,
端末から設定する
端末(ターミナル)を開き,次のコマンドを入力してください.
システム設定に関わるので,管理者として実行するsudo
が必要です.
$ sudo raspi-config
こんなTUI(テキスト ユーザ インターフェイス)画面が出てきたら,
[Interfacing Options]を選択してEnterキーを押します.
次の画面に移ったら,[Serial]を選択してEnter.
まずは,ログインシェルとして使うかどうか聞いてきますが,
端末の機能は不要なので[いいえ]です.
次に,ハードウェアとしてシリアルポートを有効にするかどうか聞いてきますが,
プログラムからシリアルポートを使いたいので[はい]です.
ログインシェルは無効で,シリアルインターフェイスは有効ですね,[はい]でEnter.
最初の画面に戻ってきたので,
TABキーとカーソルキーを使って[Finish]を選択してEnter.
すると,再起動するか聞いてくるので,[はい]を選択してEnter.
再起動すれば完了です.
SSHの有効化
Rasberry PiのSSHサーバーの機能もデフォルトで無効になっているので,有効に変える必要があります.
マウスを使ってGUIで操作する方法と,コマンドラインから変更する方法の二種類があるので,好きな方法で作業してください.
GUIで設定する
スタートメニュー-[設定]-[Raspberry Piの設定]をクリックして,アプリケーションを起動します.
[インターフェイス]のタブを開き,SSHの項目を[有効]にしてから,[OK]を押して終了してください.
これで完了です.
端末から設定する
端末(ターミナル)を開き,次のコマンドを入力してください.
システム設定に関わるので,管理者として実行するsudo
が必要です.
sudo raspi-config
こんなTUI(テキスト ユーザ インターフェイス)画面が出てきたら,
[Interfacing Options]を選択してEnterキーを押します.
次の画面に移ったら,[SSH]を選択してEnter.
「enabledにしたいか?」と聞いているので,[はい]を選択してEnter.
「enabledになったよ」ということで[了解],Enter.
最初の画面に戻ってきたので,
TABキーとカーソルキーを使って[Finish]を選択してEnter.
以上で完了です.
Pythonライブラリのインストール
ドローンの操作プログラムに必要なライブラリのインストールを行います.
端末(ターミナル)を開いて作業を行ってください.
必要なPythonライブラリは以下の2つです.
- dronekit Pixhawkとの通信用
- paho-mqtt MQTT通信用
dronekitのインストール
dronekitに必要なライブラリが不足しているので,まずは依存ライブラリをインストールします.
sudo apt install libxml2-dev libxslt-dev
次にdronekit自体のインストールです.
1度コマンドを打ってもエラーが出て上手くいかないことが多いです.
何回か実行してください...
pip install dronekit
最新版のdronekit-pythonをインストールしたい場合は,以下のように打ちます.
pip install git+https://github.com/dronekit/dronekit-python
paho-mqttのインストール
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だけ参考にしてください.
実は,この図はあまり良い例ではありません.
5V,GND,TX,RXの4本となっていますが,5Vの線は不要です.
この図の使い方は,
- Pixhawkのパワーモジュールから来た5Vを,Raspberry Piに供給する.
- 携帯用モバイルバッテリーなどで動いているRaspberry Piの5Vを,Pixhawkに供給する.
を意味しています.
Raspberry Piにヘビーな計算や通信をさせたら,最大2.5A消費する可能性があります.
すると,PixhawkのCPUが電流不足で停止する危険性があります.
飛行中に姿勢制御装置がブラウンアウトする,という状況は致命的ですね.
有人機で言えばパイロット死亡みたいな状況です.
なので**電源は別々に用意すべき**です.
例1:
Pixhawkの5Vがパワーモジュールから供給され,
Raspberry Pi3は携帯用モバイルバッテリーで駆動する場合には,
互いの5Vを接続する必要はありません.
GND,TX,RXの3本だけです.
例2:
また,この写真の様に,別のBECを使ってバッテリーから5Vを作った場合も,
Raspberry Pi3とPixhawkの接続はGND,TX,RXの3本です.
「BECのケンカ」に注意
ドローンを組み立てる際,BEC内蔵のESCが複数ある場合には,1本だけ使うように他の5V線を外します.
ラジコン用語で「BECがケンカする」と言いますが,
同じ電圧の電源を並列で接続するのは故障の原因になるので1つしか使わない,という意味です.
例えば,わずかに電圧の高い5.03Vの電源が,わずかに電圧の低い4.96Vの電源を充電しに行ってしまい,壊れるのです.
かわロボ(かわさきロボット競技会)などのロボコンをやっている方はよくご存知でしょう.
これはESCだけじゃなく,PixhawkとRaspberry Piの電源についても同様です.
電源のケンカをさせないように,配線には注意しましょう.
本来は太陽電池と同様に,逆流防止ダイオードを入れる等の処置を施すべきなのです.
Raspberry Piで動かすプログラム
ドローンを動かす(SITL編) の記事で作ったプログラム
key_ctrl_sitl.py
を,dronekit-sitlではなくpixhawk用に改変します.
キー入力のライブラリ
キーボード入力を取る必要があるので,dronekit-python を使ってみる(実機編) で使ったkbhit.pyが必要です.
リンクも貼っておきます kbhit.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()を使うための「おまじない」を最初に2つ書く
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の書き方
ポイントは,この行です.
connection_string = "/dev/ttyS0,57600" # Raspberry Piのシリアル接続だとttyS0、ボーレートは57.6k
Raspberry Piが持つレガシーなシリアル(ttyS0)を使います.
Raspbianではpiユーザは最初からdialoutグループに属しています.
したがって,dronekit-python を使ってみる(実機編)#事前準備の記事でやったような作業は不要です.
connection_stringさえ変えれば,レガシーでもUSBでもソケット通信(TCP,UDP)でも対応できるというのは,便利ですね.
目的の緯度・経度に注意!
これまでの記事で使っていた,柏の葉キャンパス前駅周辺の緯度/経度が書かれているので注意してください.
必ず,自分が使う飛行場の周辺座標を書いてください!
でないと千葉県柏市まで飛んでいってしまいますよ(笑
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を使うよりも,地理院地図 が便利です.
地図をドラッグして移動させると,マウスのボタンを離した時点での中心点の座標がアドレスバーに入ります.
これをコピー&ペーストするのがプログラミングには一番楽です.
SSHでRaspberry Piに接続
ノートパソコンで,お好みのSSHクライアントを使って,Raspberry Piに接続してください.
ここでは,Raspberry PiのIPアドレスを仮に192.168.0.10
としておきます.
Raspberry Piのログインユーザー名とパスワードは,
初期設定では
ユーザ名: pi
パスワード: raspberry
です.
変更している場合には,そのユーザ名とパスワードを打ち込んでください.
ログインが完了すると,通常の端末(ターミナル)を開いたときと同様にコマンドを打って作業ができます.
Linuxのsshコマンドで接続する場合
母艦側のLinuxのユーザー名は,Raspbianのユーザー名と同じではないと思いますので,
sshでログインする際にはユーザー名@IPアドレス
と書きます.
初期設定では,pi
ユーザ,パスワードraspberry
ですね.
ssh pi@192.168.0.10
初めてSSH接続する際には,警告が表示されますが,気にせずyes
と打ち込んでEnterします.
Are you sure you want to continue connecting (yes/no)?
参考:インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識
Puttyで接続する場合
Windows版,Linux版の両方があるGUIアプリのPuttyは,次のようにして接続します.
ログインユーザー名とパスワードを聞かれるので,打ち込んでください.
初めてSSH接続する際は,警告が表示されますが,気にせず[はい]しましょう.
参考:Windowsからssh 2でLinuxにログインするには
TeraTermで接続する場合
Windows版のみのTeraTermでは,次のようにして起動します.
ログインユーザー名とパスワードを聞かれるので,打ち込んでください.
初めてSSH接続する際は,警告が表示されますが,気にせず[続行]しましょう.
参考:Windows用定番SSHクライアント「Tera Term」の使い方
プログラムを実行
SSHクライアント上で,これまでと同様にコマンドを打ちます.
python key_ctrl.py
実行結果
正しくPixhawkに接続できていれば,dronekit-sitlの際と同じ表示がされます.
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
ポイントは2点あります.
1つ目は,CRITICAL:
で始まるメッセージです.
これはdronekitが勝手にprintしている文字列です.
「PixhawkのセーフティスイッチがONになっていない」「ジャイロはまだ設定中」などは,
Mission Plannerのフライトデータ画面に表示されるようなエラーメッセージですね.
2つ目は,LocationGlobal:lat=0.0,lon=0.0,alt=1.63
の部分です.
今は室内で起動した実験結果なので,GPSが取れていません.
なので,変数の初期値であるゼロが入り,緯度=0°,経度=0°(アフリカのギニア湾)にいることになってしまっています(笑
SSHの切断対策
SSHクライアントを終了させたり,強制終了してしまったりした場合,
SSH接続中に起動していたプログラム(プロセス)も終了してしまいます.
シミュレーション,有限要素解析,ニューラルネットの学習,,,などの数時間以上かかる計算で,SSHが切断したら計算が終了してしまうのでは,膨大な時間が無駄になります.
ドローン上のRaspberry PiとのSSHが切断されたら,プログラムが落ちるだけでは済まず,ドローンが墜ちてしまう可能性もあります.((((;゚Д゚))))
特に今回のシステム構成では,Wi-FiルータやRaspberyy Piの通信距離が短いので,簡単に圏外になって切断してしまいます.
この問題を解決してくれるのが**仮想端末**です.
仮想端末を使えば,急な切断があっても処理中の内容を保持しており,再接続すれば続きからできます.
具体的には**screenもしくはtmuxというコマンドを使うのですが,少々複雑な設定が必要です.
これらを簡単に使えるようにしてくれたラッパー機能がbyobu**です.
今回は,この**byobu**を使って仮想端末でプログラムを走らせます.
byobuの詳細に関しては,以下のページが役立ちます.
・インストールと起動の方法: byobu導入+操作メモ
・コマンド解説: byobu操作まとめ
必要なパッケージのインストール
Raspberry Piにbyobuをインストールします.
sudo apt install byobu
仮想端末の起動
新しい仮想端末セッションの開始はbyobu new
ですが,セッションに名前を付けておくと複数のプログラムを走らせるときに管理が楽になります.
具体的には,-s 名前
と追記します.今回は仮にdrone001
としました.
byobu new -s drone001
byobuが起動すると,端末画面が少々変化します.
・RaspberryPiのマシン名raspberrypi
が赤くなるなど,プロンプトの書式が変わった
・一番下にステータスバーが表示されるようになった
などです.
ステータスバーに表示させる情報は変えることができます.
参考: できるbyobu – 5分でわかる? 仮想端末入門 –
特に,ステータスバー左端に表示される[logo]が画面表示を崩してしまうことがあるので,
問題があったらlogoのチェックを外しましょう.
プログラムを実行/切断/再接続
プログラムの実行
普段の端末と同様に,コマンドを打って実行できます.
$ python key_ctrl.py
仮想端末を終了させる
仮想端末のプロセスを終了させたい場合はexit
と打てば,
終了して以前のコンソールに戻ります.
(通常コンソールでexit
と打つとSSHクライアントが終了するので気をつけましょう)
仮想端末から抜け出す
仮想端末から一時的に抜け出して,前のコンソールに戻りたい場合は
F6キーを押します.
抜け出しても,プログラムはバックグラウンドで走っています.
仮想端末に再度入る
抜け出した後に,再度仮想端末に入りたい場合は
$ byobu
とだけ打ちます.
もしも複数の仮想端末が起動している場合は,どの端末に入るかメニュー表示してくれます.
試しに,仮想端末でkey_ctrl.py
起動中に,SSHクライアントを終了させ,
再度接続してプログラムが動いているか確認してみてください.
おわりに
実際のドローンで動作確認ができました.
しかし,「SSH接続してキーを打つ」というのは,面倒ですね.
もっと簡単にドローンを操作したいものです.
次回からは,IoTデバイスでよく利用されるMQTTを利用して,ドローンをコントロールしたいと思います.