38
Dronekit ににに Python API に にににににににに @ogochan 2015 に にに に に 720

Dronekitによる python apiとアプリ開発の概要

Embed Size (px)

Citation preview

Page 1: Dronekitによる python apiとアプリ開発の概要

Dronekit による Python API とアプリ開発の概要@ogochan

2015 年7月20日

Page 2: Dronekitによる python apiとアプリ開発の概要

DroneKit-Python とは• DroneKit の中心的 API• companion computer 上で稼動して、 AruduPilot と通信する• 自律運転 ( オートパイロット ) を高度化する• MAVLink で通信する• 制御だけでなくテレメータ機能もある• OSS(Apache ライセンス ) で Github にホストされている

Page 3: Dronekitによる python apiとアプリ開発の概要

Python かよ!• 「 Ruby や C++ じゃねーの?」• ↑ と文法的にかけ離れてるわけじゃない• 後述するようにプログラムとして難しいわけじゃない ( 「凄いテクニック」とかいらない )• ぶっちゃけ Python よくわからなくても、サンプル見たらなんとなくわかる ( 私もそうだった )

たいした問題じゃない!

Page 4: Dronekitによる python apiとアプリ開発の概要

API の機能• 機体リストの取得• 機体の状態を設定、テレメトリの取得• 非同期に状態変更を受信する• waypoint mission( 通過点を指定した飛行 )の作成と管理 ( 自動モード )• 指定した場所への誘導 ( 誘導モード )• 機体へのメッセージ送信• 設定済みラジコンチャンネルの書き換え

Page 5: Dronekitによる python apiとアプリ開発の概要

API 一覧クラス API 機能 値droneapi.lib.APIConnection exit 現在のスレッドが終了しているかどうか 終了していたら True  get_vehicles 現在のコネクションで制御可能な機体の取得 制御可能な Vehicle オブジェクトの集合droneapi.lib.Vehicle        location 現在の Location droneapi.lib.Location  attitude 現在の Attitude droneapi.lib.Attitude  velocity 現在の速度 [ vx, vy, vz ]  mode 現在の飛行モードの取得と設定 droneapi.lib.VehicleMode  airspeed 現在の対気速度 double  groundspeed 現在の対地速度 double  gps_0 GPS の情報 droneapi.lib.GPSInfo  armed 装備状態 boolean  mount_status ジンバルの状態 [ pitch, yaw, roll ] or None  battery バッテリの状態 droneapi.lib.Battery  channel_override RC チャネルの直接的な変更 ハッシュ  channel_readback RC チャネルの読み出し ハッシュ  add_attribute_observer 属性オブザーバの追加    commands 現在の飛行の通過点 (waypoint) の取得 droneapi.lib.CommandSequence  flush() いわゆる flush    message_factory 生 MAV Link メッセージを作成するオブジェクトを得る    parameters 機体のパラメータ ( 編集可能 ) を得る droneapi.lib.Parameters  remove_attribute_observer 属性オブザーバの削除    send_mavlink 生 MAV Link メッセージの送信    set_mavlink_callback 非同期通知を受け取った時の callback の設定  droneapi.lib.Location   機体の位置    lat Latitude( 緯度 ) double  lon Longitude( 経度 )    alt Altitude( 高度 )    is_relative 高度が絶対 ( 海抜 ) か相対 ( ホーム位置 ) か True or Falsedroneapi.lib.Attitude   機体の方向    pitch ピッチ radian  yaw ヨー radian  roll ロール radiandroneapi.lib.VehicleMode   フライトモード ( 機体特性に依る )    name モードの名前  droneapi.lib.GPSInfo   GPS の情報    eph HDOP ( Horizontal Dilution of Precision ) cm  epv VDOP ( Vertical Dilution of Precision ) cm  fix_type GPS の運転モード 0: no, 2:2D, 3:3D  satellites_visible 見えている衛星の数  droneapi.lib.Battery   バッテリーの状態    voltage 電圧 mV  current 電流 10mA  level 残量  droneapi.lib.CommandSequence   飛行の通過点 (waypoint) の並び    takeoff(altitude) テイクオフ 高度  add(cmd) 通過点の追加 droneapi.lib.Command  clear() コマンドリストの消去    count 通過点の数    download() 機体から通過点をダウンロード    goto(location) 指定位置への移動 droneapi.lib.Location  next 現在意味のある通過点の数    wait_valid() 通過点ダウンロードが終了するまでブロック  droneapi.lib.Parameters   機体のパラメータ    []= パラメータの設定    [] パラメータの参照  

Page 6: Dronekitによる python apiとアプリ開発の概要

キモいっぱいあるけど、

droneapi.lib.Vehicleが理解出来れば、だいたい OK

他はほとんどデータ操作

Page 7: Dronekitによる python apiとアプリ開発の概要

droneapi.lib.Vehiclelocation 現在の Location droneapi.lib.Locationattitude 現在の Attitude droneapi.lib.Attitudevelocity 現在の速度 [ vx, vy, vz ]mode 現在の飛行モードの取得と設定 droneapi.lib.VehicleModeairspeed 現在の対気速度 doublegroundspeed 現在の対地速度 doublegps_0 GPS の情報 droneapi.lib.GPSInfoarmed 装備状態 booleanmount_status ジンバルの状態 [ pitch, yaw, roll ] or Nonebattery バッテリの状態 droneapi.lib.Batterychannel_override RC チャネルの直接的な変更 ハッシュchannel_readback RC チャネルの読み出し ハッシュadd_attribute_observer 属性オブザーバの追加  commands 現在の飛行の通過点 (waypoint) の取得 droneapi.lib.CommandSequenceflush() いわゆる flush  message_factory 生 MAV Link メッセージを作成するオブジェクトを得る  parameters 機体のパラメータ ( 編集可能 ) を得る droneapi.lib.Parametersremove_attribute_observer 属性オブザーバの削除  send_mavlink 生 MAV Link メッセージの送信  set_mavlink_callback 非同期通知を受け取った時の callback の設定  

Page 8: Dronekitによる python apiとアプリ開発の概要

droneapi.lib.Location

lat Latitude( 緯度 ) double

lon Longitude( 経度 )  alt Altitude( 高度 )  is_relative 高度が絶対 ( 海抜 ) か相対 ( ホーム位置 ) か True or False

Page 9: Dronekitによる python apiとアプリ開発の概要

droneapi.lib.Attitude

pitch ピッチ radian

yaw ヨー radian

roll ロール radian

Page 10: Dronekitによる python apiとアプリ開発の概要

droneapi.lib.Battery

voltage 電圧 mV

current 電流 10mA

level 残量  

Page 11: Dronekitによる python apiとアプリ開発の概要

droneapi.lib.CommandSequence

takeoff(altitude) テイクオフ 高度add(cmd) 通過点の追加 droneapi.lib.Command

clear() コマンドリストの消去  count 通過点の数  download() 機体から通過点をダウンロード  goto(location) 指定位置への移動 droneapi.lib.Location

next 現在意味のある通過点の数  wait_valid() 通過点ダウンロードが終了するまでブロック  

Page 12: Dronekitによる python apiとアプリ開発の概要

サンプル解説http://python.dronekit.io/examples/index.htmlにあるサンプルの解説をちょっとだけします。今回は、• Vehicle State• Simple Go To (Copter)• Follow Me

を解説します。

Page 13: Dronekitによる python apiとアプリ開発の概要

Vehicle State(1)

from droneapi.lib import VehicleModefrom pymavlink import mavutilimport time

api = local_connect()

v = api.get_vehicles()[0]

ライブラリのインポート

コネクションの確立コネクション配下にある最初の機体の情報の取得

値の出力をします

Page 14: Dronekitによる python apiとアプリ開発の概要

Vehicle State(2)

print "\nGet all vehicle attribute values:"print " Location: %s" % v.locationprint " Attitude: %s" % v.attitudeprint " Velocity: %s" % v.velocityprint " GPS: %s" % v.gps_0print " Groundspeed: %s" % v.groundspeedprint " Airspeed: %s" % v.airspeedprint " Mount status: %s" % v.mount_statusprint " Battery: %s" % v.batteryprint " Mode: %s" % v.mode.name # settableprint " Armed: %s" % v.armed # settable

それぞれの値はそれぞれのクラスなのだけど、’ print’ は良きにはからってくれます。

値の出力をします

Page 15: Dronekitによる python apiとアプリ開発の概要

Vehicle State(2)

Get all vehicle attribute values: Location: Attitude: Attitude:pitch=-0.00405988190323,yaw=-0.0973932668567,roll=-0.00393210304901 Velocity: [0.06, -0.07, 0.0] GPS: GPSInfo:fix=3,num_sat=10 Groundspeed: 0.0 Airspeed: 0.0 Mount status: [None, None, None] Battery: Battery voltage: 12590, current: 0, level: 99 Mode: STABILIZE Armed: False

この辺の実行結果

Page 16: Dronekitによる python apiとアプリ開発の概要

Vehicle State(3)

print "Set Vehicle.mode=GUIDED (currently: %s)" % v.mode.name v.mode = VehicleMode("GUIDED")

v.flush() while not v.mode.name=='GUIDED' and not api.exit: print " Waiting for mode change ..." time.sleep(1)

print "Set Vehicle.armed=True (currently: %s)" % v.armed v.armed = True

v.flush()while not v.armed and not api.exit: print " Waiting for arming..." time.sleep(1)

フライトモードを’ GUDED’ にします確実な操作をするために、 flush して状態が変化するまで待ちます

‘armed’ にします同じく確実に操作するために flush して状態が変化するまで待ちます

機体を「 armed 」にします

Page 17: Dronekitによる python apiとアプリ開発の概要

Vehicle State(3)

Set Vehicle.mode=GUIDED (currently: STABILIZE) Waiting for mode change ...Got MAVLink msg: COMMAND_ACK {command : 11, result : 0}GUIDED> Mode GUIDEDSet Vehicle.armed=True (currently: False) Waiting for arming...APM: ARMING MOTORSAPM: Initialising APM...Got MAVLink msg: COMMAND_ACK {command : 400, result : 0}ARMED

この辺の実行結果

Page 18: Dronekitによる python apiとアプリ開発の概要

Vehicle State(4)

def mode_callback(attribute): print " CALLBACK: Mode changed to: ", v.mode.name

print "\nAdd mode attribute observer for Vehicle.mode" v.add_attribute_observer('mode', mode_callback)

print " Set mode=STABILIZE (currently: %s)" % v.mode.name v.mode = VehicleMode("STABILIZE")v.flush()

print " Wait 2s so callback invoked before observer removed"time.sleep(2)

v.remove_attribute_observer('mode', mode_callback)

オブザーバの内容です。「オブザーバ」とか言ってますが、要するにコールバックです。モード変更のオブザーバとして登録します

モードを‘ STABILIZE’ にします確実に操作するために flush して状態が変化するまで待ちますオブザーバを外すのを 2秒待ちます

オブザーバを外します

オブザーバをつけたり外したりします

Page 19: Dronekitによる python apiとアプリ開発の概要

Vehicle State(4)

Add mode attribute observer for Vehicle.mode Set mode=STABILIZE (currently: GUIDED) Wait 2s so callback invoked before observer removedGot MAVLink msg: COMMAND_ACK {command : 11, result : 0}STABILIZE> Mode STABILIZE CALLBACK: Mode changed to: STABILIZE

この辺の実行結果

Page 20: Dronekitによる python apiとアプリ開発の概要

Vehicle State(5)

print "\nGet home location" cmds = v.commandscmds.download()

cmds.wait_valid()

print " Home WP: %s" % cmds[0]

現在のミッションの通過点 (waypoint)をダウンロードしますダウンロードが完了するまで待ちます一番最初の通過点は初期位置です

機体の初期位置 (home location) を得ます

Page 21: Dronekitによる python apiとアプリ開発の概要

Vehicle State(5)

Get home locationRequesting 0 waypoints t=Fri May 15 11:35:58 2015 now=Fri May 15 11:35:58 2015 Home WP: MISSION_ITEM {target_system : 255, target_component : 0, seq : 0, frame : 0, command : 16, current : 0, autocontinue : 1, param1 : 0.0, param2 : 0.0, param3 : 0.0, param4 : 0.0, x : -35.3632621765, y : 149.165237427, z : 583.729980469}

この辺の実行結果

Page 22: Dronekitによる python apiとアプリ開発の概要

Vehicle State(6)

print "\nRead vehicle param 'THR_MIN': %s" % v.parameters['THR_MIN']

print "Write vehicle param 'THR_MIN' : 10"v.parameters['THR_MIN']=10

v.flush()

print "Read new value of param 'THR_MIN': %s" % v.parameters['THR_MIN']

パラメータ‘ THR_MIN’ を読みます。

パラメータ’ THR_MIN’ を 10 に設定します

完了するまで待ちますあらためてパラメータ’ THR_MIN’ を読みますなお、’ THR_MIN’ とはストットルの最小値を意味します。

機体のパラメータの読み出し書き込みをします

Page 23: Dronekitによる python apiとアプリ開発の概要

Vehicle State(6)

Read vehicle param 'THR_MIN': 130.0Write vehicle param 'THR_MIN' : 10timeout setting THR_MIN to 10.000000Read new value of param 'THR_MIN': 10.0

この辺の実行結果

Page 24: Dronekitによる python apiとアプリ開発の概要

Vehicle State(7)

print "\nOverriding RC channels for roll and yaw"v.channel_override = { "1" : 900, "4" : 1000 }

v.flush()

print " Current overrides are:", v.channel_override

print " Channel default values:", v.channel_readback # All channel values before override

# Cancel override by setting channels to 0print " Cancelling override"v.channel_override = { "1" : 0, "4" : 0 }

v.flush()

チャネルの値を変更します反映させます上書きされた値を表示します

元の値を表示します

上書きをやめてコントローラの値に戻します (0 を設定するのはそういう意味 )

反映させます

RC チャンネルの上書き

Page 25: Dronekitによる python apiとアプリ開発の概要

Vehicle State(7)

Overriding RC channels for roll and yaw Current overrides are: {'1': 900, '4': 1000} Channel default values: {'1': 1500, '3': 1000, '2': 1500, '5': 1800, '4': 1500, '7': 1000, '6': 1000, '8': 1800} Cancelling override

この辺の実行結果

Page 26: Dronekitによる python apiとアプリ開発の概要

Vehicle State(8)

print "\nReset vehicle atributes/parameters and exit“

v.mode = VehicleMode("STABILIZE")

v.armed = False

v.parameters['THR_MIN']=130

v.flush()

機体モードを’ STABILIZE’ にarmed を False にスロットル最小値を 130 に反映させます

ヤバそうな値は元に戻しておきます

Page 27: Dronekitによる python apiとアプリ開発の概要

Vehicle State(8)

Reset vehicle atributes/parameters and exitGot MAVLink msg: COMMAND_ACK {command : 11, result : 0}APM: DISARMING MOTORSGot MAVLink msg: COMMAND_ACK {command : 400, result : 0}DISARMEDtimeout setting THR_MIN to 130.000000APIThread-0 exiting...

この辺の実行結果

Page 28: Dronekitによる python apiとアプリ開発の概要

Simple Go To (Copter) (1)

import timefrom droneapi.lib import VehicleModefrom pymavlink import mavutil

api = local_connect()

v = api.get_vehicles()[0]

ライブラリのインポート

コネクションの確立コネクション配下にある最初の機体の情報の取得

目的の場所に移動させるサンプルです

Page 29: Dronekitによる python apiとアプリ開発の概要

Simple Go To (Copter) (2)

def arm_and_takeoff(aTargetAltitude):

print "Basic pre-arm checks"if vehicle.mode.name == "INITIALISING":

print "Waiting for vehicle to initialise“

time.sleep(1)

while vehicle.gps_0.fix_type < 2:print “Waiting for GPS...:”, vehicle. gps_0. fix_typetime.sleep(1)

armed にし、目的の高度まで飛び上がる関数 (手続 ) を定義しますメッセージを出しますモードが’ INITIALISING’ であれば、「初期化待ち」を表示して1秒待ちますGPS が有効になるまでメッセージを出して

1秒待ちます

機体と GPS の初期化をします

GPS の fix_type が 2次元未満の場合は、GPS は無効の状態です

Page 30: Dronekitによる python apiとアプリ開発の概要

Simple Go To (Copter) (3)

print "Arming motors“

vehicle.mode = VehicleMode("GUIDED")vehicle.armed = True

vehicle.flush()

while not vehicle.armed and not api.exit:print " Waiting for arming...“time.sleep(1)

メッセージを出しますモードが’ GUIDED’ にしてarmed にします変更を反映させて、armed になるまでメッセージを出して

1秒待ちます

armed にします

モードの’ GUIDED’ とは、通過点通りに飛行する以外のモードです

Page 31: Dronekitによる python apiとアプリ開発の概要

Simple Go To (Copter) (4)

print "Taking off!“ vehicle.commands.takeoff(aTargetAltitude)

vehicle.flush()

メッセージを出します目的の高度まで飛行するコマンドを出し反映させます

飛び立ちます

Page 32: Dronekitによる python apiとアプリ開発の概要

Simple Go To (Copter) (5)

while not api.exit:

print " Altitude: ", vehicle.location.alt

if vehicle.location.alt >= aTargetAltitude * 0.95:

print "Reached target altitude“break;

time.sleep(1)

API が生きている限り高度を表示します目的の高度であるか調べ、目的の高度であればメッセージを出して、ループを抜けますそうでなければ 1秒待ちます

目的の高度になるまで処理を待ちます

Page 33: Dronekitによる python apiとアプリ開発の概要

Simple Go To (Copter) (6)

arm_and_takeoff(20)

print "Going to first point..."point1 = Location(-35.361354, 149.165218, 20, is_relative=True)vehicle.commands.goto(point1)vehicle.flush()time.sleep(30)

print "Going to second point..."point2 = Location(-35.363244, 149.168801, 20, is_relative=True)vehicle.commands.goto(point2)vehicle.flush()time.sleep(20)

print "Returning to Launch"vehicle.mode = VehicleMode("RTL")vehicle.flush()

目的高度まで飛び立たせます最初のポイントに飛行します最初の点の Location を作ります移動するよう指示して反映させます30秒待ちます (多分その間に飛行する )

次のポイントに飛行します次のポイントの Location を作ります移動するよう指示して反映させます20秒待ちます (多分その間に飛行する )

帰投モードにします反映させます

メインのコントロールです

Page 34: Dronekitによる python apiとアプリ開発の概要

Follow Me(1)

import gpsimport socketimport timefrom droneapi.lib import VehicleMode, Location

ライブラリのインポートこのサンプルでは、 GPS デーモンと通信して、その位置に移動させるために、今までとはちょっと違うライブラリもインポートしています

「付いて来る」

Page 35: Dronekitによる python apiとアプリ開発の概要

Follow Me(2)

def followme():try:

api = local_connect()v = api.get_vehicles()[0]

if v.mode.name == "INITIALISING":print "Vehicle still booting, try again later"return

cmds = v.commandsis_guided = False

gpsd = gps. gps ( mode = gps. WATCH_ENABLE)

「付いて来る」関数を定義します例外処理を考慮しますいつもの準備

モードが’ INITIALISING’ であれば、「後にしろ」を表示しておしまいCommand を取得します

GPS が取得出来るようにします

機体と GPS の初期化をします

Page 36: Dronekitによる python apiとアプリ開発の概要

Follow Me(3)

while not api.exit:gpsd.next()if is_guided and v.mode.name != "GUIDED":

print "User has changed flight modes - aborting follow-me“break

if (gpsd.valid & gps.LATLON_SET) != 0:altitude = 30dest = Location(gpsd.fix.latitude, gpsd.fix.longitude, altitude, is_relative=True)print "Going to: %s" % destcmds.goto(dest)is_guided = Truev.flush()time.sleep(2)

API が生きている間GPS データを取得しますモードに矛盾があったら停止

GPS データが有効であれば高さを 30m にしてGPS から取得した位置でLocation を作り、Location を表示しLocation に行くように指示反映させて2秒待ちます

「付いて来る」の本体

Page 37: Dronekitによる python apiとアプリ開発の概要

Follow Me(4)

except socket.error: print "Error: gpsd service does not seem to be running, plug in USB GPS or run run-fake-gps.sh"

socket の例外の場合メッセージを出します

例外処理

Page 38: Dronekitによる python apiとアプリ開発の概要

おまけ (DroneKit の build)

git clone git://github.com/diydrones/ardupilot.git

sudo apt-get install python-matplotlib python-serial python-wxgtk2.8 python-lxmlsudo apt-get install python-scipy python-opencv ccache gawk git python-pip python-pexpectsudo pip install pymavlink MAVProxy

cd ardupilot

export PATH=$PATH:$HOME/ardupilot/jsbsim/srcexport PATH=$PATH:$HOME/ardupilot/Tools/autotest

sim_vehicle.sh -w

ソースを取得いろいろ必要なものをインストール

環境変数作る

Build もこの中で勝手にしてくれる

IA64 、 RaspberryPi 上で可能 (Ubuntu 14)