Spaces:
Running
on
Zero
Running
on
Zero
#!/usr/bin/env python2 | |
# -*- coding: utf-8 -*- | |
import numpy as np | |
import utils.utils_poses.ATE.transformations as tfs | |
import utils.utils_poses.ATE.align_trajectory as align | |
def _getIndices(n_aligned, total_n): | |
if n_aligned == -1: | |
idxs = np.arange(0, total_n) | |
else: | |
assert n_aligned <= total_n and n_aligned >= 1 | |
idxs = np.arange(0, n_aligned) | |
return idxs | |
def alignPositionYawSingle(p_es, p_gt, q_es, q_gt): | |
''' | |
calcualte the 4DOF transformation: yaw R and translation t so that: | |
gt = R * est + t | |
''' | |
p_es_0, q_es_0 = p_es[0, :], q_es[0, :] | |
p_gt_0, q_gt_0 = p_gt[0, :], q_gt[0, :] | |
g_rot = tfs.quaternion_matrix(q_gt_0) | |
g_rot = g_rot[0:3, 0:3] | |
est_rot = tfs.quaternion_matrix(q_es_0) | |
est_rot = est_rot[0:3, 0:3] | |
C_R = np.dot(est_rot, g_rot.transpose()) | |
theta = align.get_best_yaw(C_R) | |
R = align.rot_z(theta) | |
t = p_gt_0 - np.dot(R, p_es_0) | |
return R, t | |
def alignPositionYaw(p_es, p_gt, q_es, q_gt, n_aligned=1): | |
if n_aligned == 1: | |
R, t = alignPositionYawSingle(p_es, p_gt, q_es, q_gt) | |
return R, t | |
else: | |
idxs = _getIndices(n_aligned, p_es.shape[0]) | |
est_pos = p_es[idxs, 0:3] | |
gt_pos = p_gt[idxs, 0:3] | |
_, R, t = align.align_umeyama(gt_pos, est_pos, known_scale=True, | |
yaw_only=True) # note the order | |
t = np.array(t) | |
t = t.reshape((3, )) | |
R = np.array(R) | |
return R, t | |
# align by a SE3 transformation | |
def alignSE3Single(p_es, p_gt, q_es, q_gt): | |
''' | |
Calculate SE3 transformation R and t so that: | |
gt = R * est + t | |
Using only the first poses of est and gt | |
''' | |
p_es_0, q_es_0 = p_es[0, :], q_es[0, :] | |
p_gt_0, q_gt_0 = p_gt[0, :], q_gt[0, :] | |
g_rot = tfs.quaternion_matrix(q_gt_0) | |
g_rot = g_rot[0:3, 0:3] | |
est_rot = tfs.quaternion_matrix(q_es_0) | |
est_rot = est_rot[0:3, 0:3] | |
R = np.dot(g_rot, np.transpose(est_rot)) | |
t = p_gt_0 - np.dot(R, p_es_0) | |
return R, t | |
def alignSE3(p_es, p_gt, q_es, q_gt, n_aligned=-1): | |
''' | |
Calculate SE3 transformation R and t so that: | |
gt = R * est + t | |
''' | |
if n_aligned == 1: | |
R, t = alignSE3Single(p_es, p_gt, q_es, q_gt) | |
return R, t | |
else: | |
idxs = _getIndices(n_aligned, p_es.shape[0]) | |
est_pos = p_es[idxs, 0:3] | |
gt_pos = p_gt[idxs, 0:3] | |
s, R, t = align.align_umeyama(gt_pos, est_pos, | |
known_scale=True) # note the order | |
t = np.array(t) | |
t = t.reshape((3, )) | |
R = np.array(R) | |
return R, t | |
# align by similarity transformation | |
def alignSIM3(p_es, p_gt, q_es, q_gt, n_aligned=-1): | |
''' | |
calculate s, R, t so that: | |
gt = R * s * est + t | |
''' | |
idxs = _getIndices(n_aligned, p_es.shape[0]) | |
est_pos = p_es[idxs, 0:3] | |
gt_pos = p_gt[idxs, 0:3] | |
s, R, t = align.align_umeyama(gt_pos, est_pos) # note the order | |
return s, R, t | |
# a general interface | |
def alignTrajectory(p_es, p_gt, q_es, q_gt, method, n_aligned=-1): | |
''' | |
calculate s, R, t so that: | |
gt = R * s * est + t | |
method can be: sim3, se3, posyaw, none; | |
n_aligned: -1 means using all the frames | |
''' | |
assert p_es.shape[1] == 3 | |
assert p_gt.shape[1] == 3 | |
assert q_es.shape[1] == 4 | |
assert q_gt.shape[1] == 4 | |
s = 1 | |
R = None | |
t = None | |
if method == 'sim3': | |
assert n_aligned >= 2 or n_aligned == -1, "sim3 uses at least 2 frames" | |
s, R, t = alignSIM3(p_es, p_gt, q_es, q_gt, n_aligned) | |
elif method == 'se3': | |
R, t = alignSE3(p_es, p_gt, q_es, q_gt, n_aligned) | |
elif method == 'posyaw': | |
R, t = alignPositionYaw(p_es, p_gt, q_es, q_gt, n_aligned) | |
elif method == 'none': | |
R = np.identity(3) | |
t = np.zeros((3, )) | |
else: | |
assert False, 'unknown alignment method' | |
return s, R, t | |
if __name__ == '__main__': | |
pass | |