Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

18,189 views

Published on

http://abc.android-group.jp/2015s/ で発表したもの

Published in: Devices & Hardware
  • Hey guys! Who wants to chat with me? More photos with me here 👉 http://www.bit.ly/katekoxx
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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

  1. 1. Dronekitによる Python APIと アプリ開発の概要 @ogochan 2015年7月20日
  2. 2. DroneKit-Pythonとは • DroneKitの中心的API • companion computer上で稼動して、 AruduPilotと通信する • 自律運転(オートパイロット)を高度化する • MAVLinkで通信する • 制御だけでなくテレメータ機能もある • OSS(Apacheライセンス)でGithubにホストされ ている
  3. 3. Pythonかよ! • 「RubyやC++じゃねーの?」 • ↑と文法的にかけ離れてるわけじゃない • 後述するようにプログラムとして難しいわけじゃない (「凄いテクニック」とかいらない) • ぶっちゃけPythonよくわからなくても、サンプル見た らなんとなくわかる(私もそうだった) たいした問題じゃない!
  4. 4. APIの機能 • 機体リストの取得 • 機体の状態を設定、テレメトリの取得 • 非同期に状態変更を受信する • waypoint mission(通過点を指定した飛行)の 作成と管理(自動モード) • 指定した場所への誘導(誘導モード) • 機体へのメッセージ送信 • 設定済みラジコンチャンネルの書き換え
  5. 5. 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 False droneapi.lib.Attitude 機体の方向 pitch ピッチ radian yaw ヨー radian roll ロール radian droneapi.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 機体のパラメータ []= パラメータの設定 [] パラメータの参照
  6. 6. キモ いっぱいあるけど、 droneapi.lib.Vehicle が理解出来れば、 だいたいOK 他はほとんどデータ操作
  7. 7. 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の設定
  8. 8. droneapi.lib.Location lat Latitude(緯度) double lon Longitude(経度) alt Altitude(高度) is_relative 高度が絶対(海抜)か相対(ホーム位置)か True or False
  9. 9. droneapi.lib.Attitude pitch ピッチ radian yaw ヨー radian roll ロール radian
  10. 10. droneapi.lib.Battery voltage 電圧 mV current 電流 10mA level 残量
  11. 11. droneapi.lib.CommandSequence takeoff(altitude) テイクオフ 高度 add(cmd) 通過点の追加 droneapi.lib.Command clear() コマンドリストの消去 count 通過点の数 download() 機体から通過点をダウンロード goto(location) 指定位置への移動 droneapi.lib.Location next 現在意味のある通過点の数 wait_valid() 通過点ダウンロードが終了するまでブロック
  12. 12. サンプル解説 http://python.dronekit.io/examples/index.html にあるサンプルの解説をちょっとだけします。 今回は、 • Vehicle State • Simple Go To (Copter) • Follow Me を解説します。
  13. 13. Vehicle State(1) from droneapi.lib import VehicleMode from pymavlink import mavutil import time api = local_connect() v = api.get_vehicles()[0] ライブラリのインポート コネクションの確立 コネクション配下にある最初の機体の情 報の取得 値の出力をします
  14. 14. Vehicle State(2) print "nGet all vehicle attribute values:" print " Location: %s" % v.location print " Attitude: %s" % v.attitude print " Velocity: %s" % v.velocity print " GPS: %s" % v.gps_0 print " Groundspeed: %s" % v.groundspeed print " Airspeed: %s" % v.airspeed print " Mount status: %s" % v.mount_status print " Battery: %s" % v.battery print " Mode: %s" % v.mode.name # settable print " Armed: %s" % v.armed # settable それぞれの値はそれぞれのクラスなの だけど、’print’は良きにはからってくれま す。 値の出力をします
  15. 15. 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 この辺の実行結果
  16. 16. 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」にします
  17. 17. Vehicle State(3) Set Vehicle.mode=GUIDED (currently: STABILIZE) Waiting for mode change ... Got MAVLink msg: COMMAND_ACK {command : 11, result : 0} GUIDED> Mode GUIDED Set Vehicle.armed=True (currently: False) Waiting for arming... APM: ARMING MOTORS APM: Initialising APM... Got MAVLink msg: COMMAND_ACK {command : 400, result : 0} ARMED この辺の実行結果
  18. 18. 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秒待ちます オブザーバを外します オブザーバをつけたり外したりします
  19. 19. Vehicle State(4) Add mode attribute observer for Vehicle.mode Set mode=STABILIZE (currently: GUIDED) Wait 2s so callback invoked before observer removed Got MAVLink msg: COMMAND_ACK {command : 11, result : 0} STABILIZE> Mode STABILIZE CALLBACK: Mode changed to: STABILIZE この辺の実行結果
  20. 20. Vehicle State(5) print "nGet home location" cmds = v.commands cmds.download() cmds.wait_valid() print " Home WP: %s" % cmds[0] 現在のミッションの通過点(waypoint)をダ ウンロードします ダウンロードが完了するまで待ちます 一番最初の通過点は初期位置です 機体の初期位置(home location)を得ます
  21. 21. Vehicle State(5) Get home location Requesting 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} この辺の実行結果
  22. 22. 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’とはストットルの最小値 を意味します。 機体のパラメータの読み出し書き込みをします
  23. 23. Vehicle State(6) Read vehicle param 'THR_MIN': 130.0 Write vehicle param 'THR_MIN' : 10 timeout setting THR_MIN to 10.000000 Read new value of param 'THR_MIN': 10.0 この辺の実行結果
  24. 24. 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 0 print " Cancelling override" v.channel_override = { "1" : 0, "4" : 0 } v.flush() チャネルの値を変更します 反映させます 上書きされた値を表示します 元の値を表示します 上書きをやめてコントローラの値に戻し ます(0を設定するのはそういう意味) 反映させます RCチャンネルの上書き
  25. 25. 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 この辺の実行結果
  26. 26. 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に 反映させます ヤバそうな値は元に戻しておきます
  27. 27. Vehicle State(8) Reset vehicle atributes/parameters and exit Got MAVLink msg: COMMAND_ACK {command : 11, result : 0} APM: DISARMING MOTORS Got MAVLink msg: COMMAND_ACK {command : 400, result : 0} DISARMED timeout setting THR_MIN to 130.000000 APIThread-0 exiting... この辺の実行結果
  28. 28. Simple Go To (Copter) (1) import time from droneapi.lib import VehicleMode from pymavlink import mavutil api = local_connect() v = api.get_vehicles()[0] ライブラリのインポート コネクションの確立 コネクション配下にある最初の機体の情 報の取得 目的の場所に移動させるサンプルです
  29. 29. 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_type time.sleep(1) armedにし、目的の高度まで飛び上がる 関数(手続)を定義します メッセージを出します モードが’INITIALISING’であれば、 「初期化待ち」を表示して 1秒待ちます GPSが有効になるまで メッセージを出して 1秒待ちます 機体とGPSの初期化をします GPSのfix_typeが2次元未満の場合は、 GPSは無効の状態です
  30. 30. 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’とは、通過点通りに飛 行する以外のモードです
  31. 31. Simple Go To (Copter) (4) print "Taking off!“ vehicle.commands.takeoff(aTargetAltitude) vehicle.flush() メッセージを出します 目的の高度まで飛行するコマンドを出し 反映させます 飛び立ちます
  32. 32. 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秒待ちます 目的の高度になるまで処理を待ちます
  33. 33. 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秒待ちます(多分その間に飛行する) 帰投モードにします 反映させます メインのコントロールです
  34. 34. Follow Me(1) import gps import socket import time from droneapi.lib import VehicleMode, Location ライブラリのインポート このサンプルでは、GPSデーモンと通信し て、その位置に移動させるために、今ま でとはちょっと違うライブラリもインポート しています 「付いて来る」
  35. 35. 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.commands is_guided = False gpsd = gps. gps ( mode = gps. WATCH_ENABLE) 「付いて来る」関数を定義します 例外処理を考慮します いつもの準備 モードが’INITIALISING’であれば、 「後にしろ」を表示して おしまい Commandを取得します GPSが取得出来るようにしま す 機体とGPSの初期化をします
  36. 36. 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 = 30 dest = Location(gpsd.fix.latitude, gpsd.fix.longitude, altitude, is_relative=True) print "Going to: %s" % dest cmds.goto(dest) is_guided = True v.flush() time.sleep(2) APIが生きている間 GPSデータを取得します モードに矛盾があったら停止 GPSデータが有効であれば 高さを30mにして GPSから取得した位置で Locationを作り、 Locationを表示し Locationに行くように指示 反映させて 2秒待ちます 「付いて来る」の本体
  37. 37. 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の例外の場合 メッセージを出します 例外処理
  38. 38. おまけ(DroneKitのbuild) git clone git://github.com/diydrones/ardupilot.git sudo apt-get install python-matplotlib python- serial python-wxgtk2.8 python-lxml sudo apt-get install python-scipy python-opencv ccache gawk git python-pip python-pexpect sudo pip install pymavlink MAVProxy cd ardupilot export PATH=$PATH:$HOME/ardupilot/jsbsim/src export PATH=$PATH:$HOME/ardupilot/Tools/autotest sim_vehicle.sh -w ソースを取得 いろいろ必要なものをインストール 環境変数作る Buildもこの中で勝手にしてくれる IA64、RaspberryPi上で可能(Ubuntu 14)

×