![書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(8)](https:///re.buildinsider.net/small/bookkinectv2/index/icon.x.png)
書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(8)
ベクトルの回転 ― Kinectで学ぶ数学
― Chapter 8 ― 8.3 ―
Kinectではプレイヤーの関節の3次元座標を取得できる。前2回の説明を踏まえて、2次元ベクトル/3次元ベクトルの回転を理解しよう。
Kinectで必要となる数学を説明します。前回は空間内のベクトルについての数学を解説しました。本稿はその続きとして、ベクトルの回転について説明します。
書籍転載について
本コーナーは、秀和システム発行の書籍『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。
『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』の詳細や購入は秀和システムのサイトや目次ページをご覧ください。プログラムのダウンロードも、秀和システムのサイトから行えます。
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
■
8.3 ベクトルの回転
8.3.1 2 次元ベクトルの回転
ある2次元位置ベクトル v=(s,t) を写像 R で原点を中心に長さを変えず回転させることを考えます。ベクトル v と x 軸とのなす角を φ とすると、
![v=(s,t)=(|v|cosφ,|v|sinφ)](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-01.gif)
と表されます。これを θ だけ回転すると、三角函数の加法公式を使い
![R(v)=|v|(cos(φ+θ),sin(φ+θ))
=|v|(cosφcosθ-sinφsinθ,sinφcosθ+cosφsinθ)](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-02.gif)
となります。
![R(v) v φ O](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-03.gif)
これを行列で書き換えると
![R(v)=|v|(■(cosφcosθ-sinφsinθ@sinφcosθ+cosφsinθ))=|v|(■(cosθ&-sinθ@sinθ&cosθ))(■(cosφ@sinφ))=(■(cosθ&-sinθ@sinθ&cosθ))(■(|v|cosφ@|v|sinφ))=(■(cosθ&-sinθ@sinθ&cosθ))(■(s@t))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-04.gif)
とかけ算の形になります。したがってベクトルを θ だけ回転する写像 R は線型写像であって、R を表す行列は
![(■(cosθ&-sin@sinθ&cosθ))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-05.gif)
だということが分かります。この形の行列を回転を表す行列という意味で回転行列ということがあります。回転行列と回転行列の積もまた回転行列です。実際
![(■(cosθ_2&-sinθ_2@sinθ_2&cosθ_2))(■(cosθ_1&-sinθ_1@sinθ_1&cosθ_1))=(■(cos(θ_1+θ_2)&-sin(θ_1+θ_2)@sin(θ_1+θ_2)&cos(θ_1+θ_2)))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-06.gif)
が成り立ちます。これはまず θ1 回転してから θ2 回転すると θ1+θ2 回転することになるという、意味を考えれば至極当たり前のことです。
位置ベクトル (s,t) を原点ではなく一般の点 (a,b) を中心に回転させた位置ベクトルが求めたければ、 (a,b) を始点、(s,t) を終点とするベクトル (s-a,t-b) を (a,b) を中心に回転させせて得られたベクトルの終点の位置ベクトルが求めるべきベクトルです。
![求めるべきベクトル](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-07.gif)
(s-a,t-b) を (a,b) を中心に回転させたベクトルは縦ベクトルで書くと
![(■(cosθ&-sinθ@sinθ&cosθ))(■(s-a@t-b))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-08.gif)
ですから、その位置ベクトルは
![(■(cosθ&-sinθ@sinθ&cosθ))(■(s-a@t-b))+(■(a@b))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-09.gif)
となります。
EXERCISE 10
右ひじ→右手首2次元ベクトルを反時計回りに30度回転させたベクトルを表示するKinectアプリケーションを作成してください。
8.3.2 3次元ベクトルの回転
残念ながら、3次元ベクトルの回転は2次元のときよりかなり複雑です。まず、ある3次元位置ベクトルを z 軸を中心として θ 回転することを考えると、これは z 成分はそのままに x 成分、y 成分だけ回転することになりますから、2次元の場合の結果からこの回転は
![R_z (θ)=(■(cosθ&-sinθ&0@sinθ&cosθ&0@0&0&1))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-10.gif)
という行列で表されることが分かります。
![z x y θ](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-11.gif)
同様に、x 軸を中心とした回転は
![R_x (θ)=(■(1&0&0@0&cosθ&-sinθ@0&sinθ&cosθ))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-12.gif)
y 軸を中心とした回転は
![R_y (θ)=(■(cosθ&0&sinθ@0&1&0@-sinθ&0&cosθ))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-13.gif)
となります。原点を通り一般の方向ベクトル (u1,u2,u3) (ただし |(u1,u2,u3)|=1 )が表す方向を向いた軸を中心とした回転を表す行列は次のようになります。
![z x y u θ](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-14.gif)
これもまた回転行列と呼ばれます。2次元のときほど明らかではありませんが、3次元の場合も回転行列と回転行列の積は回転行列になっています。つまりどのような方向を軸に何度重ねて回転させても、その結果はある一つの軸が存在してその軸を中心にいくらか回転させたことになっています。
特に、任意の回転を最初に挙げた Rx,Ry,Rz を3つ組み合わせて表現することができ、これが後に扱うロール・ピッチ・ヨーに対応します。
EXERCISE 11
右ひじ→右手首3次元ベクトルを、x 軸、y 軸、z 軸を中心としてそれぞれ反時計回りに30度回転させたベクトルを表示するKinectアプリケーションを作成してください。それぞれの回転されたベクトルと元のベクトルの方向が一致する方向はあるでしょうか。
8.3.3 線型写像による座標変換
平面座標とは、基本ベクトルの組 e1,e2 によって任意の位置ベクトルを
![ae_1+be_2](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-16.gif)
とただ一通りに表し、この係数の組 (a,b) でもって位置ベクトルを表すやり方のことだと思うことができます。したがって、別のベクトルの組を持ってきても同様のことをすることも考えられます。たとえば e′1=e1,e′2=e1+e2 というベクトルを使えば
![ae_1+be_2=(a-b)〖e^'〗_1+b〖e^'〗_2](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-17.gif)
ですから、任意の位置ベクトルをただ一通りに表すことができます。この場合そのベクトルは (a-b,b) と表されることになります。このように座標を作るために使われるベクトルの組を基底ベクトルと言いますが、この基底ベクトルを取り替えたときに同じ記号を使うのは混乱の元ですので、
![ae_1+be_2=(■(e_1&e_2))(■(a@b))=(■(〖e^'〗_1&〖e^'〗_2))(■(a-b@b))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-18.gif)
と前に「ベクトル成分の行列」を付け加えることで区別することにします。右辺は1×1行列ですから左辺も元来は (ae1+be2) と書くべきですが、誤解の恐れがない場合はこのように括弧を外して書いてしまいます。さらに、基底ベクトルの変換式も行列を用いて
![(■(〖e^'〗_1&〖e^'〗_2))=(■(e_1&e_2))(■(1&1@0&1))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-19.gif)
と書くことができます。
さて、基底ベクトルを変更したとき、各ベクトルの座標や線型写像の行列がどのように変わるかを見てみましょう。少し難しい話になりますが、これはたとえば関節の位置や回転をKinectのものからUnityのものに変換するときに必要となる、非常に重要な話題です。基底ベクトルの変換式が線型写像であらわされるときを考えます。すなわち行列 T を用いて
![(■(〖e^'〗_1&〖e^'〗_2))=(■(e_1&e_2))T](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-20.gif)
と表されるときを考えます。このとき
![(■(e_1&e_2))(■(a@b))=(■(〖e^'〗_1&〖e^'〗_2))T^-1 (■(a@b))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-21.gif)
ですから、元の基底ベクトルにおいて
![(■(a@b))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-22.gif)
と表されるベクトルは新しい基底ベクトルでは
![T^-1 (■(a@b))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-23.gif)
となることがわかります。さらに元の基底ベクトルにおいて行列 A が線型写像 f を表すというのは、写像 f によって
![(■(e_1&e_2))(■(x@y))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-24.gif)
が
![(■(e_1&e_2))A(■(x@y))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-25.gif)
に写されるという意味でしたから、これを新しい基底ベクトルでの表現に書き換えれば写像 f は
![(■(e_1&e_2))(■(x@y))=(■(〖e^'〗_1&〖e^'〗_2))T^-1 (■(x@y))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-26.gif)
を
![(■(e_1&e_2))A(■(x@y))=(■(〖e^'〗_1&〖e^'〗_2))T^-1 A(■(x@y))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-27.gif)
に写します。さらに
![T^-1 (■(x@y))=(■(〖x^'〗@〖y^'〗))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-28.gif)
と置き換えて元の形式に揃えれば写像 f は
![(■(〖e^'〗_1&〖e^'〗_2))(■(x^'@y^'))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-29.gif)
を
![(■(〖e^'〗_1&〖e^'〗_2))T^-1 AT(■(x^'@y^'))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-30.gif)
に写すことになるので、写像fを表す行列は
![T^-1 AT](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-31.gif)
であることがわかります。
ここでは2次元ベクトルで説明を行いましたが、3次元(やそれ以上の次元)でも全く話は同様で、基底ベクトルが
![(■(〖e^'〗_1&〖e^'〗_2&〖e^'〗_3 ))=(■(e_1&e_2&e_3 ))T](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-32.gif)
と変換されれば、元の基底ベクトルで
![(■(a@b@c))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-33.gif)
だったベクトルは
![T^-1 (■(a@b@c))](https:///re.buildinsider.net/small/bookkinectv2/0803/8-3-34.gif)
で表されるようになり、行列 A で表されていた線型写像は T-1AT で表されるようになります。
■
次回は、ロール・ピッチ・ヨーについて説明します。
※以下では、本稿の前後を合わせて5回分(第6回~第10回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
![書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(8)](https:///re.buildinsider.net/small/bookkinectv2/index/icon.s.png)
8. 【現在、表示中】≫ ベクトルの回転 ― Kinectで学ぶ数学
Kinectではプレイヤーの関節の3次元座標を取得できる。前2回の説明を踏まえて、2次元ベクトル/3次元ベクトルの回転を理解しよう。
![書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(8)](https:///re.buildinsider.net/small/bookkinectv2/index/icon.s.png)
10. クォータニオン ― Kinectで学ぶ数学
全5回にわたる、Kinectで必要となる数学の解説は、今回で完結。最終回では、Kinect SDKでも関節の回転角度として採用されているクォータニオンについて説明する。