9.3K Views
March 02, 26
スライド概要
■ドローンやロボットを自作することを通じて制御や関連技術の生涯勉強情報を提供■工学博士■防大航空宇宙→筑波大博士■陸自→対戦車誘導弾等の装備品開発→高専教員→大学教員■ロボットランサー優勝→マイクロマウスニューテクノロジー賞受賞■指導者としてつくばチャレンジバンナム賞→飛行ロボコンマルチコプタ部門1位等々■北海道函館出身
StampFly 勉強会 2026 ドローン制御工学ハンズオン ワークショップ 伊藤 恒平 2026/3/2 – 3/6 伊藤 恒平 StampFly 勉強会 2026 1 / 156
資料ダウンロード / Slide Download Docswell スライド資料はこちらからダウン ロードできます https://www.docswell.com/s/Kouhei_Ito/ KLV77G-2026-03-02-010945 伊藤 恒平 StampFly 勉強会 2026 2 / 156
GitHub リポジトリ / GitHub Repository stampfly_ecosystem ファームウェア・ツール・資料の 全ソースコード https://github.com/M5Fly-kanazawa/ stampfly_ecosystem 伊藤 恒平 StampFly 勉強会 2026 3 / 156
工場出荷状態に戻す / Restore Factory Firmware 注意 ワークショップを進めると、機体・送信機のファームウェアは上書きされます。 工場出荷状態に戻したい場合は、以下のコマンドを実行してください。 機体(Vehicle)を工場出荷状態に戻す 1 sf flash vehicle --legacy 送信機(Controller)を工場出荷状態に戻す 1 sf flash controller --legacy 注意: 事前に source setup_env.sh で開発環境をセットアップしてください。 デバイスを USB 接続した状態で実行してください。 伊藤 恒平 StampFly 勉強会 2026 4 / 156
リポジトリの更新 / Sync Repository 通常の更新 git pull でリモートの最新変更を取り込む 1 2 cd ~/ stampfly_ecosystem git pull git pull でエラーが出た場合 ローカルの変更がリモートと競合すると pull が失敗する。その場合はローカルを破棄してリモート に強制一致させる: git fetch origin git reset --hard origin/main 3 git clean -fd 1 2 注意: ローカルの変更・追加ファイルはすべて失われます。 伊藤 恒平 StampFly 勉強会 2026 5 / 156
Lesson 0 環境セットアップ Environment Setup StampFly Workshop
ワークショップカリキュラム / Workshop Curriculum Day Day 1 Day 2 Day 3 Day 4 Day 5 AM 伊藤 恒平 Lesson 0–2 3–5 6–8 9 – 12 13 テーマ 環境セットアップ + モータ + コントローラ LED + IMU + 初フライト モデリング + システム同定 + PID 制御 姿勢推定 + API + 独自 FW + Python SDK 精密着陸競技会 StampFly 勉強会 2026 7 / 156
StampFly ハードウェア / Hardware 項目 MCU IMU 気圧 ToF 質量 通信 バッテリ 伊藤 恒平 StampFly 勉強会 2026 仕様 ESP32-S3 (M5Stamp S3) BMI270 (6 軸 400 Hz) BMP280 VL53L3CX 37 g(バッテリ含む) ESP-NOW + WiFi LiPo 1S 3.7 V 8 / 156
エコシステム全体像 / Ecosystem Overview control/ 制御を設計 改善点を FB 設計を改善 PID パラメータ simulator/ firmware/ 仮想テスト 安全に検証 テレメトリ 実装して飛ばす tools/ protocol/ sf CLI 通信仕様 SSOT analysis/ データ解析 全体を支えるインフラ 伊藤 恒平 StampFly 勉強会 2026 9 / 156
開発ツール sf CLI / Development Tool カテゴリ ビルド 診断 ログ シミュレータ キャリブレーション コマンド例 sf build / sf flash sf doctor / sf monitor sf log wifi / sf log viz sf sim run sf cal gyro/accel/mag 説明 ファームウェア開発 デバッグ テレメトリ取得・可視化 仮想環境で練習 センサ校正 ワークショップの基本ワークフロー(各レッスン共通) sf lesson switch N → sf lesson build → sf lesson flash レッスン切替 → ビルド → 書き込みの 3 ステップで、 コードを書いてすぐに実機で動作確認できます。 伊藤 恒平 StampFly 勉強会 2026 10 / 156
Windows 環境構築 (1/2) / Windows Setup 確認コマンド (CMD) git --version python --version 期待される結果 git version 2.x Python 3.8 以上 なければ winget install Git.Git winget install Python.Python.3.12 インストール手順(CMD で実行) 1. リポジトリをクローン 2. install.bat を実行(ESP-IDF + sfcli 自動インストール) 3. setup_env.bat で開発環境をアクティベート git clone https :// github .com/M5Fly - kanazawa / stampfly_ecosystem cd stampfly_ecosystem install .bat setup_env .bat 伊藤 恒平 StampFly 勉強会 2026 11 / 156
Windows 環境構築 (2/2) / Driver & Verification USB シリアルドライバ CH9102F ドライバをインストール(M5Stack 製品用) https://docs.m5stack.com/en/download 動作確認 sf doctor で環境診断 — すべて OK になれば完了 macOS / Linux ユーザー install.sh + setup_env.sh を使用してください 伊藤 恒平 StampFly 勉強会 2026 12 / 156
今日のゴール / Today’s Goal 目標 ワークショップファームウェアをビルド・書き込み・動作確認する 1 sf lesson build でビルド 2 sf lesson flash で書き込み 3 シリアルモニタで "Hello StampFly!" を確認 sf lesson switch N sf lesson build sf lesson flash Serial Monitor student.cpp → user_code.cpp ESP-IDF compile USB flash + monitor verify output modify code & rebuild 伊藤 恒平 StampFly 勉強会 2026 13 / 156
sf CLI とは / What is sf CLI? StampFly 開発専用のコマンドラインツール ESP-IDF のコマンドをシンプルに実行できる コマンド sf doctor sf lesson build sf lesson flash sf lesson switch N sf monitor 伊藤 恒平 説明 環境診断 ワークショップビルド 書き込み+モニタ レッスン切り替え シリアルモニタ StampFly 勉強会 2026 14 / 156
ワークショップの構造 / Workshop Structure 学生が実装する関数は 2 つだけ! setup() — 起動時に 1 回呼ばれる loop_400Hz(dt) — 400Hz(2.5ms 毎)で呼ばれる ハードウェアの複雑さは ws:: 名前空間で隠蔽 FreeRTOS, SPI/I2C, センサーフュージョンを意識する必要なし 伊藤 恒平 StampFly 勉強会 2026 15 / 156
ファームウェアの全体像 / Firmware Architecture user_code.cpp ← You are here! setup() / loop_400Hz() 皆さんのコードはここ! user_code.cpp を編集するだけ sensor read, filter, motor ws::gyro_x() と書くだけで SPI 通信→フィルタ→バイアス補正を 全部やってくれる ws:: API gyro_x(), motor_set_duty() Vehicle Components IMU, baro, motor driver xTaskCreate, xQueueSend 下のレイヤーはワークショップ中 意識する必要なし ESP-IDF / FreeRTOS Tasks, timers, queues SPI, I2C, GPIO Hardware ESP32-S3, BMI270, BMP280 伊藤 恒平 StampFly 勉強会 2026 16 / 156
400Hz ループの裏側 / Behind the 400Hz Loop ESP Timer 2500 µs IMU Task Read BMI270 Go! loop_400Hz (Your Code) hardware timer interrupt SPI read + bias correction data ready user_code.cpp runs here repeats every 2.5 ms = 400 Hz ポイント loop_400Hz(dt) は常に IMU データ更新後に呼ばれる— 学生はタイ マー管理不要、ただ関数を書くだけ! 伊藤 恒平 StampFly 勉強会 2026 17 / 156
実習: Hello StampFly / Hands-on
user_code.cpp
# include "workshop_api.hpp"
void setup () {
3
ws:: print("Hello StampFly!");
4 }
5 void loop_400Hz(float dt) {
6
// Nothing to do in Lesson 0
7 }
1
2
手順
1. sf lesson switch 0
2. 上のコードを user_code.cpp に書く
3. sf lesson build && sf lesson flash
伊藤 恒平
StampFly 勉強会 2026
18 / 156
作業の進め方 / Workflow ファイル構造 firmware/workshop/ ├── lessons/ │ ├── lesson_00/student.cpp │ ├── lesson_01/student.cpp │ └── ... └── main/ └── user_code.cpp ← 編集! 1 sf lesson switch N テンプレートを user_code.cpp にコ ピー 2 user_code.cpp を編集 3 sf lesson build 4 sf lesson flash 注意 student.cpp はテンプレートなので直接編集しない! switch で何度でもリセットできる 伊藤 恒平 StampFly 勉強会 2026 19 / 156
コントローラのセットアップ / Controller Setup コントローラのビルドと書き込み 1 コントローラを USB 接続 2 sf build controller 3 sf flash controller 確認 LCD に起動画面が表示されれば OK Lesson 2 でペアリングして使用する 伊藤 恒平 StampFly 勉強会 2026 20 / 156
シミュレータで遊ぶ / Try the Simulator USB HID モードに切替 1 画面タッチでメニューを開く 2 Comm: を選択 3 USB HID に切替 → 自動再起動 操作 スロットル ロール / ピッチ ヨー 説明 上昇 傾き 回転 アクロモード(角速度制御)で飛行 コマンド sf sim run sf sim run -w ringworld 注意 終了後は Comm: を ESP-NOW に戻すこと(実機飛行用) 伊藤 恒平 StampFly 勉強会 2026 21 / 156
チェックポイント / Checkpoint 確認事項 sf doctor がエラーなしで通る ビルドが成功し "Hello StampFly!" が表示される コントローラのビルド・書き込みが完了した シミュレータが起動し操縦を試した 次のレッスン Lesson 1: モータ制御 — モータを回してプロペラの動きを確認 伊藤 恒平 StampFly 勉強会 2026 22 / 156
Lesson 1 モータ制御 Motor Control StampFly Workshop
今日のゴール / Today’s Goal 目標 モータの番号と配置を理解し、PWM で個別制御する モータ番号 M1–M4 の位置を覚える ARM / DISARM の仕組みを理解する PWM デューティ比でモータ回転数を制御 伊藤 恒平 StampFly 勉強会 2026 24 / 156
モータ配置 / Motor Layout FL FR M4 CW Front M1 CCW M2 CW ESP32 M3 CCW RL RR CW (clockwise) CCW (counter-clockwise) 対角のモータが同じ方向に回転(トルクバランス) M1(FR), M3(RL) = CCW / M2(RR), M4(FL) = CW 伊藤 恒平 StampFly 勉強会 2026 25 / 156
PWM とは / What is PWM? PWM Duty Cycle 0% T Duty Cycle 25% 50% Pulse Width Modulation (パルス幅変調) Duty 0% = 停止 Duty 100% = 最大回転 API: motor_set_duty(id, duty) id=1–4, duty=0.0–1.0 100% 伊藤 恒平 StampFly 勉強会 2026 26 / 156
ARM / DISARM とは / What is ARM? 安全スイッチ / Safety Switch ARM = モーター出力を有効化(回転可能になる) DISARM = モーター出力を無効化(強制停止) コードから arm() で ARM できる 重要 / Important arm() を呼ばないとモーターは回らない! setup() 内で最初に呼ぶこと 伊藤 恒平 StampFly 勉強会 2026 27 / 156
モータ制御 API 関数 arm() disarm() motor_set_duty(id, duty) motor_set_all(duty) motor_stop_all() 説明 モーター出力を有効化 モーター出力を無効化 個別モータ設定 全モータ一括 全モータ停止 引数 — — id=1–4, duty=0.0–1.0 duty=0.0–1.0 — 安全注意 / Safety duty は 0.15 以下で! 機体を手で押さえてテスト! 伊藤 恒平 StampFly 勉強会 2026 28 / 156
実習: モータを順番に回す / Hands-on
user_code.cpp
1
2
# include "workshop_api.hpp"
static uint32_t timer = 0;
3
void setup () {
ws:: print("Lesson 1: Motor Control");
6
ws::arm (); // Enable motor output
7 }
8 void loop_400Hz(float dt) {
9
timer ++;
10
// 800 ticks = 2 seconds at 400 Hz
11
int motor_id = (timer / 800) % 4 + 1;
12
ws:: motor_stop_all ();
13
ws:: motor_set_duty(motor_id , 0.1f);
14 }
4
5
伊藤 恒平
StampFly 勉強会 2026
29 / 156
チェックポイント / Checkpoint 確認事項 arm() なしではモータが回らないことを確認した M1 が FR(右前)のプロペラを回す M1→M2→M3→M4 の順に回転する 次のレッスン Lesson 2: コントローラ入力 — スティックでモータを操作 伊藤 恒平 StampFly 勉強会 2026 30 / 156
Lesson 2 コントローラ入力 Controller Input StampFly Workshop
今日のゴール / Today’s Goal 目標: スティック値を変数に読み取り、演算でモータを個 別制御する ESP-NOW 無線通信の仕組みを理解 チャンネル設定で他の受講生との混信を回避 変数と四則演算でスティック → モータ Duty を計算 オープンループ手動操縦の限界を体感 伊藤 恒平 StampFly 勉強会 2026 32 / 156
ESP-NOW 通信フロー / Communication Flow Controller Wireless Left Stick Right Stick Throttle / Yaw Roll / Pitch 伊藤 恒平 ESP-NOW 2.4 GHz StampFly 勉強会 2026 StampFly rc_throttle() rc_roll() 0.0 – 1.0 ±1.0 rc_pitch() rc_yaw() ±1.0 ±1.0 33 / 156
コントローラ各部 / Controller Layout (MODE 3) Alt Hold / Manual (予定) Power SW Pitch l Roll ↔ STABILIZE / ACRO MODE 3 Throttle l Yaw ↔ Push: Flip Push: ARM (予定) M5 Button (LCD) タップでペアリング等 伊藤 恒平 StampFly 勉強会 2026 34 / 156
コントローラ API 関数 set_channel(ch) rc_throttle() rc_roll() rc_pitch() rc_yaw() is_armed() motor_set_duty(id, v) 伊藤 恒平 説明 WiFi チャンネル設定 スロットル ロール ピッチ ヨー ARM 状態 モータ個別制御 StampFly 勉強会 2026 値域 1, 6, 11 0.0 – 1.0 -1.0 – +1.0 -1.0 – +1.0 -1.0 – +1.0 true / false id=1–4, v=0.0–1.0 35 / 156
ペアリング手順 / Pairing Step 操作 1 コントローラの M5 ボタンを押しながら電源 ON → LCD に “Pairing mode...” 表示 2 StampFly のボタンを 3 秒長押し → 青 LED 高速点滅 + ビープ音 3 ペアリング完了 → ビープ音が鳴り、次回から自動接続 注意 教室では一組ずつペアリングする(ブロードキャスト通信のた め近くの機体と干渉する可能性) うまくいかない場合: 両方を再起動して Step 1 からやり直す 伊藤 恒平 StampFly 勉強会 2026 36 / 156
チャンネル設定 / Channel Setting 教室で複数の StampFly を同時に飛ばすと、同じチャンネル同士で混 信が起きる。チャンネルを分けて回避する。 Ch 1 6 11 割り当て例 グループ A(緑) グループ B(黄) グループ C(赤) 伊藤 恒平 設定方法 set_channel(ch) を setup() 内で 呼ぶ 機体とコントローラで同じ番号にする こと! StampFly 勉強会 2026 37 / 156
モータ配置とミキシング / Motor Layout & Mixing FL FR M4 CW Front M1 CCW M2 CW Motor M1 FR M2 RR M3 RL M4 FL ESP32 M3 CCW RL 伊藤 恒平 Roll − − + + Pitch + − − + Yaw + − + − 直感的に理解する RR CW (clockwise) T + + + + Pitch+ → 前傾 → 前 (M1,M4) 強 + 後 (M2,M3) 弱 Roll+ → 右傾 → 右 (M1,M2) 弱 + 左 (M3,M4) 強 CCW (counter-clockwise) StampFly 勉強会 2026 38 / 156
オープンループ制御 / Open-Loop Control Open-Loop Control Controller −1.0 ∼ +1.0 Stick Scaling × gain 0.0 ∼ 1.0 Motor PWM duty StampFly Drone No Feedback! 問題点 フィードバックがないため、外乱(風・重心ずれ)に対応できない! → Lesson 5/8 で PID 制御を導入して解決 伊藤 恒平 StampFly 勉強会 2026 39 / 156
実習: 手動ミキシング (1/2) / Hands-on: Setup
user_code.cpp — setup
# include "workshop_api.hpp"
static uint32_t tick = 0;
3 void setup () {
4
ws:: print("L2: Open -Loop Control");
5
ws::arm ();
// Enable motor output
6
ws:: set_channel (1);
// 1, 6, or 11
7 }
1
2
チャンネル番号
講師が指定した番号(1 / 6 / 11)に書き換えること!
コントローラも同じチャンネルに設定する
伊藤 恒平
StampFly 勉強会 2026
40 / 156
実習: 手動ミキシング (2/2) / Hands-on: Loop
user_code.cpp — loop
void loop_400Hz(float dt) {
tick ++;
3
float t = ws:: rc_throttle ();
4
float r = ws:: rc_roll () * 0.3f;
5
float p = ws:: rc_pitch () * 0.3f;
6
float y = ws:: rc_yaw ()
* 0.3f;
7
ws:: motor_set_duty (1, t - r + p + y); // FR
8
ws:: motor_set_duty (2, t - r - p - y); // RR
9
ws:: motor_set_duty (3, t + r - p + y); // RL
10
ws:: motor_set_duty (4, t + r + p - y); // FL
11
if (tick % 80 == 0)
12
ws:: print("T=%.2f R=%.2f P=%.2f Y=%.2f",
13
t, r, p, y);
14 }
1
2
伊藤 恒平
StampFly 勉強会 2026
41 / 156
チェックポイント / Checkpoint 確認事項 指定チャンネルで混信なく通信できた コントローラとペアリングできた スロットルで全モータが均等に回る ピッチスティックで前後モータの回転差が出る 次のレッスン Lesson 3: LED 制御 — システム状態を LED で可視化 伊藤 恒平 StampFly 勉強会 2026 42 / 156
Lesson 3 LED 制御 LED Control StampFly Workshop
今日のゴール / Today’s Goal 目標 LED でシステムの状態(ARM / DISARM)とバッテリー残量を可視 化する WS2812 アドレサブル LED の制御 状態遷移の考え方(ステートマシン) バッテリー電圧のモニタリング 伊藤 恒平 StampFly 勉強会 2026 44 / 156
LED 状態遷移 / LED State Machine is_armed() == true Power ON DISARM ARM Green Battery gradient 3.3 V = Red → 4.2 V = Green is_armed() == false led_color(0, 255, 0) led_color(r, g, 0) 伊藤 恒平 StampFly 勉強会 2026 45 / 156
LED 制御 API 関数 disable_led_task() enable_led_task() led_color(r, g, b) is_armed() battery_voltage() 説明 システム LED 更新を無効化 システム LED 更新を再有効化 LED 色設定 ARM 状態確認 バッテリー電圧 引数 — — 各 0–255 true / false 3.0–4.2 V WS2812 LED RGB フルカラー(各チャンネル 8bit = 1677 万色) 1 本のデータ線で制御(ESP32 RMT ペリフェラル使用) led_color() は裏表両方の LED を同じ色に設定 伊藤 恒平 StampFly 勉強会 2026 46 / 156
バッテリー電圧と色 / Battery Voltage & Color 3.3 V 危険 3.75 V 4.2 V 満充電 LiPo バッテリー: 3.3V(空)〜 4.2V(満充電) 3.3V 以下で使用禁止! バッテリーが損傷します 伊藤 恒平 StampFly 勉強会 2026 47 / 156
実習: ARM 状態で LED 色を変える / Hands-on
user_code.cpp
# include "workshop_api.hpp"
void setup () {
3
ws:: print("Lesson 3: LED Control");
4
ws:: disable_led_task ();
5
ws:: set_channel (1);
6 }
7 void loop_400Hz(float dt) {
8
if (ws:: is_armed ()) {
9
ws:: led_color (0, 255, 0); // Armed : green
10
} else {
11
float v = ws:: battery_voltage ();
12
float lv = (v - 3.3f) / 0.9f; // 3.3 -4.2V -> 0-1
13
lv = (lv < 0) ? 0 : (lv > 1) ? 1 : lv;
14
ws:: led_color (255*(1 - lv), 255*lv , 0);
15
}
16 }
1
2
伊藤 恒平
StampFly 勉強会 2026
48 / 156
チェックポイント / Checkpoint 確認事項 DISARM 時に赤〜緑のグラデーション表示 ARM すると緑に変わる バッテリー残量に応じて色が変化する 次のレッスン Lesson 4: IMU センサー — 加速度・ジャイロで姿勢を知る 伊藤 恒平 StampFly 勉強会 2026 49 / 156
Lesson 4 IMU センサー IMU Sensor StampFly Workshop
今日のゴール / Today’s Goal 目標 IMU(ジャイロ+加速度)データを読み取り、シリアルモニタと WiFi テレメトリで確認する NED 座標系(北-東-下)の理解 ジャイロスコープで角速度を取得 加速度センサで並進加速度を取得 WiFi テレメトリでデータ取得・可視化 伊藤 恒平 StampFly 勉強会 2026 51 / 156
NED 座標系 / NED Coordinate System X (Forward) Roll Pitch Y (Right) Yaw Z (Down) BMI270 IMU — 6 軸(3 軸ジャイロ + 3 軸加速度)400 Hz ロ正方向(右手の法則) 伊藤 恒平 StampFly 勉強会 2026 | 回転矢印 = ジャイ 52 / 156
IMU API 関数 gyro_x/y/z() accel_x/y/z() 説明 角速度 (Roll/Pitch/Yaw) 加速度 (X/Y/Z) 単位 rad/s m/s2 静止時の値 ジャイロ ≈ 0、加速度 Z ≈ −9.81 m/s2 (重力の反力、上向き) 伊藤 恒平 StampFly 勉強会 2026 53 / 156
実習: 6 軸読み取り + シリアル表示 / Hands-on
user_code.cpp
# include "workshop_api.hpp"
static uint32_t tick = 0;
3 void setup () { ws:: print("Lesson 4: IMU Sensor"); }
4 void loop_400Hz(float dt) {
5
tick ++;
6
float gx=ws:: gyro_x (), gy=ws:: gyro_y(), gz=ws:: gyro_z ();
7
float ax=ws:: accel_x (),ay=ws:: accel_y (),az=ws:: accel_z ();
8
if (tick % 40 == 0) // Print every 100 ms
9
ws:: print("G=(%.3f ,%.3f ,%.3f) A=(%.2f ,%.2f ,%.2f)",
10
gx , gy , gz , ax , ay , az);
11 }
1
2
伊藤 恒平
StampFly 勉強会 2026
54 / 156
WiFi テレメトリ受信 / Receiving WiFi Telemetry システムが IMU・姿勢・センサデータを自動的に 400 Hz で送信しています 手順 1 2 3 シリアルモニタで SSID を確認(StampFly_XXXX) PC の WiFi で StampFly に接続(IP: 192.168.4.1) sf log wifi -d 30 で 30 秒キャプチャ → CSV 自動保存 出力例 logs/stampfly_wifi_20260303T143000.csv に保存されました -o name.csv でファイル名指定、--no-save で保存なし(統計のみ) 伊藤 恒平 StampFly 勉強会 2026 55 / 156
データの可視化 / Data Visualization 保存した CSV を可視化 sf log viz logs/stampfly_wifi_*.csv モード --mode all --mode sensors --mode attitude 表示内容 全パネル(デフォルト) IMU + 高度センサ 姿勢推定(Roll/Pitch/Yaw) --save plot.png でファイル保存可能 StampFly を手で揺らしながらキャプチャし、ジャイロの変化を グラフで確認しよう 伊藤 恒平 StampFly 勉強会 2026 56 / 156
チェックポイント / Checkpoint 確認事項 シリアルモニタでジャイロ・加速度の値を確認できる 静止時に accel_z ≈ −9.81 を確認(反力) sf log wifi でセンサデータを受信できる sf log viz でデータをグラフ表示できる 次のレッスン Lesson 5: レート P 制御 — ジャイロフィードバックで初フライト 伊藤 恒平 StampFly 勉強会 2026 57 / 156
Lesson 5 レート P 制御 + 初フライト Rate P-Control + First Flight StampFly Workshop
今日のゴール / Today’s Goal 目標 比例フィードバック制御を実装し、初の制御飛行を行う 閉ループ制御の考え方 P 制御で角速度を安定化 ARM/DISARM による安全管理 伊藤 恒平 StampFly 勉強会 2026 59 / 156
閉ループ制御 / Closed-Loop Control + Target Rate r Σ e P Control Kp × e u Motor Mixer StampFly Drone angular rate response − Gyro Sensor feedback 伊藤 恒平 StampFly 勉強会 2026 60 / 156
制御 API 関数 gyro_x/y/z() rc_roll() rc_pitch() rc_yaw() rc_throttle() motor_mixer(T,R,P,Y) is_armed() 伊藤 恒平 説明 ジャイロ角速度 ロールスティック ピッチスティック ヨースティック スロットル モーターミキサー ARM 状態確認 StampFly 勉強会 2026 値域 rad/s −1.0 ∼ +1.0 −1.0 ∼ +1.0 −1.0 ∼ +1.0 0.0 ∼ 1.0 — true/false 61 / 156
実習: 3 軸 P 制御 / Hands-on
user_code.cpp
# include "workshop_api.hpp"
void setup () { ws:: print("Lesson 5: Rate P-Control"); }
3 void loop_400Hz(float dt) {
4
if (!ws:: is_armed ()) {
5
ws:: motor_stop_all (); ws:: led_color (50 ,0 ,0); return;
6
}
7
ws:: led_color (0, 50, 0); // Green = ARM
8
float Kp_rp =0.5f, Kp_yaw =2.0f, rmax =1.0f, ymax =5.0f;
9
float re = ws:: rc_roll ()* rmax - ws:: gyro_x ();
10
float pe = ws:: rc_pitch ()* rmax - ws:: gyro_y ();
11
float ye = ws:: rc_yaw ()* ymax
- ws:: gyro_z ();
12
ws:: motor_mixer(ws:: rc_throttle (),
13
Kp_rp*re , Kp_rp*pe , Kp_yaw*ye);
14 }
1
2
伊藤 恒平
StampFly 勉強会 2026
62 / 156
安全注意 / Safety フライト前チェック 保護メガネを着用 低スロットルから徐々に上げる(最初は 30% 以下) プロペラの回転方向を確認(M1=CCW, M2=CW, M3=CCW, M4=CW) 異常時はすぐにスロットルを下げて DISARM 伊藤 恒平 StampFly 勉強会 2026 63 / 156
チェックポイント / Checkpoint 確認事項 ARM 後スロットルを上げて安定ホバリング スティック操作で機体が応答する DISARM で即座にモーターが停止する 次のレッスン Lesson 6: システムモデリング — 伝達関数からゲインを設計 伊藤 恒平 StampFly 勉強会 2026 64 / 156
Lesson 6 システムモデリング System Modeling StampFly Workshop
今日のゴール / Today’s Goal 目標 プラント伝達関数を導出し、モデルに基づいて P ゲインを設計する 1 2 3 モータ+機体のプラント伝達関数 Gp (s) を理解 P 制御の閉ループ特性(ωn , ζ )を導出 ζ から Kp を設計 — L05 の初フライト経験をモデルで裏付け 伊藤 恒平 StampFly 勉強会 2026 66 / 156
物理メカニズム / Physical Mechanism duty Motor Kv τm s + 1 d [rad/s] ωm PWM → motor speed linearize at hover: [N] Propeller 2 F = Ct ωm rotation → thrust [N·m] F Geometry ×4L or ×4κ differential thrust → torque Km , Kf = 2Ct Kv ωm,h , τm s + 1 τ Rigid Body 1 I ·s [rad/s] ω torque → angular rate Km = 4L · Kf duty 信号がどうやって機体の角速度になるか — 4 つのステージ 伊藤 恒平 StampFly 勉強会 2026 67 / 156
プラントモデル(簡略化)/ Plant Model (Simplified) control input u Mixer + Motor Km τm s + 1 τ angular rate ω rigid-body rotation actuator dynamics Gp (s) = Body 1 I ·s K , s(τm s + 1) K= Km I ホバー近傍で線形化 → 2 ブロックに集約 Mixer + Motor: duty → トルク— 1 次遅れ Km /(τm s + 1) Body: トルク → 角速度— 積分器 1/(I · s) 伊藤 恒平 StampFly 勉強会 2026 68 / 156
τm と Km の導出 / Deriving τm and Km モータ時定数 τm DC モータの電気 · 機械モデルから: Jmp · Rm τm = 2 Ke + Dm Rm Jmp Rm Ke Dm τm 2.01e-8 kg·m2 0.34 Ω 6.13e-4 V/(rad/s) 3.69e-8 0.018 s ≈ 0.02 s 回転子慣性 巻線抵抗 逆起電力定数 粘性摩擦 実効プラントゲイン: 伊藤 恒平 実効トルクゲイン Km Kf : ホバー点で duty を ∆d 変えたときの 1 モータ推力変化量 ( dF 4L · Kf Roll/Pitch Kf = , Km = dd hover 4κ · Kf Yaw Kf L κ Km,rp Km,yaw 0.010 N/duty 0.023 m 9.71e-3 m 9.3e-4 N·m 3.9e-4 N·m 同定値 アーム長 トルク推力比 Roll/Pitch Yaw K = Km /I (Kroll = 102, Kpitch = 70, Kyaw = 19 rad/s2 ) StampFly 勉強会 2026 69 / 156
パラメータ一覧 / Parameter Summary パラメータ 慣性モーメント トルクゲイン モータ時定数 プラントゲイン 記号 Roll Pitch Yaw I 9.16e-6 13.3e-6 20.4e-6 kg · m2 Km 9.3e-4 9.3e-4 3.9e-4 N·m τm 0.02 s(共通) K=K m /I 102 70 19 rad/s2 なぜ軸ごとに K が違う? Roll/Pitch: 同じ Km だが Iyy > Ixx → Pitch の方が遅い Yaw: κ L なので Km 自体が小さい → さらに遅い 伊藤 恒平 StampFly 勉強会 2026 70 / 156
P 制御の閉ループ / P Control Closed Loop + r (t) Σ e(t) Controller Kp u Plant Gp (s) ω(t) − Gcl (s) = Kp K τm s 2 + s + Kp K 閉ループ伝達関数 Gcl (s) = Kp K τm s 2 + s + Kp K 伊藤 恒平 ←− 2 次系! StampFly 勉強会 2026 71 / 156
2 次系の特性 / Second-Order Characteristics 固有振動数と減衰比 r ω ωn = 16% ζ = 0.5 ζ = 0.7 Kp K , τm 1 ζ= p 2 Kp K τm target ζ = 1.0 設計式: ζ から Kp を逆算 Kp = t 1 4ζ 2 K τm オーバーシュート量 ≈ e −πζ/ 1−ζ (ζ = 0.5 → 16%, ζ = 0.7 → 5%) p 伊藤 恒平 StampFly 勉強会 2026 2 72 / 156
開ループボード線図 / Open-Loop Bode Plot |L(jω)| [dB] 60 1 = 50 τm Kp = 0.5 Kp−= 0.25 2 40 開ループ伝達関数 0 dB /dec 20 L(s) = Kp · Gp (s) = ωgc = 40 0 −4 0d ωgc = 23 B/ de −20 c Kp K s(τm s + 1) −40 位相余裕 PM ∠L(jω) [deg] −60 −90 ωgc : |L(jωgc )| = 1 となる周波数 −120 −150 PM=65° PM=51° −180 100 101 102 ω 伊藤 恒平 [rad/s] PM = 90° − arctan(τm ωgc ) 103 Kp を上げると ωgc ↑ → PM ↓ → 振動的に StampFly 勉強会 2026 73 / 156
無駄時間の影響 / Dead Time Effect |L| [dB] 制御ループの無駄時間 40 0 −40 −60 No delay τd = 5 ms −90 ∠L(jω) [deg] τd ≈ 5 ms(センサ処理 + 制御演算 + PWM 更新) |e −jωτd | = 1 gain unchanged Ldelay (s) = L(s) · e −τd s −120 51° −150 ∆PM=−11° 40° −180 −210 Unstable region −240 100 101 ω Kp = 0.5 Kp = 0.25 モデル PM=51° PM=65° 実機 PM≈40° PM≈59° 60° 未達! ギリギリ 102 [rad/s] 実用上 PM ≥ 60° が必要 ζ = 0.7 設計でも遅延込みでボーダーライン→「モデル上は安定」 でも実機で振動する理由 伊藤 恒平 StampFly 勉強会 2026 74 / 156
ゲイン設計表 / Gain Design Table K Kp = 0.5 の ζ ζ = 0.7 の Kp ζ = 1.0 の Kp Roll 102 0.50 0.25 0.12 Pitch 70 0.60 0.36 0.18 Yaw 19 1.15 1.34 0.66 読み取り L05 の Kp = 0.5 は Roll で ζ = 0.50(やや振動的) Yaw は ζ > 1(過減衰 = 応答が遅い)— 軸ごとに Kp を変える べき理由! 伊藤 恒平 StampFly 勉強会 2026 75 / 156
実習: モデルベースゲイン設計 / Hands-on user_code.cpp (excerpt) // Model -based Kp design ( target zeta = 0.7) const float tau_m = 0.02f; 3 const float K_roll = 102.0f; 4 const float K_pitch = 70.0f; 5 const float K_yaw = 19.0f; 6 float zeta = 0.7f; 1 2 7 float Kp_roll = 1.0f/(4* zeta*zeta*K_roll *tau_m ); float Kp_pitch = 1.0f/(4* zeta*zeta*K_pitch*tau_m ); 10 float Kp_yaw = 1.0f/(4* zeta*zeta*K_yaw *tau_m ); 8 9 11 // Apply per -axis Kp in control loop float roll_cmd = Kp_roll * (target_roll - ws:: gyro_x ()); 14 float pitch_cmd = Kp_pitch * (target_pitch - ws:: gyro_y ()); 15 float yaw_cmd = Kp_yaw * (target_yaw - ws:: gyro_z ()); 12 13 伊藤 恒平 StampFly 勉強会 2026 76 / 156
チェックポイント / Checkpoint 確認事項 Gp (s) = K /(s(τm s + 1)) を説明できる モデルベース Kp と L05 の Kp = 0.5 を比較飛行 Roll/Pitch/Yaw の ζ 差を体感で理解 次のレッスン Lesson 7: システム同定 — フライトデータでモデルを検証 伊藤 恒平 StampFly 勉強会 2026 77 / 156
Lesson 7 システム同定 System Identification StampFly Workshop
今日のゴール / Today’s Goal 目標 フライトデータからプラントモデル Gp (s) = タ K , τm を同定する K のパラメー s (τm s + 1) システム同定(SysID)の考え方 WiFi テレメトリでデータ取得 sf sysid fit でモデルフィッティング 同定値と L6 理論値を比較 伊藤 恒平 StampFly 勉強会 2026 79 / 156
システム同定とは / What is System Identification? control input u(t) Plant Gp (s) (unknown K , τm ) measured output y(t) Parameter Estimation K̂ , τ̂m compare with L6 theory 伊藤 恒平 StampFly 勉強会 2026 80 / 156
WiFi テレメトリ / WiFi Telemetry WiFi テレメトリ(自動送信) システムが IMU・姿勢・センサデータを 400 Hz で自動送信 sf log wifi で受信 → CSV 保存 → sf log viz で可視化 コマンド 説明 sf log wifi WiFi テレメトリ取得(CSV 保存) sf log wifi -o data.csv ファイル名指定で保存 sf log analyze data.csv フライトデータ分析 sf log viz data.csv 波形可視化 伊藤 恒平 StampFly 勉強会 2026 81 / 156
プラント入出力の復元 / Reconstructing Plant I/O なぜ開ループ同定が可能? テレメトリの記録内容 ctrl_roll スティック入力 gyro_x 角速度(計測値) 復元手順(Kp 既知) 1 target = ctrl × rate_max 2 u(t) = Kp ×(target − gyro) 3 y(t) = gyro 伊藤 恒平 Kp が既知なら、プラントへの入力 u(t) を計算できる。閉ループデータでも、開 ループモデルを直接フィッティングで きる。 パラメータ Kp rate_max StampFly 勉強会 2026 値 L5 の値(例: 0.5) 1.0 rad/s 82 / 156
フィッティングの仕組み / How Fitting Works 最小二乗法によるパラメータ推定 候補の K , τm でモデル出力 ŷ(t) をシミュレーションし、実測 y(t) との誤差が最小 になる K , τm を探す。 Gp (s) 1 復元した u(t) をモデルに入力: u(t) −−−−→ ŷ(t) 2 P J(K , τm ) = ŷ(t) − y(t) 2 実測 y(t) との二乗誤差を計算: 3 J を最小化する K , τm を数値最適化で求める sf sysid fit が自動で行うこと ホバリング区間の自動検出 データを短いセグメントに分割してフィッティング 結果の統計処理(中央値・不確かさ) 伊藤 恒平 StampFly 勉強会 2026 83 / 156
実習: データ取得 / Hands-on: Data Acquisition L5 の P 制御で飛行し、テレメトリデータを取得する 同定には Kp と rate_max の値を記録しておくこと 1 2 3 4 5 sf lesson switch 7 でテンプレートをコピー user_code.cpp に Kp (例: 0.5)をセット ビルド & 書き込み: sf lesson build → sf lesson flash 離陸し、スティック操作でロール・ピッチ入力を入れる PC でデータ受信: ターミナル 1 sf log wifi -o flight.csv 伊藤 恒平 StampFly 勉強会 2026 84 / 156
sf sysid fit / Model Fitting Tool コマンド sf sysid fit flight.csv --kp 0.5 --plot 出力例 === Plant Model Identification === Model: G_p(s) = K / (s * (tau_m * s + 1)) 3 Roll K= 98.5 (ref :102.0 , err :3.4%) tau_m =0.019 R2 =0.94 4 Pitch K= 72.1 (ref: 70.0, err :3.0%) tau_m =0.021 R2 =0.91 1 2 --kp 0.5 --axis roll --rate-max 1.0 -o result.yaml 伊藤 恒平 飛行時の Kp (必須) 特定軸のみ分析 rate_max(既定=1.0, yaw=5.0) 結果をファイルに保存 StampFly 勉強会 2026 85 / 156
モデル検証 / Model Verification 軸 Roll Pitch Yaw K (同定) ? ? ? K (L6 理論) 102.0 70.0 19.0 設計 Kp の計算(ζ = 0.7) Kp = τm (同定) ? ? ? τm (理論) 0.020 0.020 0.020 R2 ? ? ? 1 4 ζ 2 K τm 考察 同定値と理論値のずれ → モデル誤差・無駄時間が原因 同定 K , τm で設計した Kp は L6 の理論値と近いか? 伊藤 恒平 StampFly 勉強会 2026 86 / 156
チェックポイント / Checkpoint 確認事項 sf log wifi でフライトデータを取得できた sf sysid fit で K , τm を同定した 同定値と L6 理論値を比較した 次のレッスン Lesson 8: PID 制御 — モデルに基づく I/D 項の追加で制御を改善 伊藤 恒平 StampFly 勉強会 2026 87 / 156
Lesson 8 PID 制御 PID Control StampFly Workshop
今日のゴール / Today’s Goal 目標 モデルベースの Kp を起点に、I 項・D 項を追加して制御を改善する P 制御の限界: モデル不確かさ・外乱に弱い 工学形式 Kp /Ti /Td とは 不完全微分: ノイズに強い微分項 ログから調整する方法 伊藤 恒平 StampFly 勉強会 2026 89 / 156
PID 制御器 / PID Controller P: Kp · e e(t) I: Kp Ti D: Kp · C (s) = Kp 伊藤 恒平 Z e dt Proportional + Integral Σ + u(t) + Td s ηTd s + 1 Incomplete Derivative 1 Td s 1+ + Ti s ηTd s + 1 StampFly 勉強会 2026 90 / 156
なぜ不完全微分か / Why Incomplete Derivative? 問題 解決策 ジャイロにはノイズがある 理想微分 de dt はノイズを増幅 高周波振動 → モータに悪 影響 不完全微分フィルタで高周 波カット η = 0.1 ∼ 0.2 小 → フィルタ弱い 大 → フィルタ強い トレードオフ 微分の効き(応答速度)←→ ノイズ除去(安定性) 伊藤 恒平 StampFly 勉強会 2026 91 / 156
工学形式パラメータ / Engineering Form パラメータ Kp Ti 意味 比例ゲイン 積分時間 [s] Td 微分時間 [s] η フィルタ係数 効果 大 → 応答速い、大きすぎ → 振動 小 → 積分強い(偏差早く消える) 、小 さすぎ → ワインドアップ 大 → 微分強い(振動抑制)、大きす ぎ → ノイズ増幅 0.1 ∼ 0.2、大 → ノイズに強い 教科書形式との対応 Ki = Kp /Ti , Kd = Kp · Td 伊藤 恒平 StampFly 勉強会 2026 92 / 156
ログから調整する / Log-Based Tuning ログで見える症状 振動が収まらない 応答が遅い 定常偏差が残る オーバーシュート大 高周波ノイズ ゆっくり発散 原因 Kp 過大 Kp 過小 I 項不足 D 項不足 η 過小 ワインドアップ 調整 Kp ↓ Kp ↑ Ti ↓(積分強化) Td ↑(微分強化) η ↑(0.1 → 0.2) Ti ↑ ヒント L7 で取得したテレメトリデータを見ながら調整する 伊藤 恒平 StampFly 勉強会 2026 93 / 156
推奨ゲイン / Recommended Gains 軸 Kp Ti [s] Td [s] η Roll 0.25 1.67 0.01 0.125 Pitch 0.36 1.67 0.01 0.125 Yaw 1.34 4.0 0.005 0.125 Kp は L6 のモデルベース設計値(ζ = 0.7)を使用 チューニング手順 1 2 3 Ti =0, Td =0 にして Kp を調整(振動しない最大値) Ti を大きい値 (5.0) から徐々に下げる Td を小さい値 (0.001) から徐々に上げる 伊藤 恒平 StampFly 勉強会 2026 94 / 156
実習 Step 1: 理想 PID / Ideal PID user_code.cpp (roll axis excerpt) float Kp =0.25f, Ti =1.67f, Td =0.01f; float integral =0, prev_err =0; 3 // inside loop_400Hz (dt) 4 float err = target - ws:: gyro_x (); 5 float P = Kp * err; 6 if (Ti > 0) integral += (dt /(2* Ti ))*( err+prev_err ); 7 float I = Kp * integral; 8 float D = Kp*Td*(err - prev_err )/dt; // ideal D 9 prev_err = err; 10 float roll_out = P + I + D; 1 2 やってみよう 飛ばしてみて → 高周波振動に注目 伊藤 恒平 StampFly 勉強会 2026 95 / 156
実習 Step 2: 不完全微分 / Incomplete Derivative user_code.cpp (D term replacement) // Replace ideal D with incomplete derivative filter float eta = 0.125f; 3 float d_filt = 0; // persistent state 4 // inside loop_400Hz (dt) 5 float alpha = 2*eta*Td / dt; 6 float a = (alpha - 1) / (alpha + 1); 7 float b = 2*Td / (( alpha + 1) * dt); 8 d_filt = a * d_filt + b * (error - prev_err ); 9 float D = Kp * d_filt; // Filtered ! 1 2 やってみよう 再び飛ばして → 高周波振動が減ったことを確認 伊藤 恒平 StampFly 勉強会 2026 96 / 156
チェックポイント / Checkpoint 確認事項 理想微分 vs 不完全微分で高周波振動の違いを確認 定常偏差がなくなった(P のみと比較) ゲイン調整表を使って応答を改善できた 次のレッスン Lesson 9: 姿勢推定 — センサフュージョンで角度を推定 伊藤 恒平 StampFly 勉強会 2026 97 / 156
Lesson 9 姿勢推定 Attitude Estimation StampFly Workshop
今日のゴール / Today’s Goal 目標 相補フィルタを実装し、ESKF の推定値と比較する ジャイロ積分のドリフト問題を理解 相補フィルタで加速度センサとジャイロを融合 Teleplot で CF vs ESKF をリアルタイム比較 伊藤 恒平 StampFly 勉強会 2026 99 / 156
姿勢の表現 — ZYX オイラー角 オイラー角とは 3 次元の姿勢(回転)を 3 つの角度で表現する方法の一つ 記号 φ θ ψ 名称 回転軸 Roll(ロール) X 00 軸 Pitch(ピッチ) Y 0 軸 Yaw(ヨー) Z 軸 意味 左右の傾き 前後の傾き 機首方向 StampFly の規約: ZYX オイラー角 回転順序: Z 軸 (ψ) → Y 0 軸 (θ) → X 00 軸 (φ) 航空宇宙分野で標準的な Tait–Bryan 角。ジンバルロック (θ = ±90°) に注意。 伊藤 恒平 StampFly 勉強会 2026 100 / 156
オイラー角微分とジャイロ角速度の関係 ジャイロの測定値 ω からオイラー角の微分を求める ジャイロはボディ座標系の角速度 ω = [ωx , ωy , ωz ]T を測定する。オイラー角の微 分とは一致しない。現在の姿勢に依存する変換が必要: φ̇ = ωx + ωy sin φ tan θ + ωz cos φ tan θ θ̇ = ωy cos φ − ωz sin φ ψ̇ = ωy (sin φ / cos θ) + ωz (cos φ / cos θ) 離散積分(毎ステップ更新) φk+1 = φk + φ̇k ∆t, θk+1 = θk + θ̇k ∆t, ψk+1 = ψk + ψ̇k ∆t 注意: 現在の (φ, θ) に依存 → 毎ステップ再計算。θ= ± 90° で cos θ=0(ジンバルロック) 伊藤 恒平 StampFly 勉強会 2026 101 / 156
加速度からのオイラー角算出 (1) — 座標変換 静止時、加速度センサは重力の反力を測定する NED 座標系の重力 [0, 0, g]T に対し、センサ出力は RT [0, 0, −g]T : ax 0 g sin θ ay = RT 0 = −g sin φ cos θ az −g −g cos φ cos θ ax はピッチ角 θ のみに依存(φ を含まない) ay と az はロール角 φ とピッチ角 θ の両方に依存 ヨー角 ψ はどの成分にも現れない(重力は鉛直 → ψ の情報なし) 前提: 機体が静止または等速運動中であること。加速中は重力以外の成分が混入しノイズとなる。 伊藤 恒平 StampFly 勉強会 2026 102 / 156
加速度からのオイラー角算出 (2) — Roll と Pitch の導出 Roll φ の算出: (−ay ) と (−az ) の比 (−ay )/(−az ) をとると g cos θ が約分され θ が消える: −ay g sin φ cos θ sin φ = = = tan φ −az g cos φ cos θ cos φ Pitch θ の算出: ax と q =⇒ φ = atan2(−ay , −az ) ay2 + az2 ay2 + az2 = g 2 cos2 θ (sin2 φ + cos2 φ) = g 2 cos2 θ より: a g sin θ q x = = tan θ g cos θ ay2 + az2 =⇒ θ = atan2 ax , q ay2 + az2 Yaw ψ: 加速度のみでは算出不可(磁気センサが必要) 長所: ドリフトなし 短所: 振動ノイズ大 伊藤 恒平 StampFly 勉強会 2026 103 / 156
ジャイロドリフト問題 / Gyro Drift Problem θ Gyro Z ジャイロは角速度 ω を測定 R 角度 θ = ω dt (積分が必要) バイアスが蓄積 → ドリフト 増大 ω dt Drift True angle 0s 10s 伊藤 恒平 20s 問題 30s 40s t ジャイロ単体では長時間の姿勢推 定が不可能 StampFly 勉強会 2026 104 / 156
相補フィルタ / Complementary Filter 数式 Gyro ω High-pass Z dt θ̂k = α (θ̂k−1 +ω ∆t)+(1−α) θaccel α + Accel atan2 θ̂ 1−α Low-pass 伊藤 恒平 StampFly 勉強会 2026 α = 0.98(ジャイロ 98% + 加速度 2%) ジャイロ: 短期精度◎ / 長 期ドリフト� 加速度: 長期安定◎ / 振動 ノイズ� 105 / 156
姿勢推定 API 関数 gyro_x/y/z() accel_x/y/z() estimated_roll/pitch/yaw() print(fmt, ...) 説明 単位 角速度(Roll/Pitch/Yaw) rad/s 加速度(X/Y/Z) m/s2 ESKF 推定姿勢角 rad シリアル出力(Teleplot 対応) — 実習で使う組み合わせ ジャイロ + 加速度 → 相補フィルタで姿勢を自作 estimated_roll() → ESKF の推定値と比較 伊藤 恒平 StampFly 勉強会 2026 106 / 156
実習: 相補フィルタ + Teleplot / Hands-on
user_code.cpp (excerpt)
# include "workshop_api.hpp"
# include <cmath >
3 static float cf_roll = 0.0f, cf_pitch = 0.0f;
4 void setup () { ws:: print("Lesson 9: Attitude Estimation"); }
5 void loop_400Hz(float dt) {
6
float gx = ws:: gyro_x (), gy = ws:: gyro_y ();
7
float ax = ws:: accel_x (), ay = ws:: accel_y (),
8
az = ws:: accel_z ();
9
float accel_roll = atan2f(ay , az);
10
float accel_pitch = atan2f(-ax , az);
11
constexpr float alpha = 0.98f;
12
cf_roll = alpha *( cf_roll + gx*dt) + (1-alpha )* accel_roll;
13
cf_pitch = alpha *( cf_pitch + gy*dt) + (1-alpha )* accel_pitch;
14
// Teleplot output ( VSCode Teleplot extension )
15
ws:: print(">cf_roll :%.1f", cf_roll *57.3f);
16
ws:: print(">eskf_roll :%.1f", ws:: estimated_roll ()*57.3f);
17 }
1
2
伊藤 恒平
StampFly 勉強会 2026
107 / 156
Teleplot によるリアルタイム可視化 Teleplot フォーマット セットアップ >変数名: 値 をシリアルに出力する だけ // Teleplot format : >name:value ws:: print(">cf_roll :%.2f", cf_roll * 57.3f); 3 ws:: print(">cf_pitch :%.2f", cf_pitch * 57.3f); 4 ws:: print(">eskf_roll :%.2f", 5 ws:: estimated_roll () * 57.3f); 1 2 1 2 3 VSCode 拡張: alexnesnes.teleplot をインストール Teleplot パネルでシリア ルポートを選択 自動でグラフ化される 注意: 400 Hz 全 tick で出力するとシリアル帯域に負荷。4 tick 毎(100 Hz)にデシメーション推奨 伊藤 恒平 StampFly 勉強会 2026 108 / 156
Madgwick フィルタ / Madgwick Filter 勾配降下法によるクォータニオン推定 チューニングパラメータが β の 1 つだけ — シンプルかつ高精度 状態: q = [q0 , q1 , q2 , q3 ] 予測: q̇ = 12 q ⊗ ω 補正勾配: ∇f = JT (q̂, d̂) f(q̂, d̂) 更新則 qt+1 = qt +∆t ∇f 1 2 qt ⊗ω −β |∇f | f: 加速度/磁気の目的関数、J: そのヤコビアン、β: 補正ゲイン(≈ 0.04) 伊藤 恒平 StampFly 勉強会 2026 109 / 156
EKF(拡張カルマンフィルタ) 非線形カルマンフィルタの 5 ステップ 状態ベクトル例: x = [φ, θ, ψ, bgx , bgy , bgz ]T ステップ 状態予測 共分散予測 カルマンゲイン 状態更新 共分散更新 伊藤 恒平 数式 x̂− = f (x̂, u) P− = FPFT + Q K = P− HT (HP− HT + R)−1 x̂ = x̂− + K(z − h(x̂− )) P = (I − KH)P− StampFly 勉強会 2026 意味 ジャイロで姿勢を積分 不確かさの伝播 予測と観測の信頼度配分 観測で補正 不確かさを縮小 110 / 156
ESKF(誤差状態カルマンフィルタ) StampFly で実際に使われている 15 状態 ESKF 名目状態 + 誤差状態の分離アーキテクチャ 誤差状態ベクトル(15 states): 観測更新: δx = [δp, δv, δθ, δbg , δba ]T 気圧 → 高度補正 ToF → 対地高度補正 予測: 名目状態はジャイロ/加速度 で直接積分 磁気 → ヨー補正 光学フロー → 速度補正 誤差共分散のみ伝播 利点: 誤差状態は常に小さい → 線形化が正確 伊藤 恒平 StampFly 勉強会 2026 111 / 156
推定手法の比較 / Estimator Comparison 計算量 パラメータ数 推定対象 使用センサ 精度 相補フィルタ Madgwick EKF ESKF 極小 小 中 中〜大 1(α) 1(β ) Q, R 行列 Q, R 行列 Roll/Pitch R/P/Yaw 姿勢+バイアス 位置/速度/姿勢/バイアス Gyro+Accel Gyro+Accel+Mag Gyro+Accel+Mag 全センサ(6 種) ○ ◎ ◎ ◎◎ StampFly のデフォルト: ESKF(15 状態)を使用。このレッスンでは相補フィルタを自作し、 ESKF と比較して理解を深める。 伊藤 恒平 StampFly 勉強会 2026 112 / 156
チェックポイント / Checkpoint 確認事項 手で傾けると CF のロール・ピッチが変化する CF と ESKF の値が概ね一致する(Teleplot で確認) α を変えて応答の違いを観察 Madgwick / EKF / ESKF の特徴を説明できる 次のレッスン Lesson 10: ws:: API リファレンス 伊藤 恒平 StampFly 勉強会 2026 113 / 156
Lesson 10 ws:: API リ ファレンス ws:: API Reference StampFly Workshop
今日のゴール / Today’s Goal 目標 ws:: API 全 43 関数をカテゴリ別に理解し、各関数の使い方を把握 する ws:: API 全 43 関数をカテゴリ別に理解 各 API の使い方をコード例で確認 環境・距離センサ API で全センサに直接アクセス 伊藤 恒平 StampFly 勉強会 2026 115 / 156
ws:: API 概要 / API Overview カテゴリ Motor Control RC Input RC Buttons IMU Sensor Env / Distance Estimation LED Utility 合計 概要 モータ制御・Arm/Disarm コントローラスティック入力 ボタン・飛行モード ジャイロ・加速度センサ 気圧・磁気・ToF・光学フロー ESKF 姿勢・高度推定 LED 色制御 時刻・電圧・通信・出力 関数数 7 4 5 6 10 4 3 4 43 #include "workshop_api.hpp" で全関数を使用可能。全関数は ws:: 名前空間に属する。 より深いアクセスには StampFlyState を使用(後半で解説)。 伊藤 恒平 StampFly 勉強会 2026 116 / 156
Motor Control API — Duty & Mixer 関数 motor_set_duty(id, duty) motor_set_all(duty) motor_stop_all() motor_mixer(t, r, p, y) // Individual motor control ws:: motor_set_duty (1, 0.3f); 3 ws:: motor_stop_all (); 1 2 4 5 6 引数 id: 1–4, duty: 0–1 duty: 0–1 — 各 float // Motor 1 (FR) = 30% // Emergency stop // Mixer: thrust + attitude corrections ws:: motor_mixer (0.5f, 0.0f, 0.0f, 0.0f); 伊藤 恒平 説明 個別モータ duty 設定 全モータ同一 duty 全モータ即時停止 スラスト+姿勢ミキシング // Hover StampFly 勉強会 2026 117 / 156
Motor Control API — Arm / Disarm
関数
arm()
disarm()
is_armed()
1
戻り値
void
void
bool
説明
モータ出力を有効化(Arm)
モータ出力を無効化(Disarm)
Arm 状態を返す(true = Armed)
if (ws:: rc_throttle () < 0.05f) ws::arm ();
2
if (ws:: is_armed ()) {
ws:: motor_mixer(ws:: rc_throttle (),
5
ws:: rc_roll (), ws:: rc_pitch (), ws:: rc_yaw ());
6 } else {
7
ws:: motor_stop_all ();
8 }
3
4
注意: arm() 前はモータコマンドを送っても回転しない
伊藤 恒平
StampFly 勉強会 2026
118 / 156
RC Input API
関数
rc_throttle()
rc_roll()
rc_pitch()
rc_yaw()
範囲
[0.0, 1.0]
[−1.0, 1.0]
[−1.0, 1.0]
[−1.0, 1.0]
説明
スロットル(上がプラス)
ロール(右がプラス)
ピッチ(前がプラス)
ヨー(右回転がプラス)
void loop_400Hz(float dt) {
float thr = ws:: rc_throttle (); // 0.0 - 1.0
3
float rol = ws:: rc_roll ();
// -1.0 - 1.0
4
float pit = ws:: rc_pitch ();
5
float yaw = ws:: rc_yaw ();
6
ws:: motor_mixer(thr , rol , pit , yaw); // ACRO mode
7 }
1
2
伊藤 恒平
StampFly 勉強会 2026
119 / 156
RC Buttons / Mode API 関数 rc_throttle_yaw_button() rc_roll_pitch_button() rc_stabilize_acro_mode() rc_alt_mode() rc_pos_mode() 戻り値 bool bool bool bool bool 説明 左スティック押し込みボタン 右スティック押し込みボタン ACRO モード判定(true = ACRO) 高度保持モード判定 位置保持モード判定 void loop_400Hz(float dt) { if (ws:: rc_stabilize_acro_mode ()) { 3 acro_control(dt); // ACRO: rate control 4 } else { 5 stabilize_control(dt); // Stabilize : angle control 6 } 7 } 1 2 伊藤 恒平 StampFly 勉強会 2026 120 / 156
IMU Sensor API
関数
gyro_x/y/z()
accel_x/y/z()
単位
rad/s
m/s2
説明
R/P/Y 角速度(BMI270)
X/Y/Z 加速度(NED 座標系)
void loop_400Hz(float dt) {
float gx = ws:: gyro_x ();
3
float gy = ws:: gyro_y ();
4
float gz = ws:: gyro_z ();
5
float az = ws:: accel_z ();
1
2
6
7
8
9
}
// [rad/s] roll rate
// [rad/s] pitch rate
// [rad/s] yaw rate
// [m/s^2] ~9.81 at rest
ws:: print(">gyro_x :%.3f", gx);
ws:: print(">accel_z :%.2f", az);
静止時: accel_z() ≈ 9.81(NED 座標系、下向き正)
伊藤 恒平
StampFly 勉強会 2026
121 / 156
Estimation API
関数
estimated_roll()
estimated_pitch()
estimated_yaw()
estimated_altitude()
単位
rad
rad
rad
m
説明
ESKF ロール推定角
ESKF ピッチ推定角
ESKF ヨー推定角
ESKF 推定高度(正 = 上)
void loop_400Hz(float dt) {
float roll = ws:: estimated_roll ();
// [rad]
3
float pitch = ws:: estimated_pitch ();
4
float alt
= ws:: estimated_altitude (); // [m]
5
// P control : level the drone
6
ws:: motor_mixer(ws:: rc_throttle (),
7
(0.0f-roll )*0.5f, (0.0f-pitch )*0.5f, ws:: rc_yaw ());
8 }
1
2
ESKF はジャイロ+加速度+気圧+ToF+磁気+光学フローを統合(L09 参照)
伊藤 恒平
StampFly 勉強会 2026
122 / 156
環境センサ API — 気圧・磁気 関数 baro_altitude() baro_pressure() mag_x() mag_y() mag_z() 単位 m Pa µT µT µT 説明 気圧高度(BMP280) 気圧値(BMP280) 磁気 X 成分(BMM150) 磁気 Y 成分(BMM150) 磁気 Z 成分(BMM150) float alt = ws:: baro_altitude (); // [m] float p = ws:: baro_pressure (); // [Pa] 3 float mx = ws:: mag_x (); // [uT] 4 ws:: print(">baro_alt :%.2f", alt); 1 2 伊藤 恒平 StampFly 勉強会 2026 123 / 156
環境センサ API — ToF・光学フロー
関数
tof_bottom()
tof_front()
flow_vx()
flow_vy()
flow_quality()
単位
m
m
m/s
m/s
0–255
説明
下方 ToF 距離(VL53L3CX, 0–2 m)
前方 ToF 距離(−1 = 未接続)
光学フロー速度 X(PMW3901)
光学フロー速度 Y(PMW3901)
光学フロー品質(高い = 良好)
float dist = ws:: tof_bottom ();
// [m] ground distance
float vx
= ws:: flow_vx ();
// [m/s]
3 uint8_t sq = ws:: flow_quality ();
// 0 -255
4 ws:: print(">tof_bottom :%.3f", dist );
1
2
伊藤 恒平
StampFly 勉強会 2026
124 / 156
LED Control API
関数
led_color(r, g, b)
disable_led_task()
enable_led_task()
is_led_task_disabled()
引数/戻り値
r,g,b: 0–255
void
void
bool
説明
LED 色を RGB 設定
システム LED タスク停止
システム LED タスク再開
LED タスク停止中か確認
void setup () {
ws:: disable_led_task (); // Take over LED control
3 }
4 void loop_400Hz(float dt) {
5
float v = ws:: battery_voltage ();
6
if (v > 3.8f)
ws:: led_color (0, 255, 0);
// Green
7
else if (v > 3.5f) ws:: led_color (255, 165, 0); // Orange
8
else
ws:: led_color (255, 0, 0);
// Red
9 }
1
2
注意: disable_led_task() を先に呼ぶこと(LED 上書き防止)
伊藤 恒平
StampFly 勉強会 2026
125 / 156
Utility API
関数
millis()
battery_voltage()
print(fmt, ...)
set_channel(ch)
戻り値
uint32_t (ms)
float (V)
void
void
説明
起動からの経過時間
バッテリー電圧
printf 形式でデバッグ出力
WiFi チャネル設定(1, 6, 11)
void setup () { ws:: set_channel (6); }
void loop_400Hz(float dt) {
3
static uint32_t last = 0;
4
uint32_t now = ws:: millis ();
5
if (now - last >= 20) { // 50 Hz decimation
6
last = now;
7
ws:: print(">battery :%.2f", ws:: battery_voltage ());
8
}
9 }
1
2
伊藤 恒平
StampFly 勉強会 2026
126 / 156
ハードウェアセンサ仕様 / Hardware Sensors センサ 型番 IMU BMI270 気圧 BMP280 磁気 BMM150 ToF(下方) VL53L3CX ToF(前方) VL53L3CX 光学フロー PMW3901 サンプルレート 測定量 400 Hz 加速度 + ジャイロ 50 Hz 気圧 → 高度 10–30 Hz 磁気ベクトル 30 Hz 対地距離(0–2 m) 30 Hz 前方距離(0–2 m) 100 Hz 対地速度 ws:: API で全センサに直接アクセス可能(baro_altitude(), tof_bottom() 等)。 より低レベルなアクセスには StampFlyState を使用。 ESKF は全センサを統合して姿勢・位置・速度を推定(Lesson 9 参照)。 伊藤 恒平 StampFly 勉強会 2026 127 / 156
Teleplot
Teleplot 形式 (>name:value) でシリアル出力すると、
VS Code 拡張 Teleplot がリアルタイムグラフを描画する。
void loop_400Hz(float dt) {
static uint32_t tick = 0; tick ++;
3
if (tick % 8 != 0) return; // 50 Hz decimation
1
2
4
5
6
7
8
9
}
// Teleplot output (>name: value format )
ws:: print(">baro_alt :%.2f", ws:: baro_altitude ());
ws:: print(">tof_bottom :%.3f", ws:: tof_bottom ());
ws:: print(">eskf_alt :%.2f", ws:: estimated_altitude ());
セットアップ: VSCode 拡張 alexnesnes.teleplot をインストール→ Teleplot パネルでシリアル
ポートを選択 → 自動グラフ化
伊藤 恒平
StampFly 勉強会 2026
128 / 156
実習: 全センサ Teleplot 出力 / Hands-on
# include "workshop_api.hpp"
void setup () { ws:: print("Lesson 10: Sensor API"); }
3 void loop_400Hz(float dt) {
4
static uint32_t tick = 0; tick ++;
5
if (tick % 8 != 0) return; // 50 Hz decimation
6
// Environmental sensors (ws:: API)
7
ws:: print(">baro_alt :%.2f", ws:: baro_altitude ());
8
ws:: print(">mag_x :%.1f", ws:: mag_x ());
9
ws:: print(">tof_bottom :%.3f", ws:: tof_bottom ());
10
ws:: print(">flow_vx :%.3f", ws:: flow_vx ());
11
// ESKF estimation
12
ws:: print(">eskf_alt :%.2f", ws:: estimated_altitude ());
13
ws:: print(">eskf_roll :%.1f", ws:: estimated_roll ()*57.3f);
14 }
1
2
Teleplot パネルでシリアルポートを選択し確認(前ページ参照)
伊藤 恒平
StampFly 勉強会 2026
129 / 156
チェックポイント / Checkpoint 確認事項 ws:: API 全 43 関数のカテゴリと役割を把握した Motor / RC / IMU / Sensor / Estimation の使い方を理解した 気圧・磁気・ToF・光学フロー API で値を取得できた Teleplot で複数センサのグラフを同時表示した 次のレッスン Lesson 11: 独自ファームウェア開発 伊藤 恒平 StampFly 勉強会 2026 130 / 156
Lesson 11 独自ファーム ウェア開発 Custom Firmware Development StampFly Workshop
今日のゴール / Today’s Goal 目標 sf app new で独自プロジェクトを作り、ネイティブ API で全センサ にアクセスする sf app new で独自ファームウェアプロジェクトを作成 テンプレートの構造(app_main, ControlTask)を理解 StampFlyState で全センサ・推定値に直接アクセス Teleplot でセンサデータをリアルタイム可視化 伊藤 恒平 StampFly 勉強会 2026 132 / 156
開発フロー / Development Flow 注意: これまでのレッスンとやり方が変わります ワークショップ(firmware/workshop/)の外に、独立したプロジェクトを作り ます。 L0 – L10(これまで) L11(このレッスン) 開始 sf lesson switch N sf app new my_drone 編集先 firmware/workshop/main/ firmware/my_drone/main/ ファイル user_code.cpp main.cpp ビルド sf lesson build sf build my_drone 書き込み sf lesson flash sf flash my_drone -m API ws:: ラッパー ネイティブ(StampFlyState) 伊藤 恒平 StampFly 勉強会 2026 133 / 156
API 比較 / API Comparison ws:: ワークショップ ネイティブ開発 ws::gyro_x(), ws::alt() state.getIMUData(a, g) ws::print(">tag:%.2f", v) printf(">tag:%.2f\n", v) setup() / loop_400Hz(dt) app_main() / ControlTask() 1 関数 = 1 センサ値 構造体で複数値を一括取得 ネイティブ = vehicle ファームウェアと同じ構成。あらゆるアルゴリズムを実装可能。 伊藤 恒平 StampFly 勉強会 2026 134 / 156
プロジェクト作成 / Create Project sf app new my_drone sf build my_drone 3 sf flash my_drone -m 1 2 # firmware / my_drone / が 生 成 # ビルド # 書き込み + モニタ テンプレートの特徴 vehicle と同じセンサタスク・初期化コードを再利用 ControlTask() のみを独自実装 IMU, 気圧, ToF, 光学フロー, モーター等すべて利用可能 伊藤 恒平 StampFly 勉強会 2026 135 / 156
プロジェクト構成 / Project Structure firmware / my_drone / 2 CMakeLists . txt 3 main / 4 CMakeLists . txt 5 main . cpp 1 ファイル CMakeLists.txt main/CMakeLists.txt main/main.cpp 伊藤 恒平 # ビルド設定 # コンパイル対象の定義 # ← ここを編集 役割 vehicle/components と common を参照(全コンポーネント利用可能) vehicle のタスク(IMU, Baro, ToF 等)と init.cpp を再利用 ユーザーが編集する唯一のファイル(ControlTask + コールバック) StampFly 勉強会 2026 136 / 156
テンプレート構造 / Template Structure app_main() — ブートシーケンス NVS → センサ初期化 → ESKF 起動 → タスク起動(自動生成済み) ControlTask() — 400 Hz ユーザーコード ← ここを編集 センサ読み取り・制御計算・モーター出力を記述するメインループ コールバック関数 onButtonEvent() — ボタン押下で ARM / DISARM handleControlInput() — コントローラからの操縦入力を処理 伊藤 恒平 StampFly 勉強会 2026 137 / 156
ControlTask / 制御ループ void ControlTask(void* pvParameters) { while (true) { 3 xSemaphoreTake(g_control_semaphore , ...); 4 // --- 1. セ ン サ 読 み 取 り --5 state.getIMUData(accel , gyro ); // 400 Hz 6 state.getAttitudeEuler(r, p, y); // ESKF 推 定 値 7 state.getBaroData(alt , p); // 50 Hz 8 state.getToFData(bot , fnt); // 30 Hz 9 // --- 2. 制 御 計 算 ( ユ ー ザ ー 実 装 ) --10 // PID , モ ー タ ー ミ キ シ ン グ 等 11 // --- 3. モ ー タ ー 出 力 --12 // g_motor . setThrust (0, thrust ); 13 // --- 4. Teleplot 出 力 ( 50 Hz ) --14 if (tick % 8 == 0) printf (...); 15 } 16 } 1 2 セマフォで IMU タイマー(2500 µs)と同期。各センサは独立タスクで取得済み。 伊藤 恒平 StampFly 勉強会 2026 138 / 156
StampFlyState API メソッド getIMUData(a, g) getBaroData(alt, p) getMagData(mag) getToFData(b, f) getFlowData(vx, vy) getAttitudeEuler(r, p, y) getPowerData(v, i) ソース BMI270 BMP280 BMM150 VL53L3CX PMW3901 ESKF INA3221 取得データ 加速度 + ジャイロ 高度 [m], 気圧 [Pa] 磁気 x,y,z [µT] 下方/前方距離 [m] 速度 vx,vy [m/s] roll, pitch, yaw [rad] 電圧 [V], 電流 [A] StampFlyState::getInstance() でシングルトンを取得し、各メソッドを呼び出す。 伊藤 恒平 StampFly 勉強会 2026 139 / 156
実習: 全センサ Teleplot 可視化 / Hands-on
auto& state = stampfly :: StampFlyState :: getInstance ();
stampfly :: Vec3 accel , gyro;
3 state.getIMUData(accel , gyro );
4 float alt , p;
5 state.getBaroData(alt , p);
6 float roll , pitch , yaw;
7 state.getAttitudeEuler(roll , pitch , yaw);
1
2
8
static uint32_t tick = 0; tick ++;
if (tick % 8 == 0) { // 50 Hz
11
printf(">baro_alt :%.2f\n", alt);
12
printf(">roll_deg :%.1f\n", roll * 57.3f);
13
printf(">gyro_x :%.3f\n", gyro.x);
14 }
9
10
手順: sf app new my_viz → firmware/my_viz/main/main.cpp の ControlTask を編集 → sf
build my_viz → sf flash my_viz -m → Teleplot
伊藤 恒平
StampFly 勉強会 2026
140 / 156
チェックポイント / Checkpoint 確認事項 sf app new でプロジェクトを作成しビルドできた プロジェクト構成(3 ファイルの役割)を理解した app_main() と ControlTask() の役割を理解した StampFlyState で全センサ値を直接取得できた Teleplot でリアルタイムグラフを確認した 次のレッスン Lesson 12: Python SDK プログラム飛行 伊藤 恒平 StampFly 勉強会 2026 141 / 156
Lesson 12 Python SDK プ ログラム飛行 Python SDK Programmatic Flight StampFly Workshop
今日のゴール / Today’s Goal 目標 Python SDK の設計思想と将来の自律飛行の姿を理解する SDK アーキテクチャ(TCP CLI + WebSocket)を理解 Python API で離陸・移動・着陸をプログラム化 Tello SDK 互換設計の利点を知る 伊藤 恒平 StampFly 勉強会 2026 143 / 156
SDK アーキテクチャ / SDK Architecture TCP CLI (port 23) commands PC (Python SDK) WiFi AP 192.168.4.1 StampFly ESP32-S3 telemetry 400 Hz sensors / motors WebSocket (port 81) TCP CLI (port 23) WebSocket (port 81) コマンド送受信(takeoff, land...) テレメトリ受信(400 Hz RT) 伊藤 恒平 StampFly 勉強会 2026 144 / 156
Python SDK API 関数 StampFly(host) connect() takeoff() land() move_forward(cm) rotate_clockwise(deg) send_rc_control(lr,fb,ud,yaw) get_telemetry() end() 伊藤 恒平 説明 インスタンス生成 WiFi 接続 離陸 着陸 前進 時計回り回転 RC 制御値送信 テレメトリ取得 切断 StampFly 勉強会 2026 備考 デフォルト 192.168.4.1 TCP CLI + WS ブロッキング ブロッキング 20–200 cm 1–360° −100~+100 400 Hz dict リソース解放 145 / 156
Tello SDK との互換性 / Tello Compatibility djitellopy 互換 StampFly の利点 Tello のコードをほぼそのまま StampFly に移植可能 同じ API 名(takeoff, land, move_forward...) connect_or_simulate() で オフライン開発も可能 大学の Tello 教材を流用可能 伊藤 恒平 StampFly 勉強会 2026 内部の PID ゲインを自由に 変更可能 テレメトリを 400 Hz で取得 制御理論の実験プラット フォーム ESP32-S3 のファームウェア も公開 146 / 156
コード例: 基本フライト / Basic Flight flight_basic.py 1 2 3 4 from stampfly import StampFly drone = StampFly () drone.connect () 5 drone.takeoff () drone.move_forward (50) # 50 cm forward 8 drone.rotate_clockwise (90) 9 drone.move_forward (50) 10 drone.land () 6 7 11 12 drone.end() 伊藤 恒平 StampFly 勉強会 2026 147 / 156
コード例: テレメトリ取得 / Telemetry
flight_telemetry.py
1
2
import time
from stampfly import StampFly
3
drone = StampFly ()
drone.connect ()
6 drone.takeoff ()
4
5
7
# Hover + read telemetry for 5 seconds
for _ in range (50):
10
drone.send_rc_control (0, 0, 0, 0)
11
t = drone.get_telemetry ()
12
print(f"alt={t.get('alt ',0):.1f}")
13
time.sleep (0.1)
8
9
14
15
16
drone.land ()
drone.end()
伊藤 恒平
StampFly 勉強会 2026
148 / 156
開発ロードマップ / Development Roadmap 状態 X X X X � � � � 機能 TCP CLI 通信(port 23) WebSocket テレメトリ(port 81) ws:: ワークショップ API sf CLI ツール群 Python SDK パッケージ connect_or_simulate() Jupyter Notebook 連携 自律ミッション(ウェイポイント) 伊藤 恒平 StampFly 勉強会 2026 将来の姿 Python でミッション 記述 Jupyter でデータ解析 シミュレータ連携 ROS2 ブリッジ 149 / 156
チェックポイント / Checkpoint 確認事項 SDK アーキテクチャ(TCP + WebSocket)を理解した Python API の基本関数を把握した Tello 互換の設計意図を理解した 開発ロードマップを確認した 次のレッスン Lesson 13: 精密着陸競技会 ルール説明 伊藤 恒平 StampFly 勉強会 2026 150 / 156
Lesson 13 精密着陸競技会 Precision Landing Competition StampFly Workshop
競技会概要 / Competition Overview 精密着陸競技 パイロットは定位置から操縦し、3 m 先のヘリポートに精密着陸する 種目: 精密着陸(パイロット定位置、3 m 先のヘリポートに着陸) ヘリポート: 約 40 cm × 40 cm 評価: 着陸までのタイム(ベストタイム採用) 伊藤 恒平 StampFly 勉強会 2026 152 / 156
競技ルール詳細 / Competition Rules 項目 種目 距離 ヘリポート 制限時間 試行回数 判定 パイロット 失格条件 内容 精密着陸(パイロット定位置操縦) パイロットからヘリポートまで 3 m 40 cm × 40 cm 60 秒 3 回(ベストタイム採用) ARM → 離陸 → ヘリポート着陸までの時間 定位置から動かない 安全エリア外飛行、手による介入、パイロットの移動 注意: 安全第一! 周囲に人がいないことを確認してから飛行 伊藤 恒平 StampFly 勉強会 2026 153 / 156
タイムスケジュール / Schedule 時間 内容 Day 4(本日午後) 13:00–13:30 ルール説明(このスライド) 13:30–16:00 準備・自由練習・予選 Day 5(最終日) 9:00– 9:15 ルール確認・機体チェック 9:15– 9:45 最終チューニング 9:45–10:45 競技本番 10:45–11:30 結果発表・表彰・振り返り 伊藤 恒平 StampFly 勉強会 2026 154 / 156
攻略のヒント / Tips for Success PID ゲイン調整 練習のポイント 安定性重視(急旋回よりも 穏やかな応答) ヨー制御で方向を合わせる スロットル微調整で高度を 安定させる まず安定ホバリングを確立 前進 → 停止 → 降下の手順 を練習 バッテリ・プロペラを毎回 チェック テレメトリ活用: Teleplot でリアルタイムデータを確認し、ゲインを追い込む 伊藤 恒平 StampFly 勉強会 2026 155 / 156