InstantSplat / utils /utils_poses /ATE /align_trajectory.py
kairunwen's picture
add code
35e2073
raw
history blame
1.93 kB
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import numpy as np
import utils.utils_poses.ATE.transformations as tfs
def get_best_yaw(C):
'''
maximize trace(Rz(theta) * C)
'''
assert C.shape == (3, 3)
A = C[0, 1] - C[1, 0]
B = C[0, 0] + C[1, 1]
theta = np.pi / 2 - np.arctan2(B, A)
return theta
def rot_z(theta):
R = tfs.rotation_matrix(theta, [0, 0, 1])
R = R[0:3, 0:3]
return R
def align_umeyama(model, data, known_scale=False, yaw_only=False):
"""Implementation of the paper: S. Umeyama, Least-Squares Estimation
of Transformation Parameters Between Two Point Patterns,
IEEE Trans. Pattern Anal. Mach. Intell., vol. 13, no. 4, 1991.
model = s * R * data + t
Input:
model -- first trajectory (nx3), numpy array type
data -- second trajectory (nx3), numpy array type
Output:
s -- scale factor (scalar)
R -- rotation matrix (3x3)
t -- translation vector (3x1)
t_error -- translational error per point (1xn)
"""
# substract mean
mu_M = model.mean(0)
mu_D = data.mean(0)
model_zerocentered = model - mu_M
data_zerocentered = data - mu_D
n = np.shape(model)[0]
# correlation
C = 1.0/n*np.dot(model_zerocentered.transpose(), data_zerocentered)
sigma2 = 1.0/n*np.multiply(data_zerocentered, data_zerocentered).sum()
U_svd, D_svd, V_svd = np.linalg.linalg.svd(C)
D_svd = np.diag(D_svd)
V_svd = np.transpose(V_svd)
S = np.eye(3)
if(np.linalg.det(U_svd)*np.linalg.det(V_svd) < 0):
S[2, 2] = -1
if yaw_only:
rot_C = np.dot(data_zerocentered.transpose(), model_zerocentered)
theta = get_best_yaw(rot_C)
R = rot_z(theta)
else:
R = np.dot(U_svd, np.dot(S, np.transpose(V_svd)))
if known_scale:
s = 1
else:
s = 1.0/sigma2*np.trace(np.dot(D_svd, S))
t = mu_M-s*np.dot(R, mu_D)
return s, R, t