🥋 チート900を数式で動かす
STAGE 4 ― 向きをなめらかにつなぐ ―
クリア 0 / 9
STAGE 4

向きをなめらかにつなぐ

四元数
🎯 ミッション
回転行列の数をそのまま混ぜると体がつぶれてしまう理由を知り、回転を4つの数で表す四元数を身につけよう。q と −q が同じ向きを表すことと、2つの向きを球面に沿ってつなぐ slerp を説明できれば合格。
未達成
ねこ博士
アニメーションを作っていると、「2つの向きの途中の向き」がほしくなる場面がよくある。たとえば踏み切りの瞬間、床を離れる足の向きを、前のコマの向きから少し後のコマの向きへ、なめらかにつなぎたい。空中で体の向きが細かく揺れているのを、前後のコマの向きの平均でならしたい。向きは回転行列で表せるのだから、2つの行列の数を、ふつうの数のように平均すればいい――と思うだろう?
うさ美
はい。行列は数の箱なので、同じ場所どうしを足して2で割れば、真ん中の向きになりそうです。
ねこ博士
試してみよう。体を上向きの軸のまわりに 0° 回した向きと、180° 回した向きの「平均」を作る。0° の回転行列の左の列(x の矢印の行き先)は (1, 0, 0)、180° の回転行列の左の列は (−1, 0, 0) だ。平均すると?
うさ美
(1+(−1))÷2 = 0 ……。x の矢印が (0, 0, 0)、長さ 0 になってしまいました。真ん中は 90° 回った向きのはずなのに、矢印が消えてしまうなんて。
ねこ博士
180° ほど極端でなくても同じことが起きる。行列の数をそのまま混ぜると、3本の矢印が縮んだり、直角でなくなったりして、もう回転ではなくなる。体に当てはめると、体がつぶれたり、ゆがんだりする。下の図で「行列の数を混ぜる」を選んで確かめてごらん。
灰色が向き A、薄い紫が向き B(A をななめの軸のまわりに回したもの)。濃い色が「途中の割合 t」の向き。行列の数を混ぜると、矢印が縮んで体がつぶれる(右下の数値:x の矢印の長さと、x・y の矢印の内積)。slerp なら、長さ1・直角のまま回っていく。図はドラッグで回せる
うさ美
行列を混ぜると、体が薄っぺらくなりました。slerp というほうは、形を保ったまま回っていきます。これは何ですか?
ねこ博士
それを説明するために、まず平面の回転を思い出そう。『本当はおもしろい複素数の世界』で学んだように、平面の回転は、長さ1の複素数 cos φ + i sin φ を掛けることだった。複素数は2つの数(実部と虚部)で1つの回転を表す。1843年、アイルランドの数学者ハミルトンは、これを3次元の回転に広げる数を考えた。i のほかに j と k という2つの「虚数」を加えて、w + x i + y j + z k という4つの数の組を作り、i² = j² = k² = ijk = −1 という掛け算の決まりを置いた。これを四元数(しげんすう)という。
うさ美
4つの数で回転を表すんですか? 回転行列は 9 個の数でした。
ねこ博士
そう、ずっと少ない。軸の向きが長さ1の矢印 k = (kx, ky, kz)、回す角度が θ の回転は、次の四元数で表す。最初の数が w、残りの3つが x、y、z だ。4つの数の2乗の和を計算すると1になる。回転を表す四元数は、いつも「長さ」が1になる。
回転の四元数:q = ( cos(θ/2), kx sin(θ/2), ky sin(θ/2), kz sin(θ/2) ) 2乗の和:cos²(θ/2) + sin²(θ/2) × (kx² + ky² + kz²) = cos²(θ/2) + sin²(θ/2) = 1
うさ美
θ ではなくて θ/2、半分の角度が出てくるのはなぜですか?
ねこ博士
四元数で点(ベクトル v)を回すときは、v を四元数 (0, vx, vy, vz) とみなして、q v q* と、左から q、右から q* を掛ける(q* は、x・y・z の符号を反対にした四元数)。ちょうど両側から挟むので、それぞれが角度の半分ずつ受け持って、合わせて θ 回る。計算すると、ステージ3のロドリゲスの公式と同じ答えになる。下の図でも確かめられるよ。
軸はななめ上向きに固定。上段は四元数 q の4つの数(w, x, y, z)。下段は、右つま先を q v q* で回した位置と、ステージ3のロドリゲスの公式で回した位置。θ を 360° を越えて動かすと、体は1周して元の向きに戻るのに、q の4つの数はすべて符号が反対(−q)になる
うさ美
θ が 360° のとき、体は元の向きに戻っているのに、q は (1, 0, 0, 0) ではなく (−1, 0, 0, 0) になりました。720° でやっと (1, 0, 0, 0) に戻ります。
ねこ博士
半分の角度を使うから、角度が 360° 増えると cos と sin の中身は 180° 増えて、4つの数の符号がそろって反転する。つまりq と −q は、まったく同じ向きを表す。1つの向きに、2つの名前があるんだ。
うさ美
同じ向きに2つの名前があると、何か困るんですか?
ねこ博士
平均を作るときに困る。向き A を q、向き B を q' とし、2つがほとんど同じ向きだとしよう。もし B のほうを −q' という名前で持っていたら、q と −q' はほとんど正反対の4つの数だから、足して2で割ると 0 に近くなってしまう。だから平均や途中を作る前に、2つの四元数の4次元の内積(4つの数を掛けて足したもの)を調べ、マイナスなら片方の符号を反転してから混ぜる。このアニメーションで空中の体の向きの揺れをならしたときも、コマごとの四元数を、前のコマとの内積がプラスになるようにそろえてから平均している。
うさ美
符号をそろえたら、四元数の4つの数はそのまま平均してもいいんですか? 行列のときは、混ぜると壊れてしまいましたけど。
ねこ博士
いいところに気づいたね。長さ1の四元数は、すべて「4次元の空間の、半径1の球面」の上にある。4つの数をそのまま平均すると、点は球面の内側にもぐって長さが1より短くなるが、長さで割って1に戻せば、ちゃんと回転を表す。行列とちがって、四元数は「縮んだら長さを1に戻す」だけで直せるんだ。さらに丁寧なのが slerp(スラープ)で、2つの点を結ぶ球面上のいちばん短い道(大円の弧)に沿って、一定の速さで進む。q₀ と q₁ の4次元の内積を cos Ω とすると、割合 t の途中は次の式で表せる。t=0 なら q₀、t=1 なら q₁ になり、その間は等しい角度ずつ回っていく。
2つの向きの間の角:cos Ω = q₀・q₁ slerp:q(t) = ( sin((1−t)Ω) q₀ + sin(tΩ) q₁ ) ÷ sin Ω
4次元の球面を、q₀ と q₁ を通る平面で切った断面(半径1の円)。紫の点が slerp の途中(円周の上を一定の速さで進む)、灰色の点が4つの数をそのまま混ぜた途中(円の内側にもぐる)。「−q₁ という名前で持つ」と、同じ向きなのに円の反対側の点になり、そのまま混ぜると遠回り(360° から差を引いた角度)になってしまう
うさ美
符号をそろえないと遠回りになるんですね。四元数の内積がマイナスのときに符号を反転するのは、近いほうの名前を選ぶため、ということですか?
ねこ博士
その通り。まとめると、向きを扱うときは計算や表示には回転行列、混ぜたりならしたりするには四元数、と使い分けるといい。行列と四元数は、いつでもお互いに変換できる。このアニメーションでは、踏み切りで床を離れる足の向きを slerp でつなぎ、空中の体の向きの揺れを、符号をそろえた四元数の平均でならしている。
💡 角度3つ(オイラー角)ではだめなの?向きを「左右に何度・上下に何度・ひねり何度」の3つの角度で表す方法(オイラー角)もある。数が3つで分かりやすいが、上下の角度が ±90° に近づくと、左右の角度とひねりの角度が同じ回転を表してしまい、角度が1つに決まらなくなる(ジンバルロックと呼ばれる)。そこでは、角度をなめらかに変えても向きが急に飛ぶ。空中で回り続けるチート900のような動きでは、四元数のほうが安全だ。
【このステージの成果】 回転行列の数をそのまま混ぜると、矢印が縮んだり直角でなくなったりして、回転でなくなる(体がつぶれる) 四元数:軸 k・角度 θ の回転は q = (cos(θ/2), k sin(θ/2))。4つの数の2乗の和はいつも 1。点は q v q* で回す(ロドリゲスの公式と同じ結果) q と −q は同じ向き(角度を 360° 増やすと符号がそろって反転する)。混ぜる前に4次元の内積を見て、マイナスなら片方を反転する slerp:q(t) = (sin((1−t)Ω) q₀ + sin(tΩ) q₁) ÷ sin Ω(cos Ω = q₀・q₁)。球面の上を一定の速さで進む。そのまま混ぜて長さを1に戻すだけでも、角度が小さければほぼ同じ 計算や表示には回転行列、混ぜる・ならすには四元数

確認クイズ

Q1. 長さ1の軸 k のまわりに角度 θ 回す回転を表す四元数は?

Q2. 四元数 q と −q(4つの数の符号をすべて反対にしたもの)は、どんな向きを表す?

Q3. 2つの向きの「途中」を作るとき、回転行列の数をそのまま混ぜないのはなぜ?

← トップへ