ジンバルロックを数学的に理解したい

# はじめに
こんにちは。しろさんと申します。
数年前にCGについて一通り勉強したのですが、未だに理解出来ていない部分が多いため、本記事では勉強を兼ねてジンバルロックについてまとめてみます。

# ジンバルロックを簡単に説明
ジンバルロックを一言で説明すると、「XYZ軸のうち2つが同一平面上に揃い、自由度が2次元になってしまうこと」です。

https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%B3%E3%83%90%E3%83%AB

ジンバルロックの説明について、Wikipediaでは

> 3軸の全てに自由な運動がある場合は、機体の回転によって3つのジンバルリングのうち2つの軸が同一平面上にそろってしまうジンバルロックという現象が発生しうる。発生すると、本来3あるはずの自由度が2になってしまう。
![Gimbal_Lock_Plane.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457210/d72dd2ff-3799-9f55-4fb3-a71f4147f806.gif)

と説明されています。
上記のgifから、飛行機が3つの軸を中心に回転しており、輪の向きが全て揃った時（gifの最後の方）、飛行機の回転は制限されている（垂直方向の軸中心の回転しか行えない状態になっている）ことが分かります。
このように、3つの回転軸のうちのいずれかが重なってしまい、回転が制限されてしまうことをジンバルロックと呼びます。

上記はジンバルロックの簡単な説明ですが、本記事では一歩踏み込んで、ジンバルロックの発生を証明してみたいと思います。

# 回転行列による座標変換
前提知識として、CGにおける3Dモデルの回転処理について説明します。
3Dモデルは、モデルを構成する頂点・辺・面によって形作られ、モデルの回転は回転行列を用いた座標変換によって行われます。
座標変換の簡単な例を説明するために、(x, y, z)=(1, 2, 3)の頂点をX軸中心に30°回転させる式を次に示します。（ここでは[同次座標](https://www.tomomi-research.com/archives/2892)を用いています）

```math
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \cos30° & -\sin30° & 0 \\
0 & \sin30° & \cos30° & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}\begin{pmatrix}
1 \\
2 \\
3 \\
1 \\
\end{pmatrix}= \begin{pmatrix}
1 \\
0.232 \\
3.598 \\
1 \\
\end{pmatrix}
```

ここで
```math
\sqrt{3}=1.732 
```
としています。

左辺は変換行列と変換前の頂点座標、右辺は変換後の頂点座標を表しています。この式の結果から、変換後の頂点座標は(x, y, z)=(1, 0.232, 3.598)になることが分かります。
上記の例ではX軸を中心とした回転を行いましたが、Y軸・Z軸を中心とする回転行列を用いて、同様の計算でそれぞれの軸を中心とした回転を行うことが出来ます。X・Y・Z軸中心の回転行列を次に紹介します。

### x軸
```math
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \cos\theta & -\sin\theta & 0 \\
0 & \sin\theta & \cos\theta & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```

### y軸
```math
\begin{pmatrix}
\cos\theta & 0 & \sin\theta & 0 \\
0 & 1 & 0 & 0 \\
-\sin\theta & 0 & \cos\theta & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```

### z軸
```math
\begin{pmatrix}
\cos\theta & -\sin\theta & 0 & 0 \\
\sin\theta & \cos\theta & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```

# オイラー角を用いた姿勢の表現
CGでは、モデルの姿勢（傾き）を表現するためにオイラー角と呼ばれる手法が用いられています。

https://ja.wikipedia.org/wiki/%E3%82%AA%E3%82%A4%E3%83%A9%E3%83%BC%E8%A7%92

X軸・Y軸・Z軸を中心とした３つの角度を定め、任意の順序で回転させます。
（回転の順序は使用するソフトウェアやライブラリによって様々なようです）
それぞれの軸を中心とした回転角の組み合わせによって、自由に傾きを表現することが出来ます。

# オイラー角によるジンバルロックの発生
例えばx-y-z系のオイラー角を用いて回転を行う場合、X軸→Y軸→Z軸の順番に回転を行います。行列にすると次のようになります。
αはZ軸、βはY軸、γはX軸中心の回転角を表しています。

```math
R=\begin{pmatrix}
\cos\alpha & -\sin\alpha & 0 & 0 \\
\sin\alpha & \cos\alpha & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}\begin{pmatrix}
\cos\beta & 0 & \sin\beta & 0 \\
0 & 1 & 0 & 0 \\
-\sin\beta & 0 & \cos\beta & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \cos\gamma & -\sin\gamma & 0 \\
0 & \sin\gamma & \cos\gamma & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```

ここで、Y軸中心の回転角が90°である場合、式は次のようになります。

```math
R=\begin{pmatrix}
\cos\alpha & -\sin\alpha & 0 & 0 \\
\sin\alpha & \cos\alpha & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}\begin{pmatrix}
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
-1 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \cos\gamma & -\sin\gamma & 0 \\
0 & \sin\gamma & \cos\gamma & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```
```math
=\begin{pmatrix}
0 & -\sin\alpha\cos\gamma+\sin\gamma\cos\alpha & \sin\alpha\sin\gamma+\cos\alpha\cos\gamma & 0 \\
0 & \sin\alpha\sin\gamma+\cos\alpha\cos\gamma & \sin\alpha\cos\gamma-\sin\gamma\cos\alpha & 0 \\
-1 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```

X軸・Z軸を中心とした回転を考えるために、α・γそれぞれについて偏微分をします。

- αについて
```math
\frac{\partial R}{\partial \alpha}=-\begin{pmatrix}
0 & \sin\alpha\sin\gamma+\cos\alpha\cos\gamma & \sin\alpha\cos\gamma-\cos\alpha\sin\gamma & 0 \\
0 & \sin\alpha\cos\gamma-\cos\alpha\sin\gamma & -(\sin\alpha\sin\gamma+\cos\alpha\cos\gamma) & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```
- γについて
```math
\frac{\partial R}{\partial \gamma}=\begin{pmatrix}
0 & \sin\alpha\sin\gamma+\cos\alpha\cos\gamma & \sin\alpha\cos\gamma-\cos\alpha\sin\gamma & 0 \\
0 & \sin\alpha\cos\gamma-\cos\alpha\sin\gamma & -(\sin\alpha\sin\gamma+\cos\alpha\cos\gamma) & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}
```
よって
```math
\frac{\partial R}{\partial \alpha}=-\frac{\partial R}{\partial \gamma}
```
となります。
この式から、X軸とZ軸中心の回転は同一直線上の軸を中心とした回転となり、ジンバルロックが発生する（回転の自由度が下がる）ことが分かります。
今回はx-y-z系でY軸中心に90°回転させたという体で計算を行いましたが、別の順序のオイラー角でも同様にジンバルロックが発生する可能性があります。


# まとめ
ジンバルロックは、オイラー角による回転処理において、2つの軸が重なることで回転の自由度が下がる現象であることが分かりました。

とまとめたいのですが個人的に上手く理解できていない部分があるため、引き続き学習を継続していこうと思います。
本当はジンバルロック問題の解決に関わるクォータニオンの概念についても書きたかったのですが、勉強に時間がかかりそうなため、一旦ここまでにします。
クォータニオンについては、また後日まとめたいと思います。
最後まで読んでいただきありがとうございました。

# 参考資料
- [Wikipedia - ジンバル](https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%B3%E3%83%90%E3%83%AB)
- [Wikipedia - オイラー角](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%82%A4%E3%83%A9%E3%83%BC%E8%A7%92)
- [貴方はオイラー角におけるジンバルロックを数学的に説明できますか？](https://qiita.com/Arihi/items/4b306feb3d9e6cd93204)
- [TOMOMI RESEARCH - 同次座標の紹介](https://www.tomomi-research.com/archives/2892)
- [オイラー角とは？定義と性質、回転行列・角速度ベクトルとの関係](https://www.sky-engin.jp/blog/eulerian-angles/)
- [ジンバルロックを完全攻略する](https://ryowaks.com/gimbal-lock/)
- [オイラー角に潜む５つの罠](https://qiita.com/take4eng/items/0f5a9ff47fd345e5fc33)