5 minute read

[Blog]

๋ณธ ํฌ์ŠคํŠธ๋Š” ์œ„ ๋ธ”๋กœ๊ทธ ๋‚ด์šฉ์„ ์ฐธ์กฐํ•˜์—ฌ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž„์„ ๋ฐํž™๋‹ˆ๋‹ค.

Lie Group SO(3), SE(3)

Lie Algebra so(3), se(3)

Image

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด SE3์—์„œ ํšŒ์ „ ๋ฐ ์ด๋™๋ณ€ํ™˜์„ ๊ตฌํ• ๋•Œ ํ•œ๋‘๋ฒˆ ๊ณ„์‚ฐํ• ๋•Œ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ SLAM์—์„œ์™€ ๊ฐ™์ด ๋งค์šฐ ๋น ๋ฅธ์‹œ๊ฐ„์— ์—ฐ์†์ ์œผ๋กœ R|T๋ฅผ ๋ณ€์ˆ˜๋กœ ํ•˜์—ฌ pose๋ฅผ ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด ๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ์—, SE3์ƒ์—์„œ๋Š” constraints๋กœ ์ธํ•ด ์ตœ์ ํ™” ํ• ๋•Œ๋งˆ๋‹ค ์ด ์กฐ๊ฑด๋“ค์ด ๋งž๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ se3์—์„œ๋Š” ์ด๋Ÿฐ constraints๊ฐ€ ์—†๊ณ  linear space์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋‹ด์—†์ด ๋ฏธ๋ถ„์„ ์ ์šฉํ•˜์—ฌ ์ตœ์ ํ™”๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ตœ์ ํ™” ๋ณ€์ˆ˜๋ฅผ se3(w,v)๋กœ ๋†“๊ณ  ๊ณ„์‚ฐ๋œ ์ฆ๋ถ„๋Ÿ‰์„ exp(zeta)๋ฅผ ํ†ตํ•ด SE3๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. constrained optimization์ด unconstrained optimization์œผ๋กœ ๋ณ€ํ™˜๋˜๋Š”๊ฑฐ์ฃ . ๋˜ํ•œ ์ตœ๊ทผ์— learning based SLAM๊ฐ™์€ ๊ฒฝ์šฐ ๋‰ด๋Ÿด๋„ท์—์„œ R|T๋ฅผ ํŽธ๋ฏธ๋ถ„ํ•ด์•ผํ•˜๋‹ˆ Lie pytorch๋ฅผ ์ด์šฉํ•˜์—ฌ Lie group์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

SE(3)๋Š” SO(3)๋ฅผ ํฌํ•จํ•˜๋Š” ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค.

SO(3)๋Š” ์ˆœ์ˆ˜ํ•œ ํšŒ์ „๋งŒ์„ ๋‚˜ํƒ€๋‚ด๊ณ , SE(3)๋Š” SO(3)์˜ ํšŒ์ „๊ณผ ์ถ”๊ฐ€์ ์ธ ์ด๋™ ๋ฒกํ„ฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, SE(3)๋Š” ๊ฐ•์ฒด์˜ ํšŒ์ „๊ณผ ์ด๋™์„ ๋ชจ๋‘ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (Rigid-body transform)

SE(3)์™€ SO(3)๋Š” ๊ฐ๊ฐ ๊ณต๊ฐ„์—์„œ์˜ ์šด๋™์„ ์„ค๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ˆ˜ํ•™์  ๊ทธ๋ฃน์ž…๋‹ˆ๋‹ค. ์ด ๋‘ ๊ทธ๋ฃน์€ ๋กœ๋ด‡๊ณตํ•™, ์ปดํ“จํ„ฐ ๋น„์ „, ๊ทธ๋ฆฌ๊ณ  ์ธ๊ณต์ง€๋Šฅ ๋ถ„์•ผ์—์„œ ํŠนํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

SO(3)๋Š” 3์ฐจ์› ๊ณต๊ฐ„์—์„œ์˜ ํšŒ์ „์„ ํ‘œํ˜„ํ•˜๋Š” ๊ทธ๋ฃน์œผ๋กœ, โ€˜Special Orthogonal Group of degree 3โ€™์˜ ์•ฝ์–ด์ž…๋‹ˆ๋‹ค. ์ด ๊ทธ๋ฃน์˜ ์›์†Œ๋Š” 3x3 ์ง๊ต ํ–‰๋ ฌ๋กœ, ํ–‰๋ ฌ์‹์ด 1์ธ ํ–‰๋ ฌ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ˆœ์ˆ˜ํ•œ ํšŒ์ „์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

SE(3)๋Š” 3์ฐจ์› ๊ณต๊ฐ„์—์„œ์˜ ํšŒ์ „๊ณผ ์ด๋™์„ ํ•จ๊ป˜ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ทธ๋ฃน์œผ๋กœ, โ€˜Special Euclidean Group of degree 3โ€™์˜ ์•ฝ์–ด์ž…๋‹ˆ๋‹ค. SE(3)๋Š” SO(3)์˜ ํšŒ์ „๊ณผ ์ถ”๊ฐ€์ ์ธ ์ด๋™ ๋ฒกํ„ฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, SE(3)๋Š” ๊ฐ•์ฒด์˜ ํšŒ์ „๊ณผ ์ด๋™์„ ๋ชจ๋‘ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ, SE(3)๋Š” SO(3)๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฐœ๋…์ด๋ฉฐ, ์ด๋™(translations)์„ ์ถ”๊ฐ€๋กœ ๋‹ค๋ฃน๋‹ˆ๋‹ค. SO(3)๋Š” SE(3) ๋‚ด์—์„œ ํšŒ์ „ ๋ถ€๋ถ„์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

์ •๋ฆฌํ•˜๋ฉด se(3)๋Š” ํšŒ์ „์ธ so(3)๋ฅผ ํฌํ•จํ•˜๋Š” ๊ด€๊ณ„์ด๊ณ , SE(3)๋Š” ํšŒ์ „์ธ SO(3)๋ฅผ ํฌํ•จํ•˜๋Š” ๊ด€๊ณ„์ด๋ฏ€๋กœ, se(3) to SE(3) ๋ณ€ํ™˜ ๊ด€๊ณ„์—์„œ ์ˆœ์ˆ˜ํ•œ ํšŒ์ „์ธ so(3), SO(3)์— ์ถ”๊ฐ€์ ์œผ๋กœ ์ด๋™ ๋ฒกํ„ฐ๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ: Lie Algebra์ธ se(3)๋Š” linear space ์—ฌ์„œ Lie Group์ธ SE(3)์— ์กด์žฌํ•˜๋Š” constraints๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์—, Lie Algebra์ธ se(3)์— ๋Œ€ํ•ด์„œ ๋ฏธ๋ถ„์„ ๊ณ„์‚ฐํ•˜๊ณ  Lie Group์ธ SE(3)๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณ ๊ฐ•์ฒด์˜ ํšŒ์ „๊ณผ ์ด๋™์„ ๋ชจ๋‘ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3DGS์—์„œ ์ฝ”๋“œ๋กœ se(3)์— ๋Œ€ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ตœ์ ํ™”ํ•˜๋Š” ๊ณผ์ •์€ w, v ๋กœ nn.Parameter๋กœ ์ •์˜ํ•˜๊ณ , ์ด๋ฅผ se3_to_SE3 ํ•จ์ˆ˜๋กœ w,v์˜ ๋ณ€์ˆ˜๋กœ SE(3)๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# gaussian_splatting/scene/cameras.py
import torch
from torch import nn
import numpy as np
from utils.graphics_utils import getWorld2View2, getProjectionMatrix, se3_to_SE3

# Define a class named Camera_Pose. The code is based on the camera_transf class in iNeRF. You can refer to iNeRF at https://github.com/salykovaa/inerf.
class Camera_Pose(nn.Module):
    def __init__(self,start_pose_w2c, FoVx, FoVy, image_width, image_height,
             trans=torch.tensor([0.0, 0.0, 0.0]), scale=1.0,
             ):
        super(Camera_Pose, self).__init__()

        self.FoVx = FoVx
        self.FoVy = FoVy

        self.image_width = image_width
        self.image_height = image_height

        self.zfar = 100.0
        self.znear = 0.01

        self.trans = trans
        self.scale = scale
        self.cov_offset = 0
        
        self.w = nn.Parameter(torch.normal(0., 1e-6, size=(3,)).to(start_pose_w2c.device))
        self.v = nn.Parameter(torch.normal(0., 1e-6, size=(3,)).to(start_pose_w2c.device))
        
        self.forward(start_pose_w2c)
    
    def forward(self, start_pose_w2c):
        deltaT=se3_to_SE3(self.w,self.v)
        self.pose_w2c = torch.matmul(deltaT, start_pose_w2c.inverse()).inverse()
        self.update()
    
    def current_campose_c2w(self):
        return self.pose_w2c.inverse().clone().cpu().detach().numpy()

    def update(self):
        self.world_view_transform = self.pose_w2c.transpose(0, 1).cuda()
        self.projection_matrix = getProjectionMatrix(znear=self.znear, zfar=self.zfar, fovX=self.FoVx, fovY=self.FoVy).transpose(0,1).cuda()
        self.full_proj_transform = (self.world_view_transform.unsqueeze(0).bmm(self.projection_matrix.unsqueeze(0))).squeeze(0)
        self.camera_center = self.world_view_transform.inverse()[3, :3]
# gaussian_splatting/utils/graphics_utils.py
def se3_to_SE3(w,v): # [...,3]
    deltaT = torch.zeros((4,4)).cuda()
    wx = skew_symmetric(w)
    theta = w.norm(dim=-1)
    I = torch.eye(3,device=w.device,dtype=torch.float32)
    A = taylor_A(theta)
    B = taylor_B(theta)
    C = taylor_C(theta)
    deltaT[:3, :3] = I+A*wx+B*wx@wx
    V = I+B*wx+C*wx@wx
    deltaT[:3, 3] = V@v
    deltaT[3, 3] = 1.
    return deltaT

๋”ฐ๋ผ์„œ 3DGS์—์„œ๋„ se(3)์—์„œ ๋ฏธ๋ถ„๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ณ  se3_to_SE3 ํ•จ์ˆ˜๋กœ ์ตœ์ข…์ ์œผ๋กœ๋Š” SE(3)๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SO(3)

\[SO(3) = \{ R \in \mathbb{R}^{3 \times 3} | R^T R = I, \text{det}(R) = 1 \}\]

์—ฌ๊ธฐ์„œ $R$์€ 3x3 ์ง๊ต ํ–‰๋ ฌ์ด๋ฉฐ, $R^T$๋Š” $R$์˜ ์ „์น˜ ํ–‰๋ ฌ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๊ทธ๋ฃน์€ ํšŒ์ „์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ํšŒ์ „ ํ–‰๋ ฌ์€ ์ง๊ต ํ–‰๋ ฌ์ด๋ฉฐ ํ–‰๋ ฌ์‹์ด 1์ž…๋‹ˆ๋‹ค.

so(3)

\[so(3) = \{ \omega \in \mathbb{R}^{3 \times 3} | \omega^T = -\omega \}\]

์—ฌ๊ธฐ์„œ $\omega$๋Š” 3x3 ๋ฐ˜๋Œ€์นญ ํ–‰๋ ฌ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ด๋Š” so(3)์˜ ์š”์†Œ๋“ค์ž…๋‹ˆ๋‹ค. so(3)๋Š” ํšŒ์ „์˜ ๋ฏธ์†Œ ๋ณ€ํ™”๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋Œ€์ˆ˜์  ๊ตฌ์กฐ๋กœ์„œ, $\mathbb{R}^3$์˜ ๋ฒกํ„ฐ๋ฅผ 3x3 ๋ฐ˜๋Œ€์นญ ํ–‰๋ ฌ๋กœ ๋ณ€ํ™˜ํ•จ์œผ๋กœ์จ SO(3) ๊ทธ๋ฃน์˜ ์ ‘๊ณต๊ฐ„์„ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋Œ€์ˆ˜ ๊ตฌ์กฐ๋Š” 3์ฐจ์› ๊ณต๊ฐ„์—์„œ์˜ ๋ฌดํ•œ์†Œ ํšŒ์ „์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ด๋Š” SO(3)์˜ ์—ฐ์†์ ์ธ ํšŒ์ „ ์šด๋™์˜ ์„ ํ˜• ๊ทผ์‚ฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

SE(3)

\[SE(3) = \{ T \in \mathbb{R}^{4 \times 4} | T = \begin{bmatrix} R & t \\ 0 & 1 \end{bmatrix}, R \in SO(3), t \in \mathbb{R}^3 \}\]

์—ฌ๊ธฐ์„œ $T$๋Š” 4x4 ๋ณ€ํ™˜ ํ–‰๋ ฌ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, $R$์€ ํšŒ์ „ ํ–‰๋ ฌ, $t$์€ ์ด๋™ ๋ฒกํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๊ทธ๋ฃน์€ ์ด๋™๊ณผ ํšŒ์ „์„ ๊ฒฐํ•ฉํ•œ ๋ณ€ํ™˜์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋ณ€ํ™˜ ํ–‰๋ ฌ์€ ์ง๊ต ํ–‰๋ ฌ๊ณผ ์ด๋™ ๋ฒกํ„ฐ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

se(3)

\[se(3) = \{ \xi \in \mathbb{R}^6 | \xi = \begin{bmatrix} \omega \\ v \end{bmatrix}, \omega, v \in \mathbb{R}^3 \}\]

์—ฌ๊ธฐ์„œ $\xi$๋Š” 6์ฐจ์› ๋ฒกํ„ฐ์ด๋ฉฐ, $\omega$๋Š” ํšŒ์ „ ์†๋„ ๋ฒกํ„ฐ, $v$๋Š” ์ด๋™ ์†๋„ ๋ฒกํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๊ทธ๋ฃน์€ ์ž‘์€ ํšŒ์ „๊ณผ ์ž‘์€ ์ด๋™์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฒกํ„ฐ ๊ณต๊ฐ„์œผ๋กœ, SE(3) ๊ทธ๋ฃน์—์„œ์˜ ์ž‘์€ ๋ณ€ํ™˜์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

se3์—์„œ SE3๋กœ์˜ ๋ณ€ํ™˜ ํ•จ์ˆ˜ ์„ค๋ช…

ํ•จ์ˆ˜ skew_symmetric(w)

  • ์ž…๋ ฅ: ๊ฐ์†๋„ ๋ฒกํ„ฐ w
  • ์ถœ๋ ฅ: w์˜ ์Šคํ ๋Œ€์นญ ํ–‰๋ ฌ(skew-symmetric matrix)
  • ์„ค๋ช…: ๊ฐ์†๋„ ๋ฒกํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ํ•ด๋‹น ๋ฒกํ„ฐ์˜ ์Šคํ ๋Œ€์นญ ํ–‰๋ ฌ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ํ–‰๋ ฌ์€ ๋ฒกํ„ฐ์˜ ์™ธ์ ์„ ํ–‰๋ ฌ ๊ณฑ์…ˆ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ taylor_A(x, nth=10), taylor_B(x, nth=10), taylor_C(x, nth=10)

  • ์ž…๋ ฅ: ์Šค์นผ๋ผ ๋˜๋Š” ๋ฒกํ„ฐ x, ๊ธ‰์ˆ˜์˜ ํ•ญ์ˆ˜ nth
  • ์ถœ๋ ฅ: ํ…Œ์ผ๋Ÿฌ ๊ธ‰์ˆ˜๋กœ ๊ทผ์‚ฌ๋œ ๊ฐ๊ฐ์˜ ํ•จ์ˆ˜ ๊ฐ’
  • ์„ค๋ช…: ๊ฐ ํ•จ์ˆ˜๋Š” ๋กœ๋“œ๋ฆฌ๊ฒŒ์Šค ํšŒ์ „ ๊ณต์‹(Rodriguesโ€™ rotation formula)์—์„œ ์‚ฌ์šฉ๋˜๋Š” sin(x)/x, (1-cos(x))/x^2, (x-sin(x))/x^3 ๋“ฑ์„ ๊ทผ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ทผ์‚ฌ๋Š” ํšŒ์ „์˜ ํฌ๊ธฐ๊ฐ€ ์ž‘์„ ๋•Œ ๋”์šฑ ์ •ํ™•ํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ se3_to_SE3(w, v)

  • ์ž…๋ ฅ: ๊ฐ์†๋„ ๋ฒกํ„ฐ w, ์„ ์†๋„ ๋ฒกํ„ฐ v
  • ์ถœ๋ ฅ: 4x4 ๋ณ€ํ™˜ ํ–‰๋ ฌ SE3
  • ์„ค๋ช…: ์ž…๋ ฅ๋œ w์™€ v๋กœ๋ถ€ํ„ฐ SE3 ๋ณ€ํ™˜ ํ–‰๋ ฌ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ํ–‰๋ ฌ์€ 3D ๊ณต๊ฐ„์—์„œ์˜ ๋ฆฌ์ง€๋“œ ๋ฐ”๋”” ๋ณ€ํ™˜(rigid body transformation)์„ ํ‘œํ˜„ํ•˜๋ฉฐ, ํšŒ์ „๊ณผ ์ด๋™์„ ๋ชจ๋‘ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
    • ์ƒ์œ„ 3x3 ๋ถ€๋ถ„์€ ํšŒ์ „์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋กœ๋“œ๋ฆฌ๊ฒŒ์Šค ๊ณต์‹๊ณผ ํ…Œ์ผ๋Ÿฌ ๊ธ‰์ˆ˜ ๊ทผ์‚ฌ๋ฅผ ํ†ตํ•ด ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
    • ๋งˆ์ง€๋ง‰ ์—ด์˜ ์ƒ์œ„ 3๊ฐœ ์š”์†Œ๋Š” ์ด๋™์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ํšŒ์ „์„ ๊ณ ๋ คํ•œ ํ…Œ์ผ๋Ÿฌ ๊ธ‰์ˆ˜ ๊ทผ์‚ฌ๋ฅผ ํ†ตํ•ด ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
    • ๋งคํŠธ๋ฆญ์Šค(matrix)์˜ ์˜ค๋ฅธ์ชฝ ์•„๋ž˜ ์š”์†Œ๋Š” ํ•ญ์ƒ 1์ž…๋‹ˆ๋‹ค.
import torch

def skew_symmetric(w):
    # ์ž…๋ ฅ๋œ ๊ฐ์†๋„ ๋ฒกํ„ฐ w์— ๋Œ€ํ•œ ์Šคํ ๋Œ€์นญ ํ–‰๋ ฌ ๋ฐ˜ํ™˜
    w0, w1, w2 = w.unbind(dim=-1)
    O = torch.zeros_like(w0)
    wx = torch.stack([torch.stack([O, -w2, w1], dim=-1),
                      torch.stack([w2, O, -w0], dim=-1),
                      torch.stack([-w1, w0, O], dim=-1)], dim=-2)
    return wx

def taylor_A(x, nth=10):
    # sin(x)/x์˜ ํ…Œ์ผ๋Ÿฌ ๊ธ‰์ˆ˜ ๊ทผ์‚ฌ, nth๋Š” ๋‹คํ•ญ์‹์˜ ์ตœ๋Œ€ ์ฐจ์ˆ˜
    ans = torch.zeros_like(x)
    denom = 1.
    for i in range(nth+1):
        if i > 0: denom *= (2*i)*(2*i+1)
        ans += (-1)**i * x**(2*i) / denom
    return ans
    
def taylor_B(x, nth=10):
    # (1-cos(x))/x^2์˜ ํ…Œ์ผ๋Ÿฌ ๊ธ‰์ˆ˜ ๊ทผ์‚ฌ, nth๋Š” ๋‹คํ•ญ์‹์˜ ์ตœ๋Œ€ ์ฐจ์ˆ˜
    ans = torch.zeros_like(x)
    denom = 1.
    for i in range(nth+1):
        denom *= (2*i+1)*(2*i+2)
        ans += (-1)**i * x**(2*i) / denom
    return ans

def taylor_C(x, nth=10):
    # (x-sin(x))/x^3์˜ ํ…Œ์ผ๋Ÿฌ ๊ธ‰์ˆ˜ ๊ทผ์‚ฌ, nth๋Š” ๋‹คํ•ญ์‹์˜ ์ตœ๋Œ€ ์ฐจ์ˆ˜
    ans = torch.zeros_like(x)
    denom = 1.
    for i in range(nth+1):
        denom *= (2*i+2)*(2*i+3)
        ans += (-1)**i * x**(2*i) / denom
    return ans

def se3_to_SE3(w, v):
    # ๊ฐ์†๋„ w์™€ ์„ ์†๋„ v๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ 4x4 ๋ณ€ํ™˜ ํ–‰๋ ฌ SE3 ๊ณ„์‚ฐ
    deltaT = torch.zeros((4,4)).cuda()
    wx = skew_symmetric(w)
    theta = w.norm(dim=-1)
    I = torch.eye(3, device=w.device, dtype=torch.float32)
    A = taylor_A(theta, nth=10)  # nth ์„ค์ •์— ๋”ฐ๋ผ ๊ทผ์‚ฌ ์ •ํ™•๋„ ๊ฒฐ์ •
    B = taylor_B(theta, nth=10)
    C = taylor_C(theta, nth=10)
    deltaT[:3, :3] = I + A*wx + B*wx@wx  # ํšŒ์ „ ํ–‰๋ ฌ ๊ณ„์‚ฐ
    V = I + B*wx + C*wx@wx  # ์ด๋™ ๋ฒกํ„ฐ ๊ณ„์‚ฐ์„ ์œ„ํ•œ ํ–‰๋ ฌ V ๊ณ„์‚ฐ
    deltaT[:3, 3] = V@v  # ์ด๋™ ๋ฒกํ„ฐ ์„ค์ •
    deltaT[3, 3] = 1.  # ๋™์ฐจ ์ขŒํ‘œ ์„ค์ •
    return deltaT

deltaT์— ๋Œ€ํ•œ ์„ค๋ช…

deltaT๋Š” SE(3) ๊ทธ๋ฃน์— ์†ํ•˜๋Š” 4x4 ๋ณ€ํ™˜ ํ–‰๋ ฌ๋กœ, ํšŒ์ „๊ณผ ์ด๋™์„ ๊ฒฐํ•ฉํ•œ rigid body transform์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

\[\begin{bmatrix} R & t \\ 0 & 1 \end{bmatrix}\]

์—ฌ๊ธฐ์„œ $R$์€ 3x3์˜ ํšŒ์ „ ํ–‰๋ ฌ๋กœ, SO(3) ๊ทธ๋ฃน์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ–‰๋ ฌ์€ ์ˆœ์ˆ˜ํ•œ ํšŒ์ „๋งŒ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ง๊ต์„ฑ๊ณผ ํ–‰๋ ฌ์‹์ด 1์ด๋ผ๋Š” ํŠน์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. $t$๋Š” 3x1์˜ ์ด๋™ ๋ฒกํ„ฐ๋กœ, SE(3) ๊ทธ๋ฃน์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฒกํ„ฐ๋Š” ๊ณต๊ฐ„์—์„œ์˜ ๊ฐ์ฒด ์œ„์น˜ ๋ณ€ํ™˜์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ์ด๋™ ์š”์†Œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ณ€ํ™˜ ํ–‰๋ ฌ deltaT๋Š” ๊ฐ์†๋„์™€ ์„ ์†๋„๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ณ„์‚ฐ๋˜๋ฉฐ, 3D ๊ณต๊ฐ„์—์„œ ๊ฐ์ฒด์˜ ์œ„์น˜์™€ ๋ฐฉํ–ฅ์„ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ฐ์†๋„๋Š” ํšŒ์ „์„, ์„ ์†๋„๋Š” ์ด๋™์„ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

Lie Group: Rotation SO(3), Rigid-body SE(3)

Image

Leave a comment