|
import numpy as np |
|
import torch |
|
|
|
from utils.utils_poses.ATE.align_utils import alignTrajectory |
|
from utils.utils_poses.lie_group_helper import SO3_to_quat, convert3x4_4x4 |
|
|
|
|
|
def pts_dist_max(pts): |
|
""" |
|
:param pts: (N, 3) torch or np |
|
:return: scalar |
|
""" |
|
if torch.is_tensor(pts): |
|
dist = pts.unsqueeze(0) - pts.unsqueeze(1) |
|
dist = dist[0] |
|
dist = dist.norm(dim=1) |
|
max_dist = dist.max() |
|
else: |
|
dist = pts[None, :, :] - pts[:, None, :] |
|
dist = dist[0] |
|
dist = np.linalg.norm(dist, axis=1) |
|
max_dist = dist.max() |
|
return max_dist |
|
|
|
|
|
def align_ate_c2b_use_a2b(traj_a, traj_b, traj_c=None, method='sim3'): |
|
"""Align c to b using the sim3 from a to b. |
|
:param traj_a: (N0, 3/4, 4) torch tensor |
|
:param traj_b: (N0, 3/4, 4) torch tensor |
|
:param traj_c: None or (N1, 3/4, 4) torch tensor |
|
:return: (N1, 4, 4) torch tensor |
|
""" |
|
device = traj_a.device |
|
if traj_c is None: |
|
traj_c = traj_a.clone() |
|
|
|
traj_a = traj_a.float().cpu().numpy() |
|
traj_b = traj_b.float().cpu().numpy() |
|
traj_c = traj_c.float().cpu().numpy() |
|
|
|
R_a = traj_a[:, :3, :3] |
|
t_a = traj_a[:, :3, 3] |
|
quat_a = SO3_to_quat(R_a) |
|
|
|
R_b = traj_b[:, :3, :3] |
|
t_b = traj_b[:, :3, 3] |
|
quat_b = SO3_to_quat(R_b) |
|
|
|
|
|
|
|
s, R, t = alignTrajectory(t_a, t_b, quat_a, quat_b, method=method) |
|
|
|
|
|
R = R[None, :, :].astype(np.float32) |
|
t = t[None, :, None].astype(np.float32) |
|
s = float(s) |
|
|
|
R_c = traj_c[:, :3, :3] |
|
t_c = traj_c[:, :3, 3:4] |
|
|
|
R_c_aligned = R @ R_c |
|
t_c_aligned = s * (R @ t_c) + t |
|
traj_c_aligned = np.concatenate([R_c_aligned, t_c_aligned], axis=2) |
|
|
|
|
|
traj_c_aligned = convert3x4_4x4(traj_c_aligned) |
|
|
|
traj_c_aligned = torch.from_numpy(traj_c_aligned).to(device) |
|
return traj_c_aligned |
|
|
|
|
|
|
|
def align_scale_c2b_use_a2b(traj_a, traj_b, traj_c=None): |
|
'''Scale c to b using the scale from a to b. |
|
:param traj_a: (N0, 3/4, 4) torch tensor |
|
:param traj_b: (N0, 3/4, 4) torch tensor |
|
:param traj_c: None or (N1, 3/4, 4) torch tensor |
|
:return: |
|
scaled_traj_c (N1, 4, 4) torch tensor |
|
scale scalar |
|
''' |
|
if traj_c is None: |
|
traj_c = traj_a.clone() |
|
|
|
t_a = traj_a[:, :3, 3] |
|
t_b = traj_b[:, :3, 3] |
|
|
|
|
|
|
|
scale_a2b = pts_dist_max(t_b) / pts_dist_max(t_a) |
|
|
|
traj_c[:, :3, 3] *= scale_a2b |
|
|
|
if traj_c.shape[1] == 3: |
|
traj_c = convert3x4_4x4(traj_c) |
|
|
|
return traj_c, scale_a2b |
|
|