箱庭ドローンシミュレータ_PythonAPI編

426 Views

January 04, 26

スライド概要

この教材では、箱庭ドローンシミュレータとPythonプログラムを連携させてドローンを制御する仕組みを説明します。事前にシミュレータ、コア、Python 3.12、lmdisk、箱庭PDUライブラリをインストールし、サンプルコードを基に自分のプログラムを作成します。提供される基本7つのAPI(離陸、位置取得、目的地移動、荷物運搬、カメラ撮影、LiDARによる障害物検出、着陸)を使って、ミッションの実装方法や座標系(ENU と左手系)の違いも解説します。これにより、教育現場や学習者が実際にドローン操作を体験できるようになります。

おすすめタグ:ドローンシミュレーション,Python,API,Unity,教育

profile-image

組込みエンジニアを30年以上やってます。 最近は、ドローンシミュレータの開発を行っており、箱庭ドローンシミュレータの開発をしています。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

箱庭ドローンシミュレータ PYTHON API教育編 Pythonプログラムを使ったドローン制御を学ぶ エデュケーションWG

2.

目次 1. 箱庭ドローンシミュレータ Pythonプログラム動作仕組み 2. 箱庭ドローンシミュレータ Python APIの解説 3. 箱庭ドローンシミュレータ Python APIを使った演習 このカリキュラム で学ぶこと 2

3.

箱庭ドローンシミュレータ PYTHONプログラム動作仕組み 箱庭ドローンシミュレータとPythonプログラム制御の動作の 仕組みを学ぶ 3

4.

箱庭ドローンシミュレータのPython動作 • 箱庭コアをハブとして、箱庭ドローンシミュレータと箱庭ドローンAPI制御のア セットを連携動作させることでドローンを操縦します。 PDU通信を使って 連携 Pythonを使った APIを使って ドローンを動かす Unityを使った ドローン操縦 の視覚化 4

5.

箱庭ドローンシミュレータ PYTHON APIの説明 箱庭ドローンシミュレータを実際に動作させるPython API 群について学ぶ 5

6.

箱庭ドローンシミュレータ Python API群 • 箱庭ドローンシミュレータ Python API以下の基本7個があります。 • ドローンを離陸させる • ドローンの現在位置を取得する • ドローンを目的地に移動させる • ドローンで荷物を運ぶ • ドローン前方カメラで撮影する • ドローンのLiDARで障害物を検出する • ドローンを着陸させる 6

7.

箱庭ドローンシミュレータ Python API群 箱庭ドローンを操作するAPIセットは基本7個あります。 現在位置を 取得する 着陸する 離陸する カメラ撮影する 障害物を検出する 目的地へ 移動する 荷物を運ぶ 7

8.

箱庭ドローンシミュレータ Python API群 Pythonアプリ ドローンを操縦 様々なミッションを コントロール Python APIライブラリ 箱庭ドローンシミュレータ 箱庭ドローンを 操作するため のAPIセット Unityの3Dモデル で作成された ドローン 今回はここ を学ぶ 8

9.
[beta]
箱庭ドローンシミュレータ Python API群
• 事前準備
• 箱庭ドローンシミュレータのインストール
• 箱庭コアのインストール
• Python(Version 3.12)のインストール
• lmdiskのインストール
• 箱庭PDUライブラリのインストール

• Python APIのサンプルプログラム

import sys
# 箱庭ドローンシミュレータ用のライブラリをインポート
import hakoniwa_pdu.apps.drone.hakosim as hakosim

def main():
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <config_path>")
return 1
# 箱庭ドローンシミュレータを利用するためのオブジェクト取得
# custom.jsonが必要になるので引数で渡す
# connect to the HakoSim simulator
client = hakosim.MultirotorClient(sys.argv[1], "Drone")
# オブジェクトの初期化
client.confirmConnection()
client.enableApiControl(True)
client.armDisarm(True)
#ここに自分のプログラムを書きます

• サンプルプログラムをベースに自分の

プログラムを作成していきます。

return 0
if __name__ == "__main__":
sys.exit(main())

9

10.

箱庭ドローンシミュレータ PYTHON APIの説明 箱庭ドローンシミュレータのPython APIの詳細説明 ここ重要 10

11.

API1:離陸する • API名:takeoff • 引数で指定した高さ(単位:メートル)まで浮上します。 離陸する # 3m浮上 client.takeoff(3) 11

12.

API2:現在位置を取得する • API名:simGetVehiclePose • ドローンの現在位置を姿勢を取得できます。 現在位置を 取得する # ドローンの現在位置と姿勢を取得 pose = client.simGetVehiclePose() # 現在位置をデバッグ出力 print(f"POS : {pose.position.x_val} {pose.position.y_val} {pose.position.z_val}") # 姿勢情報は、クォータニオンであるため、オイラー角(ラジアン)に変換します roll, pitch, yaw = hakosim.hakosim_types.Quaternionr.quaternion_to_euler(pose.orientation) # オイラー角を度に変換して、デバッグ出力 print(f"ANGLE: {math.degrees(roll)} {math.degrees(pitch)} {math.degrees(yaw)}") 12

13.

API3:目的地に移動する • API名:moveToPosition • 目的地へ移動させます。 目的地へ 移動する # ドローを目的地へ移動させます # X軸の位置:10m # Y軸の位置:0m # 高度:3m # 機首の方向:0度 client.moveToPosition(x=10, y=0, z=3, speed=3, yaw_deg=0) • 補足: • speedは最大で3m/sec程度で移動します。 • 現時点では、目標速度での移動は未サポートです。 13

14.

API4:荷物を運ぶ • API名:grab_baggage • スイッチングマグネットホルダーを使って、荷物の吸引およ びその解除を操作します # 荷物配置場所(baggage_pos)へ移動します client.moveToPosition(baggage_pos['x'], baggage_pos['y'], 3, 0, -90) client.moveToPosition(baggage_pos['x'], baggage_pos['y'], 3, 5) client.moveToPosition(baggage_pos['x'], baggage_pos['y'], 3, 5, 0) # 荷物を吸引できる位置まで高度まを下げます client.moveToPosition(baggage_pos['x'], baggage_pos['y'], 0.7, 0.01, 0) # 荷物を吸引し、高度を上げます client.grab_baggage(True) client.moveToPosition(baggage_pos['x'], baggage_pos['y'], 3, 0.01) # 荷物を下ろす場所(transfer_pos)へ移動します client.moveToPosition(transfer_pos['x'], transfer_pos['y'], 3, 0.1) client.moveToPosition(transfer_pos['x'], transfer_pos['y'], transfer_pos['z'], 0.01) # 荷物を下ろします client.grab_baggage(False) 荷物を運ぶ • 補足: • 荷物を吸引する条件は、ド ローン直下1m以下に存在 するすべての荷物が対象とな ります 14

15.

API5:カメラ撮影する(その1) • API名:simGetImage • カメラ設置位置(デフォルト:前方)からカメラ撮影します。 # 引数は必ず以下値としてください # id = “0” # image_type = hakosim.ImageType.Scene png_image = client.simGetImage("0", hakosim.ImageType.Scene) カメラ撮影する # ファイル名をscene.pngとしてファイル保存します。ファイルは、Pythonプログラム実行場所に出力されます。 if png_image: with open("scene.png", "wb") as f: f.write(png_image) • 補足: • カメラは複数配置できませんので、常にidには”0”を指定してください。 • image_typeは、ImageType.sceneのみサポートしています。 15

16.

API5:カメラ撮影する(その2) • API名:simSetCameraOrientation • カメラのピッチ角を変更します。 # 引数は必ず以下値としてください # id = “0” client.simSetCameraOrientation("0", degree=-90) png_image = client.simGetImage("0", hakosim.ImageType.Scene) カメラ撮影する # ファイル名をscene.pngとしてファイル保存します。ファイルは、Pythonプログラム実行場所に出力されます。 if png_image: with open("scene.png", "wb") as f: f.write(png_image) • 補足:degreeは下向きがマイナスです。上向きはプラスです。 • 前方真正面は0度、下向きの最大角度は-90度、上向きは+15度です。 16

17.
[beta]
API6:障害物を検出する

• API名:getLidarData

• レーザ照射し、障害物の位置を取得します。本APIは、AirSimのLiDAR

のAPI仕様に準拠していますので、詳細はこちらを参照ください。

# LiDARデータを取得します
lidarData = client.getLidarData()
if (len(lidarData.point_cloud) < 3):
print("¥tNo points received from Lidar data")
else:
print(f"len: {len(lidarData.point_cloud)}")
# 障害物情報はポイントクラウドというデータで返されますので、parse_lidarData()で整形します。
points = parse_lidarData(lidarData)
# 障害物の情報をデバッグ出力します。pointsに位置情報が入っていますので、このデータを走査すれば障害物の位置を特定できます
print("¥tReading: time_stamp: %d number_of_points: %d" % (lidarData.time_stamp, len(points)))
# LiDARの取り付け位置と姿勢情報も参照できます
print("¥t¥tlidar position: %s" % (pprint.pformat(lidarData.pose.position)))
print("¥t¥tlidar orientation: %s" % (pprint.pformat(lidarData.pose.orientation)))

障害物を検出する

def parse_lidarData(data):
# reshape array of floats to array of [X,Y,Z]
points = numpy.array(data.point_cloud, dtype=numpy.dtype('f4’))
points = numpy.reshape(points, (int(points.shape[0]/3), 3))
return points

17

18.

API7:着陸する • API名:land 着陸する • ドローンを着陸させます # 着陸 client.land() 18

19.

箱庭ドローンシミュレータ PYTHON API操縦 箱庭ドローンシミュレータPython APIを利用するにあたって の前提知識 ここかなり重要!! 19

20.

座標系:箱庭ドローン Python API X • ENU座標系です(右図) • X:前方方向(E(East):前がプラス) • Y:横方向(N(North):左がプラス) • Z:上方向(U(Up):上がプラス) Y 参考:ROSの座標系と同じです。 BlanderやCAD系では3D空間をXY平面、Zを高さ と捉えることが多い。 → 物理計算のし易さを優先していると言われている。 → OpenGLなど学術的な部分では「数式の美しさと 物理法則の整合性」を優先したと言われている。 Z 右手系:親指上、右回り 親指 :Z 人差し指 :X 中指 :Y 20

21.

座標系:Unity Z • 左手座標系です(右図) • X:横方向(右がプラス) • Y:上方向(上がプラス) • Z:前方向(前がプラス) 2D グラフィック(Xが左右、Yが上下)に奥行き(Z軸) を付け足したとされている。 → ゲーム画面の直観的に分り易いとされている。 → MicrosoftのDirect Xが左手系座標を採用して いるためとも言われている。 X Y 左手系:親指上、左回り 親指 :Y 人差し指 :Z 中指 :X 21

22.

座標系まとめ • ENUは右手系 • 親指が上(Z)、人差し指が前(X)、中指が左(Y) • Unityは左手系 • 親指が上(Y)、人差し指が前(Z)、中指が左(X) 座標系 前後 左右 上下 ENU +X +Y +Z Unity +Z +X +Y 実際に左手を使って 体感してみよう! 22

23.

座標系の課題 • 箱庭ドローンシミュレータでは、ENU座標を採用しています。Unityでのビジュ アライズの座標は異なる座標を使っています。 • Python API moveToPosition(x, y, z, speed, yaw_deg)はENU座標系が前 提となっています。 • 課題1 • Unity画面で見た場合、ドローンを「右方向へ1m進む」はENU座標をどう指定したらよ いでしょうか? • 課題2 • ENU座標系でx=1,y=0.5を指定した場合にUnity画面でドローンはどう動くでしょう か? 23

24.

箱庭ドローンシミュレータ PYTHON API演習 ここからは、実際にプログラミングしながら、ドローンの動きを理 解していくよ!! ドローン動かすよ 24

25.

演習1-1 • Unity上のドローンを1m離陸させて、3秒ホバリングして、着陸させましょう。 離陸 ホバリング (3秒) 着陸 25

26.

演習1-2 • Unity上のドローンを1m離陸させて、3秒ホバリングして、位置情報を表示し てから、着陸させましょう。 位置情報表示 離陸 ホバリング (3秒) 着陸 26

27.

演習1-3 • Unity上のドローンを1m離陸させて、1m前進して、3秒ホバリングして、着 陸させましょう。 離陸 1m前進 ホバリング (3秒) 着陸 27

28.

演習2 • Unity上のドローンで以下の部分を対応しましょう。 • 離陸 1m • カメラでの撮影 • カメラ向きの変更して撮影 • LiDARデータの取得 • 着陸 カメラ撮影 着陸 離陸 LiDARデータ取得 28

29.

箱庭ドローンシミュレータ PYTHON APIリファレンスマニュアル 参考にしてね! 29

30.

Python APIリファレンスマニュアル メソッド 概要 主な引数 __init__(config_path) 設定ファイルパスを指定してクライアントを初期化 config_path (str): PDU設定ファイルのパス confirmConnection() シミュレーション環境との接続確認 なし enableApiControl(v, vehicle_name=None) API制御の有効/無効を設定 armDisarm(v, vehicle_name=None) ドローンのアーム/ディスアーム simGetVehiclePose(vehicle_name=None) ENU座標系での位置・姿勢取得 simGetVehiclePoseUnityFrame(vehicle_name=No Unity座標系での位置・姿勢取得 ne) takeoff(height, vehicle_name=None) 指定高度まで離陸 moveToPosition(x, y, z, speed, yaw_deg=None, timeout_sec=-1, vehicle_name=None) ENU座標系で指定位置へ移動 v (bool): True=有効 vehicle_name (str, 任意) v (bool): True=アーム vehicle_name (str, 任意) vehicle_name (str, 任意) vehicle_name (str, 任意) height (float) x,y,z (float), speed (float) 30

31.

Python APIリファレンスマニュアル メソッド land(vehicle_name=None) grab_baggage(grab, timeout_sec=-1, vehicle_name=None) 概要 着陸 主な引数 vehicle_name (str, 任意) 荷物のつかみ/離し grab (bool) simGetImage(id, image_type, vehicle_name=None) カメラ画像取得 id (int), image_type (str) simSetCameraOrientation(id, degree, vehicle_name=None) カメラ向き設定 id (int), degree (float) getLidarData(vehicle_name=None) LiDARデータ取得 vehicle_name (str, 任意) getGameJoystickData(vehicle_name=None) ゲームパッドデータ取得 vehicle_name (str, 任意) putGameJoystickData(data, vehicle_name=None) ゲームパッドデータ送信 data 31