RXマイコンでCからC++のコードを実行したい
タイトルの通りです。前提は以下の通り、
- 開発環境:e2studio 6.3
- CCRX: v3.0.0
- マイコン:RX71M
経緯
e2studioでC++プロジェクト生成した際に、intprg.cがintprg.cppになってくれないため、intprg.c上に記述した関数の実行先をC++のメソッドにしたいと思った
解決方法
以下の流れで参照の流れができていればよい。
//intprg.c void Excep_CMT0_CMI0(void) { interrupt_func_cmt0(); }
//InteruptInterface.hpp #ifdef __cplusplus extern "C" { #endif void interrupt_func_cmt0(void); #ifdef __cplusplus } #endif
//InterupptInterface.cpp #include "InteruptInterface.hpp" using namespace hogehoge; // you can use namespace void interrupt_func_cmt0(void) { // any proccessing below() LEDDriver::LED1_TURN_ON(); }
問題点
この状態では、public
でstatic
な関数しか指定できない。
JavaScriptのイベントのように、コールバック関数で、特定のオブジェクトのメソッドを唱えるには、
割り込み関数interrupt_func_cmt0
内でうまくやる必要がある。
例えば、リアクティブプログラミング
を参考に登録した関数を呼び出せれば、汎用性もあり、効率が良くなるだろう。
斜めの姿勢制御をするには
この記事はMice Advent Calendar2018の8日目の記事です。
昨日はb4rrAcud4のPython&Matplotlibで簡単シミュレータを作るでした。
GUIにおいて、今となってはUI/UXを考えて作るのは当たり前であり、それは、は自分を手助けしてくれるためのものです。
しかし、UI/UXの設計を怠ると、当たり前な便利な機能やUIを遠回りして実装してしまう、なんてこともあります。良いUIがあれば率先してパクりましょう。OSSやフレームワークはそれを助けてくれるはずです。
0. 斜めの姿勢制御について(About control on diagonal running.)
マイクロマウス、クラシックマウス共に、最短時の鬼門1つが、斜め直進時の姿勢制御だといっても過言では ないだろう。
今回はその制御の一つの解を示せたらと思う。
1.なぜ斜めの姿勢制御は難しいのか(Why Diagonal Running is so difficult?)
通常の直進時は、事前にセンシングして見つけた一定のリファレンス値を理想値として、PID制御を行う。
斜めの姿勢制御では前向きのセンサーを数度傾けることで、ズレた際に見える柱を検知し、避けるように制御することが多い。(あるいは、通過後の柱のピーク値から偏差を推定し、移動するなど。)
今は思う、それ直進時と全く制御するモノが違うじゃん。と
ただのPID制御だけでいい感じに行ってくれと思いませんか?
2. 簡単に制御するためのあるべき論は?(A certain argument for easy control.)
あるべき論としては、勿論、以下の通り。
常に理想とする場所があって、そこに収束するように制御ができるようにする。
言い換えると、直進時と同様、
事前にセンシングして見つけた一定のリファレンス値を理想値として、PID制御を行う。
3. マイクロマウスのルールについて(Rule of MicroMouse)
以下抜粋
2-4 各単位区画の四隅にある0.6cm×0.6cmの小正方形部分を格子点と呼ぶ。終点領域内を除いたすべての格子点には少なくとも1つの壁が接している(図1参照)。また、迷路全体の外周の壁は全て存在する(図1、図2参照)。
上記のルール上、以下のことが言える。
斜め走行中の車体の近接する柱には壁がある。
つまり、これを以下のように考える。
斜め直進中、壁が見えるようにセンサーを置け。
4. センサーの配置を斜め用に考える(Think of the arrangement of sensors for diagonal use)
以下の画像の通り、真横90度センサーと45度センサーを使う
このとき、斜め進行中、以下のように壁が見える。
このとき、45度センサーが柱・壁の切れ目をとらえることが重要である。
壁が進行方向に対し、手前を向いているとき、45度センサーによって、確実に見える。
壁が進行方向に対し、手前を向いていないとき、90度センサーによって確実に見える。
5. 理想のリファレンス値をとる(Take the ideal reference value)
45度センサーの壁・柱の切れ目の閾値を定め、斜め直進をする。 その際、ログ情報として以下を扱う。
- 45度センサーの値
- 90度センサーの値
- 45度センサーの切れ目からの直進した距離(周期は180×1/2 or 90×21/2)
- 左右それぞれ、壁切れからの距離を加算
45度センサーの値と直進した距離を同時プロットしたのが以下。
90度センサーの値と直進した距離を同時プロットしたのが以下。
45度センサーが検知した、切れ目以降の距離0から180×21/2 (or 90×21/2)までの値をテーブルとして持つ。 これを90度センサーも同様に行うと、距離に対し、理想のセンサー値は以下のグラフの関係がある。
横軸=距離としてテーブルにすればよい。
あとは切れ目以降、この距離に応じたリファレンス値を参照して、その偏差をPID制御を行えばよい。
注意点として、柱などの付近、黄色の30~50、160~190、灰色の0~20、220~250は切れ目に近く、不安定だと判断したため、現在、この区間にいる際は制御に使ってない。
ね?簡単でしょ?
真横90度センサーがあることで、Y.Iがで示していた補正とはまた異なる、探索中の壁切れの「スラロームの後区画中に壁切れ」が実現します。
センサー5個アリだと思いませんか?勿論、最後の一つは正面に配置します。 前壁制御に使うことで、より正確にスラロームの前区画の調整します。
最後に(at last...)
明日、12/9はmm_55Tさんの「寄席に初めて行った感想」です。
概念の上の存在だったあの人が、浅草に顕現したときのお話です。
マイクロマウス2018結果報告
全日本制覇!!!!!!
見出し通りです。
クラシックマウス競技にて、やっとのことで優勝を勝ち取りました。
まずここに、Miceの諸先輩方をはじめ、アドバイスをくれた皆様に感謝申し上げます。
2011年にMiceに入部して、8年で到達できました。 数字にすると長いのか短いのかわからないですね。
パラメータ紹介
param | unit | |
---|---|---|
直進速度 | 5.3 | m/s |
加速度 | 22 | m/s2 |
減速度 | 22 | m/s2 |
探索ターン(90) | 1.0 | m/s |
大回りターン(90) | 2.2 | m/s |
180度ターン | 2.05 | m/s |
45度ターン | 2.05 | m/s |
135度ターン | 2.05 | m/s |
v90度ターン | 1.95 | m/s |
2年前のExiaと見比べると、ターンはそんなに変わってないように見えますが、安定性が全く違います。
更に言うと、今年のはこのパラメータで完走しきってます。
実は意外とヤバかった
それは2018年12月1日、午前3時のこと・・・
突如として電源を入れて、そこそこ電流を流すような動作をすると、マイコンのリセットが発生するというマズい状況になりました。
そして電源が入らなくなりました。
ここ数年の感覚では直前でハードをいじっているような機体は大会で成果は残せないと決めつけており、 「これはダメだな。」と思っていました。
そんなときのために用意しておいた
実はここ数年、2台目を作るようにしています。理由は2つ。
- 抵抗値などの電子部品のバリエーションチェックのため
- (ソフト面だが)過去に、本番直前にマウスの開発をしていたPCが全日本大会直前で壊れ、シード選手にも関わらず詰んだ
このことから、2機目の準備とGithubを使ったソースコード管理をしていました。
ただ、足回りだけは、コストがかかるため、1台しか作れないのが実情です。
そして、昨年のアドベントカレンダーで紹介した調整システム。これが無かったら、調整できずに諦めていた。
4時間でパラメータすべてを調整し、試走会に間に合わせた。
勝因は何か
考えている勝因は3つ
【1つ目】迷路との相性が良すぎた
ここ数年は連続ターンなどの険しい経路を出す、長い斜めを用意するなど、安定性、再現性、正確性に重きを置いた迷路が多かったが、今年は、ハードウェアスペックがものを言う迷路にだったことが大きい。
かといって、高速域で姿勢がぶれるマウスが散見されたことから、ターンばかりに集中し、最高速度の調整が十分にできてないのでは?と思いました。
【2つ目】調整システムの存在。
調整した項目の差分はGitで管理しているため、過去のデータから何のパラメータをどうやって調整すればよいのかが明確だった。このことから、4時間という短時間で調整しつくせた。
【3つ目】ハードウェア性能
専門ではないので、特別勉強したわけではないが、今回「不得手・不足の無いもの」を作ろうと思って作った。
「高い部品には、高いなりの理由がある。」今回、MAXONのDCX10Lを使っていたし、特注のアルミフレームも作った。
その結果、今シーズン、アニキから「走りがしっかりしてきた」と言われるようになった。
現に、決勝の動画を見返すとExiaAlterは最短成功時、ただの1度も姿勢を崩していない。加速・加速度に機体がちゃんと耐えているからである。
吸引にしているからといって、安易に軽くしていいわけではない。 そして、吸引するにも非吸引でちゃんと仕上げてきてから吸引を使わないと意味がない。
具体的には、DCマウスならば、非吸引でも直進速度4m/s、全ターン1.2m/sは出せる。そこから先、限界を見てから吸引に挑むべきだと思ってます。 吸引に関する言及はここまでとしますが、理解せずにロマンだけで吸引をしても、「サーキットで非吸引に負ける」なんてことがあり得ます。(というか今年も何件かあった)
反省点。
正直、今シーズンは「やりすぎた」。
今年、勝ちに拘った理由はいくつもあります。
それにしたって「やりすぎた」と思ってます。
だが、目標は達成した。
東日本大会
大会結果
- クラシック2位
- サーキット1位
分析(クラシック)
過去の中部地区大会の迷路をリバイバル
- 金沢草の根に比べると、比較的難易度は抑えめ
探索に失敗。スラローム時の直進区画の補正プログラムに特定の条件で打ち切るバグがあった。
当日中に部屋で同じような迷路を再現、特定に至る。
前日の試走会などがあれば十分吸収できた。
東日本大会は前日の試走会がある年とない年がある。 現地確認は大事だが、家でどれだけ担保できるかも重要である。最短は全ターンのパラメータの挙動を確認。
- フェイルセーフがかかりやすい。
機体の損傷を回避するため、必要な措置と判断
分析(サーキット)
- 過去のU宮さんの記録を上回ったことから、日本記録更新した?
- 速さのために、中心を走ることをあきらめたことで、ターン時の曲率半径を拡大。
- ターン速度の向上、減速区画の減に成功
- 壁ギリギリまで近づくことが重要
次回までにやること
- 探索の安定性向上。(対処済み)
- 制御系の変更
- やや追従が遅い場面が見受けられたた。
- ターンの再確認・再調整
- バッテリーを新しいのを作っておく(完了済み)
制御について
以下の変更を加えてみた。
Before
- 並進方向の制御量=速度に対するPID+距離に対するI
- 回転方向の制御量=角速度に対するPID+角度に対するI
After
- 並進方向の制御量(今のところ変更なし)角度と同じような構成にすべきか確認中
- 回転方向の制御量=角速度に対するPD+角度に対するPI
目標角度の入力の対応ができるように修正
金沢草の根大会
まえがき
4年ぶりに参加した金沢草の根大会
4年前と違い、場所が鶴来と金沢駅から遠くなってしまったが そこには、新たなる精神と時の部屋が出来ていた。
広大な自然の中にあるきれいな校舎
廃人たちが集うこの北陸の大地で起きた事件とは・・・
環境
迷路は昨年のU氏のブログにも合った通り、他の大会と路面とだいぶ違う印象。ざらつきが目立ち、タイヤかなりが削れた印象。 埃が少ない気がしました。
照明がLEDなのか、一部の区画で挙動がおかしくなる現象に苛まれる機体が少しいました。
準備
新作ExiaAlterの初陣に、初の大会最終出走と判明。
だが、探索すらできないことが発覚
2か月間ほとんど調整してないせいか、拗ねてしまった模様。
探索時に利用する補正が諸々狂っていたらしい。
結局、夜中3時までかかってしまったが、例の調整システムのおかげで、何とか調整をやり切れた。
人事は尽くした
大会結果
優勝しました。本来Busterすべき後輩たちがいなかったけれど、昨年度個別に指定していた黒椿をバスターしたのと、Dの陰謀が見え隠れしていたが、それを阻止。
詳細
- 1走目:1m/s探索は難なく成功(振り回されていたため、改良の必要あり)
- 2走目:オートスタート⇒失敗
- 3走目:最低パラメータ⇒成功(暫定3位)
- 4走目:たぶん2走目と同じパラメータ⇒失敗
- 5走目:複数ある上位のパラメータの中で最低のパラメータ⇒優勝
やはり、最短の安定性が課題として残る。
壁切れの読み逃し時の安全装置が働いてくれてたのは非常に助かったが、全日本に向けて不安が残ってしまった。
オートスタートの失敗は海外大会にも影響が出る。早急に対処せねば。
分析
迷路は10年前の中部地区大会のリバイバルで難易度が高め(シーズン初期でこの難易度を要求とは・・・。これは後半戦はもっとヤバい迷路が来そう)
完走率は16/28、最短成功率が9?/16。
比較のしようがないが、全日本の地区予選という位置づけなので、これぐらいの難易度ってことなのだろう 探索のゴールは難しくないが、欲張ろうとすると大変になる。お手本のような迷路ですね。
実際、最短に成功しているのが、昨年の全日本決勝に出てる人ばかり。やはり経験値の差が出てる気がします。
しかし、新作を出してきてる人が、ハーフ合わせても少ない。
9月に合わせているのだろうけど、それだと学生大会に間に合わないだろう。
終わりに
Twitterでも何度も言ってますが、今回I,Sysの組織力を感じました。 てきぱきとした運営、見ていて感心しました。
ペヤングGigamaxは好評でしたが、もう1つか2つ買ってくるべきでしたね。
副賞のヒートガンですが、おかげで旧作のマウスからマイコンを引っぺがすことに成功しました。 これで、BGAの実装もできたらな・・・
調整項目たち
調整がつらい
アドベントカレンダーでも書いた気がするのだが、何がどの規模で辛いかを伝えてなかったので、紹介したい。
調整項目の種類
項目は大きく4種類
- フィードフォワード制御で使用する物理的で自明、または計算により導出可能な数値
- スラロームなどのターンパラメータの計算可能なモノについてもここ
- フィードフォワード制御で使用する、実測により導く数値
- 計測が難しい摩擦、慣性モーメントはここ
- フィードバック制御で使用する、シミュレータなどを利用して当てはめ可能な数値
- matlab大好き勢や最適制御大好き勢に任せます。知らない。
- フィードバック制御で使用する、実測により調整する数値
おおよそ、新しい機体が完成した後に、数字の順番でパラメータが決定されると思います。
1. FFが自明
例えばモーターなど、カタログスペックを参考に、
- トルク定数
- 回転定数
- 逆機電量定数
- 電機的時定数/機械的時定数
- 抵抗値
- 質量
- ギア比
などの数値を使用し、出力トルクを導出、その後、電圧へと変換しそれをDutyとして扱うと思います。
2. FFが自明でない
1とは異なり、
- 慣性モーメント
- タイヤのグリップ力
などは、個人での計測は難しいため、繰り返しによる調整が必要になる。 例えば、FBの項をなしにした状態での動きを確認した場合の追従具合を見る。 FFが適切ならば、原理上応答が遅くなるFBの項はゲインを低く設定できる。これはロバスト性の向上にもつながる。
類似として、光センサーから距離を導出際に用いる、パラメータの決定もこれにあたる。
3.FBが自明
知らん。次。
4. FBが自明でない
一番つらい。
具体例として、
- モーターのゲイン(PID)
- ジャイロの値から角速度へのゲイン(左右それぞれ)
- 角速度追従のゲイン(PID)
- 光センサーを使った制御のゲイン(PID)
- 光センサーを使った制御のゲイン(斜め走行時)(PID)
- 区画の真ん中を走るために、
- 左右の中央時(通常時+斜め時)
- 壁切れ制御の閾値(有無の判定含め)
- 探索時の壁の有無の判別する閾値
- 壁切れ補正を時の直進距離
- 前壁制御の要求値・閾値
- スラローム時の前距離・後ろ距離
- 左右・斜め進入時で1つのターンで最大8項目×ターンの数だけ
調整に必要なもの
- 時間的余裕
- パラメータの管理能力
- 壊れない精神力
最後に
文章にしてしまうとなんて事の無い、と思うじゃないですか。。。調整パラメータが100を超えるのは意外と簡単です。 パラメータ管理を正しく行うことで、次回作以降の調整スピードにも大きく影響を及ぼしますので、管理方法も考えましょう。
また、調整に際してはバイナリへの書き込み回数を減らせるようにシステムを構築するとよいです。 例えば、「シリアル通信から、フラッシュ領域への書き込み」など。コレだけで、ビルド+書き込みの時間を大幅に削減可能です。
【俺式】ジャイロセンサの調整術
はじめに
タイトルにある【俺式】の通り、経験則に基づいたパラメータの決め方でしかありません。
実装は各自の責任でお願いします。
また、調整するパラメータのおおよその値(桁数的な意味でのスケール)を見つけていくことになります。
これができるとマイクロマウスにおける宴会芸
ができるようになります。
ジャイロのゲインの調整をする項目について
ジャイロを調整するにあたって、調整する項目は何なのかですよね?
調整する順を説明します。
- センサー値の扱い
- 取得したセンサー値を角速度に変換する定数(1種類)
- 現在の理想の角速度(=理装置)と、センサーから取得した角速度のずれから、理想値に追従するために使用する定数(PID制御を前提3種類。本記事ではPIまでとする)
0. ジャイロセンサとは
現在の角速度の値を出力するセンサーです。 出力の形式は主に2つあります。
- アナログ式・・・CPU側でA/D変換で電圧を読み取り、角速度にする
- マイクロマウスにおいては、ADXRS610、ISZ-650、LY3500がよくつかわれている。
- デジタル式・・・IC側でセンシングしたデータをSPI/I2C通信などの通信方式で取得する
- マイクロマウスにおいては、MPU-6000(6500)、ICM-20xxx系などInvenSence社のセンサーがよくつかわれている。SPI/I2Cの両方を扱えるICが多いが、速度の関係上、通信規格上速いとされる、SPIを採用することが多い。
1. センサーの値の扱い
ジャイロセンサはアナログ・デジタル問わず、常に値がぶれています。これは他のセンサー(フォトトランジスタ)と似たものと理解してください。
デジタル式においても、不動の状態でも値は0にはならず、いくつかサンプリングした値を参考に(ゼロ点という)、参考値との差分と定数を掛けたものを角速度の現在値として、利用します。
float k ; // given float omega; // [rad/s] float gyroRef ; // ゼロ点 float gyroData ; // ゼロ点 omega = k * (gyroRef - gyroData) ;
取得には前述したとおりアナログ・デジタルに違いがあるのですが、予めぶれている値であることから、フィルタ処理をする必要があることがあります。
デジタル式では、IC側でフィルタ処理がすでに施されている場合もあります。
【参考情報】ゼロ点の取得について
値を256回取得し平均したものを、ゼロ点として用いてます。 256回である理由は、2のべき乗による除算は計算誤差を減らすのに有効だと勝手に思ってます。
2. 角速度に変換する定数
まず、前述の定数k
を求めます。
しかし、この時点では厳密な値は必要ありません。ゲインのスケールを併せることが目的です。
後述の3が終わらないと、正確なゲインは与えられません。
以下のように、角速度(omega)を積分し角度(angle)します。
#define dt 0.001 // given omega = k * (gyroRef - gyroData) ; angle += omega * dt;
取得した角度の値をUARTでリアルタイムで監視し、初期値0から90度になるまで手でロボットを回してみて、k
の値を調整します。
3. 理想値に追従するために使用する定数
【前提】
マイクロマウスにおいては、ジャイロ以外に、モーター側のフィードバック制御のゲインも調整する必要があります。
即興の調整として、PI制御でPとIが決まってるとよいです。
以下の順で決めます。
- Pゲイン
- Iゲイン
調整においては1つプログラムの実装が必要です。
具体的には、マウス界隈で言われる宴会芸
のプログラムを実装してください。
マウスに速度0、角速度0を維持する制御をすればよいです。
Pゲインの決め方
紙の上にマウスを置き、宴会芸を実行します。マウスがその場で回転するように紙を動かします。
紙を速く動かしている間だけマウスが動いていればよいです。
マウスの動きがバタバタし始めたり、音があり始めると、値が大きする証拠なので、その半分ぐらいにするとよいです(経験則)
Iゲインの決め方
Pゲインの決め方同様、宴会芸で紙を動かしていきます。 Pゲインとは違い、ゆっくり動かして、マウスが応答してくれればよいです。 徐々にIゲインを上げていき、プルプルし始めたら、ゲインが高いといえるので、その半分ぐらいにするとよいでしょう(経験則)
終わりに
Dゲインについてはスラロームなどログを取って調整することになります。P,Iについても同様にログから微調整したほうが良いです。 あまりゲインを上げ過ぎるとロバスト性が悪くなることもありますのでご注意を。
本来なら動画ベースでまとめられるとよいのですが、深夜テンションでやっつけ仕事で書いたので、調整順と調整用のアプリぐらい参考になればと思います。