SymForce ๋?
- ์ต๊ทผ RSS 2022 ์์ SymForce ๋ผ๋ framework ์ด ๊ณต๊ฐ๋์๋ค. Skydio ๊ฐ ๊ณต๊ฐํ์๋ค. ๋ด๋ถ์ ์ผ๋ก 5๋ ๋์ ๊ฐ๋ฐํ๊ณ ์ค์ ๋ก ์ฌ์ฉํด์จ ๊ฒ์ด๋ผ๊ณ ํ๋ค.
- Skydio ๋ ์ด๊ธฐ์ GTSAM ์ ์์ด์ + SLAM ์ญ์ฌ์ ํฐ ํ์ ๊ทธ์ Frank Dellaert ๊ต์๋์ ์๋ฌธ์ ๋ฐ์๋ค๊ณ ๋ค์๋ค. ์ต๊ทผ์๋ ๋ฉ์ง ๊ฒฐ๊ณผ๋ค๋ ๋ณด์ฌ์ฃผ๊ณ ์์ด์, ์ด๋ค์ ๊ธฐ์ ๋ ฅ์ ์ด๋ค ์์ค์ผ์ง ๊ถ๊ธํ์๋ค.
- SymForce ๋ ผ๋ฌธ์ ๋ณด๋ฉด robotics (ํนํ ๋๋ก ๋ฑ)์ ๊ฐ์ด ๋น ๋ฅธ ๊ณ์ฐ์ด ์ค์๊ฐ์ผ๋ก ์๊ตฌ๋ ๋์๋, (Ceres ๊ฐ์) ๊ณ์ฐ๊ทธ๋ํ ๊ธฐ๋ฐ๋ณด๋ค symbolic ๊ธฐ๋ฐ ์ ๋ฏธ๋ถ์ด ๋ ์ข๋ค๊ณ ์ฃผ์ฅํ๊ณ ์๋ค. ์๋ Robotics ์์ Ceres ๊ฐ ๋ง์ด ์ฐ์ด๊ณ ์์ด์ ์๋ก์ด solver ์ ํ์์ฑ์ ๋ชป ๋๋ผ๊ณ ์์๋๋ฐ, ์ด ๋ ผ๋ฌธ์ ๋ง์ ๋ค์ด๋ณด๋ฉด ์ ์ง ์ค๋์ด ๋๋ค.
- ํ ๋ฒ ๊ณต๋ถํ ๊ฒธ ์จ๋ณด์๋ค.
Nonlinear ICP ๊ตฌํํ๊ธฐ
๋ชฉํ
- Nonlinear ICP ๋ฅผ ๊ตฌํํด๋ณด์.
๋ฐฐ๊ฒฝ์ง์
Nonlinear optimization
- Nonlinear optimization ์ด์ฉ๊ตฌ ํ๋ฉด == Gauss-Newton์ผ๋ก iterative ํ๊ฒ ํผ๋ค ๋ผ๊ณ ์ดํดํด๋ ๊ฑฐ์ ๋ฌด๋ฐฉํ๋ค.
- ์ด ๋ update step ์ ๋ฐฉํฅ๊ณผ ํฌ๊ธฐ๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด cost function ์ ๋ฏธ๋ถ๊ฐ์ด ํ์ํ๊ณ ์ด๊ฒ์ Jacobian์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
- ์ด ๋ cost function output dimension ์ด $n$์ด๊ณ , cost function ์ ๊ตฌ์ฑํ๋ ์ฐ๋ฆฌ๊ฐ ์ฐพ๊ณ ์ถ์ ์ต์ ๊ฐ์ ๋ํ ํ๋ผ๋ฏธํฐ ๋ณ์์ dimension ์ด $m$์ด๋ผ๊ณ ํ๋ฉด Jacobian์ shape ์ $n \times m$์ด ๋๊ฒ ๋๋ค.
Auto diff
- ๊ทธ๋ฐ๋ฐ nonlinearํ(์ฆ $a_0 x_0 + a_1 x_ 1 + โฆ$ ํํ๊ฐ ์๋ ๋ชจ๋ ํฌ๋งท) ๋ณต์กํ cost function ์ Jacobian ์ ์ฌ๋์ด ์์ผ๋ก ๊ณ์ฐํ๋ ๊ฒ์ ์ค์ํ ์ํ์ด ํฌ๊ธฐ ๋๋ฌธ์, ๋ณ์๋ค์ ๊ณ์ฐ๊ทธ๋ํ๋ก ์ฐ๊ฒฐํ๊ณ , ์๋์ผ๋ก ๋ฏธ๋ถ๊ฐ์ด ๊ด๋ฆฌ๋๋๋ก (์ ํ๋๋๋ก) ํ๋ ๊ตฌํ์ ์ฑํํ๋ ๋ฐฉ์์ด ๋๋ฆฌ ์ฐ์ด๊ณ ์๋ค (e.g., Ceres, Pytorch)
- ์ด ๊ฒฝ์ฐ, forward ์ ํ๋ ๋ ํ๋์ ๋ณ์์ ๋ํด value์ gradient ์ ๋ ๊ฐ์ ๋์์ ํจ๊ป ์ ์ฅํด์ผ ๋๊ฒ๋๋ค. ์๋ฅผ ๋ค์ด, Ceres ์์๋ jet์ด๋ผ๋ ํํ๋ก ๊ด๋ฆฌ๋๊ณ , autodiff ์์๋ dual ์ด๋ผ๋ ์ด๋ฆ์ด ์ฐ์ด๊ณ ์๋ค.
Symbolic diff
- ์ด๋ ๊ฒ jet, dual ๋ฑ์ ๊ตฌ์กฐ์ฒด๋ก ๋ ๊ฐ์ ๊ด๋ฆฌํ๋ฉด์ ๊ณ์ฐ๊ทธ๋ํ๋ฅผ ํ์ฑํ๋ ์์ autodiff ๊ฐ robotics ์ deep learning ๋ถ์ผ ๋ชจ๋์ ๋ํด์ ๋๋ฆฌ ์ฐ์ด๊ณ ์๋ (Ceres, autodiff, tinyAD, jax, pytorch, tensorflow ๋ฑ๋ฑ๋ฑ) ์์ฆ์ด์ง๋ง โฆ
- SymForce ๋ Symbolic ๊ธฐ๋ฐ์ด๋ผ๊ณ ํ๋ค. ์ฆ, ์์์ cost function ์ด ์ฃผ์ด์ง ๋, ์ด๊ฒ์ ์์ฝ๋น์์ ๋ช
์์ ์ผ๋ก ์์ผ๋ก ๋ฑ ๊ณ์ฐํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๊ณ์ฐ์ด ์ต์ ํ๋๋๋ก ํด์ค๋ค.
- ๊ทธ๋ฆฌ๊ณ python ์ผ๋ก ์์์ ์ ์ผ๋ฉด c++ code ๋ฅผ ์์ฑํด์ฃผ๊ธฐ๊น์ง ํ๋ค!
- ์๋ฅผ ๋ค์ด, ICP์์ cost function ์ ๋ค์๊ณผ ๊ฐ๋ค. 3D point $p_0$ ๊ณผ point $p_1$์ด ์ฃผ์ด์ง ๋, loss $= ||\left( R \{ \theta \}*p_0 + t \right) - p_1 || _2$ ๋ฅผ ์ต์ํํ๋ transformation parameter $\theta$ ์ $t$ ๋ฅผ ์ฐพ๋ ๊ฒ์ด ๋ชฉํ์ด๋ค.
- ์ด ๋ ์์ฐ์ค๋ฝ๊ฒ ๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ง๋ฌธ(๋ฉ๋ถ)์ ๋น ์ง๊ฒ ๋๋ค. $\frac{\partial\text{loss}}{\partial\bf{\theta}}$ ์ $\frac{\partial\text{loss}}{\partial{t}}$๋ฅผ ์ด๋ป๊ฒ ๊ณ์ฐํ์ง ..???!?
- ์ด ๋ ์ด๊ฑธ ๊ณ์ฐ๊ทธ๋ํ๋ก ๋ฌถ์ด์ ๊ฐ์ ์ฃผ๋ฉด autodiff ์ด๊ณ .. ๋ช ์์ ์ผ๋ก (์์์ ๊ธฐ์ค)๋ณต์กํ ์์์ ์ฐพ์์ฃผ๋ ๊ฒ symbolic ์ด๋ผ๊ณ ์ผ๋จ ์ดํดํ๊ณ ์๋ค (๋ ๊ณต๋ถ ํ์)
- ์ฆ, SymForce ์๊ฒ ์ด ์์
์ ๋งก๊ธฐ๋ฉด $\frac{\partial\text{loss}}{\partial\bf{\theta}}$์ด ๋ค์๊ณผ ๊ฐ์ด ์๋ ๊ทธ๋ฆผ์ฒ๋ผ ๋์จ๋ค (๋๋ฌด ๊ธธ์ด์ ๋ค ์ฎ๊ธธ ์๊ฐ ์์ด์ ์บก์ฒ๋ก ๋์ ํ๋ค. ์ ์ฒด ์์ ์ฌ๊ธฐ jupyter notebook๋ฅผ ์ฐธ๊ณ ).
- ์ด ๋ $\theta$๋ rotation ์ minimal ํ๊ฒ parametrize ํ๋ angle-axis ๊ฐ ๋๋ค. ์ด๋ฅผ tangent space ์์ ์ต์ ํํ๋ค๋ผ๊ณ ๋ ํํํ๊ณ , ์ดํ์ ์ด ๊ฐ์ ์๋ ๊ณต๊ฐ (e.g., rotation์ ๋ํด์๋ $\text{SO(3)}$) ์ผ๋ก ๋ณด๋ด์ฃผ๋ ์์ ์ retract ๋ผ๊ณ ๋ถ๋ฅด๊ธฐ๋ ํ๊ณ โฆ ์ด์ ๋ํด์๋ ๋ณ๋์ rotation ๊ด๋ จ ์๋ฃ(A micro Lie theory for state estimation in robotics, Quaternion kinematics for the error-state Kalman filter )๋ฅผ ์ฐธ๊ณ ํ๋๋ก ํ์.
- ์๋ฌดํผ ์์ฝํ์๋ฉด Jacobain matrix ์ ๊ฐ์ ์๋ฉด iterative update ํ๋ ๊ฒ์ ๋๋ฌด ์ฌ์ด๋ฐ, ์ด ๋ ์๋ฌด๋ฆฌ ๋ณต์กํ ํจ์์ฌ๋ SymForce ๊ฐ ์์ฝ๋น์์ ์์์ ์ ๊ตฌํด์ค๋ค๋ ๊ฒ. ํนํ robotics ์์ ๋ง์ด ์ฌ์ฉํ๋ parameter ๋ค (camera projection, rotation ๋ฑ) ์ ๋ํ ์ง์์ ํฌํจํ๊ณ ์๊ธฐ ๋๋ฌธ์ SymPy ๋ฑ์ ๊ธฐ์กด Symbolic solver ๋ค์ ์ฌ์ฉํ ๋๋ณด๋ค robotics ๋ฌธ์ ๋ฅผ ๋ ํ๊ธฐ ํธ๋ฆฌํด์ก๋ค๋ ์ ๋ฑ์ด ์ฅ์ ์ด๋ผ๊ณ ํ ์ ์๊ฒ ๋ค.
๊ตฌํ
Iterative update
- ์์ฝ๋น์์ ๊ตฌํ๋ค์, ์ด๊ฒ์ ์ด์ฉํด์ iterative ํ๊ฒ ์ต์ ์ $d[\theta, t]$ ๋ฅผ ๊ตฌํ๊ณ , ์กฐ๊ธ์ฉ ์ด ๊ฐ์ ์ ๋ฐ์ดํธ ํด๋๊ฐ๋ ๋ฃจํด์ ๋๋ฌด๋ ์๋ช ํ๋ค. ์ด์ ๋ํด์๋ Grisetti ๊ต์๋์ 2016๋ ICRA tutorial ์๋ฃ ๋ฅผ ์ถ์ฒํ๋ค. ์ฌ๊ธฐ์ ๋ณด๋ฉด ์ด๋ฐ ์์ด ์๋ค. Octave (Matlab) ๊ตฌํ์ฒด์ด๋ค.
- ์์ ๊ตฌ์กฐ๋ฅผ python์ผ๋ก ์ฎ๊ธฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋๋ค. (์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ symforce-tutorials ์ ๋ณผ ์ ์๋ค).
def icp(src, tgt, tf_init, max_iter=5, verbose=False): tf = tf_init # 6 dim num_pts = src.shape[0] for _iter in range(max_iter): # reset for each iter H = np.zeros((6, 6)) b = np.zeros((6, 1)) # gathering measurements for pt_idx in range(num_pts): src_pt = src[pt_idx, :] tgt_pt = tgt[pt_idx, :] e, Je_rot, Je_trans \ = evaluate_error_and_jacobian(src_pt, tgt_pt, tf) J = np.hstack((Je_rot, Je_trans)) # thus, 3x6 H = H + J.T @ J # H: 6x3 * 3x6 => thus H is 6x6 b = b + J.T @ e # b: 6x3 * 3x1 => thus b is 6x1 dtf = -np.linalg.solve(H, b).squeeze() # note the step direction is minus tf = tf + dtf # updated within the tangent space return tf
- note: ์ด ๋
src_pt
์tgt_pt
๋ ์ค์ ๋ก ๊ฐ์ ์ง์ ์ ํฌ์ธํธ์ฌ์ผ ํ๋ค. ์ฆ, correspondence ์ฌ์ผ ํ๋ค.- ps. ์ด๋ฒ ํํ ๋ฆฌ์ผ์ ๊ต์ก์ฉ์ผ๋ก ์์ฑํด๋ณธ ๊ฒ (1. SymForce๋ฅผ ์ด์ฉํด์ ์๋์ผ๋ก Jacobian์ ์ฌ๋ณผ๋ฆญ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐํด๋ณด๊ธฐ 2. ์ด๋ฅผ ์ด์ฉํด์ nonlinear optimization ์ update ๋ถ๋ถ from scratch๋ก ๊ตฌํํด๋ณด๊ธฐ) ์ด๊ธฐ ๋๋ฌธ์โฆ point cloud $\text{pcd}_0$(์์ ๋ฆฌํฌ์์
data/251371071.pcd
๋ฅผ ๋ก๋ํ๊ณ ์์์ $\text{SE(3)}$ transformation ์ ๊ฐํด์ฃผ์ด์ $\text{pcd}_1$ ์ ์์ฑํ๊ณ ์๋ค. ๋ฐ๋ผ์ point ์ ์์๊ฐ ๋ณด์กด๋๋ฏ๋กsrc_pt
์tgt_pt
๋ชจ๋ ๋์ผํ ์ธ๋ฑ์คpt_idx
๋ก ๊ฐ์ ธ์ค๋ฉด correspondence ๊ฐ ์ฑ๋ฆฝ๋๋ค. ์ค์ ์ธ๊ณ ๋ฌธ์ ์์๋ FPFH local feature ๋ฑ์ ๋ฐฉ๋ฒ์ผ๋ก correspondence ๋ฅผ ๋จผ์ ์ฐพ๊ณ , ์ associate ๋ pair ๋ฅผ ์์ icp ์๊ณ ๋ฆฌ์ฆ์ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค.
- ps. ์ด๋ฒ ํํ ๋ฆฌ์ผ์ ๊ต์ก์ฉ์ผ๋ก ์์ฑํด๋ณธ ๊ฒ (1. SymForce๋ฅผ ์ด์ฉํด์ ์๋์ผ๋ก Jacobian์ ์ฌ๋ณผ๋ฆญ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐํด๋ณด๊ธฐ 2. ์ด๋ฅผ ์ด์ฉํด์ nonlinear optimization ์ update ๋ถ๋ถ from scratch๋ก ๊ตฌํํด๋ณด๊ธฐ) ์ด๊ธฐ ๋๋ฌธ์โฆ point cloud $\text{pcd}_0$(์์ ๋ฆฌํฌ์์
- ์์ ๋ฃจํด์ ํน๋ณํ ์ด๋ ค์ธ ๊ฒ์ ์๋ค. Robotics ๋ฌธ์ ์์ ICP๋ฟ ์๋๋ผ ์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ด ๋๋๋ผ๋ ๊ฒฐ๊ตญ ์์ ๋ชจ์ต์ ํ๊ฒ ๋๋ค.
- ์ด ๋ ๊ทธ๋ฌ๋ฉด ์์ ๋ฃจํด์์ Jacobian์ ๊ณ์ฐํด์ฃผ๋
evaluate_error_and_jacobian
ํจ์๋ฅผ ๋์์ธํ๋ ๊ฒ์ด ๋ก๋ณดํฑ์ค ์์ง๋์ด์ ์ญํ ์ด ๋๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ๊ฒ์ ์ด์ SymForce๊ฐ ์ํํด์ค๋ค. ์๋ ์ฝ๋์ฒ๋ผ ์ ์๋ ๋ชจ๋ธ์ ํด๋น ๋ฐ์ดํฐํฌ์ธํธ์์์ ๊ฐ์ ๋ฃ์ด์ฃผ๊ธฐ๋ง ํ๋ฉด๋๋ค. ์ด ์ญํ ์ ํ๋ ๊ฒ์ด SymForce ์์.subs
method ์ธ๋ฐ substitution ์ ์๋ฏธํ๋ค.def evaluate_error_and_jacobian(src_pt: np.ndarray, tag_pt: np.ndarray, transformation): # note: transformation is 6dim vector on the tangent space (i.e., [rotvec, trans]) def inject_values(model): model_evaluated = \ model.subs(rotvec, sf.V3(transformation[:3])) \ .subs(transvec, sf.V3(transformation[3:])) \ .subs(p_src, sf.V3(src_pt)) \ .subs(p_tgt, sf.V3(tag_pt)) return model_evaluated error = inject_values(error_model) Je_rot = inject_values(Je_rot_model) Je_trans = inject_values(Je_trans_model) return error.to_numpy(), Je_rot.to_numpy(), Je_trans.to_numpy()
- ์ฐธ๊ณ ๋ก ์ฌ๊ธฐ์ ์ฐ์ด๋
error_model
,Je_rot_model
,Je_trans_model
๋ฑ์ ์๋ ์ฝ๋์ ๊ฐ์ด ํธํ๊ฒ ์์ฑํ ์ ์๋ค.# Model parameters (as symbolic) transvec = sf.V3.symbolic("t") rotvec = sf.V3.symbolic("Theta") # i.e., angle-axis parametrization rotmat = LieGroupOps.from_tangent(sf.Rot3, rotvec) # for debug, display(rotmat.to_rotation_matrix()) # Redisual (loss function) # note: the rotation 'matrix' is used to formulate the below constraint, # but it was parametrized as a 3-dim vector 'rotvec'! p_src = sf.V3.symbolic("p_src") # p means a single 3D point p_tgt = sf.V3.symbolic("p_tgt") p_tgt_est = (rotmat * p_src) + transvec # The constraint: R*p + t == p' error_val = p_tgt_est - p_tgt def loss(error_V3): for i in range(3): error_V3[i] = sf.sqrt(error_V3[i]*error_V3[i]) return error_V3 error_model = loss(error_val) # residual jacobian # this is the powerful moment of symforce. It automatically generate the Jacobian equations explicitly. Je_trans_model = error_model.jacobian(transvec) Je_rot_model = error_model.jacobian(rotvec)
V3
๋ฑ์ 3 dimension vector ๋ฅผ ์๋ฏธํ๋ค. ์ด๋ ๋ฏ SymForce ์์ ์ง์ํ๋ symbolic class ๋ก ๋ณ์๋ฅผ ์ ์ด์ด๋ถ์ฌ์ error function ์ ์ ์ํด์ฃผ๊ณ , ์ฌ๊ธฐ์.jacobian(w.r.t what)
๋ผ๊ณ ๋ง ํด์ฃผ๋ฉด ์ค๋น ๋.- ps. ์ฌ๊ธฐ์
rotvec
,rotmat
๋ฑ์ ์ฐจ์ด์ ๋ํด ๋ฐฐ๊ฒฝ์ง์์ ๊ตฌ๋นํ๊ธฐ ์ํด์๋ ์์๋ ์ด์ผ๊ธฐํ์ง๋ง rotation ๊ด๋ จ ์๋ฃ(A micro Lie theory for state estimation in robotics, Quaternion kinematics for the error-state Kalman filter)๋ฅผ ์ฐธ๊ณ ํ๋๋ก ํ์.
- ps. ์ฌ๊ธฐ์
- note: ์ด ๋
๊ฒฐ๊ณผ
- ๊ทธ๋์
icp
ํจ์๋ฅผ ์ํํ๋ฉด, ๋ค์ ๊ฒฐ๊ณผ(์บก์ฒ)์ ๊ฐ์ด ์์๋ก ์ฒ์์ ๊ฐํ๋ transformation๊ณผ ์ต์ ํํด์ ์ฐพ์ ์์ธก๊ฐ์ด ๋์ผํจ์ ์ ์ ์๋ค.diff_SE3
๊ฐ์ ๋ฌ๋ฆฌํด๊ฐ๋ฉด์ ์ฒดํํด๋ณด๊ธธ ๋ฐ๋๋ค! ๊ทธ๋๋ ๋ ๊ฐ์ ๊ฐ์ ์ ์์ธกํ๋ ๊ฒ์ ์ ์ ์๋ค.- ์ฌ๊ธฐ ์ ํ๋ธ ์์์์ ์๋ ด๊ณผ์ ์ ์๊ฐํํ์๋ค.
๊ฒฐ๋ก
์์ฝ
- SymForce ๋ ๋ก๋ณดํฑ์ค ๋ฌธ์ ๋ฅผ ํ ๋ ํ์ํ ์์ฝ๋น์์ ์ ์์ฑํด์ค๋ค.
- Gauss-Newton pipeline ์ ๊ตฌ์ฑํด๋ณผ ๋ ๊ฐ์ฅ ์ ๋จน๋ ๋ถ๋ถ์ด Jacobian ์ ๊ตฌํ๋ ๋ถ๋ถ์ธ๋ฐ, ์ด ๋ถ๋ถ์ ์บก์ํํ๊ณ ๋๋, nonliear update pipeline ์ ๊ตฌํํ๋ ๋ฐ ์ข ๋ ์ง์คํ์ฌ ์ต์ ํ ๊ณผ์ ์ ๋ ์ ํ์
ํด๋ณผ ์ ์๋ค.
- ์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ (link) ์ ๋ณผ ์ ์๋ค
- ps. ๋ณต์กํ nonlinear cost ์ Jacobian ๊ตฌํ๋ ๊ฒ๋ถํฐ ์ ๊ฒฝ์ฐ๊ฒ ๋๋ ๊ฒ์ ์ ๋ฌธ์ ์ ์ฅ์์ (์ํ์ ์ผ๋ก) ์ด๋ ต๋ค. ๊ทธ๋ ๋ค๊ณ ์ด๋ฅผ ํํผํ๋ค ๋ณด๋ฉด, ๋งค๋ฒ ๋๋ฌด ์ฌ์ด ์์ ๋ง์ ๋ค๋ฃจ๊ฒ ๋๋ค. ์ฆ ๋ก๋ณดํฑ์ค ์ค์ ๋ฌธ์ ์ค ํญ์ ์ผ๋ถ๋ง ๋ค๋ฃจ๊ฒ ๋๊ฑฐ๋ 2D space ์ ํ์ ๋๋ฏ๋ก ์์ฝ๋ค.. (e.g., 2D์์์ differential wheel motion ๋ฑ).
TODO
- ๊ณต๋ถ์ผ์ Gauss-Newton update ๊ณผ์ ์ ๊ตฌ์ฑํด๋ณด์์ง๋ง, ์๋ง optimizer ๋ผ๋ class ๋ก ์ด๋ฐ ๊ณผ์ ๋ค์ด ์ด๋ฏธ wrapping ๋์ด์๋ ๋ฏ ํ๋ค. SymForce ๊ฐ ์ ๊ณตํ๋ ์กฐ๊ธ ๋ high-level์์์ optim API๋ฅผ ์ฌ์ฉํด๋ณด์
- Cauchy kernel ์ ์์์ loss function ์ from scratch๋ก ๊ตฌํํด๋ณด์. ๊ทธ๋ฆฌ๊ณ noisy ํ correspondences pairs ๊ฐ ์ฃผ์ด์ก์ ๋ robust kernel ์ฌ๋ถ์ ๋ฐ๋ฅธ ๊ฐ๊ฑด์ฑ ์ฐจ์ด๋ฅผ ์ค์ตํด๋ณด์. ๊ทธ๋ฆฌ๊ณ GncOptimizer๋ ์ฌ์ฉํด๋ณด์.
- Automatically generated C++ code ๊ธฐ์ค Ceres ์์ ์๋์ฐจ์ด๋ฅผ ์ค์ ๋ก ํ ์คํธํด๋ณด์.