続き。
円が出来たので、折角なので回転のお話。
基底変換
空間を回したいと思う。回すって何だろうか。
を眺めていると「回っている」気がするけれど、今は点が回っているだけで空間自体を回しているわけではない。 では空間を回すためにはどうすればよいか。ここでは線形空間としての性質を使いたいので、 について考えることにする。
これは の上で「2点」が回っている図である。元々の点 に加え、その「軸」と常に直交する点 を表示したものである。
なので常に直交。ちなみに のとき である。性質が良い。
線形空間の構造は次元で決定し、その次元は基底で決定していた。今 の基底として を持っている。 とすると、これを使って で を表現できる。同じ空間を違う視点で見ることができる。
今気持ちの上では2種類の がある。1つは今回転の対象としている空間で、ベクトル空間という気持ちで記述している。 もう1つは「座標」を記すための空間で、基底を使ってオリジナルの空間の表現を構成するための空間である。
今回の基底は実はとても都合が良い。私達は が線形空間以上に内積を持っていることを知っているが、その観点からすると「基底の各点の長さが1」で「基底の異なる2点が常に直交」している。 「長さが1」というのはこの基底を使うことで大きさが変わらないこと、「異なる2点が常に直交」というのは空間を歪ませたりしないことを示す。こういう基底のことを 正規直交基底 (Orthonormal basis) と呼ぶ。
正規 (normal) は長さが1のこと、直交 (ortho) は全点直交してること。これでほぼ回転なんだけど、反転が出来てしまうのでちょっとだけ修正をする必要がある。逆に言えば反転を無視すれば回転である。
さて、ちょっと具体的な計算をしてみる。表現された空間の点を で、オリジナルの空間の点を で記す。気持ちの上の区別である。
適当な点 に対して、 の標準基底 を使って表現すると である。 ここで基底を回す: になったとしよう。ではオリジナルの空間に点を戻す。 を計算すればいいので、 になった。これは「点の回転」としてよく出てくる式の形である。
さて、この考え方は何次元の空間にでも適用できる。適当に正規直交基底を取ってきて、標準基底で表現された点に対してオリジナルの点を計算するとその基底で回る。特に空間の平面成分は先程の方法で回転を定義できるので、残りを標準基底で埋めれば「その平面で回す」回転ができる。3次元でそれをやるとこうなる:
$$R_X(x) = \begin{Bmatrix}\langle 1,&0,&0\rangle,\\ \langle 0,&\cos x ,&\sin x\rangle,\\ \langle 0,&-\sin x,&\cos x\rangle\end{Bmatrix}$$ $$R_Y(x) = \begin{Bmatrix}\langle \cos x,&0,&\sin x\rangle,\\ \langle 0,&1,&0\rangle,\\ \langle -\sin x,&0,&\cos x\rangle\end{Bmatrix}$$ $$R_Z(x) = \begin{Bmatrix}\langle \cos x,&\sin x,&0\rangle,\\ \langle -\sin x ,&\cos x,&0\rangle,\\ \langle 0,&0,&1\rangle\end{Bmatrix}$$
固定する軸に関係する成分以外を先程の2次元の回転で埋め、残りは標準基底。これが「その軸で回転する」基底変換である。
回転方向はまぁどっちでもいいとおもう。思う方向と違ったらもう1つを採用すればいい。
1次元では2次元の回転が入らないので何も回らない。実際回そうとしたら空間から出てしまうだろう。 4次元だと2次元の回転が2個入るので同時に2平面が回転する。この辺の構造もまた深い話があるらしい。
回転の表現
今までは回転を基底として表現してきた。しかし、自由度 (Degree of freedom) という意味では無駄な情報が多い。具体的に2次元と3次元に関して、もうちょっと軽い回転の表現を探ってみる。
2次元
まず2次元空間 で考えよう。2次元では回転できるのは1方向だけである。これは直感的にもわかるし、厳密に考えてもわかる。
の正規直交基底は、全て か の形で表せることが知られている。 後者は回転に反転がくっついたものなので除外すると、 分だけの回転があることになる。パラメータが1つなので自由度が1。
なら、1つの値で以って回転を表現すれば良い。実際今回は という値で回転を表現しているわけで、 が回転であると思い込めば良い。それを本当の回転にする方法を私達は知っている。 重要なのは の棲んでいる空間は というよりも になっていることである。一周回す回転は回さない回転と等しい。
「回転」には時間の情報がないから、一瞬で変換してしまう。もしも一周以上の回転という気持ちや回す経過を表現したいなら、正確には接空間 (Tangent space) や測地線 (Geodesic) という概念が必要になる。 とはいえ2次元の回転の成す空間における任意の点の接空間は結局 と同等なので、結論としては実数をそのまま使えばよい、ということにはなる。
前に記した通り は と同相である。だから を使って回転を表現することもできる。 実際 の点 があるとき なので長さは1、そして直交する点を で得られるので で回転を表す正規直交基底が作れる。
で回転を表すのは「回転角度による表現」、 で回転を表すのは「複素数による回転の表現」に似ている。どちらも便利な点はあって、前者は等速での回転を作るのが簡単、後者は実用上で特異点が発生しないことがある。悲しいことに であるというのは気持ち上なので、浮動小数で素直に扱うと と の間で狂いが発生してしまう。だけど後者も後者で 上に点があるというのは気持ち上なので、実用上では が ではなくなることがよくある。だからそれを逐次補正していかないと爆発したりする。残念ながら万能な方法はない。
前半は例えば3Dモデルで頂点に (何らかの理由で) 角度情報を乗せるときにクリティカルで、fragment shaderに頂点情報が補間されて渡された時、 の境界をまたがったポリゴンは逆向きの一周を拾ってしまう。だから2次元分使って として渡さないといけない。 後半は連続して複数の回転を実行するときにクリティカルで、大きさが1よりも大きい回転を何度も掛けるとそのスケール拡大が何度も適用され、本当に爆発したような挙動になる。 回 倍したら 倍である。「この値は 上の値である」ことを知っている人が、常に長さが1になるように 正規化 (Normalize) しつづけなくてはならない。
3次元
3次元の回転の自由度は3である。これは今までの議論からは出てこない。ちょっと考えてみる。
3次元物体を回すとき、動かない点があるはずである。どんな回転にも必ず軸が存在する。どんな回転も「ある平面を回す」ことに他ならないのである。その平面と直交する方向が軸となる。 逆に言えば軸によって回転を構成できるので、軸の自由度が問題である。「大きさが1である3次元空間内の点」が軸となるわけであるが、これは球面 (Sphere) 上の点に他ならない。
球面の次元は、全体空間 に大きさ に制約を掛けているので である。だから球面を と表記したりするわけであるが、つまり軸の自由度は2である。そこに回転量の自由度1があるので全体で3となる。
さて、この考え方は具体的に回転の表現を構成するときにも適用できる。 で1つの回転を表現できるはずである。ここから基底を構成するのがRodriguesの回転公式だったりする。具体的な中身は毎度参照すればいいので、「これで構成できること」を知ったことが何よりも重要である。
また、実は「X,Y,Z軸で順番にα,β,γ分回す回転」で任意の3次元回転が表現できることが知られている。この表現方法は Euler角 (Euler angles) と呼ばれ、Unityのinspectorに表示されているのはコレである。自由度の数は確かに一致しており、これは で1つの回転を表現するもの、ということになる。しかしこの形式では各軸が絡み合っていることがわからない。独立ではないものを独立とみなしているということは、空間の形が本来とは違ってしまっているということである。
このような歪みは と を考えてみるとわかりやすいかもしれない。片方は球面で、もう片方はトーラス (Torus) と呼ばれるドーナツ型の表面である。自由度 (次元) が同じでも空間構造は全然違う。
実は という空間も、本来の「3次元回転の成す空間」とは違うものである。「回さない回転」は直感的には唯一であってほしいが、この形式だと任意の軸 に対して は全て無回転を表現できてしまう。これもまた「軸と回転量が絡み合っている」ことがわかってないことに起因する。そうすると絡み合いを含めた回転の表現を考えたくなる。
そうすると出てくるのが、四元数 (Quaternion) である。
以降単位四元数について考える。
まず「回転量」の正しい表現を模索しよう。回しすぎると回ってないことになるわけで、最も「回している」と考えられるのは半回転 である。すると「半回転で1」「無回転で0」になってほしい。実は全ての回転はある軸ベースでの「無回転以上半回転以下」にできるので、これで十分である。
軸周りに 回転するのは、 軸周りに 回転するのと同じである。実際にやってみるとわかる。だから逆回転は軸をひっくり返すことで表現できる。半回転以上回すなら逆回転とみなせば半回転以下である。 尚ここで空間の連続性が失われていると感じるのは正しい (後述)。
天下り的だが、半回転で1、無回転で0となる値として、 がある。 のことを考えてみると同時に「回転しなさ」を表現する を取れることがわかる。この値を に絡ませてみる。 すると という での表現が完成する。これが四元数である。
なんで のことを考えたのかというと、 にするためである。つまり回転は3次元球面 の点になった。
3次元球面は4次元空間内超球の表面のことだが、1次元球面 (円) を2次元球面 (球面) にする方法として「円柱にして端を潰す」というのがあるように、「球面を『球柱』にして端を潰す」ことである程度想像ができる。 柱を伸ばす方向は内側と外側。内側は原点に収縮させて「中身のある球」にすればいいが、外側は1点に収縮させたりできないのでそこが想像の限界である。
この扱いによって無回転は と表現されることになり、本来あるべきではなかった軸の自由度は正しく消えた。今までの例よりは最も正しく3次元の回転を表現できているわけである。
とは言えちょっと考えてみると、回転量は今まで で表現していたのにも関わらず を使ってしまうのは怪しい。というかヤバい。 なので連続性が完全に失われているのである。 だけどこの現象は想定済みである。先程言った通り 軸周りの 回転は 軸周り 回転に等しい。実はこの性質を四元数での表現でも受け継いでいて、四元数 の表す回転は の表す回転に等しい。
元々は「回転を表す空間」としての であったが、そこから少しだけ意味を抜いて にしてしまった。回転の意味を正しく取り戻すには、この空間を という対称性で割る必要が出てくる。元々回転を表している、という気持ちの上では連続性は失われてない、と考えることができる。
四元数はとても綺麗且つ便利な代物なので、回転を気軽に扱うにはちょうどいいのである。
まとめ
- 正規直交基底
- 9つの実数、正規直交条件と反転しないという条件が入る
- 軸と回転量
- 3+1=4つの実数、空間に多少の無駄な自由度
- Euler角
- 3つの実数、(回転を表すにしては) 空間がかなり歪んでいる
- 単位四元数
- 4つの実数、最も回転の成す空間に近い
この辺はリー群 (Lie groups) とかの話だと思う。これに至るまでには線形代数と群と環と多様体と微分幾何がわかってる必要がある気がする。私も詳しいことはわかんない。
回転の合成
回転した後さらに回転したい、ということはたくさんある。そうすると「回転に続いた回転」を回転として表現したい。
これは自明ではない。基底変換を2度行うことが1つの基底で表現できるかはわからない。演算を繰り返しても「演算であり続ける」ことを閉じている (closed) と呼ぶ。事実として、回転は合成に関して閉じている。
基底変換で回転するのを2回やることは当然できる。だけど、「基底変換によって基底自体を変換しておく」ことができるようにも見えはしないだろうか?
を元に戻して 、さらに戻して である。しかし から への基底自体をそれぞれ戻してあげると、最初から から へ持っていく変換が得られる。基底による変換は合成できる。基底の合成方法は次のように表現できる。
$$\begin{matrix}[a,&c] \\ [b,&d]\end{matrix} \times \begin{matrix}\langle e, &g\rangle \\ \langle f,&h\rangle\end{matrix} = \begin{matrix}[ae+bg,& ce+dg] \\ [af+bh,& cf+dh] \end{matrix}$$
縦と横を入れ替え、点や括弧の表記を変えると次である。
$$\begin{pmatrix}a&b\\c&d\end{pmatrix} \times \begin{pmatrix}e&f\\g&h\end{pmatrix} = \begin{pmatrix}ae+bg&af+bh\\ce+dg&cf+dh\end{pmatrix}$$
これが行列 (matrix) であり、そして行列積である。基底による変換を合成したいから行列を使う。なんでか知らないけどみんな点を縦向きに書くからこんな演算になってる。
なんであれ、これを使えば基底で表現された2つの回転を合成することができることがわかった。だから正規直交基底で回転を表現するなら合成はできる。
点自体を行列として表現することで「変換と変換の合成」と「変換の点への適用」を同一視できるようになる。みんな「掛け算」である。
さて、合成についてもうちょっと考えたいところだが、「軸と回転量」および「Euler角」における合成は結構めんどくさい。そのために作られていないから。 それに対して四元数はよく出来ていて、合成が非常に計算しやすい。これもまた掛け算である。 四元数の空間は の一部になっているわけだが、それを使って線形空間とみなす。そして、4つの軸と4つの軸の組に対して (綺麗な) 演算表が与えられ、あとは線形性を使って新たな四元数を得ることができる。
するとなんとこれは「回転の合成」になってくれる。計算しなくてはならない成分の数は基底による表現よりも小さく、正規化するのも容易で扱いやすい。便利なわけである。
そういえば2次元での回転 () の合成は自明である。足せば良い。
2つの回転を合成できることはわかったが、一応言及しておくと合成の順番は合成結果を変える。これは直感的に当たり前で、「平行移動して回転」と「回転して平行移動」は違うという話である。 回転も同じく、「A回転した後B回転」と「B回転した後A回転」は結果が変わる。合成の順番によって結果が変わることを 非可換 (Non-commutative) と呼ぶ。
2次元の回転は可換である。実際この回転は実数の足し算で表現でき、足し算は可換であるから回転も可換であるはずである。3次元の回転は、行列にせよ四元数にせよちょこちょこと演算が入っていて可換にはならない。
あともうちょっとお話をすると、ある回転に対して「それを打ち消す回転」が常に存在する。基底による表現、つまり行列表現の場合は逆行列 (inverse matrix) と呼ばれるものになるが、回転を表す行列の場合は転置 (transpose) と一致し、計算がめちゃくちゃ簡単になることが知られている。 2次元の回転 の逆も簡単で符号反転 ()で良い。3次元でも軸と回転量による表現は自明。四元数の場合には共軛 (Conjugate) と呼ばれる計算が対応し、これも回転行列の逆行列と同じく計算が簡単である。Euler角はつらい。
閉じた演算があり、「逆」が存在する空間を 群 (Group) と言う。演算が可換であるとき アーベル群 (Abelian group) と呼ぶ。空間構造の骨組みを扱う上で便利なやつである。