ハードウェアの知見を深めるためにドローンを作ってみた (購入部品記載)


（2023年12月23日）<font color="blue">前半のNature 2023論文の紹介は完了。</font> 
（2024年1月6日）<font color="blue">後半のドローン作成も完成。</font>

## はじめに
はじめまして. OMRON SINIC Xと松尾研究室にてロボット学習の研究をしている黒木と申します。研究内容については[Personal Page](https://sites.google.com/view/sokuroki/home)をご覧ください。

本記事は[基盤モデル×Robotics Advent Calendar 2023](https://qiita.com/advent-calendar/2023/robot-ai)の22日目の記事です！

# 本記事の構成とモチベーション
本記事は主に以下の2つの構成からなります。
- 前半: ハードウェア（ドローン）の知見を学習に活かした研究の紹介
- 後半: ドローンを自作する手順のまとめ（未完。 1月初旬までに更新します）

僕は学習からロボティクスに裾野を広げた身でして、ハードウェアを自作した経験がありません。**純粋なモノづくりへの興味を満たしつつ、ハードウェアへの知見を深めるため**に本記事を執筆します。

# 前半: ハードウェア（ドローン）の知見を学習に活かした研究の紹介

**論文**: *Champion-level drone racing using deep reinforcement learning*  
**著者**: E. Kaufmann, L. Bauersfeld, A. Loquercio, M. Müller, Vladlen Koltun, Davide Scaramuzza  (Intel, チューリッヒ大学)
**出版**: Nature, 2023  

本研究では、RLをドローン操作に用いることで、ドローンレースの世界ランカーらに勝利を収める操作性能を達成しました。 強化学習は既に囲碁やatariゲーム内で人間に勝っていますが、ドローン操作のように**現実世界でRLが人間に勝利するのは本研究が初めて**であるとされています。

### ビデオ
ダイナミックでわくわくするので、とりあえずビデオを見るとよいです。
<iframe width="100" height="300" src="https://www.youtube.com/embed/fBiataDpGIo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

### 研究紹介スライド
本研究について、同じくOMRON SINIC Xでインターンをしている[渕岡湧仁](https://yunifuchioka.github.io/)さんが非常に分かりやすくまとめています。

<iframe src="https://docs.google.com/presentation/d/1NOo7i2I9LqgxKSwewroohtkLSfEMXjp7IaCNGL7oUPw/embed" frameborder="0" width="960" height="365" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

### 要点
本研究の詳細は上記渕岡さんのスライドをご覧ください。本記事において重要なのは、本研究が**著者らが長年にわたるドローン研究の中で培ったハードウェアの知見をRLの学習に存分に生かした**という点です。

例えば
- 電池残量によるモーターの性質変化を考慮したモデリング
- low level controllerのログファイルから掘り出したparameterを使用

するなど、**そこまでやるか（できるのか）**、、、という工夫がいくつもあります。本研究に感銘を受け、僕自身もハードウェア側の経験をしたいと思うに至りました。


# 後半: ドローンを自作する手順のまとめ


年末年始前後で約7日間をフルに使い、無事ドローンを飛ばすことができました！工程は部品の選定、フレーム・回路設計、ロボットの組み込み、マイコンによるPID制御となります。

まずは作成したドローンの飛行動画をご覧ください。
![マイビデオ-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/b28377d3-5c8e-7fe8-6843-5dfb6b3ef7cf.gif)

動画後半にて回転方向への不安定さはあるものの、安定した離陸と着陸、また空中でのうまくバランスが取れていることが見て取れるかと思います。作成を通して部品や制御周りの知識はもちろん、ロボット作成に取り組む際の注意点など多くの気づきがありました。

本記事ではドローン作成に当たり必要な情報をできるだけ詳細に公開します。PID制御のパラメータ調整を行う際の工夫など詳細な部分についても言及していきます。

## コード
- Arduino実装: https://github.com/Kuroki1931/DroneControl
PID制御、コントローラーとの接続など、僕がドローンを飛ばすのに使用したコードが一つのファイルにまとまっています。約50Hzでloopが回ります。

## 購入した部品
- Arduino Nano Iot 33
- ブラシレスモーター　4つ　https://www.amazon.co.jp/gp/product/B071V4VDJC/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&th=1
- ESC　4つ
https://www.amazon.co.jp/gp/product/B01GJDUQIC/ref=ppx_yo_dt_b_asin_title_o01_s01?ie=UTF8&psc=1
- プロペラ　４つ
https://www.amazon.co.jp/gp/product/B07RSNRQZJ/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1
- リモコンと受信機
https://www.amazon.co.jp/gp/product/B0B1MLXNY7/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1
- 12ボルト13アンペアの電源
（上の動画でドローンから伸びている配線はこの電源につながっています。リチウムバッテリーを使うのが一般的ですが、競技や広い範囲で飛ばすというモチベーションではなく、とりあえずドローンを飛ばしてみたい・作成の過程での学習に重きを置きたい、という方にはおすすめの方法です。バッテリーの充電が不要なため、パラメータ調整を効率的に行えます。）

## まずはモーターを回してみました
<font color="red">画像に移っている諸々の部品はテスト用で上で紹介した部品とは異なるので注意してください。ただ設計はほとんど同じになるかと思います。</font>

<img width="200" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/428f594a-c8b0-709c-b18f-a745b532fcff.jpeg">

前提としてブラシレスモーターはPWM（Pulse Width Modulation）という信号を送ることで回転を制御できます。PWMはArduinoなどマイコンから出力できます。画像では、回しつまみでPWMの幅を調整しプロペラの回転数を制御しています。

試しにプロペラを回すに際には、ついでにプロペラがどの程度の重さを持ち上げられるかを確認するとよいです。ブラシレスモータはパワーがあるので、一般的なドローン部品を持ち上げられなくなるとは考えにくいですが、バッテリーらと合わせると重くなるので確認しておくのがよいでしょう。

## フレームを作成
3Dプリンタを用いて作成しました。ネットに転がっている情報を参考にしつつ、[onshape](https://www.onshape.com/en/)でCADを書きました。いろんな情報が転がっているため悩ましいですが、**軽さと強さの両立**を意識するとよいように思います。

軽いほうが低出力モーターで飛ぶことができ安定しやすいように思います。一方で、軽ければよいというわけではありません。落とし穴は大きく2点あって、
①耐久性の低下：軽くするために重点率を下げてすかすかすると、墜落や壁と衝突した際にフレームが折れます。
②制御の不安定化：薄くペラペラにすると、モーター力や振動でフレームがゆがみ、モーターの回転によって生み出された力が横方向にかかるなど、制御を困難にします。
**適度に重点率を上げる（自分は60%くらい）、ペラペラな設計ではなくT字型や円柱型にするなど剛性を上げることで対策をしましょう。**

僕が作成したフレームは以下になります。上の注意点を満たしたよいフレーム**ではない**ので参考程度にご覧ください。何とか飛ばすことはできたんですが、先述の薄くてペラペラな設計であり、実際に2度フレームが割れました。フレームが壊れると部品の組み込みがやり直しになり時間を食うので、軽さにのみにとらわれず、耐久性も兼ね備えたフレームを設計するよう心がけるとよいでしょう。

<img width="200" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/fbc6837b-b276-9c89-be81-c6f8090dfdc5.png">

stlファイル：https://drive.google.com/file/d/1xCMGZ71YjKUms7jhfMJp-0cZVIJcMequ/view?usp=sharing

## テスト用に簡易的な組み込みを行う

作成したフレームに、ブラシレスモーターをくっつけ、ESCを接続します。この際回路はまだブレッドボードで良いかと思います。<font color="red">画像はArduino Unoになっていますが、最終的に使用したのはArduino Nano 33 IOTです。</font>

<img width="200" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/946909fc-dc79-fc49-d9d9-847097ada7a4.jpeg">

画像ではつまみに合わせて同一のPWMをUNOから4つのモーターの送っています。電源とモーターの接続は並列です。すべてのモーターが回転するか、対角ごとにロボットの回転方向が逆になっているかなど確認しましょう。


更にここで、マイコンへのPIDを実装するとよいと思います。ちょっとベースの回転が高めで傾きによる回転に変化が分かりづらいんですが、以下の動画のように**傾けた方向の羽の回転が強まり、逆側の羽の回転が弱まる**ように実装しました。これによりドローンが傾いた際に水平に戻す力が加わります。

![PID-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/59c80fe9-81e9-8662-9df7-d690f548345b.gif)

実装の詳細は公開しているコードをご覧ください。簡単に説明をすると、Arduino Nano 33 IOTにはIMUが乗っているので、**ジャイロと加速度の合わせて6つのセンサー情報**を取得します。センサー情報から実際に期待がどの程度理想状態（水平状態）から傾いているかを推定をするわけですが、カルマンフィルターやMadgwickフィルーターなどが代表的に使われます。僕は**Madgwickフィルターを使用して**実装をしています。推定された傾きを理想状態に近づけるようPID制御を実装します。

細かいパラメータの調整や羽の出力のキャリブレーションは組み込みが終わって実際にドローンを飛ばす段階で本格的にやることになるので、この段階ではほどほどでよいと思います。また羽をつけると危ないので、ティッシュで回転を見れるようにするのがおすすめです。

## コントローラーでモーターを回せるようにする

流れとしては3段階あり、①コントローラーでの操作を受信機が受け取る、②配線を伝って受信機が受け取った情報をArduinoで取り込む、そして③取り込んだ内容とPID制御を合わせてモーターの回転数を決定します。
![PID.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/a47eeafb-158d-7eef-3bec-820c5fdb764a.gif)

またここで2点ポイントを挙げておきます。
- **コントローラーの操作とロボットの動きが直感的になるよう**に実装しましょう。操作スティックを前に倒せばドローンは前に、右に倒せば右に進むようにしましょう。
- 後々のPIDパラメータ調整に向けて、4つのプロペラを回すための信号以外に、**つまみの回転に応じてPゲインとDゲインを動的に調整できるようにしておく**と楽になります。

上記は合わせて公開しているコードに実装してあるので、ぜひ参考にしてください。

## 基盤に移行する / 機体を組み立てる

ブレッドボード上の回路を基盤で再現しましょう。僕は4枚のプロペラへの導線が基盤の4つ角に来るように回路を組みました。基盤の裏側には受信機がついています。

機体の組み立てはうまく配線が収納できるよう工夫をしましょう。
<img width="200" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/7f92dab0-bded-4d26-5142-321688b96d50.jpeg">
<img width="200" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/1970f07e-4b7e-1b27-4ee9-6b172010b13b.jpeg">

自分は最終的に回路部は箱で囲い、その中に配線らを収納しました。**そこが平らになり、離陸と着陸の安定性が増す**ためおすすめです。
<img width="200" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/fd4ecb25-cc94-ef43-eb30-4a0085ff9009.jpeg">

## PIDのパラメータ調整を行う

パラメータ調整は時間がかかりますが、工夫をすることで調整にかかる時間を減らせます。僕が行った工夫は以下の2つになります。
- コントローラーの説明で触れたつまみで動的にゲインを調整できるようにしておく。
- 以下の動画のようにロープを使ってドローンを空中で固定する。

![つんつん.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550650/9f006b9d-6145-76b4-dad0-e6924907d3a8.gif)

この二つを組み合わせると、ドローンの安定性を見つつパラメーターを調整できます。僕も初めはこれらの工夫は全く取り入れておらず、飛ばしてはゲインを調整してArduinoをUpdateするを繰り返していました。これはめちゃくちゃ余計な時間がかかりますし、変数が多すぎてパラメータのあたりをつけるのが難しいです。実際に二つの工夫を取り入れたから、**実際に飛ぶのに使用したパラメータを得るまでに1時間程度でした**。その前には1日半ほど時間を費やしていましたが、見当違いなパラメータを選定してしまっていました。なので、<font color="blue">上記の2つは必ず取り入れたほうが良いと思います。</font>

## 飛ばしてみる

パラメータ調整と、実際にドローンを飛ばす固定をいききします。できる限りPIDにより安定性を保てるようにはするものの、重心の偏りや環境変数により、機体が不安定になってしまうことがあります。それらのキャリブレーションやパイロットスキルの向上を掛け合わせることでロボットを飛ばせるように調整しましょう。

## ドローン作成を通して得た知見

僕は機械系出身でもなく、またロボット系のサークルに属していたわけではないので、今回は初めてのロボット作成でした。作成の過程で強く感じたのは、気が付ける守備範囲が広がったように思います。まず一つ目は、**ハードウェアのちょっとした工夫で制御が楽になること**です。ドローンの底の部分を箱で覆うことで、地面との接触が平らになり、離着陸が大きく安定しました。また、ロボット作成よりはむしろドローン特有の気づきですが、高周波でloopが回らないとロボットが安定しないこともあり、**周波数により気を遣うよう**になりました。実は実装初めはあまり周波数を気にしておらず、10Hz弱で制御をしようとしていました。これ以外の知見も以下に列挙します。
- ちょっとめんどくさくても良さそうな工夫は早い段階で取り入れておく
- PIDのパラメータは（もちろんスケールにもよるが）自分でちょっとしか変えていないつもりでも挙動が大きく変わる
- ブラシレスモーターやESCなど部品に詳しくなる
- かつてはマイコンと聞いてビビッていたが、意外とC++などの知識をベースに進めることができ、敷居が高くないことが分かった（ArduinoのUIがすごいのもある）


## 学習に役立つ知見

上記でも触れましたが、周波数を意識できるようになったのは大きいと思います。Diffusion policyでは周波数を可変に推論できるようですが、少なくとも従来のニューラルネットでは周波数周りは制限があり、僕としてもこれまであまり意識できていませんでした。またIMUなどのlow levelセンサーへの敷居が下がり、伴ったジャイロや加速度といった変数への感度が上がったことで、それらを考慮したネットワークの実装などアイディアが広がるのではないかと思います。また少し違った角度ですが、メカ系の方々とより共通認識を持って議論をできるようになったのではないかと思います。ちょっとした部品の名前もそうですし、ハードウェア特有の楽しさ・苦しさを共有できることは、研究を遂行・発展させる助けになるのではないかと思います。

## まとめ

以上、前半ではハードウェアの知見を学習に活かした研究を紹介し、後半では実際に僕自身がドローンを作成してみました。

ロボット作成に当たりアドバイスをくださった大久保君、渕岡さんどうもありがとうございました！