20190415

回転行列の求め方

タグ:回転行列

回転行列がなぜあの形なのか気になった

2×2の回転行列は

$$\begin{bmatrix}\cos{\theta} & -\sin{\theta} \\ sin{\theta} & \cos{\theta}\end{bmatrix}$$

なぜこの形をしているのか、wikipediaでは省略されていた。能力が不足しているのか、省略されているのにわからなかった。

図形的考察または三角関数の加法定理より、x ', y ' は以下のように表されることが分かる。

とWikipediaには書かれていた。しかし、自分は分からなかった。


前々から気にはなっていたが、ヒントがwebサイト以外何もなかったのでわからなかった。

今月、「行列とベクトルのはなし 改訂版」を読み始めて、一次変換の章(4版の119Pあたり)の式から(回転行列については書かれていないように思う。)、「こんな感じのノリでx,yを求めればいいのかぁ」と思いやってみた。

こんな感じのノリ部分を、太い赤文字にしておく。

頑張って、自分が納得のいく説明を考えてみた。

2.回転行列の使い方。

先ずは、回転行列の使い方を書いておく。

回転変換したい点の座標(インプット)は、

$$\begin{Bmatrix}x_{\rm{i}}\\y_{\rm{i}}\end{Bmatrix}$$

ここには具体的な座標が入る。

回転変換後の座標(xo,yo)は、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{\theta}&-\sin{\theta} \\ \sin{\theta} & \cos{\theta}\end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\y_{\rm{i}}\end{Bmatrix}$$

行列のかけ算で、変換後の座標xo,yoが手に入る。

この回転行列がなぜこの形になるのかわからなかった。
多分、一番わかりやすいサイトは、ここ。Gifアニメも充実しているし。
しかし、上記サイトでも何か納得いかなかった。

3.自分の考え

いろいろ図を描いてみて、下のやり方を考えた。

  1. インプットをx,y成分の単位行列に分ける
  2. xy成分毎に、円周上を通り回転させる式を考える。
    x成分の回転軌跡は、(x,y)=(1, 0)から始まる円で描く。
    y成分の回転軌跡は、(x,y)=(0, 1)から始まる円で描く。
  3. x,y成分別に出した式を足す。→係数のみ抽出して行列にする。→回転行列になってる

4.円を描く方法

例えばExcelの散布図で、円を描きたいとする。→円周上のx,y座標が必要。
x,y座標は、三角関数を使えば出せる。

しかし、x軸から回転が始まる場合と、y軸から回転が始まる場合で、円の書き方が違う。

4.1.x軸から回転を始める場合

円のx,y座標は (x,y) = (cosθ,sinθ)でだせる。

x軸から回転し始めるとすると。
→θ=0の時、(1,0)
(cos0 = 1, sin0 = 0)だし、あってる。


理屈
単位円なので、半径1
cosθ=x/1=x
sinθ=y/1=y



回転後の座標は、細かい数値なので書かない。

figure_2.png

x軸から出発した、角度0から60度回転させた弧が描けた。

xi=1じゃなくてもできそう。

xo = cosθ×xi
yo = sinθ×xi
x成分しか考えていないので、yiは出てこない。

行列にしておくと、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{\theta}& 0 \\ \sin{\theta} & 0 \end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\0\end{Bmatrix}$$

例えば、

$$\theta = 60\\\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{60}& 0 \\ \sin{60} & 0 \end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\0\end{Bmatrix}\\ = \begin{bmatrix}0.866\cdots & 0 \\ 0.5 & 0 \end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\0\end{Bmatrix}$$

cos60とかは、コンピュータで出しました↑三角関数は、マクローリン展開で作ってるらしいよ。

これで、x成分のみの場合は、回転させられるようになった。

4.2.y軸から回転を始める場合

円のx,y座標は (x,y) = (sin, cos)でも、出せる。

ふつうは、(x,y) = (cos,sin)だが、逆にしても描ける。描けるったら描けるのだ。


この円は、Y軸から回転し始める。
→θ=0の時、(0,1)
(sin0 = 0, cos0 = 1)だし、あってる。。。
と思いきや、進行方向の向きが違う。

figure_3.pngfigure_5.png

sinは非対称な関数なので、変数をプラスにするかマイナスにするかで、値が変わってくる。
sinθのままだと、θが増えると、xも増える。
→x+側(時計回り。)に回転する。→回転させたいのは反時計回り。

変数をマイナスにするのも変なので、sinθ×-1しておく。
という事で、円のx,y座標は (x,y) = (-sinθ, cos)でだせる。

figure_4.png

xo = -sinθ×yi
yo = cosθ×yi
yi成分しか考えていないので、xiは出てこない。

行列にしておくと、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix} 0 & -\sin{\theta} \\ 0 & \cos{\theta} \end{bmatrix}\times\begin{Bmatrix}0\\y_{\rm{i}}\end{Bmatrix}$$

例えば、

$$\theta = 60\\\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}0 & -\sin{60}\\ 0 & \cos{60} \end{bmatrix}\times\begin{Bmatrix}0\\y_{\rm{i}}\end{Bmatrix}\\ = \begin{bmatrix} 0 & -0.5 \\ 0 & 0.866\cdots \end{bmatrix}\times\begin{Bmatrix}0\\y_{\rm{i}}\end{Bmatrix}$$

これで、y成分のみの場合にも、回転させられるようになった。


5.. 二つの式を組み合わせたら回転行列になった。

X成分にも、Y成分にも適用できるようにしたい。
(この間になんか欲しい。が、ない袖は振れない。)
X、Y両方を合わせてみたら、なんか回転行列の形になった。(ポカーン)
  1. x成分のみを回転させた場合
    xo = cosθ×xi
    yo = sinθ×xi
  2. y成分のみを回転させた場合
    xo = -sinθ×yi
    yo = cosθ×yi
  3. 1.2.を組み合わせた場合
    xo = cosθ×xi - sinθ×yi
    yo = sinθ×xi + cosθ×yi

上記3を行列に直すと、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{\theta}&-\sin{\theta} \\ \sin{\theta} & \cos{\theta}\end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\y_{\rm{i}}\end{Bmatrix}$$

最初の式と全く同じだけど、書いちゃったぜ。

回転行列が取り出せましたね。

6.使用したpythonコード

最近気づいたのは(今思いついたのは)、他人のサイトにpythonコードがあっても、わざわざコピペして実行なんかしてない。試さない。
そもそも、見て勉強すらしてない。

「うんうん、できるんだね。」といった感想しか持てない。

なら、本文の前のほうでスペースを占めるより、最後に押し込めたほうが、読み手の立場に立っているのではないかと思いました。欲しい(見たい)のは絵やアニメ。
(本当は、文章全体の見通しが悪かったので、コードが邪魔になっただけ。)

なので、この位置。
来月には忘れているかもな。

import numpy as np
import matplotlib.pyplot as plt

N = 500

# gray: circle(360[deg])
theta1 = 2 * np.pi
n1 = np.linspace(0, theta1, N)
x1 = np.cos(n1)
y1 = np.sin(n1)
plt.plot(x1,y1, "-", c="gray")

# red: 60[deg]
theta2 = 1.0 / 6 * 2 * np.pi
n2 = np.linspace(0, theta2, N)
x2 = np.cos(n2) #x2 = np.sin(n2) #x2 = -np.sin(n2)
y2 = np.sin(n2) #y2 = np.cos(n2)
plt.plot(x2,y2, "-", c="red", lw=3)

# Appearance
plt.xlim(-1,1)
plt.ylim(-1,1)
plt.axes().set_aspect('equal')
plt.grid(which='major',color='gray',linestyle='-')
ax = plt.gca() # get current axis
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))

plt.show()

円の方程式は、$$x^2+y^2=r^2$$と習った。けど、この形ではx,y座標が出せなかったので、放っておいた。何か大切な議論が抜けている気がするが不明。なぜ、x成分とy成分に分けたら、ちゃんと考えられたのか今以て不明。


×(かける)の後にx(エックス)を平然と持ってくるあたり、何か欠けているのかもしれない。直すつもりはないが。

タグ:回転行列
posted by yuchan at 07:00 | Comment(306) | 数学

20170919

内積の記号と、行列のかけ算で悩む

ベクトルを使った、法線の方程式の所で、悩んだので書いた。

何を悩む事があるのか

  • 内積は・で表現される。
  • 行列のかけ算も(普通のかけ算も)・で表す。(自分だけか。)
  • ベクトルを使った「一点を通る法線の方程式」の作り方で、上記二つが出てくる。

行列のかけ算は、行と列の向きが結構大事なのに、ベクトルの内積では、行列の向きをさほど意識していない(気がする)。

一般にベクトルは、n×1行列で…

ベクトルはn×1行列で書く。

$$\vec{v} = \left( \begin{array}{c} v_{x} \\ v_{y} \end{array}\right), \vec{w} = \left( \begin{array}{c} w_{x} \\ w_{y} \end{array}\right)$$
確かに、こんなん見たことあります。

座標は横長な事が多い気がする。

$$v = \left( \begin{array}{cc} v_{x}, & v_{y} \end{array}\right), w = \left( \begin{array}{cc} w_{x}, & w_{y} \end{array}\right)$$


しかも , が打ってある。

ベクトルを使った法線の方程式

ベクトルAPと垂直な法線のベクトルを考える。
$$\rm \vec{AP}\perp\vec{n}$$

$$\rm \vec{AP}\cdot\vec{n}=0$$
になる方程式が、法線の方程式だそうな
(この場合の・は、内積のドット。行列のかけ算ではない。

上の式の答えが0になる理由は、ベクトルAPとベクトルnが、90°の時の内積は0になるから、(cos90°=0を×ので)0になる。
$$\rm |\vec{AP}| |\vec{n}|\cos 90^{\circ}=|\vec{AP}| |\vec{n}|\times 0=0$$
2つのベクトル(片方は変数xを含む)の内積で、方程式が得られるのかぁ。

$$\rm \vec{AP}\cdot \vec{n}= AP\cdot n=0$$
左が内積の\cdot 、右が行列の掛け算の\cdot 。

$$\rm \vec{AP}\cdot \vec{n}= AP\cdot n = \{ \left( \begin{array}{ccc} a_{x} \\ a_{y} \end{array}\right) - \left( \begin{array}{ccc} x \\ y \end{array}\right) \} \cdot \left( \begin{array}{ccc} n_{x} \\ n_{y} \end{array}\right) =0$$

なぜ、縦向きのn×1行列で、横向きの1×n行列にしないのかという疑問で悩む。
このままだと両方縦向きなので、行列のかけ算をするときに行列の向きが、かけ算が定義できない形になる。

ベクトルの内積は縦のままでいいのか?

行列のかけ算

行列のかけ算の手順の直感的な説明はここらへんとか、
日本語では、geisyaサイトとか、で覚えるといいと思う。
とにかく、このままでは、かけ算できない。転置すべき。
でも、転置記号が書いてない。

$$\left( \begin{array}{c} a_{x}-x \\ a_{y}-y \end{array}\right) \cdot \left( \begin{array}{c} n_{x} \\ n_{y} \end{array}\right) =0$$

これじゃ、行列の掛け算ができないでしょ!

$$\rm \vec{AP}\cdot \vec{n}= (AP)^T \cdot n=0$$
こうすべきじゃないかと思った。

$$\left( \begin{array}{cc} a_{x}-x & a_{y}-y \end{array}\right) \cdot \left( \begin{array}{c} n_{x} \\ n_{y} \end{array}\right) =0$$

内積の書き方

Wikipedia「数学記号の表」の代数学の記号の下のほうに載ってたが、内積は、a・bの他にも<a,b>とか(a,b)なんかの書き方もある。

上記の内積記号の注意

注意したいのは大小比較(>とか<)ではなくtexでいうところの\langle, \rangleだという事。
並べてみるとわかるが、

$$\langle a,b \rangle$$ $$< a,b >$$
上が正しい内積。下が間違い。

$$\langle a,b \rangle$$ $$< a,b >$$

TeXで書くと、こう。

結局こうする

$$\rm \langle \vec{AP}, \vec{n}\rangle = \langle  \left( \begin{array}{c} a_{x}-x \\ a_{y}-y \end{array}\right) , \left( \begin{array}{c} n_{x} \\ n_{y} \end{array} \right) \rangle \\ =AP^T n=\left( \begin{array}{cc} a_{x}-x & a_{y}-y \end{array}\right) \cdot \left( \begin{array}{c} n_{x} \\ n_{y} \end{array}\right) \\ = \left. \begin{array}{cc} (a_{x}-x)\times n_{x} & + &(a_{y}-y)\times n_{y} \end{array}\right. =0$$

本当は中置記法で置く演算子が使いたい。

只、本当は、中置記法で置く演算子が使いたい。

・に代わる内積の記号を作ってほしい。
もしくは、行列のかけ算は、ほかの演算子でもいいのだろうか…



よく考えると、行列のかけ算の方がおかしいのかなぁとか考えてしまう。でも、縦長のまんまでもいいかも…

なんでひっくり返すんだよと。

内積の表記の方が、直感的でわかりやすい気がしてきた。

ただ、内積の表記は、最後に足し算をしなければならない点を忘れやすい気がする。

今まで勘違いしていた

行列のかけ算はドット積だと思っていた。

ベクトルの内積はドット積。
行列のかけ算はドット積と言う人はいない気がする。

勘違いした理由は、多分、numpyのnp.dotsで行列のかけ算をやっていたからだと思う。
ただ、numpyのリファレンスをよく読むと、

2-d配列だったら行列のかけ算、1-d配列だったら内積(innner product)と同等。N-dだったら…

と、ちゃんと書いてあった。結構ドット積という言葉をそこかしこで連発していたので、修正しなければ。

もうちょいで新しい動画が完成する。

もうちょいなんだが、そのもうちょいで時間を浪費している。
今回の内積云々も、その一環。

posted by yuchan at 07:00 | Comment(71) | 数学