四元数を利用した回転についての考察 2008/01/05 21:00
今回は、(まじめに、)3次元空間内での剛体の回転における四元数(クォータニオン)の使用について考察してみたいと思います。
なぜ、このようなことになったかというところから始めると、
「3次元での回転にクォータニオンを使うジンバルロックを避けられる」
などという、どういう利点があるのかよく分からない記事を読んで、それで、いろいろ検索した結果、
検索の上位に書かれているものは、結果が中心で、ちゃんと解説していないじゃないか。
と思ったからです。
「四元数が3次元内で回転を計算に使える理由は2次元で複素数が回転となるのと同様です。」について
このような説明がされているところは多少あったのですが、それで納得はできないわけです。
計算して一致することを示しているところもありましたが、それも直観的な理解ができないわけです。
ところで、自分は四元数についての知識はそれまで、
演算方法と、
絶対値が保存されることと、
積の順序は保存されないが、加減乗除できること
ぐらいだったのですが、
Wikipediaに、
「さらに純虚四元数は三次元ベクトルと同一視できる性質を備えており、二つの純虚四元数の積の虚部はベクトル積であり、その実部はスカラー積の符号を変えたものであると見ることができる。」
とあるように、これが、3次元の回転に用いることができる理由です。
やっと本題、ベクトルvを単位ベクトルuを軸として角2θ(後の記述を楽にするために2倍してあります)回転させるとします。
「四元数を用いて、
(cosθ; u sinθ)(0; v)(cosθ; -u sinθ) = (0; v')
として、回転後のベクトルv'を求めることができます。」
ということが知られています。
さて、この結論だけ見るとかなり不思議です。
uをsinθ倍してるあたりとか、挟み込んでるところとか。
回転を直感的に行うには、
v = v1 + v2と分解し、v1はuに平行、v2はuに垂直として、
v2を2θ回転させてv1と足せばよいということから考えます。
一見、単純に、vとu,vの外積を取ったものをcos2θ:sin2θで混ぜる
すなわち、(cos2θ; u sin2θ)(0; v)の虚部をとればばよい気がしますが、
それがうまくいくのはv1 = 0のときのみで、v1成分がcos2θ倍されてしまいます。
ここで、四元数が、逆演算ができるということを思い出すと、
(♪)変換前のvを「θ回転」させたものと変換後のv'を「-θ回転」させたものが一致すれば良いことになります。
単純に外積を取って混ぜた上の「回転」は欠陥がありますが、
vと同様にv' = v'1 + v'2と分けた時に、
v1 = v'1となることを考えると、問題が全く存在しません。
ただし、注意すべきは、四元数で計算するときの、実部を一致させる必要があるということで、実際、これらは、-uv sinθ, uv sinθと符号が異なりなり、四元数としては、一致するわけではなく、共役な関係です。
以上を踏まえて(♪)を式に直すと、
(cosθ; u sinθ)(0; v) = -conj((cosθ; -u sinθ)(0; v'))
(四元数ではどう書くのか分からなかったのですが、qの共役四元数をconj(q)と表記しました。)
となり、右辺は
-conj((cosθ; -u sinθ)(0; v')) = -conj((0; v')) conj((cosθ; -u sinθ))
= (0; v') (cosθ; -u sinθ)^{-1}
となるので、右から、(cosθ; -u sinθ)を掛けて、最初に言った式が出てきます。
個人的には、かなり直感的に記述しようとしたはずなのに、数学にはなれているが、四元数を知らない人向けな解説になってしまいました。
そのような場合、ここまでは見なかったことにしてください。
クォータニオンどうしの積を取り、回転を合成することができるのですが、
(これは、(q2q1)^{-1} = q1q2から示される)
「クォータニオンを用いて回転を計算する際、積を取っていくうちに、誤差により絶対値が1からずれていってしまうので定期的な正規化が必要。」について
まず、絶対値が1でない場合、何を表しているのかを考えてみると、実は等倍拡大です。
q(0; v)conj(q) = |q|^2 q(0; v)q^{-1}
であることを考えると、絶対値の二乗拡大されるだけなので、
原点を視点として透視している場合は全く問題がないことになります。
(距離に応じての効果、たとえばfogとか使ってると困るし、前の面や、後ろの面の距離が十分無視できる範囲でない場合は、どこで切れるかが違ってきたりしますが)
ので、正規化は必ずしも必要がありません。
しかし、回転させたいものは、視点だけではなくそれ以外の物体の場合もあるので正規化が必要になるわけです。
さて、「定期的な正規化」とあるように、毎回計算するには取るに足らず、また示されていた方法で用いるsqrtが重いということかもしれません。
q = q/|q|
(= q / sqrt(q0^2 + q1^2 + q2^2 + q3^2))
としているわけですが、
改良方法案
q = q (1 - 0.5(q0^2 + q1^2 + q2^2 + q3^2 - 1))
を提唱したいと思います。
誤差を直すためなら、1にもともと十分近いはずなので、
1/√(1+t) = 1 - t/2の近似がつかえそうです。
未検証ですが、sqrtを使おうとしている人がいたら、これを試してほしいです。
なんか、これも、大したことがないので見なかったことにしてほしいです。
おしまい。
なぜ、このようなことになったかというところから始めると、
「3次元での回転にクォータニオンを使うジンバルロックを避けられる」
などという、どういう利点があるのかよく分からない記事を読んで、それで、いろいろ検索した結果、
検索の上位に書かれているものは、結果が中心で、ちゃんと解説していないじゃないか。
と思ったからです。
「四元数が3次元内で回転を計算に使える理由は2次元で複素数が回転となるのと同様です。」について
このような説明がされているところは多少あったのですが、それで納得はできないわけです。
計算して一致することを示しているところもありましたが、それも直観的な理解ができないわけです。
ところで、自分は四元数についての知識はそれまで、
演算方法と、
絶対値が保存されることと、
積の順序は保存されないが、加減乗除できること
ぐらいだったのですが、
Wikipediaに、
「さらに純虚四元数は三次元ベクトルと同一視できる性質を備えており、二つの純虚四元数の積の虚部はベクトル積であり、その実部はスカラー積の符号を変えたものであると見ることができる。」
とあるように、これが、3次元の回転に用いることができる理由です。
やっと本題、ベクトルvを単位ベクトルuを軸として角2θ(後の記述を楽にするために2倍してあります)回転させるとします。
「四元数を用いて、
(cosθ; u sinθ)(0; v)(cosθ; -u sinθ) = (0; v')
として、回転後のベクトルv'を求めることができます。」
ということが知られています。
さて、この結論だけ見るとかなり不思議です。
uをsinθ倍してるあたりとか、挟み込んでるところとか。
回転を直感的に行うには、
v = v1 + v2と分解し、v1はuに平行、v2はuに垂直として、
v2を2θ回転させてv1と足せばよいということから考えます。
一見、単純に、vとu,vの外積を取ったものをcos2θ:sin2θで混ぜる
すなわち、(cos2θ; u sin2θ)(0; v)の虚部をとればばよい気がしますが、
それがうまくいくのはv1 = 0のときのみで、v1成分がcos2θ倍されてしまいます。
ここで、四元数が、逆演算ができるということを思い出すと、
(♪)変換前のvを「θ回転」させたものと変換後のv'を「-θ回転」させたものが一致すれば良いことになります。
単純に外積を取って混ぜた上の「回転」は欠陥がありますが、
vと同様にv' = v'1 + v'2と分けた時に、
v1 = v'1となることを考えると、問題が全く存在しません。
ただし、注意すべきは、四元数で計算するときの、実部を一致させる必要があるということで、実際、これらは、-uv sinθ, uv sinθと符号が異なりなり、四元数としては、一致するわけではなく、共役な関係です。
以上を踏まえて(♪)を式に直すと、
(cosθ; u sinθ)(0; v) = -conj((cosθ; -u sinθ)(0; v'))
(四元数ではどう書くのか分からなかったのですが、qの共役四元数をconj(q)と表記しました。)
となり、右辺は
-conj((cosθ; -u sinθ)(0; v')) = -conj((0; v')) conj((cosθ; -u sinθ))
= (0; v') (cosθ; -u sinθ)^{-1}
となるので、右から、(cosθ; -u sinθ)を掛けて、最初に言った式が出てきます。
個人的には、かなり直感的に記述しようとしたはずなのに、数学にはなれているが、四元数を知らない人向けな解説になってしまいました。
そのような場合、ここまでは見なかったことにしてください。
クォータニオンどうしの積を取り、回転を合成することができるのですが、
(これは、(q2q1)^{-1} = q1q2から示される)
「クォータニオンを用いて回転を計算する際、積を取っていくうちに、誤差により絶対値が1からずれていってしまうので定期的な正規化が必要。」について
まず、絶対値が1でない場合、何を表しているのかを考えてみると、実は等倍拡大です。
q(0; v)conj(q) = |q|^2 q(0; v)q^{-1}
であることを考えると、絶対値の二乗拡大されるだけなので、
原点を視点として透視している場合は全く問題がないことになります。
(距離に応じての効果、たとえばfogとか使ってると困るし、前の面や、後ろの面の距離が十分無視できる範囲でない場合は、どこで切れるかが違ってきたりしますが)
ので、正規化は必ずしも必要がありません。
しかし、回転させたいものは、視点だけではなくそれ以外の物体の場合もあるので正規化が必要になるわけです。
さて、「定期的な正規化」とあるように、毎回計算するには取るに足らず、また示されていた方法で用いるsqrtが重いということかもしれません。
q = q/|q|
(= q / sqrt(q0^2 + q1^2 + q2^2 + q3^2))
としているわけですが、
改良方法案
q = q (1 - 0.5(q0^2 + q1^2 + q2^2 + q3^2 - 1))
を提唱したいと思います。
誤差を直すためなら、1にもともと十分近いはずなので、
1/√(1+t) = 1 - t/2の近似がつかえそうです。
未検証ですが、sqrtを使おうとしている人がいたら、これを試してほしいです。
なんか、これも、大したことがないので見なかったことにしてほしいです。
おしまい。
スポンサード リンク
コメント
コメントはまだありません