skip to content
/var/log/little-things
Search any posts

複素数における回転の表現と補間

複素数における回転の表現と補間について

概要

複素数における回転の表現と補間について簡単に整理をする。

回転の表現

定義は

C1:={pCp=1}={eθiθR}\mathbb{C}_1 := \{p \in \mathbb{C} \mid |p|=1 \}=\{e^{\theta\mathbb{i}} \mid \theta \in \mathbb{R} \}

eθie^{\theta\mathbb{i}} はオイラーの公式1

eθi=cos(θ)+sin(θ)ie^{\theta\mathbb{i}} =\cos{(\theta)} + \sin{(\theta)} \mathbb{i}

補間の方法

p=a+bi,q=c+diC1p=a+b\mathbb{i}, \hspace{3pt} q=c+d\mathbb{i} \in \mathbb{C}_1 間を hRh \in \mathbb{R} で補間する方法。

線形補間

定義は

LERP(p,q;h)=(1h)p+hq\operatorname{LERP}(p,q;h) =(1-h)p + hq

特徴は

  • 大きさを維持しない
  • 速度は不定

正規化線形補間

定義は

nLERP(p,q;h)=LERP(p,q;h)LERP(p,q;h)\operatorname{nLERP}(p,q;h) =\frac{\operatorname{LERP}(p,q;h)}{|\operatorname{LERP}(p,q;h)|}

特徴は

  • 大きさを維持
  • 速度は不定

球面線形補間

定義は

SLERP(p,q;h)=p(p1q)h=pexp(hlog(p1q))\operatorname{SLERP}(p,q;h) =p \cdot (p^{-1} \cdot q)^h =p \cdot \exp{(h \log{(p^{-1} \cdot q)})}

特徴は

  • 大きさを維持
  • 速度は一定

スプライン補間

定義は

SQUAD(pi,pi+1,si,si+1;h)=SLERP(SLERP(pi,pi+1;h),SLERP(si,si+1;h),2h(1h))\operatorname{SQUAD}(p_{i}, p_{i+1}, s_{i}, s{i+1}; h) =\operatorname{SLERP}(\operatorname{SLERP}(p_{i}, p_{i+1}; h), \operatorname{SLERP}(s_{i}, s_{i+1}; h), 2h(1-h))

ここで pi,pi+1,si,si+1C1p_{i}, p_{i+1}, s_{i}, s_{i+1} \in \mathbb{C}_1sis_{i} は次式で表される。

si=piexp(log(pi1pi1)+log(pi1pi+1)4)s_{i} =p_{i} \exp{\left(- \frac{\log{(p_{i}^{-1} p_{i-1})} + \log{(p_{i}^{-1} p_{i+1})}}{4}\right)}

eθie^{\theta\mathbb{i}} の補間

一般的な回転を表現する複素数での補間は、常に最短円弧を描く補間となる。

Fig. 1. 最短円弧を描く補間

なす角が180度を超える場合に最長円弧を描く補間にするには2

  1. 複素数の偏角の主値の範囲を (π,π](-\pi, \pi] とし p,qp, q の角度を [0,π)[0,\pi) で求める
ϕ={Arg(p)+2πif Arg(p)<0Arg(p)otherwiseψ={Arg(q)+2πif Arg(q)<0Arg(q)otherwise\begin{aligned} \phi= \begin{cases} Arg{(p)} + 2\pi & \text{if } Arg{(p)} < 0\\ Arg{(p)} & \text{otherwise} \end{cases}\\ \\ \psi= \begin{cases} Arg{(q)} + 2\pi & \text{if } Arg{(q)} < 0\\ Arg{(q)} & \text{otherwise} \end{cases} \end{aligned}
  1. 向きを求める
d=p.xq.xp.yq.y=p.xq.yp.yq.x\begin{aligned} d= \begin{vmatrix} p.x & q.x\\ p.y & q.y \end{vmatrix} =p.x \cdot q.y - p.y \cdot q.x \end{aligned}
  1. なす角を決定する
α={{cos1(p,q)if d<02πcos1(p,q)otherwiseif ψϕ<0{2πcos1(p,q)if d<0cos1(p,q)otherwiseotherwise\begin{aligned} \alpha= \begin{cases} \begin{cases} \cos^{-1}{(\langle p, q \rangle)} & \text{if } d < 0\\ 2 \pi - \cos^{-1}{(\langle p, q \rangle)} & \text{otherwise} \end{cases} & \text{if } \psi - \phi < 0\\ \begin{cases} 2 \pi - \cos^{-1}{(\langle p, q \rangle)} & \text{if } d < 0\\ \cos^{-1}{(\langle p, q \rangle)} & \text{otherwise} \end{cases} & \text{otherwise} \end{cases} \end{aligned}
Fig. 2. 最長円弧を描く補間

eθ2ie^{\frac{\theta}{2}\mathbb{i}} の補間

半角形式の補間は、なす角が180度を超えると最長円弧を描く補間となる。

半角形式は半円で360度を表現し残りは繰り返しとなるので ±eθ2i\pm e^{\frac{\theta}{2}\mathbb{i}} は同じ回転を表現する。

Fig. 3. 半角形式の補間

なす角が180度を超える場合に最短円弧を描く補間にするには3

  • なす角が180度を超える場合に片方の符号を反転し補間を行う

    符号を反転しても同じ回転を表現することを利用

    r={qif p,q<0+qotherwise\begin{aligned} r= \begin{cases} -q & \text{if } \langle p, q \rangle \lt 0\\ +q & \text{otherwise} \end{cases} \end{aligned}

球面線形補間の別形式

指数・対数関数を用いない形式について。

z0=a+bi,z1=c+diC1z_0=a+b\mathbb{i}, \hspace{3pt} z_1=c+d\mathbb{i} \in \mathbb{C}_1 のなす角を α\alpha とし hRh \in \mathbb{R} で補間した zhC1z_h \in \mathbb{C}_1 を求める。

この時 z1z_1 を元に z0z_0 に垂直な軸を z1z^{'}_1 とすると

zh=cos(αh)z0+sin(αh)z1z_h =\cos{(\alpha h)} z_0 + \sin{(\alpha h)} z^{'}_1
Fig. 4. 球面線形補間

z1z^{'}_1 は二次元の場合は90度回転として求められる。

z1=b+aiz^{'}_1 =- b + a \mathbb{i}

より一般的には

z1=z1z0,z1z0z1z0,z1z0z^{'}_1 =\frac{z_1 - \langle z_0, z_1 \rangle z_0}{|z_1 - \langle z_0, z_1 \rangle z_0|}

または簡潔に

z1=z1cos(α)z0sin(α)z^{'}_1 =\frac{z_1 - \cos{(\alpha)} z_0}{\sin{(\alpha)}}

s=z0,z1=cos(α)s=\langle z_0, z_1 \rangle=\cos{(\alpha)} とすると分母は

z1z0,z1z0=z1sz0=(csa)2+(dsb)2=s2z022sz0,z1+z12=s22s2+1=1s2=1cos2(α)=sin2(α)=sin(α)\begin{aligned} |z_1 - \langle z_0, z_1 \rangle z_0| &=|z_1 - s z_0|\\ &=\sqrt{(c-sa)^2 + (d-sb)^2}\\ &=\sqrt{s^2 |z_0|^2 - 2s \langle z_0,z_1 \rangle + |z_1|^2}\\ &=\sqrt{s^2 - 2s^2 + 1}\\ &=\sqrt{1 - s^2}\\ &=\sqrt{1 - \cos^{2}{(\alpha)}}\\ &=\sqrt{\sin^{2}{(\alpha)}} =\sin{(\alpha)} \end{aligned}

z1z^{'}_1zhz_h に代入すると

zh=cos(αh)z0+sin(αh)z1=cos(αh)z0+sin(αh)z1cos(α)z0sin(α)=cos(αh)z0+sin(αh)sin(α)z1sin(αh)cos(α)sin(α)z0=sin(α)cos(αh)cos(α)sin(αh)sin(α)z0+sin(αh)sin(α)z1=sin(α(1h))sin(α)z0+sin(αh)sin(α)z1\begin{aligned} z_{h} &=\cos(\alpha h) z_0 + \sin(\alpha h) z^{'}_1\\ &=\cos(\alpha h) z_0 + \sin(\alpha h) \frac{z_1 - \cos(\alpha) z_0}{\sin(\alpha)}\\ &=\cos(\alpha h)z_{0} + \frac{\sin(\alpha h)}{\sin(\alpha)}z_{1} - \frac{\sin(\alpha h)\cos(\alpha)}{\sin(\alpha)}z_{0}\\ &=\frac{\sin(\alpha)\cos(\alpha h) - \cos(\alpha)\sin(\alpha h)}{\sin(\alpha)}z_{0} + \frac{\sin(\alpha h)}{\sin(\alpha)}z_{1}\\ &=\frac{\sin(\alpha(1 - h))}{\sin(\alpha)}z_{0} + \frac{\sin(\alpha h)}{\sin(\alpha)}z_{1} \end{aligned}

途中、三角関数の加法定理を利用した。

このままでは分母に sin(α)\sin{(\alpha)} があるため α0\alpha \to 0 で発散するので

1z0,z1ϵ1 - |\langle z_0, z_1 \rangle| \le \epsilon ならば線形補間に切り替え回避をする。

スプライン補間の補足

未知数 sis_{i} の導出方法。

  • SLERP\operatorname{SLERP} の微分

    ddhSLERP(p,q;h)=ddhp(pq)h=pddhexp(hlog(pq))=pexp(hlog(pq))log(pq)=SLERP(p,q;h)log(pq)\begin{aligned} \frac{d}{dh} \operatorname{SLERP}(p,q;h) &=\frac{d}{dh} p \cdot (\overline{p} \cdot q)^{h}\\ &=p \cdot \frac{d}{dh} \exp{(h \log{(\overline{p} \cdot q)})}\\ &=p \cdot \exp{(h \log{(\overline{p} \cdot q)})} \cdot \log{(\overline{p} \cdot q)}\\ &=\operatorname{SLERP}(p,q;h) \cdot \log{(\overline{p} \cdot q)} \end{aligned}
  • Squad(pi1,pi,si1,si,1)=Squad(pi,pi+1,si,si+1,0)\operatorname{Squad}(p_{i-1}, p_{i}, s_{i-1}, s_{i}, 1) = \operatorname{Squad}(p_{i}, p_{i+1}, s_{i}, s_{i+1}, 0)

    Squad(pi1,pi,si1,si;1)=SLERP(SLERP(pi1,pi;1),SLERP(si1,si;1);0)=SLERP(pi,si;0)=piSquad(pi,pi+1,si,si+1;0)=SLERP(SLERP(pi,pi+1;0),SLERP(si,si+1;0),0)=SLERP(pi,si;0)=pi\begin{aligned} \operatorname{Squad}(p_{i-1}, p_{i}, s_{i-1}, s_{i}; 1) &=\operatorname{SLERP}(\operatorname{SLERP}(p_{i-1}, p_{i}; 1), \operatorname{SLERP}(s_{i-1}, s_{i}; 1); 0)\\ &=\operatorname{SLERP}(p_{i}, s_{i}; 0)\\ &=p_{i}\\ \\ \operatorname{Squad}(p_{i}, p_{i+1}, s_{i}, s_{i+1}; 0) &=\operatorname{SLERP}(\operatorname{SLERP}(p_{i}, p_{i+1}; 0), \operatorname{SLERP}(s_{i}, s_{i+1}; 0), 0)\\ &=\operatorname{SLERP}(p_{i}, s_{i}; 0)\\ &=p_{i} \end{aligned}
  • SQUAD\operatorname{SQUAD} の微分

    gi(h)=SLERP(pi,pi+1;h)SLERP(si,si+1;h)g_{i}(h) = \overline{\operatorname{SLERP}(p_{i}, p_{i+1}; h)} \cdot \operatorname{SLERP}(s_{i}, s_{i+1}; h) とすると

    ddhSquad(pi,pi+1,si,si+1;h)=ddhSLERP(SLERP(pi,pi+1;h),SLERP(si,si+1;h),2h(1h))=ddhSLERP(pi,pi+1;h)gi(h)2h(1h)=(ddhSLERP(pi,pi+1;h))gi(h)2h(1h)SLERP(pi,pi+1;h)(ddhgi(h)2h(1h))=SLERP(pi,pi+1;h)log(pipi+1)gi(h)2h(1h)SLERP(pi,pi+1;h)(ddhgi(h)2h(1h))\begin{aligned} \frac{d}{dh} \operatorname{Squad}(p_{i}, p_{i+1}, s_{i}, s_{i+1}; h) &=\frac{d}{dh} \operatorname{SLERP}(\operatorname{SLERP}(p_{i}, p_{i+1}; h), \operatorname{SLERP}(s_{i}, s_{i+1}; h), 2h(1-h))\\ &=\frac{d}{dh} \operatorname{SLERP}(p_{i}, p_{i+1}; h) \cdot g_{i}(h)^{2h(1-h)}\\ &=\left(\frac{d}{dh} \operatorname{SLERP}(p_{i}, p_{i+1}; h)\right) \cdot g_{i}(h)^{2h(1-h)} - \operatorname{SLERP}(p_{i}, p_{i+1}; h) \cdot \left(\frac{d}{dh} g_{i}(h)^{2h(1-h)}\right)\\ &=\operatorname{SLERP}(p_{i}, p_{i+1}; h) \cdot \log{(\overline{p_{i}} \cdot p_{i+1})} \cdot g_{i}(h)^{2h(1-h)} - \operatorname{SLERP}(p_{i}, p_{i+1}; h) \cdot \left(\frac{d}{dh} g_{i}(h)^{2h(1-h)}\right) \end{aligned}
  • gi(h)2h(1h)g_{i}(h)^{2h(1-h)} の微分

    gi(h)=cos(θgi(h))+sin(θgi(h))i,f(h)=2h(1h)g_{i}(h)=\cos{(\theta_{g_{i}(h)})} + \sin{(\theta_{g_{i}(h)})} \mathbb{i}, \hspace{5pt} f(h)=2h(1-h) と置いて

    ddhgi(h)2h(1h)=ddhexp(f(h)log(gi(h)))=ddhexp(f(h)θgi(h)i)=ddh(cos(f(h)θgi(h))+sin(f(h)θgi(h))i)=sin(f(h)θgi(h))(ddhf(h)θgi(h))cos(f(h)θgi(h))(ddhf(h)θgi(h))i=sin(f(h)θgi(h))((ddhf(h))θgi(h)+f(h)(ddhθgi(h)))cos(f(h)θgi(h))((ddhf(h))θgi(h)+f(h)(ddhθgi(h)))i\begin{aligned} \frac{d}{dh} g_{i}(h)^{2h(1-h)} &=\frac{d}{dh} \exp{(f(h) \cdot \log{(g_{i}(h))})}\\ &=\frac{d}{dh} \exp{(f(h) \cdot \theta_{g_{i}(h)} \mathbb{i})}\\ &=\frac{d}{dh} \left(\cos{(f(h) \cdot \theta_{g_{i}(h)})} + \sin{(f(h) \cdot \theta_{g_{i}(h)})} \mathbb{i}\right)\\ &=-\sin{(f(h) \cdot \theta_{g_{i}(h)})} \cdot \left(\frac{d}{dh} f(h) \cdot \theta_{g_{i}(h)}\right) - \cos{(f(h) \cdot \theta_{g_{i}(h)})} \cdot \left(\frac{d}{dh} f(h) \cdot \theta_{g_{i}(h)}\right) \mathbb{i}\\ &=-\sin{(f(h) \cdot \theta_{g_{i}(h)})} \cdot \left(\left(\frac{d}{dh} f(h)\right) \cdot \theta_{g_{i}(h)} + f(h) \cdot \left(\frac{d}{dh} \theta_{g_{i}(h)}\right)\right) \\&\hspace{11pt} - \cos{(f(h) \cdot \theta_{g_{i}(h)})} \cdot \left(\left(\frac{d}{dh} f(h)\right) \cdot \theta_{g_{i}(h)} + f(h) \cdot \left(\frac{d}{dh} \theta_{g_{i}(h)}\right)\right) \mathbb{i} \end{aligned}
  • ddhSquad(pi1,pi,si1,si,1)=ddhSquad(pi,pi+1,si,si+1,0)\frac{d}{dh} \operatorname{Squad}(p_{i-1}, p_{i}, s_{i-1}, s_{i}, 1) = \frac{d}{dh} \operatorname{Squad}(p_{i}, p_{i+1}, s_{i}, s_{i+1}, 0)

    ddhSquad(pi1,pi,si1,si,1)=SLERP(pi1,pi;1)log(pi1pi)SLERP(pi1,pi;1)(ddhgi1(h)2h(1h))(1)=pilog(pi1pi)2piθgi1(1)i=pi(log(pi1pi)2log(gi1(1)))=pi(log(pi1pi)2log(pisi))ddhSquad(pi,pi+1,si,si+1,0)=SLERP(pi,pi+1;0)log(pipi+1)SLERP(pi,pi+1;0)(ddhgi(h)2h(1h))(0)=pilog(pipi+1)2piθgi(0)i=pi(log(pipi+1)2log(gi(0)))=pi(log(pipi+1)2log(pisi))\begin{aligned} \frac{d}{dh} \operatorname{Squad}(p_{i-1}, p_{i}, s_{i-1}, s_{i}, 1) &=\operatorname{SLERP}(p_{i-1}, p_{i}; 1) \cdot \log{(\overline{p_{i-1}} \cdot p_{i})} - \operatorname{SLERP}(p_{i-1}, p_{i}; 1) \cdot \left(\frac{d}{dh} g_{i-1}(h)^{2h(1-h)}\right)(1)\\ &=p_{i} \cdot \log{(\overline{p_{i-1}} \cdot p_{i})} - 2 p_{i} \cdot \theta_{g_{i-1}(1)} \mathbb{i}\\ &=p_{i} \cdot \left(\log{(\overline{p_{i-1}} \cdot p_{i})} - 2 \log(g_{i-1}(1))\right)\\ &=p_{i} \cdot \left(\log{(\overline{p_{i-1}} \cdot p_{i})} - 2 \log(\overline{p_{i}} \cdot s_{i})\right)\\ \\ \frac{d}{dh} \operatorname{Squad}(p_{i}, p_{i+1}, s_{i}, s_{i+1}, 0) &=\operatorname{SLERP}(p_{i}, p_{i+1}; 0) \cdot \log{(\overline{p_{i}} \cdot p_{i+1})} - \operatorname{SLERP}(p_{i}, p_{i+1}; 0) \cdot \left(\frac{d}{dh} g_{i}(h)^{2h(1-h)}\right)(0)\\ &=p_{i} \cdot \log{(\overline{p_{i}} \cdot p_{i+1})} - 2 p_{i} \cdot \theta_{g_{i}(0)} \mathbb{i}\\ &=p_{i} \cdot \left(\log{(\overline{p_{i}} \cdot p_{i+1})} - 2 \log{(g_{i}(0))}\right)\\ &=p_{i} \cdot \left(\log{(\overline{p_{i}} \cdot p_{i+1})} - 2 \log{(\overline{p_{i}} \cdot s_{i})}\right) \end{aligned}
  • 上式より

    pi(log(pi1pi)2log(pisi))=pi(log(pipi+1)2log(pisi))log(pi1pi)2log(pisi)=log(pipi+1)2log(pisi)4log(pisi)=log(pi1pi)log(pipi+1)pisi=exp(log(pi1pi)log(pipi+1)4)si=piexp(log(pi1pi)log(pipi+1)4)\begin{aligned} p_{i} \cdot \left(\log{(\overline{p_{i-1}} \cdot p_{i})} - 2 \log(\overline{p_{i}} \cdot s_{i})\right) &=p_{i} \cdot \left(\log{(\overline{p_{i}} \cdot p_{i+1})} - 2 \log{(\overline{p_{i}} \cdot s_{i})}\right)\\ \\ \log{(\overline{p_{i-1}} \cdot p_{i})} - 2 \log(\overline{p_{i}} \cdot s_{i}) &=\log{(\overline{p_{i}} \cdot p_{i+1})} - 2 \log{(\overline{p_{i}} \cdot s_{i})}\\ 4 \log{(\overline{p_{i}} \cdot s_{i})} &=\log{(\overline{p_{i-1}} \cdot p_{i})} - \log{(\overline{p_{i}} \cdot p_{i+1})}\\ \\ \overline{p_{i}} \cdot s_{i} &=\exp{\left(\frac{\log{(\overline{p_{i-1}} \cdot p_{i})} - \log{(\overline{p_{i}} \cdot p_{i+1})}}{4}\right)}\\ \\ s_{i} &=p_{i} \cdot \exp{\left(\frac{\log{(\overline{p_{i-1}} \cdot p_{i})} - \log{(\overline{p_{i}} \cdot p_{i+1})}}{4}\right)} \end{aligned}

    p1p2=p1p2,log(p)=log(p),p=p1\overline{p_1 \cdot p_2}=\overline{p_1} \cdot \overline{p_2}, \hspace{3pt} \log(\overline{p})=-\log(p), \hspace{3pt} \overline{p}=p^{-1} を利用し

    si=piexp(log(pi1pi)log(pipi+1)4)=piexp(log(pi1pi)log(pipi+1)4)=piexp(log(pipi1)log(pipi+1)4)=piexp(log(pi1pi1)log(pi1pi+1)4)\begin{aligned} s_{i} &=p_{i} \cdot \exp{\left(\frac{\log{(\overline{p_{i-1}} \cdot p_{i})} - \log{(\overline{p_{i}} \cdot p_{i+1})}}{4}\right)}\\ &=p_{i} \cdot \exp{\left(\frac{\log{(\overline{p_{i-1} \cdot \overline{p_{i}}})} - \log{(\overline{p_{i}} \cdot p_{i+1})}}{4}\right)}\\ &=p_{i} \cdot \exp{\left(- \frac{\log{(\overline{p_{i}} \cdot p_{i-1})} - \log{(\overline{p_{i}} \cdot p_{i+1})}}{4}\right)}\\ &=p_{i} \cdot \exp{\left(- \frac{\log{(p_{i}^{-1} \cdot p_{i-1})} - \log{(p_{i}^{-1} \cdot p_{i+1})}}{4}\right)} \end{aligned}

    四元数 piH1p_{i} \in {H}_1 なら p1p2=p2p1\overline{p_1 \otimes p_2}=\overline{p_2} \otimes \overline{p_1}

四元数のスプライン補間4と同様となる。

Fig. 5. スプライン補間

C++ での実装例

GitHub Gist

参考文献

  1. Jim Van Verth 2012 Understanding Rotations
  2. Erik B. Dam, Martin Koch, Martin Lillholm 1998 Quaternions, Interpolation and Animation

Footnotes

  1. https://en.wikipedia.org/wiki/Euler’s_formula

  2. 後述の eθ2ie^{\frac{\theta}{2}\mathbb{i}} の補間での Default 動作

  3. 前述の eθie^{\theta\mathbb{i}} の補間での Default 動作

  4. 参考文献 [2] を参照。