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