四元数のおべんきょログ

今やってるやつの向きの指定に四元数を使おうと思う。外部から使うことはできるものの、いまだに内部がどうなってるのかは詳しくないので、あらためて勉強しなおし。そのログ。

四元数の目的

Quaternionとも呼ばれ、「向き」を決定するのに使う。もう少し厳密に言えば「姿勢」を一意に決定するために使う。「向き」と「姿勢」の違いはあとで出てくる。はず。

四元数の構造

「Quaternion」でググる。見つけたやつをもとにスタディ開始。


参考ここらへん。


まず、「Quaternion」とは「複素数」の拡張であるらしい。
「実数」だけなら、それは数直線で表現できる。直線。つまり一次元。
複素数」は「実数」+「虚数」で、軸が一本増える。平面。つまり二次元。
であるならば、三次元を表現するためにはもう一つ軸が増えればいい。つまり、「実数+虚数+何か」で表現すればいい。で、「Quaternion」の構造はどうなっているかというと、

Q = t + xi + yj + zk

多いー!一個多いー!kって何だkって。


落ち着け。素数以外の数を数えて落ち着くんだ。「1,4,6,8,9,10...」。「素数以外の数」はあまり注目されない孤独な数字。わたしに勇気を与えてくれる。


つまりこれが「向き」と「姿勢」の違いなわけだな。「向き」とは方向。ベクトル。いわば「どっちに向かって指差すか」を表すもの。「姿勢」は「向き」に加えて「本体の傾き」も決定する。「どっちを指差すか」に「腕をどれくらいコークスクリューさせているか」を加えたもの。つまり、同じ向きを指していても「どれくらい回転をかけているか」は決まらないので、それを決めてしまおうということだ。きっとそうだ。そうに違いない。


で、確認してみると、(x, y, z)が3次元ベクトル(腕の向き)を表し、tが回転量(腕の回転)を表しているらしい。これだけだとだいぶ誤解を招くな(tは2PIとか書くの?みたいな)。厳密に書けば「(x, y, z)を軸にθだけ回転する」は「cos(θ/2) + x*sin(θ/2)*i + y*sin(θ/2)*j + z*sin(θ/2)*k」と表現される。


さらに、「指差し」を例えに使ってしまうと、「Quaternionってのは"どっちを向いてるか"+"回転量"なんだぁ」みたいに誤解されてしまうな。実際には「最初の姿勢をもとに、"この軸で""これだけ回転したもの"」を表すのがQuaternionだ。と思う(→これもちょっと違うっぽいな。基本はそうなんだけど)。「指差し」を例えに使ったのは「3次元だけじゃ足りない」というのを表現するためのものなのだ。(でも、「大きさ」というものを考慮しなければ3次元だけでもいけんじゃね?とか考えつつ、ややこしくなるので置いておく)

四元数の使い方

この先は知ってるので、ここらへんで終了。使い方はさっきのリンク先とかにあるし。
ざっとメモると、

  • 逆Quaternionというのがある。(かけると「1」になるアレ)
  • 実際の計算では、もとのQuaternionと逆Quaternionではさんで計算する。

あたり。

その他

「球面線型補間」とかは「柱が倒れる」とかに使えるんだよねぇ。これを使わずに単純な方法でやると「柱の根元が変な風に移動する」という現象が起こるのだ。もっと早目に知りたかったな。


Quaternion×Quaternionで出てくるのも「軸と回転量」かなぁと思ったけど、そうじゃないよなぁ。頭の中で「90度回転」とか組み合わせてみたやつは、一つの「軸と回転量」では表現できない。だからたぶん「軸と回転量の掛け合わせた結果」みたいなものを表現してるんだろう。ちゃんと計算してみるべきか。

ちゃんと計算してみる

概念だけの状態と計算で身に付けることの差を実感したく、実際に計算する所存なり。


例に出した「指差し」をもとに座標の計算テスト。まずは、そのために方向とかを決定しておく。
「前後」を「Z軸」にして、自分にとっての「前」をプラス方向にする。「上下」を「Y軸」にして、「上」をプラスにする。で、「左右」が「X軸」になるのだが、どっちをプラスにすべきか。いわゆる右手座標系と左手座標系の問題。ライブラリ作る場合は、両方対応して定数使ってプリコンパイルの段階で分岐させればいいんだろうけど、ここではODEの座標系に合わせることにする。で、確認したところ、「え〜!Zが上下なの〜!」ともう一度驚く。なんで忘れてんだ俺。まぁそれはともかく「右手座標系」なので「左」がX軸のプラスになる。


で、その座標系で「犯人はお前だ!」という感じの腕の位置を初期座標にしてみる。「肘」を原点。「人差し指の先」が前方向にあるので(0,0,10)ぐらいで。さらに親指は左を向いているので(2,0,8)あたり。
これを、まず時計回りに90度回転させて、「手で銃をつくって発射する前の態勢」にする。この段階で、人差し指の座標は変わらないけど親指の座標は(0,2,8)になってるはず。
さらに肘を中心に左に回転させて「死刑!」のポーズにする(古いよ。俺の世代でもビミョーだよ。でもミサミサがいるか)。そうすると、人差し指の座標は(10,0,0)で、親指の座標は(8,2,0)になるはず。
これを、実際に計算して確かめてみる。

「犯人はお前だ!」→「手で銃」

腕を軸に時計回りに90度回転する。つまり、Z軸を中心に90度だか−90度だか回転するわけだ。で、90度なのか−90度なのか。「腕を軸に時計回り」というのをXY平面での回転で考えると、「いわゆるXY平面」=「Xのプラスが右、Yのプラスが上」における「反時計回り」=「いわゆる普通の回転」なので、たぶん「プラス90度回転」なんだろうなぁと見当つけて、回転開始。
親指の座標が(2,0,8)から(0,2,8)になるはず。


まず、Quaternionは「Z軸:(0,0,1)に90度回転」から、定義より「cos(90/2) + 0*sin(90/2)*i + 0*sin(90/2)*j + 1*sin(90/2)*k」→「\frac{1}{\sqrt{2}} + \frac{1}{\sqrt{2}}*k
座標(2,0,8)は「2*i + 0*j + 8*k」→「2*i + 8*k」と表現される。これを回転させるには、「四元数×座標×共役四元数」とするので、
(\frac{1}{\sqrt{2}} + \frac{1}{\sqrt{2}}*k) * (2*i + 8*k) * (\frac{1}{\sqrt{2}} - \frac{1}{\sqrt{2}}*k)
= (\sqrt{2}*i + \sqrt{2}*k*i + 4\sqrt{2}*k + 4\sqrt{2}*k*k) * (\frac{1}{\sqrt{2}} - \frac{1}{\sqrt{2}}*k)
(i + k*i + 4*k + 4*k*k) - (i*k + k*i*k + 4*k*k + 4*k*k*k)
ここで、「i*i = -1, j*j = -1, k*k = -1」「i*j = k, j*k = i, k*i = j」「j*i = -k, k*j = -i, i*k = -j」を使うと、
(i + j + 4*k - 4) - (-j + i - 4 - 4*k)
2*j + 8*k
となって、「0*i + 2*j + 8*k」→座標(0,2,8)になった。目標通り。
計算途中で、「i, j, kが軸に対応するなら、右手座標系と左手座標系で計算方法違ったりする?」とか思ったりするが、ひとまずおいておこう。覚えてたら通勤中にでも確認するさ。

「手で銃」→「死刑!」

上の計算結果にさらに「Y軸方向に時計回りに90度」?さっきは当たり前のように「時計回り」とか使ったけど、ちゃんと「プラスの向き」を意識しないといかんね。指差しの時と同じく「プラス=奥方向」とした場合に「Y軸方向に時計回りに90度」=「Y軸プラス90度回転」だ。
で、普通に計算してももう面白くないので、「2つのQuaternionをかけたもの」を先に計算してから、「初期座標」にかけて最終地点を求めてみる。こっちの方が実際のコーディングの確認にもなるし。


じゃ、まずは「2つのQuaternionをかけたもの」を計算。
2つのQuaternionはそれぞれ下の通り。
「Z軸:(0,0,1)に90度回転」は「\frac{1}{\sqrt{2}} + \frac{1}{\sqrt{2}}*k
「Y軸:(0,1,0)に90度回転」は「\frac{1}{\sqrt{2}} + \frac{1}{\sqrt{2}}*j
で、どっちを右にしてかければいいのだろうか。やってみるとわかるが、順序を逆にしてしまうと「死刑!」じゃなくて「手で銃を発射した後のポーズ」になるのだ。
計算方法を確認してみよう。「四元数×座標×共役四元数」で計算する。記号に変換して、「Q * P * -Q」と表現してみる。Q1で回転させた後にQ2で回転させることを考えると、「Q1 * P * -Q1」の結果をQ2で回転させればいい。「Q1 * P * -Q1」の結果をP1としてみると、「Q2 * P1 * -Q2」が求めるものだ。で、まんま「P1 = Q1 * P * -Q1」だから、「Q2 * (Q1 * P * -Q1) * -Q2」となり、これは「(Q2 * Q1) * P * -(Q1 * Q2)」となるはず。ぶっちゃけ共役四元数(-(Q1 * Q2))の方は自信ないが。
まぁともかく、「P」にかけるべき共役数は「Q2 * Q1」なので、「先にかけるやつは右側」なのだと思う。なので、その方向で計算。
(\frac{1}{\sqrt{2}} + \frac{1}{\sqrt{2}}*j) * (\frac{1}{\sqrt{2}} + \frac{1}{\sqrt{2}}*k)
\frac{1}{2} + \frac{1}{2}*j + \frac{1}{2}*k + \frac{1}{2}*j*k
さっきの「j*k = i」を使って、
\frac{1}{2} + \frac{1}{2}*j + \frac{1}{2}*k + \frac{1}{2}*i
順番を整理して、
\frac{1}{2} + \frac{1}{2}*i + \frac{1}{2}*j + \frac{1}{2}*k
となる。ちなみに、「これの共役四元数」も「それぞれの共役四元数の積」も同じになることを確認した。「それぞれの共役四元数の積」の方はかける順序が逆になるので注意。一般化してちゃんと証明もできそうだ。じゃあそこらへんはもういいや。次、次。


人差し指の位置を計算する。
最初の位置が(0,0,10)=「10*k」で、これが(10,0,0)=「10*i」になるはず。
(\frac{1}{2} + \frac{1}{2}*i + \frac{1}{2}*j + \frac{1}{2}*k) * (10*k) * (\frac{1}{2} - \frac{1}{2}*i - \frac{1}{2}*j - \frac{1}{2}*k)
(\frac{10}{2}*k + \frac{10}{2}*i*k + \frac{10}{2}*j*k + \frac{10}{2}*k*k) * (\frac{1}{2} - \frac{1}{2}*i - \frac{1}{2}*j - \frac{1}{2}*k)
(\frac{10}{4}*k + \frac{10}{4}*i*k + \frac{10}{4}*j*k + \frac{10}{4}*k*k) - (\frac{10}{4}*k*i + \frac{10}{4}*i*k*i + \frac{10}{4}*j*k*i + \frac{10}{4}*k*k*i) - (\frac{10}{4}*k*j + \frac{10}{4}*i*k*j + \frac{10}{4}*j*k*j + \frac{10}{4}*k*k*j) - (\frac{10}{4}*k*k + \frac{10}{4}*i*k*k + \frac{10}{4}*j*k*k + \frac{10}{4}*k*k*k)
「i*i = -1, j*j = -1, k*k = -1」「i*j = k, j*k = i, k*i = j」「j*i = -k, k*j = -i, i*k = -j」を使って整理。
(\frac{10}{4}*k - \frac{10}{4}*j + \frac{10}{4}*i - \frac{10}{4}) - (\frac{10}{4}*j + \frac{10}{4}*k - \frac{10}{4} - \frac{10}{4}*i) - (-\frac{10}{4}*i + \frac{10}{4} + \frac{10}{4}*k - \frac{10}{4}*j) - (-\frac{10}{4} - \frac{10}{4}*i - \frac{10}{4}*j - \frac{10}{4}*k)
10*i
ん。上手くいった。てか、そろそろ寝る時間なんだけど。コーディングしてないんだけど。結構「感じ」はつかめたから、もう親指の位置とかどうでもいいんだけど。てことで終了。

未分類の雑記

・睡眠時間6〜7時間だと思う。あいかわらず,いつ寝たのかさっぱり。あいかわらず,睡眠時間が振動。
振動するなら収束させればいいじゃない,ということで「6時間→10時間→7時間→9時間→8時間」みたいに収束すればいいなぁと思いつつ。まぁうまくいかんだろうな。


・例えばイラク戦争だとか,植民地だとか,「正義」を建前にした行為を検証するために,やはりなにかしらの善悪の定義が必要なんだろうか。善悪がたとえただの学習結果なのだとしても。むしろ,本当に「善」だと思ってやっているのならなおのこと。
戦争レベルだと本当にただの建前なんだろうけど、個人レベルだと云々。
とか休日に書きたくねーよ。もっと「秋めいてくると下痢気味になってつらいね」とか、そういうの書きたいよ。いや、「書きたい」ってわけではないけど。


・そろそろケガのログも飽きてきたなぁ。現状は,「最初のカサブタ」「はがした後にできたカサブタ」「さらにそれをはがした部分」が中央から上端にかけてできている状況。
風呂入った。洗っててすこし下端のがはがれた。回復しかけの部分が白くなった。あがってしばらくしたら、なんかまわりの部分が薄くはがれ出した。


・どうせ寝つきが悪いならと,学習と慣れの観点で今までのことを振り返った。やっぱり慣れは重要っぽい。というか、全てのボトルネックは「慣れ」っぽい。理屈の段階でつまるのは「量子力学」くらい?あれはあれで確率じゃないとダメ、という理屈はわかるというか。「確率じゃないとダメ」ってわけじゃないか。「確率を導入すると上手くいく」ってことか。そいで、他に手段はないんかとか考えたり。ん?やっぱり慣れの問題か?


・この前の「水に浮かぶ氷」の説明書いたのを思い出したけど、「慣れ」ってつまり「階段を上がること」?自分で階段をつくればいいのか?言語化可能な部分はそれでいいか。言語化不能な部分は?それもある種の階段のような気はするけど。今までは「努力」とか「なんとか」で感覚的にやってたけど、その「やり方」自体はある程度言語化可能な気もする。無理な部分もある気がする。
→Quaternionを階段つくりながらやってみた(上のやつ)。言語化可能な部分はその通りという感じ。今からQuaternionクラスを書くのがたぶん言語化不能な部分?さらにその先もあるか。とりあえず、書き終わった後にまだ覚えてたらメモ。
あと、飛ばせる部分は飛ばしてしまうので、階段は作るけど「他人に読みやすいか」はまた別の話になるな。
→そいやーさぁ、Quaternionって会社で使ってるじゃん?でも内部とか詳しくなかったじゃん?それって何を意味すんの?階段は途中からでも上れるってこと?レイヤの違い?レイヤかもなぁ。「車の内部構造を知らなくても運転できる」みたいな?運転とかできないからあてずっぽだけど。「原理」と「活用」とか。一般化可能?一般化できれば学習効率上がるんだけど。階段の設定方法にしても、知らなくて良いレイヤを飛ばすにしても。
→とりあえず、計算結果の感想。計算過程を示すとこで「段差」が大きくなるね。「変換規則」を示すのと、変換した部分を下線かなんかで示せば、多少はわかりやすくなりそう。
あと、計算そのものよりは、計算の前準備(どちら側からかけるか、とか)の方が大事。計算はただの確認にすぎない、という感じだった。なので、「手を動かす」ということは重要だけど、それ自体を目的化しちゃいかん、という結論。


・カンマとピリオドだとやっぱり読みづらいので、句読点を元に戻してみた。これで、家で書いてるのか会社で書いてるのかわからなくなるが、問題はないはず。
→「読みづらいので」とか言ってるけど、きっと「馬鹿だと思われたくない」と考えてるに違いない!
→違う!俺は「かっこつけだと思われたくない」と考えてるんだ!


・「どーでもいい=しょーもない」?そんな感じで使ってる気はする。


・ショック。YOUはSHOCK!ユワッシャー!
なんだよ。Texの色変えられるんじゃんよ。じゃあ黒背景でもいいじゃんよ。じゃあその方向で。


・SFの古典だとか哲学の誰かだとかアセンブラだとかを、とりあえず、必要なものなのだと仮定してみる。
その場合、「それは必要なものなのだ」という認識と「それに関する情報はどこにあるか」という情報はどう整備されておくべきか。自分の考えだけで「昔の人の考えを取り込むことが必要」だとか「必要な古典はこれだ」とか決定させるべきか。
とか色々考えるものの、よくわからん。「彼ら」はどうやってそこに行き着いたのだろう。「彼ら」にしても何らかの「環境」があったからこそ、そこに行き着いたと考えるのだけど、違うのだろうか。その「環境」が「誰か」であった場合、今度は自分がその「誰か」になるべきだと思うのだけど、違うのだろうか。あるいは自分の読みが甘くて、すでに「彼ら」はその「誰か」の役をやってるんだろうか。「この古典を読まないと、あんたなんか相手にしてあげないんだから!」みたいな?「彼ら」もそういうことを言われて「じゃあ古典読まなきゃ」となったのだろうか。
とか、いちいち考えてみたけど、対話を望んでるようには見えないんだよなぁ。「自分と同じ位置にいる人間とだけ対話したい」のであって、「誰かを自分と同じ位置に引き上げて対話しよう」という考えはない?コストが高いもんな。
あれかなぁ。「匿名の人とは対話できない」みたいな。「匿名の発言は信用できない」みたいな。信頼度の問題?


・で、上で「必要なものだと仮定」してみたのだけれど、どういう状況ならその仮定は正しいのだろうか。SFも哲学もさっぱりなので、「マシン語」限定で考えてみる。
すぐに思いついた例は「vectorとlistの違い」とか。マシン語関係あるか?とりあえず「下の方」であるのは間違いないか。「vectorで中間に要素を挿入したり削除すると遅い」とか「listだとランダムアクセスできないOR遅い」とかで問題になるけど、それって十分にマシンパワーがあったら問題にならないよなぁ。例が悪いのか。
プログラミングの問題を色々考えてみる。
「継承すべきか所持すべきか」「参照かポインタか」「デリゲータ、リスナ、関数オブジェクト」
C++に寄りすぎてる気がするが、マシン語のレイヤとは別で語れる問題が多い気がする。一つの評価基準としては使えるけど、他にも評価基準が存在して、
疲れた。ってか今日は休日だっての。もっと楽しいこと考えろよ俺。
そもそもがアセンブラとか詳しくないんだから、劣等感によってバイアスがかかった思考をしてる可能性が高いのだ。しかもSFも哲学もまったくの無知なんだから、それによってさらにバイアスがかかってる可能性は高い上に、まったくもって相手のベースを理解していないのだ。だから、今現在どんなことを推測してもしょうがない。どうせやるなら、アセンブラに詳しくなってからとか、彼らの行動パターンを観察して共通項を洗い出すとか、そういうことをしてからやるべきなんだ。ということで色々終了。休日以前の問題だ。
→さっきのレイヤの話が関係しそうなんだが終了ですか、そうですか、そうですね。


・そいや、「痛いニュース」がやってるのは「区別」にすぎないのに、なんで俺にはそれが「差別」みたいに見えるんだろ。「差別」?「偏見」か?ある種の「思想誘導」みたいな?「黒文字=一般的な文字色」から「黒文字=一般的な考え」という解釈は俺側が勝手にやってることだよなぁ。そこら辺の但し書きみたいなもんは見たことないし。でも、わりと他の人もそういう風に「解釈」してるように見える。ちゃんとリテれば「黒文字=そのスレでの主流意見」みたいに解釈することも可能なはずなんだが、なんで俺はそうしなかったんだっけ?リテれなかっただけとか?
そして今まで「リテる」という単語をすっかり忘れていた。
てか、今の「リテレベル」でもそう見えるってことは云々?いや、まだ足りないだけかも。
そして、しれっとまた造語を増やすな俺。それはまんま「リテラシー」で済むところじゃんか。
→青文字の後にそれを否定するような黒文字があったりするんだっけか?それだと「構造」まで関係するんだが、そこまで覚えてない。


・アニメやらゲームやらが悪影響を及ぼすかどうかって統計取らないと何とも言えないはずだよなぁ。「少年犯罪の増加?」の例もあるし。概念の話は「因果関係」を示すために必要だけど、そもそも「相関関係」みたいなデータがないと、潰したい側と潰されたくない側の結論ありきのわめきあいにしかならんよなぁ。
と思ったけど、統計取るのって難しいな。単純に「犯罪者」と「犯罪者と呼ばれない人達」で「アニメを見てるか」のアンケートを取っても、それだけでは「因果関係」を語るには不十分。「アニメを見てるか」「ゲーム持ってるか」「TV見るか」「ラジオは」「ネットは」とか色んな要素を網羅しないとたぶん駄目なんだろうし、さらにアンケートを「誰が取るか」が問題になる。ゲーム会社がアンケート取って「ゲームの影響はない」と言っても信憑性ないし、TVがアンケート取って「TVが影響してる」という結果が出ても公表はしないだろうし。じゃあ中立のところで、と言っても国がやると、「国がアンケート取るからには結果次第で制限をかけないといけない」とかなってあれこれあるかもだし、じゃあ大学?という感じ。
この先は「すでに大学でそういうことやってない?」ってこと調べて云々か。面倒だからやらないけど。統計嫌いってのもあるし。見つけてもまだその先にも面倒なことがあるだろうし。


・休日なのに、なんでこんなに書いてんだ。あほか俺、あほか。時間がもったいないわ。捨てろ。ログせず捨てろ。どうでもいいのは捨てちまえ。