aks3g が 2021年01月10日21時19分26秒 に編集
初版
タイトルの変更
機械学習するミニ四駆を作る
タグの変更
ARM
ミニ四駆
Python
秋葉原2021
メイン画像の変更
記事種類の変更
製作品
本文の変更
# ミニ四駆AI ミニ四駆AIという競技をご存じでしょうか?知らないと思います。マイナーなので。 詳しくは[公式のWeb](https://sites.google.com/site/ai4wdcar/)をご覧ください。 また、ソフトウェアについては全部解説しても仕方がないので[Github](https://github.com/aks3g/ai_mini_4wd_kit)の方をご覧ください。 # 概要 ミニ四駆AIでは、基本的に走行用バッテリ(単三乾電池2本)でモーターが回れば後は何やってもいいというルールになります(コースを走る前提なのでサイズ等はタミヤのミニ四駆レギュレーション準拠)。外部との通信や外部定点カメラの設置などもルール上OKになりますが私は趣味の問題で、1.走行用バッテリを使って制御装置を動かす、2.外部機器を使用せずオフラインで完結するという2つの縛りをもって参戦しています。 制御可能なミニ四駆を達成するためには、出力部としてモータードライバ、入力部として各種センサが必要になります。モータードライバは市販のものを使うことも多いようですが、低い電圧でそれなりの電流を流そうと思うとディスクリートのFETを用いて自分で作る方が性能が良いです。センサは、多くの競技者がIMU(加速度、角速度センサ)を使っています。私も使っていますが、それに加えてモーター電流のセンサとモーターの回転数を取得するタコメータを装備しています。 ![外観](https://camo.elchika.com/2ab5362d9e2c1fdf058c5b87a6739837e33fb3e8/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f33626332323732302d323863622d343361622d393464342d353638363633636533323866/) # 構造 ミニ四駆をご存じの方はピンとくると思うのですが、こちらのマシンはS2(スーパー2シャーシ)にポン付けできる形で設計されています。バッテリとモーターとの接触部(ターミナル)の間にフレキ基板を挟み、電池の出力を一旦制御装置に流して、モータードライバを介してモーターに電流を流す構造を取っています。 ![モジュール部](https://camo.elchika.com/273d733010bb6c75cb3147cfee6ed48cc2b9ab29/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f30666538353865652d643733662d343236392d396330372d643062633530666238646362/)![ターミナル部](https://camo.elchika.com/19ac2f216043c74f79d279cf91454b81ff64fd88/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f38353338333033312d643037352d346137372d386130662d386166373838646436613861/) 構造部品はCADで設計してDMMで出力しています。S2シャーシのバッテリーホルダにボルトで固定できるようにしてあり、S2シャーシ側は無改造で済むようになっています。 # 制御装置 競技者によって制御装置の作りは違いますが、私の場合にはモータードライバ、センサ、MCU、電源などを1つの基板に実装しています。回路図全部説明しても読みたい人いないと思うのでブロック図を描きます。 ![ブロック図](https://camo.elchika.com/aba12b5c3c7267f230f8bf2f781b3307923b356c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f35306131383035332d353636302d343131352d383132392d346331643333616139623363/) ## モータードライバ モータードライバはミニ四駆を走らせるための核心部品で、うまく作らないと速く走れません。私が作ったものは一般的なHブリッジのモータードライバですが、Hi側もLo側もN-ch Power MOS FETを使用しています。電源電圧が2-3V程度なのでPchのゲートを開けるのが大変そうだったため、昇圧できるN-ch用ゲートドライバを使用することにしました。 ミニ四駆を速く走らせるためにはOn抵抗が低いFETを選定する必要がありますが、ON抵抗が低いとゲートの容量が大きいことが多いです。ゲートの容量が大きいとゲートがONするまでに時間がかかるためPWMでの制御に向きません。今回作ったドライバでは、PWM制御を行わないHi側はややゲート容量が大きいがON抵抗が小さいFETを、PWM制御を行うLo側はゲート容量が小さいがON抵抗がやや大きいFETを選定しています。 ![モータードライバ部回路図](https://camo.elchika.com/3885026f3a0007adbd6264ffcba9a37f86282ac4/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f64666639363461352d643563372d346336332d383939372d323630333237353736633163/) 実はFETの選定作業が一番面倒な作業で、数種類のFETを購入し実際に半田付けして実力を確認していくことで最も良い組み合わせを見つけました。また半導体部品は日々新しい部品が出てくるため、大会の前はFETの貼ったり剥がしたりの作業が繰り返されます。 ## センサ系 搭載しているセンサはIMU、タコメータ、モーター電流、電圧センサとなります。 タコメータは搭載方法を悩んだ結果、プロペラシャフトの回転をフォトリフレクタで読み取るという方式を取りました。この方式の有利な点はミニ四駆側に改造をほとんどせず(プロペラシャフトに黒テープを張る必要はある)に回転数を取得できることです。 ## MCU MCUとして旧Atmel社のSAMD51を使用しています。外部部品をほとんど使わずに120MHzで動くことが出来るのである程度重い処理を行わせるのにも最適です。またUSB PHYを持っているため外付け部品なしでUSBシリアルの実装なども可能です。 # ソフトウェア SAMD51のドライバからスクラッチで書いているため外部ライブラリをほとんど必要としません。ただ、実際の走行制御を行う部分にはMicroPythonを使用しています。ちょっとした調整を行うときにFlashを書き換えるよりも、スクリプトベースで処理を切り替える方が大会の時に各種対応が容易だと感じたためです。MicroPythonのポーティングについてもGithubの方に置いてあります。port以下の他のプロジェクトを読めばポーティング自体はさほど難しい作業ではないと思います。 Micro Pythonは容易にプログラムを変更できるものの、C言語/アセンブラで書いたプログラムに比べて、100-1000倍程度遅くなります。実時間処理が求められるミニ四駆AIにとっては致命的な速度であるため、処理が比較的重い処理(中央値処理や機械学習の枠組みなど)はC言語で記述して、MicroPythonからは組み込みオブジェクト/関数としてこれを実行できるようにしてあります。 # センサデータの扱い センサデータのうち、ジャイロセンサの値とタコメータの値を主に使用しています。これが分かると、走行距離、速度、回転半径が分かるためコース形状の推定などが容易になります。 機械学習をする、しないに関わらずコース上でのコース形状の同定と自己位置推定が出来る必要があります。コース形状の同定はジャイロセンサの値とタコメータの値があれば容易で、スタート地点からの移動量をプロットすればよいです。実験環境でコース形状を同定したときの結果が次のようになります。 ![キャプションを入力できます](https://camo.elchika.com/1b4bd49519c5a062dd4d8edcf3068deab3feae7d/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f34653939393339372d363130332d346562662d396330662d336638363535306430383830/) ![キャプションを入力できます](https://camo.elchika.com/42e3d10d760a87b0ea3761ebbfc9128c7aae023b/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f30306366303033612d653865622d346639392d393862372d6364333762386166666538312f31306531373463302d343664662d346133622d613131632d646565653334643365376565/) # 自己位置推定&機械学習 コースの形状が事前にわかっている状態でミニ四駆がコース上のどこを走っているかを認識するための操作を自己位置推定と呼びます。ミニ四駆の場合、回転半径が事前に分かっている(3レーンなら3種類、5レーンなら5種類)であるため、自分がどのレーンを走っているかはすぐにわかります。この、自分が今どのレーンのカーブを曲がっているかという情報と存在確率分布の考え方を使うと自分の位置が推定可能です。このあたりは確率ロボティクスの本を読んでもらうのが確実です。有名どころのアルゴリズムではパーティクルフィルタがありますが、あれは処理が重いのとパーティクルフィルタを使わないといけないほど状態空間が多くないので簡素なアルゴリズムで大丈夫です。自己位置推定が出来てしまえば、あとは試行錯誤させながら最適な走行を獲得する機械学習をさせるだけとなります。一般的な機械学習では学習データセットを大量に用意する必要がありますが実際の機械でそれをやろうとすると日が暮れます。ですので、強化学習をベースにした学習量が少なくてもそれなりの結果が出る(最適な結果ではないと思うが、それなりに良い結果を生むもの)アルゴリズムを組みました。実際に10回ほど学習させた結果の動画を張っておきます。 @[youtube](https://youtu.be/QMZVI695LoA) ゼロ着前の上り坂に差し掛かる部分でブレーキを思いきり踏んでいる様子が分かると思います。 # さいごに 未だにミニ四駆AIは本気のミニ四駆勢に勝てない状況にあります。今後勝てるかといわれると厳しいなぁという気持ちがあるのですが、いつかミニ四駆が自力で獲得したセッティングでいい試合が出来ると面白いなぁと思っています。また、競技人口が絶望的に少ないので興味がある方はぜひ自分でも作ってみてください。