このページは現在編集途上です
手っ取り早く感覚的に理解をしたい場合は、下記の参考文献が役に立ちます。
- https://www.cam.ac.uk/research/news/opinion-how-does-a-bike-stay-upright-surprisingly-its-all-in-the-mind
- https://www.youtube.com/watch?v=xS_9ml3qS7U
- https://www.bridgestone.co.jp/products/tire/mc/howto/role.html
二輪車の制御理論
本章では、大学課程での力学を踏まえた詳細な解説として、2輪車の力学モデルを提示し、状態の数式化、制御則設計、安定性解析、そしてジャイロ効果に関する誤解の解消までを詳述します。
倒立振子モデルの数学的定式化
倒立振子は、角度 \( \theta \) の小さな動作範囲を考慮した線形近似モデルで表します。
そして、ROBOBIKE(以下車体と表す)について下記の設定(モデル化)を行います。
- 前後方向の軸をロール軸(y軸)、上下方向をヨー軸(z軸)、左右方向の軸をピッチ軸(x軸)とする
- は剛体である
- すべての質量が重心位置に集中する
- 前項に起因して、車体の慣性モーメントは無い
この制御則の面白さは、教科書的な「静的な釣り合い」ではなく、「動的な角運動量のマネジメント」を直感的に行っている点にあります。以下の2段階構成で解説すると、先生や学生にも深く刺さるはずです。
なぜ倒れないのか:角速度による「勢い」の相殺
まず、制御則のC言語による実装コードを記す。
str_dev = str_target - str_out;
str_dev_diff = (str_dev - last_str_dev) * SV_FRQ;
str_diff_lps =
saved.str_diff_alph * str_diff_lps
+ (1.0f - saved.str_diff_alph) * str_dev_diff;
w_roll_cmd =
str_dev * saved.gain_str
+ str_diff_lps * saved.gain_str_diff;
w_roll_dev =
w_roll_cmd - IMU_roll();
str_out -=
w_roll_dev * saved.gain_w_roll * (1.0f / SV_FRQ);
last_str_dev = str_dev;
chklimit(&str_out, STRMAX);
str_pwm_out(str_out);
注目すべきは「角度(姿勢)」を目標にするのではなく、「角速度(動き)」を制御対象にしていることです。
- 「傾き」を直すのではなく「倒れる勢い」を殺す 通常の倒立振子は「直立(0度)」を目標にしますが、本機は「倒れようとする速度(w_roll_dev)」をゼロにすることを最優先しています。
- 逆操舵(カウンターステア)の実装 コード内の
str_out -= w_roll_dev...は、物理的に「左に倒れ始めたら、ハンドルを左に切る」という動作を指します。- 左に切ることで、タイヤの接地点が左に移動し、相対的に重心が右に残ります。
- この瞬間的な「起立モーメント」の発生により、倒れようとする勢い(ロール角速度)を逆方向の加速度で打ち消します。
- 積分項の役割:未知の釣り合い点の探索 ハンドル角を積分で更新する形式(速度型)は、路面の傾斜やメカ的な重心のズレといった「定数的な外乱」を、積分項が「必要なハンドル角」として勝手に溜め込んで相殺することを意味します。これにより、バンク角の計算を飛ばしても結果的に「倒れないハンドル角」に収束します。
好きな方向へ走らせる方法:目標進路と姿勢制御の「主従関係」
次に、外側のループを加えて「方向(str_target)」を制御する仕組みを説明します。
- 進路偏差を「姿勢の変化」にすり替える 本来、ハンドルを左に切れば左に曲がりますが、二輪車はそのままでは外側に倒れてしまいます。 本機では、
str_dev * gain_strによって、「目標進路からのズレ」を「発生させるべきロール速度(w_roll_cmd)」へと変換しています。 - 「曲がるために、あえて一度逆に倒す」プロセス
- 左に曲がりたい(目標進路が左)
str_devがプラスになり、内側ループへ「左へロールせよ(w_roll_cmd)」と命令。- 内側ループは左へ倒すため、あえて一瞬右にステアリングを切る(逆操舵)。
- 車体が左に傾き、そのバンク角によって「セルフステア」が発生し、自然に左へ旋回を開始する。
- カスケード制御の妙 この「進路を直したい」という欲求(外側ループ)が、内側の「バランスを保つ反射(内側ループ)」を上手く利用して、結果的に高度な旋回動作を実現しています。
第1段階:定常状態の維持(なぜ倒れないのか)
- メカニズム: 微小な傾きに対し、接地点を重心の下へ滑り込ませる追従制御。
- 物理: 重力による転倒モーメントが成長する前に、最小限の操舵で「起立(復元)モーメント」を発生させ、平衡状態を維持する。
第2段階:過渡状態の遷移(なぜ曲がれるのか)
- メカニズム: 大型バイクの操縦と同様、復元力に抗ってハンドルを逆方向へ切り込むプロセス。
- 物理:
gain_strによって生成された強い要求(角速度目標)が、一時的に「安定の壁」を突き崩す。これにより車体を意図的に倒し込み、旋回に必要なバンク角を「重力を使って無理やり作り出す」。
「本制御系は、静的な『バンク角の目標値』を保持しない。代わりに、ステアリングの進路偏差を『必要な姿勢変化(角速度)』へと逐次変換し、内側の高速なバランス・リフレックス(反射)に委ねることで、人間が自転車を操る際の『無意識の身体知』を再現している。」
まとめ:論文向けのロジック構成
- 内側(反射層): 角速度フィードバックによる倒立維持。逆操舵の物理的実装。
- 外側(戦略層): 進路偏差を「姿勢変化要求」へ変換。
- 統合: 目標バンク角を計算しない「速度型カスケード制御」による、演算負荷の低減とロバスト性の両立。
「計算を端折った」のではなく、「物理現象の微分的な変化をダイレクトに叩くことで、非線形な挙動を抑え込んだ」と定義する
運動方程式は以下のように記述されます:
\[
I \cdot \ddot{\theta} = mgh \cdot \theta + u
\]
ここで、\( I \) は慣性モーメント、\( m \) は質量、\( g \) は重力加速度、\( h \) は重心の高さ、\( u \) は制御入力トルクを表します。
状態空間モデルの導出
状態変数を \( x = [\theta, \dot{\theta}]^T \) と定義すると、状態空間表現は以下のようになります:
\[
\begin{bmatrix}
\dot{\theta} \\
\ddot{\theta}
\end{bmatrix}
=
\begin{bmatrix}
0 & 1 \\
\frac{mgh}{I} & 0
\end{bmatrix}
\begin{bmatrix}
\theta \\
\dot{\theta}
\end{bmatrix}
+
\begin{bmatrix}
0 \\
\frac{1}{I}
\end{bmatrix}
u
\]
制御則設計
代表的な制御則として、状態フィードバック制御が挙げられます。制御入力 \( u \) を状態の線形結合として設計します:
\[
u = -Kx = -\begin{bmatrix} K_p & K_d \end{bmatrix}
\begin{bmatrix}
\theta \\
\dot{\theta}
\end{bmatrix}
\]
ここで、\( K_p \) は比例ゲイン、\( K_d \) は微分ゲインです。これにより、倒立振子の安定化を図ります。
また、PI制御の例としては:
\[
u(t) = -K_p \cdot \theta(t) - K_i \int_0^t \theta(\tau) \, d\tau
\]
があり、定常偏差の除去に寄与します。
- 「ジャイロ効果で倒れない」は誤解であることを明言
- 倒立振子モデルの導入(高校物理レベルの記法)
- 制御則の例(状態フィードバック、PI制御など)
- ジャイロスコピックプリセッションが式に現れないことの確認
ROBOBIKEの制御実装と工夫
- 実際の制御構成(RTOS、マルチタスク、I2Cセンサ)
サーボ制御パルスは通常20msec周期で送出されるところ、本気では5ms間隔で送出して、高速応答を実現
パルスに同期して、最短時間でIMUによる角速度測定値取得から演算を経てパルス幅確定直後にサーボへ送出できるよう、GPIO入力立ち上がり割り込みからのハードウェアタイマによるタイミング調整を実施。一連の演算処理結果を最短時間でサーボ出力に反映する実装とする。 - 倒立制御の安定化のためのパラメータ調整
- ソフトウェア設計のポイント(C言語、ESP-IDF)
- 複数台走行時の制御同期や干渉対策