Skip to content

Commit

Permalink
quaternion
Browse files Browse the repository at this point in the history
  • Loading branch information
songdaegeun committed May 6, 2024
1 parent c464ceb commit b998984
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 6 deletions.
175 changes: 169 additions & 6 deletions _posts/2024-05-02-κ°œλ…-quaternion.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Quaternion이 SO(3)에 μ†ν•˜λŠ”, νšŒμ „ν–‰λ ¬κ³Ό λ™μΉ˜λΌλŠ” 것 λ§κ³ λŠ” 이

### λ¬Έμ œμƒν™©

1. μš°μ„  Quaternion이 뭔지 μ§κ΄€μ μœΌλ‘œ λͺ¨λ₯΄κ² λ‹€.\
1. μš°μ„  Quaternion이 뭔지 μ§κ΄€μ μœΌλ‘œ λͺ¨λ₯΄κ² λ‹€.
2. c code[Quaternion, Euler, Matrixλ³€ν™˜](/assets/img/κ°œλ…/2024-05-02-κ°œλ…-quaternion/quaternion_euler.c)이 이해가 μ•ˆλœλ‹€.

### 해결방법
Expand All @@ -44,14 +44,14 @@ $$

quaternion에 unit quaternion을 κ³±ν•˜λŠ” ν–‰μœ„λŠ” 4d hyper sphereλ₯Ό νšŒμ „μ‹œν‚€λŠ” 것이닀..!\
(μ •ν™•νžˆλŠ” λ™κΈ°ν™”λœ μ„œλ‘œ μ§κ΅ν•˜λŠ” 두 μ›μ˜ 2dνšŒμ „. ν•œ 원이 νšŒμ „ν•˜λŠ” μ–‘λ§ŒνΌ μ§κ΅ν•˜λŠ” λ‹€λ₯Έ 원도 νšŒμ „ν•œλ‹€.)\
unit quaternionλ₯Ό λ‚˜νƒ€λ‚΄λŠ” λͺ¨λ“  μ’Œν‘œ μƒμ˜ μž„μ˜μ˜ 점은 νšŒμ „μœΌλ‘œ 생각할 수 있고, κ·Έ λͺ¨λ“  점(νšŒμ „)은 3d둜 mappingν•  수 μžˆλ‹€.\
unit quaternionλ₯Ό λ‚˜νƒ€λ‚΄λŠ” λͺ¨λ“  μ’Œν‘œ μƒμ˜ μž„μ˜μ˜ 점은 νšŒμ „μœΌλ‘œ 생각할 수 있고, κ·Έ λͺ¨λ“  점(νšŒμ „)은 3d둜 mappingν•  수 μžˆλ‹€.

μ•„λž˜ μ˜μƒκ³Ό 같이, μ΄ˆκΈ°μ— real partκ°€ 0μ΄λΌμ„œ vector space(ijk)에 unit sphere둜 ν‘œμ‹œλ˜λŠ” 4d hypersphereλŠ”\
μš°μΈ‘μƒλ‹¨μ— ν‘œκΈ°λ˜λŠ” unit quaternion을 κ³±ν•  λ•Œ, μš°λ¦¬κ°€ 인지할 수 μ—†λŠ” λ°©μ‹μœΌλ‘œ νšŒμ „ν•˜κ²Œλœλ‹€.\
ν•΄λ‹Ή 경우 pureν•œ iμΆ• 성뢄을 κ³±ν•˜κ³  μžˆμœΌλ―€λ‘œ i좕에 λŒ€ν•œ νšŒμ „μ΄λ‹€.\
νšŒμ „μ˜ κ²°κ³ΌλŠ” μ—­μ‹œ unit quaternionλ₯Ό λ‚˜νƒ€λ‚΄λŠ” λͺ¨λ“  μ’Œν‘œ μƒμ˜ μž„μ˜μ˜ 점으둜 λ‚˜νƒ€λ‚œλ‹€.

![μ˜μƒ](/assets/img/κ°œλ…/2024-05-02-κ°œλ…-quaternion/quaternion_rotation.gif){: width=300}
![μ˜μƒ](/assets/img/κ°œλ…/2024-05-02-κ°œλ…-quaternion/quaternion_rotation.gif){: width="400"}

μ˜μƒμ˜ 결과에 λŒ€ν•΄ ν•΄μ„ν•΄λ³΄μž.\
ν•΄λ‹Ή vector space(ijk)μ—μ„œ νšŒμ „μ˜ 결과인 μ λ“€μ˜ 이동을 μ‚΄νŽ΄λ³΄λ©΄, iλ₯Ό κ³±ν•  λ•Œλ§ˆλ‹€ λ‹€μŒκ³Ό 같은 일이 λ²Œμ–΄μ§„λ‹€.\
Expand All @@ -73,8 +73,9 @@ real number -1μ—μ„œ λ°”λΌλ³΄λŠ” λ°©ν–₯으둜 quternion numberλ₯Ό projectionν• 
곱해진 결과인 quternion numberλ₯Ό 톡해 각 좕에 λŒ€ν•œ νšŒμ „λŸ‰μ„ μ•Œ 수 있게 λœλ‹€.\
(iμΆ•μ—λŠ” i와 real에 수직인 좕에 λŒ€ν•œ νšŒμ „,jμΆ•μ—λŠ” j와 real에 수직인 좕에 λŒ€ν•œ νšŒμ „,kμΆ•μ—λŠ” k와 real에 수직인 좕에 λŒ€ν•œ νšŒμ „)\
즉 λ‹€μŒκ³Ό 같이 μž„μ˜μ˜ unit quaternion을 κ³±ν•˜κ²Œ 될 λ•Œ, 이에 μˆ˜μ§ν•˜κ³  vector space의 원점(1+0i+0j+0k)을 μ§€λ‚˜λŠ” 평면은 vector quaternion의 크기만큼 νšŒμ „(μ΅œλŒ€ 1 radianμ΄λ―€λ‘œ 90degree)ν•˜κ²Œ λœλ‹€.\
(이 λ•Œ νšŒμ „μΆ•μ€ {real,i,j,k}에 λͺ¨λ‘ 수직인 λ°©ν–₯으둜의 hyper sphere의 νšŒμ „μ΄κ³ , 인지할 수 μ—†λŠ” orthogonalν•œ 세좕에 λŒ€ν•΄ $$ \sin(\theta) $$만큼 projectionλ˜κΈ°λ•Œλ¬Έμ—, κ·ΈλŸ¬λ―€λ‘œ 각 basis에 λŒ€ν•΄ λͺ¨λ‘ 수직인 λ°©ν–₯으둜 νšŒμ „μ΄ μΌμ–΄λ‚˜λŠ” 것이고, 각각에 projection될 수 μžˆκΈ°λ•Œλ¬Έμ— κ·Έ 합은 vector quaternion의 크기와 κ°™λ‹€.)\
![νšŒμ „](/assets/img/κ°œλ…/2024-05-02-κ°œλ…-quaternion/rotation%20for%20each%20axis.png){: width=300}
(이 λ•Œ νšŒμ „μΆ•μ€ {real,i,j,k}에 λͺ¨λ‘ 수직인 λ°©ν–₯으둜의 hyper sphere의 νšŒμ „μ΄κ³ , 인지할 수 μ—†λŠ” orthogonalν•œ 세좕에 λŒ€ν•΄ $$ \sin(\theta) $$만큼 projectionλ˜κΈ°λ•Œλ¬Έμ—, κ·ΈλŸ¬λ―€λ‘œ 각 basis에 λŒ€ν•΄ λͺ¨λ‘ 수직인 λ°©ν–₯으둜 νšŒμ „μ΄ μΌμ–΄λ‚˜λŠ” 것이고, 각각에 projection될 수 μžˆκΈ°λ•Œλ¬Έμ— κ·Έ 합은 vector quaternion의 크기와 κ°™λ‹€.)

![νšŒμ „](/assets/img/κ°œλ…/2024-05-02-κ°œλ…-quaternion/rotation_for_each_axis.jpg){: width="300"}

μ΄λŠ” 3μ°¨μ›μ˜ νšŒμ „μ„ κΈ°μˆ ν•˜κΈ° μœ„ν•œ κ²ƒμœΌλ‘œ, 4차원 hyper sphereλ₯Ό νšŒμ „μ‹œν‚€κ³  realμΆ•μ˜ 인지λ₯Ό ν¬κΈ°ν•˜λ©΄ 3μΆ•(i,j,k좕은 μ•„λ‹Œ μ–΄λ–€ μΆ•)에 λŒ€ν•œ νšŒμ „λŸ‰μ„ μ•Œ 수 있게 λ˜λŠ” λ†€λΌμš΄ 계산법인 것이닀..

Expand All @@ -88,8 +89,8 @@ quternion numberλŠ” complex number의 ν™•μž₯인만큼, commutativity(κ΅ν™˜μ„±)
### 2. Quaternion, Euler, Matrixλ³€ν™˜

[Using quaternions as rotations](https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Using_quaternions_as_rotations)을 보면,\

λ‹€μŒκ³Ό 같이 ν‘œν˜„λ˜λŠ” unit vectorλ₯Ό μΆ•μœΌλ‘œ rotation of angle $$\theta$$ 만큼 νšŒμ „ν•˜λŠ” 경우,

$$
{\displaystyle \mathbf {u} =(u_{x},u_{y},u_{z})=u_{x}\mathbf {i} +u_{y}\mathbf {j} +u_{z}\mathbf {k} }
$$
Expand All @@ -111,3 +112,165 @@ $$
$$
{\displaystyle \mathbf {r} =(\cos ^{2}{\frac {\theta }{2}}-\sin ^{2}{\frac {\theta }{2}}||\mathbf {u} ||^{2})\mathbf {p} +2\sin ^{2}{\frac {\theta }{2}}(\mathbf {u} .\mathbf {p} )\mathbf {u} +2\cos {\frac {\theta }{2}}\sin {\frac {\theta }{2}}(\mathbf {u} \times \mathbf {p} ),}
$$

### 2.1. Quaternion, Euler, Matrixλ³€ν™˜ in c code

mat2eulerλŠ” XYZ Euler angle을 κΈ°μ€€μœΌλ‘œ ν•œλ‹€.\
[곡식](https://en.wikipedia.org/wiki/Euler_angles) 은 λ‹€μŒκ³Ό κ°™λ‹€.\
![euler angle](/assets/img/κ°œλ…/2024-05-02-κ°œλ…-quaternion/xyz_euler_angle.png){: width="300"}

dircos[0][2]($$\sin\theta_2$$)의 μ ˆλŒ“κ°’μ΄ 1 근처(μž…μ‹€λ‘ :1e-15)인 경우,
$$\theta_2=\phi/2 or -\phi/2$$λ₯Ό μ˜λ―Έν•˜λ―€λ‘œ\
th1,th2,th3λ₯Ό κ΅¬ν•˜λŠ” 방법이 달라짐을 λ³Ό 수 μžˆλ‹€.\
(singularity에 μ˜ν•΄ th1κ³Ό th3이 κ²Ήμ³μ„œ λͺ©ν‘œ orientation을 μΆ©μ‘±ν•˜λŠ” {th1,th3}κ°€ λ¬΄ν•œ 개 μ‘΄μž¬ν•˜λ―€λ‘œ, th3λ₯Ό 0으둜 두고 th1을 계산)

```
void mat2euler(double dircos[3][3],
double *a1,
double *a2,
double *a3)
{
double th1,th2,th3,temp[10];
if (((fabs(dircos[0][2])-1.) <= -1e-15) ) {
th1 = atan2(dircos[2][1],dircos[1][1]);
if ((dircos[0][2] > 0.)) {
temp[0] = 1.5707963267949;
} else {
temp[0] = -1.5707963267949;
}
th2 = temp[0];
th3 = 0.;
} else {
th1 = atan2(-dircos[1][2],dircos[2][2]);
th2 = asin(dircos[0][2]);
th3 = atan2(-dircos[0][1],dircos[0][0]);
}
*a1 = th1;
*a2 = th2;
*a3 = th3;
}
```

euler2matλŠ” a1,a2,a3λ₯Ό 각 좕에 λŒ€ν•œ νšŒμ „ν–‰λ ¬μ— λŒ€μž…ν•˜κ³  3개의 행렬이 곱해진 곡식을 따라 dircos에 λŒ€μž…ν•œλ‹€.

```
void euler2mat(double a1,
double a2,
double a3,
double dircos[3][3])
{
double cos1,cos2,cos3,sin1,sin2,sin3;
cos1 = cos(a1);
cos2 = cos(a2);
cos3 = cos(a3);
sin1 = sin(a1);
sin2 = sin(a2);
sin3 = sin(a3);
dircos[0][0] = (cos2*cos3);
dircos[0][1] = -(cos2*sin3);
dircos[0][2] = sin2;
dircos[1][0] = ((cos1*sin3)+(sin1*(cos3*sin2)));
dircos[1][1] = ((cos1*cos3)-(sin1*(sin2*sin3)));
dircos[1][2] = -(cos2*sin1);
dircos[2][0] = ((sin1*sin3)-(cos1*(cos3*sin2)));
dircos[2][1] = ((cos1*(sin2*sin3))+(cos3*sin1));
dircos[2][2] = (cos1*cos2);
}
```

quat2matλŠ” λ‹¨μˆœ 계산이 λ„ˆλ¬΄ κΈΈλ‹€. [μ°Έκ³ ](https://www.songho.ca/opengl/gl_quaternion.html)\
vector v = Xi+Yj+Zk에 λŒ€ν•΄, rotation을 μœ„ν•œ unit quaternion곱을 μ·¨ν•˜λ©΄ Mvν˜•νƒœλ‘œ μ •λ¦¬λ˜κ³ ,\
M이 곧 rotation matrixκ°€ λœλ‹€.

```
void quat2mat(double ie4, //constant
double ie1, //qx
double ie2, //qy
double ie3, //qz
double dircos[3][3])
{
double e1,e2,e3,e4,e11,e22,e33,e44,norm;
e11 = ie1*ie1;
e22 = ie2*ie2;
e33 = ie3*ie3;
e44 = ie4*ie4;
norm = sqrt(e11+e22+e33+e44);
if (norm == 0.) {
e4 = 1.;
norm = 1.;
} else {
e4 = ie4;
}
norm = 1./norm;
e1 = ie1*norm;
e2 = ie2*norm;
e3 = ie3*norm;
e4 = e4*norm;
e11 = e1*e1;
e22 = e2*e2;
e33 = e3*e3;
dircos[0][0] = 1.-(2.*(e22+e33));
dircos[0][1] = 2.*(e1*e2-e3*e4);
dircos[0][2] = 2.*(e1*e3+e2*e4);
dircos[1][0] = 2.*(e1*e2+e3*e4);
dircos[1][1] = 1.-(2.*(e11+e33));
dircos[1][2] = 2.*(e2*e3-e1*e4);
dircos[2][0] = 2.*(e1*e3-e2*e4);
dircos[2][1] = 2.*(e2*e3+e1*e4);
dircos[2][2] = 1.-(2.*(e11+e22));
}
```

mat2quatλŠ” 주어진 mat의 μš”μ†Œ 값을 quaternion q = e4 + e1i + e2j + e3kμœΌλ‘œλΆ€ν„° matrix둜 μœ λ„λœ form의 matrix(quat2matμ°Έκ³ )의 각 μš”μ†Œμ™€ λΉ„κ΅ν•΄μ„œ λŒ€μˆ˜\ κ³„μ‚°ν•œλ‹€. [μ°Έκ³ ](https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/) \
(계산상 ν…Œν¬λ‹‰μ„ λ³΄λ‹ˆ s,x,y,z쀑 tmp = (1./sqrt(((tmp1*tmp1)+((tmp2*tmp2)+((tmp3*tmp3)+(tmp4*tmp4))))))계산을 톡해 μ•½λΆ„ν•  term을 κ³ λ₯΄λŠ” 것같닀.)

```
void mat2quat(double dircos[3][3],
double *e4, //const
double *e1, //qx
double *e2, //qy
double *e3) //qz
{
double tmp,tmp1,tmp2,tmp3,tmp4,temp[10];
tmp = (dircos[0][0]+(dircos[1][1]+dircos[2][2]));
if (((tmp >= dircos[0][0]) && ((tmp >= dircos[1][1]) && (tmp >= dircos[2][2]
))) ) {
tmp1 = (dircos[2][1]-dircos[1][2]);
tmp2 = (dircos[0][2]-dircos[2][0]);
tmp3 = (dircos[1][0]-dircos[0][1]);
tmp4 = (1.+tmp);
} else {
if (((dircos[0][0] >= dircos[1][1]) && (dircos[0][0] >= dircos[2][2]))
) {
tmp1 = (1.-(tmp-(2.*dircos[0][0])));
tmp2 = (dircos[0][1]+dircos[1][0]);
tmp3 = (dircos[0][2]+dircos[2][0]);
tmp4 = (dircos[2][1]-dircos[1][2]);
} else {
if ((dircos[1][1] >= dircos[2][2]) ) {
tmp1 = (dircos[0][1]+dircos[1][0]);
tmp2 = (1.-(tmp-(2.*dircos[1][1])));
tmp3 = (dircos[1][2]+dircos[2][1]);
tmp4 = (dircos[0][2]-dircos[2][0]);
} else {
tmp1 = (dircos[0][2]+dircos[2][0]);
tmp2 = (dircos[1][2]+dircos[2][1]);
tmp3 = (1.-(tmp-(2.*dircos[2][2])));
tmp4 = (dircos[1][0]-dircos[0][1]);
}
}
}
tmp = (1./sqrt(((tmp1*tmp1)+((tmp2*tmp2)+((tmp3*tmp3)+(tmp4*tmp4))))));
*e1 = (tmp*tmp1);
*e2 = (tmp*tmp2);
*e3 = (tmp*tmp3);
*e4 = (tmp*tmp4);
}
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b998984

Please sign in to comment.