SNSへはこちら

マイクロマウスの加速テーブルをコンパイル時に生成する using C++

久々にマウスの記事投稿です。俺史上初(マジ)の DC モータを使ったマイクロマウス、じゃき太浪:wq(読み: じゃきたろう, :wqは読まない)を作っています。

実際に動かすとなると、速度制御を行う都合上、何らかの速度目標値を設定する方法が必要です。具体的に僕が知っている範囲内でいうと

  1. 加速テーブルを生成し、周期割り込みごとに目標値としてそれを用いる(インデックスのインクリメント or デクリメント)
  2. 加速テーブルは使わず、周期割り込みごとに目標値をマイコンに計算させ、それを使用

というやり方が考えられます。僕はこの内、C++ を使うと実行時コストが圧倒的に少なくなる 1. を採用しています。実装が簡単な台形加速を採用しているところです。
今回はこの加速テーブルを実行時でなく、コンパイル時に生成してしまおうという方法をご紹介します。
理屈の紹介は面倒なので、申し訳ありませんが今回は実装のみの紹介です(中身がない)。

参考サイト

実装

注意
MSVC(Microsoft Visual C++のコンパイラ)ではコンパイラのバグにより下記のコードのパースが通らず、コンパイルエラーが発生してしまうようです。おおん
なので、良い子は黙って gccclang を使いましょう

こんな感じで加速テーブルジェネレータを作ってみました。テンプレートパラメータパックconstexpr を全力で利用しました。

使用法

このヘッダをどっかにインクルードして、以下のように変数宣言を行えばサクッとテーブルを生成できます。
コンパイラに掛けるときに、PC の方で加速テーブルを生成してしまえるということがポイントです。マイコンでは一切計算を行いません。加速にかかるコストはテーブルのインデックスポインタの加算・減算だけです。O(1) で済むのでとっても嬉しいですね。特に FPU のないマイコンではとてもいいと思います。

// main.cpp

const auto table = AccelarationTableGenerator::daikei::generate<1250, 500, 1>(); // 加速後の速度は500.0mm/sec

基本的に、変数宣言に constexpr を付けて -O2 以上でコンパイルをすれば、実行バイナリ生成時にはすでに PC にて計算が完了しています。

では PC にてその加速の様子を見てみましょう。

きちんと直線加速できています。

それでは最高速度 500.0mm/sec のもとで、クロソイドスラロームをしてみたらどうでしょう。クロソイドスラロームは途中まで各加速度を台形加速させるという方法なので、上のジェネレータがそのまま使えます。こんな感じでシミュレートしてみます。

このログを gnuplot に噛ませるとこんなかんじ(std::cerrfprintf が混じっているのは許してください...)。

うん、いい感じにできています。