飛行制御
トップページでは、二層が地に着くところを配送ドローンで示しました。このページは、そのデモを余さず書きます。何がどこで走り、故障にどう答え、何が実証されていて何がされていないか。
走るのは実機です。Raspberry Pi Pico W(RP2040、Cortex-M0+)と Pico 2 W(RP2350、RISC-V)——どちらも MMU 無し——の上で、HIL コントローラとして。コントローラはチップで、シミュレートされた機体は PC で走り、その 2 つがふつうの Wi-Fi 越しにセンサとモータのフレームを交換します。
何がどこで走るか
**カーネルが、機体を飛ばします。**カスケード PID + 四元数の制御ループと安全包絡線は、ネイティブ Zig で、特権で、カーネルの中にあります。HIL フレームごとに、コントローラがセンサを読み、安全包絡線が目標を決め、制御則が 4 つのモータ指令を計算します。
**ミッションは、1 つの隔離アクターです。**それは飛行計画——基地から上昇し、海上を 90 m 先の島まで巡航し、貨物を落とし、帰り、着陸する——で、Lambda C バイトコードとしてアップロードされ、非特権で、PMP(RP2350)または MPU(RP2040)に箱詰めされています。コントローラのライブ位置を読み、次の航点を提案します。ネイティブの安全包絡線がその提案を読んで、コントローラが実際に飛ぶ目標を決めます。
これは二層の分割を裏返した形です。ここでは安全に関わる部分がネイティブで、変わる部分——飛行計画、案件ごとに違うもの——が隔離されたバイトコードです。飛行計画のバグは、安全包絡線にも制御ループにも届きません。カーネル境界の向こう側にあるからです。
安全包絡線は、失われた能力の量で答える
包絡線はネイティブで、毎フレーム、ミッションの提案とコントローラが飛ぶ目標のあいだで走ります。その応答は段階的です。「全部止める」でもなく、帰投がもう不可能なときに「帰れ」と命じるのでもなく。
| 状態 | 応答 |
|---|---|
| 正常 | ミッションの提案した目標を飛ぶ(ジオフェンス内) |
| IMU が 1 つ故障 | 切り離し、バックアップで飛ぶ——ミッションは継続し、完走する |
| バッテリ低下 | 帰投——まだ飛べる、ただエネルギーが少ない |
| 制御デッドラインの連続超過 | 帰投 |
| 両 IMU 喪失、またはロータ停止 | パラシュート展開 |
2 つの IMU は、デバウンス付きで相互検査されます。1 つの故障は切り離されますが、2 つの読みが激しい動きで一致しているときは、二重故障ではなく本物のタンブルと見なします。ロータ停止は、揺れからの推測でなく ESC のテレメトリから読みます。そしてパラシュートは、制御を本当に失ったときの正直な答えです。クアッドは劣駆動なので 3 枚では制御された降下ができず、両 IMU を失った機体は保つべき姿勢が無い——「帰投」は従えない指令になります。チュートは一発で、着地して故障が晴れるまでラッチされます。
ミッションは目標を提案できます。このどれ一つ、動かせません。
基板は、武装する前に境界を実証する
RP2350 は、飛ぶ前にプリフライトの手順を走らせ、各チェックを地上局へ報告します——無線、コア、制御ループ、そして保護。
保護のチェックは、非特権からカーネルメモリへのストアを試み、ハードウェアがそれを拒否しなければなりません。そしてこのチェックが無内容でないことを、同じ起動の中で示します——まずスクラッチページの拒否を外してストアが通ることを確かめ、次に拒否を戻して同じストアがフォルトすることを確かめる。メモリに届かないストアなら、どんなハードウェアでも「通過」してしまうからです。本物のストアが通った場合、または判定が無い場合、基板は失敗を報告し、ミッションを起動しません。拒否が観測されて初めて、ミッションが非特権・隔離状態で起動され、基板はそのあと人間が発進コマンドを送るまで待ちます。地上局は手順全体の再実行も要求でき、その場合は基板が再起動して——記憶した行の再生でなく——実際に走り直します。
プラントは、PC の中に
ループのもう半分は、剛体クアッドのシミュレータです。HIL のテストは、プラントの出来でしか価値が決まりません。ノイズも遅れも無い綺麗なモデルなら、どんなコントローラも良く見えてしまい、何も証明しない。だからシミュレータは、実機が実際に直面するものをコントローラに与えます。綺麗な力学で調整したコントローラは、その全部に耐えなければなりません。以下が常時かかります。
- 2 つの IMU。それぞれノイズと機体毎のバイアスを持つ。位置はジャイロより遅い GPS 相当のレート
- 指令に一次遅れで追いつくローター推力、二次抗力、地面近くの吹き返しによる余分な揚力
- 高度とともに強くなる定常風と、地面近くの乱流。相対風速への抗力として物理に入るので、コントローラは風上へ傾いて耐え、それが見える
そして運用者は、危機をキーボードから注入できます。主 IMU を故障(s)、バックアップを故障(x)、ロータを停止(m)、バッテリを落とす(b)、突風(g)、風の強さと向き。その一つ一つに、基板がその場で答えます。
コントローラと PC は、Wi-Fi の UDP 上でロックステップで走ります。PC が 2 ダースほどの float のセンサフレームを送り、基板が 4 つのモータ指令を返し、PC が物理を 1 ステップ進めて繰り返す。往復は中央値 60 ms、335 往復で損失ゼロ。HIL フレームは 20 Hz です。ミッションは配送を完走します——1.4 kg で積載、投下で 1.0 kg へ落ち、コントローラが質量ステップを吸収して上昇に戻る。
何が実測され、何がされていないか
飛行と、リアルタイムの結果は、1 つの制御則の 2 つの別々の実証です。分けておく価値があります。
- 飛行は、上の閉ループです。本物の制御則と安全包絡線が、実機で、Wi-Fi 越しに、HIL フレームのレートで配送を飛ばす。フォールト応答を通してミッションが完走することを示します。
- 1 kHz のデッドライン結果は、同じ制御コードをスケジュールされた周期タスクとして、片方のコアで 1 kHz で走らせ、もう片方でネットワークを回したものです。RP2350:1,741,824 ジョブ中、超過 0 回(周期 948.9〜1056.5 µs)、フル配送飛行。RP2040:113,664 ジョブ中、超過 0 回(周期 998〜1002 µs)、ただし VM ミッション無し——264 KB のチップに両方は載りません。スケジューラがレートを保つことを示すもので、機体を飛ばしているループではありません。
- 制御演算の最悪値は、Cortex-M0+(RP2040)で 190 µs、Hazard3(RP2350)で 98 µs。どちらもボード上の再現可能な敵対的掃引で実測し、1 kHz の予算に対して 5.2 倍・10.2 倍の余裕です。
1 回の 1 kHz 閉ループ飛行は、これらの合わせ技——演算が収まり、スケジューラがレートを保ち、ループが飛ぶ——であって、1 回の実行として示したものではありません。それぞれの測定手法は リアルタイム のページに、ミッションが走る隔離は 隔離 のページにあります。